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.

148 lines
3.7 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. void WriteBatch::Clear() {
  27. rep_.clear();
  28. rep_.resize(12);
  29. }
  30. int WriteBatchInternal::Count(const WriteBatch* b) {
  31. return DecodeFixed32(b->rep_.data() + 8);
  32. }
  33. void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
  34. EncodeFixed32(&b->rep_[8], n);
  35. }
  36. SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
  37. return SequenceNumber(DecodeFixed64(b->rep_.data()));
  38. }
  39. void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
  40. EncodeFixed64(&b->rep_[0], seq);
  41. }
  42. void WriteBatch::Put(const Slice& key, const Slice& value) {
  43. WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  44. rep_.push_back(static_cast<char>(kTypeValue));
  45. PutLengthPrefixedSlice(&rep_, key);
  46. PutLengthPrefixedSlice(&rep_, value);
  47. }
  48. void WriteBatch::Delete(const Slice& key) {
  49. WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
  50. rep_.push_back(static_cast<char>(kTypeDeletion));
  51. PutLengthPrefixedSlice(&rep_, key);
  52. }
  53. Status WriteBatchInternal::InsertInto(const WriteBatch* b,
  54. MemTable* memtable) {
  55. const int count = WriteBatchInternal::Count(b);
  56. int found = 0;
  57. Iterator it(*b);
  58. for (; !it.Done(); it.Next()) {
  59. switch (it.op()) {
  60. case kTypeDeletion:
  61. memtable->Add(it.sequence_number(), kTypeDeletion, it.key(), Slice());
  62. break;
  63. case kTypeValue:
  64. memtable->Add(it.sequence_number(), kTypeValue, it.key(), it.value());
  65. break;
  66. }
  67. found++;
  68. }
  69. if (!it.status().ok()) {
  70. return it.status();
  71. } else if (found != count) {
  72. return Status::Corruption("wrong count in WriteBatch");
  73. }
  74. return Status::OK();
  75. }
  76. void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
  77. assert(contents.size() >= 12);
  78. b->rep_.assign(contents.data(), contents.size());
  79. }
  80. WriteBatchInternal::Iterator::Iterator(const WriteBatch& batch)
  81. : input_(WriteBatchInternal::Contents(&batch)),
  82. done_(false) {
  83. if (input_.size() < 12) {
  84. done_ = true;
  85. } else {
  86. seq_ = WriteBatchInternal::Sequence(&batch),
  87. input_.remove_prefix(12);
  88. GetNextEntry();
  89. }
  90. }
  91. void WriteBatchInternal::Iterator::Next() {
  92. assert(!done_);
  93. seq_++;
  94. GetNextEntry();
  95. }
  96. void WriteBatchInternal::Iterator::GetNextEntry() {
  97. if (input_.empty()) {
  98. done_ = true;
  99. return;
  100. }
  101. char tag = input_[0];
  102. input_.remove_prefix(1);
  103. switch (tag) {
  104. case kTypeValue:
  105. if (GetLengthPrefixedSlice(&input_, &key_) &&
  106. GetLengthPrefixedSlice(&input_, &value_)) {
  107. op_ = static_cast<ValueType>(tag);
  108. } else {
  109. status_ = Status::Corruption("bad WriteBatch Put");
  110. done_ = true;
  111. input_.clear();
  112. }
  113. break;
  114. case kTypeDeletion:
  115. if (GetLengthPrefixedSlice(&input_, &key_)) {
  116. op_ = kTypeDeletion;
  117. } else {
  118. status_ = Status::Corruption("bad WriteBatch Delete");
  119. done_ = true;
  120. input_.clear();
  121. }
  122. break;
  123. default:
  124. status_ = Status::Corruption("unknown WriteBatch tag");
  125. done_ = true;
  126. input_.clear();
  127. break;
  128. }
  129. }
  130. }