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,104 @@
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
+ // Endian-neutral encoding:
6
+ // * Fixed-length numbers are encoded with least-significant byte first
7
+ // * In addition we support variable length "varint" encoding
8
+ // * Strings are encoded prefixed by their length in varint format
9
+
10
+ #ifndef STORAGE_LEVELDB_UTIL_CODING_H_
11
+ #define STORAGE_LEVELDB_UTIL_CODING_H_
12
+
13
+ #include <stdint.h>
14
+ #include <string.h>
15
+ #include <string>
16
+ #include "leveldb/slice.h"
17
+ #include "port/port.h"
18
+
19
+ namespace leveldb {
20
+
21
+ // Standard Put... routines append to a string
22
+ extern void PutFixed32(std::string* dst, uint32_t value);
23
+ extern void PutFixed64(std::string* dst, uint64_t value);
24
+ extern void PutVarint32(std::string* dst, uint32_t value);
25
+ extern void PutVarint64(std::string* dst, uint64_t value);
26
+ extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value);
27
+
28
+ // Standard Get... routines parse a value from the beginning of a Slice
29
+ // and advance the slice past the parsed value.
30
+ extern bool GetVarint32(Slice* input, uint32_t* value);
31
+ extern bool GetVarint64(Slice* input, uint64_t* value);
32
+ extern bool GetLengthPrefixedSlice(Slice* input, Slice* result);
33
+
34
+ // Pointer-based variants of GetVarint... These either store a value
35
+ // in *v and return a pointer just past the parsed value, or return
36
+ // NULL on error. These routines only look at bytes in the range
37
+ // [p..limit-1]
38
+ extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v);
39
+ extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v);
40
+
41
+ // Returns the length of the varint32 or varint64 encoding of "v"
42
+ extern int VarintLength(uint64_t v);
43
+
44
+ // Lower-level versions of Put... that write directly into a character buffer
45
+ // REQUIRES: dst has enough space for the value being written
46
+ extern void EncodeFixed32(char* dst, uint32_t value);
47
+ extern void EncodeFixed64(char* dst, uint64_t value);
48
+
49
+ // Lower-level versions of Put... that write directly into a character buffer
50
+ // and return a pointer just past the last byte written.
51
+ // REQUIRES: dst has enough space for the value being written
52
+ extern char* EncodeVarint32(char* dst, uint32_t value);
53
+ extern char* EncodeVarint64(char* dst, uint64_t value);
54
+
55
+ // Lower-level versions of Get... that read directly from a character buffer
56
+ // without any bounds checking.
57
+
58
+ inline uint32_t DecodeFixed32(const char* ptr) {
59
+ if (port::kLittleEndian) {
60
+ // Load the raw bytes
61
+ uint32_t result;
62
+ memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
63
+ return result;
64
+ } else {
65
+ return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
66
+ | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
67
+ | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
68
+ | (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
69
+ }
70
+ }
71
+
72
+ inline uint64_t DecodeFixed64(const char* ptr) {
73
+ if (port::kLittleEndian) {
74
+ // Load the raw bytes
75
+ uint64_t result;
76
+ memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
77
+ return result;
78
+ } else {
79
+ uint64_t lo = DecodeFixed32(ptr);
80
+ uint64_t hi = DecodeFixed32(ptr + 4);
81
+ return (hi << 32) | lo;
82
+ }
83
+ }
84
+
85
+ // Internal routine for use by fallback path of GetVarint32Ptr
86
+ extern const char* GetVarint32PtrFallback(const char* p,
87
+ const char* limit,
88
+ uint32_t* value);
89
+ inline const char* GetVarint32Ptr(const char* p,
90
+ const char* limit,
91
+ uint32_t* value) {
92
+ if (p < limit) {
93
+ uint32_t result = *(reinterpret_cast<const unsigned char*>(p));
94
+ if ((result & 128) == 0) {
95
+ *value = result;
96
+ return p + 1;
97
+ }
98
+ }
99
+ return GetVarint32PtrFallback(p, limit, value);
100
+ }
101
+
102
+ } // namespace leveldb
103
+
104
+ #endif // STORAGE_LEVELDB_UTIL_CODING_H_
@@ -0,0 +1,196 @@
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
+ #include "util/coding.h"
6
+
7
+ #include "util/testharness.h"
8
+
9
+ namespace leveldb {
10
+
11
+ class Coding { };
12
+
13
+ TEST(Coding, Fixed32) {
14
+ std::string s;
15
+ for (uint32_t v = 0; v < 100000; v++) {
16
+ PutFixed32(&s, v);
17
+ }
18
+
19
+ const char* p = s.data();
20
+ for (uint32_t v = 0; v < 100000; v++) {
21
+ uint32_t actual = DecodeFixed32(p);
22
+ ASSERT_EQ(v, actual);
23
+ p += sizeof(uint32_t);
24
+ }
25
+ }
26
+
27
+ TEST(Coding, Fixed64) {
28
+ std::string s;
29
+ for (int power = 0; power <= 63; power++) {
30
+ uint64_t v = static_cast<uint64_t>(1) << power;
31
+ PutFixed64(&s, v - 1);
32
+ PutFixed64(&s, v + 0);
33
+ PutFixed64(&s, v + 1);
34
+ }
35
+
36
+ const char* p = s.data();
37
+ for (int power = 0; power <= 63; power++) {
38
+ uint64_t v = static_cast<uint64_t>(1) << power;
39
+ uint64_t actual;
40
+ actual = DecodeFixed64(p);
41
+ ASSERT_EQ(v-1, actual);
42
+ p += sizeof(uint64_t);
43
+
44
+ actual = DecodeFixed64(p);
45
+ ASSERT_EQ(v+0, actual);
46
+ p += sizeof(uint64_t);
47
+
48
+ actual = DecodeFixed64(p);
49
+ ASSERT_EQ(v+1, actual);
50
+ p += sizeof(uint64_t);
51
+ }
52
+ }
53
+
54
+ // Test that encoding routines generate little-endian encodings
55
+ TEST(Coding, EncodingOutput) {
56
+ std::string dst;
57
+ PutFixed32(&dst, 0x04030201);
58
+ ASSERT_EQ(4, dst.size());
59
+ ASSERT_EQ(0x01, static_cast<int>(dst[0]));
60
+ ASSERT_EQ(0x02, static_cast<int>(dst[1]));
61
+ ASSERT_EQ(0x03, static_cast<int>(dst[2]));
62
+ ASSERT_EQ(0x04, static_cast<int>(dst[3]));
63
+
64
+ dst.clear();
65
+ PutFixed64(&dst, 0x0807060504030201ull);
66
+ ASSERT_EQ(8, dst.size());
67
+ ASSERT_EQ(0x01, static_cast<int>(dst[0]));
68
+ ASSERT_EQ(0x02, static_cast<int>(dst[1]));
69
+ ASSERT_EQ(0x03, static_cast<int>(dst[2]));
70
+ ASSERT_EQ(0x04, static_cast<int>(dst[3]));
71
+ ASSERT_EQ(0x05, static_cast<int>(dst[4]));
72
+ ASSERT_EQ(0x06, static_cast<int>(dst[5]));
73
+ ASSERT_EQ(0x07, static_cast<int>(dst[6]));
74
+ ASSERT_EQ(0x08, static_cast<int>(dst[7]));
75
+ }
76
+
77
+ TEST(Coding, Varint32) {
78
+ std::string s;
79
+ for (uint32_t i = 0; i < (32 * 32); i++) {
80
+ uint32_t v = (i / 32) << (i % 32);
81
+ PutVarint32(&s, v);
82
+ }
83
+
84
+ const char* p = s.data();
85
+ const char* limit = p + s.size();
86
+ for (uint32_t i = 0; i < (32 * 32); i++) {
87
+ uint32_t expected = (i / 32) << (i % 32);
88
+ uint32_t actual;
89
+ const char* start = p;
90
+ p = GetVarint32Ptr(p, limit, &actual);
91
+ ASSERT_TRUE(p != NULL);
92
+ ASSERT_EQ(expected, actual);
93
+ ASSERT_EQ(VarintLength(actual), p - start);
94
+ }
95
+ ASSERT_EQ(p, s.data() + s.size());
96
+ }
97
+
98
+ TEST(Coding, Varint64) {
99
+ // Construct the list of values to check
100
+ std::vector<uint64_t> values;
101
+ // Some special values
102
+ values.push_back(0);
103
+ values.push_back(100);
104
+ values.push_back(~static_cast<uint64_t>(0));
105
+ values.push_back(~static_cast<uint64_t>(0) - 1);
106
+ for (uint32_t k = 0; k < 64; k++) {
107
+ // Test values near powers of two
108
+ const uint64_t power = 1ull << k;
109
+ values.push_back(power);
110
+ values.push_back(power-1);
111
+ values.push_back(power+1);
112
+ }
113
+
114
+ std::string s;
115
+ for (int i = 0; i < values.size(); i++) {
116
+ PutVarint64(&s, values[i]);
117
+ }
118
+
119
+ const char* p = s.data();
120
+ const char* limit = p + s.size();
121
+ for (int i = 0; i < values.size(); i++) {
122
+ ASSERT_TRUE(p < limit);
123
+ uint64_t actual;
124
+ const char* start = p;
125
+ p = GetVarint64Ptr(p, limit, &actual);
126
+ ASSERT_TRUE(p != NULL);
127
+ ASSERT_EQ(values[i], actual);
128
+ ASSERT_EQ(VarintLength(actual), p - start);
129
+ }
130
+ ASSERT_EQ(p, limit);
131
+
132
+ }
133
+
134
+ TEST(Coding, Varint32Overflow) {
135
+ uint32_t result;
136
+ std::string input("\x81\x82\x83\x84\x85\x11");
137
+ ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result)
138
+ == NULL);
139
+ }
140
+
141
+ TEST(Coding, Varint32Truncation) {
142
+ uint32_t large_value = (1u << 31) + 100;
143
+ std::string s;
144
+ PutVarint32(&s, large_value);
145
+ uint32_t result;
146
+ for (int len = 0; len < s.size() - 1; len++) {
147
+ ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL);
148
+ }
149
+ ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL);
150
+ ASSERT_EQ(large_value, result);
151
+ }
152
+
153
+ TEST(Coding, Varint64Overflow) {
154
+ uint64_t result;
155
+ std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
156
+ ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result)
157
+ == NULL);
158
+ }
159
+
160
+ TEST(Coding, Varint64Truncation) {
161
+ uint64_t large_value = (1ull << 63) + 100ull;
162
+ std::string s;
163
+ PutVarint64(&s, large_value);
164
+ uint64_t result;
165
+ for (int len = 0; len < s.size() - 1; len++) {
166
+ ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL);
167
+ }
168
+ ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL);
169
+ ASSERT_EQ(large_value, result);
170
+ }
171
+
172
+ TEST(Coding, Strings) {
173
+ std::string s;
174
+ PutLengthPrefixedSlice(&s, Slice(""));
175
+ PutLengthPrefixedSlice(&s, Slice("foo"));
176
+ PutLengthPrefixedSlice(&s, Slice("bar"));
177
+ PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x')));
178
+
179
+ Slice input(s);
180
+ Slice v;
181
+ ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
182
+ ASSERT_EQ("", v.ToString());
183
+ ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
184
+ ASSERT_EQ("foo", v.ToString());
185
+ ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
186
+ ASSERT_EQ("bar", v.ToString());
187
+ ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
188
+ ASSERT_EQ(std::string(200, 'x'), v.ToString());
189
+ ASSERT_EQ("", input.ToString());
190
+ }
191
+
192
+ } // namespace leveldb
193
+
194
+ int main(int argc, char** argv) {
195
+ return leveldb::test::RunAllTests();
196
+ }
@@ -0,0 +1,81 @@
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
+ #include <algorithm>
6
+ #include <stdint.h>
7
+ #include "leveldb/comparator.h"
8
+ #include "leveldb/slice.h"
9
+ #include "port/port.h"
10
+ #include "util/logging.h"
11
+
12
+ namespace leveldb {
13
+
14
+ Comparator::~Comparator() { }
15
+
16
+ namespace {
17
+ class BytewiseComparatorImpl : public Comparator {
18
+ public:
19
+ BytewiseComparatorImpl() { }
20
+
21
+ virtual const char* Name() const {
22
+ return "leveldb.BytewiseComparator";
23
+ }
24
+
25
+ virtual int Compare(const Slice& a, const Slice& b) const {
26
+ return a.compare(b);
27
+ }
28
+
29
+ virtual void FindShortestSeparator(
30
+ std::string* start,
31
+ const Slice& limit) const {
32
+ // Find length of common prefix
33
+ size_t min_length = std::min(start->size(), limit.size());
34
+ size_t diff_index = 0;
35
+ while ((diff_index < min_length) &&
36
+ ((*start)[diff_index] == limit[diff_index])) {
37
+ diff_index++;
38
+ }
39
+
40
+ if (diff_index >= min_length) {
41
+ // Do not shorten if one string is a prefix of the other
42
+ } else {
43
+ uint8_t diff_byte = static_cast<uint8_t>((*start)[diff_index]);
44
+ if (diff_byte < static_cast<uint8_t>(0xff) &&
45
+ diff_byte + 1 < static_cast<uint8_t>(limit[diff_index])) {
46
+ (*start)[diff_index]++;
47
+ start->resize(diff_index + 1);
48
+ assert(Compare(*start, limit) < 0);
49
+ }
50
+ }
51
+ }
52
+
53
+ virtual void FindShortSuccessor(std::string* key) const {
54
+ // Find first character that can be incremented
55
+ size_t n = key->size();
56
+ for (size_t i = 0; i < n; i++) {
57
+ const uint8_t byte = (*key)[i];
58
+ if (byte != static_cast<uint8_t>(0xff)) {
59
+ (*key)[i] = byte + 1;
60
+ key->resize(i+1);
61
+ return;
62
+ }
63
+ }
64
+ // *key is a run of 0xffs. Leave it alone.
65
+ }
66
+ };
67
+ } // namespace
68
+
69
+ static port::OnceType once = LEVELDB_ONCE_INIT;
70
+ static const Comparator* bytewise;
71
+
72
+ static void InitModule() {
73
+ bytewise = new BytewiseComparatorImpl;
74
+ }
75
+
76
+ const Comparator* BytewiseComparator() {
77
+ port::InitOnce(&once, InitModule);
78
+ return bytewise;
79
+ }
80
+
81
+ } // namespace leveldb