github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/c-deps/libroach/table_props.cc (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 #include "table_props.h" 12 #include <rocksdb/slice.h> 13 #include <rocksdb/status.h> 14 #include <rocksdb/table_properties.h> 15 #include <rocksdb/types.h> 16 #include "encoding.h" 17 18 namespace cockroach { 19 20 namespace { 21 22 // This is re-implemented in sst_writer.go and should be kept in sync. 23 class TimeBoundTblPropCollector : public rocksdb::TablePropertiesCollector { 24 public: 25 const char* Name() const override { return "TimeBoundTblPropCollector"; } 26 27 rocksdb::Status Finish(rocksdb::UserCollectedProperties* properties) override { 28 if (!last_value_.empty()) { 29 // Check to see if an intent was the last key in the SSTable. If 30 // it was, we need to extract the timestamp from the intent and 31 // update the bounds to include that timestamp. 32 cockroach::storage::enginepb::MVCCMetadata meta; 33 if (!meta.ParseFromArray(last_value_.data(), last_value_.size())) { 34 // We're unable to parse the MVCCMetadata. Fail open by not 35 // setting the min/max timestamp properties. 36 return rocksdb::Status::OK(); 37 } 38 if (meta.has_txn()) { 39 // We have an intent, use the intent's timestamp to update the 40 // timestamp bounds. 41 std::string ts; 42 EncodeTimestamp(ts, meta.timestamp().wall_time(), meta.timestamp().logical()); 43 UpdateBounds(ts); 44 } 45 } 46 47 *properties = rocksdb::UserCollectedProperties{ 48 {"crdb.ts.min", ts_min_}, 49 {"crdb.ts.max", ts_max_}, 50 }; 51 return rocksdb::Status::OK(); 52 } 53 54 rocksdb::Status AddUserKey(const rocksdb::Slice& user_key, const rocksdb::Slice& value, 55 rocksdb::EntryType type, rocksdb::SequenceNumber seq, 56 uint64_t file_size) override { 57 rocksdb::Slice unused; 58 rocksdb::Slice ts; 59 if (!SplitKey(user_key, &unused, &ts)) { 60 return rocksdb::Status::OK(); 61 } 62 63 if (!ts.empty()) { 64 last_value_.clear(); 65 ts.remove_prefix(1); // The NUL prefix. 66 UpdateBounds(ts); 67 return rocksdb::Status::OK(); 68 } 69 70 last_value_.assign(value.data(), value.size()); 71 return rocksdb::Status::OK(); 72 } 73 74 virtual rocksdb::UserCollectedProperties GetReadableProperties() const override { 75 return rocksdb::UserCollectedProperties{}; 76 } 77 78 private: 79 void UpdateBounds(rocksdb::Slice ts) { 80 if (ts_max_.empty() || ts.compare(ts_max_) > 0) { 81 ts_max_.assign(ts.data(), ts.size()); 82 } 83 if (ts_min_.empty() || ts.compare(ts_min_) < 0) { 84 ts_min_.assign(ts.data(), ts.size()); 85 } 86 } 87 88 private: 89 std::string ts_min_; 90 std::string ts_max_; 91 std::string last_value_; 92 }; 93 94 class TimeBoundTblPropCollectorFactory : public rocksdb::TablePropertiesCollectorFactory { 95 public: 96 explicit TimeBoundTblPropCollectorFactory() {} 97 virtual rocksdb::TablePropertiesCollector* CreateTablePropertiesCollector( 98 rocksdb::TablePropertiesCollectorFactory::Context context) override { 99 return new TimeBoundTblPropCollector(); 100 } 101 const char* Name() const override { return "TimeBoundTblPropCollectorFactory"; } 102 }; 103 104 class DeleteRangeTblPropCollector : public rocksdb::TablePropertiesCollector { 105 public: 106 const char* Name() const override { return "DeleteRangeTblPropCollector"; } 107 108 rocksdb::Status Finish(rocksdb::UserCollectedProperties*) override { 109 return rocksdb::Status::OK(); 110 } 111 112 rocksdb::Status AddUserKey(const rocksdb::Slice&, const rocksdb::Slice&, rocksdb::EntryType type, 113 rocksdb::SequenceNumber, uint64_t) override { 114 if (type == rocksdb::kEntryRangeDeletion) { 115 ntombstones_++; 116 } 117 return rocksdb::Status::OK(); 118 } 119 120 virtual rocksdb::UserCollectedProperties GetReadableProperties() const override { 121 return rocksdb::UserCollectedProperties{}; 122 } 123 124 virtual bool NeedCompact() const override { 125 // NB: Mark any file containing range deletions as requiring a 126 // compaction. This ensures that range deletions are quickly compacted out 127 // of existence. 128 return ntombstones_ > 0; 129 } 130 131 private: 132 int ntombstones_ = 0; 133 }; 134 135 class DeleteRangeTblPropCollectorFactory : public rocksdb::TablePropertiesCollectorFactory { 136 virtual rocksdb::TablePropertiesCollector* CreateTablePropertiesCollector( 137 rocksdb::TablePropertiesCollectorFactory::Context context) override { 138 return new DeleteRangeTblPropCollector(); 139 } 140 const char* Name() const override { return "DeleteRangeTblPropCollectorFactory"; } 141 }; 142 143 } // namespace 144 145 rocksdb::TablePropertiesCollectorFactory* DBMakeTimeBoundCollector() { 146 return new TimeBoundTblPropCollectorFactory(); 147 } 148 149 rocksdb::TablePropertiesCollectorFactory* DBMakeDeleteRangeCollector() { 150 return new DeleteRangeTblPropCollectorFactory(); 151 } 152 153 } // namespace cockroach