version_edit.cc 25.2 KB
Newer Older
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
S
Siying Dong 已提交
2 3 4
//  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).
5
//
J
jorlow@chromium.org 已提交
6 7 8 9 10 11
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "db/version_edit.h"

12
#include "db/blob/blob_index.h"
J
jorlow@chromium.org 已提交
13
#include "db/version_set.h"
14
#include "logging/event_logger.h"
15
#include "rocksdb/slice.h"
16
#include "test_util/sync_point.h"
J
jorlow@chromium.org 已提交
17
#include "util/coding.h"
18
#include "util/string_util.h"
J
jorlow@chromium.org 已提交
19

20
namespace ROCKSDB_NAMESPACE {
21 22

namespace {
23

24
}  // anonymous namespace
25

26 27 28 29 30
uint64_t PackFileNumberAndPathId(uint64_t number, uint64_t path_id) {
  assert(number <= kFileNumberMask);
  return number | (path_id * (kFileNumberMask + 1));
}

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
void FileMetaData::UpdateBoundaries(const Slice& key, const Slice& value,
                                    SequenceNumber seqno,
                                    ValueType value_type) {
  if (smallest.size() == 0) {
    smallest.DecodeFrom(key);
  }
  largest.DecodeFrom(key);
  fd.smallest_seqno = std::min(fd.smallest_seqno, seqno);
  fd.largest_seqno = std::max(fd.largest_seqno, seqno);

  if (value_type == kTypeBlobIndex) {
    BlobIndex blob_index;
    const Status s = blob_index.DecodeFrom(value);
    if (!s.ok()) {
      return;
    }

    if (blob_index.IsInlined()) {
      return;
    }

    if (blob_index.HasTTL()) {
      return;
    }

    // Paranoid check: this should not happen because BlobDB numbers the blob
    // files starting from 1.
    if (blob_index.file_number() == kInvalidBlobFileNumber) {
      return;
    }

    if (oldest_blob_file_number == kInvalidBlobFileNumber ||
        oldest_blob_file_number > blob_index.file_number()) {
      oldest_blob_file_number = blob_index.file_number();
    }
  }
}

J
jorlow@chromium.org 已提交
69
void VersionEdit::Clear() {
L
Levi Tamasi 已提交
70
  max_level_ = 0;
71
  db_id_.clear();
J
jorlow@chromium.org 已提交
72 73
  comparator_.clear();
  log_number_ = 0;
74
  prev_log_number_ = 0;
J
jorlow@chromium.org 已提交
75
  next_file_number_ = 0;
76
  max_column_family_ = 0;
S
Siying Dong 已提交
77
  min_log_number_to_keep_ = 0;
L
Levi Tamasi 已提交
78
  last_sequence_ = 0;
79
  has_db_id_ = false;
J
jorlow@chromium.org 已提交
80 81
  has_comparator_ = false;
  has_log_number_ = false;
82
  has_prev_log_number_ = false;
J
jorlow@chromium.org 已提交
83
  has_next_file_number_ = false;
84
  has_max_column_family_ = false;
S
Siying Dong 已提交
85
  has_min_log_number_to_keep_ = false;
L
Levi Tamasi 已提交
86
  has_last_sequence_ = false;
J
jorlow@chromium.org 已提交
87 88
  deleted_files_.clear();
  new_files_.clear();
89 90
  blob_file_additions_.clear();
  blob_file_garbages_.clear();
91 92
  wal_additions_.clear();
  wal_deletions_.clear();
93
  column_family_ = 0;
L
Levi Tamasi 已提交
94 95
  is_column_family_add_ = false;
  is_column_family_drop_ = false;
96
  column_family_name_.clear();
97 98
  is_in_atomic_group_ = false;
  remaining_entries_ = 0;
J
jorlow@chromium.org 已提交
99 100
}

101
bool VersionEdit::EncodeTo(std::string* dst) const {
102 103 104 105
  if (has_db_id_) {
    PutVarint32(dst, kDbId);
    PutLengthPrefixedSlice(dst, db_id_);
  }
J
jorlow@chromium.org 已提交
106 107 108 109 110
  if (has_comparator_) {
    PutVarint32(dst, kComparator);
    PutLengthPrefixedSlice(dst, comparator_);
  }
  if (has_log_number_) {
111
    PutVarint32Varint64(dst, kLogNumber, log_number_);
J
jorlow@chromium.org 已提交
112
  }
113
  if (has_prev_log_number_) {
114
    PutVarint32Varint64(dst, kPrevLogNumber, prev_log_number_);
115
  }
J
jorlow@chromium.org 已提交
116
  if (has_next_file_number_) {
117
    PutVarint32Varint64(dst, kNextFileNumber, next_file_number_);
J
jorlow@chromium.org 已提交
118
  }
119
  if (has_max_column_family_) {
120
    PutVarint32Varint32(dst, kMaxColumnFamily, max_column_family_);
121
  }
L
Levi Tamasi 已提交
122 123 124
  if (has_last_sequence_) {
    PutVarint32Varint64(dst, kLastSequence, last_sequence_);
  }
K
kailiu 已提交
125
  for (const auto& deleted : deleted_files_) {
126 127
    PutVarint32Varint32Varint64(dst, kDeletedFile, deleted.first /* level */,
                                deleted.second /* file number */);
J
jorlow@chromium.org 已提交
128 129
  }

S
Siying Dong 已提交
130
  bool min_log_num_written = false;
D
dgrogan@chromium.org 已提交
131
  for (size_t i = 0; i < new_files_.size(); i++) {
J
jorlow@chromium.org 已提交
132
    const FileMetaData& f = new_files_[i].second;
133 134 135
    if (!f.smallest.Valid() || !f.largest.Valid()) {
      return false;
    }
136
    PutVarint32(dst, kNewFile4);
137
    PutVarint32Varint64(dst, new_files_[i].first /* level */, f.fd.GetNumber());
138
    PutVarint64(dst, f.fd.GetFileSize());
J
jorlow@chromium.org 已提交
139 140
    PutLengthPrefixedSlice(dst, f.smallest.Encode());
    PutLengthPrefixedSlice(dst, f.largest.Encode());
141
    PutVarint64Varint64(dst, f.fd.smallest_seqno, f.fd.largest_seqno);
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    // Customized fields' format:
    // +-----------------------------+
    // | 1st field's tag (varint32)  |
    // +-----------------------------+
    // | 1st field's size (varint32) |
    // +-----------------------------+
    // |    bytes for 1st field      |
    // |  (based on size decoded)    |
    // +-----------------------------+
    // |                             |
    // |          ......             |
    // |                             |
    // +-----------------------------+
    // | last field's size (varint32)|
    // +-----------------------------+
    // |    bytes for last field     |
    // |  (based on size decoded)    |
    // +-----------------------------+
    // | terminating tag (varint32)  |
    // +-----------------------------+
    //
    // Customized encoding for fields:
    //   tag kPathId: 1 byte as path_id
    //   tag kNeedCompaction:
    //        now only can take one char value 1 indicating need-compaction
    //
168
    PutVarint32(dst, NewFileCustomTag::kOldestAncesterTime);
169 170 171 172 173
    std::string varint_oldest_ancester_time;
    PutVarint64(&varint_oldest_ancester_time, f.oldest_ancester_time);
    TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:VarintOldestAncesterTime",
                             &varint_oldest_ancester_time);
    PutLengthPrefixedSlice(dst, Slice(varint_oldest_ancester_time));
174

175
    PutVarint32(dst, NewFileCustomTag::kFileCreationTime);
176 177 178 179 180 181
    std::string varint_file_creation_time;
    PutVarint64(&varint_file_creation_time, f.file_creation_time);
    TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:VarintFileCreationTime",
                             &varint_file_creation_time);
    PutLengthPrefixedSlice(dst, Slice(varint_file_creation_time));

182
    PutVarint32(dst, NewFileCustomTag::kFileChecksum);
183 184
    PutLengthPrefixedSlice(dst, Slice(f.file_checksum));

185
    PutVarint32(dst, NewFileCustomTag::kFileChecksumFuncName);
186 187
    PutLengthPrefixedSlice(dst, Slice(f.file_checksum_func_name));

188
    if (f.fd.GetPathId() != 0) {
189
      PutVarint32(dst, NewFileCustomTag::kPathId);
190 191
      char p = static_cast<char>(f.fd.GetPathId());
      PutLengthPrefixedSlice(dst, Slice(&p, 1));
192
    }
193
    if (f.marked_for_compaction) {
194
      PutVarint32(dst, NewFileCustomTag::kNeedCompaction);
195 196 197 198
      char p = static_cast<char>(1);
      PutLengthPrefixedSlice(dst, Slice(&p, 1));
    }
    if (has_min_log_number_to_keep_ && !min_log_num_written) {
199
      PutVarint32(dst, NewFileCustomTag::kMinLogNumberToKeepHack);
200 201 202 203 204 205
      std::string varint_log_number;
      PutFixed64(&varint_log_number, min_log_number_to_keep_);
      PutLengthPrefixedSlice(dst, Slice(varint_log_number));
      min_log_num_written = true;
    }
    if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
206
      PutVarint32(dst, NewFileCustomTag::kOldestBlobFileNumber);
207 208 209 210 211 212 213
      std::string oldest_blob_file_number;
      PutVarint64(&oldest_blob_file_number, f.oldest_blob_file_number);
      PutLengthPrefixedSlice(dst, Slice(oldest_blob_file_number));
    }
    TEST_SYNC_POINT_CALLBACK("VersionEdit::EncodeTo:NewFile4:CustomizeFields",
                             dst);

