leveldb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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_
|