summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/db/blob/blob_garbage_meter.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/rocksdb/db/blob/blob_garbage_meter.cc100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/rocksdb/db/blob/blob_garbage_meter.cc b/src/rocksdb/db/blob/blob_garbage_meter.cc
new file mode 100644
index 000000000..d328d7ff4
--- /dev/null
+++ b/src/rocksdb/db/blob/blob_garbage_meter.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
+// This source code is licensed under both the GPLv2 (found in the
+// COPYING file in the root directory) and Apache 2.0 License
+// (found in the LICENSE.Apache file in the root directory).
+
+#include "db/blob/blob_garbage_meter.h"
+
+#include "db/blob/blob_index.h"
+#include "db/blob/blob_log_format.h"
+#include "db/dbformat.h"
+
+namespace ROCKSDB_NAMESPACE {
+
+Status BlobGarbageMeter::ProcessInFlow(const Slice& key, const Slice& value) {
+ uint64_t blob_file_number = kInvalidBlobFileNumber;
+ uint64_t bytes = 0;
+
+ const Status s = Parse(key, value, &blob_file_number, &bytes);
+ if (!s.ok()) {
+ return s;
+ }
+
+ if (blob_file_number == kInvalidBlobFileNumber) {
+ return Status::OK();
+ }
+
+ flows_[blob_file_number].AddInFlow(bytes);
+
+ return Status::OK();
+}
+
+Status BlobGarbageMeter::ProcessOutFlow(const Slice& key, const Slice& value) {
+ uint64_t blob_file_number = kInvalidBlobFileNumber;
+ uint64_t bytes = 0;
+
+ const Status s = Parse(key, value, &blob_file_number, &bytes);
+ if (!s.ok()) {
+ return s;
+ }
+
+ if (blob_file_number == kInvalidBlobFileNumber) {
+ return Status::OK();
+ }
+
+ // Note: in order to measure the amount of additional garbage, we only need to
+ // track the outflow for preexisting files, i.e. those that also had inflow.
+ // (Newly written files would only have outflow.)
+ auto it = flows_.find(blob_file_number);
+ if (it == flows_.end()) {
+ return Status::OK();
+ }
+
+ it->second.AddOutFlow(bytes);
+
+ return Status::OK();
+}
+
+Status BlobGarbageMeter::Parse(const Slice& key, const Slice& value,
+ uint64_t* blob_file_number, uint64_t* bytes) {
+ assert(blob_file_number);
+ assert(*blob_file_number == kInvalidBlobFileNumber);
+ assert(bytes);
+ assert(*bytes == 0);
+
+ ParsedInternalKey ikey;
+
+ {
+ constexpr bool log_err_key = false;
+ const Status s = ParseInternalKey(key, &ikey, log_err_key);
+ if (!s.ok()) {
+ return s;
+ }
+ }
+
+ if (ikey.type != kTypeBlobIndex) {
+ return Status::OK();
+ }
+
+ BlobIndex blob_index;
+
+ {
+ const Status s = blob_index.DecodeFrom(value);
+ if (!s.ok()) {
+ return s;
+ }
+ }
+
+ if (blob_index.IsInlined() || blob_index.HasTTL()) {
+ return Status::Corruption("Unexpected TTL/inlined blob index");
+ }
+
+ *blob_file_number = blob_index.file_number();
+ *bytes =
+ blob_index.size() +
+ BlobLogRecord::CalculateAdjustmentForRecordHeader(ikey.user_key.size());
+
+ return Status::OK();
+}
+
+} // namespace ROCKSDB_NAMESPACE