214 215 216
    PutVarint32(dst, NewFileCustomTag::kTerminate);
  }

217 218 219 220 221 222 223 224
  for (const auto& blob_file_addition : blob_file_additions_) {
    PutVarint32(dst, kBlobFileAddition);
    blob_file_addition.EncodeTo(dst);
  }

  for (const auto& blob_file_garbage : blob_file_garbages_) {
    PutVarint32(dst, kBlobFileGarbage);
    blob_file_garbage.EncodeTo(dst);
J
jorlow@chromium.org 已提交
225
  }
226

227 228 229 230 231 232 233 234 235 236
  for (const auto& wal_addition : wal_additions_) {
    PutVarint32(dst, kWalAddition);
    wal_addition.EncodeTo(dst);
  }

  for (const auto& wal_deletion : wal_deletions_) {
    PutVarint32(dst, kWalDeletion);
    wal_deletion.EncodeTo(dst);
  }

237 238
  // 0 is default and does not need to be explicitly written
  if (column_family_ != 0) {
239
    PutVarint32Varint32(dst, kColumnFamily, column_family_);
240 241 242 243 244 245 246 247 248 249
  }

  if (is_column_family_add_) {
    PutVarint32(dst, kColumnFamilyAdd);
    PutLengthPrefixedSlice(dst, Slice(column_family_name_));
  }

  if (is_column_family_drop_) {
    PutVarint32(dst, kColumnFamilyDrop);
  }
