filiptepper-leveldb-ruby 0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/LICENSE +24 -0
  2. data/README +72 -0
  3. data/ext/leveldb/extconf.rb +14 -0
  4. data/ext/leveldb/leveldb.cc +530 -0
  5. data/ext/leveldb/platform.rb +83 -0
  6. data/leveldb/Makefile +191 -0
  7. data/leveldb/build_detect_platform +160 -0
  8. data/leveldb/db/builder.cc +88 -0
  9. data/leveldb/db/builder.h +34 -0
  10. data/leveldb/db/c.cc +581 -0
  11. data/leveldb/db/corruption_test.cc +359 -0
  12. data/leveldb/db/db_bench.cc +970 -0
  13. data/leveldb/db/db_impl.cc +1448 -0
  14. data/leveldb/db/db_impl.h +194 -0
  15. data/leveldb/db/db_iter.cc +299 -0
  16. data/leveldb/db/db_iter.h +26 -0
  17. data/leveldb/db/db_test.cc +1901 -0
  18. data/leveldb/db/dbformat.cc +140 -0
  19. data/leveldb/db/dbformat.h +227 -0
  20. data/leveldb/db/dbformat_test.cc +112 -0
  21. data/leveldb/db/filename.cc +139 -0
  22. data/leveldb/db/filename.h +80 -0
  23. data/leveldb/db/filename_test.cc +122 -0
  24. data/leveldb/db/log_format.h +35 -0
  25. data/leveldb/db/log_reader.cc +259 -0
  26. data/leveldb/db/log_reader.h +108 -0
  27. data/leveldb/db/log_test.cc +500 -0
  28. data/leveldb/db/log_writer.cc +103 -0
  29. data/leveldb/db/log_writer.h +48 -0
  30. data/leveldb/db/memtable.cc +145 -0
  31. data/leveldb/db/memtable.h +91 -0
  32. data/leveldb/db/repair.cc +389 -0
  33. data/leveldb/db/skiplist.h +379 -0
  34. data/leveldb/db/skiplist_test.cc +378 -0
  35. data/leveldb/db/snapshot.h +66 -0
  36. data/leveldb/db/table_cache.cc +121 -0
  37. data/leveldb/db/table_cache.h +61 -0
  38. data/leveldb/db/version_edit.cc +266 -0
  39. data/leveldb/db/version_edit.h +107 -0
  40. data/leveldb/db/version_edit_test.cc +46 -0
  41. data/leveldb/db/version_set.cc +1402 -0
  42. data/leveldb/db/version_set.h +370 -0
  43. data/leveldb/db/version_set_test.cc +179 -0
  44. data/leveldb/db/write_batch.cc +147 -0
  45. data/leveldb/db/write_batch_internal.h +49 -0
  46. data/leveldb/db/write_batch_test.cc +120 -0
  47. data/leveldb/helpers/memenv/memenv.cc +374 -0
  48. data/leveldb/helpers/memenv/memenv.h +20 -0
  49. data/leveldb/helpers/memenv/memenv_test.cc +232 -0
  50. data/leveldb/include/leveldb/c.h +275 -0
  51. data/leveldb/include/leveldb/cache.h +99 -0
  52. data/leveldb/include/leveldb/comparator.h +63 -0
  53. data/leveldb/include/leveldb/db.h +161 -0
  54. data/leveldb/include/leveldb/env.h +323 -0
  55. data/leveldb/include/leveldb/filter_policy.h +70 -0
  56. data/leveldb/include/leveldb/iterator.h +100 -0
  57. data/leveldb/include/leveldb/options.h +195 -0
  58. data/leveldb/include/leveldb/slice.h +109 -0
  59. data/leveldb/include/leveldb/status.h +106 -0
  60. data/leveldb/include/leveldb/table.h +85 -0
  61. data/leveldb/include/leveldb/table_builder.h +92 -0
  62. data/leveldb/include/leveldb/write_batch.h +64 -0
  63. data/leveldb/port/atomic_pointer.h +144 -0
  64. data/leveldb/port/port.h +21 -0
  65. data/leveldb/port/port_android.cc +64 -0
  66. data/leveldb/port/port_android.h +159 -0
  67. data/leveldb/port/port_example.h +125 -0
  68. data/leveldb/port/port_posix.cc +50 -0
  69. data/leveldb/port/port_posix.h +129 -0
  70. data/leveldb/port/win/stdint.h +24 -0
  71. data/leveldb/table/block.cc +267 -0
  72. data/leveldb/table/block.h +44 -0
  73. data/leveldb/table/block_builder.cc +109 -0
  74. data/leveldb/table/block_builder.h +57 -0
  75. data/leveldb/table/filter_block.cc +111 -0
  76. data/leveldb/table/filter_block.h +68 -0
  77. data/leveldb/table/filter_block_test.cc +128 -0
  78. data/leveldb/table/format.cc +145 -0
  79. data/leveldb/table/format.h +108 -0
  80. data/leveldb/table/iterator.cc +67 -0
  81. data/leveldb/table/iterator_wrapper.h +63 -0
  82. data/leveldb/table/merger.cc +197 -0
  83. data/leveldb/table/merger.h +26 -0
  84. data/leveldb/table/table.cc +276 -0
  85. data/leveldb/table/table_builder.cc +270 -0
  86. data/leveldb/table/table_test.cc +838 -0
  87. data/leveldb/table/two_level_iterator.cc +182 -0
  88. data/leveldb/table/two_level_iterator.h +34 -0
  89. data/leveldb/util/arena.cc +68 -0
  90. data/leveldb/util/arena.h +68 -0
  91. data/leveldb/util/arena_test.cc +68 -0
  92. data/leveldb/util/bloom.cc +95 -0
  93. data/leveldb/util/bloom_test.cc +159 -0
  94. data/leveldb/util/cache.cc +328 -0
  95. data/leveldb/util/cache_test.cc +186 -0
  96. data/leveldb/util/coding.cc +194 -0
  97. data/leveldb/util/coding.h +104 -0
  98. data/leveldb/util/coding_test.cc +173 -0
  99. data/leveldb/util/comparator.cc +76 -0
  100. data/leveldb/util/crc32c.cc +332 -0
  101. data/leveldb/util/crc32c.h +45 -0
  102. data/leveldb/util/crc32c_test.cc +72 -0
  103. data/leveldb/util/env.cc +96 -0
  104. data/leveldb/util/env_posix.cc +609 -0
  105. data/leveldb/util/env_test.cc +104 -0
  106. data/leveldb/util/filter_policy.cc +11 -0
  107. data/leveldb/util/hash.cc +45 -0
  108. data/leveldb/util/hash.h +19 -0
  109. data/leveldb/util/histogram.cc +139 -0
  110. data/leveldb/util/histogram.h +42 -0
  111. data/leveldb/util/logging.cc +81 -0
  112. data/leveldb/util/logging.h +47 -0
  113. data/leveldb/util/mutexlock.h +39 -0
  114. data/leveldb/util/options.cc +29 -0
  115. data/leveldb/util/posix_logger.h +98 -0
  116. data/leveldb/util/random.h +59 -0
  117. data/leveldb/util/status.cc +75 -0
  118. data/leveldb/util/testharness.cc +77 -0
  119. data/leveldb/util/testharness.h +138 -0
  120. data/leveldb/util/testutil.cc +51 -0
  121. data/leveldb/util/testutil.h +53 -0
  122. data/lib/leveldb.rb +76 -0
  123. metadata +175 -0
