leveldb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +95 -0
  4. data/ext/Rakefile +11 -0
  5. data/ext/leveldb/LICENSE +27 -0
  6. data/ext/leveldb/Makefile +206 -0
  7. data/ext/leveldb/build_config.mk +13 -0
  8. data/ext/leveldb/db/builder.cc +88 -0
  9. data/ext/leveldb/db/builder.h +34 -0
  10. data/ext/leveldb/db/c.cc +595 -0
  11. data/ext/leveldb/db/c_test.c +390 -0
  12. data/ext/leveldb/db/corruption_test.cc +359 -0
  13. data/ext/leveldb/db/db_bench.cc +979 -0
  14. data/ext/leveldb/db/db_impl.cc +1485 -0
  15. data/ext/leveldb/db/db_impl.h +203 -0
  16. data/ext/leveldb/db/db_iter.cc +299 -0
  17. data/ext/leveldb/db/db_iter.h +26 -0
  18. data/ext/leveldb/db/db_test.cc +2092 -0
  19. data/ext/leveldb/db/dbformat.cc +140 -0
  20. data/ext/leveldb/db/dbformat.h +227 -0
  21. data/ext/leveldb/db/dbformat_test.cc +112 -0
  22. data/ext/leveldb/db/filename.cc +139 -0
  23. data/ext/leveldb/db/filename.h +80 -0
  24. data/ext/leveldb/db/filename_test.cc +122 -0
  25. data/ext/leveldb/db/leveldb_main.cc +238 -0
  26. data/ext/leveldb/db/log_format.h +35 -0
  27. data/ext/leveldb/db/log_reader.cc +259 -0
  28. data/ext/leveldb/db/log_reader.h +108 -0
  29. data/ext/leveldb/db/log_test.cc +500 -0
  30. data/ext/leveldb/db/log_writer.cc +103 -0
  31. data/ext/leveldb/db/log_writer.h +48 -0
  32. data/ext/leveldb/db/memtable.cc +145 -0
  33. data/ext/leveldb/db/memtable.h +91 -0
  34. data/ext/leveldb/db/repair.cc +389 -0
  35. data/ext/leveldb/db/skiplist.h +379 -0
  36. data/ext/leveldb/db/skiplist_test.cc +378 -0
  37. data/ext/leveldb/db/snapshot.h +66 -0
  38. data/ext/leveldb/db/table_cache.cc +121 -0
  39. data/ext/leveldb/db/table_cache.h +61 -0
  40. data/ext/leveldb/db/version_edit.cc +266 -0
  41. data/ext/leveldb/db/version_edit.h +107 -0
  42. data/ext/leveldb/db/version_edit_test.cc +46 -0
  43. data/ext/leveldb/db/version_set.cc +1443 -0
  44. data/ext/leveldb/db/version_set.h +383 -0
  45. data/ext/leveldb/db/version_set_test.cc +179 -0
  46. data/ext/leveldb/db/write_batch.cc +147 -0
  47. data/ext/leveldb/db/write_batch_internal.h +49 -0
  48. data/ext/leveldb/db/write_batch_test.cc +120 -0
  49. data/ext/leveldb/doc/bench/db_bench_sqlite3.cc +718 -0
  50. data/ext/leveldb/doc/bench/db_bench_tree_db.cc +528 -0
  51. data/ext/leveldb/helpers/memenv/memenv.cc +384 -0
  52. data/ext/leveldb/helpers/memenv/memenv.h +20 -0
  53. data/ext/leveldb/helpers/memenv/memenv_test.cc +232 -0
  54. data/ext/leveldb/include/leveldb/c.h +291 -0
  55. data/ext/leveldb/include/leveldb/cache.h +99 -0
  56. data/ext/leveldb/include/leveldb/comparator.h +63 -0
  57. data/ext/leveldb/include/leveldb/db.h +161 -0
  58. data/ext/leveldb/include/leveldb/env.h +333 -0
  59. data/ext/leveldb/include/leveldb/filter_policy.h +70 -0
  60. data/ext/leveldb/include/leveldb/iterator.h +100 -0
  61. data/ext/leveldb/include/leveldb/options.h +195 -0
  62. data/ext/leveldb/include/leveldb/slice.h +109 -0
  63. data/ext/leveldb/include/leveldb/status.h +106 -0
  64. data/ext/leveldb/include/leveldb/table.h +85 -0
  65. data/ext/leveldb/include/leveldb/table_builder.h +92 -0
  66. data/ext/leveldb/include/leveldb/write_batch.h +64 -0
  67. data/ext/leveldb/issues/issue178_test.cc +92 -0
  68. data/ext/leveldb/port/atomic_pointer.h +224 -0
  69. data/ext/leveldb/port/port.h +19 -0
  70. data/ext/leveldb/port/port_example.h +135 -0
  71. data/ext/leveldb/port/port_posix.cc +54 -0
  72. data/ext/leveldb/port/port_posix.h +157 -0
  73. data/ext/leveldb/port/thread_annotations.h +59 -0
  74. data/ext/leveldb/port/win/stdint.h +24 -0
  75. data/ext/leveldb/table/block.cc +268 -0
  76. data/ext/leveldb/table/block.h +44 -0
  77. data/ext/leveldb/table/block_builder.cc +109 -0
  78. data/ext/leveldb/table/block_builder.h +57 -0
  79. data/ext/leveldb/table/filter_block.cc +111 -0
  80. data/ext/leveldb/table/filter_block.h +68 -0
  81. data/ext/leveldb/table/filter_block_test.cc +128 -0
  82. data/ext/leveldb/table/format.cc +145 -0
  83. data/ext/leveldb/table/format.h +108 -0
  84. data/ext/leveldb/table/iterator.cc +67 -0
  85. data/ext/leveldb/table/iterator_wrapper.h +63 -0
  86. data/ext/leveldb/table/merger.cc +197 -0
  87. data/ext/leveldb/table/merger.h +26 -0
  88. data/ext/leveldb/table/table.cc +275 -0
  89. data/ext/leveldb/table/table_builder.cc +270 -0
  90. data/ext/leveldb/table/table_test.cc +868 -0
  91. data/ext/leveldb/table/two_level_iterator.cc +182 -0
  92. data/ext/leveldb/table/two_level_iterator.h +34 -0
  93. data/ext/leveldb/util/arena.cc +68 -0
  94. data/ext/leveldb/util/arena.h +68 -0
  95. data/ext/leveldb/util/arena_test.cc +68 -0
  96. data/ext/leveldb/util/bloom.cc +95 -0
  97. data/ext/leveldb/util/bloom_test.cc +160 -0
  98. data/ext/leveldb/util/cache.cc +325 -0
  99. data/ext/leveldb/util/cache_test.cc +186 -0
  100. data/ext/leveldb/util/coding.cc +194 -0
  101. data/ext/leveldb/util/coding.h +104 -0
  102. data/ext/leveldb/util/coding_test.cc +196 -0
  103. data/ext/leveldb/util/comparator.cc +81 -0
  104. data/ext/leveldb/util/crc32c.cc +332 -0
  105. data/ext/leveldb/util/crc32c.h +45 -0
  106. data/ext/leveldb/util/crc32c_test.cc +72 -0
  107. data/ext/leveldb/util/env.cc +96 -0
  108. data/ext/leveldb/util/env_posix.cc +698 -0
  109. data/ext/leveldb/util/env_test.cc +104 -0
  110. data/ext/leveldb/util/filter_policy.cc +11 -0
  111. data/ext/leveldb/util/hash.cc +52 -0
  112. data/ext/leveldb/util/hash.h +19 -0
  113. data/ext/leveldb/util/histogram.cc +139 -0
  114. data/ext/leveldb/util/histogram.h +42 -0
  115. data/ext/leveldb/util/logging.cc +81 -0
  116. data/ext/leveldb/util/logging.h +47 -0
  117. data/ext/leveldb/util/mutexlock.h +41 -0
  118. data/ext/leveldb/util/options.cc +29 -0
  119. data/ext/leveldb/util/posix_logger.h +98 -0
  120. data/ext/leveldb/util/random.h +59 -0
  121. data/ext/leveldb/util/status.cc +75 -0
  122. data/ext/leveldb/util/testharness.cc +77 -0
  123. data/ext/leveldb/util/testharness.h +138 -0
  124. data/ext/leveldb/util/testutil.cc +51 -0
  125. data/ext/leveldb/util/testutil.h +53 -0
  126. data/lib/leveldb/version.rb +3 -0
  127. data/lib/leveldb.rb +1006 -0
  128. metadata +228 -0
