xref: /leveldb-1.20/db/write_batch.cc (revision f122c6df)
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 
16 #include "leveldb/write_batch.h"
17 
18 #include "leveldb/db.h"
19 #include "db/dbformat.h"
20 #include "db/memtable.h"
21 #include "db/write_batch_internal.h"
22 #include "util/coding.h"
23 
24 namespace leveldb {
25 
26 WriteBatch::WriteBatch() {
27   Clear();
28 }
29 
30 WriteBatch::~WriteBatch() { }
31 
32 WriteBatch::Handler::~Handler() { }
33 
34 void WriteBatch::Clear() {
35   rep_.clear();
36   rep_.resize(12);
37 }
38 
39 Status WriteBatch::Iterate(Handler* handler) const {
40   Slice input(rep_);
41   if (input.size() < 12) {
42     return Status::Corruption("malformed WriteBatch (too small)");
43   }
44 
45   input.remove_prefix(12);
46   Slice key, value;
47   int found = 0;
48   while (!input.empty()) {
49     found++;
50     char tag = input[0];
51     input.remove_prefix(1);
52     switch (tag) {
53       case kTypeValue:
54         if (GetLengthPrefixedSlice(&input, &key) &&
55             GetLengthPrefixedSlice(&input, &value)) {
56           handler->Put(key, value);
57         } else {
58           return Status::Corruption("bad WriteBatch Put");
59         }
60         break;
61       case kTypeDeletion:
62         if (GetLengthPrefixedSlice(&input, &key)) {
63           handler->Delete(key);
64         } else {
65           return Status::Corruption("bad WriteBatch Delete");
66         }
67         break;
68       default:
69         return Status::Corruption("unknown WriteBatch tag");
70     }
71   }
72   if (found != WriteBatchInternal::Count(this)) {
73     return Status::Corruption("WriteBatch has wrong count");
74   } else {
75     return Status::OK();
76   }
77 }
78 
79 int WriteBatchInternal::Count(const WriteBatch* b) {
80   return DecodeFixed32(b->rep_.data() + 8);
81 }
82 
83 void WriteBatchInternal::SetCount(WriteBatch* b, int n) {
84   EncodeFixed32(&b->rep_[8], n);
85 }
86 
87 SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) {
88   return SequenceNumber(DecodeFixed64(b->rep_.data()));
89 }
90 
91 void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) {
92   EncodeFixed64(&b->rep_[0], seq);
93 }
94 
95 void WriteBatch::Put(const Slice& key, const Slice& value) {
96   WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
97   rep_.push_back(static_cast<char>(kTypeValue));
98   PutLengthPrefixedSlice(&rep_, key);
99   PutLengthPrefixedSlice(&rep_, value);
100 }
101 
102 void WriteBatch::Delete(const Slice& key) {
103   WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1);
104   rep_.push_back(static_cast<char>(kTypeDeletion));
105   PutLengthPrefixedSlice(&rep_, key);
106 }
107 
108 namespace {
109 class MemTableInserter : public WriteBatch::Handler {
110  public:
111   SequenceNumber sequence_;
112   MemTable* mem_;
113 
114   virtual void Put(const Slice& key, const Slice& value) {
115     mem_->Add(sequence_, kTypeValue, key, value);
116     sequence_++;
117   }
118   virtual void Delete(const Slice& key) {
119     mem_->Add(sequence_, kTypeDeletion, key, Slice());
120     sequence_++;
121   }
122 };
123 }
124 
125 Status WriteBatchInternal::InsertInto(const WriteBatch* b,
126                                       MemTable* memtable) {
127   MemTableInserter inserter;
128   inserter.sequence_ = WriteBatchInternal::Sequence(b);
129   inserter.mem_ = memtable;
130   return b->Iterate(&inserter);
131 }
132 
133 void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) {
134   assert(contents.size() >= 12);
135   b->rep_.assign(contents.data(), contents.size());
136 }
137 
138 }
139