作者: 韩晨旭 10225101440 李畅 10225102463
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.6 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. //
  5. // WriteBatch::rep_ :=
  6. // sequence: fixed64
  7. // count: fixed32
  8. // data: record[count]
  9. // record :=
  10. // kTypeValue varstring varstring |
  11. // kTypeDeletion varstring
  12. // varstring :=
  13. // len: varint32
  14. // data: uint8[len]
  15. #include "leveldb/write_batch.h"
  16. #include "leveldb/db.h"
  17. #include "db/dbformat.h"
  18. #include "db/memtable.h"
  19. #include "db/write_batch_internal.h"
  20. #include "util/coding.h"
  21. namespace leveldb {
  22. WriteBatch::WriteBatch() {
  23. Clear();
  24. }
  25. WriteBatch::~WriteBatch() { }
  26. WriteBatch::Handler::~Handler() { }
  27. void WriteBatch::Clear() {
  28. rep_.clear();
  29. rep_.resize(12);
  30. }
  31. Status WriteBatch::Iterate(Handler* handler) const {
  32. Slice input(rep_);
  33. if (input.size() < 12) {
  34. return Status::Corruption("malformed WriteBatch (too small)");
  35. }
  36. input.remove_prefix(12);
  37. Slice key, value;
  38. int found = 0;
  39. while (!input.empty()) {
  40. found++;
  41. char tag = input[0];
  42. input.remove_prefix(1);
  43. switch (tag) {
  44. case kTypeValue:
  45. if (GetLengthPrefixedSlice(&input, &key) &&
  46. GetLengthPrefixedSlice(&input, &value)) {
  47. handler->Put(key, value);
  48. } else {
  49. return Status::Corruption("bad WriteBatch Put");
  50. }
  51. break;
  52. case kTypeDeletion:
  53. if (GetLengthPrefixedSlice(&input, &key)) {
  54. handler->Delete(key);
  55. } else {
  56. return Status::Corruption("bad WriteBatch Delete");
  57. }
  58. break;
  59. default:
  60. return Status::Corruption("unknown WriteBatch tag");
  61. }
  62. }
  63. if (found != WriteBatchInternal::Count(this)) {
  64. return Status::Corruption("WriteBatch has wrong count");
  65. } else {
  66. return Status::OK();
  67. }
  68. }
  69. int WriteBatchInternal::Count(const WriteBatch* b) {
  70. return DecodeFixed32(b->rep_.data() + 8);
  71. }
  72. void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
  73. EncodeFixed32(&b->rep_[8], n);
  74. }
  75. SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
  76. return SequenceNumber(DecodeFixed64(b->rep_.data()));
  77. }
  78. void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
  79. EncodeFixed64(&b->rep_[0], seq);
  80. }
  81. void WriteBatch::Put(const Slice& key, const Slice& value) {
  82. WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  83. rep_.push_back(static_cast<char>(kTypeValue));
  84. PutLengthPrefixedSlice(&rep_, key);
  85. PutLengthPrefixedSlice(&rep_, value);
  86. }
  87. void WriteBatch::Delete(const Slice& key) {
  88. WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  89. rep_.push_back(static_cast<char>(kTypeDeletion));
  90. PutLengthPrefixedSlice(&rep_, key);
  91. }
  92. namespace {
  93. class MemTableInserter : public WriteBatch::Handler {
  94. public:
  95. SequenceNumber sequence_;
  96. MemTable* mem_;
  97. virtual void Put(const Slice& key, const Slice& value) {
  98. mem_->Add(sequence_, kTypeValue, key, value);
  99. sequence_++;
  100. }
  101. virtual void Delete(const Slice& key) {
  102. mem_->Add(sequence_, kTypeDeletion, key, Slice());
  103. sequence_++;
  104. }
  105. };
  106. } // namespace
  107. Status WriteBatchInternal::InsertInto(const WriteBatch* b,
  108. MemTable* memtable) {
  109. MemTableInserter inserter;
  110. inserter.sequence_ = WriteBatchInternal::Sequence(b);
  111. inserter.mem_ = memtable;
  112. return b->Iterate(&inserter);
  113. }
  114. void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
  115. assert(contents.size() >= 12);
  116. b->rep_.assign(contents.data(), contents.size());
  117. }
  118. } // namespace leveldb