Coverage Report

Created: 2026-09-28 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/db/blob/blob_garbage_meter.h
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
6
#pragma once
7
8
#include <cassert>
9
#include <cstdint>
10
#include <unordered_map>
11
12
#include "db/blob/blob_constants.h"
13
#include "rocksdb/rocksdb_namespace.h"
14
#include "rocksdb/status.h"
15
16
namespace ROCKSDB_NAMESPACE {
17
18
class BlobIndex;
19
struct ParsedInternalKey;
20
class Slice;
21
22
// A class that can be used to compute the amount of additional garbage
23
// generated by a compaction. It parses the keys and blob references in the
24
// input and output of a compaction, and aggregates the "inflow" and "outflow"
25
// on a per-blob file basis. The amount of additional garbage for any given blob
26
// file can then be computed by subtracting the outflow from the inflow.
27
class BlobGarbageMeter {
28
 public:
29
  // A class to store the number and total size of blobs on a per-blob file
30
  // basis.
31
  class BlobStats {
32
   public:
33
0
    void Add(uint64_t bytes) {
34
0
      ++count_;
35
0
      bytes_ += bytes;
36
0
    }
37
0
    void Add(uint64_t count, uint64_t bytes) {
38
0
      count_ += count;
39
0
      bytes_ += bytes;
40
0
    }
41
42
0
    uint64_t GetCount() const { return count_; }
43
0
    uint64_t GetBytes() const { return bytes_; }
44
45
   private:
46
    uint64_t count_ = 0;
47
    uint64_t bytes_ = 0;
48
  };
49
50
  // A class to keep track of the "inflow" and the "outflow" and to compute the
51
  // amount of additional garbage for a given blob file.
52
  class BlobInOutFlow {
53
   public:
54
0
    void AddInFlow(uint64_t bytes) {
55
0
      in_flow_.Add(bytes);
56
0
      assert(IsValid());
57
0
    }
58
0
    void AddOutFlow(uint64_t bytes) {
59
0
      out_flow_.Add(bytes);
60
0
      assert(IsValid());
61
0
    }
62
63
0
    const BlobStats& GetInFlow() const { return in_flow_; }
64
0
    const BlobStats& GetOutFlow() const { return out_flow_; }
65
66
0
    bool IsValid() const {
67
0
      return in_flow_.GetCount() >= out_flow_.GetCount() &&
68
0
             in_flow_.GetBytes() >= out_flow_.GetBytes();
69
0
    }
70
0
    bool HasGarbage() const {
71
0
      assert(IsValid());
72
0
      return in_flow_.GetCount() > out_flow_.GetCount();
73
0
    }
74
0
    uint64_t GetGarbageCount() const {
75
0
      assert(IsValid());
76
0
      assert(HasGarbage());
77
0
      return in_flow_.GetCount() - out_flow_.GetCount();
78
0
    }
79
0
    uint64_t GetGarbageBytes() const {
80
0
      assert(IsValid());
81
0
      assert(HasGarbage());
82
0
      return in_flow_.GetBytes() - out_flow_.GetBytes();
83
0
    }
84
85
   private:
86
    BlobStats in_flow_;
87
    BlobStats out_flow_;
88
  };
89
90
  Status ProcessInFlow(const Slice& key, const Slice& value);
91
  Status ProcessOutFlow(const Slice& key, const Slice& value);
92
93
0
  const std::unordered_map<uint64_t, BlobInOutFlow>& flows() const {
94
0
    return flows_;
95
0
  }
96
97
 private:
98
  static Status GetBlobReferenceDetails(const ParsedInternalKey& ikey,
99
                                        const BlobIndex& blob_index,
100
                                        uint64_t* blob_file_number,
101
                                        uint64_t* bytes);
102
  static Status ParseBlobIndexReference(const ParsedInternalKey& ikey,
103
                                        const Slice& value,
104
                                        uint64_t* blob_file_number,
105
                                        uint64_t* bytes);
106
107
  void AddFlow(uint64_t blob_file_number, uint64_t bytes, bool is_inflow);
108
  Status ProcessFlow(const Slice& key, const Slice& value, bool is_inflow);
109
  Status ProcessEntityBlobReferences(const ParsedInternalKey& ikey,
110
                                     const Slice& value, bool is_inflow);
111
112
  std::unordered_map<uint64_t, BlobInOutFlow> flows_;
113
};
114
115
}  // namespace ROCKSDB_NAMESPACE