作者: 韩晨旭 10225101440 李畅 10225102463
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
11 KiB

Release 1.18 Changes are: * Update version number to 1.18 * Replace the basic fprintf call with a call to fwrite in order to work around the apparent compiler optimization/rewrite failure that we are seeing with the new toolchain/iOS SDKs provided with Xcode6 and iOS8. * Fix ALL the header guards. * Createed a README.md with the LevelDB project description. * A new CONTRIBUTING file. * Don't implicitly convert uint64_t to size_t or int. Either preserve it as uint64_t, or explicitly cast. This fixes MSVC warnings about possible value truncation when compiling this code in Chromium. * Added a DumpFile() library function that encapsulates the guts of the "leveldbutil dump" command. This will allow clients to dump data to their log files instead of stdout. It will also allow clients to supply their own environment. * leveldb: Remove unused function 'ConsumeChar'. * leveldbutil: Remove unused member variables from WriteBatchItemPrinter. * OpenBSD, NetBSD and DragonflyBSD have _LITTLE_ENDIAN, so define PLATFORM_IS_LITTLE_ENDIAN like on FreeBSD. This fixes: * issue #143 * issue #198 * issue #249 * Switch from <cstdatomic> to <atomic>. The former never made it into the standard and doesn't exist in modern gcc versions at all. The later contains everything that leveldb was using from the former. This problem was noticed when porting to Portable Native Client where no memory barrier is defined. The fact that <cstdatomic> is missing normally goes unnoticed since memory barriers are defined for most architectures. * Make Hash() treat its input as unsigned. Before this change LevelDB files from platforms with different signedness of char were not compatible. This change fixes: issue #243 * Verify checksums of index/meta/filter blocks when paranoid_checks set. * Invoke all tools for iOS with xcrun. (This was causing problems with the new XCode 5.1.1 image on pulse.) * include <sys/stat.h> only once, and fix the following linter warning: "Found C system header after C++ system header" * When encountering a corrupted table file, return Status::Corruption instead of Status::InvalidArgument. * Support cygwin as build platform, patch is from https://code.google.com/p/leveldb/issues/detail?id=188 * Fix typo, merge patch from https://code.google.com/p/leveldb/issues/detail?id=159 * Fix typos and comments, and address the following two issues: * issue #166 * issue #241 * Add missing db synchronize after "fillseq" in the benchmark. * Removed unused variable in SeekRandom: value (issue #201)
10 years ago
Release 1.18 Changes are: * Update version number to 1.18 * Replace the basic fprintf call with a call to fwrite in order to work around the apparent compiler optimization/rewrite failure that we are seeing with the new toolchain/iOS SDKs provided with Xcode6 and iOS8. * Fix ALL the header guards. * Createed a README.md with the LevelDB project description. * A new CONTRIBUTING file. * Don't implicitly convert uint64_t to size_t or int. Either preserve it as uint64_t, or explicitly cast. This fixes MSVC warnings about possible value truncation when compiling this code in Chromium. * Added a DumpFile() library function that encapsulates the guts of the "leveldbutil dump" command. This will allow clients to dump data to their log files instead of stdout. It will also allow clients to supply their own environment. * leveldb: Remove unused function 'ConsumeChar'. * leveldbutil: Remove unused member variables from WriteBatchItemPrinter. * OpenBSD, NetBSD and DragonflyBSD have _LITTLE_ENDIAN, so define PLATFORM_IS_LITTLE_ENDIAN like on FreeBSD. This fixes: * issue #143 * issue #198 * issue #249 * Switch from <cstdatomic> to <atomic>. The former never made it into the standard and doesn't exist in modern gcc versions at all. The later contains everything that leveldb was using from the former. This problem was noticed when porting to Portable Native Client where no memory barrier is defined. The fact that <cstdatomic> is missing normally goes unnoticed since memory barriers are defined for most architectures. * Make Hash() treat its input as unsigned. Before this change LevelDB files from platforms with different signedness of char were not compatible. This change fixes: issue #243 * Verify checksums of index/meta/filter blocks when paranoid_checks set. * Invoke all tools for iOS with xcrun. (This was causing problems with the new XCode 5.1.1 image on pulse.) * include <sys/stat.h> only once, and fix the following linter warning: "Found C system header after C++ system header" * When encountering a corrupted table file, return Status::Corruption instead of Status::InvalidArgument. * Support cygwin as build platform, patch is from https://code.google.com/p/leveldb/issues/detail?id=188 * Fix typo, merge patch from https://code.google.com/p/leveldb/issues/detail?id=159 * Fix typos and comments, and address the following two issues: * issue #166 * issue #241 * Add missing db synchronize after "fillseq" in the benchmark. * Removed unused variable in SeekRandom: value (issue #201)
10 years ago
  1. #ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_
  2. #define STORAGE_LEVELDB_DB_SKIPLIST_H_
  3. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  4. // Use of this source code is governed by a BSD-style license that can be
  5. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  6. //
  7. // Thread safety
  8. // -------------
  9. //
  10. // Writes require external synchronization, most likely a mutex.
  11. // Reads require a guarantee that the SkipList will not be destroyed
  12. // while the read is in progress. Apart from that, reads progress
  13. // without any internal locking or synchronization.
  14. //
  15. // Invariants:
  16. //
  17. // (1) Allocated nodes are never deleted until the SkipList is
  18. // destroyed. This is trivially guaranteed by the code since we
  19. // never delete any skip list nodes.
  20. //
  21. // (2) The contents of a Node except for the next/prev pointers are
  22. // immutable after the Node has been linked into the SkipList.
  23. // Only Insert() modifies the list, and it is careful to initialize
  24. // a node and use release-stores to publish the nodes in one or
  25. // more lists.
  26. //
  27. // ... prev vs. next pointer ordering ...
  28. #include <assert.h>
  29. #include <stdlib.h>
  30. #include "port/port.h"
  31. #include "util/arena.h"
  32. #include "util/random.h"
  33. namespace leveldb {
  34. class Arena;
  35. template<typename Key, class Comparator>
  36. class SkipList {
  37. private:
  38. struct Node;
  39. public:
  40. // Create a new SkipList object that will use "cmp" for comparing keys,
  41. // and will allocate memory using "*arena". Objects allocated in the arena
  42. // must remain allocated for the lifetime of the skiplist object.
  43. explicit SkipList(Comparator cmp, Arena* arena);
  44. // Insert key into the list.
  45. // REQUIRES: nothing that compares equal to key is currently in the list.
  46. void Insert(const Key& key);
  47. // Returns true iff an entry that compares equal to key is in the list.
  48. bool Contains(const Key& key) const;
  49. // Iteration over the contents of a skip list
  50. class Iterator {
  51. public:
  52. // Initialize an iterator over the specified list.
  53. // The returned iterator is not valid.
  54. explicit Iterator(const SkipList* list);
  55. // Returns true iff the iterator is positioned at a valid node.
  56. bool Valid() const;
  57. // Returns the key at the current position.
  58. // REQUIRES: Valid()
  59. const Key& key() const;
  60. // Advances to the next position.
  61. // REQUIRES: Valid()
  62. void Next();
  63. // Advances to the previous position.
  64. // REQUIRES: Valid()
  65. void Prev();
  66. // Advance to the first entry with a key >= target
  67. void Seek(const Key& target);
  68. // Position at the first entry in list.
  69. // Final state of iterator is Valid() iff list is not empty.
  70. void SeekToFirst();
  71. // Position at the last entry in list.
  72. // Final state of iterator is Valid() iff list is not empty.
  73. void SeekToLast();
  74. private:
  75. const SkipList* list_;
  76. Node* node_;
  77. // Intentionally copyable
  78. };
  79. private:
  80. enum { kMaxHeight = 12 };
  81. // Immutable after construction
  82. Comparator const compare_;
  83. Arena* const arena_; // Arena used for allocations of nodes
  84. Node* const head_;
  85. // Modified only by Insert(). Read racily by readers, but stale
  86. // values are ok.
  87. port::AtomicPointer max_height_; // Height of the entire list
  88. inline int GetMaxHeight() const {
  89. return static_cast<int>(
  90. reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load()));
  91. }
  92. // Read/written only by Insert().
  93. Random rnd_;
  94. Node* NewNode(const Key& key, int height);
  95. int RandomHeight();
  96. bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); }
  97. // Return true if key is greater than the data stored in "n"
  98. bool KeyIsAfterNode(const Key& key, Node* n) const;
  99. // Return the earliest node that comes at or after key.
  100. // Return NULL if there is no such node.
  101. //
  102. // If prev is non-NULL, fills prev[level] with pointer to previous
  103. // node at "level" for every level in [0..max_height_-1].
  104. Node* FindGreaterOrEqual(const Key& key, Node** prev) const;
  105. // Return the latest node with a key < key.
  106. // Return head_ if there is no such node.
  107. Node* FindLessThan(const Key& key) const;
  108. // Return the last node in the list.
  109. // Return head_ if list is empty.
  110. Node* FindLast() const;
  111. // No copying allowed
  112. SkipList(const SkipList&);
  113. void operator=(const SkipList&);
  114. };
  115. // Implementation details follow
  116. template<typename Key, class Comparator>
  117. struct SkipList<Key,Comparator>::Node {
  118. explicit Node(const Key& k) : key(k) { }
  119. Key const key;
  120. // Accessors/mutators for links. Wrapped in methods so we can
  121. // add the appropriate barriers as necessary.
  122. Node* Next(int n) {
  123. assert(n >= 0);
  124. // Use an 'acquire load' so that we observe a fully initialized
  125. // version of the returned Node.
  126. return reinterpret_cast<Node*>(next_[n].Acquire_Load());
  127. }
  128. void SetNext(int n, Node* x) {
  129. assert(n >= 0);
  130. // Use a 'release store' so that anybody who reads through this
  131. // pointer observes a fully initialized version of the inserted node.
  132. next_[n].Release_Store(x);
  133. }
  134. // No-barrier variants that can be safely used in a few locations.
  135. Node* NoBarrier_Next(int n) {
  136. assert(n >= 0);
  137. return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
  138. }
  139. void NoBarrier_SetNext(int n, Node* x) {
  140. assert(n >= 0);
  141. next_[n].NoBarrier_Store(x);
  142. }
  143. private:
  144. // Array of length equal to the node height. next_[0] is lowest level link.
  145. port::AtomicPointer next_[1];
  146. };
  147. template<typename Key, class Comparator>
  148. typename SkipList<Key,Comparator>::Node*
  149. SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
  150. char* mem = arena_->AllocateAligned(
  151. sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
  152. return new (mem) Node(key);
  153. }
  154. template<typename Key, class Comparator>
  155. inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
  156. list_ = list;
  157. node_ = NULL;
  158. }
  159. template<typename Key, class Comparator>
  160. inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
  161. return node_ != NULL;
  162. }
  163. template<typename Key, class Comparator>
  164. inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
  165. assert(Valid());
  166. return node_->key;
  167. }
  168. template<typename Key, class Comparator>
  169. inline void SkipList<Key,Comparator>::Iterator::Next() {
  170. assert(Valid());
  171. node_ = node_->Next(0);
  172. }
  173. template<typename Key, class Comparator>
  174. inline void SkipList<Key,Comparator>::Iterator::Prev() {
  175. // Instead of using explicit "prev" links, we just search for the
  176. // last node that falls before key.
  177. assert(Valid());
  178. node_ = list_->FindLessThan(node_->key);
  179. if (node_ == list_->head_) {
  180. node_ = NULL;
  181. }
  182. }
  183. template<typename Key, class Comparator>
  184. inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
  185. node_ = list_->FindGreaterOrEqual(target, NULL);
  186. }
  187. template<typename Key, class Comparator>
  188. inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
  189. node_ = list_->head_->Next(0);
  190. }
  191. template<typename Key, class Comparator>
  192. inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
  193. node_ = list_->FindLast();
  194. if (node_ == list_->head_) {
  195. node_ = NULL;
  196. }
  197. }
  198. template<typename Key, class Comparator>
  199. int SkipList<Key,Comparator>::RandomHeight() {
  200. // Increase height with probability 1 in kBranching
  201. static const unsigned int kBranching = 4;
  202. int height = 1;
  203. while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) {
  204. height++;
  205. }
  206. assert(height > 0);
  207. assert(height <= kMaxHeight);
  208. return height;
  209. }
  210. template<typename Key, class Comparator>
  211. bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
  212. // NULL n is considered infinite
  213. return (n != NULL) && (compare_(n->key, key) < 0);
  214. }
  215. template<typename Key, class Comparator>
  216. typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
  217. const {
  218. Node* x = head_;
  219. int level = GetMaxHeight() - 1;
  220. while (true) {
  221. Node* next = x->Next(level);
  222. if (KeyIsAfterNode(key, next)) {
  223. // Keep searching in this list
  224. x = next;
  225. } else {
  226. if (prev != NULL) prev[level] = x;
  227. if (level == 0) {
  228. return next;
  229. } else {
  230. // Switch to next list
  231. level--;
  232. }
  233. }
  234. }
  235. }
  236. template<typename Key, class Comparator>
  237. typename SkipList<Key,Comparator>::Node*
  238. SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
  239. Node* x = head_;
  240. int level = GetMaxHeight() - 1;
  241. while (true) {
  242. assert(x == head_ || compare_(x->key, key) < 0);
  243. Node* next = x->Next(level);
  244. if (next == NULL || compare_(next->key, key) >= 0) {
  245. if (level == 0) {
  246. return x;
  247. } else {
  248. // Switch to next list
  249. level--;
  250. }
  251. } else {
  252. x = next;
  253. }
  254. }
  255. }
  256. template<typename Key, class Comparator>
  257. typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
  258. const {
  259. Node* x = head_;
  260. int level = GetMaxHeight() - 1;
  261. while (true) {
  262. Node* next = x->Next(level);
  263. if (next == NULL) {
  264. if (level == 0) {
  265. return x;
  266. } else {
  267. // Switch to next list
  268. level--;
  269. }
  270. } else {
  271. x = next;
  272. }
  273. }
  274. }
  275. template<typename Key, class Comparator>
  276. SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
  277. : compare_(cmp),
  278. arena_(arena),
  279. head_(NewNode(0 /* any key will do */, kMaxHeight)),
  280. max_height_(reinterpret_cast<void*>(1)),
  281. rnd_(0xdeadbeef) {
  282. for (int i = 0; i < kMaxHeight; i++) {
  283. head_->SetNext(i, NULL);
  284. }
  285. }
  286. template<typename Key, class Comparator>
  287. void SkipList<Key,Comparator>::Insert(const Key& key) {
  288. // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
  289. // here since Insert() is externally synchronized.
  290. Node* prev[kMaxHeight];
  291. Node* x = FindGreaterOrEqual(key, prev);
  292. // Our data structure does not allow duplicate insertion
  293. assert(x == NULL || !Equal(key, x->key));
  294. int height = RandomHeight();
  295. if (height > GetMaxHeight()) {
  296. for (int i = GetMaxHeight(); i < height; i++) {
  297. prev[i] = head_;
  298. }
  299. //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);
  300. // It is ok to mutate max_height_ without any synchronization
  301. // with concurrent readers. A concurrent reader that observes
  302. // the new value of max_height_ will see either the old value of
  303. // new level pointers from head_ (NULL), or a new value set in
  304. // the loop below. In the former case the reader will
  305. // immediately drop to the next level since NULL sorts after all
  306. // keys. In the latter case the reader will use the new node.
  307. max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
  308. }
  309. x = NewNode(key, height);
  310. for (int i = 0; i < height; i++) {
  311. // NoBarrier_SetNext() suffices since we will add a barrier when
  312. // we publish a pointer to "x" in prev[i].
  313. x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
  314. prev[i]->SetNext(i, x);
  315. }
  316. }
  317. template<typename Key, class Comparator>
  318. bool SkipList<Key,Comparator>::Contains(const Key& key) const {
  319. Node* x = FindGreaterOrEqual(key, NULL);
  320. if (x != NULL && Equal(key, x->key)) {
  321. return true;
  322. } else {
  323. return false;
  324. }
  325. }
  326. } // namespace leveldb
  327. #endif // STORAGE_LEVELDB_DB_SKIPLIST_H_