Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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