Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
block.cc
Go to the documentation of this file.
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 // Decodes the blocks generated by block_builder.cc.
6 
7 #include "table/block.h"
8 
9 #include <vector>
10 #include <algorithm>
11 #include "leveldb/comparator.h"
12 #include "table/format.h"
13 #include "util/coding.h"
14 #include "util/logging.h"
15 
16 namespace leveldb {
17 
18 inline uint32_t Block::NumRestarts() const {
19  assert(size_ >= sizeof(uint32_t));
20  return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
21 }
22 
23 Block::Block(const BlockContents& contents)
24  : data_(contents.data.data()),
25  size_(contents.data.size()),
26  owned_(contents.heap_allocated) {
27  if (size_ < sizeof(uint32_t)) {
28  size_ = 0; // Error marker
29  } else {
30  size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t);
31  if (NumRestarts() > max_restarts_allowed) {
32  // The size is too small for NumRestarts()
33  size_ = 0;
34  } else {
35  restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
36  }
37  }
38 }
39 
41  if (owned_) {
42  delete[] data_;
43  }
44 }
45 
46 // Helper routine: decode the next block entry starting at "p",
47 // storing the number of shared key bytes, non_shared key bytes,
48 // and the length of the value in "*shared", "*non_shared", and
49 // "*value_length", respectively. Will not derefence past "limit".
50 //
51 // If any errors are detected, returns NULL. Otherwise, returns a
52 // pointer to the key delta (just past the three decoded values).
53 static inline const char* DecodeEntry(const char* p, const char* limit,
55  uint32_t* non_shared,
56  uint32_t* value_length) {
57  if (limit - p < 3) return NULL;
58  *shared = reinterpret_cast<const unsigned char*>(p)[0];
59  *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
60  *value_length = reinterpret_cast<const unsigned char*>(p)[2];
61  if ((*shared | *non_shared | *value_length) < 128) {
62  // Fast path: all three values are encoded in one byte each
63  p += 3;
64  } else {
65  if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL;
66  if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL;
67  if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL;
68  }
69 
70  if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) {
71  return NULL;
72  }
73  return p;
74 }
75 
76 class Block::Iter : public Iterator {
77  private:
78  const Comparator* const comparator_;
79  const char* const data_; // underlying block contents
80  uint32_t const restarts_; // Offset of restart array (list of fixed32)
81  uint32_t const num_restarts_; // Number of uint32_t entries in restart array
82 
83  // current_ is offset in data_ of current entry. >= restarts_ if !Valid
85  uint32_t restart_index_; // Index of restart block in which current_ falls
86  std::string key_;
89 
90  inline int Compare(const Slice& a, const Slice& b) const {
91  return comparator_->Compare(a, b);
92  }
93 
94  // Return the offset in data_ just past the end of the current entry.
95  inline uint32_t NextEntryOffset() const {
96  return (value_.data() + value_.size()) - data_;
97  }
98 
100  assert(index < num_restarts_);
101  return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
102  }
103 
105  key_.clear();
106  restart_index_ = index;
107  // current_ will be fixed by ParseNextKey();
108 
109  // ParseNextKey() starts at the end of value_, so set value_ accordingly
110  uint32_t offset = GetRestartPoint(index);
111  value_ = Slice(data_ + offset, 0);
112  }
113 
114  public:
115  Iter(const Comparator* comparator,
116  const char* data,
117  uint32_t restarts,
118  uint32_t num_restarts)
119  : comparator_(comparator),
120  data_(data),
121  restarts_(restarts),
122  num_restarts_(num_restarts),
123  current_(restarts_),
124  restart_index_(num_restarts_) {
125  assert(num_restarts_ > 0);
126  }
127 
128  virtual bool Valid() const { return current_ < restarts_; }
129  virtual Status status() const { return status_; }
130  virtual Slice key() const {
131  assert(Valid());
132  return key_;
133  }
134  virtual Slice value() const {
135  assert(Valid());
136  return value_;
137  }
138 
139  virtual void Next() {
140  assert(Valid());
141  ParseNextKey();
142  }
143 
144  virtual void Prev() {
145  assert(Valid());
146 
147  // Scan backwards to a restart point before current_
148  const uint32_t original = current_;
149  while (GetRestartPoint(restart_index_) >= original) {
150  if (restart_index_ == 0) {
151  // No more entries
152  current_ = restarts_;
153  restart_index_ = num_restarts_;
154  return;
155  }
156  restart_index_--;
157  }
158 
159  SeekToRestartPoint(restart_index_);
160  do {
161  // Loop until end of current entry hits the start of original entry
162  } while (ParseNextKey() && NextEntryOffset() < original);
163  }
164 
165  virtual void Seek(const Slice& target) {
166  // Binary search in restart array to find the last restart point
167  // with a key < target
168  uint32_t left = 0;
169  uint32_t right = num_restarts_ - 1;
170  while (left < right) {
171  uint32_t mid = (left + right + 1) / 2;
172  uint32_t region_offset = GetRestartPoint(mid);
173  uint32_t shared, non_shared, value_length;
174  const char* key_ptr = DecodeEntry(data_ + region_offset,
175  data_ + restarts_,
176  &shared, &non_shared, &value_length);
177  if (key_ptr == NULL || (shared != 0)) {
178  CorruptionError();
179  return;
180  }
181  Slice mid_key(key_ptr, non_shared);
182  if (Compare(mid_key, target) < 0) {
183  // Key at "mid" is smaller than "target". Therefore all
184  // blocks before "mid" are uninteresting.
185  left = mid;
186  } else {
187  // Key at "mid" is >= "target". Therefore all blocks at or
188  // after "mid" are uninteresting.
189  right = mid - 1;
190  }
191  }
192 
193  // Linear search (within restart block) for first key >= target
194  SeekToRestartPoint(left);
195  while (true) {
196  if (!ParseNextKey()) {
197  return;
198  }
199  if (Compare(key_, target) >= 0) {
200  return;
201  }
202  }
203  }
204 
205  virtual void SeekToFirst() {
207  ParseNextKey();
208  }
209 
210  virtual void SeekToLast() {
211  SeekToRestartPoint(num_restarts_ - 1);
212  while (ParseNextKey() && NextEntryOffset() < restarts_) {
213  // Keep skipping
214  }
215  }
216 
217  private:
219  current_ = restarts_;
220  restart_index_ = num_restarts_;
221  status_ = Status::Corruption("bad entry in block");
222  key_.clear();
223  value_.clear();
224  }
225 
226  bool ParseNextKey() {
227  current_ = NextEntryOffset();
228  const char* p = data_ + current_;
229  const char* limit = data_ + restarts_; // Restarts come right after data
230  if (p >= limit) {
231  // No more entries to return. Mark as invalid.
232  current_ = restarts_;
233  restart_index_ = num_restarts_;
234  return false;
235  }
236 
237  // Decode next entry
238  uint32_t shared, non_shared, value_length;
239  p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
240  if (p == NULL || key_.size() < shared) {
241  CorruptionError();
242  return false;
243  } else {
244  key_.resize(shared);
245  key_.append(p, non_shared);
246  value_ = Slice(p + non_shared, value_length);
247  while (restart_index_ + 1 < num_restarts_ &&
248  GetRestartPoint(restart_index_ + 1) < current_) {
249  ++restart_index_;
250  }
251  return true;
252  }
253  }
254 };
255 
257  if (size_ < sizeof(uint32_t)) {
258  return NewErrorIterator(Status::Corruption("bad block contents"));
259  }
260  const uint32_t num_restarts = NumRestarts();
261  if (num_restarts == 0) {
262  return NewEmptyIterator();
263  } else {
264  return new Iter(cmp, data_, restart_offset_, num_restarts);
265  }
266 }
267 
268 } // namespace leveldb
const char *const data_
Definition: block.cc:79
bool ParseNextKey()
Definition: block.cc:226
uint32_t restart_index_
Definition: block.cc:85
uint32_t const restarts_
Definition: block.cc:80
Iter(const Comparator *comparator, const char *data, uint32_t restarts, uint32_t num_restarts)
Definition: block.cc:115
const char * data() const
Definition: slice.h:40
const char * GetVarint32Ptr(const char *p, const char *limit, uint32_t *v)
Definition: coding.h:89
SharedState * shared
Definition: db_bench.cc:292
const Comparator *const comparator_
Definition: block.cc:78
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
virtual void Seek(const Slice &target)
Definition: block.cc:165
Block(const BlockContents &contents)
Definition: block.cc:23
uint32_t DecodeFixed32(const char *ptr)
Definition: coding.h:58
void clear()
Definition: slice.h:56
size_t size_
Definition: block.h:31
virtual Slice key() const
Definition: block.cc:130
virtual Status status() const
Definition: block.cc:129
Iterator * NewIterator(const Comparator *comparator)
Definition: block.cc:256
virtual void SeekToFirst()
Definition: block.cc:205
uint64_t size_
Definition: memenv.cc:143
const char * data_
Definition: block.h:30
virtual void Prev()
Definition: block.cc:144
unsigned int uint32_t
Definition: stdint.h:21
uint32_t current_
Definition: block.cc:84
bool owned_
Definition: block.h:33
size_t size() const
Definition: slice.h:43
Iterator * NewErrorIterator(const Status &status)
Definition: iterator.cc:63
Iterator * NewEmptyIterator()
Definition: iterator.cc:59
void SeekToRestartPoint(uint32_t index)
Definition: block.cc:104
virtual bool Valid() const
Definition: block.cc:128
uint32_t restart_offset_
Definition: block.h:32
virtual int Compare(const Slice &a, const Slice &b) const =0
const Comparator * cmp
Definition: table_test.cc:80
int Compare(const Slice &a, const Slice &b) const
Definition: block.cc:90
virtual Slice value() const
Definition: block.cc:134
uint32_t NumRestarts() const
Definition: block.cc:18
std::string data_
Definition: db_bench.cc:112
uint32_t const num_restarts_
Definition: block.cc:81
uint32_t GetRestartPoint(uint32_t index)
Definition: block.cc:99
void CorruptionError()
Definition: block.cc:218
std::string key_
Definition: block.cc:86
virtual void SeekToLast()
Definition: block.cc:210
virtual void Next()
Definition: block.cc:139
uint32_t NextEntryOffset() const
Definition: block.cc:95