250 251 252 253 254

  if (is_in_atomic_group_) {
    PutVarint32(dst, kInAtomicGroup);
    PutVarint32(dst, remaining_entries_);
  }
255
  return true;
J
jorlow@chromium.org 已提交
256 257 258 259 260 261
}

static bool GetInternalKey(Slice* input, InternalKey* dst) {
  Slice str;
  if (GetLengthPrefixedSlice(input, &str)) {
    dst->DecodeFrom(str);
262
    return dst->Valid();
J
jorlow@chromium.org 已提交
263 264 265 266 267
  } else {
    return false;
  }
}

A
Andrew Kryczka 已提交
268
bool VersionEdit::GetLevel(Slice* input, int* level, const char** /*msg*/) {
L
Levi Tamasi 已提交
269
  uint32_t v = 0;
270
  if (GetVarint32(input, &v)) {
J
jorlow@chromium.org 已提交
271
    *level = v;
272 273 274
    if (max_level_ < *level) {
      max_level_ = *level;
    }
J
jorlow@chromium.org 已提交
275 276 277 278 279 280
    return true;
  } else {
    return false;
  }
}

281 282
const char* VersionEdit::DecodeNewFile4From(Slice* input) {
  const char* msg = nullptr;
L
Levi Tamasi 已提交
283
  int level = 0;
284
  FileMetaData f;
L
Levi Tamasi 已提交
285
  uint64_t number = 0;
286
  uint32_t path_id = 0;
L
Levi Tamasi 已提交
287 288 289
  uint64_t file_size = 0;
  SequenceNumber smallest_seqno = 0;
  SequenceNumber largest_seqno = kMaxSequenceNumber;
290 291 292
  if (GetLevel(input, &level, &msg) && GetVarint64(input, &number) &&
      GetVarint64(input, &file_size) && GetInternalKey(input, &f.smallest) &&
      GetInternalKey(input, &f.largest) &&
293 294
      GetVarint64(input, &smallest_seqno) &&
      GetVarint64(input, &largest_seqno)) {
295 296
    // See comments in VersionEdit::EncodeTo() for format of customized fields
    while (true) {
L
Levi Tamasi 已提交
297
      uint32_t custom_tag = 0;
298 299 300 301 302 303 304 305
      Slice field;
      if (!GetVarint32(input, &custom_tag)) {
        return "new-file4 custom field";
      }
      if (custom_tag == kTerminate) {
        break;
      }
      if (!GetLengthPrefixedSlice(input, &field)) {
F
Faustin Lammler 已提交
306
        return "new-file4 custom field length prefixed slice error";
307 308 309 310 311 312 313 314 315 316 317
      }
      switch (custom_tag) {
        case kPathId:
          if (field.size() != 1) {
            return "path_id field wrong size";
          }
          path_id = field[0];
          if (path_id > 3) {
            return "path_id wrong vaue";
          }
          break;
318 319 320 321 322
        case kOldestAncesterTime:
          if (!GetVarint64(&field, &f.oldest_ancester_time)) {
            return "invalid oldest ancester time";
          }
          break;
323 324 325 326 327
        case kFileCreationTime:
          if (!GetVarint64(&field, &f.file_creation_time)) {
            return "invalid file creation time";
          }
          break;
328 329 330 331 332 333
        case kFileChecksum:
          f.file_checksum = field.ToString();
          break;
        case kFileChecksumFuncName:
          f.file_checksum_func_name = field.ToString();
          break;
334 335 336 337 338 339
        case kNeedCompaction:
          if (field.size() != 1) {
            return "need_compaction field wrong size";
          }
          f.marked_for_compaction = (field[0] == 1);
          break;
S
Siying Dong 已提交
340 341
        case kMinLogNumberToKeepHack:
          // This is a hack to encode kMinLogNumberToKeep in a
342
          // forward-compatible fashion.
S
Siying Dong 已提交
343 344 345 346 347
          if (!GetFixed64(&field, &min_log_number_to_keep_)) {
            return "deleted log number malformatted";
          }
          has_min_log_number_to_keep_ = true;
          break;
348 349 350 351 352
        case kOldestBlobFileNumber:
          if (!GetVarint64(&field, &f.oldest_blob_file_number)) {
            return "invalid oldest blob file number";
          }
          break;
353 354 355 356 357 358 359 360 361 362 363
        default:
          if ((custom_tag & kCustomTagNonSafeIgnoreMask) != 0) {
            // Should not proceed if cannot understand it
            return "new-file4 custom field not supported";
          }
          break;
      }
    }
  } else {
    return "new-file4 entry";
  }
364 365
  f.fd =
      FileDescriptor(number, path_id, file_size, smallest_seqno, largest_seqno);
366 367 368 369
  new_files_.push_back(std::make_pair(level, f));
  return nullptr;
}

