| 40 | size_t WriteBatch::ApproximateSize() const { return rep_.size(); } |
| 41 | |
| 42 | Status WriteBatch::Iterate(Handler* handler) const { |
| 43 | Slice input(rep_); |
| 44 | if (input.size() < kHeader) { |
| 45 | return Status::Corruption("malformed WriteBatch (too small)"); |
| 46 | } |
| 47 | |
| 48 | input.remove_prefix(kHeader); |
| 49 | Slice key, value; |
| 50 | int found = 0; |
| 51 | while (!input.empty()) { |
| 52 | found++; |
| 53 | char tag = input[0]; |
| 54 | input.remove_prefix(1); |
| 55 | switch (tag) { |
| 56 | case kTypeValue: |
| 57 | if (GetLengthPrefixedSlice(&input, &key) && |
| 58 | GetLengthPrefixedSlice(&input, &value)) { |
| 59 | handler->Put(key, value); |
| 60 | } else { |
| 61 | return Status::Corruption("bad WriteBatch Put"); |
| 62 | } |
| 63 | break; |
| 64 | case kTypeDeletion: |
| 65 | if (GetLengthPrefixedSlice(&input, &key)) { |
| 66 | handler->Delete(key); |
| 67 | } else { |
| 68 | return Status::Corruption("bad WriteBatch Delete"); |
| 69 | } |
| 70 | break; |
| 71 | default: |
| 72 | return Status::Corruption("unknown WriteBatch tag"); |
| 73 | } |
| 74 | } |
| 75 | if (found != WriteBatchInternal::Count(this)) { |
| 76 | return Status::Corruption("WriteBatch has wrong count"); |
| 77 | } else { |
| 78 | return Status::OK(); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | int WriteBatchInternal::Count(const WriteBatch* b) { |
| 83 | return DecodeFixed32(b->rep_.data() + 8); |