@@ -0,0 +1,59 @@
1
+ // Copyright (c) 2012 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
+ #ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H
6
+
7
+ // Some environments provide custom macros to aid in static thread-safety
8
+ // analysis. Provide empty definitions of such macros unless they are already
9
+ // defined.
10
+
11
+ #ifndef EXCLUSIVE_LOCKS_REQUIRED
12
+ #define EXCLUSIVE_LOCKS_REQUIRED(...)
13
+ #endif
14
+
15
+ #ifndef SHARED_LOCKS_REQUIRED
16
+ #define SHARED_LOCKS_REQUIRED(...)
17
+ #endif
18
+
19
+ #ifndef LOCKS_EXCLUDED
20
+ #define LOCKS_EXCLUDED(...)
21
+ #endif
22
+
23
+ #ifndef LOCK_RETURNED
24
+ #define LOCK_RETURNED(x)
25
+ #endif
26
+
27
+ #ifndef LOCKABLE
28
+ #define LOCKABLE
29
+ #endif
30
+
31
+ #ifndef SCOPED_LOCKABLE
32
+ #define SCOPED_LOCKABLE
33
+ #endif
34
+
35
+ #ifndef EXCLUSIVE_LOCK_FUNCTION
36
+ #define EXCLUSIVE_LOCK_FUNCTION(...)
37
+ #endif
38
+
39
+ #ifndef SHARED_LOCK_FUNCTION
40
+ #define SHARED_LOCK_FUNCTION(...)
41
+ #endif
42
+
43
+ #ifndef EXCLUSIVE_TRYLOCK_FUNCTION
44
+ #define EXCLUSIVE_TRYLOCK_FUNCTION(...)
45
+ #endif
46
+
47
+ #ifndef SHARED_TRYLOCK_FUNCTION
48
+ #define SHARED_TRYLOCK_FUNCTION(...)
49
+ #endif
50
+
51
+ #ifndef UNLOCK_FUNCTION
52
+ #define UNLOCK_FUNCTION(...)
53
+ #endif
54
+
55
+ #ifndef NO_THREAD_SAFETY_ANALYSIS
56
+ #define NO_THREAD_SAFETY_ANALYSIS
57
+ #endif
58
+
59
+ #endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H
@@ -0,0 +1,24 @@
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
+ // MSVC didn't ship with this file until the 2010 version.
6
+
7
+ #ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_
8
+ #define STORAGE_LEVELDB_PORT_WIN_STDINT_H_
9
+
10
+ #if !defined(_MSC_VER)
11
+ #error This file should only be included when compiling with MSVC.
12
+ #endif
13
+
14
+ // Define C99 equivalent types.
15
+ typedef signed char int8_t;
16
+ typedef signed short int16_t;
17
+ typedef signed int int32_t;
18
+ typedef signed long long int64_t;
19
+ typedef unsigned char uint8_t;
20
+ typedef unsigned short uint16_t;
21
+ typedef unsigned int uint32_t;
22
+ typedef unsigned long long uint64_t;
23
+
24
+ #endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_
@@ -0,0 +1,268 @@
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
+
7
+ #include "table/block.h"
8
+
9
+ #include <vector>
10
+ #include <algorithm>
11
+ #include "leveldb/comparator.h"
12
+ #include "table/format.h"
13
+ #include "util/coding.h"
14
+ #include "util/logging.h"
15
+
16
+ namespace leveldb {
17
+
18
+ inline uint32_t Block::NumRestarts() const {
19
+ assert(size_ >= sizeof(uint32_t));
20
+ return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
21
+ }
22
+
23
+ Block::Block(const BlockContents& contents)
24
+ : data_(contents.data.data()),
25
+ size_(contents.data.size()),
26
+ owned_(contents.heap_allocated) {
27
+ if (size_ < sizeof(uint32_t)) {
28
+ size_ = 0; // Error marker
29
+ } else {
30
+ size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t);
31
+ if (NumRestarts() > max_restarts_allowed) {
32
+ // The size is too small for NumRestarts()
33
+ size_ = 0;
34
+ } else {
35
+ restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
36
+ }
37
+ }
38
+ }
39
+
40
+ Block::~Block() {
41
+ if (owned_) {
42
+ delete[] data_;
43
+ }
44
+ }
45
+
46
+ // Helper routine: decode the next block entry starting at "p",
47
+ // storing the number of shared key bytes, non_shared key bytes,
48
+ // and the length of the value in "*shared", "*non_shared", and
49
+ // "*value_length", respectively. Will not derefence past "limit".
50
+ //
51
+ // If any errors are detected, returns NULL. Otherwise, returns a
52
+ // pointer to the key delta (just past the three decoded values).
53
+ static inline const char* DecodeEntry(const char* p, const char* limit,
54
+ uint32_t* shared,
55
+ uint32_t* non_shared,
56
+ uint32_t* value_length) {
57
+ if (limit - p < 3) return NULL;
58
+ *shared = reinterpret_cast<const unsigned char*>(p)[0];
59
+ *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
60
+ *value_length = reinterpret_cast<const unsigned char*>(p)[2];
61
+ if ((*shared | *non_shared | *value_length) < 128) {
62
+ // Fast path: all three values are encoded in one byte each
63
+ p += 3;
64
+ } else {
65
+ if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL;
66
+ if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL;
67
+ if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL;
68
+ }
69
+
70
+ if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) {
71
+ return NULL;
72
+ }
73
+ return p;
74
+ }
75
+
76
+ class Block::Iter : public Iterator {
77
+ private:
78
+ const Comparator* const comparator_;
79
+ const char* const data_; // underlying block contents
80
+ uint32_t const restarts_; // Offset of restart array (list of fixed32)
81
+ uint32_t const num_restarts_; // Number of uint32_t entries in restart array
82
+
83
+ // current_ is offset in data_ of current entry. >= restarts_ if !Valid
84
+ uint32_t current_;
85
+ uint32_t restart_index_; // Index of restart block in which current_ falls
86
+ std::string key_;
87
+ Slice value_;
88
+ Status status_;
89
+
90
+ inline int Compare(const Slice& a, const Slice& b) const {
91
+ return comparator_->Compare(a, b);
92
+ }
93
+
94
+ // Return the offset in data_ just past the end of the current entry.
95
+ inline uint32_t NextEntryOffset() const {
96
+ return (value_.data() + value_.size()) - data_;
97
+ }
98
+
99
+ uint32_t GetRestartPoint(uint32_t index) {
100
+ assert(index < num_restarts_);
101
+ return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
102
+ }
103
+
104
+ void SeekToRestartPoint(uint32_t index) {
105
+ key_.clear();
106
+ restart_index_ = index;
107
+ // current_ will be fixed by ParseNextKey();
108
+
109
+ // ParseNextKey() starts at the end of value_, so set value_ accordingly
110
+ uint32_t offset = GetRestartPoint(index);
111
+ value_ = Slice(data_ + offset, 0);
112
+ }
113
+
114
+ public:
115
+ Iter(const Comparator* comparator,
116
+ const char* data,
117
+ uint32_t restarts,
118
+ uint32_t num_restarts)
119
+ : comparator_(comparator),
120
+ data_(data),
121
+ restarts_(restarts),
122
+ num_restarts_(num_restarts),
123
+ current_(restarts_),
124
+ restart_index_(num_restarts_) {
125
+ assert(num_restarts_ > 0);
126
+ }
127
+
128
+ virtual bool Valid() const { return current_ < restarts_; }
129
+ virtual Status status() const { return status_; }
130
+ virtual Slice key() const {
131
+ assert(Valid());
132
+ return key_;
133
+ }
134
+ virtual Slice value() const {
135
+ assert(Valid());
136
+ return value_;
137
+ }
138
+
139
+ virtual void Next() {
140
+ assert(Valid());
141
+ ParseNextKey();
142
+ }
143
+
144
+ virtual void Prev() {
145
+ assert(Valid());
146
+
147
+ // Scan backwards to a restart point before current_
148
+ const uint32_t original = current_;
149
+ while (GetRestartPoint(restart_index_) >= original) {
150
+ if (restart_index_ == 0) {
151
+ // No more entries
152
+ current_ = restarts_;
153
+ restart_index_ = num_restarts_;
154
+ return;
155
+ }
156
+ restart_index_--;
157
+ }
158
+
159
+ SeekToRestartPoint(restart_index_);
160
+ do {
161
+ // Loop until end of current entry hits the start of original entry
162
+ } while (ParseNextKey() && NextEntryOffset() < original);
163
+ }
164
+
165
+ virtual void Seek(const Slice& target) {
166
+ // Binary search in restart array to find the last restart point
167
+ // with a key < target
168
+ uint32_t left = 0;
169
+ uint32_t right = num_restarts_ - 1;
170
+ while (left < right) {
171
+ uint32_t mid = (left + right + 1) / 2;
172
+ uint32_t region_offset = GetRestartPoint(mid);
173
+ uint32_t shared, non_shared, value_length;
174
+ const char* key_ptr = DecodeEntry(data_ + region_offset,
175
+ data_ + restarts_,
176
+ &shared, &non_shared, &value_length);
177
+ if (key_ptr == NULL || (shared != 0)) {
178
+ CorruptionError();
179
+ return;
180
+ }
181
+ Slice mid_key(key_ptr, non_shared);
182
+ if (Compare(mid_key, target) < 0) {
183
+ // Key at "mid" is smaller than "target". Therefore all
184
+ // blocks before "mid" are uninteresting.
185
+ left = mid;
186
+ } else {
187
+ // Key at "mid" is >= "target". Therefore all blocks at or
188
+ // after "mid" are uninteresting.
189
+ right = mid - 1;
190
+ }
191
+ }
192
+
193
+ // Linear search (within restart block) for first key >= target
194
+ SeekToRestartPoint(left);
195
+ while (true) {
196
+ if (!ParseNextKey()) {
197
+ return;
198
+ }
199
+ if (Compare(key_, target) >= 0) {
200
+ return;
201
+ }
202
+ }
203
+ }
204
+
205
+ virtual void SeekToFirst() {
206
+ SeekToRestartPoint(0);
207
+ ParseNextKey();
208
+ }
209
+
210
+ virtual void SeekToLast() {
211
+ SeekToRestartPoint(num_restarts_ - 1);
212
+ while (ParseNextKey() && NextEntryOffset() < restarts_) {
213
+ // Keep skipping
214
+ }
215
+ }
216
+
217
+ private:
218
+ void CorruptionError() {
219
+ current_ = restarts_;
220
+ restart_index_ = num_restarts_;
221
+ status_ = Status::Corruption("bad entry in block");
222
+ key_.clear();
223
+ value_.clear();
224
+ }
225
+
226
+ bool ParseNextKey() {
227
+ current_ = NextEntryOffset();
228
+ const char* p = data_ + current_;
229
+ const char* limit = data_ + restarts_; // Restarts come right after data
230
+ if (p >= limit) {
231
+ // No more entries to return. Mark as invalid.
232
+ current_ = restarts_;
233
+ restart_index_ = num_restarts_;
234
+ return false;
235
+ }
236
+
237
+ // Decode next entry
238
+ uint32_t shared, non_shared, value_length;
239
+ p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
240
+ if (p == NULL || key_.size() < shared) {
241
+ CorruptionError();
242
+ return false;
243
+ } else {
244
+ key_.resize(shared);
245
+ key_.append(p, non_shared);
246
+ value_ = Slice(p + non_shared, value_length);
247
+ while (restart_index_ + 1 < num_restarts_ &&
248
+ GetRestartPoint(restart_index_ + 1) < current_) {
249
+ ++restart_index_;
250
+ }
251
+ return true;
252
+ }
253
+ }
254
+ };
255
+
256
+ Iterator* Block::NewIterator(const Comparator* cmp) {
257
+ if (size_ < sizeof(uint32_t)) {
258
+ return NewErrorIterator(Status::Corruption("bad block contents"));
259
+ }
260
+ const uint32_t num_restarts = NumRestarts();
261
+ if (num_restarts == 0) {
262
+ return NewEmptyIterator();
263
+ } else {
264
+ return new Iter(cmp, data_, restart_offset_, num_restarts);
265
+ }
266
+ }
267
+
268
+ } // namespace leveldb
@@ -0,0 +1,44 @@
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
+ #ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_
6
+ #define STORAGE_LEVELDB_TABLE_BLOCK_H_
7
+
8
+ #include <stddef.h>
9
+ #include <stdint.h>
10
+ #include "leveldb/iterator.h"
11
+
12
+ namespace leveldb {
13
+
14
+ struct BlockContents;
15
+ class Comparator;
16
+
17
+ class Block {
18
+ public:
19
+ // Initialize the block with the specified contents.
20
+ explicit Block(const BlockContents& contents);
21
+
22
+ ~Block();
23
+
24
+ size_t size() const { return size_; }
25
+ Iterator* NewIterator(const Comparator* comparator);
26
+
27
+ private:
28
+ uint32_t NumRestarts() const;
29
+
30
+ const char* data_;
31
+ size_t size_;
32
+ uint32_t restart_offset_; // Offset in data_ of restart array
33
+ bool owned_; // Block owns data_[]
34
+
35
+ // No copying allowed
36
+ Block(const Block&);
37
+ void operator=(const Block&);
38
+
39
+ class Iter;
40
+ };
41
+
42
+ } // namespace leveldb
43
+
44
+ #endif // STORAGE_LEVELDB_TABLE_BLOCK_H_
@@ -0,0 +1,109 @@
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
+ // BlockBuilder generates blocks where keys are prefix-compressed:
6
+ //
7
+ // When we store a key, we drop the prefix shared with the previous
8
+ // string. This helps reduce the space requirement significantly.
9
+ // Furthermore, once every K keys, we do not apply the prefix
10
+ // compression and store the entire key. We call this a "restart
11
+ // point". The tail end of the block stores the offsets of all of the
12
+ // restart points, and can be used to do a binary search when looking
13
+ // for a particular key. Values are stored as-is (without compression)
14
+ // immediately following the corresponding key.
15
+ //
16
+ // An entry for a particular key-value pair has the form:
17
+ // shared_bytes: varint32
18
+ // unshared_bytes: varint32
19
+ // value_length: varint32
20
+ // key_delta: char[unshared_bytes]
21
+ // value: char[value_length]
22
+ // shared_bytes == 0 for restart points.
23
+ //
24
+ // The trailer of the block has the form:
25
+ // restarts: uint32[num_restarts]
26
+ // num_restarts: uint32
27
+ // restarts[i] contains the offset within the block of the ith restart point.
28
+
29
+ #include "table/block_builder.h"
30
+
31
+ #include <algorithm>
32
+ #include <assert.h>
33
+ #include "leveldb/comparator.h"
34
+ #include "leveldb/table_builder.h"
35
+ #include "util/coding.h"
36
+
37
+ namespace leveldb {
38
+
39
+ BlockBuilder::BlockBuilder(const Options* options)
40
+ : options_(options),
41
+ restarts_(),
42
+ counter_(0),
43
+ finished_(false) {
44
+ assert(options->block_restart_interval >= 1);
45
+ restarts_.push_back(0); // First restart point is at offset 0
46
+ }
47
+
48
+ void BlockBuilder::Reset() {
49
+ buffer_.clear();
50
+ restarts_.clear();
51
+ restarts_.push_back(0); // First restart point is at offset 0
52
+ counter_ = 0;
53
+ finished_ = false;
54
+ last_key_.clear();
55
+ }
56
+
57
+ size_t BlockBuilder::CurrentSizeEstimate() const {
58
+ return (buffer_.size() + // Raw data buffer
59
+ restarts_.size() * sizeof(uint32_t) + // Restart array
60
+ sizeof(uint32_t)); // Restart array length
61
+ }
62
+
63
+ Slice BlockBuilder::Finish() {
64
+ // Append restart array
65
+ for (size_t i = 0; i < restarts_.size(); i++) {
66
+ PutFixed32(&buffer_, restarts_[i]);
67
+ }
68
+ PutFixed32(&buffer_, restarts_.size());
69
+ finished_ = true;
70
+ return Slice(buffer_);
71
+ }
72
+
73
+ void BlockBuilder::Add(const Slice& key, const Slice& value) {
74
+ Slice last_key_piece(last_key_);
75
+ assert(!finished_);
76
+ assert(counter_ <= options_->block_restart_interval);
77
+ assert(buffer_.empty() // No values yet?
78
+ || options_->comparator->Compare(key, last_key_piece) > 0);
79
+ size_t shared = 0;
80
+ if (counter_ < options_->block_restart_interval) {
81
+ // See how much sharing to do with previous string
82
+ const size_t min_length = std::min(last_key_piece.size(), key.size());
83
+ while ((shared < min_length) && (last_key_piece[shared] == key[shared])) {
84
+ shared++;
85
+ }
86
+ } else {
87
+ // Restart compression
88
+ restarts_.push_back(buffer_.size());
89
+ counter_ = 0;
90
+ }
91
+ const size_t non_shared = key.size() - shared;
92
+
93
+ // Add "<shared><non_shared><value_size>" to buffer_
94
+ PutVarint32(&buffer_, shared);
95
+ PutVarint32(&buffer_, non_shared);
96
+ PutVarint32(&buffer_, value.size());
97
+
98
+ // Add string delta to buffer_ followed by value
99
+ buffer_.append(key.data() + shared, non_shared);
100
+ buffer_.append(value.data(), value.size());
101
+
102
+ // Update state
103
+ last_key_.resize(shared);
104
+ last_key_.append(key.data() + shared, non_shared);
105
+ assert(Slice(last_key_) == key);
106
+ counter_++;
107
+ }
108
+
109
+ } // namespace leveldb
@@ -0,0 +1,57 @@
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
+ #ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
6
+ #define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
7
+
8
+ #include <vector>
9
+
10
+ #include <stdint.h>
11
+ #include "leveldb/slice.h"
12
+
13
+ namespace leveldb {
14
+
15
+ struct Options;
16
+
17
+ class BlockBuilder {
18
+ public:
19
+ explicit BlockBuilder(const Options* options);
20
+
21
+ // Reset the contents as if the BlockBuilder was just constructed.
22
+ void Reset();
23
+
24
+ // REQUIRES: Finish() has not been callled since the last call to Reset().
25
+ // REQUIRES: key is larger than any previously added key
26
+ void Add(const Slice& key, const Slice& value);
27
+
28
+ // Finish building the block and return a slice that refers to the
29
+ // block contents. The returned slice will remain valid for the
30
+ // lifetime of this builder or until Reset() is called.
31
+ Slice Finish();
32
+
33
+ // Returns an estimate of the current (uncompressed) size of the block
34
+ // we are building.
35
+ size_t CurrentSizeEstimate() const;
36
+
37
+ // Return true iff no entries have been added since the last Reset()
38
+ bool empty() const {
39
+ return buffer_.empty();
40
+ }
41
+
42
+ private:
43
+ const Options* options_;
44
+ std::string buffer_; // Destination buffer
45
+ std::vector<uint32_t> restarts_; // Restart points
46
+ int counter_; // Number of entries emitted since restart
47
+ bool finished_; // Has Finish() been called?
48
+ std::string last_key_;
49
+
50
+ // No copying allowed
51
+ BlockBuilder(const BlockBuilder&);
52
+ void operator=(const BlockBuilder&);
53
+ };
54
+
55
+ } // namespace leveldb
56
+
57
+ #endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
@@ -0,0 +1,111 @@
1
+ // Copyright (c) 2012 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 "table/filter_block.h"
6
+
7
+ #include "leveldb/filter_policy.h"
8
+ #include "util/coding.h"
9
+
10
+ namespace leveldb {
11
+
12
+ // See doc/table_format.txt for an explanation of the filter block format.
13
+
14
+ // Generate new filter every 2KB of data
15
+ static const size_t kFilterBaseLg = 11;
16
+ static const size_t kFilterBase = 1 << kFilterBaseLg;
17
+
18
+ FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)
19
+ : policy_(policy) {
20
+ }
21
+
22
+ void FilterBlockBuilder::StartBlock(uint64_t block_offset) {
23
+ uint64_t filter_index = (block_offset / kFilterBase);
24
+ assert(filter_index >= filter_offsets_.size());
25
+ while (filter_index > filter_offsets_.size()) {
26
+ GenerateFilter();
27
+ }
28
+ }
29
+
30
+ void FilterBlockBuilder::AddKey(const Slice& key) {
31
+ Slice k = key;
32
+ start_.push_back(keys_.size());
33
+ keys_.append(k.data(), k.size());
34
+ }
35
+
36
+ Slice FilterBlockBuilder::Finish() {
37
+ if (!start_.empty()) {
38
+ GenerateFilter();
39
+ }
40
+
41
+ // Append array of per-filter offsets
42
+ const uint32_t array_offset = result_.size();
43
+ for (size_t i = 0; i < filter_offsets_.size(); i++) {
44
+ PutFixed32(&result_, filter_offsets_[i]);
45
+ }
46
+
47
+ PutFixed32(&result_, array_offset);
48
+ result_.push_back(kFilterBaseLg); // Save encoding parameter in result
49
+ return Slice(result_);
50
+ }
51
+
52
+ void FilterBlockBuilder::GenerateFilter() {
53
+ const size_t num_keys = start_.size();
54
+ if (num_keys == 0) {
55
+ // Fast path if there are no keys for this filter
56
+ filter_offsets_.push_back(result_.size());
57
+ return;
58
+ }
59
+
60
+ // Make list of keys from flattened key structure
61
+ start_.push_back(keys_.size()); // Simplify length computation
62
+ tmp_keys_.resize(num_keys);
63
+ for (size_t i = 0; i < num_keys; i++) {
64
+ const char* base = keys_.data() + start_[i];
65
+ size_t length = start_[i+1] - start_[i];
66
+ tmp_keys_[i] = Slice(base, length);
67
+ }
68
+
69
+ // Generate filter for current set of keys and append to result_.
70
+ filter_offsets_.push_back(result_.size());
71
+ policy_->CreateFilter(&tmp_keys_[0], num_keys, &result_);
72
+
73
+ tmp_keys_.clear();
74
+ keys_.clear();
75
+ start_.clear();
76
+ }
77
+
78
+ FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
79
+ const Slice& contents)
80
+ : policy_(policy),
81
+ data_(NULL),
82
+ offset_(NULL),
83
+ num_(0),
84
+ base_lg_(0) {
85
+ size_t n = contents.size();
86
+ if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array
87
+ base_lg_ = contents[n-1];
88
+ uint32_t last_word = DecodeFixed32(contents.data() + n - 5);
89
+ if (last_word > n - 5) return;
90
+ data_ = contents.data();
91
+ offset_ = data_ + last_word;
92
+ num_ = (n - 5 - last_word) / 4;
93
+ }
94
+
95
+ bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
96
+ uint64_t index = block_offset >> base_lg_;
97
+ if (index < num_) {
98
+ uint32_t start = DecodeFixed32(offset_ + index*4);
99
+ uint32_t limit = DecodeFixed32(offset_ + index*4 + 4);
100
+ if (start <= limit && limit <= (offset_ - data_)) {
101
+ Slice filter = Slice(data_ + start, limit - start);
102
+ return policy_->KeyMayMatch(key, filter);
103
+ } else if (start == limit) {
104
+ // Empty filters do not match any keys
105
+ return false;
106
+ }
107
+ }
108
+ return true; // Errors are treated as potential matches
109
+ }
110
+
111
+ }