@@ -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
+ }
@@ -0,0 +1,68 @@
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
+ // A filter block is stored near the end of a Table file. It contains
6
+ // filters (e.g., bloom filters) for all data blocks in the table combined
7
+ // into a single filter block.
8
+
9
+ #ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
10
+ #define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
11
+
12
+ #include <stddef.h>
13
+ #include <stdint.h>
14
+ #include <string>
15
+ #include <vector>
16
+ #include "leveldb/slice.h"
17
+ #include "util/hash.h"
18
+
19
+ namespace leveldb {
20
+
21
+ class FilterPolicy;
22
+
23
+ // A FilterBlockBuilder is used to construct all of the filters for a
24
+ // particular Table. It generates a single string which is stored as
25
+ // a special block in the Table.
26
+ //
27
+ // The sequence of calls to FilterBlockBuilder must match the regexp:
28
+ // (StartBlock AddKey*)* Finish
29
+ class FilterBlockBuilder {
30
+ public:
31
+ explicit FilterBlockBuilder(const FilterPolicy*);
32
+
33
+ void StartBlock(uint64_t block_offset);
34
+ void AddKey(const Slice& key);
35
+ Slice Finish();
36
+
37
+ private:
38
+ void GenerateFilter();
39
+
40
+ const FilterPolicy* policy_;
41
+ std::string keys_; // Flattened key contents
42
+ std::vector<size_t> start_; // Starting index in keys_ of each key
43
+ std::string result_; // Filter data computed so far
44
+ std::vector<Slice> tmp_keys_; // policy_->CreateFilter() argument
45
+ std::vector<uint32_t> filter_offsets_;
46
+
47
+ // No copying allowed
48
+ FilterBlockBuilder(const FilterBlockBuilder&);
49
+ void operator=(const FilterBlockBuilder&);
50
+ };
51
+
52
+ class FilterBlockReader {
53
+ public:
54
+ // REQUIRES: "contents" and *policy must stay live while *this is live.
55
+ FilterBlockReader(const FilterPolicy* policy, const Slice& contents);
56
+ bool KeyMayMatch(uint64_t block_offset, const Slice& key);
57
+
58
+ private:
59
+ const FilterPolicy* policy_;
60
+ const char* data_; // Pointer to filter data (at block-start)
61
+ const char* offset_; // Pointer to beginning of offset array (at block-end)
62
+ size_t num_; // Number of entries in offset array
63
+ size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file)
64
+ };
65
+
66
+ }
67
+
68
+ #endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
@@ -0,0 +1,128 @@
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
+ #include "util/hash.h"
10
+ #include "util/logging.h"
11
+ #include "util/testharness.h"
12
+ #include "util/testutil.h"
13
+
14
+ namespace leveldb {
15
+
16
+ // For testing: emit an array with one hash value per key
17
+ class TestHashFilter : public FilterPolicy {
18
+ public:
19
+ virtual const char* Name() const {
20
+ return "TestHashFilter";
21
+ }
22
+
23
+ virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
24
+ for (int i = 0; i < n; i++) {
25
+ uint32_t h = Hash(keys[i].data(), keys[i].size(), 1);
26
+ PutFixed32(dst, h);
27
+ }
28
+ }
29
+
30
+ virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
31
+ uint32_t h = Hash(key.data(), key.size(), 1);
32
+ for (int i = 0; i + 4 <= filter.size(); i += 4) {
33
+ if (h == DecodeFixed32(filter.data() + i)) {
34
+ return true;
35
+ }
36
+ }
37
+ return false;
38
+ }
39
+ };
40
+
41
+ class FilterBlockTest {
42
+ public:
43
+ TestHashFilter policy_;
44
+ };
45
+
46
+ TEST(FilterBlockTest, EmptyBuilder) {
47
+ FilterBlockBuilder builder(&policy_);
48
+ Slice block = builder.Finish();
49
+ ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block));
50
+ FilterBlockReader reader(&policy_, block);
51
+ ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
52
+ ASSERT_TRUE(reader.KeyMayMatch(100000, "foo"));
53
+ }
54
+
55
+ TEST(FilterBlockTest, SingleChunk) {
56
+ FilterBlockBuilder builder(&policy_);
57
+ builder.StartBlock(100);
58
+ builder.AddKey("foo");
59
+ builder.AddKey("bar");
60
+ builder.AddKey("box");
61
+ builder.StartBlock(200);
62
+ builder.AddKey("box");
63
+ builder.StartBlock(300);
64
+ builder.AddKey("hello");
65
+ Slice block = builder.Finish();
66
+ FilterBlockReader reader(&policy_, block);
67
+ ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
68
+ ASSERT_TRUE(reader.KeyMayMatch(100, "bar"));
69
+ ASSERT_TRUE(reader.KeyMayMatch(100, "box"));
70
+ ASSERT_TRUE(reader.KeyMayMatch(100, "hello"));
71
+ ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
72
+ ASSERT_TRUE(! reader.KeyMayMatch(100, "missing"));
73
+ ASSERT_TRUE(! reader.KeyMayMatch(100, "other"));
74
+ }
75
+
76
+ TEST(FilterBlockTest, MultiChunk) {
77
+ FilterBlockBuilder builder(&policy_);
78
+
79
+ // First filter
80
+ builder.StartBlock(0);
81
+ builder.AddKey("foo");
82
+ builder.StartBlock(2000);
83
+ builder.AddKey("bar");
84
+
85
+ // Second filter
86
+ builder.StartBlock(3100);
87
+ builder.AddKey("box");
88
+
89
+ // Third filter is empty
90
+
91
+ // Last filter
92
+ builder.StartBlock(9000);
93
+ builder.AddKey("box");
94
+ builder.AddKey("hello");
95
+
96
+ Slice block = builder.Finish();
97
+ FilterBlockReader reader(&policy_, block);
98
+
99
+ // Check first filter
100
+ ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
101
+ ASSERT_TRUE(reader.KeyMayMatch(2000, "bar"));
102
+ ASSERT_TRUE(! reader.KeyMayMatch(0, "box"));
103
+ ASSERT_TRUE(! reader.KeyMayMatch(0, "hello"));
104
+
105
+ // Check second filter
106
+ ASSERT_TRUE(reader.KeyMayMatch(3100, "box"));
107
+ ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo"));
108
+ ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar"));
109
+ ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello"));
110
+
111
+ // Check third filter (empty)
112
+ ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo"));
113
+ ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar"));
114
+ ASSERT_TRUE(! reader.KeyMayMatch(4100, "box"));
115
+ ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello"));
116
+
117
+ // Check last filter
118
+ ASSERT_TRUE(reader.KeyMayMatch(9000, "box"));
119
+ ASSERT_TRUE(reader.KeyMayMatch(9000, "hello"));
120
+ ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo"));
121
+ ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar"));
122
+ }
123
+
124
+ } // namespace leveldb
125
+
126
+ int main(int argc, char** argv) {
127
+ return leveldb::test::RunAllTests();
128
+ }
@@ -0,0 +1,145 @@
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 "table/format.h"
6
+
7
+ #include "leveldb/env.h"
8
+ #include "port/port.h"
9
+ #include "table/block.h"
10
+ #include "util/coding.h"
11
+ #include "util/crc32c.h"
12
+
13
+ namespace leveldb {
14
+
15
+ void BlockHandle::EncodeTo(std::string* dst) const {
16
+ // Sanity check that all fields have been set
17
+ assert(offset_ != ~static_cast<uint64_t>(0));
18
+ assert(size_ != ~static_cast<uint64_t>(0));
19
+ PutVarint64(dst, offset_);
20
+ PutVarint64(dst, size_);
21
+ }
22
+
23
+ Status BlockHandle::DecodeFrom(Slice* input) {
24
+ if (GetVarint64(input, &offset_) &&
25
+ GetVarint64(input, &size_)) {
26
+ return Status::OK();
27
+ } else {
28
+ return Status::Corruption("bad block handle");
29
+ }
30
+ }
31
+
32
+ void Footer::EncodeTo(std::string* dst) const {
33
+ #ifndef NDEBUG
34
+ const size_t original_size = dst->size();
35
+ #endif
36
+ metaindex_handle_.EncodeTo(dst);
37
+ index_handle_.EncodeTo(dst);
38
+ dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding
39
+ PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));
40
+ PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
41
+ assert(dst->size() == original_size + kEncodedLength);
42
+ }
43
+
44
+ Status Footer::DecodeFrom(Slice* input) {
45
+ const char* magic_ptr = input->data() + kEncodedLength - 8;
46
+ const uint32_t magic_lo = DecodeFixed32(magic_ptr);
47
+ const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
48
+ const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |
49
+ (static_cast<uint64_t>(magic_lo)));
50
+ if (magic != kTableMagicNumber) {
51
+ return Status::InvalidArgument("not an sstable (bad magic number)");
52
+ }
53
+
54
+ Status result = metaindex_handle_.DecodeFrom(input);
55
+ if (result.ok()) {
56
+ result = index_handle_.DecodeFrom(input);
57
+ }
58
+ if (result.ok()) {
59
+ // We skip over any leftover data (just padding for now) in "input"
60
+ const char* end = magic_ptr + 8;
61
+ *input = Slice(end, input->data() + input->size() - end);
62
+ }
63
+ return result;
64
+ }
65
+
66
+ Status ReadBlock(RandomAccessFile* file,
67
+ const ReadOptions& options,
68
+ const BlockHandle& handle,
69
+ BlockContents* result) {
70
+ result->data = Slice();
71
+ result->cachable = false;
72
+ result->heap_allocated = false;
73
+
74
+ // Read the block contents as well as the type/crc footer.
75
+ // See table_builder.cc for the code that built this structure.
76
+ size_t n = static_cast<size_t>(handle.size());
77
+ char* buf = new char[n + kBlockTrailerSize];
78
+ Slice contents;
79
+ Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
80
+ if (!s.ok()) {
81
+ delete[] buf;
82
+ return s;
83
+ }
84
+ if (contents.size() != n + kBlockTrailerSize) {
85
+ delete[] buf;
86
+ return Status::Corruption("truncated block read");
87
+ }
88
+
89
+ // Check the crc of the type and the block contents
90
+ const char* data = contents.data(); // Pointer to where Read put the data
91
+ if (options.verify_checksums) {
92
+ const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
93
+ const uint32_t actual = crc32c::Value(data, n + 1);
94
+ if (actual != crc) {
95
+ delete[] buf;
96
+ s = Status::Corruption("block checksum mismatch");
97
+ return s;
98
+ }
99
+ }
100
+
101
+ switch (data[n]) {
102
+ case kNoCompression:
103
+ if (data != buf) {
104
+ // File implementation gave us pointer to some other data.
105
+ // Use it directly under the assumption that it will be live
106
+ // while the file is open.
107
+ delete[] buf;
108
+ result->data = Slice(data, n);
109
+ result->heap_allocated = false;
110
+ result->cachable = false; // Do not double-cache
111
+ } else {
112
+ result->data = Slice(buf, n);
113
+ result->heap_allocated = true;
114
+ result->cachable = true;
115
+ }
116
+
117
+ // Ok
118
+ break;
119
+ case kSnappyCompression: {
120
+ size_t ulength = 0;
121
+ if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {
122
+ delete[] buf;
123
+ return Status::Corruption("corrupted compressed block contents");
124
+ }
125
+ char* ubuf = new char[ulength];
126
+ if (!port::Snappy_Uncompress(data, n, ubuf)) {
127
+ delete[] buf;
128
+ delete[] ubuf;
129
+ return Status::Corruption("corrupted compressed block contents");
130
+ }
131
+ delete[] buf;
132
+ result->data = Slice(ubuf, ulength);
133
+ result->heap_allocated = true;
134
+ result->cachable = true;
135
+ break;
136
+ }
137
+ default:
138
+ delete[] buf;
139
+ return Status::Corruption("bad block type");
140
+ }
141
+
142
+ return Status::OK();
143
+ }
144
+
145
+ } // namespace leveldb