J
jorlow@chromium.org 已提交
370 371 372
Status VersionEdit::DecodeFrom(const Slice& src) {
  Clear();
  Slice input = src;
A
Abhishek Kona 已提交
373
  const char* msg = nullptr;
L
Levi Tamasi 已提交
374
  uint32_t tag = 0;
J
jorlow@chromium.org 已提交
375 376

  // Temporary storage for parsing
L
Levi Tamasi 已提交
377
  int level = 0;
J
jorlow@chromium.org 已提交
378 379 380
  FileMetaData f;
  Slice str;
  InternalKey key;
A
Abhishek Kona 已提交
381
  while (msg == nullptr && GetVarint32(&input, &tag)) {
J
jorlow@chromium.org 已提交
382
    switch (tag) {
383 384 385 386 387 388 389 390
      case kDbId:
        if (GetLengthPrefixedSlice(&input, &str)) {
          db_id_ = str.ToString();
          has_db_id_ = true;
        } else {
          msg = "db id";
        }
        break;
J
jorlow@chromium.org 已提交
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
      case kComparator:
        if (GetLengthPrefixedSlice(&input, &str)) {
          comparator_ = str.ToString();
          has_comparator_ = true;
        } else {
          msg = "comparator name";
        }
        break;

      case kLogNumber:
        if (GetVarint64(&input, &log_number_)) {
          has_log_number_ = true;
        } else {
          msg = "log number";
        }
        break;

408 409 410 411 412 413 414 415
      case kPrevLogNumber:
        if (GetVarint64(&input, &prev_log_number_)) {
          has_prev_log_number_ = true;
        } else {
          msg = "previous log number";
        }
        break;

J
jorlow@chromium.org 已提交
416 417 418 419 420 421 422 423
      case kNextFileNumber:
        if (GetVarint64(&input, &next_file_number_)) {
          has_next_file_number_ = true;
        } else {
          msg = "next file number";
        }
        break;

424 425 426 427 428 429 430 431
      case kMaxColumnFamily:
        if (GetVarint32(&input, &max_column_family_)) {
          has_max_column_family_ = true;
        } else {
          msg = "max column family";
        }
        break;

S
Siying Dong 已提交
432 433 434 435 436 437 438 439
      case kMinLogNumberToKeep:
        if (GetVarint64(&input, &min_log_number_to_keep_)) {
          has_min_log_number_to_keep_ = true;
        } else {
          msg = "min log number to kee";
        }
        break;

L
Levi Tamasi 已提交
440 441 442 443 444 445 446 447
      case kLastSequence:
        if (GetVarint64(&input, &last_sequence_)) {
          has_last_sequence_ = true;
        } else {
          msg = "last sequence number";
        }
        break;

J
jorlow@chromium.org 已提交
448
      case kCompactPointer:
449
        if (GetLevel(&input, &level, &msg) &&
J
jorlow@chromium.org 已提交
450
            GetInternalKey(&input, &key)) {
I
Igor Canadi 已提交
451 452 453
          // we don't use compact pointers anymore,
          // but we should not fail if they are still
          // in manifest
J
jorlow@chromium.org 已提交
454
        } else {
455 456 457
          if (!msg) {
            msg = "compaction pointer";
          }
J
jorlow@chromium.org 已提交
458 459 460
        }
        break;

I
Igor Canadi 已提交
461
      case kDeletedFile: {
L
Levi Tamasi 已提交
462
        uint64_t number = 0;
I
Igor Canadi 已提交
463
        if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number)) {
J
jorlow@chromium.org 已提交
464 465
          deleted_files_.insert(std::make_pair(level, number));
        } else {
466 467 468
          if (!msg) {
            msg = "deleted file";
          }
J
jorlow@chromium.org 已提交
469 470
        }
        break;
I
Igor Canadi 已提交
471
      }
J
jorlow@chromium.org 已提交
472

473
      case kNewFile: {
L
Levi Tamasi 已提交
474 475
        uint64_t number = 0;
        uint64_t file_size = 0;
476 477
        if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
            GetVarint64(&input, &file_size) &&
J
jorlow@chromium.org 已提交
478 479
            GetInternalKey(&input, &f.smallest) &&
            GetInternalKey(&input, &f.largest)) {
480
          f.fd = FileDescriptor(number, 0, file_size);
J
jorlow@chromium.org 已提交
481 482
          new_files_.push_back(std::make_pair(level, f));
        } else {
483 484 485
          if (!msg) {
            msg = "new-file entry";
          }
J
jorlow@chromium.org 已提交
486 487
        }
        break;
488 489
      }
      case kNewFile2: {
L
Levi Tamasi 已提交
490 491 492 493
        uint64_t number = 0;
        uint64_t file_size = 0;
        SequenceNumber smallest_seqno = 0;
        SequenceNumber largest_seqno = kMaxSequenceNumber;
494 495
        if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
            GetVarint64(&input, &file_size) &&
496 497
            GetInternalKey(&input, &f.smallest) &&
            GetInternalKey(&input, &f.largest) &&
498 499 500 501
            GetVarint64(&input, &smallest_seqno) &&
            GetVarint64(&input, &largest_seqno)) {
          f.fd = FileDescriptor(number, 0, file_size, smallest_seqno,
                                largest_seqno);
502 503 504 505 506 507 508 509 510 511
          new_files_.push_back(std::make_pair(level, f));
        } else {
          if (!msg) {
            msg = "new-file2 entry";
          }
        }
        break;
      }

      case kNewFile3: {
L
Levi Tamasi 已提交
512 513 514 515 516
        uint64_t number = 0;
        uint32_t path_id = 0;
        uint64_t file_size = 0;
        SequenceNumber smallest_seqno = 0;
        SequenceNumber largest_seqno = kMaxSequenceNumber;
517 518 519 520
        if (GetLevel(&input, &level, &msg) && GetVarint64(&input, &number) &&
            GetVarint32(&input, &path_id) && GetVarint64(&input, &file_size) &&
            GetInternalKey(&input, &f.smallest) &&
            GetInternalKey(&input, &f.largest) &&
521 522 523 524
            GetVarint64(&input, &smallest_seqno) &&
            GetVarint64(&input, &largest_seqno)) {
          f.fd = FileDescriptor(number, path_id, file_size, smallest_seqno,
                                largest_seqno);
525 526 527
          new_files_.push_back(std::make_pair(level, f));
        } else {
          if (!msg) {
528
            msg = "new-file3 entry";
529 530 531
          }
        }
        break;
532
      }
