]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/db/version_edit.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / db / version_edit.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
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#include "db/version_edit.h"
11
20effc67 12#include "db/blob/blob_index.h"
7c673cae 13#include "db/version_set.h"
f67539c2 14#include "logging/event_logger.h"
7c673cae 15#include "rocksdb/slice.h"
f67539c2 16#include "test_util/sync_point.h"
7c673cae 17#include "util/coding.h"
7c673cae 18#include "util/string_util.h"
7c673cae 19
f67539c2 20namespace ROCKSDB_NAMESPACE {
20effc67
TL
21
22namespace {
23
24} // anonymous namespace
7c673cae
FG
25
26uint64_t PackFileNumberAndPathId(uint64_t number, uint64_t path_id) {
27 assert(number <= kFileNumberMask);
28 return number | (path_id * (kFileNumberMask + 1));
29}
30
f67539c2
TL
31void FileMetaData::UpdateBoundaries(const Slice& key, const Slice& value,
32 SequenceNumber seqno,
33 ValueType value_type) {
34 if (smallest.size() == 0) {
35 smallest.DecodeFrom(key);
36 }
37 largest.DecodeFrom(key);
38 fd.smallest_seqno = std::min(fd.smallest_seqno, seqno);
39 fd.largest_seqno = std::max(fd.largest_seqno, seqno);
40
f67539c2
TL
41 if (value_type == kTypeBlobIndex) {
42 BlobIndex blob_index;
43 const Status s = blob_index.DecodeFrom(value);
44 if (!s.ok()) {
45 return;
46 }
47
48 if (blob_index.IsInlined()) {
49 return;
50 }
51
52 if (blob_index.HasTTL()) {
53 return;
54 }
55
56 // Paranoid check: this should not happen because BlobDB numbers the blob
57 // files starting from 1.
58 if (blob_index.file_number() == kInvalidBlobFileNumber) {
59 return;
60 }
61
62 if (oldest_blob_file_number == kInvalidBlobFileNumber ||
63 oldest_blob_file_number > blob_index.file_number()) {
64 oldest_blob_file_number = blob_index.file_number();
65 }
66 }
f67539c2
TL
67}
68
7c673cae 69void VersionEdit::Clear() {
7c673cae 70 max_level_ = 0;
f67539c2
TL
71 db_id_.clear();
72 comparator_.clear();
7c673cae
FG
73 log_number_ = 0;
74 prev_log_number_ = 0;
7c673cae
FG
75 next_file_number_ = 0;
76 max_column_family_ = 0;
11fdf7f2 77 min_log_number_to_keep_ = 0;
f67539c2
TL
78 last_sequence_ = 0;
79 has_db_id_ = false;
7c673cae
FG
80 has_comparator_ = false;
81 has_log_number_ = false;
82 has_prev_log_number_ = false;
83 has_next_file_number_ = false;
7c673cae 84 has_max_column_family_ = false;
11fdf7f2 85 has_min_log_number_to_keep_ = false;
f67539c2 86 has_last_sequence_ = false;
7c673cae
FG
87 deleted_files_.clear();
88 new_files_.clear();
20effc67
TL
89 blob_file_additions_.clear();
90 blob_file_garbages_.clear();
91 wal_additions_.clear();
92 wal_deletion_.Reset();
7c673cae 93 column_family_ = 0;
f67539c2
TL
94 is_column_family_add_ = false;
95 is_column_family_drop_ = false;
7c673cae 96 column_family_name_.clear();
11fdf7f2
TL
97 is_in_atomic_group_ = false;
98 remaining_entries_ = 0;
7c673cae
FG
99}
100
101bool VersionEdit::EncodeTo(std::string* dst) const {
f67539c2
TL
102 if (has_db_id_) {
103 PutVarint32(dst, kDbId);
104 PutLengthPrefixedSlice(dst, db_id_);
105 }
7c673cae
FG
106 if (has_comparator_) {
107 PutVarint32(dst, kComparator);
108 PutLengthPrefixedSlice(dst, comparator_);
109 }
110 if (has_log_number_) {
111 PutVarint32Varint64(dst, kLogNumber, log_number_);
112 }
113 if (has_prev_log_number_) {
114 PutVarint32Varint64(dst, kPrevLogNumber, prev_log_number_);
115 }
116 if (has_next_file_number_) {
117 PutVarint32Varint64(dst, kNextFileNumber, next_file_number_);
118 }
7c673cae
FG
119 if (has_max_column_family_) {
120 PutVarint32Varint32(dst, kMaxColumnFamily, max_column_family_);
121 }
f67539c2
TL
122 if (has_last_sequence_) {
123 PutVarint32Varint64(dst, kLastSequence, last_sequence_);
124 }
7c673cae
FG
125 for (const auto& deleted : deleted_files_) {
126 PutVarint32Varint32Varint64(dst, kDeletedFile, deleted.first /* level */,
127 deleted.second /* file number */);
128 }
129
11fdf7f2 130 bool min_log_num_written = false;
7c673cae
FG
131 for (size_t i = 0; i < new_files_.size(); i++) {
132 const FileMetaData& f = new_files_[i].second;
133 if (!f.smallest.Valid() || !f.largest.Valid()) {
134 return false;
135 }
f67539c2 136 PutVarint32(dst, kNewFile4);
7c673cae 137 PutVarint32Varint64(dst, new_files_[i].first /* level */, f.fd.GetNumber());
7c673cae
FG
138 PutVarint64(dst, f.fd.GetFileSize());
139 PutLengthPrefixedSlice(dst, f.smallest.Encode());
140 PutLengthPrefixedSlice(dst, f.largest.Encode());
11fdf7f2 141 PutVarint64Varint64(dst, f.fd.smallest_seqno, f.fd.largest_seqno);
f67539c2
TL
142 // Customized fields' format:
143 // +-----------------------------+
144 // | 1st field's tag (varint32) |
145 // +-----------------------------+
146 // | 1st field's size (varint32) |
147 // +-----------------------------+
148 // | bytes for 1st field |
149 // | (based on size decoded) |
150 // +-----------------------------+
151 // | |
152 // | ...... |
153 // | |
154 // +-----------------------------+
155 // | last field's size (varint32)|
156 // +-----------------------------+
157 // | bytes for last field |
158 // | (based on size decoded) |
159 // +-----------------------------+
160 // | terminating tag (varint32) |
161 // +-----------------------------+
162 //
163 // Customized encoding for fields:
164 // tag kPathId: 1 byte as path_id
165 // tag kNeedCompaction:
166 // now only can take one char value 1 indicating need-compaction
167 //
20effc67 168 PutVarint32(dst, NewFileCustomTag::kOldestAncesterTime);
f67539c2
TL
169 std::string varint_oldest_ancester_time;
170 PutVarint64(&varint_oldest_ancester_time, f.oldest_ancester_time);
171 TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:VarintOldestAncesterTime",
172 &varint_oldest_ancester_time);
173 PutLengthPrefixedSlice(dst, Slice(varint_oldest_ancester_time));
174
20effc67 175 PutVarint32(dst, NewFileCustomTag::kFileCreationTime);
f67539c2
TL
176 std::string varint_file_creation_time;
177 PutVarint64(&varint_file_creation_time, f.file_creation_time);
178 TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:VarintFileCreationTime",
179 &varint_file_creation_time);
180 PutLengthPrefixedSlice(dst, Slice(varint_file_creation_time));
181
20effc67 182 PutVarint32(dst, NewFileCustomTag::kFileChecksum);
f67539c2
TL
183 PutLengthPrefixedSlice(dst, Slice(f.file_checksum));
184
20effc67 185 PutVarint32(dst, NewFileCustomTag::kFileChecksumFuncName);
f67539c2
TL
186 PutLengthPrefixedSlice(dst, Slice(f.file_checksum_func_name));
187
188 if (f.fd.GetPathId() != 0) {
20effc67 189 PutVarint32(dst, NewFileCustomTag::kPathId);
f67539c2
TL
190 char p = static_cast<char>(f.fd.GetPathId());
191 PutLengthPrefixedSlice(dst, Slice(&p, 1));
192 }
193 if (f.marked_for_compaction) {
20effc67 194 PutVarint32(dst, NewFileCustomTag::kNeedCompaction);
f67539c2
TL
195 char p = static_cast<char>(1);
196 PutLengthPrefixedSlice(dst, Slice(&p, 1));
7c673cae 197 }
f67539c2 198 if (has_min_log_number_to_keep_ && !min_log_num_written) {
20effc67 199 PutVarint32(dst, NewFileCustomTag::kMinLogNumberToKeepHack);
f67539c2
TL
200 std::string varint_log_number;
201 PutFixed64(&varint_log_number, min_log_number_to_keep_);
202 PutLengthPrefixedSlice(dst, Slice(varint_log_number));
203 min_log_num_written = true;
204 }
205 if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
20effc67 206 PutVarint32(dst, NewFileCustomTag::kOldestBlobFileNumber);
f67539c2
TL
207 std::string oldest_blob_file_number;
208 PutVarint64(&oldest_blob_file_number, f.oldest_blob_file_number);
209 PutLengthPrefixedSlice(dst, Slice(oldest_blob_file_number));
210 }
211 TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:NewFile4:CustomizeFields",
212 dst);
213
20effc67
TL
214 PutVarint32(dst, NewFileCustomTag::kTerminate);
215 }
216
217 for (const auto& blob_file_addition : blob_file_additions_) {
218 PutVarint32(dst, kBlobFileAddition);
219 blob_file_addition.EncodeTo(dst);
220 }
221
222 for (const auto& blob_file_garbage : blob_file_garbages_) {
223 PutVarint32(dst, kBlobFileGarbage);
224 blob_file_garbage.EncodeTo(dst);
225 }
226
227 for (const auto& wal_addition : wal_additions_) {
228 PutVarint32(dst, kWalAddition);
229 wal_addition.EncodeTo(dst);
230 }
231
232 if (!wal_deletion_.IsEmpty()) {
233 PutVarint32(dst, kWalDeletion);
234 wal_deletion_.EncodeTo(dst);
7c673cae
FG
235 }
236
237 // 0 is default and does not need to be explicitly written
238 if (column_family_ != 0) {
239 PutVarint32Varint32(dst, kColumnFamily, column_family_);
240 }
241
242 if (is_column_family_add_) {
243 PutVarint32(dst, kColumnFamilyAdd);
244 PutLengthPrefixedSlice(dst, Slice(column_family_name_));
245 }
246
247 if (is_column_family_drop_) {
248 PutVarint32(dst, kColumnFamilyDrop);
249 }
11fdf7f2
TL
250
251 if (is_in_atomic_group_) {
252 PutVarint32(dst, kInAtomicGroup);
253 PutVarint32(dst, remaining_entries_);
254 }
7c673cae
FG
255 return true;
256}
257
258static bool GetInternalKey(Slice* input, InternalKey* dst) {
259 Slice str;
260 if (GetLengthPrefixedSlice(input, &str)) {
261 dst->DecodeFrom(str);
262 return dst->Valid();
263 } else {
264 return false;
265 }
266}
267
11fdf7f2 268bool VersionEdit::GetLevel(Slice* input, int* level, const char** /*msg*/) {
f67539c2 269 uint32_t v = 0;
7c673cae
FG
270 if (GetVarint32(input, &v)) {
271 *level = v;
272 if (max_level_ < *level) {
273 max_level_ = *level;
274 }
275 return true;
276 } else {
277 return false;
278 }
279}
280
11fdf7f2
TL
281static bool is_pseudo_new_file_record_pr3488(
282 const int level,
283 const uint64_t number,
284 const uint64_t file_size,
285 InternalKey& smallest,
286 InternalKey& largest,
287 const bool has_min_log_number_to_keep_) {
288
289 if (level == 0 && number == 0 && file_size == 0 &&
290 has_min_log_number_to_keep_) {
291 InternalKey dummy_key(Slice("dummy_key"), 0ull, ValueType::kTypeValue);
292 return (*smallest.rep() == *dummy_key.rep() &&
293 *largest.rep() == *dummy_key.rep());
294 } else {
295 return false;
296 }
297}
298
7c673cae
FG
299const char* VersionEdit::DecodeNewFile4From(Slice* input) {
300 const char* msg = nullptr;
f67539c2 301 int level = 0;
7c673cae 302 FileMetaData f;
f67539c2 303 uint64_t number = 0;
7c673cae 304 uint32_t path_id = 0;
f67539c2
TL
305 uint64_t file_size = 0;
306 SequenceNumber smallest_seqno = 0;
307 SequenceNumber largest_seqno = kMaxSequenceNumber;
7c673cae
FG
308 if (GetLevel(input, &level, &msg) && GetVarint64(input, &number) &&
309 GetVarint64(input, &file_size) && GetInternalKey(input, &f.smallest) &&
310 GetInternalKey(input, &f.largest) &&
11fdf7f2
TL
311 GetVarint64(input, &smallest_seqno) &&
312 GetVarint64(input, &largest_seqno)) {
7c673cae
FG
313 // See comments in VersionEdit::EncodeTo() for format of customized fields
314 while (true) {
f67539c2 315 uint32_t custom_tag = 0;
7c673cae
FG
316 Slice field;
317 if (!GetVarint32(input, &custom_tag)) {
318 return "new-file4 custom field";
319 }
320 if (custom_tag == kTerminate) {
321 break;
322 }
323 if (!GetLengthPrefixedSlice(input, &field)) {
494da23a 324 return "new-file4 custom field length prefixed slice error";
7c673cae
FG
325 }
326 switch (custom_tag) {
327 case kPathId:
328 if (field.size() != 1) {
329 return "path_id field wrong size";
330 }
331 path_id = field[0];
332 if (path_id > 3) {
333 return "path_id wrong vaue";
334 }
335 break;
f67539c2
TL
336 case kOldestAncesterTime:
337 if (!GetVarint64(&field, &f.oldest_ancester_time)) {
338 return "invalid oldest ancester time";
339 }
340 break;
341 case kFileCreationTime:
342 if (!GetVarint64(&field, &f.file_creation_time)) {
343 return "invalid file creation time";
344 }
345 break;
346 case kFileChecksum:
347 f.file_checksum = field.ToString();
348 break;
349 case kFileChecksumFuncName:
350 f.file_checksum_func_name = field.ToString();
351 break;
7c673cae
FG
352 case kNeedCompaction:
353 if (field.size() != 1) {
354 return "need_compaction field wrong size";
355 }
356 f.marked_for_compaction = (field[0] == 1);
357 break;
11fdf7f2
TL
358 case kMinLogNumberToKeepHack:
359 // This is a hack to encode kMinLogNumberToKeep in a
360 // forward-compatible fashion.
361 if (!GetFixed64(&field, &min_log_number_to_keep_)) {
362 return "deleted log number malformatted";
363 }
364 has_min_log_number_to_keep_ = true;
365 break;
f67539c2
TL
366 case kOldestBlobFileNumber:
367 if (!GetVarint64(&field, &f.oldest_blob_file_number)) {
368 return "invalid oldest blob file number";
369 }
370 break;
7c673cae
FG
371 default:
372 if ((custom_tag & kCustomTagNonSafeIgnoreMask) != 0) {
373 // Should not proceed if cannot understand it
374 return "new-file4 custom field not supported";
375 }
376 break;
377 }
378 }
379 } else {
380 return "new-file4 entry";
381 }
11fdf7f2
TL
382 if (is_pseudo_new_file_record_pr3488(level, number, file_size,
383 f.smallest, f.largest,
384 has_min_log_number_to_keep_)) {
385 // Since this has nothing to do with NewFile, return immediately.
386 return nullptr;
387 }
388 f.fd =
389 FileDescriptor(number, path_id, file_size, smallest_seqno, largest_seqno);
7c673cae
FG
390 new_files_.push_back(std::make_pair(level, f));
391 return nullptr;
392}
393
394Status VersionEdit::DecodeFrom(const Slice& src) {
395 Clear();
396 Slice input = src;
397 const char* msg = nullptr;
f67539c2 398 uint32_t tag = 0;
7c673cae
FG
399
400 // Temporary storage for parsing
f67539c2 401 int level = 0;
7c673cae
FG
402 FileMetaData f;
403 Slice str;
404 InternalKey key;
7c673cae
FG
405 while (msg == nullptr && GetVarint32(&input, &tag)) {
406 switch (tag) {
f67539c2
TL
407 case kDbId:
408 if (GetLengthPrefixedSlice(&input, &str)) {
409 db_id_ = str.ToString();
410 has_db_id_ = true;
411 } else {
412 msg = "db id";
413 }
414 break;
7c673cae
FG
415 case kComparator:
416 if (GetLengthPrefixedSlice(&input, &str)) {
417 comparator_ = str.ToString();
418 has_comparator_ = true;
419 } else {
420 msg = "comparator name";
421 }
422 break;
423
424 case kLogNumber:
425 if (GetVarint64(&input, &log_number_)) {
426 has_log_number_ = true;
427 } else {
428 msg = "log number";
429 }
430 break;
431
432 case kPrevLogNumber:
433 if (GetVarint64(&input, &prev_log_number_)) {
434 has_prev_log_number_ = true;
435 } else {
436 msg = "previous log number";
437 }
438 break;
439
440 case kNextFileNumber:
441 if (GetVarint64(&input, &next_file_number_)) {
442 has_next_file_number_ = true;
443 } else {
444 msg = "next file number";
445 }
446 break;
447
7c673cae
FG
448 case kMaxColumnFamily:
449 if (GetVarint32(&input, &max_column_family_)) {
450 has_max_column_family_ = true;
451 } else {
452 msg = "max column family";
453 }
454 break;
455
11fdf7f2
TL
456 case kMinLogNumberToKeep:
457 if (GetVarint64(&input, &min_log_number_to_keep_)) {
458 has_min_log_number_to_keep_ = true;
459 } else {
460 msg = "min log number to kee";
461 }
462 break;
463
f67539c2
TL
464 case kLastSequence:
465 if (GetVarint64(&input, &last_sequence_)) {
466 has_last_sequence_ = true;
467 } else {
468 msg = "last sequence number";
469 }
470 break;
471
7c673cae
FG
472 case kCompactPointer:
473 if (GetLevel(&input, &level, &msg) &&
474 GetInternalKey(&input, &key)) {
475 // we don't use compact pointers anymore,
476 // but we should not fail if they are still
477 // in manifest
478 } else {
479 if (!msg) {
480 msg = "compaction pointer";
481 }
482 }
483 break;
484
485 case kDeletedFile: {
f67539c2 486 uint64_t number = 0;
7c673cae
FG
487 if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number)) {
488 deleted_files_.insert(std::make_pair(level, number));
489 } else {
490 if (!msg) {
491 msg = "deleted file";
492 }
493 }
494 break;
495 }
496
497 case kNewFile: {
f67539c2
TL
498 uint64_t number = 0;
499 uint64_t file_size = 0;
7c673cae
FG
500 if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
501 GetVarint64(&input, &file_size) &&
502 GetInternalKey(&input, &f.smallest) &&
503 GetInternalKey(&input, &f.largest)) {
504 f.fd = FileDescriptor(number, 0, file_size);
505 new_files_.push_back(std::make_pair(level, f));
506 } else {
507 if (!msg) {
508 msg = "new-file entry";
509 }
510 }
511 break;
512 }
513 case kNewFile2: {
f67539c2
TL
514 uint64_t number = 0;
515 uint64_t file_size = 0;
516 SequenceNumber smallest_seqno = 0;
517 SequenceNumber largest_seqno = kMaxSequenceNumber;
7c673cae
FG
518 if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
519 GetVarint64(&input, &file_size) &&
520 GetInternalKey(&input, &f.smallest) &&
521 GetInternalKey(&input, &f.largest) &&
11fdf7f2
TL
522 GetVarint64(&input, &smallest_seqno) &&
523 GetVarint64(&input, &largest_seqno)) {
524 f.fd = FileDescriptor(number, 0, file_size, smallest_seqno,
525 largest_seqno);
7c673cae
FG
526 new_files_.push_back(std::make_pair(level, f));
527 } else {
528 if (!msg) {
529 msg = "new-file2 entry";
530 }
531 }
532 break;
533 }
534
535 case kNewFile3: {
f67539c2
TL
536 uint64_t number = 0;
537 uint32_t path_id = 0;
538 uint64_t file_size = 0;
539 SequenceNumber smallest_seqno = 0;
540 SequenceNumber largest_seqno = kMaxSequenceNumber;
7c673cae
FG
541 if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
542 GetVarint32(&input, &path_id) && GetVarint64(&input, &file_size) &&
543 GetInternalKey(&input, &f.smallest) &&
544 GetInternalKey(&input, &f.largest) &&
11fdf7f2
TL
545 GetVarint64(&input, &smallest_seqno) &&
546 GetVarint64(&input, &largest_seqno)) {
547 f.fd = FileDescriptor(number, path_id, file_size, smallest_seqno,
548 largest_seqno);
7c673cae
FG
549 new_files_.push_back(std::make_pair(level, f));
550 } else {
551 if (!msg) {
552 msg = "new-file3 entry";
553 }
554 }
555 break;
556 }
557
558 case kNewFile4: {
559 msg = DecodeNewFile4From(&input);
560 break;
561 }
562
20effc67
TL
563 case kBlobFileAddition: {
564 BlobFileAddition blob_file_addition;
565 const Status s = blob_file_addition.DecodeFrom(&input);
566 if (!s.ok()) {
567 return s;
568 }
569
570 AddBlobFile(std::move(blob_file_addition));
571 break;
572 }
573
574 case kBlobFileGarbage: {
575 BlobFileGarbage blob_file_garbage;
576 const Status s = blob_file_garbage.DecodeFrom(&input);
577 if (!s.ok()) {
578 return s;
579 }
580
581 AddBlobFileGarbage(std::move(blob_file_garbage));
582 break;
583 }
584
585 case kWalAddition: {
586 WalAddition wal_addition;
587 const Status s = wal_addition.DecodeFrom(&input);
588 if (!s.ok()) {
589 return s;
590 }
591
592 wal_additions_.emplace_back(std::move(wal_addition));
593 break;
594 }
595
596 case kWalDeletion: {
597 WalDeletion wal_deletion;
598 const Status s = wal_deletion.DecodeFrom(&input);
599 if (!s.ok()) {
600 return s;
601 }
602
603 wal_deletion_ = std::move(wal_deletion);
604 break;
605 }
606
7c673cae
FG
607 case kColumnFamily:
608 if (!GetVarint32(&input, &column_family_)) {
609 if (!msg) {
610 msg = "set column family id";
611 }
612 }
613 break;
614
615 case kColumnFamilyAdd:
616 if (GetLengthPrefixedSlice(&input, &str)) {
617 is_column_family_add_ = true;
618 column_family_name_ = str.ToString();
619 } else {
620 if (!msg) {
621 msg = "column family add";
622 }
623 }
624 break;
625
626 case kColumnFamilyDrop:
627 is_column_family_drop_ = true;
628 break;
629
11fdf7f2
TL
630 case kInAtomicGroup:
631 is_in_atomic_group_ = true;
632 if (!GetVarint32(&input, &remaining_entries_)) {
633 if (!msg) {
634 msg = "remaining entries";
635 }
636 }
637 break;
638
7c673cae 639 default:
494da23a
TL
640 if (tag & kTagSafeIgnoreMask) {
641 // Tag from future which can be safely ignored.
642 // The next field must be the length of the entry.
643 uint32_t field_len;
644 if (!GetVarint32(&input, &field_len) ||
645 static_cast<size_t>(field_len) > input.size()) {
646 if (!msg) {
647 msg = "safely ignoreable tag length error";
648 }
649 } else {
650 input.remove_prefix(static_cast<size_t>(field_len));
651 }
652 } else {
653 msg = "unknown tag";
654 }
7c673cae
FG
655 break;
656 }
657 }
658
659 if (msg == nullptr && !input.empty()) {
660 msg = "invalid tag";
661 }
662
663 Status result;
664 if (msg != nullptr) {
665 result = Status::Corruption("VersionEdit", msg);
666 }
667 return result;
668}
669
670std::string VersionEdit::DebugString(bool hex_key) const {
671 std::string r;
672 r.append("VersionEdit {");
f67539c2
TL
673 if (has_db_id_) {
674 r.append("\n DB ID: ");
675 r.append(db_id_);
676 }
7c673cae
FG
677 if (has_comparator_) {
678 r.append("\n Comparator: ");
679 r.append(comparator_);
680 }
681 if (has_log_number_) {
682 r.append("\n LogNumber: ");
683 AppendNumberTo(&r, log_number_);
684 }
685 if (has_prev_log_number_) {
686 r.append("\n PrevLogNumber: ");
687 AppendNumberTo(&r, prev_log_number_);
688 }
689 if (has_next_file_number_) {
690 r.append("\n NextFileNumber: ");
691 AppendNumberTo(&r, next_file_number_);
692 }
f67539c2
TL
693 if (has_max_column_family_) {
694 r.append("\n MaxColumnFamily: ");
695 AppendNumberTo(&r, max_column_family_);
696 }
11fdf7f2
TL
697 if (has_min_log_number_to_keep_) {
698 r.append("\n MinLogNumberToKeep: ");
699 AppendNumberTo(&r, min_log_number_to_keep_);
700 }
7c673cae
FG
701 if (has_last_sequence_) {
702 r.append("\n LastSeq: ");
703 AppendNumberTo(&r, last_sequence_);
704 }
f67539c2 705 for (const auto& deleted_file : deleted_files_) {
7c673cae 706 r.append("\n DeleteFile: ");
f67539c2 707 AppendNumberTo(&r, deleted_file.first);
7c673cae 708 r.append(" ");
f67539c2 709 AppendNumberTo(&r, deleted_file.second);
7c673cae
FG
710 }
711 for (size_t i = 0; i < new_files_.size(); i++) {
712 const FileMetaData& f = new_files_[i].second;
713 r.append("\n AddFile: ");
714 AppendNumberTo(&r, new_files_[i].first);
715 r.append(" ");
716 AppendNumberTo(&r, f.fd.GetNumber());
717 r.append(" ");
718 AppendNumberTo(&r, f.fd.GetFileSize());
719 r.append(" ");
720 r.append(f.smallest.DebugString(hex_key));
721 r.append(" .. ");
722 r.append(f.largest.DebugString(hex_key));
f67539c2
TL
723 if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
724 r.append(" blob_file:");
725 AppendNumberTo(&r, f.oldest_blob_file_number);
726 }
727 r.append(" oldest_ancester_time:");
728 AppendNumberTo(&r, f.oldest_ancester_time);
729 r.append(" file_creation_time:");
730 AppendNumberTo(&r, f.file_creation_time);
731 r.append(" file_checksum:");
732 r.append(f.file_checksum);
733 r.append(" file_checksum_func_name: ");
734 r.append(f.file_checksum_func_name);
7c673cae 735 }
20effc67
TL
736
737 for (const auto& blob_file_addition : blob_file_additions_) {
738 r.append("\n BlobFileAddition: ");
739 r.append(blob_file_addition.DebugString());
740 }
741
742 for (const auto& blob_file_garbage : blob_file_garbages_) {
743 r.append("\n BlobFileGarbage: ");
744 r.append(blob_file_garbage.DebugString());
745 }
746
747 for (const auto& wal_addition : wal_additions_) {
748 r.append("\n WalAddition: ");
749 r.append(wal_addition.DebugString());
750 }
751
752 if (!wal_deletion_.IsEmpty()) {
753 r.append("\n WalDeletion: ");
754 r.append(wal_deletion_.DebugString());
755 }
756
7c673cae
FG
757 r.append("\n ColumnFamily: ");
758 AppendNumberTo(&r, column_family_);
759 if (is_column_family_add_) {
760 r.append("\n ColumnFamilyAdd: ");
761 r.append(column_family_name_);
762 }
763 if (is_column_family_drop_) {
764 r.append("\n ColumnFamilyDrop");
765 }
11fdf7f2 766 if (is_in_atomic_group_) {
494da23a 767 r.append("\n AtomicGroup: ");
11fdf7f2
TL
768 AppendNumberTo(&r, remaining_entries_);
769 r.append(" entries remains");
770 }
7c673cae
FG
771 r.append("\n}\n");
772 return r;
773}
774
775std::string VersionEdit::DebugJSON(int edit_num, bool hex_key) const {
776 JSONWriter jw;
777 jw << "EditNumber" << edit_num;
778
f67539c2
TL
779 if (has_db_id_) {
780 jw << "DB ID" << db_id_;
781 }
7c673cae
FG
782 if (has_comparator_) {
783 jw << "Comparator" << comparator_;
784 }
785 if (has_log_number_) {
786 jw << "LogNumber" << log_number_;
787 }
788 if (has_prev_log_number_) {
789 jw << "PrevLogNumber" << prev_log_number_;
790 }
791 if (has_next_file_number_) {
792 jw << "NextFileNumber" << next_file_number_;
793 }
f67539c2
TL
794 if (has_max_column_family_) {
795 jw << "MaxColumnFamily" << max_column_family_;
796 }
797 if (has_min_log_number_to_keep_) {
798 jw << "MinLogNumberToKeep" << min_log_number_to_keep_;
799 }
7c673cae
FG
800 if (has_last_sequence_) {
801 jw << "LastSeq" << last_sequence_;
802 }
803
804 if (!deleted_files_.empty()) {
805 jw << "DeletedFiles";
806 jw.StartArray();
807
f67539c2 808 for (const auto& deleted_file : deleted_files_) {
7c673cae 809 jw.StartArrayedObject();
f67539c2
TL
810 jw << "Level" << deleted_file.first;
811 jw << "FileNumber" << deleted_file.second;
7c673cae
FG
812 jw.EndArrayedObject();
813 }
814
815 jw.EndArray();
816 }
817
818 if (!new_files_.empty()) {
819 jw << "AddedFiles";
820 jw.StartArray();
821
822 for (size_t i = 0; i < new_files_.size(); i++) {
823 jw.StartArrayedObject();
824 jw << "Level" << new_files_[i].first;
825 const FileMetaData& f = new_files_[i].second;
826 jw << "FileNumber" << f.fd.GetNumber();
827 jw << "FileSize" << f.fd.GetFileSize();
828 jw << "SmallestIKey" << f.smallest.DebugString(hex_key);
829 jw << "LargestIKey" << f.largest.DebugString(hex_key);
f67539c2
TL
830 if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
831 jw << "OldestBlobFile" << f.oldest_blob_file_number;
832 }
7c673cae
FG
833 jw.EndArrayedObject();
834 }
835
836 jw.EndArray();
837 }
838
20effc67
TL
839 if (!blob_file_additions_.empty()) {
840 jw << "BlobFileAdditions";
841
842 jw.StartArray();
843
844 for (const auto& blob_file_addition : blob_file_additions_) {
845 jw.StartArrayedObject();
846 jw << blob_file_addition;
847 jw.EndArrayedObject();
848 }
849
850 jw.EndArray();
851 }
852
853 if (!blob_file_garbages_.empty()) {
854 jw << "BlobFileGarbages";
855
856 jw.StartArray();
857
858 for (const auto& blob_file_garbage : blob_file_garbages_) {
859 jw.StartArrayedObject();
860 jw << blob_file_garbage;
861 jw.EndArrayedObject();
862 }
863
864 jw.EndArray();
865 }
866
867 if (!wal_additions_.empty()) {
868 jw << "WalAdditions";
869
870 jw.StartArray();
871
872 for (const auto& wal_addition : wal_additions_) {
873 jw.StartArrayedObject();
874 jw << wal_addition;
875 jw.EndArrayedObject();
876 }
877
878 jw.EndArray();
879 }
880
881 if (!wal_deletion_.IsEmpty()) {
882 jw << "WalDeletion";
883 jw.StartObject();
884 jw << wal_deletion_;
885 jw.EndObject();
886 }
887
7c673cae
FG
888 jw << "ColumnFamily" << column_family_;
889
890 if (is_column_family_add_) {
891 jw << "ColumnFamilyAdd" << column_family_name_;
892 }
893 if (is_column_family_drop_) {
894 jw << "ColumnFamilyDrop" << column_family_name_;
895 }
11fdf7f2
TL
896 if (is_in_atomic_group_) {
897 jw << "AtomicGroup" << remaining_entries_;
898 }
7c673cae
FG
899
900 jw.EndObject();
901
902 return jw.Get();
903}
904
f67539c2 905} // namespace ROCKSDB_NAMESPACE