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 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 
10 #pragma once
11 #include <algorithm>
12 #include <set>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "db/blob/blob_file_addition.h"
18 #include "db/blob/blob_file_garbage.h"
19 #include "db/dbformat.h"
20 #include "db/wal_edit.h"
21 #include "memory/arena.h"
22 #include "rocksdb/cache.h"
23 #include "table/table_reader.h"
24 #include "util/autovector.h"
25 
26 namespace ROCKSDB_NAMESPACE {
27 
28 // Tag numbers for serialized VersionEdit.  These numbers are written to
29 // disk and should not be changed. The number should be forward compatible so
30 // users can down-grade RocksDB safely. A future Tag is ignored by doing '&'
31 // between Tag and kTagSafeIgnoreMask field.
32 enum Tag : uint32_t {
33   kComparator = 1,
34   kLogNumber = 2,
35   kNextFileNumber = 3,
36   kLastSequence = 4,
37   kCompactPointer = 5,
38   kDeletedFile = 6,
39   kNewFile = 7,
40   // 8 was used for large value refs
41   kPrevLogNumber = 9,
42   kMinLogNumberToKeep = 10,
43 
44   // these are new formats divergent from open source leveldb
45   kNewFile2 = 100,
46   kNewFile3 = 102,
47   kNewFile4 = 103,      // 4th (the latest) format version of adding files
48   kColumnFamily = 200,  // specify column family for version edit
49   kColumnFamilyAdd = 201,
50   kColumnFamilyDrop = 202,
51   kMaxColumnFamily = 203,
52 
53   kInAtomicGroup = 300,
54 
55   kBlobFileAddition = 400,
56   kBlobFileGarbage,
57 
58   // Mask for an unidentified tag from the future which can be safely ignored.
59   kTagSafeIgnoreMask = 1 << 13,
60 
61   // Forward compatible (aka ignorable) records
62   kDbId,
63   kBlobFileAddition_DEPRECATED,
64   kBlobFileGarbage_DEPRECATED,
65   kWalAddition,
66   kWalDeletion,
67   kFullHistoryTsLow,
68   kWalAddition2,
69   kWalDeletion2,
70 };
71 
72 enum NewFileCustomTag : uint32_t {
73   kTerminate = 1,  // The end of customized fields
74   kNeedCompaction = 2,
75   // Since Manifest is not entirely forward-compatible, we currently encode
76   // kMinLogNumberToKeep as part of NewFile as a hack. This should be removed
77   // when manifest becomes forward-compatible.
78   kMinLogNumberToKeepHack = 3,
79   kOldestBlobFileNumber = 4,
80   kOldestAncesterTime = 5,
81   kFileCreationTime = 6,
82   kFileChecksum = 7,
83   kFileChecksumFuncName = 8,
84   kTemperature = 9,
85 
86   // If this bit for the custom tag is set, opening DB should fail if
87   // we don't know this field.
88   kCustomTagNonSafeIgnoreMask = 1 << 6,
89 
90   // Forward incompatible (aka unignorable) fields
91   kPathId,
92 };
93 
94 class VersionSet;
95 
96 constexpr uint64_t kFileNumberMask = 0x3FFFFFFFFFFFFFFF;
97 constexpr uint64_t kUnknownOldestAncesterTime = 0;
98 constexpr uint64_t kUnknownFileCreationTime = 0;
99 
100 extern uint64_t PackFileNumberAndPathId(uint64_t number, uint64_t path_id);
101 
102 // A copyable structure contains information needed to read data from an SST
103 // file. It can contain a pointer to a table reader opened for the file, or
104 // file number and size, which can be used to create a new table reader for it.
105 // The behavior is undefined when a copied of the structure is used when the
106 // file is not in any live version any more.
107 struct FileDescriptor {
108   // Table reader in table_reader_handle
109   TableReader* table_reader;
110   uint64_t packed_number_and_path_id;
111   uint64_t file_size;  // File size in bytes
112   SequenceNumber smallest_seqno;  // The smallest seqno in this file
113   SequenceNumber largest_seqno;   // The largest seqno in this file
114 
FileDescriptorFileDescriptor115   FileDescriptor() : FileDescriptor(0, 0, 0) {}
116 
FileDescriptorFileDescriptor117   FileDescriptor(uint64_t number, uint32_t path_id, uint64_t _file_size)
118       : FileDescriptor(number, path_id, _file_size, kMaxSequenceNumber, 0) {}
119 
FileDescriptorFileDescriptor120   FileDescriptor(uint64_t number, uint32_t path_id, uint64_t _file_size,
121                  SequenceNumber _smallest_seqno, SequenceNumber _largest_seqno)
122       : table_reader(nullptr),
123         packed_number_and_path_id(PackFileNumberAndPathId(number, path_id)),
124         file_size(_file_size),
125         smallest_seqno(_smallest_seqno),
126         largest_seqno(_largest_seqno) {}
127 
FileDescriptorFileDescriptor128   FileDescriptor(const FileDescriptor& fd) { *this = fd; }
129 
130   FileDescriptor& operator=(const FileDescriptor& fd) {
131     table_reader = fd.table_reader;
132     packed_number_and_path_id = fd.packed_number_and_path_id;
133     file_size = fd.file_size;
134     smallest_seqno = fd.smallest_seqno;
135     largest_seqno = fd.largest_seqno;
136     return *this;
137   }
138 
GetNumberFileDescriptor139   uint64_t GetNumber() const {
140     return packed_number_and_path_id & kFileNumberMask;
141   }
GetPathIdFileDescriptor142   uint32_t GetPathId() const {
143     return static_cast<uint32_t>(
144         packed_number_and_path_id / (kFileNumberMask + 1));
145   }
GetFileSizeFileDescriptor146   uint64_t GetFileSize() const { return file_size; }
147 };
148 
149 struct FileSampledStats {
FileSampledStatsFileSampledStats150   FileSampledStats() : num_reads_sampled(0) {}
FileSampledStatsFileSampledStats151   FileSampledStats(const FileSampledStats& other) { *this = other; }
152   FileSampledStats& operator=(const FileSampledStats& other) {
153     num_reads_sampled = other.num_reads_sampled.load();
154     return *this;
155   }
156 
157   // number of user reads to this file.
158   mutable std::atomic<uint64_t> num_reads_sampled;
159 };
160 
161 struct FileMetaData {
162   FileDescriptor fd;
163   InternalKey smallest;            // Smallest internal key served by table
164   InternalKey largest;             // Largest internal key served by table
165 
166   // Needs to be disposed when refs becomes 0.
167   Cache::Handle* table_reader_handle = nullptr;
168 
169   FileSampledStats stats;
170 
171   // Stats for compensating deletion entries during compaction
172 
173   // File size compensated by deletion entry.
174   // This is updated in Version::UpdateAccumulatedStats() first time when the
175   // file is created or loaded.  After it is updated (!= 0), it is immutable.
176   uint64_t compensated_file_size = 0;
177   // These values can mutate, but they can only be read or written from
178   // single-threaded LogAndApply thread
179   uint64_t num_entries = 0;     // the number of entries.
180   uint64_t num_deletions = 0;   // the number of deletion entries.
181   uint64_t raw_key_size = 0;    // total uncompressed key size.
182   uint64_t raw_value_size = 0;  // total uncompressed value size.
183 
184   int refs = 0;  // Reference count
185 
186   bool being_compacted = false;       // Is this file undergoing compaction?
187   bool init_stats_from_file = false;  // true if the data-entry stats of this
188                                       // file has initialized from file.
189 
190   bool marked_for_compaction = false;  // True if client asked us nicely to
191                                        // compact this file.
192   Temperature temperature = Temperature::kUnknown;
193 
194   // Used only in BlobDB. The file number of the oldest blob file this SST file
195   // refers to. 0 is an invalid value; BlobDB numbers the files starting from 1.
196   uint64_t oldest_blob_file_number = kInvalidBlobFileNumber;
197 
198   // The file could be the compaction output from other SST files, which could
199   // in turn be outputs for compact older SST files. We track the memtable
200   // flush timestamp for the oldest SST file that eventually contribute data
201   // to this file. 0 means the information is not available.
202   uint64_t oldest_ancester_time = kUnknownOldestAncesterTime;
203 
204   // Unix time when the SST file is created.
205   uint64_t file_creation_time = kUnknownFileCreationTime;
206 
207   // File checksum
208   std::string file_checksum = kUnknownFileChecksum;
209 
210   // File checksum function name
211   std::string file_checksum_func_name = kUnknownFileChecksumFuncName;
212 
213   FileMetaData() = default;
214 
FileMetaDataFileMetaData215   FileMetaData(uint64_t file, uint32_t file_path_id, uint64_t file_size,
216                const InternalKey& smallest_key, const InternalKey& largest_key,
217                const SequenceNumber& smallest_seq,
218                const SequenceNumber& largest_seq, bool marked_for_compact,
219                uint64_t oldest_blob_file, uint64_t _oldest_ancester_time,
220                uint64_t _file_creation_time, const std::string& _file_checksum,
221                const std::string& _file_checksum_func_name)
222       : fd(file, file_path_id, file_size, smallest_seq, largest_seq),
223         smallest(smallest_key),
224         largest(largest_key),
225         marked_for_compaction(marked_for_compact),
226         oldest_blob_file_number(oldest_blob_file),
227         oldest_ancester_time(_oldest_ancester_time),
228         file_creation_time(_file_creation_time),
229         file_checksum(_file_checksum),
230         file_checksum_func_name(_file_checksum_func_name) {
231     TEST_SYNC_POINT_CALLBACK("FileMetaData::FileMetaData", this);
232   }
233 
234   // REQUIRED: Keys must be given to the function in sorted order (it expects
235   // the last key to be the largest).
236   void UpdateBoundaries(const Slice& key, const Slice& value,
237                         SequenceNumber seqno, ValueType value_type);
238 
239   // Unlike UpdateBoundaries, ranges do not need to be presented in any
240   // particular order.
UpdateBoundariesForRangeFileMetaData241   void UpdateBoundariesForRange(const InternalKey& start,
242                                 const InternalKey& end, SequenceNumber seqno,
243                                 const InternalKeyComparator& icmp) {
244     if (smallest.size() == 0 || icmp.Compare(start, smallest) < 0) {
245       smallest = start;
246     }
247     if (largest.size() == 0 || icmp.Compare(largest, end) < 0) {
248       largest = end;
249     }
250     fd.smallest_seqno = std::min(fd.smallest_seqno, seqno);
251     fd.largest_seqno = std::max(fd.largest_seqno, seqno);
252   }
253 
254   // Try to get oldest ancester time from the class itself or table properties
255   // if table reader is already pinned.
256   // 0 means the information is not available.
TryGetOldestAncesterTimeFileMetaData257   uint64_t TryGetOldestAncesterTime() {
258     if (oldest_ancester_time != kUnknownOldestAncesterTime) {
259       return oldest_ancester_time;
260     } else if (fd.table_reader != nullptr &&
261                fd.table_reader->GetTableProperties() != nullptr) {
262       return fd.table_reader->GetTableProperties()->creation_time;
263     }
264     return kUnknownOldestAncesterTime;
265   }
266 
TryGetFileCreationTimeFileMetaData267   uint64_t TryGetFileCreationTime() {
268     if (file_creation_time != kUnknownFileCreationTime) {
269       return file_creation_time;
270     } else if (fd.table_reader != nullptr &&
271                fd.table_reader->GetTableProperties() != nullptr) {
272       return fd.table_reader->GetTableProperties()->file_creation_time;
273     }
274     return kUnknownFileCreationTime;
275   }
276 };
277 
278 // A compressed copy of file meta data that just contain minimum data needed
279 // to server read operations, while still keeping the pointer to full metadata
280 // of the file in case it is needed.
281 struct FdWithKeyRange {
282   FileDescriptor fd;
283   FileMetaData* file_metadata;  // Point to all metadata
284   Slice smallest_key;    // slice that contain smallest key
285   Slice largest_key;     // slice that contain largest key
286 
FdWithKeyRangeFdWithKeyRange287   FdWithKeyRange()
288       : fd(),
289         file_metadata(nullptr),
290         smallest_key(),
291         largest_key() {
292   }
293 
FdWithKeyRangeFdWithKeyRange294   FdWithKeyRange(FileDescriptor _fd, Slice _smallest_key, Slice _largest_key,
295                  FileMetaData* _file_metadata)
296       : fd(_fd),
297         file_metadata(_file_metadata),
298         smallest_key(_smallest_key),
299         largest_key(_largest_key) {}
300 };
301 
302 // Data structure to store an array of FdWithKeyRange in one level
303 // Actual data is guaranteed to be stored closely
304 struct LevelFilesBrief {
305   size_t num_files;
306   FdWithKeyRange* files;
LevelFilesBriefLevelFilesBrief307   LevelFilesBrief() {
308     num_files = 0;
309     files = nullptr;
310   }
311 };
312 
313 // The state of a DB at any given time is referred to as a Version.
314 // Any modification to the Version is considered a Version Edit. A Version is
315 // constructed by joining a sequence of Version Edits. Version Edits are written
316 // to the MANIFEST file.
317 class VersionEdit {
318  public:
319   void Clear();
320 
SetDBId(const std::string & db_id)321   void SetDBId(const std::string& db_id) {
322     has_db_id_ = true;
323     db_id_ = db_id;
324   }
HasDbId()325   bool HasDbId() const { return has_db_id_; }
GetDbId()326   const std::string& GetDbId() const { return db_id_; }
327 
SetComparatorName(const Slice & name)328   void SetComparatorName(const Slice& name) {
329     has_comparator_ = true;
330     comparator_ = name.ToString();
331   }
HasComparatorName()332   bool HasComparatorName() const { return has_comparator_; }
GetComparatorName()333   const std::string& GetComparatorName() const { return comparator_; }
334 
SetLogNumber(uint64_t num)335   void SetLogNumber(uint64_t num) {
336     has_log_number_ = true;
337     log_number_ = num;
338   }
HasLogNumber()339   bool HasLogNumber() const { return has_log_number_; }
GetLogNumber()340   uint64_t GetLogNumber() const { return log_number_; }
341 
SetPrevLogNumber(uint64_t num)342   void SetPrevLogNumber(uint64_t num) {
343     has_prev_log_number_ = true;
344     prev_log_number_ = num;
345   }
HasPrevLogNumber()346   bool HasPrevLogNumber() const { return has_prev_log_number_; }
GetPrevLogNumber()347   uint64_t GetPrevLogNumber() const { return prev_log_number_; }
348 
SetNextFile(uint64_t num)349   void SetNextFile(uint64_t num) {
350     has_next_file_number_ = true;
351     next_file_number_ = num;
352   }
HasNextFile()353   bool HasNextFile() const { return has_next_file_number_; }
GetNextFile()354   uint64_t GetNextFile() const { return next_file_number_; }
355 
SetMaxColumnFamily(uint32_t max_column_family)356   void SetMaxColumnFamily(uint32_t max_column_family) {
357     has_max_column_family_ = true;
358     max_column_family_ = max_column_family;
359   }
HasMaxColumnFamily()360   bool HasMaxColumnFamily() const { return has_max_column_family_; }
GetMaxColumnFamily()361   uint32_t GetMaxColumnFamily() const { return max_column_family_; }
362 
SetMinLogNumberToKeep(uint64_t num)363   void SetMinLogNumberToKeep(uint64_t num) {
364     has_min_log_number_to_keep_ = true;
365     min_log_number_to_keep_ = num;
366   }
HasMinLogNumberToKeep()367   bool HasMinLogNumberToKeep() const { return has_min_log_number_to_keep_; }
GetMinLogNumberToKeep()368   uint64_t GetMinLogNumberToKeep() const { return min_log_number_to_keep_; }
369 
SetLastSequence(SequenceNumber seq)370   void SetLastSequence(SequenceNumber seq) {
371     has_last_sequence_ = true;
372     last_sequence_ = seq;
373   }
HasLastSequence()374   bool HasLastSequence() const { return has_last_sequence_; }
GetLastSequence()375   SequenceNumber GetLastSequence() const { return last_sequence_; }
376 
377   // Delete the specified table file from the specified level.
DeleteFile(int level,uint64_t file)378   void DeleteFile(int level, uint64_t file) {
379     deleted_files_.emplace(level, file);
380   }
381 
382   // Retrieve the table files deleted as well as their associated levels.
383   using DeletedFiles = std::set<std::pair<int, uint64_t>>;
GetDeletedFiles()384   const DeletedFiles& GetDeletedFiles() const { return deleted_files_; }
385 
386   // Add the specified table file at the specified level.
387   // REQUIRES: This version has not been saved (see VersionSet::SaveTo)
388   // REQUIRES: "smallest" and "largest" are smallest and largest keys in file
389   // REQUIRES: "oldest_blob_file_number" is the number of the oldest blob file
390   // referred to by this file if any, kInvalidBlobFileNumber otherwise.
AddFile(int level,uint64_t file,uint32_t file_path_id,uint64_t file_size,const InternalKey & smallest,const InternalKey & largest,const SequenceNumber & smallest_seqno,const SequenceNumber & largest_seqno,bool marked_for_compaction,uint64_t oldest_blob_file_number,uint64_t oldest_ancester_time,uint64_t file_creation_time,const std::string & file_checksum,const std::string & file_checksum_func_name)391   void AddFile(int level, uint64_t file, uint32_t file_path_id,
392                uint64_t file_size, const InternalKey& smallest,
393                const InternalKey& largest, const SequenceNumber& smallest_seqno,
394                const SequenceNumber& largest_seqno, bool marked_for_compaction,
395                uint64_t oldest_blob_file_number, uint64_t oldest_ancester_time,
396                uint64_t file_creation_time, const std::string& file_checksum,
397                const std::string& file_checksum_func_name) {
398     assert(smallest_seqno <= largest_seqno);
399     new_files_.emplace_back(
400         level, FileMetaData(file, file_path_id, file_size, smallest, largest,
401                             smallest_seqno, largest_seqno,
402                             marked_for_compaction, oldest_blob_file_number,
403                             oldest_ancester_time, file_creation_time,
404                             file_checksum, file_checksum_func_name));
405   }
406 
AddFile(int level,const FileMetaData & f)407   void AddFile(int level, const FileMetaData& f) {
408     assert(f.fd.smallest_seqno <= f.fd.largest_seqno);
409     new_files_.emplace_back(level, f);
410   }
411 
412   // Retrieve the table files added as well as their associated levels.
413   using NewFiles = std::vector<std::pair<int, FileMetaData>>;
GetNewFiles()414   const NewFiles& GetNewFiles() const { return new_files_; }
415 
416   // Add a new blob file.
AddBlobFile(uint64_t blob_file_number,uint64_t total_blob_count,uint64_t total_blob_bytes,std::string checksum_method,std::string checksum_value)417   void AddBlobFile(uint64_t blob_file_number, uint64_t total_blob_count,
418                    uint64_t total_blob_bytes, std::string checksum_method,
419                    std::string checksum_value) {
420     blob_file_additions_.emplace_back(
421         blob_file_number, total_blob_count, total_blob_bytes,
422         std::move(checksum_method), std::move(checksum_value));
423   }
424 
AddBlobFile(BlobFileAddition blob_file_addition)425   void AddBlobFile(BlobFileAddition blob_file_addition) {
426     blob_file_additions_.emplace_back(std::move(blob_file_addition));
427   }
428 
429   // Retrieve all the blob files added.
430   using BlobFileAdditions = std::vector<BlobFileAddition>;
GetBlobFileAdditions()431   const BlobFileAdditions& GetBlobFileAdditions() const {
432     return blob_file_additions_;
433   }
434 
SetBlobFileAdditions(BlobFileAdditions blob_file_additions)435   void SetBlobFileAdditions(BlobFileAdditions blob_file_additions) {
436     assert(blob_file_additions_.empty());
437     blob_file_additions_ = std::move(blob_file_additions);
438   }
439 
440   // Add garbage for an existing blob file.  Note: intentionally broken English
441   // follows.
AddBlobFileGarbage(uint64_t blob_file_number,uint64_t garbage_blob_count,uint64_t garbage_blob_bytes)442   void AddBlobFileGarbage(uint64_t blob_file_number,
443                           uint64_t garbage_blob_count,
444                           uint64_t garbage_blob_bytes) {
445     blob_file_garbages_.emplace_back(blob_file_number, garbage_blob_count,
446                                      garbage_blob_bytes);
447   }
448 
AddBlobFileGarbage(BlobFileGarbage blob_file_garbage)449   void AddBlobFileGarbage(BlobFileGarbage blob_file_garbage) {
450     blob_file_garbages_.emplace_back(std::move(blob_file_garbage));
451   }
452 
453   // Retrieve all the blob file garbage added.
454   using BlobFileGarbages = std::vector<BlobFileGarbage>;
GetBlobFileGarbages()455   const BlobFileGarbages& GetBlobFileGarbages() const {
456     return blob_file_garbages_;
457   }
458 
SetBlobFileGarbages(BlobFileGarbages blob_file_garbages)459   void SetBlobFileGarbages(BlobFileGarbages blob_file_garbages) {
460     assert(blob_file_garbages_.empty());
461     blob_file_garbages_ = std::move(blob_file_garbages);
462   }
463 
464   // Add a WAL (either just created or closed).
465   // AddWal and DeleteWalsBefore cannot be called on the same VersionEdit.
466   void AddWal(WalNumber number, WalMetadata metadata = WalMetadata()) {
467     assert(NumEntries() == wal_additions_.size());
468     wal_additions_.emplace_back(number, std::move(metadata));
469   }
470 
471   // Retrieve all the added WALs.
GetWalAdditions()472   const WalAdditions& GetWalAdditions() const { return wal_additions_; }
473 
IsWalAddition()474   bool IsWalAddition() const { return !wal_additions_.empty(); }
475 
476   // Delete a WAL (either directly deleted or archived).
477   // AddWal and DeleteWalsBefore cannot be called on the same VersionEdit.
DeleteWalsBefore(WalNumber number)478   void DeleteWalsBefore(WalNumber number) {
479     assert((NumEntries() == 1) == !wal_deletion_.IsEmpty());
480     wal_deletion_ = WalDeletion(number);
481   }
482 
GetWalDeletion()483   const WalDeletion& GetWalDeletion() const { return wal_deletion_; }
484 
IsWalDeletion()485   bool IsWalDeletion() const { return !wal_deletion_.IsEmpty(); }
486 
IsWalManipulation()487   bool IsWalManipulation() const {
488     size_t entries = NumEntries();
489     return (entries > 0) && ((entries == wal_additions_.size()) ||
490                              (entries == !wal_deletion_.IsEmpty()));
491   }
492 
493   // Number of edits
NumEntries()494   size_t NumEntries() const {
495     return new_files_.size() + deleted_files_.size() +
496            blob_file_additions_.size() + blob_file_garbages_.size() +
497            wal_additions_.size() + !wal_deletion_.IsEmpty();
498   }
499 
SetColumnFamily(uint32_t column_family_id)500   void SetColumnFamily(uint32_t column_family_id) {
501     column_family_ = column_family_id;
502   }
GetColumnFamily()503   uint32_t GetColumnFamily() const { return column_family_; }
504 
505   // set column family ID by calling SetColumnFamily()
AddColumnFamily(const std::string & name)506   void AddColumnFamily(const std::string& name) {
507     assert(!is_column_family_drop_);
508     assert(!is_column_family_add_);
509     assert(NumEntries() == 0);
510     is_column_family_add_ = true;
511     column_family_name_ = name;
512   }
513 
514   // set column family ID by calling SetColumnFamily()
DropColumnFamily()515   void DropColumnFamily() {
516     assert(!is_column_family_drop_);
517     assert(!is_column_family_add_);
518     assert(NumEntries() == 0);
519     is_column_family_drop_ = true;
520   }
521 
IsColumnFamilyManipulation()522   bool IsColumnFamilyManipulation() const {
523     return is_column_family_add_ || is_column_family_drop_;
524   }
525 
IsColumnFamilyAdd()526   bool IsColumnFamilyAdd() const { return is_column_family_add_; }
527 
IsColumnFamilyDrop()528   bool IsColumnFamilyDrop() const { return is_column_family_drop_; }
529 
MarkAtomicGroup(uint32_t remaining_entries)530   void MarkAtomicGroup(uint32_t remaining_entries) {
531     is_in_atomic_group_ = true;
532     remaining_entries_ = remaining_entries;
533   }
IsInAtomicGroup()534   bool IsInAtomicGroup() const { return is_in_atomic_group_; }
GetRemainingEntries()535   uint32_t GetRemainingEntries() const { return remaining_entries_; }
536 
HasFullHistoryTsLow()537   bool HasFullHistoryTsLow() const { return !full_history_ts_low_.empty(); }
GetFullHistoryTsLow()538   const std::string& GetFullHistoryTsLow() const {
539     assert(HasFullHistoryTsLow());
540     return full_history_ts_low_;
541   }
SetFullHistoryTsLow(std::string full_history_ts_low)542   void SetFullHistoryTsLow(std::string full_history_ts_low) {
543     assert(!full_history_ts_low.empty());
544     full_history_ts_low_ = std::move(full_history_ts_low);
545   }
546 
547   // return true on success.
548   bool EncodeTo(std::string* dst) const;
549   Status DecodeFrom(const Slice& src);
550 
551   std::string DebugString(bool hex_key = false) const;
552   std::string DebugJSON(int edit_num, bool hex_key = false) const;
553 
554  private:
555   friend class ReactiveVersionSet;
556   friend class VersionEditHandlerBase;
557   friend class ListColumnFamiliesHandler;
558   friend class VersionEditHandler;
559   friend class VersionEditHandlerPointInTime;
560   friend class DumpManifestHandler;
561   friend class VersionSet;
562   friend class Version;
563   friend class AtomicGroupReadBuffer;
564 
565   bool GetLevel(Slice* input, int* level, const char** msg);
566 
567   const char* DecodeNewFile4From(Slice* input);
568 
569   int max_level_ = 0;
570   std::string db_id_;
571   std::string comparator_;
572   uint64_t log_number_ = 0;
573   uint64_t prev_log_number_ = 0;
574   uint64_t next_file_number_ = 0;
575   uint32_t max_column_family_ = 0;
576   // The most recent WAL log number that is deleted
577   uint64_t min_log_number_to_keep_ = 0;
578   SequenceNumber last_sequence_ = 0;
579   bool has_db_id_ = false;
580   bool has_comparator_ = false;
581   bool has_log_number_ = false;
582   bool has_prev_log_number_ = false;
583   bool has_next_file_number_ = false;
584   bool has_max_column_family_ = false;
585   bool has_min_log_number_to_keep_ = false;
586   bool has_last_sequence_ = false;
587 
588   DeletedFiles deleted_files_;
589   NewFiles new_files_;
590 
591   BlobFileAdditions blob_file_additions_;
592   BlobFileGarbages blob_file_garbages_;
593 
594   WalAdditions wal_additions_;
595   WalDeletion wal_deletion_;
596 
597   // Each version edit record should have column_family_ set
598   // If it's not set, it is default (0)
599   uint32_t column_family_ = 0;
600   // a version edit can be either column_family add or
601   // column_family drop. If it's column family add,
602   // it also includes column family name.
603   bool is_column_family_drop_ = false;
604   bool is_column_family_add_ = false;
605   std::string column_family_name_;
606 
607   bool is_in_atomic_group_ = false;
608   uint32_t remaining_entries_ = 0;
609 
610   std::string full_history_ts_low_;
611 };
612 
613 }  // namespace ROCKSDB_NAMESPACE
614