533

534 535 536 537 538
      case kNewFile4: {
        msg = DecodeNewFile4From(&input);
        break;
      }

539 540 541
      case kBlobFileAddition: {
        BlobFileAddition blob_file_addition;
        const Status s = blob_file_addition.DecodeFrom(&input);
542 543 544 545
        if (!s.ok()) {
          return s;
        }

546 547 548 549 550 551 552 553 554 555 556 557
        blob_file_additions_.emplace_back(blob_file_addition);
        break;
      }

      case kBlobFileGarbage: {
        BlobFileGarbage blob_file_garbage;
        const Status s = blob_file_garbage.DecodeFrom(&input);
        if (!s.ok()) {
          return s;
        }

        blob_file_garbages_.emplace_back(blob_file_garbage);
558 559 560
        break;
      }

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
      case kWalAddition: {
        WalAddition wal_addition;
        const Status s = wal_addition.DecodeFrom(&input);
        if (!s.ok()) {
          return s;
        }

        wal_additions_.emplace_back(std::move(wal_addition));
        break;
      }

      case kWalDeletion: {
        WalDeletion wal_deletion;
        const Status s = wal_deletion.DecodeFrom(&input);
        if (!s.ok()) {
          return s;
        }

        wal_deletions_.emplace_back(std::move(wal_deletion));
        break;
      }

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
      case kColumnFamily:
        if (!GetVarint32(&input, &column_family_)) {
          if (!msg) {
            msg = "set column family id";
          }
        }
        break;

      case kColumnFamilyAdd:
        if (GetLengthPrefixedSlice(&input, &str)) {
          is_column_family_add_ = true;
          column_family_name_ = str.ToString();
        } else {
          if (!msg) {
            msg = "column family add";
          }
        }
        break;

      case kColumnFamilyDrop:
        is_column_family_drop_ = true;
        break;

