1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker
5*9507f98cSAndroid Build Coastguard Worker #include "leveldb/db.h"
6*9507f98cSAndroid Build Coastguard Worker
7*9507f98cSAndroid Build Coastguard Worker #include <atomic>
8*9507f98cSAndroid Build Coastguard Worker #include <cinttypes>
9*9507f98cSAndroid Build Coastguard Worker #include <string>
10*9507f98cSAndroid Build Coastguard Worker
11*9507f98cSAndroid Build Coastguard Worker #include "gtest/gtest.h"
12*9507f98cSAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
13*9507f98cSAndroid Build Coastguard Worker #include "db/db_impl.h"
14*9507f98cSAndroid Build Coastguard Worker #include "db/filename.h"
15*9507f98cSAndroid Build Coastguard Worker #include "db/version_set.h"
16*9507f98cSAndroid Build Coastguard Worker #include "db/write_batch_internal.h"
17*9507f98cSAndroid Build Coastguard Worker #include "leveldb/cache.h"
18*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
19*9507f98cSAndroid Build Coastguard Worker #include "leveldb/filter_policy.h"
20*9507f98cSAndroid Build Coastguard Worker #include "leveldb/table.h"
21*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
22*9507f98cSAndroid Build Coastguard Worker #include "port/thread_annotations.h"
23*9507f98cSAndroid Build Coastguard Worker #include "util/hash.h"
24*9507f98cSAndroid Build Coastguard Worker #include "util/logging.h"
25*9507f98cSAndroid Build Coastguard Worker #include "util/mutexlock.h"
26*9507f98cSAndroid Build Coastguard Worker #include "util/testutil.h"
27*9507f98cSAndroid Build Coastguard Worker
28*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
29*9507f98cSAndroid Build Coastguard Worker
RandomString(Random * rnd,int len)30*9507f98cSAndroid Build Coastguard Worker static std::string RandomString(Random* rnd, int len) {
31*9507f98cSAndroid Build Coastguard Worker std::string r;
32*9507f98cSAndroid Build Coastguard Worker test::RandomString(rnd, len, &r);
33*9507f98cSAndroid Build Coastguard Worker return r;
34*9507f98cSAndroid Build Coastguard Worker }
35*9507f98cSAndroid Build Coastguard Worker
RandomKey(Random * rnd)36*9507f98cSAndroid Build Coastguard Worker static std::string RandomKey(Random* rnd) {
37*9507f98cSAndroid Build Coastguard Worker int len =
38*9507f98cSAndroid Build Coastguard Worker (rnd->OneIn(3) ? 1 // Short sometimes to encourage collisions
39*9507f98cSAndroid Build Coastguard Worker : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
40*9507f98cSAndroid Build Coastguard Worker return test::RandomKey(rnd, len);
41*9507f98cSAndroid Build Coastguard Worker }
42*9507f98cSAndroid Build Coastguard Worker
43*9507f98cSAndroid Build Coastguard Worker namespace {
44*9507f98cSAndroid Build Coastguard Worker class AtomicCounter {
45*9507f98cSAndroid Build Coastguard Worker public:
AtomicCounter()46*9507f98cSAndroid Build Coastguard Worker AtomicCounter() : count_(0) {}
Increment()47*9507f98cSAndroid Build Coastguard Worker void Increment() { IncrementBy(1); }
IncrementBy(int count)48*9507f98cSAndroid Build Coastguard Worker void IncrementBy(int count) LOCKS_EXCLUDED(mu_) {
49*9507f98cSAndroid Build Coastguard Worker MutexLock l(&mu_);
50*9507f98cSAndroid Build Coastguard Worker count_ += count;
51*9507f98cSAndroid Build Coastguard Worker }
Read()52*9507f98cSAndroid Build Coastguard Worker int Read() LOCKS_EXCLUDED(mu_) {
53*9507f98cSAndroid Build Coastguard Worker MutexLock l(&mu_);
54*9507f98cSAndroid Build Coastguard Worker return count_;
55*9507f98cSAndroid Build Coastguard Worker }
Reset()56*9507f98cSAndroid Build Coastguard Worker void Reset() LOCKS_EXCLUDED(mu_) {
57*9507f98cSAndroid Build Coastguard Worker MutexLock l(&mu_);
58*9507f98cSAndroid Build Coastguard Worker count_ = 0;
59*9507f98cSAndroid Build Coastguard Worker }
60*9507f98cSAndroid Build Coastguard Worker
61*9507f98cSAndroid Build Coastguard Worker private:
62*9507f98cSAndroid Build Coastguard Worker port::Mutex mu_;
63*9507f98cSAndroid Build Coastguard Worker int count_ GUARDED_BY(mu_);
64*9507f98cSAndroid Build Coastguard Worker };
65*9507f98cSAndroid Build Coastguard Worker
DelayMilliseconds(int millis)66*9507f98cSAndroid Build Coastguard Worker void DelayMilliseconds(int millis) {
67*9507f98cSAndroid Build Coastguard Worker Env::Default()->SleepForMicroseconds(millis * 1000);
68*9507f98cSAndroid Build Coastguard Worker }
69*9507f98cSAndroid Build Coastguard Worker } // namespace
70*9507f98cSAndroid Build Coastguard Worker
71*9507f98cSAndroid Build Coastguard Worker // Test Env to override default Env behavior for testing.
72*9507f98cSAndroid Build Coastguard Worker class TestEnv : public EnvWrapper {
73*9507f98cSAndroid Build Coastguard Worker public:
TestEnv(Env * base)74*9507f98cSAndroid Build Coastguard Worker explicit TestEnv(Env* base) : EnvWrapper(base), ignore_dot_files_(false) {}
75*9507f98cSAndroid Build Coastguard Worker
SetIgnoreDotFiles(bool ignored)76*9507f98cSAndroid Build Coastguard Worker void SetIgnoreDotFiles(bool ignored) { ignore_dot_files_ = ignored; }
77*9507f98cSAndroid Build Coastguard Worker
GetChildren(const std::string & dir,std::vector<std::string> * result)78*9507f98cSAndroid Build Coastguard Worker Status GetChildren(const std::string& dir,
79*9507f98cSAndroid Build Coastguard Worker std::vector<std::string>* result) override {
80*9507f98cSAndroid Build Coastguard Worker Status s = target()->GetChildren(dir, result);
81*9507f98cSAndroid Build Coastguard Worker if (!s.ok() || !ignore_dot_files_) {
82*9507f98cSAndroid Build Coastguard Worker return s;
83*9507f98cSAndroid Build Coastguard Worker }
84*9507f98cSAndroid Build Coastguard Worker
85*9507f98cSAndroid Build Coastguard Worker std::vector<std::string>::iterator it = result->begin();
86*9507f98cSAndroid Build Coastguard Worker while (it != result->end()) {
87*9507f98cSAndroid Build Coastguard Worker if ((*it == ".") || (*it == "..")) {
88*9507f98cSAndroid Build Coastguard Worker it = result->erase(it);
89*9507f98cSAndroid Build Coastguard Worker } else {
90*9507f98cSAndroid Build Coastguard Worker ++it;
91*9507f98cSAndroid Build Coastguard Worker }
92*9507f98cSAndroid Build Coastguard Worker }
93*9507f98cSAndroid Build Coastguard Worker
94*9507f98cSAndroid Build Coastguard Worker return s;
95*9507f98cSAndroid Build Coastguard Worker }
96*9507f98cSAndroid Build Coastguard Worker
97*9507f98cSAndroid Build Coastguard Worker private:
98*9507f98cSAndroid Build Coastguard Worker bool ignore_dot_files_;
99*9507f98cSAndroid Build Coastguard Worker };
100*9507f98cSAndroid Build Coastguard Worker
101*9507f98cSAndroid Build Coastguard Worker // Special Env used to delay background operations.
102*9507f98cSAndroid Build Coastguard Worker class SpecialEnv : public EnvWrapper {
103*9507f98cSAndroid Build Coastguard Worker public:
104*9507f98cSAndroid Build Coastguard Worker // sstable/log Sync() calls are blocked while this pointer is non-null.
105*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> delay_data_sync_;
106*9507f98cSAndroid Build Coastguard Worker
107*9507f98cSAndroid Build Coastguard Worker // sstable/log Sync() calls return an error.
108*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> data_sync_error_;
109*9507f98cSAndroid Build Coastguard Worker
110*9507f98cSAndroid Build Coastguard Worker // Simulate no-space errors while this pointer is non-null.
111*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> no_space_;
112*9507f98cSAndroid Build Coastguard Worker
113*9507f98cSAndroid Build Coastguard Worker // Simulate non-writable file system while this pointer is non-null.
114*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> non_writable_;
115*9507f98cSAndroid Build Coastguard Worker
116*9507f98cSAndroid Build Coastguard Worker // Force sync of manifest files to fail while this pointer is non-null.
117*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> manifest_sync_error_;
118*9507f98cSAndroid Build Coastguard Worker
119*9507f98cSAndroid Build Coastguard Worker // Force write to manifest files to fail while this pointer is non-null.
120*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> manifest_write_error_;
121*9507f98cSAndroid Build Coastguard Worker
122*9507f98cSAndroid Build Coastguard Worker bool count_random_reads_;
123*9507f98cSAndroid Build Coastguard Worker AtomicCounter random_read_counter_;
124*9507f98cSAndroid Build Coastguard Worker
SpecialEnv(Env * base)125*9507f98cSAndroid Build Coastguard Worker explicit SpecialEnv(Env* base)
126*9507f98cSAndroid Build Coastguard Worker : EnvWrapper(base),
127*9507f98cSAndroid Build Coastguard Worker delay_data_sync_(false),
128*9507f98cSAndroid Build Coastguard Worker data_sync_error_(false),
129*9507f98cSAndroid Build Coastguard Worker no_space_(false),
130*9507f98cSAndroid Build Coastguard Worker non_writable_(false),
131*9507f98cSAndroid Build Coastguard Worker manifest_sync_error_(false),
132*9507f98cSAndroid Build Coastguard Worker manifest_write_error_(false),
133*9507f98cSAndroid Build Coastguard Worker count_random_reads_(false) {}
134*9507f98cSAndroid Build Coastguard Worker
NewWritableFile(const std::string & f,WritableFile ** r)135*9507f98cSAndroid Build Coastguard Worker Status NewWritableFile(const std::string& f, WritableFile** r) {
136*9507f98cSAndroid Build Coastguard Worker class DataFile : public WritableFile {
137*9507f98cSAndroid Build Coastguard Worker private:
138*9507f98cSAndroid Build Coastguard Worker SpecialEnv* const env_;
139*9507f98cSAndroid Build Coastguard Worker WritableFile* const base_;
140*9507f98cSAndroid Build Coastguard Worker
141*9507f98cSAndroid Build Coastguard Worker public:
142*9507f98cSAndroid Build Coastguard Worker DataFile(SpecialEnv* env, WritableFile* base) : env_(env), base_(base) {}
143*9507f98cSAndroid Build Coastguard Worker ~DataFile() { delete base_; }
144*9507f98cSAndroid Build Coastguard Worker Status Append(const Slice& data) {
145*9507f98cSAndroid Build Coastguard Worker if (env_->no_space_.load(std::memory_order_acquire)) {
146*9507f98cSAndroid Build Coastguard Worker // Drop writes on the floor
147*9507f98cSAndroid Build Coastguard Worker return Status::OK();
148*9507f98cSAndroid Build Coastguard Worker } else {
149*9507f98cSAndroid Build Coastguard Worker return base_->Append(data);
150*9507f98cSAndroid Build Coastguard Worker }
151*9507f98cSAndroid Build Coastguard Worker }
152*9507f98cSAndroid Build Coastguard Worker Status Close() { return base_->Close(); }
153*9507f98cSAndroid Build Coastguard Worker Status Flush() { return base_->Flush(); }
154*9507f98cSAndroid Build Coastguard Worker Status Sync() {
155*9507f98cSAndroid Build Coastguard Worker if (env_->data_sync_error_.load(std::memory_order_acquire)) {
156*9507f98cSAndroid Build Coastguard Worker return Status::IOError("simulated data sync error");
157*9507f98cSAndroid Build Coastguard Worker }
158*9507f98cSAndroid Build Coastguard Worker while (env_->delay_data_sync_.load(std::memory_order_acquire)) {
159*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(100);
160*9507f98cSAndroid Build Coastguard Worker }
161*9507f98cSAndroid Build Coastguard Worker return base_->Sync();
162*9507f98cSAndroid Build Coastguard Worker }
163*9507f98cSAndroid Build Coastguard Worker };
164*9507f98cSAndroid Build Coastguard Worker class ManifestFile : public WritableFile {
165*9507f98cSAndroid Build Coastguard Worker private:
166*9507f98cSAndroid Build Coastguard Worker SpecialEnv* env_;
167*9507f98cSAndroid Build Coastguard Worker WritableFile* base_;
168*9507f98cSAndroid Build Coastguard Worker
169*9507f98cSAndroid Build Coastguard Worker public:
170*9507f98cSAndroid Build Coastguard Worker ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) {}
171*9507f98cSAndroid Build Coastguard Worker ~ManifestFile() { delete base_; }
172*9507f98cSAndroid Build Coastguard Worker Status Append(const Slice& data) {
173*9507f98cSAndroid Build Coastguard Worker if (env_->manifest_write_error_.load(std::memory_order_acquire)) {
174*9507f98cSAndroid Build Coastguard Worker return Status::IOError("simulated writer error");
175*9507f98cSAndroid Build Coastguard Worker } else {
176*9507f98cSAndroid Build Coastguard Worker return base_->Append(data);
177*9507f98cSAndroid Build Coastguard Worker }
178*9507f98cSAndroid Build Coastguard Worker }
179*9507f98cSAndroid Build Coastguard Worker Status Close() { return base_->Close(); }
180*9507f98cSAndroid Build Coastguard Worker Status Flush() { return base_->Flush(); }
181*9507f98cSAndroid Build Coastguard Worker Status Sync() {
182*9507f98cSAndroid Build Coastguard Worker if (env_->manifest_sync_error_.load(std::memory_order_acquire)) {
183*9507f98cSAndroid Build Coastguard Worker return Status::IOError("simulated sync error");
184*9507f98cSAndroid Build Coastguard Worker } else {
185*9507f98cSAndroid Build Coastguard Worker return base_->Sync();
186*9507f98cSAndroid Build Coastguard Worker }
187*9507f98cSAndroid Build Coastguard Worker }
188*9507f98cSAndroid Build Coastguard Worker };
189*9507f98cSAndroid Build Coastguard Worker
190*9507f98cSAndroid Build Coastguard Worker if (non_writable_.load(std::memory_order_acquire)) {
191*9507f98cSAndroid Build Coastguard Worker return Status::IOError("simulated write error");
192*9507f98cSAndroid Build Coastguard Worker }
193*9507f98cSAndroid Build Coastguard Worker
194*9507f98cSAndroid Build Coastguard Worker Status s = target()->NewWritableFile(f, r);
195*9507f98cSAndroid Build Coastguard Worker if (s.ok()) {
196*9507f98cSAndroid Build Coastguard Worker if (strstr(f.c_str(), ".ldb") != nullptr ||
197*9507f98cSAndroid Build Coastguard Worker strstr(f.c_str(), ".log") != nullptr) {
198*9507f98cSAndroid Build Coastguard Worker *r = new DataFile(this, *r);
199*9507f98cSAndroid Build Coastguard Worker } else if (strstr(f.c_str(), "MANIFEST") != nullptr) {
200*9507f98cSAndroid Build Coastguard Worker *r = new ManifestFile(this, *r);
201*9507f98cSAndroid Build Coastguard Worker }
202*9507f98cSAndroid Build Coastguard Worker }
203*9507f98cSAndroid Build Coastguard Worker return s;
204*9507f98cSAndroid Build Coastguard Worker }
205*9507f98cSAndroid Build Coastguard Worker
NewRandomAccessFile(const std::string & f,RandomAccessFile ** r)206*9507f98cSAndroid Build Coastguard Worker Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {
207*9507f98cSAndroid Build Coastguard Worker class CountingFile : public RandomAccessFile {
208*9507f98cSAndroid Build Coastguard Worker private:
209*9507f98cSAndroid Build Coastguard Worker RandomAccessFile* target_;
210*9507f98cSAndroid Build Coastguard Worker AtomicCounter* counter_;
211*9507f98cSAndroid Build Coastguard Worker
212*9507f98cSAndroid Build Coastguard Worker public:
213*9507f98cSAndroid Build Coastguard Worker CountingFile(RandomAccessFile* target, AtomicCounter* counter)
214*9507f98cSAndroid Build Coastguard Worker : target_(target), counter_(counter) {}
215*9507f98cSAndroid Build Coastguard Worker ~CountingFile() override { delete target_; }
216*9507f98cSAndroid Build Coastguard Worker Status Read(uint64_t offset, size_t n, Slice* result,
217*9507f98cSAndroid Build Coastguard Worker char* scratch) const override {
218*9507f98cSAndroid Build Coastguard Worker counter_->Increment();
219*9507f98cSAndroid Build Coastguard Worker return target_->Read(offset, n, result, scratch);
220*9507f98cSAndroid Build Coastguard Worker }
221*9507f98cSAndroid Build Coastguard Worker };
222*9507f98cSAndroid Build Coastguard Worker
223*9507f98cSAndroid Build Coastguard Worker Status s = target()->NewRandomAccessFile(f, r);
224*9507f98cSAndroid Build Coastguard Worker if (s.ok() && count_random_reads_) {
225*9507f98cSAndroid Build Coastguard Worker *r = new CountingFile(*r, &random_read_counter_);
226*9507f98cSAndroid Build Coastguard Worker }
227*9507f98cSAndroid Build Coastguard Worker return s;
228*9507f98cSAndroid Build Coastguard Worker }
229*9507f98cSAndroid Build Coastguard Worker };
230*9507f98cSAndroid Build Coastguard Worker
231*9507f98cSAndroid Build Coastguard Worker class DBTest : public testing::Test {
232*9507f98cSAndroid Build Coastguard Worker public:
233*9507f98cSAndroid Build Coastguard Worker std::string dbname_;
234*9507f98cSAndroid Build Coastguard Worker SpecialEnv* env_;
235*9507f98cSAndroid Build Coastguard Worker DB* db_;
236*9507f98cSAndroid Build Coastguard Worker
237*9507f98cSAndroid Build Coastguard Worker Options last_options_;
238*9507f98cSAndroid Build Coastguard Worker
DBTest()239*9507f98cSAndroid Build Coastguard Worker DBTest() : env_(new SpecialEnv(Env::Default())), option_config_(kDefault) {
240*9507f98cSAndroid Build Coastguard Worker filter_policy_ = NewBloomFilterPolicy(10);
241*9507f98cSAndroid Build Coastguard Worker dbname_ = testing::TempDir() + "db_test";
242*9507f98cSAndroid Build Coastguard Worker DestroyDB(dbname_, Options());
243*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
244*9507f98cSAndroid Build Coastguard Worker Reopen();
245*9507f98cSAndroid Build Coastguard Worker }
246*9507f98cSAndroid Build Coastguard Worker
~DBTest()247*9507f98cSAndroid Build Coastguard Worker ~DBTest() {
248*9507f98cSAndroid Build Coastguard Worker delete db_;
249*9507f98cSAndroid Build Coastguard Worker DestroyDB(dbname_, Options());
250*9507f98cSAndroid Build Coastguard Worker delete env_;
251*9507f98cSAndroid Build Coastguard Worker delete filter_policy_;
252*9507f98cSAndroid Build Coastguard Worker }
253*9507f98cSAndroid Build Coastguard Worker
254*9507f98cSAndroid Build Coastguard Worker // Switch to a fresh database with the next option configuration to
255*9507f98cSAndroid Build Coastguard Worker // test. Return false if there are no more configurations to test.
ChangeOptions()256*9507f98cSAndroid Build Coastguard Worker bool ChangeOptions() {
257*9507f98cSAndroid Build Coastguard Worker option_config_++;
258*9507f98cSAndroid Build Coastguard Worker if (option_config_ >= kEnd) {
259*9507f98cSAndroid Build Coastguard Worker return false;
260*9507f98cSAndroid Build Coastguard Worker } else {
261*9507f98cSAndroid Build Coastguard Worker DestroyAndReopen();
262*9507f98cSAndroid Build Coastguard Worker return true;
263*9507f98cSAndroid Build Coastguard Worker }
264*9507f98cSAndroid Build Coastguard Worker }
265*9507f98cSAndroid Build Coastguard Worker
266*9507f98cSAndroid Build Coastguard Worker // Return the current option configuration.
CurrentOptions()267*9507f98cSAndroid Build Coastguard Worker Options CurrentOptions() {
268*9507f98cSAndroid Build Coastguard Worker Options options;
269*9507f98cSAndroid Build Coastguard Worker options.reuse_logs = false;
270*9507f98cSAndroid Build Coastguard Worker switch (option_config_) {
271*9507f98cSAndroid Build Coastguard Worker case kReuse:
272*9507f98cSAndroid Build Coastguard Worker options.reuse_logs = true;
273*9507f98cSAndroid Build Coastguard Worker break;
274*9507f98cSAndroid Build Coastguard Worker case kFilter:
275*9507f98cSAndroid Build Coastguard Worker options.filter_policy = filter_policy_;
276*9507f98cSAndroid Build Coastguard Worker break;
277*9507f98cSAndroid Build Coastguard Worker case kUncompressed:
278*9507f98cSAndroid Build Coastguard Worker options.compression = kNoCompression;
279*9507f98cSAndroid Build Coastguard Worker break;
280*9507f98cSAndroid Build Coastguard Worker default:
281*9507f98cSAndroid Build Coastguard Worker break;
282*9507f98cSAndroid Build Coastguard Worker }
283*9507f98cSAndroid Build Coastguard Worker return options;
284*9507f98cSAndroid Build Coastguard Worker }
285*9507f98cSAndroid Build Coastguard Worker
dbfull()286*9507f98cSAndroid Build Coastguard Worker DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }
287*9507f98cSAndroid Build Coastguard Worker
Reopen(Options * options=nullptr)288*9507f98cSAndroid Build Coastguard Worker void Reopen(Options* options = nullptr) {
289*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(TryReopen(options));
290*9507f98cSAndroid Build Coastguard Worker }
291*9507f98cSAndroid Build Coastguard Worker
Close()292*9507f98cSAndroid Build Coastguard Worker void Close() {
293*9507f98cSAndroid Build Coastguard Worker delete db_;
294*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
295*9507f98cSAndroid Build Coastguard Worker }
296*9507f98cSAndroid Build Coastguard Worker
DestroyAndReopen(Options * options=nullptr)297*9507f98cSAndroid Build Coastguard Worker void DestroyAndReopen(Options* options = nullptr) {
298*9507f98cSAndroid Build Coastguard Worker delete db_;
299*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
300*9507f98cSAndroid Build Coastguard Worker DestroyDB(dbname_, Options());
301*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(TryReopen(options));
302*9507f98cSAndroid Build Coastguard Worker }
303*9507f98cSAndroid Build Coastguard Worker
TryReopen(Options * options)304*9507f98cSAndroid Build Coastguard Worker Status TryReopen(Options* options) {
305*9507f98cSAndroid Build Coastguard Worker delete db_;
306*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
307*9507f98cSAndroid Build Coastguard Worker Options opts;
308*9507f98cSAndroid Build Coastguard Worker if (options != nullptr) {
309*9507f98cSAndroid Build Coastguard Worker opts = *options;
310*9507f98cSAndroid Build Coastguard Worker } else {
311*9507f98cSAndroid Build Coastguard Worker opts = CurrentOptions();
312*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = true;
313*9507f98cSAndroid Build Coastguard Worker }
314*9507f98cSAndroid Build Coastguard Worker last_options_ = opts;
315*9507f98cSAndroid Build Coastguard Worker
316*9507f98cSAndroid Build Coastguard Worker return DB::Open(opts, dbname_, &db_);
317*9507f98cSAndroid Build Coastguard Worker }
318*9507f98cSAndroid Build Coastguard Worker
Put(const std::string & k,const std::string & v)319*9507f98cSAndroid Build Coastguard Worker Status Put(const std::string& k, const std::string& v) {
320*9507f98cSAndroid Build Coastguard Worker return db_->Put(WriteOptions(), k, v);
321*9507f98cSAndroid Build Coastguard Worker }
322*9507f98cSAndroid Build Coastguard Worker
Delete(const std::string & k)323*9507f98cSAndroid Build Coastguard Worker Status Delete(const std::string& k) { return db_->Delete(WriteOptions(), k); }
324*9507f98cSAndroid Build Coastguard Worker
Get(const std::string & k,const Snapshot * snapshot=nullptr)325*9507f98cSAndroid Build Coastguard Worker std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {
326*9507f98cSAndroid Build Coastguard Worker ReadOptions options;
327*9507f98cSAndroid Build Coastguard Worker options.snapshot = snapshot;
328*9507f98cSAndroid Build Coastguard Worker std::string result;
329*9507f98cSAndroid Build Coastguard Worker Status s = db_->Get(options, k, &result);
330*9507f98cSAndroid Build Coastguard Worker if (s.IsNotFound()) {
331*9507f98cSAndroid Build Coastguard Worker result = "NOT_FOUND";
332*9507f98cSAndroid Build Coastguard Worker } else if (!s.ok()) {
333*9507f98cSAndroid Build Coastguard Worker result = s.ToString();
334*9507f98cSAndroid Build Coastguard Worker }
335*9507f98cSAndroid Build Coastguard Worker return result;
336*9507f98cSAndroid Build Coastguard Worker }
337*9507f98cSAndroid Build Coastguard Worker
338*9507f98cSAndroid Build Coastguard Worker // Return a string that contains all key,value pairs in order,
339*9507f98cSAndroid Build Coastguard Worker // formatted like "(k1->v1)(k2->v2)".
Contents()340*9507f98cSAndroid Build Coastguard Worker std::string Contents() {
341*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> forward;
342*9507f98cSAndroid Build Coastguard Worker std::string result;
343*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
344*9507f98cSAndroid Build Coastguard Worker for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
345*9507f98cSAndroid Build Coastguard Worker std::string s = IterStatus(iter);
346*9507f98cSAndroid Build Coastguard Worker result.push_back('(');
347*9507f98cSAndroid Build Coastguard Worker result.append(s);
348*9507f98cSAndroid Build Coastguard Worker result.push_back(')');
349*9507f98cSAndroid Build Coastguard Worker forward.push_back(s);
350*9507f98cSAndroid Build Coastguard Worker }
351*9507f98cSAndroid Build Coastguard Worker
352*9507f98cSAndroid Build Coastguard Worker // Check reverse iteration results are the reverse of forward results
353*9507f98cSAndroid Build Coastguard Worker size_t matched = 0;
354*9507f98cSAndroid Build Coastguard Worker for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
355*9507f98cSAndroid Build Coastguard Worker EXPECT_LT(matched, forward.size());
356*9507f98cSAndroid Build Coastguard Worker EXPECT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
357*9507f98cSAndroid Build Coastguard Worker matched++;
358*9507f98cSAndroid Build Coastguard Worker }
359*9507f98cSAndroid Build Coastguard Worker EXPECT_EQ(matched, forward.size());
360*9507f98cSAndroid Build Coastguard Worker
361*9507f98cSAndroid Build Coastguard Worker delete iter;
362*9507f98cSAndroid Build Coastguard Worker return result;
363*9507f98cSAndroid Build Coastguard Worker }
364*9507f98cSAndroid Build Coastguard Worker
AllEntriesFor(const Slice & user_key)365*9507f98cSAndroid Build Coastguard Worker std::string AllEntriesFor(const Slice& user_key) {
366*9507f98cSAndroid Build Coastguard Worker Iterator* iter = dbfull()->TEST_NewInternalIterator();
367*9507f98cSAndroid Build Coastguard Worker InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
368*9507f98cSAndroid Build Coastguard Worker iter->Seek(target.Encode());
369*9507f98cSAndroid Build Coastguard Worker std::string result;
370*9507f98cSAndroid Build Coastguard Worker if (!iter->status().ok()) {
371*9507f98cSAndroid Build Coastguard Worker result = iter->status().ToString();
372*9507f98cSAndroid Build Coastguard Worker } else {
373*9507f98cSAndroid Build Coastguard Worker result = "[ ";
374*9507f98cSAndroid Build Coastguard Worker bool first = true;
375*9507f98cSAndroid Build Coastguard Worker while (iter->Valid()) {
376*9507f98cSAndroid Build Coastguard Worker ParsedInternalKey ikey;
377*9507f98cSAndroid Build Coastguard Worker if (!ParseInternalKey(iter->key(), &ikey)) {
378*9507f98cSAndroid Build Coastguard Worker result += "CORRUPTED";
379*9507f98cSAndroid Build Coastguard Worker } else {
380*9507f98cSAndroid Build Coastguard Worker if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) {
381*9507f98cSAndroid Build Coastguard Worker break;
382*9507f98cSAndroid Build Coastguard Worker }
383*9507f98cSAndroid Build Coastguard Worker if (!first) {
384*9507f98cSAndroid Build Coastguard Worker result += ", ";
385*9507f98cSAndroid Build Coastguard Worker }
386*9507f98cSAndroid Build Coastguard Worker first = false;
387*9507f98cSAndroid Build Coastguard Worker switch (ikey.type) {
388*9507f98cSAndroid Build Coastguard Worker case kTypeValue:
389*9507f98cSAndroid Build Coastguard Worker result += iter->value().ToString();
390*9507f98cSAndroid Build Coastguard Worker break;
391*9507f98cSAndroid Build Coastguard Worker case kTypeDeletion:
392*9507f98cSAndroid Build Coastguard Worker result += "DEL";
393*9507f98cSAndroid Build Coastguard Worker break;
394*9507f98cSAndroid Build Coastguard Worker }
395*9507f98cSAndroid Build Coastguard Worker }
396*9507f98cSAndroid Build Coastguard Worker iter->Next();
397*9507f98cSAndroid Build Coastguard Worker }
398*9507f98cSAndroid Build Coastguard Worker if (!first) {
399*9507f98cSAndroid Build Coastguard Worker result += " ";
400*9507f98cSAndroid Build Coastguard Worker }
401*9507f98cSAndroid Build Coastguard Worker result += "]";
402*9507f98cSAndroid Build Coastguard Worker }
403*9507f98cSAndroid Build Coastguard Worker delete iter;
404*9507f98cSAndroid Build Coastguard Worker return result;
405*9507f98cSAndroid Build Coastguard Worker }
406*9507f98cSAndroid Build Coastguard Worker
NumTableFilesAtLevel(int level)407*9507f98cSAndroid Build Coastguard Worker int NumTableFilesAtLevel(int level) {
408*9507f98cSAndroid Build Coastguard Worker std::string property;
409*9507f98cSAndroid Build Coastguard Worker EXPECT_TRUE(db_->GetProperty(
410*9507f98cSAndroid Build Coastguard Worker "leveldb.num-files-at-level" + NumberToString(level), &property));
411*9507f98cSAndroid Build Coastguard Worker return std::stoi(property);
412*9507f98cSAndroid Build Coastguard Worker }
413*9507f98cSAndroid Build Coastguard Worker
TotalTableFiles()414*9507f98cSAndroid Build Coastguard Worker int TotalTableFiles() {
415*9507f98cSAndroid Build Coastguard Worker int result = 0;
416*9507f98cSAndroid Build Coastguard Worker for (int level = 0; level < config::kNumLevels; level++) {
417*9507f98cSAndroid Build Coastguard Worker result += NumTableFilesAtLevel(level);
418*9507f98cSAndroid Build Coastguard Worker }
419*9507f98cSAndroid Build Coastguard Worker return result;
420*9507f98cSAndroid Build Coastguard Worker }
421*9507f98cSAndroid Build Coastguard Worker
422*9507f98cSAndroid Build Coastguard Worker // Return spread of files per level
FilesPerLevel()423*9507f98cSAndroid Build Coastguard Worker std::string FilesPerLevel() {
424*9507f98cSAndroid Build Coastguard Worker std::string result;
425*9507f98cSAndroid Build Coastguard Worker int last_non_zero_offset = 0;
426*9507f98cSAndroid Build Coastguard Worker for (int level = 0; level < config::kNumLevels; level++) {
427*9507f98cSAndroid Build Coastguard Worker int f = NumTableFilesAtLevel(level);
428*9507f98cSAndroid Build Coastguard Worker char buf[100];
429*9507f98cSAndroid Build Coastguard Worker std::snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);
430*9507f98cSAndroid Build Coastguard Worker result += buf;
431*9507f98cSAndroid Build Coastguard Worker if (f > 0) {
432*9507f98cSAndroid Build Coastguard Worker last_non_zero_offset = result.size();
433*9507f98cSAndroid Build Coastguard Worker }
434*9507f98cSAndroid Build Coastguard Worker }
435*9507f98cSAndroid Build Coastguard Worker result.resize(last_non_zero_offset);
436*9507f98cSAndroid Build Coastguard Worker return result;
437*9507f98cSAndroid Build Coastguard Worker }
438*9507f98cSAndroid Build Coastguard Worker
CountFiles()439*9507f98cSAndroid Build Coastguard Worker int CountFiles() {
440*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> files;
441*9507f98cSAndroid Build Coastguard Worker env_->GetChildren(dbname_, &files);
442*9507f98cSAndroid Build Coastguard Worker return static_cast<int>(files.size());
443*9507f98cSAndroid Build Coastguard Worker }
444*9507f98cSAndroid Build Coastguard Worker
Size(const Slice & start,const Slice & limit)445*9507f98cSAndroid Build Coastguard Worker uint64_t Size(const Slice& start, const Slice& limit) {
446*9507f98cSAndroid Build Coastguard Worker Range r(start, limit);
447*9507f98cSAndroid Build Coastguard Worker uint64_t size;
448*9507f98cSAndroid Build Coastguard Worker db_->GetApproximateSizes(&r, 1, &size);
449*9507f98cSAndroid Build Coastguard Worker return size;
450*9507f98cSAndroid Build Coastguard Worker }
451*9507f98cSAndroid Build Coastguard Worker
Compact(const Slice & start,const Slice & limit)452*9507f98cSAndroid Build Coastguard Worker void Compact(const Slice& start, const Slice& limit) {
453*9507f98cSAndroid Build Coastguard Worker db_->CompactRange(&start, &limit);
454*9507f98cSAndroid Build Coastguard Worker }
455*9507f98cSAndroid Build Coastguard Worker
456*9507f98cSAndroid Build Coastguard Worker // Do n memtable compactions, each of which produces an sstable
457*9507f98cSAndroid Build Coastguard Worker // covering the range [small_key,large_key].
MakeTables(int n,const std::string & small_key,const std::string & large_key)458*9507f98cSAndroid Build Coastguard Worker void MakeTables(int n, const std::string& small_key,
459*9507f98cSAndroid Build Coastguard Worker const std::string& large_key) {
460*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < n; i++) {
461*9507f98cSAndroid Build Coastguard Worker Put(small_key, "begin");
462*9507f98cSAndroid Build Coastguard Worker Put(large_key, "end");
463*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
464*9507f98cSAndroid Build Coastguard Worker }
465*9507f98cSAndroid Build Coastguard Worker }
466*9507f98cSAndroid Build Coastguard Worker
467*9507f98cSAndroid Build Coastguard Worker // Prevent pushing of new sstables into deeper levels by adding
468*9507f98cSAndroid Build Coastguard Worker // tables that cover a specified range to all levels.
FillLevels(const std::string & smallest,const std::string & largest)469*9507f98cSAndroid Build Coastguard Worker void FillLevels(const std::string& smallest, const std::string& largest) {
470*9507f98cSAndroid Build Coastguard Worker MakeTables(config::kNumLevels, smallest, largest);
471*9507f98cSAndroid Build Coastguard Worker }
472*9507f98cSAndroid Build Coastguard Worker
DumpFileCounts(const char * label)473*9507f98cSAndroid Build Coastguard Worker void DumpFileCounts(const char* label) {
474*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "---\n%s:\n", label);
475*9507f98cSAndroid Build Coastguard Worker std::fprintf(
476*9507f98cSAndroid Build Coastguard Worker stderr, "maxoverlap: %lld\n",
477*9507f98cSAndroid Build Coastguard Worker static_cast<long long>(dbfull()->TEST_MaxNextLevelOverlappingBytes()));
478*9507f98cSAndroid Build Coastguard Worker for (int level = 0; level < config::kNumLevels; level++) {
479*9507f98cSAndroid Build Coastguard Worker int num = NumTableFilesAtLevel(level);
480*9507f98cSAndroid Build Coastguard Worker if (num > 0) {
481*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, " level %3d : %d files\n", level, num);
482*9507f98cSAndroid Build Coastguard Worker }
483*9507f98cSAndroid Build Coastguard Worker }
484*9507f98cSAndroid Build Coastguard Worker }
485*9507f98cSAndroid Build Coastguard Worker
DumpSSTableList()486*9507f98cSAndroid Build Coastguard Worker std::string DumpSSTableList() {
487*9507f98cSAndroid Build Coastguard Worker std::string property;
488*9507f98cSAndroid Build Coastguard Worker db_->GetProperty("leveldb.sstables", &property);
489*9507f98cSAndroid Build Coastguard Worker return property;
490*9507f98cSAndroid Build Coastguard Worker }
491*9507f98cSAndroid Build Coastguard Worker
IterStatus(Iterator * iter)492*9507f98cSAndroid Build Coastguard Worker std::string IterStatus(Iterator* iter) {
493*9507f98cSAndroid Build Coastguard Worker std::string result;
494*9507f98cSAndroid Build Coastguard Worker if (iter->Valid()) {
495*9507f98cSAndroid Build Coastguard Worker result = iter->key().ToString() + "->" + iter->value().ToString();
496*9507f98cSAndroid Build Coastguard Worker } else {
497*9507f98cSAndroid Build Coastguard Worker result = "(invalid)";
498*9507f98cSAndroid Build Coastguard Worker }
499*9507f98cSAndroid Build Coastguard Worker return result;
500*9507f98cSAndroid Build Coastguard Worker }
501*9507f98cSAndroid Build Coastguard Worker
DeleteAnSSTFile()502*9507f98cSAndroid Build Coastguard Worker bool DeleteAnSSTFile() {
503*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> filenames;
504*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(env_->GetChildren(dbname_, &filenames));
505*9507f98cSAndroid Build Coastguard Worker uint64_t number;
506*9507f98cSAndroid Build Coastguard Worker FileType type;
507*9507f98cSAndroid Build Coastguard Worker for (size_t i = 0; i < filenames.size(); i++) {
508*9507f98cSAndroid Build Coastguard Worker if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
509*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(env_->RemoveFile(TableFileName(dbname_, number)));
510*9507f98cSAndroid Build Coastguard Worker return true;
511*9507f98cSAndroid Build Coastguard Worker }
512*9507f98cSAndroid Build Coastguard Worker }
513*9507f98cSAndroid Build Coastguard Worker return false;
514*9507f98cSAndroid Build Coastguard Worker }
515*9507f98cSAndroid Build Coastguard Worker
516*9507f98cSAndroid Build Coastguard Worker // Returns number of files renamed.
RenameLDBToSST()517*9507f98cSAndroid Build Coastguard Worker int RenameLDBToSST() {
518*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> filenames;
519*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(env_->GetChildren(dbname_, &filenames));
520*9507f98cSAndroid Build Coastguard Worker uint64_t number;
521*9507f98cSAndroid Build Coastguard Worker FileType type;
522*9507f98cSAndroid Build Coastguard Worker int files_renamed = 0;
523*9507f98cSAndroid Build Coastguard Worker for (size_t i = 0; i < filenames.size(); i++) {
524*9507f98cSAndroid Build Coastguard Worker if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
525*9507f98cSAndroid Build Coastguard Worker const std::string from = TableFileName(dbname_, number);
526*9507f98cSAndroid Build Coastguard Worker const std::string to = SSTTableFileName(dbname_, number);
527*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(env_->RenameFile(from, to));
528*9507f98cSAndroid Build Coastguard Worker files_renamed++;
529*9507f98cSAndroid Build Coastguard Worker }
530*9507f98cSAndroid Build Coastguard Worker }
531*9507f98cSAndroid Build Coastguard Worker return files_renamed;
532*9507f98cSAndroid Build Coastguard Worker }
533*9507f98cSAndroid Build Coastguard Worker
534*9507f98cSAndroid Build Coastguard Worker private:
535*9507f98cSAndroid Build Coastguard Worker // Sequence of option configurations to try
536*9507f98cSAndroid Build Coastguard Worker enum OptionConfig { kDefault, kReuse, kFilter, kUncompressed, kEnd };
537*9507f98cSAndroid Build Coastguard Worker
538*9507f98cSAndroid Build Coastguard Worker const FilterPolicy* filter_policy_;
539*9507f98cSAndroid Build Coastguard Worker int option_config_;
540*9507f98cSAndroid Build Coastguard Worker };
541*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Empty)542*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Empty) {
543*9507f98cSAndroid Build Coastguard Worker do {
544*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db_ != nullptr);
545*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("foo"));
546*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
547*9507f98cSAndroid Build Coastguard Worker }
548*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,EmptyKey)549*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, EmptyKey) {
550*9507f98cSAndroid Build Coastguard Worker do {
551*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("", "v1"));
552*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(""));
553*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("", "v2"));
554*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get(""));
555*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
556*9507f98cSAndroid Build Coastguard Worker }
557*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,EmptyValue)558*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, EmptyValue) {
559*9507f98cSAndroid Build Coastguard Worker do {
560*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("key", "v1"));
561*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("key"));
562*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("key", ""));
563*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("", Get("key"));
564*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("key", "v2"));
565*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("key"));
566*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
567*9507f98cSAndroid Build Coastguard Worker }
568*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ReadWrite)569*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ReadWrite) {
570*9507f98cSAndroid Build Coastguard Worker do {
571*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
572*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
573*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("bar", "v2"));
574*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v3"));
575*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v3", Get("foo"));
576*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("bar"));
577*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
578*9507f98cSAndroid Build Coastguard Worker }
579*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,PutDeleteGet)580*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, PutDeleteGet) {
581*9507f98cSAndroid Build Coastguard Worker do {
582*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Put(WriteOptions(), "foo", "v1"));
583*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
584*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Put(WriteOptions(), "foo", "v2"));
585*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo"));
586*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Delete(WriteOptions(), "foo"));
587*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("foo"));
588*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
589*9507f98cSAndroid Build Coastguard Worker }
590*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetFromImmutableLayer)591*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetFromImmutableLayer) {
592*9507f98cSAndroid Build Coastguard Worker do {
593*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
594*9507f98cSAndroid Build Coastguard Worker options.env = env_;
595*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 100000; // Small write buffer
596*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
597*9507f98cSAndroid Build Coastguard Worker
598*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
599*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
600*9507f98cSAndroid Build Coastguard Worker
601*9507f98cSAndroid Build Coastguard Worker // Block sync calls.
602*9507f98cSAndroid Build Coastguard Worker env_->delay_data_sync_.store(true, std::memory_order_release);
603*9507f98cSAndroid Build Coastguard Worker Put("k1", std::string(100000, 'x')); // Fill memtable.
604*9507f98cSAndroid Build Coastguard Worker Put("k2", std::string(100000, 'y')); // Trigger compaction.
605*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
606*9507f98cSAndroid Build Coastguard Worker // Release sync calls.
607*9507f98cSAndroid Build Coastguard Worker env_->delay_data_sync_.store(false, std::memory_order_release);
608*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
609*9507f98cSAndroid Build Coastguard Worker }
610*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetFromVersions)611*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetFromVersions) {
612*9507f98cSAndroid Build Coastguard Worker do {
613*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
614*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
615*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
616*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
617*9507f98cSAndroid Build Coastguard Worker }
618*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetMemUsage)619*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetMemUsage) {
620*9507f98cSAndroid Build Coastguard Worker do {
621*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
622*9507f98cSAndroid Build Coastguard Worker std::string val;
623*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db_->GetProperty("leveldb.approximate-memory-usage", &val));
624*9507f98cSAndroid Build Coastguard Worker int mem_usage = std::stoi(val);
625*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(mem_usage, 0);
626*9507f98cSAndroid Build Coastguard Worker ASSERT_LT(mem_usage, 5 * 1024 * 1024);
627*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
628*9507f98cSAndroid Build Coastguard Worker }
629*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetSnapshot)630*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetSnapshot) {
631*9507f98cSAndroid Build Coastguard Worker do {
632*9507f98cSAndroid Build Coastguard Worker // Try with both a short key and a long key
633*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
634*9507f98cSAndroid Build Coastguard Worker std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x');
635*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(key, "v1"));
636*9507f98cSAndroid Build Coastguard Worker const Snapshot* s1 = db_->GetSnapshot();
637*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(key, "v2"));
638*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get(key));
639*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s1));
640*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
641*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get(key));
642*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s1));
643*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s1);
644*9507f98cSAndroid Build Coastguard Worker }
645*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
646*9507f98cSAndroid Build Coastguard Worker }
647*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetIdenticalSnapshots)648*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetIdenticalSnapshots) {
649*9507f98cSAndroid Build Coastguard Worker do {
650*9507f98cSAndroid Build Coastguard Worker // Try with both a short key and a long key
651*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
652*9507f98cSAndroid Build Coastguard Worker std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x');
653*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(key, "v1"));
654*9507f98cSAndroid Build Coastguard Worker const Snapshot* s1 = db_->GetSnapshot();
655*9507f98cSAndroid Build Coastguard Worker const Snapshot* s2 = db_->GetSnapshot();
656*9507f98cSAndroid Build Coastguard Worker const Snapshot* s3 = db_->GetSnapshot();
657*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(key, "v2"));
658*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get(key));
659*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s1));
660*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s2));
661*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s3));
662*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s1);
663*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
664*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get(key));
665*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s2));
666*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s2);
667*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get(key, s3));
668*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s3);
669*9507f98cSAndroid Build Coastguard Worker }
670*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
671*9507f98cSAndroid Build Coastguard Worker }
672*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterateOverEmptySnapshot)673*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterateOverEmptySnapshot) {
674*9507f98cSAndroid Build Coastguard Worker do {
675*9507f98cSAndroid Build Coastguard Worker const Snapshot* snapshot = db_->GetSnapshot();
676*9507f98cSAndroid Build Coastguard Worker ReadOptions read_options;
677*9507f98cSAndroid Build Coastguard Worker read_options.snapshot = snapshot;
678*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
679*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
680*9507f98cSAndroid Build Coastguard Worker
681*9507f98cSAndroid Build Coastguard Worker Iterator* iterator1 = db_->NewIterator(read_options);
682*9507f98cSAndroid Build Coastguard Worker iterator1->SeekToFirst();
683*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iterator1->Valid());
684*9507f98cSAndroid Build Coastguard Worker delete iterator1;
685*9507f98cSAndroid Build Coastguard Worker
686*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
687*9507f98cSAndroid Build Coastguard Worker
688*9507f98cSAndroid Build Coastguard Worker Iterator* iterator2 = db_->NewIterator(read_options);
689*9507f98cSAndroid Build Coastguard Worker iterator2->SeekToFirst();
690*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iterator2->Valid());
691*9507f98cSAndroid Build Coastguard Worker delete iterator2;
692*9507f98cSAndroid Build Coastguard Worker
693*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(snapshot);
694*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
695*9507f98cSAndroid Build Coastguard Worker }
696*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetLevel0Ordering)697*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetLevel0Ordering) {
698*9507f98cSAndroid Build Coastguard Worker do {
699*9507f98cSAndroid Build Coastguard Worker // Check that we process level-0 files in correct order. The code
700*9507f98cSAndroid Build Coastguard Worker // below generates two level-0 files where the earlier one comes
701*9507f98cSAndroid Build Coastguard Worker // before the later one in the level-0 file list since the earlier
702*9507f98cSAndroid Build Coastguard Worker // one has a smaller "smallest" key.
703*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("bar", "b"));
704*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
705*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
706*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
707*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
708*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo"));
709*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
710*9507f98cSAndroid Build Coastguard Worker }
711*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetOrderedByLevels)712*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetOrderedByLevels) {
713*9507f98cSAndroid Build Coastguard Worker do {
714*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
715*9507f98cSAndroid Build Coastguard Worker Compact("a", "z");
716*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
717*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
718*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo"));
719*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
720*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo"));
721*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
722*9507f98cSAndroid Build Coastguard Worker }
723*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetPicksCorrectFile)724*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetPicksCorrectFile) {
725*9507f98cSAndroid Build Coastguard Worker do {
726*9507f98cSAndroid Build Coastguard Worker // Arrange to have multiple files in a non-level-0 level.
727*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
728*9507f98cSAndroid Build Coastguard Worker Compact("a", "b");
729*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("x", "vx"));
730*9507f98cSAndroid Build Coastguard Worker Compact("x", "y");
731*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("f", "vf"));
732*9507f98cSAndroid Build Coastguard Worker Compact("f", "g");
733*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("va", Get("a"));
734*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("vf", Get("f"));
735*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("vx", Get("x"));
736*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
737*9507f98cSAndroid Build Coastguard Worker }
738*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,GetEncountersEmptyLevel)739*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, GetEncountersEmptyLevel) {
740*9507f98cSAndroid Build Coastguard Worker do {
741*9507f98cSAndroid Build Coastguard Worker // Arrange for the following to happen:
742*9507f98cSAndroid Build Coastguard Worker // * sstable A in level 0
743*9507f98cSAndroid Build Coastguard Worker // * nothing in level 1
744*9507f98cSAndroid Build Coastguard Worker // * sstable B in level 2
745*9507f98cSAndroid Build Coastguard Worker // Then do enough Get() calls to arrange for an automatic compaction
746*9507f98cSAndroid Build Coastguard Worker // of sstable A. A bug would cause the compaction to be marked as
747*9507f98cSAndroid Build Coastguard Worker // occurring at level 1 (instead of the correct level 0).
748*9507f98cSAndroid Build Coastguard Worker
749*9507f98cSAndroid Build Coastguard Worker // Step 1: First place sstables in levels 0 and 2
750*9507f98cSAndroid Build Coastguard Worker int compaction_count = 0;
751*9507f98cSAndroid Build Coastguard Worker while (NumTableFilesAtLevel(0) == 0 || NumTableFilesAtLevel(2) == 0) {
752*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2";
753*9507f98cSAndroid Build Coastguard Worker compaction_count++;
754*9507f98cSAndroid Build Coastguard Worker Put("a", "begin");
755*9507f98cSAndroid Build Coastguard Worker Put("z", "end");
756*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
757*9507f98cSAndroid Build Coastguard Worker }
758*9507f98cSAndroid Build Coastguard Worker
759*9507f98cSAndroid Build Coastguard Worker // Step 2: clear level 1 if necessary.
760*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(1, nullptr, nullptr);
761*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 1);
762*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(1), 0);
763*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(2), 1);
764*9507f98cSAndroid Build Coastguard Worker
765*9507f98cSAndroid Build Coastguard Worker // Step 3: read a bunch of times
766*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 1000; i++) {
767*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("missing"));
768*9507f98cSAndroid Build Coastguard Worker }
769*9507f98cSAndroid Build Coastguard Worker
770*9507f98cSAndroid Build Coastguard Worker // Step 4: Wait for compaction to finish
771*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(1000);
772*9507f98cSAndroid Build Coastguard Worker
773*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
774*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
775*9507f98cSAndroid Build Coastguard Worker }
776*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterEmpty)777*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterEmpty) {
778*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
779*9507f98cSAndroid Build Coastguard Worker
780*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
781*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
782*9507f98cSAndroid Build Coastguard Worker
783*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
784*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
785*9507f98cSAndroid Build Coastguard Worker
786*9507f98cSAndroid Build Coastguard Worker iter->Seek("foo");
787*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
788*9507f98cSAndroid Build Coastguard Worker
789*9507f98cSAndroid Build Coastguard Worker delete iter;
790*9507f98cSAndroid Build Coastguard Worker }
791*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterSingle)792*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterSingle) {
793*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
794*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
795*9507f98cSAndroid Build Coastguard Worker
796*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
797*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
798*9507f98cSAndroid Build Coastguard Worker iter->Next();
799*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
800*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
801*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
802*9507f98cSAndroid Build Coastguard Worker iter->Prev();
803*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
804*9507f98cSAndroid Build Coastguard Worker
805*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
806*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
807*9507f98cSAndroid Build Coastguard Worker iter->Next();
808*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
809*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
810*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
811*9507f98cSAndroid Build Coastguard Worker iter->Prev();
812*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
813*9507f98cSAndroid Build Coastguard Worker
814*9507f98cSAndroid Build Coastguard Worker iter->Seek("");
815*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
816*9507f98cSAndroid Build Coastguard Worker iter->Next();
817*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
818*9507f98cSAndroid Build Coastguard Worker
819*9507f98cSAndroid Build Coastguard Worker iter->Seek("a");
820*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
821*9507f98cSAndroid Build Coastguard Worker iter->Next();
822*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
823*9507f98cSAndroid Build Coastguard Worker
824*9507f98cSAndroid Build Coastguard Worker iter->Seek("b");
825*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
826*9507f98cSAndroid Build Coastguard Worker
827*9507f98cSAndroid Build Coastguard Worker delete iter;
828*9507f98cSAndroid Build Coastguard Worker }
829*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterMulti)830*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterMulti) {
831*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
832*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", "vb"));
833*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("c", "vc"));
834*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
835*9507f98cSAndroid Build Coastguard Worker
836*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
837*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
838*9507f98cSAndroid Build Coastguard Worker iter->Next();
839*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
840*9507f98cSAndroid Build Coastguard Worker iter->Next();
841*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
842*9507f98cSAndroid Build Coastguard Worker iter->Next();
843*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
844*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
845*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
846*9507f98cSAndroid Build Coastguard Worker iter->Prev();
847*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
848*9507f98cSAndroid Build Coastguard Worker
849*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
850*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
851*9507f98cSAndroid Build Coastguard Worker iter->Prev();
852*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
853*9507f98cSAndroid Build Coastguard Worker iter->Prev();
854*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
855*9507f98cSAndroid Build Coastguard Worker iter->Prev();
856*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
857*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
858*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
859*9507f98cSAndroid Build Coastguard Worker iter->Next();
860*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
861*9507f98cSAndroid Build Coastguard Worker
862*9507f98cSAndroid Build Coastguard Worker iter->Seek("");
863*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
864*9507f98cSAndroid Build Coastguard Worker iter->Seek("a");
865*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
866*9507f98cSAndroid Build Coastguard Worker iter->Seek("ax");
867*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
868*9507f98cSAndroid Build Coastguard Worker iter->Seek("b");
869*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
870*9507f98cSAndroid Build Coastguard Worker iter->Seek("z");
871*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
872*9507f98cSAndroid Build Coastguard Worker
873*9507f98cSAndroid Build Coastguard Worker // Switch from reverse to forward
874*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
875*9507f98cSAndroid Build Coastguard Worker iter->Prev();
876*9507f98cSAndroid Build Coastguard Worker iter->Prev();
877*9507f98cSAndroid Build Coastguard Worker iter->Next();
878*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
879*9507f98cSAndroid Build Coastguard Worker
880*9507f98cSAndroid Build Coastguard Worker // Switch from forward to reverse
881*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
882*9507f98cSAndroid Build Coastguard Worker iter->Next();
883*9507f98cSAndroid Build Coastguard Worker iter->Next();
884*9507f98cSAndroid Build Coastguard Worker iter->Prev();
885*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
886*9507f98cSAndroid Build Coastguard Worker
887*9507f98cSAndroid Build Coastguard Worker // Make sure iter stays at snapshot
888*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va2"));
889*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a2", "va3"));
890*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", "vb2"));
891*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("c", "vc2"));
892*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("b"));
893*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
894*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
895*9507f98cSAndroid Build Coastguard Worker iter->Next();
896*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
897*9507f98cSAndroid Build Coastguard Worker iter->Next();
898*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
899*9507f98cSAndroid Build Coastguard Worker iter->Next();
900*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
901*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
902*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
903*9507f98cSAndroid Build Coastguard Worker iter->Prev();
904*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->vb");
905*9507f98cSAndroid Build Coastguard Worker iter->Prev();
906*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
907*9507f98cSAndroid Build Coastguard Worker iter->Prev();
908*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
909*9507f98cSAndroid Build Coastguard Worker
910*9507f98cSAndroid Build Coastguard Worker delete iter;
911*9507f98cSAndroid Build Coastguard Worker }
912*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterSmallAndLargeMix)913*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterSmallAndLargeMix) {
914*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
915*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", std::string(100000, 'b')));
916*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("c", "vc"));
917*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("d", std::string(100000, 'd')));
918*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("e", std::string(100000, 'e')));
919*9507f98cSAndroid Build Coastguard Worker
920*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
921*9507f98cSAndroid Build Coastguard Worker
922*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
923*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
924*9507f98cSAndroid Build Coastguard Worker iter->Next();
925*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b'));
926*9507f98cSAndroid Build Coastguard Worker iter->Next();
927*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
928*9507f98cSAndroid Build Coastguard Worker iter->Next();
929*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd'));
930*9507f98cSAndroid Build Coastguard Worker iter->Next();
931*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e'));
932*9507f98cSAndroid Build Coastguard Worker iter->Next();
933*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
934*9507f98cSAndroid Build Coastguard Worker
935*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
936*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e'));
937*9507f98cSAndroid Build Coastguard Worker iter->Prev();
938*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd'));
939*9507f98cSAndroid Build Coastguard Worker iter->Prev();
940*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
941*9507f98cSAndroid Build Coastguard Worker iter->Prev();
942*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b'));
943*9507f98cSAndroid Build Coastguard Worker iter->Prev();
944*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
945*9507f98cSAndroid Build Coastguard Worker iter->Prev();
946*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "(invalid)");
947*9507f98cSAndroid Build Coastguard Worker
948*9507f98cSAndroid Build Coastguard Worker delete iter;
949*9507f98cSAndroid Build Coastguard Worker }
950*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterMultiWithDelete)951*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterMultiWithDelete) {
952*9507f98cSAndroid Build Coastguard Worker do {
953*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
954*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", "vb"));
955*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("c", "vc"));
956*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("b"));
957*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("b"));
958*9507f98cSAndroid Build Coastguard Worker
959*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
960*9507f98cSAndroid Build Coastguard Worker iter->Seek("c");
961*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
962*9507f98cSAndroid Build Coastguard Worker iter->Prev();
963*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
964*9507f98cSAndroid Build Coastguard Worker delete iter;
965*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
966*9507f98cSAndroid Build Coastguard Worker }
967*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IterMultiWithDeleteAndCompaction)968*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IterMultiWithDeleteAndCompaction) {
969*9507f98cSAndroid Build Coastguard Worker do {
970*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", "vb"));
971*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("c", "vc"));
972*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "va"));
973*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
974*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("b"));
975*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("b"));
976*9507f98cSAndroid Build Coastguard Worker
977*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
978*9507f98cSAndroid Build Coastguard Worker iter->Seek("c");
979*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
980*9507f98cSAndroid Build Coastguard Worker iter->Prev();
981*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "a->va");
982*9507f98cSAndroid Build Coastguard Worker iter->Seek("b");
983*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(IterStatus(iter), "c->vc");
984*9507f98cSAndroid Build Coastguard Worker delete iter;
985*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
986*9507f98cSAndroid Build Coastguard Worker }
987*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Recover)988*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Recover) {
989*9507f98cSAndroid Build Coastguard Worker do {
990*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
991*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("baz", "v5"));
992*9507f98cSAndroid Build Coastguard Worker
993*9507f98cSAndroid Build Coastguard Worker Reopen();
994*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
995*9507f98cSAndroid Build Coastguard Worker
996*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
997*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v5", Get("baz"));
998*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("bar", "v2"));
999*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v3"));
1000*9507f98cSAndroid Build Coastguard Worker
1001*9507f98cSAndroid Build Coastguard Worker Reopen();
1002*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v3", Get("foo"));
1003*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v4"));
1004*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v4", Get("foo"));
1005*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("bar"));
1006*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v5", Get("baz"));
1007*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1008*9507f98cSAndroid Build Coastguard Worker }
1009*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,RecoveryWithEmptyLog)1010*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, RecoveryWithEmptyLog) {
1011*9507f98cSAndroid Build Coastguard Worker do {
1012*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
1013*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
1014*9507f98cSAndroid Build Coastguard Worker Reopen();
1015*9507f98cSAndroid Build Coastguard Worker Reopen();
1016*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v3"));
1017*9507f98cSAndroid Build Coastguard Worker Reopen();
1018*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v3", Get("foo"));
1019*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1020*9507f98cSAndroid Build Coastguard Worker }
1021*9507f98cSAndroid Build Coastguard Worker
1022*9507f98cSAndroid Build Coastguard Worker // Check that writes done during a memtable compaction are recovered
1023*9507f98cSAndroid Build Coastguard Worker // if the database is shutdown during the memtable compaction.
TEST_F(DBTest,RecoverDuringMemtableCompaction)1024*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, RecoverDuringMemtableCompaction) {
1025*9507f98cSAndroid Build Coastguard Worker do {
1026*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1027*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1028*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 1000000;
1029*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1030*9507f98cSAndroid Build Coastguard Worker
1031*9507f98cSAndroid Build Coastguard Worker // Trigger a long memtable compaction and reopen the database during it
1032*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1")); // Goes to 1st log file
1033*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(
1034*9507f98cSAndroid Build Coastguard Worker Put("big1", std::string(10000000, 'x'))); // Fills memtable
1035*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(
1036*9507f98cSAndroid Build Coastguard Worker Put("big2", std::string(1000, 'y'))); // Triggers compaction
1037*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("bar", "v2")); // Goes to new log file
1038*9507f98cSAndroid Build Coastguard Worker
1039*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1040*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
1041*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("bar"));
1042*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(10000000, 'x'), Get("big1"));
1043*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(1000, 'y'), Get("big2"));
1044*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1045*9507f98cSAndroid Build Coastguard Worker }
1046*9507f98cSAndroid Build Coastguard Worker
Key(int i)1047*9507f98cSAndroid Build Coastguard Worker static std::string Key(int i) {
1048*9507f98cSAndroid Build Coastguard Worker char buf[100];
1049*9507f98cSAndroid Build Coastguard Worker std::snprintf(buf, sizeof(buf), "key%06d", i);
1050*9507f98cSAndroid Build Coastguard Worker return std::string(buf);
1051*9507f98cSAndroid Build Coastguard Worker }
1052*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,MinorCompactionsHappen)1053*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, MinorCompactionsHappen) {
1054*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1055*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 10000;
1056*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1057*9507f98cSAndroid Build Coastguard Worker
1058*9507f98cSAndroid Build Coastguard Worker const int N = 500;
1059*9507f98cSAndroid Build Coastguard Worker
1060*9507f98cSAndroid Build Coastguard Worker int starting_num_tables = TotalTableFiles();
1061*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1062*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(i), Key(i) + std::string(1000, 'v')));
1063*9507f98cSAndroid Build Coastguard Worker }
1064*9507f98cSAndroid Build Coastguard Worker int ending_num_tables = TotalTableFiles();
1065*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(ending_num_tables, starting_num_tables);
1066*9507f98cSAndroid Build Coastguard Worker
1067*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1068*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i)));
1069*9507f98cSAndroid Build Coastguard Worker }
1070*9507f98cSAndroid Build Coastguard Worker
1071*9507f98cSAndroid Build Coastguard Worker Reopen();
1072*9507f98cSAndroid Build Coastguard Worker
1073*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1074*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i)));
1075*9507f98cSAndroid Build Coastguard Worker }
1076*9507f98cSAndroid Build Coastguard Worker }
1077*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,RecoverWithLargeLog)1078*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, RecoverWithLargeLog) {
1079*9507f98cSAndroid Build Coastguard Worker {
1080*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1081*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1082*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("big1", std::string(200000, '1')));
1083*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("big2", std::string(200000, '2')));
1084*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("small3", std::string(10, '3')));
1085*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("small4", std::string(10, '4')));
1086*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1087*9507f98cSAndroid Build Coastguard Worker }
1088*9507f98cSAndroid Build Coastguard Worker
1089*9507f98cSAndroid Build Coastguard Worker // Make sure that if we re-open with a small write buffer size that
1090*9507f98cSAndroid Build Coastguard Worker // we flush table files in the middle of a large log file.
1091*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1092*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 100000;
1093*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1094*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 3);
1095*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(200000, '1'), Get("big1"));
1096*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(200000, '2'), Get("big2"));
1097*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(10, '3'), Get("small3"));
1098*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(std::string(10, '4'), Get("small4"));
1099*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(NumTableFilesAtLevel(0), 1);
1100*9507f98cSAndroid Build Coastguard Worker }
1101*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,CompactionsGenerateMultipleFiles)1102*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, CompactionsGenerateMultipleFiles) {
1103*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1104*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 100000000; // Large write buffer
1105*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1106*9507f98cSAndroid Build Coastguard Worker
1107*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
1108*9507f98cSAndroid Build Coastguard Worker
1109*9507f98cSAndroid Build Coastguard Worker // Write 8MB (80 values, each 100K)
1110*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1111*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> values;
1112*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 80; i++) {
1113*9507f98cSAndroid Build Coastguard Worker values.push_back(RandomString(&rnd, 100000));
1114*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(i), values[i]));
1115*9507f98cSAndroid Build Coastguard Worker }
1116*9507f98cSAndroid Build Coastguard Worker
1117*9507f98cSAndroid Build Coastguard Worker // Reopening moves updates to level-0
1118*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1119*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, nullptr, nullptr);
1120*9507f98cSAndroid Build Coastguard Worker
1121*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1122*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(NumTableFilesAtLevel(1), 1);
1123*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 80; i++) {
1124*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(Get(Key(i)), values[i]);
1125*9507f98cSAndroid Build Coastguard Worker }
1126*9507f98cSAndroid Build Coastguard Worker }
1127*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,RepeatedWritesToSameKey)1128*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, RepeatedWritesToSameKey) {
1129*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1130*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1131*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 100000; // Small write buffer
1132*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1133*9507f98cSAndroid Build Coastguard Worker
1134*9507f98cSAndroid Build Coastguard Worker // We must have at most one file per level except for level-0,
1135*9507f98cSAndroid Build Coastguard Worker // which may have up to kL0_StopWritesTrigger files.
1136*9507f98cSAndroid Build Coastguard Worker const int kMaxFiles = config::kNumLevels + config::kL0_StopWritesTrigger;
1137*9507f98cSAndroid Build Coastguard Worker
1138*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
1139*9507f98cSAndroid Build Coastguard Worker std::string value = RandomString(&rnd, 2 * options.write_buffer_size);
1140*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 5 * kMaxFiles; i++) {
1141*9507f98cSAndroid Build Coastguard Worker Put("key", value);
1142*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(TotalTableFiles(), kMaxFiles);
1143*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "after %d: %d files\n", i + 1, TotalTableFiles());
1144*9507f98cSAndroid Build Coastguard Worker }
1145*9507f98cSAndroid Build Coastguard Worker }
1146*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,SparseMerge)1147*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, SparseMerge) {
1148*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1149*9507f98cSAndroid Build Coastguard Worker options.compression = kNoCompression;
1150*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1151*9507f98cSAndroid Build Coastguard Worker
1152*9507f98cSAndroid Build Coastguard Worker FillLevels("A", "Z");
1153*9507f98cSAndroid Build Coastguard Worker
1154*9507f98cSAndroid Build Coastguard Worker // Suppose there is:
1155*9507f98cSAndroid Build Coastguard Worker // small amount of data with prefix A
1156*9507f98cSAndroid Build Coastguard Worker // large amount of data with prefix B
1157*9507f98cSAndroid Build Coastguard Worker // small amount of data with prefix C
1158*9507f98cSAndroid Build Coastguard Worker // and that recent updates have made small changes to all three prefixes.
1159*9507f98cSAndroid Build Coastguard Worker // Check that we do not do a compaction that merges all of B in one shot.
1160*9507f98cSAndroid Build Coastguard Worker const std::string value(1000, 'x');
1161*9507f98cSAndroid Build Coastguard Worker Put("A", "va");
1162*9507f98cSAndroid Build Coastguard Worker // Write approximately 100MB of "B" values
1163*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 100000; i++) {
1164*9507f98cSAndroid Build Coastguard Worker char key[100];
1165*9507f98cSAndroid Build Coastguard Worker std::snprintf(key, sizeof(key), "B%010d", i);
1166*9507f98cSAndroid Build Coastguard Worker Put(key, value);
1167*9507f98cSAndroid Build Coastguard Worker }
1168*9507f98cSAndroid Build Coastguard Worker Put("C", "vc");
1169*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1170*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, nullptr, nullptr);
1171*9507f98cSAndroid Build Coastguard Worker
1172*9507f98cSAndroid Build Coastguard Worker // Make sparse update
1173*9507f98cSAndroid Build Coastguard Worker Put("A", "va2");
1174*9507f98cSAndroid Build Coastguard Worker Put("B100", "bvalue2");
1175*9507f98cSAndroid Build Coastguard Worker Put("C", "vc2");
1176*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1177*9507f98cSAndroid Build Coastguard Worker
1178*9507f98cSAndroid Build Coastguard Worker // Compactions should not cause us to create a situation where
1179*9507f98cSAndroid Build Coastguard Worker // a file overlaps too much data at the next level.
1180*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
1181*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, nullptr, nullptr);
1182*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
1183*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(1, nullptr, nullptr);
1184*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20 * 1048576);
1185*9507f98cSAndroid Build Coastguard Worker }
1186*9507f98cSAndroid Build Coastguard Worker
Between(uint64_t val,uint64_t low,uint64_t high)1187*9507f98cSAndroid Build Coastguard Worker static bool Between(uint64_t val, uint64_t low, uint64_t high) {
1188*9507f98cSAndroid Build Coastguard Worker bool result = (val >= low) && (val <= high);
1189*9507f98cSAndroid Build Coastguard Worker if (!result) {
1190*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
1191*9507f98cSAndroid Build Coastguard Worker (unsigned long long)(val), (unsigned long long)(low),
1192*9507f98cSAndroid Build Coastguard Worker (unsigned long long)(high));
1193*9507f98cSAndroid Build Coastguard Worker }
1194*9507f98cSAndroid Build Coastguard Worker return result;
1195*9507f98cSAndroid Build Coastguard Worker }
1196*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ApproximateSizes)1197*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ApproximateSizes) {
1198*9507f98cSAndroid Build Coastguard Worker do {
1199*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1200*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 100000000; // Large write buffer
1201*9507f98cSAndroid Build Coastguard Worker options.compression = kNoCompression;
1202*9507f98cSAndroid Build Coastguard Worker DestroyAndReopen();
1203*9507f98cSAndroid Build Coastguard Worker
1204*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", "xyz"), 0, 0));
1205*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1206*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", "xyz"), 0, 0));
1207*9507f98cSAndroid Build Coastguard Worker
1208*9507f98cSAndroid Build Coastguard Worker // Write 8MB (80 values, each 100K)
1209*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1210*9507f98cSAndroid Build Coastguard Worker const int N = 80;
1211*9507f98cSAndroid Build Coastguard Worker static const int S1 = 100000;
1212*9507f98cSAndroid Build Coastguard Worker static const int S2 = 105000; // Allow some expansion from metadata
1213*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
1214*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1215*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(i), RandomString(&rnd, S1)));
1216*9507f98cSAndroid Build Coastguard Worker }
1217*9507f98cSAndroid Build Coastguard Worker
1218*9507f98cSAndroid Build Coastguard Worker // 0 because GetApproximateSizes() does not account for memtable space
1219*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(50)), 0, 0));
1220*9507f98cSAndroid Build Coastguard Worker
1221*9507f98cSAndroid Build Coastguard Worker if (options.reuse_logs) {
1222*9507f98cSAndroid Build Coastguard Worker // Recovery will reuse memtable, and GetApproximateSizes() does not
1223*9507f98cSAndroid Build Coastguard Worker // account for memtable usage;
1224*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1225*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(50)), 0, 0));
1226*9507f98cSAndroid Build Coastguard Worker continue;
1227*9507f98cSAndroid Build Coastguard Worker }
1228*9507f98cSAndroid Build Coastguard Worker
1229*9507f98cSAndroid Build Coastguard Worker // Check sizes across recovery by reopening a few times
1230*9507f98cSAndroid Build Coastguard Worker for (int run = 0; run < 3; run++) {
1231*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1232*9507f98cSAndroid Build Coastguard Worker
1233*9507f98cSAndroid Build Coastguard Worker for (int compact_start = 0; compact_start < N; compact_start += 10) {
1234*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i += 10) {
1235*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(i)), S1 * i, S2 * i));
1236*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(i) + ".suffix"), S1 * (i + 1),
1237*9507f98cSAndroid Build Coastguard Worker S2 * (i + 1)));
1238*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size(Key(i), Key(i + 10)), S1 * 10, S2 * 10));
1239*9507f98cSAndroid Build Coastguard Worker }
1240*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(50)), S1 * 50, S2 * 50));
1241*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(50) + ".suffix"), S1 * 50, S2 * 50));
1242*9507f98cSAndroid Build Coastguard Worker
1243*9507f98cSAndroid Build Coastguard Worker std::string cstart_str = Key(compact_start);
1244*9507f98cSAndroid Build Coastguard Worker std::string cend_str = Key(compact_start + 9);
1245*9507f98cSAndroid Build Coastguard Worker Slice cstart = cstart_str;
1246*9507f98cSAndroid Build Coastguard Worker Slice cend = cend_str;
1247*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, &cstart, &cend);
1248*9507f98cSAndroid Build Coastguard Worker }
1249*9507f98cSAndroid Build Coastguard Worker
1250*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1251*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(NumTableFilesAtLevel(1), 0);
1252*9507f98cSAndroid Build Coastguard Worker }
1253*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1254*9507f98cSAndroid Build Coastguard Worker }
1255*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ApproximateSizes_MixOfSmallAndLarge)1256*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ApproximateSizes_MixOfSmallAndLarge) {
1257*9507f98cSAndroid Build Coastguard Worker do {
1258*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1259*9507f98cSAndroid Build Coastguard Worker options.compression = kNoCompression;
1260*9507f98cSAndroid Build Coastguard Worker Reopen();
1261*9507f98cSAndroid Build Coastguard Worker
1262*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
1263*9507f98cSAndroid Build Coastguard Worker std::string big1 = RandomString(&rnd, 100000);
1264*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(0), RandomString(&rnd, 10000)));
1265*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(1), RandomString(&rnd, 10000)));
1266*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(2), big1));
1267*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(3), RandomString(&rnd, 10000)));
1268*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(4), big1));
1269*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(5), RandomString(&rnd, 10000)));
1270*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(6), RandomString(&rnd, 300000)));
1271*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(7), RandomString(&rnd, 10000)));
1272*9507f98cSAndroid Build Coastguard Worker
1273*9507f98cSAndroid Build Coastguard Worker if (options.reuse_logs) {
1274*9507f98cSAndroid Build Coastguard Worker // Need to force a memtable compaction since recovery does not do so.
1275*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable());
1276*9507f98cSAndroid Build Coastguard Worker }
1277*9507f98cSAndroid Build Coastguard Worker
1278*9507f98cSAndroid Build Coastguard Worker // Check sizes across recovery by reopening a few times
1279*9507f98cSAndroid Build Coastguard Worker for (int run = 0; run < 3; run++) {
1280*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1281*9507f98cSAndroid Build Coastguard Worker
1282*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(0)), 0, 0));
1283*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(1)), 10000, 11000));
1284*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(2)), 20000, 21000));
1285*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(3)), 120000, 121000));
1286*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(4)), 130000, 131000));
1287*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(5)), 230000, 231000));
1288*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(6)), 240000, 241000));
1289*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(7)), 540000, 541000));
1290*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", Key(8)), 550000, 560000));
1291*9507f98cSAndroid Build Coastguard Worker
1292*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000));
1293*9507f98cSAndroid Build Coastguard Worker
1294*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, nullptr, nullptr);
1295*9507f98cSAndroid Build Coastguard Worker }
1296*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1297*9507f98cSAndroid Build Coastguard Worker }
1298*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,IteratorPinsRef)1299*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, IteratorPinsRef) {
1300*9507f98cSAndroid Build Coastguard Worker Put("foo", "hello");
1301*9507f98cSAndroid Build Coastguard Worker
1302*9507f98cSAndroid Build Coastguard Worker // Get iterator that will yield the current contents of the DB.
1303*9507f98cSAndroid Build Coastguard Worker Iterator* iter = db_->NewIterator(ReadOptions());
1304*9507f98cSAndroid Build Coastguard Worker
1305*9507f98cSAndroid Build Coastguard Worker // Write to force compactions
1306*9507f98cSAndroid Build Coastguard Worker Put("foo", "newvalue1");
1307*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 100; i++) {
1308*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(
1309*9507f98cSAndroid Build Coastguard Worker Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values
1310*9507f98cSAndroid Build Coastguard Worker }
1311*9507f98cSAndroid Build Coastguard Worker Put("foo", "newvalue2");
1312*9507f98cSAndroid Build Coastguard Worker
1313*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
1314*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(iter->Valid());
1315*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("foo", iter->key().ToString());
1316*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("hello", iter->value().ToString());
1317*9507f98cSAndroid Build Coastguard Worker iter->Next();
1318*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
1319*9507f98cSAndroid Build Coastguard Worker delete iter;
1320*9507f98cSAndroid Build Coastguard Worker }
1321*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Snapshot)1322*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Snapshot) {
1323*9507f98cSAndroid Build Coastguard Worker do {
1324*9507f98cSAndroid Build Coastguard Worker Put("foo", "v1");
1325*9507f98cSAndroid Build Coastguard Worker const Snapshot* s1 = db_->GetSnapshot();
1326*9507f98cSAndroid Build Coastguard Worker Put("foo", "v2");
1327*9507f98cSAndroid Build Coastguard Worker const Snapshot* s2 = db_->GetSnapshot();
1328*9507f98cSAndroid Build Coastguard Worker Put("foo", "v3");
1329*9507f98cSAndroid Build Coastguard Worker const Snapshot* s3 = db_->GetSnapshot();
1330*9507f98cSAndroid Build Coastguard Worker
1331*9507f98cSAndroid Build Coastguard Worker Put("foo", "v4");
1332*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo", s1));
1333*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo", s2));
1334*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v3", Get("foo", s3));
1335*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v4", Get("foo"));
1336*9507f98cSAndroid Build Coastguard Worker
1337*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s3);
1338*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo", s1));
1339*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo", s2));
1340*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v4", Get("foo"));
1341*9507f98cSAndroid Build Coastguard Worker
1342*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s1);
1343*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v2", Get("foo", s2));
1344*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v4", Get("foo"));
1345*9507f98cSAndroid Build Coastguard Worker
1346*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(s2);
1347*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v4", Get("foo"));
1348*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1349*9507f98cSAndroid Build Coastguard Worker }
1350*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,HiddenValuesAreRemoved)1351*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, HiddenValuesAreRemoved) {
1352*9507f98cSAndroid Build Coastguard Worker do {
1353*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
1354*9507f98cSAndroid Build Coastguard Worker FillLevels("a", "z");
1355*9507f98cSAndroid Build Coastguard Worker
1356*9507f98cSAndroid Build Coastguard Worker std::string big = RandomString(&rnd, 50000);
1357*9507f98cSAndroid Build Coastguard Worker Put("foo", big);
1358*9507f98cSAndroid Build Coastguard Worker Put("pastfoo", "v");
1359*9507f98cSAndroid Build Coastguard Worker const Snapshot* snapshot = db_->GetSnapshot();
1360*9507f98cSAndroid Build Coastguard Worker Put("foo", "tiny");
1361*9507f98cSAndroid Build Coastguard Worker Put("pastfoo2", "v2"); // Advance sequence number one more
1362*9507f98cSAndroid Build Coastguard Worker
1363*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable());
1364*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(NumTableFilesAtLevel(0), 0);
1365*9507f98cSAndroid Build Coastguard Worker
1366*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(big, Get("foo", snapshot));
1367*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", "pastfoo"), 50000, 60000));
1368*9507f98cSAndroid Build Coastguard Worker db_->ReleaseSnapshot(snapshot);
1369*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]");
1370*9507f98cSAndroid Build Coastguard Worker Slice x("x");
1371*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(0, nullptr, &x);
1372*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
1373*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(0), 0);
1374*9507f98cSAndroid Build Coastguard Worker ASSERT_GE(NumTableFilesAtLevel(1), 1);
1375*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(1, nullptr, &x);
1376*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
1377*9507f98cSAndroid Build Coastguard Worker
1378*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000));
1379*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1380*9507f98cSAndroid Build Coastguard Worker }
1381*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,DeletionMarkers1)1382*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, DeletionMarkers1) {
1383*9507f98cSAndroid Build Coastguard Worker Put("foo", "v1");
1384*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable());
1385*9507f98cSAndroid Build Coastguard Worker const int last = config::kMaxMemCompactLevel;
1386*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
1387*9507f98cSAndroid Build Coastguard Worker
1388*9507f98cSAndroid Build Coastguard Worker // Place a table at level last-1 to prevent merging with preceding mutation
1389*9507f98cSAndroid Build Coastguard Worker Put("a", "begin");
1390*9507f98cSAndroid Build Coastguard Worker Put("z", "end");
1391*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1392*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last), 1);
1393*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last - 1), 1);
1394*9507f98cSAndroid Build Coastguard Worker
1395*9507f98cSAndroid Build Coastguard Worker Delete("foo");
1396*9507f98cSAndroid Build Coastguard Worker Put("foo", "v2");
1397*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]");
1398*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
1399*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]");
1400*9507f98cSAndroid Build Coastguard Worker Slice z("z");
1401*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(last - 2, nullptr, &z);
1402*9507f98cSAndroid Build Coastguard Worker // DEL eliminated, but v1 remains because we aren't compacting that level
1403*9507f98cSAndroid Build Coastguard Worker // (DEL can be eliminated because v2 hides v1).
1404*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]");
1405*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(last - 1, nullptr, nullptr);
1406*9507f98cSAndroid Build Coastguard Worker // Merging last-1 w/ last, so we are the base level for "foo", so
1407*9507f98cSAndroid Build Coastguard Worker // DEL is removed. (as is v1).
1408*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]");
1409*9507f98cSAndroid Build Coastguard Worker }
1410*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,DeletionMarkers2)1411*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, DeletionMarkers2) {
1412*9507f98cSAndroid Build Coastguard Worker Put("foo", "v1");
1413*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable());
1414*9507f98cSAndroid Build Coastguard Worker const int last = config::kMaxMemCompactLevel;
1415*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level
1416*9507f98cSAndroid Build Coastguard Worker
1417*9507f98cSAndroid Build Coastguard Worker // Place a table at level last-1 to prevent merging with preceding mutation
1418*9507f98cSAndroid Build Coastguard Worker Put("a", "begin");
1419*9507f98cSAndroid Build Coastguard Worker Put("z", "end");
1420*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1421*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last), 1);
1422*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last - 1), 1);
1423*9507f98cSAndroid Build Coastguard Worker
1424*9507f98cSAndroid Build Coastguard Worker Delete("foo");
1425*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
1426*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
1427*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
1428*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(last - 2, nullptr, nullptr);
1429*9507f98cSAndroid Build Coastguard Worker // DEL kept: "last" file overlaps
1430*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
1431*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(last - 1, nullptr, nullptr);
1432*9507f98cSAndroid Build Coastguard Worker // Merging last-1 w/ last, so we are the base level for "foo", so
1433*9507f98cSAndroid Build Coastguard Worker // DEL is removed. (as is v1).
1434*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(AllEntriesFor("foo"), "[ ]");
1435*9507f98cSAndroid Build Coastguard Worker }
1436*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,OverlapInLevel0)1437*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, OverlapInLevel0) {
1438*9507f98cSAndroid Build Coastguard Worker do {
1439*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config";
1440*9507f98cSAndroid Build Coastguard Worker
1441*9507f98cSAndroid Build Coastguard Worker // Fill levels 1 and 2 to disable the pushing of new memtables to levels >
1442*9507f98cSAndroid Build Coastguard Worker // 0.
1443*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("100", "v100"));
1444*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("999", "v999"));
1445*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1446*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("100"));
1447*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("999"));
1448*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1449*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("0,1,1", FilesPerLevel());
1450*9507f98cSAndroid Build Coastguard Worker
1451*9507f98cSAndroid Build Coastguard Worker // Make files spanning the following ranges in level-0:
1452*9507f98cSAndroid Build Coastguard Worker // files[0] 200 .. 900
1453*9507f98cSAndroid Build Coastguard Worker // files[1] 300 .. 500
1454*9507f98cSAndroid Build Coastguard Worker // Note that files are sorted by smallest key.
1455*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("300", "v300"));
1456*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("500", "v500"));
1457*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1458*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("200", "v200"));
1459*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("600", "v600"));
1460*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("900", "v900"));
1461*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1462*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("2,1,1", FilesPerLevel());
1463*9507f98cSAndroid Build Coastguard Worker
1464*9507f98cSAndroid Build Coastguard Worker // Compact away the placeholder files we created initially
1465*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(1, nullptr, nullptr);
1466*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(2, nullptr, nullptr);
1467*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("2", FilesPerLevel());
1468*9507f98cSAndroid Build Coastguard Worker
1469*9507f98cSAndroid Build Coastguard Worker // Do a memtable compaction. Before bug-fix, the compaction would
1470*9507f98cSAndroid Build Coastguard Worker // not detect the overlap with level-0 files and would incorrectly place
1471*9507f98cSAndroid Build Coastguard Worker // the deletion in a deeper level.
1472*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("600"));
1473*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1474*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("3", FilesPerLevel());
1475*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("600"));
1476*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
1477*9507f98cSAndroid Build Coastguard Worker }
1478*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,L0_CompactionBug_Issue44_a)1479*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, L0_CompactionBug_Issue44_a) {
1480*9507f98cSAndroid Build Coastguard Worker Reopen();
1481*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("b", "v"));
1482*9507f98cSAndroid Build Coastguard Worker Reopen();
1483*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("b"));
1484*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("a"));
1485*9507f98cSAndroid Build Coastguard Worker Reopen();
1486*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Delete("a"));
1487*9507f98cSAndroid Build Coastguard Worker Reopen();
1488*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("a", "v"));
1489*9507f98cSAndroid Build Coastguard Worker Reopen();
1490*9507f98cSAndroid Build Coastguard Worker Reopen();
1491*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("(a->v)", Contents());
1492*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(1000); // Wait for compaction to finish
1493*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("(a->v)", Contents());
1494*9507f98cSAndroid Build Coastguard Worker }
1495*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,L0_CompactionBug_Issue44_b)1496*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, L0_CompactionBug_Issue44_b) {
1497*9507f98cSAndroid Build Coastguard Worker Reopen();
1498*9507f98cSAndroid Build Coastguard Worker Put("", "");
1499*9507f98cSAndroid Build Coastguard Worker Reopen();
1500*9507f98cSAndroid Build Coastguard Worker Delete("e");
1501*9507f98cSAndroid Build Coastguard Worker Put("", "");
1502*9507f98cSAndroid Build Coastguard Worker Reopen();
1503*9507f98cSAndroid Build Coastguard Worker Put("c", "cv");
1504*9507f98cSAndroid Build Coastguard Worker Reopen();
1505*9507f98cSAndroid Build Coastguard Worker Put("", "");
1506*9507f98cSAndroid Build Coastguard Worker Reopen();
1507*9507f98cSAndroid Build Coastguard Worker Put("", "");
1508*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(1000); // Wait for compaction to finish
1509*9507f98cSAndroid Build Coastguard Worker Reopen();
1510*9507f98cSAndroid Build Coastguard Worker Put("d", "dv");
1511*9507f98cSAndroid Build Coastguard Worker Reopen();
1512*9507f98cSAndroid Build Coastguard Worker Put("", "");
1513*9507f98cSAndroid Build Coastguard Worker Reopen();
1514*9507f98cSAndroid Build Coastguard Worker Delete("d");
1515*9507f98cSAndroid Build Coastguard Worker Delete("b");
1516*9507f98cSAndroid Build Coastguard Worker Reopen();
1517*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("(->)(c->cv)", Contents());
1518*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(1000); // Wait for compaction to finish
1519*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("(->)(c->cv)", Contents());
1520*9507f98cSAndroid Build Coastguard Worker }
1521*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Fflush_Issue474)1522*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Fflush_Issue474) {
1523*9507f98cSAndroid Build Coastguard Worker static const int kNum = 100000;
1524*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed());
1525*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNum; i++) {
1526*9507f98cSAndroid Build Coastguard Worker std::fflush(nullptr);
1527*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(RandomKey(&rnd), RandomString(&rnd, 100)));
1528*9507f98cSAndroid Build Coastguard Worker }
1529*9507f98cSAndroid Build Coastguard Worker }
1530*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ComparatorCheck)1531*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ComparatorCheck) {
1532*9507f98cSAndroid Build Coastguard Worker class NewComparator : public Comparator {
1533*9507f98cSAndroid Build Coastguard Worker public:
1534*9507f98cSAndroid Build Coastguard Worker const char* Name() const override { return "leveldb.NewComparator"; }
1535*9507f98cSAndroid Build Coastguard Worker int Compare(const Slice& a, const Slice& b) const override {
1536*9507f98cSAndroid Build Coastguard Worker return BytewiseComparator()->Compare(a, b);
1537*9507f98cSAndroid Build Coastguard Worker }
1538*9507f98cSAndroid Build Coastguard Worker void FindShortestSeparator(std::string* s, const Slice& l) const override {
1539*9507f98cSAndroid Build Coastguard Worker BytewiseComparator()->FindShortestSeparator(s, l);
1540*9507f98cSAndroid Build Coastguard Worker }
1541*9507f98cSAndroid Build Coastguard Worker void FindShortSuccessor(std::string* key) const override {
1542*9507f98cSAndroid Build Coastguard Worker BytewiseComparator()->FindShortSuccessor(key);
1543*9507f98cSAndroid Build Coastguard Worker }
1544*9507f98cSAndroid Build Coastguard Worker };
1545*9507f98cSAndroid Build Coastguard Worker NewComparator cmp;
1546*9507f98cSAndroid Build Coastguard Worker Options new_options = CurrentOptions();
1547*9507f98cSAndroid Build Coastguard Worker new_options.comparator = &cmp;
1548*9507f98cSAndroid Build Coastguard Worker Status s = TryReopen(&new_options);
1549*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!s.ok());
1550*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos)
1551*9507f98cSAndroid Build Coastguard Worker << s.ToString();
1552*9507f98cSAndroid Build Coastguard Worker }
1553*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,CustomComparator)1554*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, CustomComparator) {
1555*9507f98cSAndroid Build Coastguard Worker class NumberComparator : public Comparator {
1556*9507f98cSAndroid Build Coastguard Worker public:
1557*9507f98cSAndroid Build Coastguard Worker const char* Name() const override { return "test.NumberComparator"; }
1558*9507f98cSAndroid Build Coastguard Worker int Compare(const Slice& a, const Slice& b) const override {
1559*9507f98cSAndroid Build Coastguard Worker return ToNumber(a) - ToNumber(b);
1560*9507f98cSAndroid Build Coastguard Worker }
1561*9507f98cSAndroid Build Coastguard Worker void FindShortestSeparator(std::string* s, const Slice& l) const override {
1562*9507f98cSAndroid Build Coastguard Worker ToNumber(*s); // Check format
1563*9507f98cSAndroid Build Coastguard Worker ToNumber(l); // Check format
1564*9507f98cSAndroid Build Coastguard Worker }
1565*9507f98cSAndroid Build Coastguard Worker void FindShortSuccessor(std::string* key) const override {
1566*9507f98cSAndroid Build Coastguard Worker ToNumber(*key); // Check format
1567*9507f98cSAndroid Build Coastguard Worker }
1568*9507f98cSAndroid Build Coastguard Worker
1569*9507f98cSAndroid Build Coastguard Worker private:
1570*9507f98cSAndroid Build Coastguard Worker static int ToNumber(const Slice& x) {
1571*9507f98cSAndroid Build Coastguard Worker // Check that there are no extra characters.
1572*9507f98cSAndroid Build Coastguard Worker EXPECT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size() - 1] == ']')
1573*9507f98cSAndroid Build Coastguard Worker << EscapeString(x);
1574*9507f98cSAndroid Build Coastguard Worker int val;
1575*9507f98cSAndroid Build Coastguard Worker char ignored;
1576*9507f98cSAndroid Build Coastguard Worker EXPECT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1)
1577*9507f98cSAndroid Build Coastguard Worker << EscapeString(x);
1578*9507f98cSAndroid Build Coastguard Worker return val;
1579*9507f98cSAndroid Build Coastguard Worker }
1580*9507f98cSAndroid Build Coastguard Worker };
1581*9507f98cSAndroid Build Coastguard Worker NumberComparator cmp;
1582*9507f98cSAndroid Build Coastguard Worker Options new_options = CurrentOptions();
1583*9507f98cSAndroid Build Coastguard Worker new_options.create_if_missing = true;
1584*9507f98cSAndroid Build Coastguard Worker new_options.comparator = &cmp;
1585*9507f98cSAndroid Build Coastguard Worker new_options.filter_policy = nullptr; // Cannot use bloom filters
1586*9507f98cSAndroid Build Coastguard Worker new_options.write_buffer_size = 1000; // Compact more often
1587*9507f98cSAndroid Build Coastguard Worker DestroyAndReopen(&new_options);
1588*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("[10]", "ten"));
1589*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("[0x14]", "twenty"));
1590*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
1591*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("ten", Get("[10]"));
1592*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("ten", Get("[0xa]"));
1593*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("twenty", Get("[20]"));
1594*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("twenty", Get("[0x14]"));
1595*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("[15]"));
1596*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("[0xf]"));
1597*9507f98cSAndroid Build Coastguard Worker Compact("[0]", "[9999]");
1598*9507f98cSAndroid Build Coastguard Worker }
1599*9507f98cSAndroid Build Coastguard Worker
1600*9507f98cSAndroid Build Coastguard Worker for (int run = 0; run < 2; run++) {
1601*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 1000; i++) {
1602*9507f98cSAndroid Build Coastguard Worker char buf[100];
1603*9507f98cSAndroid Build Coastguard Worker std::snprintf(buf, sizeof(buf), "[%d]", i * 10);
1604*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(buf, buf));
1605*9507f98cSAndroid Build Coastguard Worker }
1606*9507f98cSAndroid Build Coastguard Worker Compact("[0]", "[1000000]");
1607*9507f98cSAndroid Build Coastguard Worker }
1608*9507f98cSAndroid Build Coastguard Worker }
1609*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ManualCompaction)1610*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ManualCompaction) {
1611*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(config::kMaxMemCompactLevel, 2)
1612*9507f98cSAndroid Build Coastguard Worker << "Need to update this test to match kMaxMemCompactLevel";
1613*9507f98cSAndroid Build Coastguard Worker
1614*9507f98cSAndroid Build Coastguard Worker MakeTables(3, "p", "q");
1615*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("1,1,1", FilesPerLevel());
1616*9507f98cSAndroid Build Coastguard Worker
1617*9507f98cSAndroid Build Coastguard Worker // Compaction range falls before files
1618*9507f98cSAndroid Build Coastguard Worker Compact("", "c");
1619*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("1,1,1", FilesPerLevel());
1620*9507f98cSAndroid Build Coastguard Worker
1621*9507f98cSAndroid Build Coastguard Worker // Compaction range falls after files
1622*9507f98cSAndroid Build Coastguard Worker Compact("r", "z");
1623*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("1,1,1", FilesPerLevel());
1624*9507f98cSAndroid Build Coastguard Worker
1625*9507f98cSAndroid Build Coastguard Worker // Compaction range overlaps files
1626*9507f98cSAndroid Build Coastguard Worker Compact("p1", "p9");
1627*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("0,0,1", FilesPerLevel());
1628*9507f98cSAndroid Build Coastguard Worker
1629*9507f98cSAndroid Build Coastguard Worker // Populate a different range
1630*9507f98cSAndroid Build Coastguard Worker MakeTables(3, "c", "e");
1631*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("1,1,2", FilesPerLevel());
1632*9507f98cSAndroid Build Coastguard Worker
1633*9507f98cSAndroid Build Coastguard Worker // Compact just the new range
1634*9507f98cSAndroid Build Coastguard Worker Compact("b", "f");
1635*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("0,0,2", FilesPerLevel());
1636*9507f98cSAndroid Build Coastguard Worker
1637*9507f98cSAndroid Build Coastguard Worker // Compact all
1638*9507f98cSAndroid Build Coastguard Worker MakeTables(1, "a", "z");
1639*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("0,1,2", FilesPerLevel());
1640*9507f98cSAndroid Build Coastguard Worker db_->CompactRange(nullptr, nullptr);
1641*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("0,0,1", FilesPerLevel());
1642*9507f98cSAndroid Build Coastguard Worker }
1643*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,DBOpen_Options)1644*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, DBOpen_Options) {
1645*9507f98cSAndroid Build Coastguard Worker std::string dbname = testing::TempDir() + "db_options_test";
1646*9507f98cSAndroid Build Coastguard Worker DestroyDB(dbname, Options());
1647*9507f98cSAndroid Build Coastguard Worker
1648*9507f98cSAndroid Build Coastguard Worker // Does not exist, and create_if_missing == false: error
1649*9507f98cSAndroid Build Coastguard Worker DB* db = nullptr;
1650*9507f98cSAndroid Build Coastguard Worker Options opts;
1651*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = false;
1652*9507f98cSAndroid Build Coastguard Worker Status s = DB::Open(opts, dbname, &db);
1653*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != nullptr);
1654*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db == nullptr);
1655*9507f98cSAndroid Build Coastguard Worker
1656*9507f98cSAndroid Build Coastguard Worker // Does not exist, and create_if_missing == true: OK
1657*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = true;
1658*9507f98cSAndroid Build Coastguard Worker s = DB::Open(opts, dbname, &db);
1659*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(s);
1660*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db != nullptr);
1661*9507f98cSAndroid Build Coastguard Worker
1662*9507f98cSAndroid Build Coastguard Worker delete db;
1663*9507f98cSAndroid Build Coastguard Worker db = nullptr;
1664*9507f98cSAndroid Build Coastguard Worker
1665*9507f98cSAndroid Build Coastguard Worker // Does exist, and error_if_exists == true: error
1666*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = false;
1667*9507f98cSAndroid Build Coastguard Worker opts.error_if_exists = true;
1668*9507f98cSAndroid Build Coastguard Worker s = DB::Open(opts, dbname, &db);
1669*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != nullptr);
1670*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db == nullptr);
1671*9507f98cSAndroid Build Coastguard Worker
1672*9507f98cSAndroid Build Coastguard Worker // Does exist, and error_if_exists == false: OK
1673*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = true;
1674*9507f98cSAndroid Build Coastguard Worker opts.error_if_exists = false;
1675*9507f98cSAndroid Build Coastguard Worker s = DB::Open(opts, dbname, &db);
1676*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(s);
1677*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db != nullptr);
1678*9507f98cSAndroid Build Coastguard Worker
1679*9507f98cSAndroid Build Coastguard Worker delete db;
1680*9507f98cSAndroid Build Coastguard Worker db = nullptr;
1681*9507f98cSAndroid Build Coastguard Worker }
1682*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,DestroyEmptyDir)1683*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, DestroyEmptyDir) {
1684*9507f98cSAndroid Build Coastguard Worker std::string dbname = testing::TempDir() + "db_empty_dir";
1685*9507f98cSAndroid Build Coastguard Worker TestEnv env(Env::Default());
1686*9507f98cSAndroid Build Coastguard Worker env.RemoveDir(dbname);
1687*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!env.FileExists(dbname));
1688*9507f98cSAndroid Build Coastguard Worker
1689*9507f98cSAndroid Build Coastguard Worker Options opts;
1690*9507f98cSAndroid Build Coastguard Worker opts.env = &env;
1691*9507f98cSAndroid Build Coastguard Worker
1692*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(env.CreateDir(dbname));
1693*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(env.FileExists(dbname));
1694*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> children;
1695*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(env.GetChildren(dbname, &children));
1696*9507f98cSAndroid Build Coastguard Worker // The stock Env's do not filter out '.' and '..' special files.
1697*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(2, children.size());
1698*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(DestroyDB(dbname, opts));
1699*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!env.FileExists(dbname));
1700*9507f98cSAndroid Build Coastguard Worker
1701*9507f98cSAndroid Build Coastguard Worker // Should also be destroyed if Env is filtering out dot files.
1702*9507f98cSAndroid Build Coastguard Worker env.SetIgnoreDotFiles(true);
1703*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(env.CreateDir(dbname));
1704*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(env.FileExists(dbname));
1705*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(env.GetChildren(dbname, &children));
1706*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(0, children.size());
1707*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(DestroyDB(dbname, opts));
1708*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!env.FileExists(dbname));
1709*9507f98cSAndroid Build Coastguard Worker }
1710*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,DestroyOpenDB)1711*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, DestroyOpenDB) {
1712*9507f98cSAndroid Build Coastguard Worker std::string dbname = testing::TempDir() + "open_db_dir";
1713*9507f98cSAndroid Build Coastguard Worker env_->RemoveDir(dbname);
1714*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!env_->FileExists(dbname));
1715*9507f98cSAndroid Build Coastguard Worker
1716*9507f98cSAndroid Build Coastguard Worker Options opts;
1717*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = true;
1718*9507f98cSAndroid Build Coastguard Worker DB* db = nullptr;
1719*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(DB::Open(opts, dbname, &db));
1720*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db != nullptr);
1721*9507f98cSAndroid Build Coastguard Worker
1722*9507f98cSAndroid Build Coastguard Worker // Must fail to destroy an open db.
1723*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(env_->FileExists(dbname));
1724*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!DestroyDB(dbname, Options()).ok());
1725*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(env_->FileExists(dbname));
1726*9507f98cSAndroid Build Coastguard Worker
1727*9507f98cSAndroid Build Coastguard Worker delete db;
1728*9507f98cSAndroid Build Coastguard Worker db = nullptr;
1729*9507f98cSAndroid Build Coastguard Worker
1730*9507f98cSAndroid Build Coastguard Worker // Should succeed destroying a closed db.
1731*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(DestroyDB(dbname, Options()));
1732*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!env_->FileExists(dbname));
1733*9507f98cSAndroid Build Coastguard Worker }
1734*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Locking)1735*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Locking) {
1736*9507f98cSAndroid Build Coastguard Worker DB* db2 = nullptr;
1737*9507f98cSAndroid Build Coastguard Worker Status s = DB::Open(CurrentOptions(), dbname_, &db2);
1738*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db";
1739*9507f98cSAndroid Build Coastguard Worker }
1740*9507f98cSAndroid Build Coastguard Worker
1741*9507f98cSAndroid Build Coastguard Worker // Check that number of files does not grow when we are out of space
TEST_F(DBTest,NoSpace)1742*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, NoSpace) {
1743*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1744*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1745*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1746*9507f98cSAndroid Build Coastguard Worker
1747*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
1748*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("foo"));
1749*9507f98cSAndroid Build Coastguard Worker Compact("a", "z");
1750*9507f98cSAndroid Build Coastguard Worker const int num_files = CountFiles();
1751*9507f98cSAndroid Build Coastguard Worker // Force out-of-space errors.
1752*9507f98cSAndroid Build Coastguard Worker env_->no_space_.store(true, std::memory_order_release);
1753*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) {
1754*9507f98cSAndroid Build Coastguard Worker for (int level = 0; level < config::kNumLevels - 1; level++) {
1755*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(level, nullptr, nullptr);
1756*9507f98cSAndroid Build Coastguard Worker }
1757*9507f98cSAndroid Build Coastguard Worker }
1758*9507f98cSAndroid Build Coastguard Worker env_->no_space_.store(false, std::memory_order_release);
1759*9507f98cSAndroid Build Coastguard Worker ASSERT_LT(CountFiles(), num_files + 3);
1760*9507f98cSAndroid Build Coastguard Worker }
1761*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,NonWritableFileSystem)1762*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, NonWritableFileSystem) {
1763*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1764*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 1000;
1765*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1766*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1767*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v1"));
1768*9507f98cSAndroid Build Coastguard Worker // Force errors for new files.
1769*9507f98cSAndroid Build Coastguard Worker env_->non_writable_.store(true, std::memory_order_release);
1770*9507f98cSAndroid Build Coastguard Worker std::string big(100000, 'x');
1771*9507f98cSAndroid Build Coastguard Worker int errors = 0;
1772*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 20; i++) {
1773*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "iter %d; errors %d\n", i, errors);
1774*9507f98cSAndroid Build Coastguard Worker if (!Put("foo", big).ok()) {
1775*9507f98cSAndroid Build Coastguard Worker errors++;
1776*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(100);
1777*9507f98cSAndroid Build Coastguard Worker }
1778*9507f98cSAndroid Build Coastguard Worker }
1779*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(errors, 0);
1780*9507f98cSAndroid Build Coastguard Worker env_->non_writable_.store(false, std::memory_order_release);
1781*9507f98cSAndroid Build Coastguard Worker }
1782*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,WriteSyncError)1783*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, WriteSyncError) {
1784*9507f98cSAndroid Build Coastguard Worker // Check that log sync errors cause the DB to disallow future writes.
1785*9507f98cSAndroid Build Coastguard Worker
1786*9507f98cSAndroid Build Coastguard Worker // (a) Cause log sync calls to fail
1787*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1788*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1789*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1790*9507f98cSAndroid Build Coastguard Worker env_->data_sync_error_.store(true, std::memory_order_release);
1791*9507f98cSAndroid Build Coastguard Worker
1792*9507f98cSAndroid Build Coastguard Worker // (b) Normal write should succeed
1793*9507f98cSAndroid Build Coastguard Worker WriteOptions w;
1794*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Put(w, "k1", "v1"));
1795*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("k1"));
1796*9507f98cSAndroid Build Coastguard Worker
1797*9507f98cSAndroid Build Coastguard Worker // (c) Do a sync write; should fail
1798*9507f98cSAndroid Build Coastguard Worker w.sync = true;
1799*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok());
1800*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("k1"));
1801*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("k2"));
1802*9507f98cSAndroid Build Coastguard Worker
1803*9507f98cSAndroid Build Coastguard Worker // (d) make sync behave normally
1804*9507f98cSAndroid Build Coastguard Worker env_->data_sync_error_.store(false, std::memory_order_release);
1805*9507f98cSAndroid Build Coastguard Worker
1806*9507f98cSAndroid Build Coastguard Worker // (e) Do a non-sync write; should fail
1807*9507f98cSAndroid Build Coastguard Worker w.sync = false;
1808*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok());
1809*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("v1", Get("k1"));
1810*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("k2"));
1811*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get("k3"));
1812*9507f98cSAndroid Build Coastguard Worker }
1813*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,ManifestWriteError)1814*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, ManifestWriteError) {
1815*9507f98cSAndroid Build Coastguard Worker // Test for the following problem:
1816*9507f98cSAndroid Build Coastguard Worker // (a) Compaction produces file F
1817*9507f98cSAndroid Build Coastguard Worker // (b) Log record containing F is written to MANIFEST file, but Sync() fails
1818*9507f98cSAndroid Build Coastguard Worker // (c) GC deletes F
1819*9507f98cSAndroid Build Coastguard Worker // (d) After reopening DB, reads fail since deleted F is named in log record
1820*9507f98cSAndroid Build Coastguard Worker
1821*9507f98cSAndroid Build Coastguard Worker // We iterate twice. In the second iteration, everything is the
1822*9507f98cSAndroid Build Coastguard Worker // same except the log record never makes it to the MANIFEST file.
1823*9507f98cSAndroid Build Coastguard Worker for (int iter = 0; iter < 2; iter++) {
1824*9507f98cSAndroid Build Coastguard Worker std::atomic<bool>* error_type = (iter == 0) ? &env_->manifest_sync_error_
1825*9507f98cSAndroid Build Coastguard Worker : &env_->manifest_write_error_;
1826*9507f98cSAndroid Build Coastguard Worker
1827*9507f98cSAndroid Build Coastguard Worker // Insert foo=>bar mapping
1828*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1829*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1830*9507f98cSAndroid Build Coastguard Worker options.create_if_missing = true;
1831*9507f98cSAndroid Build Coastguard Worker options.error_if_exists = false;
1832*9507f98cSAndroid Build Coastguard Worker DestroyAndReopen(&options);
1833*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "bar"));
1834*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1835*9507f98cSAndroid Build Coastguard Worker
1836*9507f98cSAndroid Build Coastguard Worker // Memtable compaction (will succeed)
1837*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1838*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1839*9507f98cSAndroid Build Coastguard Worker const int last = config::kMaxMemCompactLevel;
1840*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level
1841*9507f98cSAndroid Build Coastguard Worker
1842*9507f98cSAndroid Build Coastguard Worker // Merging compaction (will fail)
1843*9507f98cSAndroid Build Coastguard Worker error_type->store(true, std::memory_order_release);
1844*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactRange(last, nullptr, nullptr); // Should fail
1845*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1846*9507f98cSAndroid Build Coastguard Worker
1847*9507f98cSAndroid Build Coastguard Worker // Recovery: should not lose data
1848*9507f98cSAndroid Build Coastguard Worker error_type->store(false, std::memory_order_release);
1849*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1850*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1851*9507f98cSAndroid Build Coastguard Worker }
1852*9507f98cSAndroid Build Coastguard Worker }
1853*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,MissingSSTFile)1854*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, MissingSSTFile) {
1855*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "bar"));
1856*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1857*9507f98cSAndroid Build Coastguard Worker
1858*9507f98cSAndroid Build Coastguard Worker // Dump the memtable to disk.
1859*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1860*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1861*9507f98cSAndroid Build Coastguard Worker
1862*9507f98cSAndroid Build Coastguard Worker Close();
1863*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(DeleteAnSSTFile());
1864*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1865*9507f98cSAndroid Build Coastguard Worker options.paranoid_checks = true;
1866*9507f98cSAndroid Build Coastguard Worker Status s = TryReopen(&options);
1867*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!s.ok());
1868*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) << s.ToString();
1869*9507f98cSAndroid Build Coastguard Worker }
1870*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,StillReadSST)1871*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, StillReadSST) {
1872*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "bar"));
1873*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1874*9507f98cSAndroid Build Coastguard Worker
1875*9507f98cSAndroid Build Coastguard Worker // Dump the memtable to disk.
1876*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1877*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1878*9507f98cSAndroid Build Coastguard Worker Close();
1879*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(RenameLDBToSST(), 0);
1880*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1881*9507f98cSAndroid Build Coastguard Worker options.paranoid_checks = true;
1882*9507f98cSAndroid Build Coastguard Worker Status s = TryReopen(&options);
1883*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(s.ok());
1884*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("bar", Get("foo"));
1885*9507f98cSAndroid Build Coastguard Worker }
1886*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,FilesDeletedAfterCompaction)1887*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, FilesDeletedAfterCompaction) {
1888*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
1889*9507f98cSAndroid Build Coastguard Worker Compact("a", "z");
1890*9507f98cSAndroid Build Coastguard Worker const int num_files = CountFiles();
1891*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) {
1892*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put("foo", "v2"));
1893*9507f98cSAndroid Build Coastguard Worker Compact("a", "z");
1894*9507f98cSAndroid Build Coastguard Worker }
1895*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(CountFiles(), num_files);
1896*9507f98cSAndroid Build Coastguard Worker }
1897*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,BloomFilter)1898*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, BloomFilter) {
1899*9507f98cSAndroid Build Coastguard Worker env_->count_random_reads_ = true;
1900*9507f98cSAndroid Build Coastguard Worker Options options = CurrentOptions();
1901*9507f98cSAndroid Build Coastguard Worker options.env = env_;
1902*9507f98cSAndroid Build Coastguard Worker options.block_cache = NewLRUCache(0); // Prevent cache hits
1903*9507f98cSAndroid Build Coastguard Worker options.filter_policy = NewBloomFilterPolicy(10);
1904*9507f98cSAndroid Build Coastguard Worker Reopen(&options);
1905*9507f98cSAndroid Build Coastguard Worker
1906*9507f98cSAndroid Build Coastguard Worker // Populate multiple layers
1907*9507f98cSAndroid Build Coastguard Worker const int N = 10000;
1908*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1909*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(i), Key(i)));
1910*9507f98cSAndroid Build Coastguard Worker }
1911*9507f98cSAndroid Build Coastguard Worker Compact("a", "z");
1912*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i += 100) {
1913*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(Put(Key(i), Key(i)));
1914*9507f98cSAndroid Build Coastguard Worker }
1915*9507f98cSAndroid Build Coastguard Worker dbfull()->TEST_CompactMemTable();
1916*9507f98cSAndroid Build Coastguard Worker
1917*9507f98cSAndroid Build Coastguard Worker // Prevent auto compactions triggered by seeks
1918*9507f98cSAndroid Build Coastguard Worker env_->delay_data_sync_.store(true, std::memory_order_release);
1919*9507f98cSAndroid Build Coastguard Worker
1920*9507f98cSAndroid Build Coastguard Worker // Lookup present keys. Should rarely read from small sstable.
1921*9507f98cSAndroid Build Coastguard Worker env_->random_read_counter_.Reset();
1922*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1923*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(Key(i), Get(Key(i)));
1924*9507f98cSAndroid Build Coastguard Worker }
1925*9507f98cSAndroid Build Coastguard Worker int reads = env_->random_read_counter_.Read();
1926*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "%d present => %d reads\n", N, reads);
1927*9507f98cSAndroid Build Coastguard Worker ASSERT_GE(reads, N);
1928*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(reads, N + 2 * N / 100);
1929*9507f98cSAndroid Build Coastguard Worker
1930*9507f98cSAndroid Build Coastguard Worker // Lookup present keys. Should rarely read from either sstable.
1931*9507f98cSAndroid Build Coastguard Worker env_->random_read_counter_.Reset();
1932*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < N; i++) {
1933*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing"));
1934*9507f98cSAndroid Build Coastguard Worker }
1935*9507f98cSAndroid Build Coastguard Worker reads = env_->random_read_counter_.Read();
1936*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "%d missing => %d reads\n", N, reads);
1937*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(reads, 3 * N / 100);
1938*9507f98cSAndroid Build Coastguard Worker
1939*9507f98cSAndroid Build Coastguard Worker env_->delay_data_sync_.store(false, std::memory_order_release);
1940*9507f98cSAndroid Build Coastguard Worker Close();
1941*9507f98cSAndroid Build Coastguard Worker delete options.block_cache;
1942*9507f98cSAndroid Build Coastguard Worker delete options.filter_policy;
1943*9507f98cSAndroid Build Coastguard Worker }
1944*9507f98cSAndroid Build Coastguard Worker
1945*9507f98cSAndroid Build Coastguard Worker // Multi-threaded test:
1946*9507f98cSAndroid Build Coastguard Worker namespace {
1947*9507f98cSAndroid Build Coastguard Worker
1948*9507f98cSAndroid Build Coastguard Worker static const int kNumThreads = 4;
1949*9507f98cSAndroid Build Coastguard Worker static const int kTestSeconds = 10;
1950*9507f98cSAndroid Build Coastguard Worker static const int kNumKeys = 1000;
1951*9507f98cSAndroid Build Coastguard Worker
1952*9507f98cSAndroid Build Coastguard Worker struct MTState {
1953*9507f98cSAndroid Build Coastguard Worker DBTest* test;
1954*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> stop;
1955*9507f98cSAndroid Build Coastguard Worker std::atomic<int> counter[kNumThreads];
1956*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> thread_done[kNumThreads];
1957*9507f98cSAndroid Build Coastguard Worker };
1958*9507f98cSAndroid Build Coastguard Worker
1959*9507f98cSAndroid Build Coastguard Worker struct MTThread {
1960*9507f98cSAndroid Build Coastguard Worker MTState* state;
1961*9507f98cSAndroid Build Coastguard Worker int id;
1962*9507f98cSAndroid Build Coastguard Worker };
1963*9507f98cSAndroid Build Coastguard Worker
MTThreadBody(void * arg)1964*9507f98cSAndroid Build Coastguard Worker static void MTThreadBody(void* arg) {
1965*9507f98cSAndroid Build Coastguard Worker MTThread* t = reinterpret_cast<MTThread*>(arg);
1966*9507f98cSAndroid Build Coastguard Worker int id = t->id;
1967*9507f98cSAndroid Build Coastguard Worker DB* db = t->state->test->db_;
1968*9507f98cSAndroid Build Coastguard Worker int counter = 0;
1969*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "... starting thread %d\n", id);
1970*9507f98cSAndroid Build Coastguard Worker Random rnd(1000 + id);
1971*9507f98cSAndroid Build Coastguard Worker std::string value;
1972*9507f98cSAndroid Build Coastguard Worker char valbuf[1500];
1973*9507f98cSAndroid Build Coastguard Worker while (!t->state->stop.load(std::memory_order_acquire)) {
1974*9507f98cSAndroid Build Coastguard Worker t->state->counter[id].store(counter, std::memory_order_release);
1975*9507f98cSAndroid Build Coastguard Worker
1976*9507f98cSAndroid Build Coastguard Worker int key = rnd.Uniform(kNumKeys);
1977*9507f98cSAndroid Build Coastguard Worker char keybuf[20];
1978*9507f98cSAndroid Build Coastguard Worker std::snprintf(keybuf, sizeof(keybuf), "%016d", key);
1979*9507f98cSAndroid Build Coastguard Worker
1980*9507f98cSAndroid Build Coastguard Worker if (rnd.OneIn(2)) {
1981*9507f98cSAndroid Build Coastguard Worker // Write values of the form <key, my id, counter>.
1982*9507f98cSAndroid Build Coastguard Worker // We add some padding for force compactions.
1983*9507f98cSAndroid Build Coastguard Worker std::snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", key, id,
1984*9507f98cSAndroid Build Coastguard Worker static_cast<int>(counter));
1985*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));
1986*9507f98cSAndroid Build Coastguard Worker } else {
1987*9507f98cSAndroid Build Coastguard Worker // Read a value and verify that it matches the pattern written above.
1988*9507f98cSAndroid Build Coastguard Worker Status s = db->Get(ReadOptions(), Slice(keybuf), &value);
1989*9507f98cSAndroid Build Coastguard Worker if (s.IsNotFound()) {
1990*9507f98cSAndroid Build Coastguard Worker // Key has not yet been written
1991*9507f98cSAndroid Build Coastguard Worker } else {
1992*9507f98cSAndroid Build Coastguard Worker // Check that the writer thread counter is >= the counter in the value
1993*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(s);
1994*9507f98cSAndroid Build Coastguard Worker int k, w, c;
1995*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value;
1996*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(k, key);
1997*9507f98cSAndroid Build Coastguard Worker ASSERT_GE(w, 0);
1998*9507f98cSAndroid Build Coastguard Worker ASSERT_LT(w, kNumThreads);
1999*9507f98cSAndroid Build Coastguard Worker ASSERT_LE(c, t->state->counter[w].load(std::memory_order_acquire));
2000*9507f98cSAndroid Build Coastguard Worker }
2001*9507f98cSAndroid Build Coastguard Worker }
2002*9507f98cSAndroid Build Coastguard Worker counter++;
2003*9507f98cSAndroid Build Coastguard Worker }
2004*9507f98cSAndroid Build Coastguard Worker t->state->thread_done[id].store(true, std::memory_order_release);
2005*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "... stopping thread %d after %d ops\n", id, counter);
2006*9507f98cSAndroid Build Coastguard Worker }
2007*9507f98cSAndroid Build Coastguard Worker
2008*9507f98cSAndroid Build Coastguard Worker } // namespace
2009*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,MultiThreaded)2010*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, MultiThreaded) {
2011*9507f98cSAndroid Build Coastguard Worker do {
2012*9507f98cSAndroid Build Coastguard Worker // Initialize state
2013*9507f98cSAndroid Build Coastguard Worker MTState mt;
2014*9507f98cSAndroid Build Coastguard Worker mt.test = this;
2015*9507f98cSAndroid Build Coastguard Worker mt.stop.store(false, std::memory_order_release);
2016*9507f98cSAndroid Build Coastguard Worker for (int id = 0; id < kNumThreads; id++) {
2017*9507f98cSAndroid Build Coastguard Worker mt.counter[id].store(false, std::memory_order_release);
2018*9507f98cSAndroid Build Coastguard Worker mt.thread_done[id].store(false, std::memory_order_release);
2019*9507f98cSAndroid Build Coastguard Worker }
2020*9507f98cSAndroid Build Coastguard Worker
2021*9507f98cSAndroid Build Coastguard Worker // Start threads
2022*9507f98cSAndroid Build Coastguard Worker MTThread thread[kNumThreads];
2023*9507f98cSAndroid Build Coastguard Worker for (int id = 0; id < kNumThreads; id++) {
2024*9507f98cSAndroid Build Coastguard Worker thread[id].state = &mt;
2025*9507f98cSAndroid Build Coastguard Worker thread[id].id = id;
2026*9507f98cSAndroid Build Coastguard Worker env_->StartThread(MTThreadBody, &thread[id]);
2027*9507f98cSAndroid Build Coastguard Worker }
2028*9507f98cSAndroid Build Coastguard Worker
2029*9507f98cSAndroid Build Coastguard Worker // Let them run for a while
2030*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(kTestSeconds * 1000);
2031*9507f98cSAndroid Build Coastguard Worker
2032*9507f98cSAndroid Build Coastguard Worker // Stop the threads and wait for them to finish
2033*9507f98cSAndroid Build Coastguard Worker mt.stop.store(true, std::memory_order_release);
2034*9507f98cSAndroid Build Coastguard Worker for (int id = 0; id < kNumThreads; id++) {
2035*9507f98cSAndroid Build Coastguard Worker while (!mt.thread_done[id].load(std::memory_order_acquire)) {
2036*9507f98cSAndroid Build Coastguard Worker DelayMilliseconds(100);
2037*9507f98cSAndroid Build Coastguard Worker }
2038*9507f98cSAndroid Build Coastguard Worker }
2039*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
2040*9507f98cSAndroid Build Coastguard Worker }
2041*9507f98cSAndroid Build Coastguard Worker
2042*9507f98cSAndroid Build Coastguard Worker namespace {
2043*9507f98cSAndroid Build Coastguard Worker typedef std::map<std::string, std::string> KVMap;
2044*9507f98cSAndroid Build Coastguard Worker }
2045*9507f98cSAndroid Build Coastguard Worker
2046*9507f98cSAndroid Build Coastguard Worker class ModelDB : public DB {
2047*9507f98cSAndroid Build Coastguard Worker public:
2048*9507f98cSAndroid Build Coastguard Worker class ModelSnapshot : public Snapshot {
2049*9507f98cSAndroid Build Coastguard Worker public:
2050*9507f98cSAndroid Build Coastguard Worker KVMap map_;
2051*9507f98cSAndroid Build Coastguard Worker };
2052*9507f98cSAndroid Build Coastguard Worker
ModelDB(const Options & options)2053*9507f98cSAndroid Build Coastguard Worker explicit ModelDB(const Options& options) : options_(options) {}
2054*9507f98cSAndroid Build Coastguard Worker ~ModelDB() override = default;
Put(const WriteOptions & o,const Slice & k,const Slice & v)2055*9507f98cSAndroid Build Coastguard Worker Status Put(const WriteOptions& o, const Slice& k, const Slice& v) override {
2056*9507f98cSAndroid Build Coastguard Worker return DB::Put(o, k, v);
2057*9507f98cSAndroid Build Coastguard Worker }
Delete(const WriteOptions & o,const Slice & key)2058*9507f98cSAndroid Build Coastguard Worker Status Delete(const WriteOptions& o, const Slice& key) override {
2059*9507f98cSAndroid Build Coastguard Worker return DB::Delete(o, key);
2060*9507f98cSAndroid Build Coastguard Worker }
Get(const ReadOptions & options,const Slice & key,std::string * value)2061*9507f98cSAndroid Build Coastguard Worker Status Get(const ReadOptions& options, const Slice& key,
2062*9507f98cSAndroid Build Coastguard Worker std::string* value) override {
2063*9507f98cSAndroid Build Coastguard Worker assert(false); // Not implemented
2064*9507f98cSAndroid Build Coastguard Worker return Status::NotFound(key);
2065*9507f98cSAndroid Build Coastguard Worker }
NewIterator(const ReadOptions & options)2066*9507f98cSAndroid Build Coastguard Worker Iterator* NewIterator(const ReadOptions& options) override {
2067*9507f98cSAndroid Build Coastguard Worker if (options.snapshot == nullptr) {
2068*9507f98cSAndroid Build Coastguard Worker KVMap* saved = new KVMap;
2069*9507f98cSAndroid Build Coastguard Worker *saved = map_;
2070*9507f98cSAndroid Build Coastguard Worker return new ModelIter(saved, true);
2071*9507f98cSAndroid Build Coastguard Worker } else {
2072*9507f98cSAndroid Build Coastguard Worker const KVMap* snapshot_state =
2073*9507f98cSAndroid Build Coastguard Worker &(reinterpret_cast<const ModelSnapshot*>(options.snapshot)->map_);
2074*9507f98cSAndroid Build Coastguard Worker return new ModelIter(snapshot_state, false);
2075*9507f98cSAndroid Build Coastguard Worker }
2076*9507f98cSAndroid Build Coastguard Worker }
GetSnapshot()2077*9507f98cSAndroid Build Coastguard Worker const Snapshot* GetSnapshot() override {
2078*9507f98cSAndroid Build Coastguard Worker ModelSnapshot* snapshot = new ModelSnapshot;
2079*9507f98cSAndroid Build Coastguard Worker snapshot->map_ = map_;
2080*9507f98cSAndroid Build Coastguard Worker return snapshot;
2081*9507f98cSAndroid Build Coastguard Worker }
2082*9507f98cSAndroid Build Coastguard Worker
ReleaseSnapshot(const Snapshot * snapshot)2083*9507f98cSAndroid Build Coastguard Worker void ReleaseSnapshot(const Snapshot* snapshot) override {
2084*9507f98cSAndroid Build Coastguard Worker delete reinterpret_cast<const ModelSnapshot*>(snapshot);
2085*9507f98cSAndroid Build Coastguard Worker }
Write(const WriteOptions & options,WriteBatch * batch)2086*9507f98cSAndroid Build Coastguard Worker Status Write(const WriteOptions& options, WriteBatch* batch) override {
2087*9507f98cSAndroid Build Coastguard Worker class Handler : public WriteBatch::Handler {
2088*9507f98cSAndroid Build Coastguard Worker public:
2089*9507f98cSAndroid Build Coastguard Worker KVMap* map_;
2090*9507f98cSAndroid Build Coastguard Worker void Put(const Slice& key, const Slice& value) override {
2091*9507f98cSAndroid Build Coastguard Worker (*map_)[key.ToString()] = value.ToString();
2092*9507f98cSAndroid Build Coastguard Worker }
2093*9507f98cSAndroid Build Coastguard Worker void Delete(const Slice& key) override { map_->erase(key.ToString()); }
2094*9507f98cSAndroid Build Coastguard Worker };
2095*9507f98cSAndroid Build Coastguard Worker Handler handler;
2096*9507f98cSAndroid Build Coastguard Worker handler.map_ = &map_;
2097*9507f98cSAndroid Build Coastguard Worker return batch->Iterate(&handler);
2098*9507f98cSAndroid Build Coastguard Worker }
2099*9507f98cSAndroid Build Coastguard Worker
GetProperty(const Slice & property,std::string * value)2100*9507f98cSAndroid Build Coastguard Worker bool GetProperty(const Slice& property, std::string* value) override {
2101*9507f98cSAndroid Build Coastguard Worker return false;
2102*9507f98cSAndroid Build Coastguard Worker }
GetApproximateSizes(const Range * r,int n,uint64_t * sizes)2103*9507f98cSAndroid Build Coastguard Worker void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) override {
2104*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < n; i++) {
2105*9507f98cSAndroid Build Coastguard Worker sizes[i] = 0;
2106*9507f98cSAndroid Build Coastguard Worker }
2107*9507f98cSAndroid Build Coastguard Worker }
CompactRange(const Slice * start,const Slice * end)2108*9507f98cSAndroid Build Coastguard Worker void CompactRange(const Slice* start, const Slice* end) override {}
2109*9507f98cSAndroid Build Coastguard Worker
2110*9507f98cSAndroid Build Coastguard Worker private:
2111*9507f98cSAndroid Build Coastguard Worker class ModelIter : public Iterator {
2112*9507f98cSAndroid Build Coastguard Worker public:
ModelIter(const KVMap * map,bool owned)2113*9507f98cSAndroid Build Coastguard Worker ModelIter(const KVMap* map, bool owned)
2114*9507f98cSAndroid Build Coastguard Worker : map_(map), owned_(owned), iter_(map_->end()) {}
~ModelIter()2115*9507f98cSAndroid Build Coastguard Worker ~ModelIter() override {
2116*9507f98cSAndroid Build Coastguard Worker if (owned_) delete map_;
2117*9507f98cSAndroid Build Coastguard Worker }
Valid() const2118*9507f98cSAndroid Build Coastguard Worker bool Valid() const override { return iter_ != map_->end(); }
SeekToFirst()2119*9507f98cSAndroid Build Coastguard Worker void SeekToFirst() override { iter_ = map_->begin(); }
SeekToLast()2120*9507f98cSAndroid Build Coastguard Worker void SeekToLast() override {
2121*9507f98cSAndroid Build Coastguard Worker if (map_->empty()) {
2122*9507f98cSAndroid Build Coastguard Worker iter_ = map_->end();
2123*9507f98cSAndroid Build Coastguard Worker } else {
2124*9507f98cSAndroid Build Coastguard Worker iter_ = map_->find(map_->rbegin()->first);
2125*9507f98cSAndroid Build Coastguard Worker }
2126*9507f98cSAndroid Build Coastguard Worker }
Seek(const Slice & k)2127*9507f98cSAndroid Build Coastguard Worker void Seek(const Slice& k) override {
2128*9507f98cSAndroid Build Coastguard Worker iter_ = map_->lower_bound(k.ToString());
2129*9507f98cSAndroid Build Coastguard Worker }
Next()2130*9507f98cSAndroid Build Coastguard Worker void Next() override { ++iter_; }
Prev()2131*9507f98cSAndroid Build Coastguard Worker void Prev() override { --iter_; }
key() const2132*9507f98cSAndroid Build Coastguard Worker Slice key() const override { return iter_->first; }
value() const2133*9507f98cSAndroid Build Coastguard Worker Slice value() const override { return iter_->second; }
status() const2134*9507f98cSAndroid Build Coastguard Worker Status status() const override { return Status::OK(); }
2135*9507f98cSAndroid Build Coastguard Worker
2136*9507f98cSAndroid Build Coastguard Worker private:
2137*9507f98cSAndroid Build Coastguard Worker const KVMap* const map_;
2138*9507f98cSAndroid Build Coastguard Worker const bool owned_; // Do we own map_
2139*9507f98cSAndroid Build Coastguard Worker KVMap::const_iterator iter_;
2140*9507f98cSAndroid Build Coastguard Worker };
2141*9507f98cSAndroid Build Coastguard Worker const Options options_;
2142*9507f98cSAndroid Build Coastguard Worker KVMap map_;
2143*9507f98cSAndroid Build Coastguard Worker };
2144*9507f98cSAndroid Build Coastguard Worker
CompareIterators(int step,DB * model,DB * db,const Snapshot * model_snap,const Snapshot * db_snap)2145*9507f98cSAndroid Build Coastguard Worker static bool CompareIterators(int step, DB* model, DB* db,
2146*9507f98cSAndroid Build Coastguard Worker const Snapshot* model_snap,
2147*9507f98cSAndroid Build Coastguard Worker const Snapshot* db_snap) {
2148*9507f98cSAndroid Build Coastguard Worker ReadOptions options;
2149*9507f98cSAndroid Build Coastguard Worker options.snapshot = model_snap;
2150*9507f98cSAndroid Build Coastguard Worker Iterator* miter = model->NewIterator(options);
2151*9507f98cSAndroid Build Coastguard Worker options.snapshot = db_snap;
2152*9507f98cSAndroid Build Coastguard Worker Iterator* dbiter = db->NewIterator(options);
2153*9507f98cSAndroid Build Coastguard Worker bool ok = true;
2154*9507f98cSAndroid Build Coastguard Worker int count = 0;
2155*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> seek_keys;
2156*9507f98cSAndroid Build Coastguard Worker // Compare equality of all elements using Next(). Save some of the keys for
2157*9507f98cSAndroid Build Coastguard Worker // comparing Seek equality.
2158*9507f98cSAndroid Build Coastguard Worker for (miter->SeekToFirst(), dbiter->SeekToFirst();
2159*9507f98cSAndroid Build Coastguard Worker ok && miter->Valid() && dbiter->Valid(); miter->Next(), dbiter->Next()) {
2160*9507f98cSAndroid Build Coastguard Worker count++;
2161*9507f98cSAndroid Build Coastguard Worker if (miter->key().compare(dbiter->key()) != 0) {
2162*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", step,
2163*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->key()).c_str(),
2164*9507f98cSAndroid Build Coastguard Worker EscapeString(dbiter->key()).c_str());
2165*9507f98cSAndroid Build Coastguard Worker ok = false;
2166*9507f98cSAndroid Build Coastguard Worker break;
2167*9507f98cSAndroid Build Coastguard Worker }
2168*9507f98cSAndroid Build Coastguard Worker
2169*9507f98cSAndroid Build Coastguard Worker if (miter->value().compare(dbiter->value()) != 0) {
2170*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr,
2171*9507f98cSAndroid Build Coastguard Worker "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n",
2172*9507f98cSAndroid Build Coastguard Worker step, EscapeString(miter->key()).c_str(),
2173*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->value()).c_str(),
2174*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->value()).c_str());
2175*9507f98cSAndroid Build Coastguard Worker ok = false;
2176*9507f98cSAndroid Build Coastguard Worker break;
2177*9507f98cSAndroid Build Coastguard Worker }
2178*9507f98cSAndroid Build Coastguard Worker
2179*9507f98cSAndroid Build Coastguard Worker if (count % 10 == 0) {
2180*9507f98cSAndroid Build Coastguard Worker seek_keys.push_back(miter->key().ToString());
2181*9507f98cSAndroid Build Coastguard Worker }
2182*9507f98cSAndroid Build Coastguard Worker }
2183*9507f98cSAndroid Build Coastguard Worker
2184*9507f98cSAndroid Build Coastguard Worker if (ok) {
2185*9507f98cSAndroid Build Coastguard Worker if (miter->Valid() != dbiter->Valid()) {
2186*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "step %d: Mismatch at end of iterators: %d vs. %d\n",
2187*9507f98cSAndroid Build Coastguard Worker step, miter->Valid(), dbiter->Valid());
2188*9507f98cSAndroid Build Coastguard Worker ok = false;
2189*9507f98cSAndroid Build Coastguard Worker }
2190*9507f98cSAndroid Build Coastguard Worker }
2191*9507f98cSAndroid Build Coastguard Worker
2192*9507f98cSAndroid Build Coastguard Worker if (ok) {
2193*9507f98cSAndroid Build Coastguard Worker // Validate iterator equality when performing seeks.
2194*9507f98cSAndroid Build Coastguard Worker for (auto kiter = seek_keys.begin(); ok && kiter != seek_keys.end();
2195*9507f98cSAndroid Build Coastguard Worker ++kiter) {
2196*9507f98cSAndroid Build Coastguard Worker miter->Seek(*kiter);
2197*9507f98cSAndroid Build Coastguard Worker dbiter->Seek(*kiter);
2198*9507f98cSAndroid Build Coastguard Worker if (!miter->Valid() || !dbiter->Valid()) {
2199*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "step %d: Seek iterators invalid: %d vs. %d\n",
2200*9507f98cSAndroid Build Coastguard Worker step, miter->Valid(), dbiter->Valid());
2201*9507f98cSAndroid Build Coastguard Worker ok = false;
2202*9507f98cSAndroid Build Coastguard Worker }
2203*9507f98cSAndroid Build Coastguard Worker if (miter->key().compare(dbiter->key()) != 0) {
2204*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "step %d: Seek key mismatch: '%s' vs. '%s'\n",
2205*9507f98cSAndroid Build Coastguard Worker step, EscapeString(miter->key()).c_str(),
2206*9507f98cSAndroid Build Coastguard Worker EscapeString(dbiter->key()).c_str());
2207*9507f98cSAndroid Build Coastguard Worker ok = false;
2208*9507f98cSAndroid Build Coastguard Worker break;
2209*9507f98cSAndroid Build Coastguard Worker }
2210*9507f98cSAndroid Build Coastguard Worker
2211*9507f98cSAndroid Build Coastguard Worker if (miter->value().compare(dbiter->value()) != 0) {
2212*9507f98cSAndroid Build Coastguard Worker std::fprintf(
2213*9507f98cSAndroid Build Coastguard Worker stderr,
2214*9507f98cSAndroid Build Coastguard Worker "step %d: Seek value mismatch for key '%s': '%s' vs. '%s'\n", step,
2215*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->key()).c_str(),
2216*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->value()).c_str(),
2217*9507f98cSAndroid Build Coastguard Worker EscapeString(miter->value()).c_str());
2218*9507f98cSAndroid Build Coastguard Worker ok = false;
2219*9507f98cSAndroid Build Coastguard Worker break;
2220*9507f98cSAndroid Build Coastguard Worker }
2221*9507f98cSAndroid Build Coastguard Worker }
2222*9507f98cSAndroid Build Coastguard Worker }
2223*9507f98cSAndroid Build Coastguard Worker
2224*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "%d entries compared: ok=%d\n", count, ok);
2225*9507f98cSAndroid Build Coastguard Worker delete miter;
2226*9507f98cSAndroid Build Coastguard Worker delete dbiter;
2227*9507f98cSAndroid Build Coastguard Worker return ok;
2228*9507f98cSAndroid Build Coastguard Worker }
2229*9507f98cSAndroid Build Coastguard Worker
TEST_F(DBTest,Randomized)2230*9507f98cSAndroid Build Coastguard Worker TEST_F(DBTest, Randomized) {
2231*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed());
2232*9507f98cSAndroid Build Coastguard Worker do {
2233*9507f98cSAndroid Build Coastguard Worker ModelDB model(CurrentOptions());
2234*9507f98cSAndroid Build Coastguard Worker const int N = 10000;
2235*9507f98cSAndroid Build Coastguard Worker const Snapshot* model_snap = nullptr;
2236*9507f98cSAndroid Build Coastguard Worker const Snapshot* db_snap = nullptr;
2237*9507f98cSAndroid Build Coastguard Worker std::string k, v;
2238*9507f98cSAndroid Build Coastguard Worker for (int step = 0; step < N; step++) {
2239*9507f98cSAndroid Build Coastguard Worker if (step % 100 == 0) {
2240*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "Step %d of %d\n", step, N);
2241*9507f98cSAndroid Build Coastguard Worker }
2242*9507f98cSAndroid Build Coastguard Worker // TODO(sanjay): Test Get() works
2243*9507f98cSAndroid Build Coastguard Worker int p = rnd.Uniform(100);
2244*9507f98cSAndroid Build Coastguard Worker if (p < 45) { // Put
2245*9507f98cSAndroid Build Coastguard Worker k = RandomKey(&rnd);
2246*9507f98cSAndroid Build Coastguard Worker v = RandomString(
2247*9507f98cSAndroid Build Coastguard Worker &rnd, rnd.OneIn(20) ? 100 + rnd.Uniform(100) : rnd.Uniform(8));
2248*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(model.Put(WriteOptions(), k, v));
2249*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Put(WriteOptions(), k, v));
2250*9507f98cSAndroid Build Coastguard Worker
2251*9507f98cSAndroid Build Coastguard Worker } else if (p < 90) { // Delete
2252*9507f98cSAndroid Build Coastguard Worker k = RandomKey(&rnd);
2253*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(model.Delete(WriteOptions(), k));
2254*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Delete(WriteOptions(), k));
2255*9507f98cSAndroid Build Coastguard Worker
2256*9507f98cSAndroid Build Coastguard Worker } else { // Multi-element batch
2257*9507f98cSAndroid Build Coastguard Worker WriteBatch b;
2258*9507f98cSAndroid Build Coastguard Worker const int num = rnd.Uniform(8);
2259*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < num; i++) {
2260*9507f98cSAndroid Build Coastguard Worker if (i == 0 || !rnd.OneIn(10)) {
2261*9507f98cSAndroid Build Coastguard Worker k = RandomKey(&rnd);
2262*9507f98cSAndroid Build Coastguard Worker } else {
2263*9507f98cSAndroid Build Coastguard Worker // Periodically re-use the same key from the previous iter, so
2264*9507f98cSAndroid Build Coastguard Worker // we have multiple entries in the write batch for the same key
2265*9507f98cSAndroid Build Coastguard Worker }
2266*9507f98cSAndroid Build Coastguard Worker if (rnd.OneIn(2)) {
2267*9507f98cSAndroid Build Coastguard Worker v = RandomString(&rnd, rnd.Uniform(10));
2268*9507f98cSAndroid Build Coastguard Worker b.Put(k, v);
2269*9507f98cSAndroid Build Coastguard Worker } else {
2270*9507f98cSAndroid Build Coastguard Worker b.Delete(k);
2271*9507f98cSAndroid Build Coastguard Worker }
2272*9507f98cSAndroid Build Coastguard Worker }
2273*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(model.Write(WriteOptions(), &b));
2274*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(db_->Write(WriteOptions(), &b));
2275*9507f98cSAndroid Build Coastguard Worker }
2276*9507f98cSAndroid Build Coastguard Worker
2277*9507f98cSAndroid Build Coastguard Worker if ((step % 100) == 0) {
2278*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr));
2279*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap));
2280*9507f98cSAndroid Build Coastguard Worker // Save a snapshot from each DB this time that we'll use next
2281*9507f98cSAndroid Build Coastguard Worker // time we compare things, to make sure the current state is
2282*9507f98cSAndroid Build Coastguard Worker // preserved with the snapshot
2283*9507f98cSAndroid Build Coastguard Worker if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
2284*9507f98cSAndroid Build Coastguard Worker if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
2285*9507f98cSAndroid Build Coastguard Worker
2286*9507f98cSAndroid Build Coastguard Worker Reopen();
2287*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr));
2288*9507f98cSAndroid Build Coastguard Worker
2289*9507f98cSAndroid Build Coastguard Worker model_snap = model.GetSnapshot();
2290*9507f98cSAndroid Build Coastguard Worker db_snap = db_->GetSnapshot();
2291*9507f98cSAndroid Build Coastguard Worker }
2292*9507f98cSAndroid Build Coastguard Worker }
2293*9507f98cSAndroid Build Coastguard Worker if (model_snap != nullptr) model.ReleaseSnapshot(model_snap);
2294*9507f98cSAndroid Build Coastguard Worker if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap);
2295*9507f98cSAndroid Build Coastguard Worker } while (ChangeOptions());
2296*9507f98cSAndroid Build Coastguard Worker }
2297*9507f98cSAndroid Build Coastguard Worker
MakeKey(unsigned int num)2298*9507f98cSAndroid Build Coastguard Worker std::string MakeKey(unsigned int num) {
2299*9507f98cSAndroid Build Coastguard Worker char buf[30];
2300*9507f98cSAndroid Build Coastguard Worker std::snprintf(buf, sizeof(buf), "%016u", num);
2301*9507f98cSAndroid Build Coastguard Worker return std::string(buf);
2302*9507f98cSAndroid Build Coastguard Worker }
2303*9507f98cSAndroid Build Coastguard Worker
BM_LogAndApply(benchmark::State & state)2304*9507f98cSAndroid Build Coastguard Worker static void BM_LogAndApply(benchmark::State& state) {
2305*9507f98cSAndroid Build Coastguard Worker const int num_base_files = state.range(0);
2306*9507f98cSAndroid Build Coastguard Worker
2307*9507f98cSAndroid Build Coastguard Worker std::string dbname = testing::TempDir() + "leveldb_test_benchmark";
2308*9507f98cSAndroid Build Coastguard Worker DestroyDB(dbname, Options());
2309*9507f98cSAndroid Build Coastguard Worker
2310*9507f98cSAndroid Build Coastguard Worker DB* db = nullptr;
2311*9507f98cSAndroid Build Coastguard Worker Options opts;
2312*9507f98cSAndroid Build Coastguard Worker opts.create_if_missing = true;
2313*9507f98cSAndroid Build Coastguard Worker Status s = DB::Open(opts, dbname, &db);
2314*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(s);
2315*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db != nullptr);
2316*9507f98cSAndroid Build Coastguard Worker
2317*9507f98cSAndroid Build Coastguard Worker delete db;
2318*9507f98cSAndroid Build Coastguard Worker db = nullptr;
2319*9507f98cSAndroid Build Coastguard Worker
2320*9507f98cSAndroid Build Coastguard Worker Env* env = Env::Default();
2321*9507f98cSAndroid Build Coastguard Worker
2322*9507f98cSAndroid Build Coastguard Worker port::Mutex mu;
2323*9507f98cSAndroid Build Coastguard Worker MutexLock l(&mu);
2324*9507f98cSAndroid Build Coastguard Worker
2325*9507f98cSAndroid Build Coastguard Worker InternalKeyComparator cmp(BytewiseComparator());
2326*9507f98cSAndroid Build Coastguard Worker Options options;
2327*9507f98cSAndroid Build Coastguard Worker VersionSet vset(dbname, &options, nullptr, &cmp);
2328*9507f98cSAndroid Build Coastguard Worker bool save_manifest;
2329*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(vset.Recover(&save_manifest));
2330*9507f98cSAndroid Build Coastguard Worker VersionEdit vbase;
2331*9507f98cSAndroid Build Coastguard Worker uint64_t fnum = 1;
2332*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < num_base_files; i++) {
2333*9507f98cSAndroid Build Coastguard Worker InternalKey start(MakeKey(2 * fnum), 1, kTypeValue);
2334*9507f98cSAndroid Build Coastguard Worker InternalKey limit(MakeKey(2 * fnum + 1), 1, kTypeDeletion);
2335*9507f98cSAndroid Build Coastguard Worker vbase.AddFile(2, fnum++, 1 /* file size */, start, limit);
2336*9507f98cSAndroid Build Coastguard Worker }
2337*9507f98cSAndroid Build Coastguard Worker ASSERT_LEVELDB_OK(vset.LogAndApply(&vbase, &mu));
2338*9507f98cSAndroid Build Coastguard Worker
2339*9507f98cSAndroid Build Coastguard Worker uint64_t start_micros = env->NowMicros();
2340*9507f98cSAndroid Build Coastguard Worker
2341*9507f98cSAndroid Build Coastguard Worker for (auto st : state) {
2342*9507f98cSAndroid Build Coastguard Worker VersionEdit vedit;
2343*9507f98cSAndroid Build Coastguard Worker vedit.RemoveFile(2, fnum);
2344*9507f98cSAndroid Build Coastguard Worker InternalKey start(MakeKey(2 * fnum), 1, kTypeValue);
2345*9507f98cSAndroid Build Coastguard Worker InternalKey limit(MakeKey(2 * fnum + 1), 1, kTypeDeletion);
2346*9507f98cSAndroid Build Coastguard Worker vedit.AddFile(2, fnum++, 1 /* file size */, start, limit);
2347*9507f98cSAndroid Build Coastguard Worker vset.LogAndApply(&vedit, &mu);
2348*9507f98cSAndroid Build Coastguard Worker }
2349*9507f98cSAndroid Build Coastguard Worker uint64_t stop_micros = env->NowMicros();
2350*9507f98cSAndroid Build Coastguard Worker unsigned int us = stop_micros - start_micros;
2351*9507f98cSAndroid Build Coastguard Worker char buf[16];
2352*9507f98cSAndroid Build Coastguard Worker std::snprintf(buf, sizeof(buf), "%d", num_base_files);
2353*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr,
2354*9507f98cSAndroid Build Coastguard Worker "BM_LogAndApply/%-6s %8" PRIu64
2355*9507f98cSAndroid Build Coastguard Worker " iters : %9u us (%7.0f us / iter)\n",
2356*9507f98cSAndroid Build Coastguard Worker buf, state.iterations(), us, ((float)us) / state.iterations());
2357*9507f98cSAndroid Build Coastguard Worker }
2358*9507f98cSAndroid Build Coastguard Worker
2359*9507f98cSAndroid Build Coastguard Worker BENCHMARK(BM_LogAndApply)->Arg(1)->Arg(100)->Arg(10000)->Arg(100000);
2360*9507f98cSAndroid Build Coastguard Worker } // namespace leveldb
2361*9507f98cSAndroid Build Coastguard Worker
2362