Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
db_iter.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 #include "db/db_iter.h"
6 
7 #include "db/filename.h"
8 #include "db/db_impl.h"
9 #include "db/dbformat.h"
10 #include "leveldb/env.h"
11 #include "leveldb/iterator.h"
12 #include "port/port.h"
13 #include "util/logging.h"
14 #include "util/mutexlock.h"
15 #include "util/random.h"
16 
17 namespace leveldb {
18 
19 #if 0
20 static void DumpInternalIter(Iterator* iter) {
21  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
22  ParsedInternalKey k;
23  if (!ParseInternalKey(iter->key(), &k)) {
24  fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
25  } else {
26  fprintf(stderr, "@ '%s'\n", k.DebugString().c_str());
27  }
28  }
29 }
30 #endif
31 
32 namespace {
33 
34 // Memtables and sstables that make the DB representation contain
35 // (userkey,seq,type) => uservalue entries. DBIter
36 // combines multiple entries for the same userkey found in the DB
37 // representation into a single entry while accounting for sequence
38 // numbers, deletion markers, overwrites, etc.
39 class DBIter: public Iterator {
40  public:
41  // Which direction is the iterator currently moving?
42  // (1) When moving forward, the internal iterator is positioned at
43  // the exact entry that yields this->key(), this->value()
44  // (2) When moving backwards, the internal iterator is positioned
45  // just before all entries whose user key == this->key().
46  enum Direction {
47  kForward,
48  kReverse
49  };
50 
51  DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
52  uint32_t seed)
53  : db_(db),
54  user_comparator_(cmp),
55  iter_(iter),
56  sequence_(s),
57  direction_(kForward),
58  valid_(false),
59  rnd_(seed),
60  bytes_counter_(RandomPeriod()) {
61  }
62  virtual ~DBIter() {
63  delete iter_;
64  }
65  virtual bool Valid() const { return valid_; }
66  virtual Slice key() const {
67  assert(valid_);
68  return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
69  }
70  virtual Slice value() const {
71  assert(valid_);
72  return (direction_ == kForward) ? iter_->value() : saved_value_;
73  }
74  virtual Status status() const {
75  if (status_.ok()) {
76  return iter_->status();
77  } else {
78  return status_;
79  }
80  }
81 
82  virtual void Next();
83  virtual void Prev();
84  virtual void Seek(const Slice& target);
85  virtual void SeekToFirst();
86  virtual void SeekToLast();
87 
88  private:
89  void FindNextUserEntry(bool skipping, std::string* skip);
90  void FindPrevUserEntry();
91  bool ParseKey(ParsedInternalKey* key);
92 
93  inline void SaveKey(const Slice& k, std::string* dst) {
94  dst->assign(k.data(), k.size());
95  }
96 
97  inline void ClearSavedValue() {
98  if (saved_value_.capacity() > 1048576) {
99  std::string empty;
100  swap(empty, saved_value_);
101  } else {
102  saved_value_.clear();
103  }
104  }
105 
106  // Pick next gap with average value of config::kReadBytesPeriod.
107  ssize_t RandomPeriod() {
108  return rnd_.Uniform(2*config::kReadBytesPeriod);
109  }
110 
111  DBImpl* db_;
112  const Comparator* const user_comparator_;
113  Iterator* const iter_;
115 
116  Status status_;
117  std::string saved_key_; // == current key when direction_==kReverse
118  std::string saved_value_; // == current raw value when direction_==kReverse
119  Direction direction_;
120  bool valid_;
121 
122  Random rnd_;
123  ssize_t bytes_counter_;
124 
125  // No copying allowed
126  DBIter(const DBIter&);
127  void operator=(const DBIter&);
128 };
129 
130 inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
131  Slice k = iter_->key();
132  ssize_t n = k.size() + iter_->value().size();
133  bytes_counter_ -= n;
134  while (bytes_counter_ < 0) {
135  bytes_counter_ += RandomPeriod();
136  db_->RecordReadSample(k);
137  }
138  if (!ParseInternalKey(k, ikey)) {
139  status_ = Status::Corruption("corrupted internal key in DBIter");
140  return false;
141  } else {
142  return true;
143  }
144 }
145 
146 void DBIter::Next() {
147  assert(valid_);
148 
149  if (direction_ == kReverse) { // Switch directions?
150  direction_ = kForward;
151  // iter_ is pointing just before the entries for this->key(),
152  // so advance into the range of entries for this->key() and then
153  // use the normal skipping code below.
154  if (!iter_->Valid()) {
155  iter_->SeekToFirst();
156  } else {
157  iter_->Next();
158  }
159  if (!iter_->Valid()) {
160  valid_ = false;
161  saved_key_.clear();
162  return;
163  }
164  }
165 
166  // Temporarily use saved_key_ as storage for key to skip.
167  std::string* skip = &saved_key_;
168  SaveKey(ExtractUserKey(iter_->key()), skip);
169  FindNextUserEntry(true, skip);
170 }
171 
172 void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
173  // Loop until we hit an acceptable entry to yield
174  assert(iter_->Valid());
175  assert(direction_ == kForward);
176  do {
177  ParsedInternalKey ikey;
178  if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
179  switch (ikey.type) {
180  case kTypeDeletion:
181  // Arrange to skip all upcoming entries for this key since
182  // they are hidden by this deletion.
183  SaveKey(ikey.user_key, skip);
184  skipping = true;
185  break;
186  case kTypeValue:
187  if (skipping &&
188  user_comparator_->Compare(ikey.user_key, *skip) <= 0) {
189  // Entry hidden
190  } else {
191  valid_ = true;
192  saved_key_.clear();
193  return;
194  }
195  break;
196  }
197  }
198  iter_->Next();
199  } while (iter_->Valid());
200  saved_key_.clear();
201  valid_ = false;
202 }
203 
204 void DBIter::Prev() {
205  assert(valid_);
206 
207  if (direction_ == kForward) { // Switch directions?
208  // iter_ is pointing at the current entry. Scan backwards until
209  // the key changes so we can use the normal reverse scanning code.
210  assert(iter_->Valid()); // Otherwise valid_ would have been false
211  SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
212  while (true) {
213  iter_->Prev();
214  if (!iter_->Valid()) {
215  valid_ = false;
216  saved_key_.clear();
217  ClearSavedValue();
218  return;
219  }
221  saved_key_) < 0) {
222  break;
223  }
224  }
225  direction_ = kReverse;
226  }
227 
228  FindPrevUserEntry();
229 }
230 
231 void DBIter::FindPrevUserEntry() {
232  assert(direction_ == kReverse);
233 
234  ValueType value_type = kTypeDeletion;
235  if (iter_->Valid()) {
236  do {
237  ParsedInternalKey ikey;
238  if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
239  if ((value_type != kTypeDeletion) &&
240  user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {
241  // We encountered a non-deleted value in entries for previous keys,
242  break;
243  }
244  value_type = ikey.type;
245  if (value_type == kTypeDeletion) {
246  saved_key_.clear();
247  ClearSavedValue();
248  } else {
249  Slice raw_value = iter_->value();
250  if (saved_value_.capacity() > raw_value.size() + 1048576) {
251  std::string empty;
252  swap(empty, saved_value_);
253  }
254  SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
255  saved_value_.assign(raw_value.data(), raw_value.size());
256  }
257  }
258  iter_->Prev();
259  } while (iter_->Valid());
260  }
261 
262  if (value_type == kTypeDeletion) {
263  // End
264  valid_ = false;
265  saved_key_.clear();
266  ClearSavedValue();
267  direction_ = kForward;
268  } else {
269  valid_ = true;
270  }
271 }
272 
273 void DBIter::Seek(const Slice& target) {
274  direction_ = kForward;
275  ClearSavedValue();
276  saved_key_.clear();
278  &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek));
280  if (iter_->Valid()) {
281  FindNextUserEntry(false, &saved_key_ /* temporary storage */);
282  } else {
283  valid_ = false;
284  }
285 }
286 
287 void DBIter::SeekToFirst() {
288  direction_ = kForward;
289  ClearSavedValue();
290  iter_->SeekToFirst();
291  if (iter_->Valid()) {
292  FindNextUserEntry(false, &saved_key_ /* temporary storage */);
293  } else {
294  valid_ = false;
295  }
296 }
297 
298 void DBIter::SeekToLast() {
299  direction_ = kReverse;
300  ClearSavedValue();
301  iter_->SeekToLast();
302  FindPrevUserEntry();
303 }
304 
305 } // anonymous namespace
306 
308  DBImpl* db,
309  const Comparator* user_key_comparator,
310  Iterator* internal_iter,
311  SequenceNumber sequence,
312  uint32_t seed) {
313  return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
314 }
315 
316 } // namespace leveldb
std::string saved_key_
Definition: db_iter.cc:117
Direction direction_
Definition: db_iter.cc:119
virtual void Prev()=0
std::string * value
Definition: version_set.cc:270
Iterator *const iter_
Definition: db_iter.cc:113
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
bool valid_
Definition: db_iter.cc:120
ValueType
Definition: dbformat.h:51
DBImpl * db_
Definition: db_iter.cc:111
Iterator * NewDBIterator(DBImpl *db, const Comparator *user_key_comparator, Iterator *internal_iter, SequenceNumber sequence, uint32_t seed)
Definition: db_iter.cc:307
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Definition: dbformat.h:176
void AppendInternalKey(std::string *result, const ParsedInternalKey &key)
Definition: dbformat.cc:18
virtual Slice value() const =0
virtual void Next()=0
uint64_t SequenceNumber
Definition: dbformat.h:63
virtual void SeekToLast()=0
SequenceNumber const sequence_
Definition: db_iter.cc:114
unsigned int uint32_t
Definition: stdint.h:21
size_t size() const
Definition: slice.h:43
virtual void Seek(const Slice &target)=0
std::string EscapeString(const Slice &value)
Definition: logging.cc:42
virtual void SeekToFirst()=0
std::string saved_value_
Definition: db_iter.cc:118
Status status_
Definition: db_iter.cc:116
virtual int Compare(const Slice &a, const Slice &b) const =0
virtual bool Valid() const =0
const Comparator * cmp
Definition: table_test.cc:80
Slice ExtractUserKey(const Slice &internal_key)
Definition: dbformat.h:98
Random rnd_
Definition: db_iter.cc:122
virtual Slice key() const =0
const Comparator *const user_comparator_
Definition: db_iter.cc:112
void RecordReadSample(Slice key)
Definition: db_impl.cc:1131
ssize_t bytes_counter_
Definition: db_iter.cc:123