606 607 608 609 610 611 612 613 614
      case kInAtomicGroup:
        is_in_atomic_group_ = true;
        if (!GetVarint32(&input, &remaining_entries_)) {
          if (!msg) {
            msg = "remaining entries";
          }
        }
        break;

J
jorlow@chromium.org 已提交
615
      default:
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
        if (tag & kTagSafeIgnoreMask) {
          // Tag from future which can be safely ignored.
          // The next field must be the length of the entry.
          uint32_t field_len;
          if (!GetVarint32(&input, &field_len) ||
              static_cast<size_t>(field_len) > input.size()) {
            if (!msg) {
              msg = "safely ignoreable tag length error";
            }
          } else {
            input.remove_prefix(static_cast<size_t>(field_len));
          }
        } else {
          msg = "unknown tag";
        }
J
jorlow@chromium.org 已提交
631 632 633 634
        break;
    }
  }

A
Abhishek Kona 已提交
635
  if (msg == nullptr && !input.empty()) {
J
jorlow@chromium.org 已提交
636 637 638 639
    msg = "invalid tag";
  }

  Status result;
A
Abhishek Kona 已提交
640
  if (msg != nullptr) {
J
jorlow@chromium.org 已提交
641 642 643 644 645
    result = Status::Corruption("VersionEdit", msg);
  }
  return result;
}

