xref: /aosp_15_r20/external/leveldb/db/db_test.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
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