filiptepper-leveldb-ruby 0.14
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.
- data/LICENSE +24 -0
- data/README +72 -0
- data/ext/leveldb/extconf.rb +14 -0
- data/ext/leveldb/leveldb.cc +530 -0
- data/ext/leveldb/platform.rb +83 -0
- data/leveldb/Makefile +191 -0
- data/leveldb/build_detect_platform +160 -0
- data/leveldb/db/builder.cc +88 -0
- data/leveldb/db/builder.h +34 -0
- data/leveldb/db/c.cc +581 -0
- data/leveldb/db/corruption_test.cc +359 -0
- data/leveldb/db/db_bench.cc +970 -0
- data/leveldb/db/db_impl.cc +1448 -0
- data/leveldb/db/db_impl.h +194 -0
- data/leveldb/db/db_iter.cc +299 -0
- data/leveldb/db/db_iter.h +26 -0
- data/leveldb/db/db_test.cc +1901 -0
- data/leveldb/db/dbformat.cc +140 -0
- data/leveldb/db/dbformat.h +227 -0
- data/leveldb/db/dbformat_test.cc +112 -0
- data/leveldb/db/filename.cc +139 -0
- data/leveldb/db/filename.h +80 -0
- data/leveldb/db/filename_test.cc +122 -0
- data/leveldb/db/log_format.h +35 -0
- data/leveldb/db/log_reader.cc +259 -0
- data/leveldb/db/log_reader.h +108 -0
- data/leveldb/db/log_test.cc +500 -0
- data/leveldb/db/log_writer.cc +103 -0
- data/leveldb/db/log_writer.h +48 -0
- data/leveldb/db/memtable.cc +145 -0
- data/leveldb/db/memtable.h +91 -0
- data/leveldb/db/repair.cc +389 -0
- data/leveldb/db/skiplist.h +379 -0
- data/leveldb/db/skiplist_test.cc +378 -0
- data/leveldb/db/snapshot.h +66 -0
- data/leveldb/db/table_cache.cc +121 -0
- data/leveldb/db/table_cache.h +61 -0
- data/leveldb/db/version_edit.cc +266 -0
- data/leveldb/db/version_edit.h +107 -0
- data/leveldb/db/version_edit_test.cc +46 -0
- data/leveldb/db/version_set.cc +1402 -0
- data/leveldb/db/version_set.h +370 -0
- data/leveldb/db/version_set_test.cc +179 -0
- data/leveldb/db/write_batch.cc +147 -0
- data/leveldb/db/write_batch_internal.h +49 -0
- data/leveldb/db/write_batch_test.cc +120 -0
- data/leveldb/helpers/memenv/memenv.cc +374 -0
- data/leveldb/helpers/memenv/memenv.h +20 -0
- data/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/leveldb/include/leveldb/c.h +275 -0
- data/leveldb/include/leveldb/cache.h +99 -0
- data/leveldb/include/leveldb/comparator.h +63 -0
- data/leveldb/include/leveldb/db.h +161 -0
- data/leveldb/include/leveldb/env.h +323 -0
- data/leveldb/include/leveldb/filter_policy.h +70 -0
- data/leveldb/include/leveldb/iterator.h +100 -0
- data/leveldb/include/leveldb/options.h +195 -0
- data/leveldb/include/leveldb/slice.h +109 -0
- data/leveldb/include/leveldb/status.h +106 -0
- data/leveldb/include/leveldb/table.h +85 -0
- data/leveldb/include/leveldb/table_builder.h +92 -0
- data/leveldb/include/leveldb/write_batch.h +64 -0
- data/leveldb/port/atomic_pointer.h +144 -0
- data/leveldb/port/port.h +21 -0
- data/leveldb/port/port_android.cc +64 -0
- data/leveldb/port/port_android.h +159 -0
- data/leveldb/port/port_example.h +125 -0
- data/leveldb/port/port_posix.cc +50 -0
- data/leveldb/port/port_posix.h +129 -0
- data/leveldb/port/win/stdint.h +24 -0
- data/leveldb/table/block.cc +267 -0
- data/leveldb/table/block.h +44 -0
- data/leveldb/table/block_builder.cc +109 -0
- data/leveldb/table/block_builder.h +57 -0
- data/leveldb/table/filter_block.cc +111 -0
- data/leveldb/table/filter_block.h +68 -0
- data/leveldb/table/filter_block_test.cc +128 -0
- data/leveldb/table/format.cc +145 -0
- data/leveldb/table/format.h +108 -0
- data/leveldb/table/iterator.cc +67 -0
- data/leveldb/table/iterator_wrapper.h +63 -0
- data/leveldb/table/merger.cc +197 -0
- data/leveldb/table/merger.h +26 -0
- data/leveldb/table/table.cc +276 -0
- data/leveldb/table/table_builder.cc +270 -0
- data/leveldb/table/table_test.cc +838 -0
- data/leveldb/table/two_level_iterator.cc +182 -0
- data/leveldb/table/two_level_iterator.h +34 -0
- data/leveldb/util/arena.cc +68 -0
- data/leveldb/util/arena.h +68 -0
- data/leveldb/util/arena_test.cc +68 -0
- data/leveldb/util/bloom.cc +95 -0
- data/leveldb/util/bloom_test.cc +159 -0
- data/leveldb/util/cache.cc +328 -0
- data/leveldb/util/cache_test.cc +186 -0
- data/leveldb/util/coding.cc +194 -0
- data/leveldb/util/coding.h +104 -0
- data/leveldb/util/coding_test.cc +173 -0
- data/leveldb/util/comparator.cc +76 -0
- data/leveldb/util/crc32c.cc +332 -0
- data/leveldb/util/crc32c.h +45 -0
- data/leveldb/util/crc32c_test.cc +72 -0
- data/leveldb/util/env.cc +96 -0
- data/leveldb/util/env_posix.cc +609 -0
- data/leveldb/util/env_test.cc +104 -0
- data/leveldb/util/filter_policy.cc +11 -0
- data/leveldb/util/hash.cc +45 -0
- data/leveldb/util/hash.h +19 -0
- data/leveldb/util/histogram.cc +139 -0
- data/leveldb/util/histogram.h +42 -0
- data/leveldb/util/logging.cc +81 -0
- data/leveldb/util/logging.h +47 -0
- data/leveldb/util/mutexlock.h +39 -0
- data/leveldb/util/options.cc +29 -0
- data/leveldb/util/posix_logger.h +98 -0
- data/leveldb/util/random.h +59 -0
- data/leveldb/util/status.cc +75 -0
- data/leveldb/util/testharness.cc +77 -0
- data/leveldb/util/testharness.h +138 -0
- data/leveldb/util/testutil.cc +51 -0
- data/leveldb/util/testutil.h +53 -0
- data/lib/leveldb.rb +76 -0
- metadata +175 -0
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
// Must not be included from any .h files to avoid polluting the namespace
|
|
6
|
+
// with macros.
|
|
7
|
+
|
|
8
|
+
#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_
|
|
9
|
+
#define STORAGE_LEVELDB_UTIL_LOGGING_H_
|
|
10
|
+
|
|
11
|
+
#include <stdio.h>
|
|
12
|
+
#include <stdint.h>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include "port/port.h"
|
|
15
|
+
|
|
16
|
+
namespace leveldb {
|
|
17
|
+
|
|
18
|
+
class Slice;
|
|
19
|
+
class WritableFile;
|
|
20
|
+
|
|
21
|
+
// Append a human-readable printout of "num" to *str
|
|
22
|
+
extern void AppendNumberTo(std::string* str, uint64_t num);
|
|
23
|
+
|
|
24
|
+
// Append a human-readable printout of "value" to *str.
|
|
25
|
+
// Escapes any non-printable characters found in "value".
|
|
26
|
+
extern void AppendEscapedStringTo(std::string* str, const Slice& value);
|
|
27
|
+
|
|
28
|
+
// Return a human-readable printout of "num"
|
|
29
|
+
extern std::string NumberToString(uint64_t num);
|
|
30
|
+
|
|
31
|
+
// Return a human-readable version of "value".
|
|
32
|
+
// Escapes any non-printable characters found in "value".
|
|
33
|
+
extern std::string EscapeString(const Slice& value);
|
|
34
|
+
|
|
35
|
+
// If *in starts with "c", advances *in past the first character and
|
|
36
|
+
// returns true. Otherwise, returns false.
|
|
37
|
+
extern bool ConsumeChar(Slice* in, char c);
|
|
38
|
+
|
|
39
|
+
// Parse a human-readable number from "*in" into *value. On success,
|
|
40
|
+
// advances "*in" past the consumed number and sets "*val" to the
|
|
41
|
+
// numeric value. Otherwise, returns false and leaves *in in an
|
|
42
|
+
// unspecified state.
|
|
43
|
+
extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val);
|
|
44
|
+
|
|
45
|
+
} // namespace leveldb
|
|
46
|
+
|
|
47
|
+
#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_
|
|
@@ -0,0 +1,39 @@
|
|
|
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_UTIL_MUTEXLOCK_H_
|
|
6
|
+
#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
|
|
7
|
+
|
|
8
|
+
#include "port/port.h"
|
|
9
|
+
|
|
10
|
+
namespace leveldb {
|
|
11
|
+
|
|
12
|
+
// Helper class that locks a mutex on construction and unlocks the mutex when
|
|
13
|
+
// the destructor of the MutexLock object is invoked.
|
|
14
|
+
//
|
|
15
|
+
// Typical usage:
|
|
16
|
+
//
|
|
17
|
+
// void MyClass::MyMethod() {
|
|
18
|
+
// MutexLock l(&mu_); // mu_ is an instance variable
|
|
19
|
+
// ... some complex code, possibly with multiple return paths ...
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
class MutexLock {
|
|
23
|
+
public:
|
|
24
|
+
explicit MutexLock(port::Mutex *mu) : mu_(mu) {
|
|
25
|
+
this->mu_->Lock();
|
|
26
|
+
}
|
|
27
|
+
~MutexLock() { this->mu_->Unlock(); }
|
|
28
|
+
|
|
29
|
+
private:
|
|
30
|
+
port::Mutex *const mu_;
|
|
31
|
+
// No copying allowed
|
|
32
|
+
MutexLock(const MutexLock&);
|
|
33
|
+
void operator=(const MutexLock&);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
} // namespace leveldb
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
|
|
@@ -0,0 +1,29 @@
|
|
|
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 "leveldb/options.h"
|
|
6
|
+
|
|
7
|
+
#include "leveldb/comparator.h"
|
|
8
|
+
#include "leveldb/env.h"
|
|
9
|
+
|
|
10
|
+
namespace leveldb {
|
|
11
|
+
|
|
12
|
+
Options::Options()
|
|
13
|
+
: comparator(BytewiseComparator()),
|
|
14
|
+
create_if_missing(false),
|
|
15
|
+
error_if_exists(false),
|
|
16
|
+
paranoid_checks(false),
|
|
17
|
+
env(Env::Default()),
|
|
18
|
+
info_log(NULL),
|
|
19
|
+
write_buffer_size(4<<20),
|
|
20
|
+
max_open_files(1000),
|
|
21
|
+
block_cache(NULL),
|
|
22
|
+
block_size(4096),
|
|
23
|
+
block_restart_interval(16),
|
|
24
|
+
compression(kSnappyCompression),
|
|
25
|
+
filter_policy(NULL) {
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
} // namespace leveldb
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
// Logger implementation that can be shared by all environments
|
|
6
|
+
// where enough posix functionality is available.
|
|
7
|
+
|
|
8
|
+
#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
|
|
9
|
+
#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
|
|
10
|
+
|
|
11
|
+
#include <algorithm>
|
|
12
|
+
#include <stdio.h>
|
|
13
|
+
#include <sys/time.h>
|
|
14
|
+
#include <time.h>
|
|
15
|
+
#include "leveldb/env.h"
|
|
16
|
+
|
|
17
|
+
namespace leveldb {
|
|
18
|
+
|
|
19
|
+
class PosixLogger : public Logger {
|
|
20
|
+
private:
|
|
21
|
+
FILE* file_;
|
|
22
|
+
uint64_t (*gettid_)(); // Return the thread id for the current thread
|
|
23
|
+
public:
|
|
24
|
+
PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
|
|
25
|
+
virtual ~PosixLogger() {
|
|
26
|
+
fclose(file_);
|
|
27
|
+
}
|
|
28
|
+
virtual void Logv(const char* format, va_list ap) {
|
|
29
|
+
const uint64_t thread_id = (*gettid_)();
|
|
30
|
+
|
|
31
|
+
// We try twice: the first time with a fixed-size stack allocated buffer,
|
|
32
|
+
// and the second time with a much larger dynamically allocated buffer.
|
|
33
|
+
char buffer[500];
|
|
34
|
+
for (int iter = 0; iter < 2; iter++) {
|
|
35
|
+
char* base;
|
|
36
|
+
int bufsize;
|
|
37
|
+
if (iter == 0) {
|
|
38
|
+
bufsize = sizeof(buffer);
|
|
39
|
+
base = buffer;
|
|
40
|
+
} else {
|
|
41
|
+
bufsize = 30000;
|
|
42
|
+
base = new char[bufsize];
|
|
43
|
+
}
|
|
44
|
+
char* p = base;
|
|
45
|
+
char* limit = base + bufsize;
|
|
46
|
+
|
|
47
|
+
struct timeval now_tv;
|
|
48
|
+
gettimeofday(&now_tv, NULL);
|
|
49
|
+
const time_t seconds = now_tv.tv_sec;
|
|
50
|
+
struct tm t;
|
|
51
|
+
localtime_r(&seconds, &t);
|
|
52
|
+
p += snprintf(p, limit - p,
|
|
53
|
+
"%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
|
|
54
|
+
t.tm_year + 1900,
|
|
55
|
+
t.tm_mon + 1,
|
|
56
|
+
t.tm_mday,
|
|
57
|
+
t.tm_hour,
|
|
58
|
+
t.tm_min,
|
|
59
|
+
t.tm_sec,
|
|
60
|
+
static_cast<int>(now_tv.tv_usec),
|
|
61
|
+
static_cast<long long unsigned int>(thread_id));
|
|
62
|
+
|
|
63
|
+
// Print the message
|
|
64
|
+
if (p < limit) {
|
|
65
|
+
va_list backup_ap;
|
|
66
|
+
va_copy(backup_ap, ap);
|
|
67
|
+
p += vsnprintf(p, limit - p, format, backup_ap);
|
|
68
|
+
va_end(backup_ap);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Truncate to available space if necessary
|
|
72
|
+
if (p >= limit) {
|
|
73
|
+
if (iter == 0) {
|
|
74
|
+
continue; // Try again with larger buffer
|
|
75
|
+
} else {
|
|
76
|
+
p = limit - 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Add newline if necessary
|
|
81
|
+
if (p == base || p[-1] != '\n') {
|
|
82
|
+
*p++ = '\n';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
assert(p <= limit);
|
|
86
|
+
fwrite(base, 1, p - base, file_);
|
|
87
|
+
fflush(file_);
|
|
88
|
+
if (base != buffer) {
|
|
89
|
+
delete[] base;
|
|
90
|
+
}
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
} // namespace leveldb
|
|
97
|
+
|
|
98
|
+
#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
|
|
@@ -0,0 +1,59 @@
|
|
|
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_UTIL_RANDOM_H_
|
|
6
|
+
#define STORAGE_LEVELDB_UTIL_RANDOM_H_
|
|
7
|
+
|
|
8
|
+
#include <stdint.h>
|
|
9
|
+
|
|
10
|
+
namespace leveldb {
|
|
11
|
+
|
|
12
|
+
// A very simple random number generator. Not especially good at
|
|
13
|
+
// generating truly random bits, but good enough for our needs in this
|
|
14
|
+
// package.
|
|
15
|
+
class Random {
|
|
16
|
+
private:
|
|
17
|
+
uint32_t seed_;
|
|
18
|
+
public:
|
|
19
|
+
explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { }
|
|
20
|
+
uint32_t Next() {
|
|
21
|
+
static const uint32_t M = 2147483647L; // 2^31-1
|
|
22
|
+
static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0
|
|
23
|
+
// We are computing
|
|
24
|
+
// seed_ = (seed_ * A) % M, where M = 2^31-1
|
|
25
|
+
//
|
|
26
|
+
// seed_ must not be zero or M, or else all subsequent computed values
|
|
27
|
+
// will be zero or M respectively. For all other values, seed_ will end
|
|
28
|
+
// up cycling through every number in [1,M-1]
|
|
29
|
+
uint64_t product = seed_ * A;
|
|
30
|
+
|
|
31
|
+
// Compute (product % M) using the fact that ((x << 31) % M) == x.
|
|
32
|
+
seed_ = static_cast<uint32_t>((product >> 31) + (product & M));
|
|
33
|
+
// The first reduction may overflow by 1 bit, so we may need to
|
|
34
|
+
// repeat. mod == M is not possible; using > allows the faster
|
|
35
|
+
// sign-bit-based test.
|
|
36
|
+
if (seed_ > M) {
|
|
37
|
+
seed_ -= M;
|
|
38
|
+
}
|
|
39
|
+
return seed_;
|
|
40
|
+
}
|
|
41
|
+
// Returns a uniformly distributed value in the range [0..n-1]
|
|
42
|
+
// REQUIRES: n > 0
|
|
43
|
+
uint32_t Uniform(int n) { return Next() % n; }
|
|
44
|
+
|
|
45
|
+
// Randomly returns true ~"1/n" of the time, and false otherwise.
|
|
46
|
+
// REQUIRES: n > 0
|
|
47
|
+
bool OneIn(int n) { return (Next() % n) == 0; }
|
|
48
|
+
|
|
49
|
+
// Skewed: pick "base" uniformly from range [0,max_log] and then
|
|
50
|
+
// return "base" random bits. The effect is to pick a number in the
|
|
51
|
+
// range [0,2^max_log-1] with exponential bias towards smaller numbers.
|
|
52
|
+
uint32_t Skewed(int max_log) {
|
|
53
|
+
return Uniform(1 << Uniform(max_log + 1));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
} // namespace leveldb
|
|
58
|
+
|
|
59
|
+
#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_
|
|
@@ -0,0 +1,75 @@
|
|
|
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 <stdio.h>
|
|
6
|
+
#include "port/port.h"
|
|
7
|
+
#include "leveldb/status.h"
|
|
8
|
+
|
|
9
|
+
namespace leveldb {
|
|
10
|
+
|
|
11
|
+
const char* Status::CopyState(const char* state) {
|
|
12
|
+
uint32_t size;
|
|
13
|
+
memcpy(&size, state, sizeof(size));
|
|
14
|
+
char* result = new char[size + 5];
|
|
15
|
+
memcpy(result, state, size + 5);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Status::Status(Code code, const Slice& msg, const Slice& msg2) {
|
|
20
|
+
assert(code != kOk);
|
|
21
|
+
const uint32_t len1 = msg.size();
|
|
22
|
+
const uint32_t len2 = msg2.size();
|
|
23
|
+
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
|
|
24
|
+
char* result = new char[size + 5];
|
|
25
|
+
memcpy(result, &size, sizeof(size));
|
|
26
|
+
result[4] = static_cast<char>(code);
|
|
27
|
+
memcpy(result + 5, msg.data(), len1);
|
|
28
|
+
if (len2) {
|
|
29
|
+
result[5 + len1] = ':';
|
|
30
|
+
result[6 + len1] = ' ';
|
|
31
|
+
memcpy(result + 7 + len1, msg2.data(), len2);
|
|
32
|
+
}
|
|
33
|
+
state_ = result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
std::string Status::ToString() const {
|
|
37
|
+
if (state_ == NULL) {
|
|
38
|
+
return "OK";
|
|
39
|
+
} else {
|
|
40
|
+
char tmp[30];
|
|
41
|
+
const char* type;
|
|
42
|
+
switch (code()) {
|
|
43
|
+
case kOk:
|
|
44
|
+
type = "OK";
|
|
45
|
+
break;
|
|
46
|
+
case kNotFound:
|
|
47
|
+
type = "NotFound: ";
|
|
48
|
+
break;
|
|
49
|
+
case kCorruption:
|
|
50
|
+
type = "Corruption: ";
|
|
51
|
+
break;
|
|
52
|
+
case kNotSupported:
|
|
53
|
+
type = "Not implemented: ";
|
|
54
|
+
break;
|
|
55
|
+
case kInvalidArgument:
|
|
56
|
+
type = "Invalid argument: ";
|
|
57
|
+
break;
|
|
58
|
+
case kIOError:
|
|
59
|
+
type = "IO error: ";
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
|
|
63
|
+
static_cast<int>(code()));
|
|
64
|
+
type = tmp;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
std::string result(type);
|
|
68
|
+
uint32_t length;
|
|
69
|
+
memcpy(&length, state_, sizeof(length));
|
|
70
|
+
result.append(state_ + 5, length);
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
} // namespace leveldb
|
|
@@ -0,0 +1,77 @@
|
|
|
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/testharness.h"
|
|
6
|
+
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <sys/stat.h>
|
|
10
|
+
#include <sys/types.h>
|
|
11
|
+
|
|
12
|
+
namespace leveldb {
|
|
13
|
+
namespace test {
|
|
14
|
+
|
|
15
|
+
namespace {
|
|
16
|
+
struct Test {
|
|
17
|
+
const char* base;
|
|
18
|
+
const char* name;
|
|
19
|
+
void (*func)();
|
|
20
|
+
};
|
|
21
|
+
std::vector<Test>* tests;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
bool RegisterTest(const char* base, const char* name, void (*func)()) {
|
|
25
|
+
if (tests == NULL) {
|
|
26
|
+
tests = new std::vector<Test>;
|
|
27
|
+
}
|
|
28
|
+
Test t;
|
|
29
|
+
t.base = base;
|
|
30
|
+
t.name = name;
|
|
31
|
+
t.func = func;
|
|
32
|
+
tests->push_back(t);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
int RunAllTests() {
|
|
37
|
+
const char* matcher = getenv("LEVELDB_TESTS");
|
|
38
|
+
|
|
39
|
+
int num = 0;
|
|
40
|
+
if (tests != NULL) {
|
|
41
|
+
for (int i = 0; i < tests->size(); i++) {
|
|
42
|
+
const Test& t = (*tests)[i];
|
|
43
|
+
if (matcher != NULL) {
|
|
44
|
+
std::string name = t.base;
|
|
45
|
+
name.push_back('.');
|
|
46
|
+
name.append(t.name);
|
|
47
|
+
if (strstr(name.c_str(), matcher) == NULL) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
fprintf(stderr, "==== Test %s.%s\n", t.base, t.name);
|
|
52
|
+
(*t.func)();
|
|
53
|
+
++num;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
fprintf(stderr, "==== PASSED %d tests\n", num);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
std::string TmpDir() {
|
|
61
|
+
std::string dir;
|
|
62
|
+
Status s = Env::Default()->GetTestDirectory(&dir);
|
|
63
|
+
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
64
|
+
return dir;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
int RandomSeed() {
|
|
68
|
+
const char* env = getenv("TEST_RANDOM_SEED");
|
|
69
|
+
int result = (env != NULL ? atoi(env) : 301);
|
|
70
|
+
if (result <= 0) {
|
|
71
|
+
result = 301;
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace test
|
|
77
|
+
} // namespace leveldb
|
|
@@ -0,0 +1,138 @@
|
|
|
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_UTIL_TESTHARNESS_H_
|
|
6
|
+
#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_
|
|
7
|
+
|
|
8
|
+
#include <stdio.h>
|
|
9
|
+
#include <stdlib.h>
|
|
10
|
+
#include <sstream>
|
|
11
|
+
#include "leveldb/env.h"
|
|
12
|
+
#include "leveldb/slice.h"
|
|
13
|
+
#include "util/random.h"
|
|
14
|
+
|
|
15
|
+
namespace leveldb {
|
|
16
|
+
namespace test {
|
|
17
|
+
|
|
18
|
+
// Run some of the tests registered by the TEST() macro. If the
|
|
19
|
+
// environment variable "LEVELDB_TESTS" is not set, runs all tests.
|
|
20
|
+
// Otherwise, runs only the tests whose name contains the value of
|
|
21
|
+
// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are:
|
|
22
|
+
// TEST(Foo, Hello) { ... }
|
|
23
|
+
// TEST(Foo, World) { ... }
|
|
24
|
+
// LEVELDB_TESTS=Hello will run the first test
|
|
25
|
+
// LEVELDB_TESTS=o will run both tests
|
|
26
|
+
// LEVELDB_TESTS=Junk will run no tests
|
|
27
|
+
//
|
|
28
|
+
// Returns 0 if all tests pass.
|
|
29
|
+
// Dies or returns a non-zero value if some test fails.
|
|
30
|
+
extern int RunAllTests();
|
|
31
|
+
|
|
32
|
+
// Return the directory to use for temporary storage.
|
|
33
|
+
extern std::string TmpDir();
|
|
34
|
+
|
|
35
|
+
// Return a randomization seed for this run. Typically returns the
|
|
36
|
+
// same number on repeated invocations of this binary, but automated
|
|
37
|
+
// runs may be able to vary the seed.
|
|
38
|
+
extern int RandomSeed();
|
|
39
|
+
|
|
40
|
+
// An instance of Tester is allocated to hold temporary state during
|
|
41
|
+
// the execution of an assertion.
|
|
42
|
+
class Tester {
|
|
43
|
+
private:
|
|
44
|
+
bool ok_;
|
|
45
|
+
const char* fname_;
|
|
46
|
+
int line_;
|
|
47
|
+
std::stringstream ss_;
|
|
48
|
+
|
|
49
|
+
public:
|
|
50
|
+
Tester(const char* f, int l)
|
|
51
|
+
: ok_(true), fname_(f), line_(l) {
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
~Tester() {
|
|
55
|
+
if (!ok_) {
|
|
56
|
+
fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
|
|
57
|
+
exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Tester& Is(bool b, const char* msg) {
|
|
62
|
+
if (!b) {
|
|
63
|
+
ss_ << " Assertion failure " << msg;
|
|
64
|
+
ok_ = false;
|
|
65
|
+
}
|
|
66
|
+
return *this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Tester& IsOk(const Status& s) {
|
|
70
|
+
if (!s.ok()) {
|
|
71
|
+
ss_ << " " << s.ToString();
|
|
72
|
+
ok_ = false;
|
|
73
|
+
}
|
|
74
|
+
return *this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#define BINARY_OP(name,op) \
|
|
78
|
+
template <class X, class Y> \
|
|
79
|
+
Tester& name(const X& x, const Y& y) { \
|
|
80
|
+
if (! (x op y)) { \
|
|
81
|
+
ss_ << " failed: " << x << (" " #op " ") << y; \
|
|
82
|
+
ok_ = false; \
|
|
83
|
+
} \
|
|
84
|
+
return *this; \
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
BINARY_OP(IsEq, ==)
|
|
88
|
+
BINARY_OP(IsNe, !=)
|
|
89
|
+
BINARY_OP(IsGe, >=)
|
|
90
|
+
BINARY_OP(IsGt, >)
|
|
91
|
+
BINARY_OP(IsLe, <=)
|
|
92
|
+
BINARY_OP(IsLt, <)
|
|
93
|
+
#undef BINARY_OP
|
|
94
|
+
|
|
95
|
+
// Attach the specified value to the error message if an error has occurred
|
|
96
|
+
template <class V>
|
|
97
|
+
Tester& operator<<(const V& value) {
|
|
98
|
+
if (!ok_) {
|
|
99
|
+
ss_ << " " << value;
|
|
100
|
+
}
|
|
101
|
+
return *this;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c)
|
|
106
|
+
#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s))
|
|
107
|
+
#define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b))
|
|
108
|
+
#define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b))
|
|
109
|
+
#define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b))
|
|
110
|
+
#define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b))
|
|
111
|
+
#define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b))
|
|
112
|
+
#define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b))
|
|
113
|
+
|
|
114
|
+
#define TCONCAT(a,b) TCONCAT1(a,b)
|
|
115
|
+
#define TCONCAT1(a,b) a##b
|
|
116
|
+
|
|
117
|
+
#define TEST(base,name) \
|
|
118
|
+
class TCONCAT(_Test_,name) : public base { \
|
|
119
|
+
public: \
|
|
120
|
+
void _Run(); \
|
|
121
|
+
static void _RunIt() { \
|
|
122
|
+
TCONCAT(_Test_,name) t; \
|
|
123
|
+
t._Run(); \
|
|
124
|
+
} \
|
|
125
|
+
}; \
|
|
126
|
+
bool TCONCAT(_Test_ignored_,name) = \
|
|
127
|
+
::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \
|
|
128
|
+
void TCONCAT(_Test_,name)::_Run()
|
|
129
|
+
|
|
130
|
+
// Register the specified test. Typically not used directly, but
|
|
131
|
+
// invoked via the macro expansion of TEST.
|
|
132
|
+
extern bool RegisterTest(const char* base, const char* name, void (*func)());
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
} // namespace test
|
|
136
|
+
} // namespace leveldb
|
|
137
|
+
|
|
138
|
+
#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_
|