646
std::string VersionEdit::DebugString(bool hex_key) const {
J
jorlow@chromium.org 已提交
647 648
  std::string r;
  r.append("VersionEdit {");
649 650 651 652
  if (has_db_id_) {
    r.append("\n  DB ID: ");
    r.append(db_id_);
  }
J
jorlow@chromium.org 已提交
653 654 655 656 657 658 659 660
  if (has_comparator_) {
    r.append("\n  Comparator: ");
    r.append(comparator_);
  }
  if (has_log_number_) {
    r.append("\n  LogNumber: ");
    AppendNumberTo(&r, log_number_);
  }
661 662 663 664
  if (has_prev_log_number_) {
    r.append("\n  PrevLogNumber: ");
    AppendNumberTo(&r, prev_log_number_);
  }
J
jorlow@chromium.org 已提交
665
  if (has_next_file_number_) {
666
    r.append("\n  NextFileNumber: ");
J
jorlow@chromium.org 已提交
667 668
    AppendNumberTo(&r, next_file_number_);
  }
L
Levi Tamasi 已提交
669 670 671 672
  if (has_max_column_family_) {
    r.append("\n  MaxColumnFamily: ");
    AppendNumberTo(&r, max_column_family_);
  }
S
Siying Dong 已提交
673 674 675 676
  if (has_min_log_number_to_keep_) {
    r.append("\n  MinLogNumberToKeep: ");
    AppendNumberTo(&r, min_log_number_to_keep_);
  }
J
jorlow@chromium.org 已提交
677 678 679 680
  if (has_last_sequence_) {
    r.append("\n  LastSeq: ");
    AppendNumberTo(&r, last_sequence_);
  }
L
Levi Tamasi 已提交
681
  for (const auto& deleted_file : deleted_files_) {
J
jorlow@chromium.org 已提交
682
    r.append("\n  DeleteFile: ");
L
Levi Tamasi 已提交
683
    AppendNumberTo(&r, deleted_file.first);
J
jorlow@chromium.org 已提交
684
    r.append(" ");
L
Levi Tamasi 已提交
685
    AppendNumberTo(&r, deleted_file.second);
J
jorlow@chromium.org 已提交
686
  }
D
dgrogan@chromium.org 已提交
687
  for (size_t i = 0; i < new_files_.size(); i++) {
J
jorlow@chromium.org 已提交
688 689 690 691
    const FileMetaData& f = new_files_[i].second;
    r.append("\n  AddFile: ");
    AppendNumberTo(&r, new_files_[i].first);
    r.append(" ");
692
    AppendNumberTo(&r, f.fd.GetNumber());
J
jorlow@chromium.org 已提交
693
    r.append(" ");
694
    AppendNumberTo(&r, f.fd.GetFileSize());
G
Gabor Cselle 已提交
695
    r.append(" ");
696
    r.append(f.smallest.DebugString(hex_key));
G
Gabor Cselle 已提交
697
    r.append(" .. ");
698
    r.append(f.largest.DebugString(hex_key));
699 700 701 702
    if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
      r.append(" blob_file:");
      AppendNumberTo(&r, f.oldest_blob_file_number);
    }
703 704
    r.append(" oldest_ancester_time:");
    AppendNumberTo(&r, f.oldest_ancester_time);
705 706
    r.append(" file_creation_time:");
    AppendNumberTo(&r, f.file_creation_time);
707 708 709 710
    r.append(" file_checksum:");
    r.append(f.file_checksum);
    r.append(" file_checksum_func_name: ");
    r.append(f.file_checksum_func_name);
J
jorlow@chromium.org 已提交
711
  }
712

713 714 715 716 717 718 719 720
  for (const auto& blob_file_addition : blob_file_additions_) {
    r.append("\n  BlobFileAddition: ");
    r.append(blob_file_addition.DebugString());
  }

  for (const auto& blob_file_garbage : blob_file_garbages_) {
    r.append("\n  BlobFileGarbage: ");
    r.append(blob_file_garbage.DebugString());
721 722
  }

723 724 725 726 727 728 729 730 731 732
  for (const auto& wal_addition : wal_additions_) {
    r.append("\n  WalAddition: ");
    r.append(wal_addition.DebugString());
  }

  for (const auto& wal_deletion : wal_deletions_) {
    r.append("\n  WalDeletion: ");
    r.append(wal_deletion.DebugString());
  }

733 734 735 736 737 738 739 740 741
  r.append("\n  ColumnFamily: ");
  AppendNumberTo(&r, column_family_);
  if (is_column_family_add_) {
    r.append("\n  ColumnFamilyAdd: ");
    r.append(column_family_name_);
  }
  if (is_column_family_drop_) {
    r.append("\n  ColumnFamilyDrop");
  }
