10225501448 李度 10225101546 陈胤遒 10215501422 高宇菲
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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