1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be 3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors. 4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// 5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// WriteBatch::rep_ := 6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// sequence: fixed64 7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// count: fixed32 8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// data: record[count] 9179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// record := 10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// kTypeValue varstring varstring | 11179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// kTypeDeletion varstring 12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// varstring := 13179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// len: varint32 14179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// data: uint8[len] 15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 16fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/write_batch.h" 17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 18fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/db.h" 19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/dbformat.h" 20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/memtable.h" 21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/write_batch_internal.h" 22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/coding.h" 23179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 24179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb { 25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 2613daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. 2713daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.comstatic const size_t kHeader = 12; 2813daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com 29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgWriteBatch::WriteBatch() { 30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Clear(); 31179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgWriteBatch::~WriteBatch() { } 34179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 35a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgWriteBatch::Handler::~Handler() { } 36a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 37179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatch::Clear() { 38179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org rep_.clear(); 3913daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com rep_.resize(kHeader); 40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 42a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgStatus WriteBatch::Iterate(Handler* handler) const { 43a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org Slice input(rep_); 4413daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com if (input.size() < kHeader) { 45a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::Corruption("malformed WriteBatch (too small)"); 46a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 47a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 4813daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com input.remove_prefix(kHeader); 49a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org Slice key, value; 50a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org int found = 0; 51a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org while (!input.empty()) { 52a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org found++; 53a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org char tag = input[0]; 54a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org input.remove_prefix(1); 55a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org switch (tag) { 56a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org case kTypeValue: 57a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org if (GetLengthPrefixedSlice(&input, &key) && 58a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org GetLengthPrefixedSlice(&input, &value)) { 59a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org handler->Put(key, value); 60a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } else { 61a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::Corruption("bad WriteBatch Put"); 62a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 63a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org break; 64a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org case kTypeDeletion: 65a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org if (GetLengthPrefixedSlice(&input, &key)) { 66a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org handler->Delete(key); 67a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } else { 68a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::Corruption("bad WriteBatch Delete"); 69a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 70a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org break; 71a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org default: 72a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::Corruption("unknown WriteBatch tag"); 73a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 74a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 75a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org if (found != WriteBatchInternal::Count(this)) { 76a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::Corruption("WriteBatch has wrong count"); 77a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } else { 78a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::OK(); 79a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 80a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org} 81a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 82179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgint WriteBatchInternal::Count(const WriteBatch* b) { 83179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return DecodeFixed32(b->rep_.data() + 8); 84179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 85179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 86179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatchInternal::SetCount(WriteBatch* b, int n) { 87179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org EncodeFixed32(&b->rep_[8], n); 88179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 89179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 90179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgSequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { 91179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return SequenceNumber(DecodeFixed64(b->rep_.data())); 92179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 93179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 94179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { 95179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org EncodeFixed64(&b->rep_[0], seq); 96179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 97179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 98179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatch::Put(const Slice& key, const Slice& value) { 99179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); 100179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org rep_.push_back(static_cast<char>(kTypeValue)); 101179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PutLengthPrefixedSlice(&rep_, key); 102179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PutLengthPrefixedSlice(&rep_, value); 103179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 104179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 105179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatch::Delete(const Slice& key) { 106179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); 107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org rep_.push_back(static_cast<char>(kTypeDeletion)); 108179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PutLengthPrefixedSlice(&rep_, key); 109179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 110179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 111a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgnamespace { 112a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgclass MemTableInserter : public WriteBatch::Handler { 113a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org public: 114a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org SequenceNumber sequence_; 115a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org MemTable* mem_; 116a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 117a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org virtual void Put(const Slice& key, const Slice& value) { 118a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org mem_->Add(sequence_, kTypeValue, key, value); 119a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org sequence_++; 120179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 121a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org virtual void Delete(const Slice& key) { 122a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org mem_->Add(sequence_, kTypeDeletion, key, Slice()); 123a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org sequence_++; 124179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 125a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org}; 12645b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace 127a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 128a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgStatus WriteBatchInternal::InsertInto(const WriteBatch* b, 129a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org MemTable* memtable) { 130a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org MemTableInserter inserter; 131a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org inserter.sequence_ = WriteBatchInternal::Sequence(b); 132a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org inserter.mem_ = memtable; 133a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return b->Iterate(&inserter); 134179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 135179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 136179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { 13713daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com assert(contents.size() >= kHeader); 138179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org b->rep_.assign(contents.data(), contents.size()); 139179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 140179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 14113daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.comvoid WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { 14213daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com SetCount(dst, Count(dst) + Count(src)); 14313daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com assert(src->rep_.size() >= kHeader); 14413daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); 14513daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com} 14613daa9f29c999ee40a257ee0775abee2c78a0ad9sanjay@google.com 14745b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace leveldb 148