742
  if (is_in_atomic_group_) {
743
    r.append("\n  AtomicGroup: ");
744 745 746
    AppendNumberTo(&r, remaining_entries_);
    r.append(" entries remains");
  }
J
jorlow@chromium.org 已提交
747 748 749 750
  r.append("\n}\n");
  return r;
}

751 752 753 754
std::string VersionEdit::DebugJSON(int edit_num, bool hex_key) const {
  JSONWriter jw;
  jw << "EditNumber" << edit_num;

755 756 757
  if (has_db_id_) {
    jw << "DB ID" << db_id_;
  }
758 759 760 761 762 763 764 765 766 767 768 769
  if (has_comparator_) {
    jw << "Comparator" << comparator_;
  }
  if (has_log_number_) {
    jw << "LogNumber" << log_number_;
  }
  if (has_prev_log_number_) {
    jw << "PrevLogNumber" << prev_log_number_;
  }
  if (has_next_file_number_) {
    jw << "NextFileNumber" << next_file_number_;
  }
L
Levi Tamasi 已提交
770 771 772 773 774 775
  if (has_max_column_family_) {
    jw << "MaxColumnFamily" << max_column_family_;
  }
  if (has_min_log_number_to_keep_) {
    jw << "MinLogNumberToKeep" << min_log_number_to_keep_;
  }
776 777 778 779 780 781 782 783
  if (has_last_sequence_) {
    jw << "LastSeq" << last_sequence_;
  }

  if (!deleted_files_.empty()) {
    jw << "DeletedFiles";
    jw.StartArray();

L
Levi Tamasi 已提交
784
    for (const auto& deleted_file : deleted_files_) {
785
      jw.StartArrayedObject();
L
Levi Tamasi 已提交
786 787
      jw << "Level" << deleted_file.first;
      jw << "FileNumber" << deleted_file.second;
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

  if (!new_files_.empty()) {
    jw << "AddedFiles";
    jw.StartArray();

    for (size_t i = 0; i < new_files_.size(); i++) {
      jw.StartArrayedObject();
      jw << "Level" << new_files_[i].first;
      const FileMetaData& f = new_files_[i].second;
      jw << "FileNumber" << f.fd.GetNumber();
      jw << "FileSize" << f.fd.GetFileSize();
      jw << "SmallestIKey" << f.smallest.DebugString(hex_key);
      jw << "LargestIKey" << f.largest.DebugString(hex_key);
806 807 808
      if (f.oldest_blob_file_number != kInvalidBlobFileNumber) {
        jw << "OldestBlobFile" << f.oldest_blob_file_number;
      }
809 810 811 812 813 814
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
  if (!blob_file_additions_.empty()) {
    jw << "BlobFileAdditions";

    jw.StartArray();

    for (const auto& blob_file_addition : blob_file_additions_) {
      jw.StartArrayedObject();
      jw << blob_file_addition;
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

  if (!blob_file_garbages_.empty()) {
    jw << "BlobFileGarbages";
831 832 833

    jw.StartArray();

834
    for (const auto& blob_file_garbage : blob_file_garbages_) {
835
      jw.StartArrayedObject();
836
      jw << blob_file_garbage;
837 838 839 840 841 842
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
  if (!wal_additions_.empty()) {
    jw << "WalAdditions";

    jw.StartArray();

    for (const auto& wal_addition : wal_additions_) {
      jw.StartArrayedObject();
      jw << wal_addition;
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

  if (!wal_deletions_.empty()) {
    jw << "WalDeletions";

    jw.StartArray();

    for (const auto& wal_deletion : wal_deletions_) {
      jw.StartArrayedObject();
      jw << wal_deletion;
      jw.EndArrayedObject();
    }

    jw.EndArray();
  }

871 872 873 874 875 876 877 878
  jw << "ColumnFamily" << column_family_;

  if (is_column_family_add_) {
    jw << "ColumnFamilyAdd" << column_family_name_;
  }
  if (is_column_family_drop_) {
    jw << "ColumnFamilyDrop" << column_family_name_;
  }
879 880 881
  if (is_in_atomic_group_) {
    jw << "AtomicGroup" << remaining_entries_;
  }
882 883 884 885 886 887

  jw.EndObject();

  return jw.Get();
}

888
}  // namespace ROCKSDB_NAMESPACE