blob: 23eb00fd4237fad2020041cc1d5deb0112362b5f [file] [log] [blame]
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +00001// 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 |
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000011// kTypeDeletion varstring
12// varstring :=
13// len: varint32
14// data: uint8[len]
15
jorlow@chromium.org4671a692011-03-30 18:35:40 +000016#include "leveldb/write_batch.h"
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000017
jorlow@chromium.org4671a692011-03-30 18:35:40 +000018#include "leveldb/db.h"
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000019#include "db/dbformat.h"
20#include "db/memtable.h"
21#include "db/write_batch_internal.h"
22#include "util/coding.h"
23
24namespace leveldb {
25
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -080026// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
27static const size_t kHeader = 12;
28
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000029WriteBatch::WriteBatch() {
30 Clear();
31}
32
33WriteBatch::~WriteBatch() { }
34
dgrogan@chromium.orgda799092011-05-21 02:17:43 +000035WriteBatch::Handler::~Handler() { }
36
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000037void WriteBatch::Clear() {
38 rep_.clear();
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -080039 rep_.resize(kHeader);
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000040}
41
costanfe449482019-01-15 10:29:55 -080042size_t WriteBatch::ApproximateSize() const {
costan69e2bd22017-05-23 17:29:44 -070043 return rep_.size();
44}
45
dgrogan@chromium.orgda799092011-05-21 02:17:43 +000046Status WriteBatch::Iterate(Handler* handler) const {
47 Slice input(rep_);
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -080048 if (input.size() < kHeader) {
dgrogan@chromium.orgda799092011-05-21 02:17:43 +000049 return Status::Corruption("malformed WriteBatch (too small)");
50 }
51
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -080052 input.remove_prefix(kHeader);
dgrogan@chromium.orgda799092011-05-21 02:17:43 +000053 Slice key, value;
54 int found = 0;
55 while (!input.empty()) {
56 found++;
57 char tag = input[0];
58 input.remove_prefix(1);
59 switch (tag) {
60 case kTypeValue:
61 if (GetLengthPrefixedSlice(&input, &key) &&
62 GetLengthPrefixedSlice(&input, &value)) {
63 handler->Put(key, value);
64 } else {
65 return Status::Corruption("bad WriteBatch Put");
66 }
67 break;
68 case kTypeDeletion:
69 if (GetLengthPrefixedSlice(&input, &key)) {
70 handler->Delete(key);
71 } else {
72 return Status::Corruption("bad WriteBatch Delete");
73 }
74 break;
75 default:
76 return Status::Corruption("unknown WriteBatch tag");
77 }
78 }
79 if (found != WriteBatchInternal::Count(this)) {
80 return Status::Corruption("WriteBatch has wrong count");
81 } else {
82 return Status::OK();
83 }
84}
85
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +000086int WriteBatchInternal::Count(const WriteBatch* b) {
87 return DecodeFixed32(b->rep_.data() + 8);
88}
89
90void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
91 EncodeFixed32(&b->rep_[8], n);
92}
93
94SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
95 return SequenceNumber(DecodeFixed64(b->rep_.data()));
96}
97
98void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
99 EncodeFixed64(&b->rep_[0], seq);
100}
101
102void WriteBatch::Put(const Slice& key, const Slice& value) {
103 WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
104 rep_.push_back(static_cast<char>(kTypeValue));
105 PutLengthPrefixedSlice(&rep_, key);
106 PutLengthPrefixedSlice(&rep_, value);
107}
108
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +0000109void WriteBatch::Delete(const Slice& key) {
110 WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
111 rep_.push_back(static_cast<char>(kTypeDeletion));
112 PutLengthPrefixedSlice(&rep_, key);
113}
114
costanf7b0e1d2018-08-14 15:23:53 -0700115void WriteBatch::Append(const WriteBatch &source) {
116 WriteBatchInternal::Append(this, &source);
117}
118
dgrogan@chromium.orgda799092011-05-21 02:17:43 +0000119namespace {
120class MemTableInserter : public WriteBatch::Handler {
121 public:
122 SequenceNumber sequence_;
123 MemTable* mem_;
124
125 virtual void Put(const Slice& key, const Slice& value) {
126 mem_->Add(sequence_, kTypeValue, key, value);
127 sequence_++;
128 }
129 virtual void Delete(const Slice& key) {
130 mem_->Add(sequence_, kTypeDeletion, key, Slice());
131 sequence_++;
132 }
133};
Hans Wennborg36a5f8e2011-10-31 17:22:06 +0000134} // namespace
dgrogan@chromium.orgda799092011-05-21 02:17:43 +0000135
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +0000136Status WriteBatchInternal::InsertInto(const WriteBatch* b,
137 MemTable* memtable) {
dgrogan@chromium.orgda799092011-05-21 02:17:43 +0000138 MemTableInserter inserter;
139 inserter.sequence_ = WriteBatchInternal::Sequence(b);
140 inserter.mem_ = memtable;
141 return b->Iterate(&inserter);
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +0000142}
143
144void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -0800145 assert(contents.size() >= kHeader);
jorlow@chromium.orgf67e15e2011-03-18 22:37:00 +0000146 b->rep_.assign(contents.data(), contents.size());
147}
148
Sanjay Ghemawatd79762e2012-03-08 16:23:21 -0800149void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
150 SetCount(dst, Count(dst) + Count(src));
151 assert(src->rep_.size() >= kHeader);
152 dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
153}
154
Hans Wennborg36a5f8e2011-10-31 17:22:06 +0000155} // namespace leveldb