leveldb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/ext/Rakefile +11 -0
- data/ext/leveldb/LICENSE +27 -0
- data/ext/leveldb/Makefile +206 -0
- data/ext/leveldb/build_config.mk +13 -0
- data/ext/leveldb/db/builder.cc +88 -0
- data/ext/leveldb/db/builder.h +34 -0
- data/ext/leveldb/db/c.cc +595 -0
- data/ext/leveldb/db/c_test.c +390 -0
- data/ext/leveldb/db/corruption_test.cc +359 -0
- data/ext/leveldb/db/db_bench.cc +979 -0
- data/ext/leveldb/db/db_impl.cc +1485 -0
- data/ext/leveldb/db/db_impl.h +203 -0
- data/ext/leveldb/db/db_iter.cc +299 -0
- data/ext/leveldb/db/db_iter.h +26 -0
- data/ext/leveldb/db/db_test.cc +2092 -0
- data/ext/leveldb/db/dbformat.cc +140 -0
- data/ext/leveldb/db/dbformat.h +227 -0
- data/ext/leveldb/db/dbformat_test.cc +112 -0
- data/ext/leveldb/db/filename.cc +139 -0
- data/ext/leveldb/db/filename.h +80 -0
- data/ext/leveldb/db/filename_test.cc +122 -0
- data/ext/leveldb/db/leveldb_main.cc +238 -0
- data/ext/leveldb/db/log_format.h +35 -0
- data/ext/leveldb/db/log_reader.cc +259 -0
- data/ext/leveldb/db/log_reader.h +108 -0
- data/ext/leveldb/db/log_test.cc +500 -0
- data/ext/leveldb/db/log_writer.cc +103 -0
- data/ext/leveldb/db/log_writer.h +48 -0
- data/ext/leveldb/db/memtable.cc +145 -0
- data/ext/leveldb/db/memtable.h +91 -0
- data/ext/leveldb/db/repair.cc +389 -0
- data/ext/leveldb/db/skiplist.h +379 -0
- data/ext/leveldb/db/skiplist_test.cc +378 -0
- data/ext/leveldb/db/snapshot.h +66 -0
- data/ext/leveldb/db/table_cache.cc +121 -0
- data/ext/leveldb/db/table_cache.h +61 -0
- data/ext/leveldb/db/version_edit.cc +266 -0
- data/ext/leveldb/db/version_edit.h +107 -0
- data/ext/leveldb/db/version_edit_test.cc +46 -0
- data/ext/leveldb/db/version_set.cc +1443 -0
- data/ext/leveldb/db/version_set.h +383 -0
- data/ext/leveldb/db/version_set_test.cc +179 -0
- data/ext/leveldb/db/write_batch.cc +147 -0
- data/ext/leveldb/db/write_batch_internal.h +49 -0
- data/ext/leveldb/db/write_batch_test.cc +120 -0
- data/ext/leveldb/doc/bench/db_bench_sqlite3.cc +718 -0
- data/ext/leveldb/doc/bench/db_bench_tree_db.cc +528 -0
- data/ext/leveldb/helpers/memenv/memenv.cc +384 -0
- data/ext/leveldb/helpers/memenv/memenv.h +20 -0
- data/ext/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/ext/leveldb/include/leveldb/c.h +291 -0
- data/ext/leveldb/include/leveldb/cache.h +99 -0
- data/ext/leveldb/include/leveldb/comparator.h +63 -0
- data/ext/leveldb/include/leveldb/db.h +161 -0
- data/ext/leveldb/include/leveldb/env.h +333 -0
- data/ext/leveldb/include/leveldb/filter_policy.h +70 -0
- data/ext/leveldb/include/leveldb/iterator.h +100 -0
- data/ext/leveldb/include/leveldb/options.h +195 -0
- data/ext/leveldb/include/leveldb/slice.h +109 -0
- data/ext/leveldb/include/leveldb/status.h +106 -0
- data/ext/leveldb/include/leveldb/table.h +85 -0
- data/ext/leveldb/include/leveldb/table_builder.h +92 -0
- data/ext/leveldb/include/leveldb/write_batch.h +64 -0
- data/ext/leveldb/issues/issue178_test.cc +92 -0
- data/ext/leveldb/port/atomic_pointer.h +224 -0
- data/ext/leveldb/port/port.h +19 -0
- data/ext/leveldb/port/port_example.h +135 -0
- data/ext/leveldb/port/port_posix.cc +54 -0
- data/ext/leveldb/port/port_posix.h +157 -0
- data/ext/leveldb/port/thread_annotations.h +59 -0
- data/ext/leveldb/port/win/stdint.h +24 -0
- data/ext/leveldb/table/block.cc +268 -0
- data/ext/leveldb/table/block.h +44 -0
- data/ext/leveldb/table/block_builder.cc +109 -0
- data/ext/leveldb/table/block_builder.h +57 -0
- data/ext/leveldb/table/filter_block.cc +111 -0
- data/ext/leveldb/table/filter_block.h +68 -0
- data/ext/leveldb/table/filter_block_test.cc +128 -0
- data/ext/leveldb/table/format.cc +145 -0
- data/ext/leveldb/table/format.h +108 -0
- data/ext/leveldb/table/iterator.cc +67 -0
- data/ext/leveldb/table/iterator_wrapper.h +63 -0
- data/ext/leveldb/table/merger.cc +197 -0
- data/ext/leveldb/table/merger.h +26 -0
- data/ext/leveldb/table/table.cc +275 -0
- data/ext/leveldb/table/table_builder.cc +270 -0
- data/ext/leveldb/table/table_test.cc +868 -0
- data/ext/leveldb/table/two_level_iterator.cc +182 -0
- data/ext/leveldb/table/two_level_iterator.h +34 -0
- data/ext/leveldb/util/arena.cc +68 -0
- data/ext/leveldb/util/arena.h +68 -0
- data/ext/leveldb/util/arena_test.cc +68 -0
- data/ext/leveldb/util/bloom.cc +95 -0
- data/ext/leveldb/util/bloom_test.cc +160 -0
- data/ext/leveldb/util/cache.cc +325 -0
- data/ext/leveldb/util/cache_test.cc +186 -0
- data/ext/leveldb/util/coding.cc +194 -0
- data/ext/leveldb/util/coding.h +104 -0
- data/ext/leveldb/util/coding_test.cc +196 -0
- data/ext/leveldb/util/comparator.cc +81 -0
- data/ext/leveldb/util/crc32c.cc +332 -0
- data/ext/leveldb/util/crc32c.h +45 -0
- data/ext/leveldb/util/crc32c_test.cc +72 -0
- data/ext/leveldb/util/env.cc +96 -0
- data/ext/leveldb/util/env_posix.cc +698 -0
- data/ext/leveldb/util/env_test.cc +104 -0
- data/ext/leveldb/util/filter_policy.cc +11 -0
- data/ext/leveldb/util/hash.cc +52 -0
- data/ext/leveldb/util/hash.h +19 -0
- data/ext/leveldb/util/histogram.cc +139 -0
- data/ext/leveldb/util/histogram.h +42 -0
- data/ext/leveldb/util/logging.cc +81 -0
- data/ext/leveldb/util/logging.h +47 -0
- data/ext/leveldb/util/mutexlock.h +41 -0
- data/ext/leveldb/util/options.cc +29 -0
- data/ext/leveldb/util/posix_logger.h +98 -0
- data/ext/leveldb/util/random.h +59 -0
- data/ext/leveldb/util/status.cc +75 -0
- data/ext/leveldb/util/testharness.cc +77 -0
- data/ext/leveldb/util/testharness.h +138 -0
- data/ext/leveldb/util/testutil.cc +51 -0
- data/ext/leveldb/util/testutil.h +53 -0
- data/lib/leveldb/version.rb +3 -0
- data/lib/leveldb.rb +1006 -0
- metadata +228 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
// Copyright (c) 2013 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
|
+
// Test for issue 178: a manual compaction causes deleted data to reappear.
|
6
|
+
#include <iostream>
|
7
|
+
#include <sstream>
|
8
|
+
#include <cstdlib>
|
9
|
+
|
10
|
+
#include "leveldb/db.h"
|
11
|
+
#include "leveldb/write_batch.h"
|
12
|
+
#include "util/testharness.h"
|
13
|
+
|
14
|
+
namespace {
|
15
|
+
|
16
|
+
const int kNumKeys = 1100000;
|
17
|
+
|
18
|
+
std::string Key1(int i) {
|
19
|
+
char buf[100];
|
20
|
+
snprintf(buf, sizeof(buf), "my_key_%d", i);
|
21
|
+
return buf;
|
22
|
+
}
|
23
|
+
|
24
|
+
std::string Key2(int i) {
|
25
|
+
return Key1(i) + "_xxx";
|
26
|
+
}
|
27
|
+
|
28
|
+
class Issue178 { };
|
29
|
+
|
30
|
+
TEST(Issue178, Test) {
|
31
|
+
// Get rid of any state from an old run.
|
32
|
+
std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test";
|
33
|
+
DestroyDB(dbpath, leveldb::Options());
|
34
|
+
|
35
|
+
// Open database. Disable compression since it affects the creation
|
36
|
+
// of layers and the code below is trying to test against a very
|
37
|
+
// specific scenario.
|
38
|
+
leveldb::DB* db;
|
39
|
+
leveldb::Options db_options;
|
40
|
+
db_options.create_if_missing = true;
|
41
|
+
db_options.compression = leveldb::kNoCompression;
|
42
|
+
ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db));
|
43
|
+
|
44
|
+
// create first key range
|
45
|
+
leveldb::WriteBatch batch;
|
46
|
+
for (size_t i = 0; i < kNumKeys; i++) {
|
47
|
+
batch.Put(Key1(i), "value for range 1 key");
|
48
|
+
}
|
49
|
+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
|
50
|
+
|
51
|
+
// create second key range
|
52
|
+
batch.Clear();
|
53
|
+
for (size_t i = 0; i < kNumKeys; i++) {
|
54
|
+
batch.Put(Key2(i), "value for range 2 key");
|
55
|
+
}
|
56
|
+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
|
57
|
+
|
58
|
+
// delete second key range
|
59
|
+
batch.Clear();
|
60
|
+
for (size_t i = 0; i < kNumKeys; i++) {
|
61
|
+
batch.Delete(Key2(i));
|
62
|
+
}
|
63
|
+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
|
64
|
+
|
65
|
+
// compact database
|
66
|
+
std::string start_key = Key1(0);
|
67
|
+
std::string end_key = Key1(kNumKeys - 1);
|
68
|
+
leveldb::Slice least(start_key.data(), start_key.size());
|
69
|
+
leveldb::Slice greatest(end_key.data(), end_key.size());
|
70
|
+
|
71
|
+
// commenting out the line below causes the example to work correctly
|
72
|
+
db->CompactRange(&least, &greatest);
|
73
|
+
|
74
|
+
// count the keys
|
75
|
+
leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
|
76
|
+
size_t num_keys = 0;
|
77
|
+
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
78
|
+
num_keys++;
|
79
|
+
}
|
80
|
+
delete iter;
|
81
|
+
ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
|
82
|
+
|
83
|
+
// close database
|
84
|
+
delete db;
|
85
|
+
DestroyDB(dbpath, leveldb::Options());
|
86
|
+
}
|
87
|
+
|
88
|
+
} // anonymous namespace
|
89
|
+
|
90
|
+
int main(int argc, char** argv) {
|
91
|
+
return leveldb::test::RunAllTests();
|
92
|
+
}
|
@@ -0,0 +1,224 @@
|
|
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
|
+
// AtomicPointer provides storage for a lock-free pointer.
|
6
|
+
// Platform-dependent implementation of AtomicPointer:
|
7
|
+
// - If the platform provides a cheap barrier, we use it with raw pointers
|
8
|
+
// - If cstdatomic is present (on newer versions of gcc, it is), we use
|
9
|
+
// a cstdatomic-based AtomicPointer. However we prefer the memory
|
10
|
+
// barrier based version, because at least on a gcc 4.4 32-bit build
|
11
|
+
// on linux, we have encountered a buggy <cstdatomic>
|
12
|
+
// implementation. Also, some <cstdatomic> implementations are much
|
13
|
+
// slower than a memory-barrier based implementation (~16ns for
|
14
|
+
// <cstdatomic> based acquire-load vs. ~1ns for a barrier based
|
15
|
+
// acquire-load).
|
16
|
+
// This code is based on atomicops-internals-* in Google's perftools:
|
17
|
+
// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase
|
18
|
+
|
19
|
+
#ifndef PORT_ATOMIC_POINTER_H_
|
20
|
+
#define PORT_ATOMIC_POINTER_H_
|
21
|
+
|
22
|
+
#include <stdint.h>
|
23
|
+
#ifdef LEVELDB_CSTDATOMIC_PRESENT
|
24
|
+
#include <cstdatomic>
|
25
|
+
#endif
|
26
|
+
#ifdef OS_WIN
|
27
|
+
#include <windows.h>
|
28
|
+
#endif
|
29
|
+
#ifdef OS_MACOSX
|
30
|
+
#include <libkern/OSAtomic.h>
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#if defined(_M_X64) || defined(__x86_64__)
|
34
|
+
#define ARCH_CPU_X86_FAMILY 1
|
35
|
+
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
36
|
+
#define ARCH_CPU_X86_FAMILY 1
|
37
|
+
#elif defined(__ARMEL__)
|
38
|
+
#define ARCH_CPU_ARM_FAMILY 1
|
39
|
+
#elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
|
40
|
+
#define ARCH_CPU_PPC_FAMILY 1
|
41
|
+
#endif
|
42
|
+
|
43
|
+
namespace leveldb {
|
44
|
+
namespace port {
|
45
|
+
|
46
|
+
// Define MemoryBarrier() if available
|
47
|
+
// Windows on x86
|
48
|
+
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
|
49
|
+
// windows.h already provides a MemoryBarrier(void) macro
|
50
|
+
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
|
51
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
52
|
+
|
53
|
+
// Gcc on x86
|
54
|
+
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
|
55
|
+
inline void MemoryBarrier() {
|
56
|
+
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
57
|
+
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
58
|
+
__asm__ __volatile__("" : : : "memory");
|
59
|
+
}
|
60
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
61
|
+
|
62
|
+
// Sun Studio
|
63
|
+
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC)
|
64
|
+
inline void MemoryBarrier() {
|
65
|
+
// See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on
|
66
|
+
// this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering.
|
67
|
+
asm volatile("" : : : "memory");
|
68
|
+
}
|
69
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
70
|
+
|
71
|
+
// Mac OS
|
72
|
+
#elif defined(OS_MACOSX)
|
73
|
+
inline void MemoryBarrier() {
|
74
|
+
OSMemoryBarrier();
|
75
|
+
}
|
76
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
77
|
+
|
78
|
+
// ARM Linux
|
79
|
+
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__)
|
80
|
+
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
|
81
|
+
// The Linux ARM kernel provides a highly optimized device-specific memory
|
82
|
+
// barrier function at a fixed memory address that is mapped in every
|
83
|
+
// user-level process.
|
84
|
+
//
|
85
|
+
// This beats using CPU-specific instructions which are, on single-core
|
86
|
+
// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more
|
87
|
+
// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking
|
88
|
+
// shows that the extra function call cost is completely negligible on
|
89
|
+
// multi-core devices.
|
90
|
+
//
|
91
|
+
inline void MemoryBarrier() {
|
92
|
+
(*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)();
|
93
|
+
}
|
94
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
95
|
+
|
96
|
+
// PPC
|
97
|
+
#elif defined(ARCH_CPU_PPC_FAMILY) && defined(__GNUC__)
|
98
|
+
inline void MemoryBarrier() {
|
99
|
+
// TODO for some powerpc expert: is there a cheaper suitable variant?
|
100
|
+
// Perhaps by having separate barriers for acquire and release ops.
|
101
|
+
asm volatile("sync" : : : "memory");
|
102
|
+
}
|
103
|
+
#define LEVELDB_HAVE_MEMORY_BARRIER
|
104
|
+
|
105
|
+
#endif
|
106
|
+
|
107
|
+
// AtomicPointer built using platform-specific MemoryBarrier()
|
108
|
+
#if defined(LEVELDB_HAVE_MEMORY_BARRIER)
|
109
|
+
class AtomicPointer {
|
110
|
+
private:
|
111
|
+
void* rep_;
|
112
|
+
public:
|
113
|
+
AtomicPointer() { }
|
114
|
+
explicit AtomicPointer(void* p) : rep_(p) {}
|
115
|
+
inline void* NoBarrier_Load() const { return rep_; }
|
116
|
+
inline void NoBarrier_Store(void* v) { rep_ = v; }
|
117
|
+
inline void* Acquire_Load() const {
|
118
|
+
void* result = rep_;
|
119
|
+
MemoryBarrier();
|
120
|
+
return result;
|
121
|
+
}
|
122
|
+
inline void Release_Store(void* v) {
|
123
|
+
MemoryBarrier();
|
124
|
+
rep_ = v;
|
125
|
+
}
|
126
|
+
};
|
127
|
+
|
128
|
+
// AtomicPointer based on <cstdatomic>
|
129
|
+
#elif defined(LEVELDB_CSTDATOMIC_PRESENT)
|
130
|
+
class AtomicPointer {
|
131
|
+
private:
|
132
|
+
std::atomic<void*> rep_;
|
133
|
+
public:
|
134
|
+
AtomicPointer() { }
|
135
|
+
explicit AtomicPointer(void* v) : rep_(v) { }
|
136
|
+
inline void* Acquire_Load() const {
|
137
|
+
return rep_.load(std::memory_order_acquire);
|
138
|
+
}
|
139
|
+
inline void Release_Store(void* v) {
|
140
|
+
rep_.store(v, std::memory_order_release);
|
141
|
+
}
|
142
|
+
inline void* NoBarrier_Load() const {
|
143
|
+
return rep_.load(std::memory_order_relaxed);
|
144
|
+
}
|
145
|
+
inline void NoBarrier_Store(void* v) {
|
146
|
+
rep_.store(v, std::memory_order_relaxed);
|
147
|
+
}
|
148
|
+
};
|
149
|
+
|
150
|
+
// Atomic pointer based on sparc memory barriers
|
151
|
+
#elif defined(__sparcv9) && defined(__GNUC__)
|
152
|
+
class AtomicPointer {
|
153
|
+
private:
|
154
|
+
void* rep_;
|
155
|
+
public:
|
156
|
+
AtomicPointer() { }
|
157
|
+
explicit AtomicPointer(void* v) : rep_(v) { }
|
158
|
+
inline void* Acquire_Load() const {
|
159
|
+
void* val;
|
160
|
+
__asm__ __volatile__ (
|
161
|
+
"ldx [%[rep_]], %[val] \n\t"
|
162
|
+
"membar #LoadLoad|#LoadStore \n\t"
|
163
|
+
: [val] "=r" (val)
|
164
|
+
: [rep_] "r" (&rep_)
|
165
|
+
: "memory");
|
166
|
+
return val;
|
167
|
+
}
|
168
|
+
inline void Release_Store(void* v) {
|
169
|
+
__asm__ __volatile__ (
|
170
|
+
"membar #LoadStore|#StoreStore \n\t"
|
171
|
+
"stx %[v], [%[rep_]] \n\t"
|
172
|
+
:
|
173
|
+
: [rep_] "r" (&rep_), [v] "r" (v)
|
174
|
+
: "memory");
|
175
|
+
}
|
176
|
+
inline void* NoBarrier_Load() const { return rep_; }
|
177
|
+
inline void NoBarrier_Store(void* v) { rep_ = v; }
|
178
|
+
};
|
179
|
+
|
180
|
+
// Atomic pointer based on ia64 acq/rel
|
181
|
+
#elif defined(__ia64) && defined(__GNUC__)
|
182
|
+
class AtomicPointer {
|
183
|
+
private:
|
184
|
+
void* rep_;
|
185
|
+
public:
|
186
|
+
AtomicPointer() { }
|
187
|
+
explicit AtomicPointer(void* v) : rep_(v) { }
|
188
|
+
inline void* Acquire_Load() const {
|
189
|
+
void* val ;
|
190
|
+
__asm__ __volatile__ (
|
191
|
+
"ld8.acq %[val] = [%[rep_]] \n\t"
|
192
|
+
: [val] "=r" (val)
|
193
|
+
: [rep_] "r" (&rep_)
|
194
|
+
: "memory"
|
195
|
+
);
|
196
|
+
return val;
|
197
|
+
}
|
198
|
+
inline void Release_Store(void* v) {
|
199
|
+
__asm__ __volatile__ (
|
200
|
+
"st8.rel [%[rep_]] = %[v] \n\t"
|
201
|
+
:
|
202
|
+
: [rep_] "r" (&rep_), [v] "r" (v)
|
203
|
+
: "memory"
|
204
|
+
);
|
205
|
+
}
|
206
|
+
inline void* NoBarrier_Load() const { return rep_; }
|
207
|
+
inline void NoBarrier_Store(void* v) { rep_ = v; }
|
208
|
+
};
|
209
|
+
|
210
|
+
// We have neither MemoryBarrier(), nor <cstdatomic>
|
211
|
+
#else
|
212
|
+
#error Please implement AtomicPointer for this platform.
|
213
|
+
|
214
|
+
#endif
|
215
|
+
|
216
|
+
#undef LEVELDB_HAVE_MEMORY_BARRIER
|
217
|
+
#undef ARCH_CPU_X86_FAMILY
|
218
|
+
#undef ARCH_CPU_ARM_FAMILY
|
219
|
+
#undef ARCH_CPU_PPC_FAMILY
|
220
|
+
|
221
|
+
} // namespace port
|
222
|
+
} // namespace leveldb
|
223
|
+
|
224
|
+
#endif // PORT_ATOMIC_POINTER_H_
|
@@ -0,0 +1,19 @@
|
|
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_PORT_PORT_H_
|
6
|
+
#define STORAGE_LEVELDB_PORT_PORT_H_
|
7
|
+
|
8
|
+
#include <string.h>
|
9
|
+
|
10
|
+
// Include the appropriate platform specific file below. If you are
|
11
|
+
// porting to a new platform, see "port_example.h" for documentation
|
12
|
+
// of what the new port_<platform>.h file must provide.
|
13
|
+
#if defined(LEVELDB_PLATFORM_POSIX)
|
14
|
+
# include "port/port_posix.h"
|
15
|
+
#elif defined(LEVELDB_PLATFORM_CHROMIUM)
|
16
|
+
# include "port/port_chromium.h"
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#endif // STORAGE_LEVELDB_PORT_PORT_H_
|
@@ -0,0 +1,135 @@
|
|
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
|
+
// This file contains the specification, but not the implementations,
|
6
|
+
// of the types/operations/etc. that should be defined by a platform
|
7
|
+
// specific port_<platform>.h file. Use this file as a reference for
|
8
|
+
// how to port this package to a new platform.
|
9
|
+
|
10
|
+
#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
|
11
|
+
#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
|
12
|
+
|
13
|
+
namespace leveldb {
|
14
|
+
namespace port {
|
15
|
+
|
16
|
+
// TODO(jorlow): Many of these belong more in the environment class rather than
|
17
|
+
// here. We should try moving them and see if it affects perf.
|
18
|
+
|
19
|
+
// The following boolean constant must be true on a little-endian machine
|
20
|
+
// and false otherwise.
|
21
|
+
static const bool kLittleEndian = true /* or some other expression */;
|
22
|
+
|
23
|
+
// ------------------ Threading -------------------
|
24
|
+
|
25
|
+
// A Mutex represents an exclusive lock.
|
26
|
+
class Mutex {
|
27
|
+
public:
|
28
|
+
Mutex();
|
29
|
+
~Mutex();
|
30
|
+
|
31
|
+
// Lock the mutex. Waits until other lockers have exited.
|
32
|
+
// Will deadlock if the mutex is already locked by this thread.
|
33
|
+
void Lock();
|
34
|
+
|
35
|
+
// Unlock the mutex.
|
36
|
+
// REQUIRES: This mutex was locked by this thread.
|
37
|
+
void Unlock();
|
38
|
+
|
39
|
+
// Optionally crash if this thread does not hold this mutex.
|
40
|
+
// The implementation must be fast, especially if NDEBUG is
|
41
|
+
// defined. The implementation is allowed to skip all checks.
|
42
|
+
void AssertHeld();
|
43
|
+
};
|
44
|
+
|
45
|
+
class CondVar {
|
46
|
+
public:
|
47
|
+
explicit CondVar(Mutex* mu);
|
48
|
+
~CondVar();
|
49
|
+
|
50
|
+
// Atomically release *mu and block on this condition variable until
|
51
|
+
// either a call to SignalAll(), or a call to Signal() that picks
|
52
|
+
// this thread to wakeup.
|
53
|
+
// REQUIRES: this thread holds *mu
|
54
|
+
void Wait();
|
55
|
+
|
56
|
+
// If there are some threads waiting, wake up at least one of them.
|
57
|
+
void Signal();
|
58
|
+
|
59
|
+
// Wake up all waiting threads.
|
60
|
+
void SignallAll();
|
61
|
+
};
|
62
|
+
|
63
|
+
// Thread-safe initialization.
|
64
|
+
// Used as follows:
|
65
|
+
// static port::OnceType init_control = LEVELDB_ONCE_INIT;
|
66
|
+
// static void Initializer() { ... do something ...; }
|
67
|
+
// ...
|
68
|
+
// port::InitOnce(&init_control, &Initializer);
|
69
|
+
typedef intptr_t OnceType;
|
70
|
+
#define LEVELDB_ONCE_INIT 0
|
71
|
+
extern void InitOnce(port::OnceType*, void (*initializer)());
|
72
|
+
|
73
|
+
// A type that holds a pointer that can be read or written atomically
|
74
|
+
// (i.e., without word-tearing.)
|
75
|
+
class AtomicPointer {
|
76
|
+
private:
|
77
|
+
intptr_t rep_;
|
78
|
+
public:
|
79
|
+
// Initialize to arbitrary value
|
80
|
+
AtomicPointer();
|
81
|
+
|
82
|
+
// Initialize to hold v
|
83
|
+
explicit AtomicPointer(void* v) : rep_(v) { }
|
84
|
+
|
85
|
+
// Read and return the stored pointer with the guarantee that no
|
86
|
+
// later memory access (read or write) by this thread can be
|
87
|
+
// reordered ahead of this read.
|
88
|
+
void* Acquire_Load() const;
|
89
|
+
|
90
|
+
// Set v as the stored pointer with the guarantee that no earlier
|
91
|
+
// memory access (read or write) by this thread can be reordered
|
92
|
+
// after this store.
|
93
|
+
void Release_Store(void* v);
|
94
|
+
|
95
|
+
// Read the stored pointer with no ordering guarantees.
|
96
|
+
void* NoBarrier_Load() const;
|
97
|
+
|
98
|
+
// Set va as the stored pointer with no ordering guarantees.
|
99
|
+
void NoBarrier_Store(void* v);
|
100
|
+
};
|
101
|
+
|
102
|
+
// ------------------ Compression -------------------
|
103
|
+
|
104
|
+
// Store the snappy compression of "input[0,input_length-1]" in *output.
|
105
|
+
// Returns false if snappy is not supported by this port.
|
106
|
+
extern bool Snappy_Compress(const char* input, size_t input_length,
|
107
|
+
std::string* output);
|
108
|
+
|
109
|
+
// If input[0,input_length-1] looks like a valid snappy compressed
|
110
|
+
// buffer, store the size of the uncompressed data in *result and
|
111
|
+
// return true. Else return false.
|
112
|
+
extern bool Snappy_GetUncompressedLength(const char* input, size_t length,
|
113
|
+
size_t* result);
|
114
|
+
|
115
|
+
// Attempt to snappy uncompress input[0,input_length-1] into *output.
|
116
|
+
// Returns true if successful, false if the input is invalid lightweight
|
117
|
+
// compressed data.
|
118
|
+
//
|
119
|
+
// REQUIRES: at least the first "n" bytes of output[] must be writable
|
120
|
+
// where "n" is the result of a successful call to
|
121
|
+
// Snappy_GetUncompressedLength.
|
122
|
+
extern bool Snappy_Uncompress(const char* input_data, size_t input_length,
|
123
|
+
char* output);
|
124
|
+
|
125
|
+
// ------------------ Miscellaneous -------------------
|
126
|
+
|
127
|
+
// If heap profiling is not supported, returns false.
|
128
|
+
// Else repeatedly calls (*func)(arg, data, n) and then returns true.
|
129
|
+
// The concatenation of all "data[0,n-1]" fragments is the heap profile.
|
130
|
+
extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg);
|
131
|
+
|
132
|
+
} // namespace port
|
133
|
+
} // namespace leveldb
|
134
|
+
|
135
|
+
#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_
|
@@ -0,0 +1,54 @@
|
|
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 "port/port_posix.h"
|
6
|
+
|
7
|
+
#include <cstdlib>
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include "util/logging.h"
|
11
|
+
|
12
|
+
namespace leveldb {
|
13
|
+
namespace port {
|
14
|
+
|
15
|
+
static void PthreadCall(const char* label, int result) {
|
16
|
+
if (result != 0) {
|
17
|
+
fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
|
18
|
+
abort();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); }
|
23
|
+
|
24
|
+
Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }
|
25
|
+
|
26
|
+
void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }
|
27
|
+
|
28
|
+
void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }
|
29
|
+
|
30
|
+
CondVar::CondVar(Mutex* mu)
|
31
|
+
: mu_(mu) {
|
32
|
+
PthreadCall("init cv", pthread_cond_init(&cv_, NULL));
|
33
|
+
}
|
34
|
+
|
35
|
+
CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }
|
36
|
+
|
37
|
+
void CondVar::Wait() {
|
38
|
+
PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
|
39
|
+
}
|
40
|
+
|
41
|
+
void CondVar::Signal() {
|
42
|
+
PthreadCall("signal", pthread_cond_signal(&cv_));
|
43
|
+
}
|
44
|
+
|
45
|
+
void CondVar::SignalAll() {
|
46
|
+
PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
|
47
|
+
}
|
48
|
+
|
49
|
+
void InitOnce(OnceType* once, void (*initializer)()) {
|
50
|
+
PthreadCall("once", pthread_once(once, initializer));
|
51
|
+
}
|
52
|
+
|
53
|
+
} // namespace port
|
54
|
+
} // namespace leveldb
|
@@ -0,0 +1,157 @@
|
|
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
|
+
// See port_example.h for documentation for the following types/functions.
|
6
|
+
|
7
|
+
#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|
8
|
+
#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|
9
|
+
|
10
|
+
#undef PLATFORM_IS_LITTLE_ENDIAN
|
11
|
+
#if defined(OS_MACOSX)
|
12
|
+
#include <machine/endian.h>
|
13
|
+
#if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER)
|
14
|
+
#define PLATFORM_IS_LITTLE_ENDIAN \
|
15
|
+
(__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN)
|
16
|
+
#endif
|
17
|
+
#elif defined(OS_SOLARIS)
|
18
|
+
#include <sys/isa_defs.h>
|
19
|
+
#ifdef _LITTLE_ENDIAN
|
20
|
+
#define PLATFORM_IS_LITTLE_ENDIAN true
|
21
|
+
#else
|
22
|
+
#define PLATFORM_IS_LITTLE_ENDIAN false
|
23
|
+
#endif
|
24
|
+
#elif defined(OS_FREEBSD)
|
25
|
+
#include <sys/types.h>
|
26
|
+
#include <sys/endian.h>
|
27
|
+
#define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
28
|
+
#elif defined(OS_OPENBSD) || defined(OS_NETBSD) ||\
|
29
|
+
defined(OS_DRAGONFLYBSD)
|
30
|
+
#include <sys/types.h>
|
31
|
+
#include <sys/endian.h>
|
32
|
+
#elif defined(OS_HPUX)
|
33
|
+
#define PLATFORM_IS_LITTLE_ENDIAN false
|
34
|
+
#elif defined(OS_ANDROID)
|
35
|
+
// Due to a bug in the NDK x86 <sys/endian.h> definition,
|
36
|
+
// _BYTE_ORDER must be used instead of __BYTE_ORDER on Android.
|
37
|
+
// See http://code.google.com/p/android/issues/detail?id=39824
|
38
|
+
#include <endian.h>
|
39
|
+
#define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
40
|
+
#else
|
41
|
+
#include <endian.h>
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#include <pthread.h>
|
45
|
+
#ifdef SNAPPY
|
46
|
+
#include <snappy.h>
|
47
|
+
#endif
|
48
|
+
#include <stdint.h>
|
49
|
+
#include <string>
|
50
|
+
#include "port/atomic_pointer.h"
|
51
|
+
|
52
|
+
#ifndef PLATFORM_IS_LITTLE_ENDIAN
|
53
|
+
#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
|
54
|
+
#endif
|
55
|
+
|
56
|
+
#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\
|
57
|
+
defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\
|
58
|
+
defined(OS_ANDROID) || defined(OS_HPUX)
|
59
|
+
// Use fread/fwrite/fflush on platforms without _unlocked variants
|
60
|
+
#define fread_unlocked fread
|
61
|
+
#define fwrite_unlocked fwrite
|
62
|
+
#define fflush_unlocked fflush
|
63
|
+
#endif
|
64
|
+
|
65
|
+
#if defined(OS_MACOSX) || defined(OS_FREEBSD) ||\
|
66
|
+
defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD)
|
67
|
+
// Use fsync() on platforms without fdatasync()
|
68
|
+
#define fdatasync fsync
|
69
|
+
#endif
|
70
|
+
|
71
|
+
#if defined(OS_ANDROID) && __ANDROID_API__ < 9
|
72
|
+
// fdatasync() was only introduced in API level 9 on Android. Use fsync()
|
73
|
+
// when targetting older platforms.
|
74
|
+
#define fdatasync fsync
|
75
|
+
#endif
|
76
|
+
|
77
|
+
namespace leveldb {
|
78
|
+
namespace port {
|
79
|
+
|
80
|
+
static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN;
|
81
|
+
#undef PLATFORM_IS_LITTLE_ENDIAN
|
82
|
+
|
83
|
+
class CondVar;
|
84
|
+
|
85
|
+
class Mutex {
|
86
|
+
public:
|
87
|
+
Mutex();
|
88
|
+
~Mutex();
|
89
|
+
|
90
|
+
void Lock();
|
91
|
+
void Unlock();
|
92
|
+
void AssertHeld() { }
|
93
|
+
|
94
|
+
private:
|
95
|
+
friend class CondVar;
|
96
|
+
pthread_mutex_t mu_;
|
97
|
+
|
98
|
+
// No copying
|
99
|
+
Mutex(const Mutex&);
|
100
|
+
void operator=(const Mutex&);
|
101
|
+
};
|
102
|
+
|
103
|
+
class CondVar {
|
104
|
+
public:
|
105
|
+
explicit CondVar(Mutex* mu);
|
106
|
+
~CondVar();
|
107
|
+
void Wait();
|
108
|
+
void Signal();
|
109
|
+
void SignalAll();
|
110
|
+
private:
|
111
|
+
pthread_cond_t cv_;
|
112
|
+
Mutex* mu_;
|
113
|
+
};
|
114
|
+
|
115
|
+
typedef pthread_once_t OnceType;
|
116
|
+
#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
|
117
|
+
extern void InitOnce(OnceType* once, void (*initializer)());
|
118
|
+
|
119
|
+
inline bool Snappy_Compress(const char* input, size_t length,
|
120
|
+
::std::string* output) {
|
121
|
+
#ifdef SNAPPY
|
122
|
+
output->resize(snappy::MaxCompressedLength(length));
|
123
|
+
size_t outlen;
|
124
|
+
snappy::RawCompress(input, length, &(*output)[0], &outlen);
|
125
|
+
output->resize(outlen);
|
126
|
+
return true;
|
127
|
+
#endif
|
128
|
+
|
129
|
+
return false;
|
130
|
+
}
|
131
|
+
|
132
|
+
inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
|
133
|
+
size_t* result) {
|
134
|
+
#ifdef SNAPPY
|
135
|
+
return snappy::GetUncompressedLength(input, length, result);
|
136
|
+
#else
|
137
|
+
return false;
|
138
|
+
#endif
|
139
|
+
}
|
140
|
+
|
141
|
+
inline bool Snappy_Uncompress(const char* input, size_t length,
|
142
|
+
char* output) {
|
143
|
+
#ifdef SNAPPY
|
144
|
+
return snappy::RawUncompress(input, length, output);
|
145
|
+
#else
|
146
|
+
return false;
|
147
|
+
#endif
|
148
|
+
}
|
149
|
+
|
150
|
+
inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
|
151
|
+
return false;
|
152
|
+
}
|
153
|
+
|
154
|
+
} // namespace port
|
155
|
+
} // namespace leveldb
|
156
|
+
|
157
|
+
#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_
|