小组成员:姚凯文(kevinyao0901),姜嘉琪
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.7 KiB

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