1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be
3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/db.h"
699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "leveldb/filter_policy.h"
7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/db_impl.h"
8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/filename.h"
9179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/version_set.h"
10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/write_batch_internal.h"
1199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "leveldb/cache.h"
12fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h"
13fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/table.h"
1499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "util/hash.h"
15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/logging.h"
16394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com#include "util/mutexlock.h"
17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/testharness.h"
18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/testutil.h"
19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb {
21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic std::string RandomString(Random* rnd, int len) {
23179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string r;
24179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  test::RandomString(rnd, len, &r);
25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return r;
26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
27179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
2899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comnamespace {
2999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comclass AtomicCounter {
3099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com private:
3199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  port::Mutex mu_;
3299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  int count_;
3399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com public:
3499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  AtomicCounter() : count_(0) { }
3599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void Increment() {
3611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    IncrementBy(1);
3711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  }
3811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  void IncrementBy(int count) {
3999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    MutexLock l(&mu_);
4011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    count_ += count;
4199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
4299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  int Read() {
4399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    MutexLock l(&mu_);
4499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    return count_;
4599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
4699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void Reset() {
4799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    MutexLock l(&mu_);
4899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    count_ = 0;
4999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
5099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com};
5111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
5211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgvoid DelayMilliseconds(int millis) {
5311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  Env::Default()->SleepForMicroseconds(millis * 1000);
5411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
5599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com}
5699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
578cd4ab8303620197cf24282ae8639060efbb326egabor@google.com// Special Env used to delay background operations
588cd4ab8303620197cf24282ae8639060efbb326egabor@google.comclass SpecialEnv : public EnvWrapper {
598cd4ab8303620197cf24282ae8639060efbb326egabor@google.com public:
604935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // sstable/log Sync() calls are blocked while this pointer is non-NULL.
614935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  port::AtomicPointer delay_data_sync_;
624935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
634935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // sstable/log Sync() calls return an error.
644935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  port::AtomicPointer data_sync_error_;
658cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
66e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  // Simulate no-space errors while this pointer is non-NULL.
67e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  port::AtomicPointer no_space_;
68e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
69158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  // Simulate non-writable file system while this pointer is non-NULL
70158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  port::AtomicPointer non_writable_;
71158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com
7285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // Force sync of manifest files to fail while this pointer is non-NULL
7385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  port::AtomicPointer manifest_sync_error_;
7485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
7585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // Force write to manifest files to fail while this pointer is non-NULL
7685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  port::AtomicPointer manifest_write_error_;
7785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
7899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  bool count_random_reads_;
7999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  AtomicCounter random_read_counter_;
8099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
818cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  explicit SpecialEnv(Env* base) : EnvWrapper(base) {
824935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    delay_data_sync_.Release_Store(NULL);
834935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    data_sync_error_.Release_Store(NULL);
84e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    no_space_.Release_Store(NULL);
85158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    non_writable_.Release_Store(NULL);
8699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    count_random_reads_ = false;
8785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    manifest_sync_error_.Release_Store(NULL);
8885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    manifest_write_error_.Release_Store(NULL);
898cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  }
908cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
918cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  Status NewWritableFile(const std::string& f, WritableFile** r) {
924935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    class DataFile : public WritableFile {
938cd4ab8303620197cf24282ae8639060efbb326egabor@google.com     private:
948cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      SpecialEnv* env_;
958cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      WritableFile* base_;
968cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
978cd4ab8303620197cf24282ae8639060efbb326egabor@google.com     public:
984935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org      DataFile(SpecialEnv* env, WritableFile* base)
998cd4ab8303620197cf24282ae8639060efbb326egabor@google.com          : env_(env),
1008cd4ab8303620197cf24282ae8639060efbb326egabor@google.com            base_(base) {
1018cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      }
1024935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org      ~DataFile() { delete base_; }
103e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com      Status Append(const Slice& data) {
104e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com        if (env_->no_space_.Acquire_Load() != NULL) {
105e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com          // Drop writes on the floor
106e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com          return Status::OK();
107e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com        } else {
108e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com          return base_->Append(data);
109e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com        }
110e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com      }
1118cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      Status Close() { return base_->Close(); }
1128cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      Status Flush() { return base_->Flush(); }
1138cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      Status Sync() {
1144935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org        if (env_->data_sync_error_.Acquire_Load() != NULL) {
1154935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org          return Status::IOError("simulated data sync error");
1164935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org        }
1174935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org        while (env_->delay_data_sync_.Acquire_Load() != NULL) {
11811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org          DelayMilliseconds(100);
1198cd4ab8303620197cf24282ae8639060efbb326egabor@google.com        }
1208cd4ab8303620197cf24282ae8639060efbb326egabor@google.com        return base_->Sync();
1218cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      }
1228cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    };
12385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    class ManifestFile : public WritableFile {
12485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org     private:
12585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      SpecialEnv* env_;
12685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      WritableFile* base_;
12785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org     public:
12885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { }
12985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      ~ManifestFile() { delete base_; }
13085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      Status Append(const Slice& data) {
13185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        if (env_->manifest_write_error_.Acquire_Load() != NULL) {
13285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org          return Status::IOError("simulated writer error");
13385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        } else {
13485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org          return base_->Append(data);
13585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        }
13685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      }
13785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      Status Close() { return base_->Close(); }
13885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      Status Flush() { return base_->Flush(); }
13985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      Status Sync() {
14085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        if (env_->manifest_sync_error_.Acquire_Load() != NULL) {
14185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org          return Status::IOError("simulated sync error");
14285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        } else {
14385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org          return base_->Sync();
14485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        }
14585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      }
14685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    };
1478cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
148158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    if (non_writable_.Acquire_Load() != NULL) {
149158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      return Status::IOError("simulated write error");
150158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    }
151158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com
1528cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    Status s = target()->NewWritableFile(f, r);
1538cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    if (s.ok()) {
1544935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org      if (strstr(f.c_str(), ".ldb") != NULL ||
1554935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org          strstr(f.c_str(), ".log") != NULL) {
1564935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org        *r = new DataFile(this, *r);
15785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org      } else if (strstr(f.c_str(), "MANIFEST") != NULL) {
15885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        *r = new ManifestFile(this, *r);
1598cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      }
1608cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    }
1618cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    return s;
1628cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  }
16399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
16499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {
16599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    class CountingFile : public RandomAccessFile {
16699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com     private:
16799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      RandomAccessFile* target_;
16899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      AtomicCounter* counter_;
16999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com     public:
17099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      CountingFile(RandomAccessFile* target, AtomicCounter* counter)
17199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          : target_(target), counter_(counter) {
17299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
17399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      virtual ~CountingFile() { delete target_; }
17499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      virtual Status Read(uint64_t offset, size_t n, Slice* result,
17599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                          char* scratch) const {
17699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        counter_->Increment();
17799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        return target_->Read(offset, n, result, scratch);
17899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
17999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    };
18099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
18199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Status s = target()->NewRandomAccessFile(f, r);
18299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    if (s.ok() && count_random_reads_) {
18399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      *r = new CountingFile(*r, &random_read_counter_);
18499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
18599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    return s;
18699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
1878cd4ab8303620197cf24282ae8639060efbb326egabor@google.com};
1888cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
189179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass DBTest {
19099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com private:
19199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  const FilterPolicy* filter_policy_;
19299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
19399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Sequence of option configurations to try
19499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  enum OptionConfig {
19599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    kDefault,
19699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    kFilter,
197158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    kUncompressed,
19899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    kEnd
19999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  };
20099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  int option_config_;
20199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
202179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public:
203179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string dbname_;
2048cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  SpecialEnv* env_;
205179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  DB* db_;
206179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
207179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Options last_options_;
208179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
20999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  DBTest() : option_config_(kDefault),
21099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com             env_(new SpecialEnv(Env::Default())) {
21199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    filter_policy_ = NewBloomFilterPolicy(10);
212179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    dbname_ = test::TmpDir() + "/db_test";
213179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    DestroyDB(dbname_, Options());
214179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    db_ = NULL;
215179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Reopen();
216179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
217179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
218179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ~DBTest() {
219179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete db_;
220179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    DestroyDB(dbname_, Options());
2218cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    delete env_;
22299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    delete filter_policy_;
22399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
22499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
22599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Switch to a fresh database with the next option configuration to
22699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // test.  Return false if there are no more configurations to test.
22799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  bool ChangeOptions() {
228158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    option_config_++;
229158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    if (option_config_ >= kEnd) {
23099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      return false;
23199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    } else {
23299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      DestroyAndReopen();
23399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      return true;
23499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
23599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
23699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
23799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Return the current option configuration.
23899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options CurrentOptions() {
23999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options;
24099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    switch (option_config_) {
24199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      case kFilter:
24299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        options.filter_policy = filter_policy_;
24399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        break;
244158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      case kUncompressed:
245158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com        options.compression = kNoCompression;
246158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com        break;
24799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      default:
24899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        break;
24999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
25099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    return options;
251179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
252179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
253179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  DBImpl* dbfull() {
254179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return reinterpret_cast<DBImpl*>(db_);
255179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
256179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
257179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  void Reopen(Options* options = NULL) {
258179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(TryReopen(options));
259179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
260179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
26199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void Close() {
26299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    delete db_;
26399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    db_ = NULL;
26499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
26599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
266179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  void DestroyAndReopen(Options* options = NULL) {
267179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete db_;
268179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    db_ = NULL;
269179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    DestroyDB(dbname_, Options());
270179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(TryReopen(options));
271179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
272179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
273179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status TryReopen(Options* options) {
274179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete db_;
275179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    db_ = NULL;
276179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Options opts;
277179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (options != NULL) {
278179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      opts = *options;
279179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else {
28099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      opts = CurrentOptions();
281179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      opts.create_if_missing = true;
282179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
283179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    last_options_ = opts;
284179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
285179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return DB::Open(opts, dbname_, &db_);
286179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
287179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
288179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status Put(const std::string& k, const std::string& v) {
28995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    return db_->Put(WriteOptions(), k, v);
290179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
291179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
292179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status Delete(const std::string& k) {
29395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    return db_->Delete(WriteOptions(), k);
294179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
295179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
296179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string Get(const std::string& k, const Snapshot* snapshot = NULL) {
297179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ReadOptions options;
298179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    options.snapshot = snapshot;
299179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::string result;
300179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Status s = db_->Get(options, k, &result);
301179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (s.IsNotFound()) {
302179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      result = "NOT_FOUND";
303179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (!s.ok()) {
304179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      result = s.ToString();
305179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
306179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return result;
307179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
308179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
30945b9940be332834440bd5299419f396e38085ebehans@chromium.org  // Return a string that contains all key,value pairs in order,
31045b9940be332834440bd5299419f396e38085ebehans@chromium.org  // formatted like "(k1->v1)(k2->v2)".
31145b9940be332834440bd5299419f396e38085ebehans@chromium.org  std::string Contents() {
31245b9940be332834440bd5299419f396e38085ebehans@chromium.org    std::vector<std::string> forward;
31345b9940be332834440bd5299419f396e38085ebehans@chromium.org    std::string result;
31445b9940be332834440bd5299419f396e38085ebehans@chromium.org    Iterator* iter = db_->NewIterator(ReadOptions());
31545b9940be332834440bd5299419f396e38085ebehans@chromium.org    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
31645b9940be332834440bd5299419f396e38085ebehans@chromium.org      std::string s = IterStatus(iter);
31745b9940be332834440bd5299419f396e38085ebehans@chromium.org      result.push_back('(');
31845b9940be332834440bd5299419f396e38085ebehans@chromium.org      result.append(s);
31945b9940be332834440bd5299419f396e38085ebehans@chromium.org      result.push_back(')');
32045b9940be332834440bd5299419f396e38085ebehans@chromium.org      forward.push_back(s);
32145b9940be332834440bd5299419f396e38085ebehans@chromium.org    }
32245b9940be332834440bd5299419f396e38085ebehans@chromium.org
32345b9940be332834440bd5299419f396e38085ebehans@chromium.org    // Check reverse iteration results are the reverse of forward results
3244935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    size_t matched = 0;
32545b9940be332834440bd5299419f396e38085ebehans@chromium.org    for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
32645b9940be332834440bd5299419f396e38085ebehans@chromium.org      ASSERT_LT(matched, forward.size());
32745b9940be332834440bd5299419f396e38085ebehans@chromium.org      ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
32845b9940be332834440bd5299419f396e38085ebehans@chromium.org      matched++;
32945b9940be332834440bd5299419f396e38085ebehans@chromium.org    }
33045b9940be332834440bd5299419f396e38085ebehans@chromium.org    ASSERT_EQ(matched, forward.size());
33145b9940be332834440bd5299419f396e38085ebehans@chromium.org
33245b9940be332834440bd5299419f396e38085ebehans@chromium.org    delete iter;
33345b9940be332834440bd5299419f396e38085ebehans@chromium.org    return result;
33445b9940be332834440bd5299419f396e38085ebehans@chromium.org  }
33545b9940be332834440bd5299419f396e38085ebehans@chromium.org
336179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string AllEntriesFor(const Slice& user_key) {
337179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Iterator* iter = dbfull()->TEST_NewInternalIterator();
338179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
339179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    iter->Seek(target.Encode());
340179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::string result;
341179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!iter->status().ok()) {
342179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      result = iter->status().ToString();
343179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else {
344179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      result = "[ ";
345179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      bool first = true;
346179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      while (iter->Valid()) {
347179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        ParsedInternalKey ikey;
348179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        if (!ParseInternalKey(iter->key(), &ikey)) {
349179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          result += "CORRUPTED";
350179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        } else {
35199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) {
352179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            break;
353179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          }
354179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          if (!first) {
355179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            result += ", ";
356179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          }
357179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          first = false;
358179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          switch (ikey.type) {
359179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            case kTypeValue:
360179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              result += iter->value().ToString();
361179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              break;
362179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            case kTypeDeletion:
363179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              result += "DEL";
364179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              break;
365179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org          }
366179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        }
367179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        iter->Next();
368179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
369179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (!first) {
370179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        result += " ";
371179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
372179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      result += "]";
373179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
374179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete iter;
375179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return result;
376179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
377179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
378179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int NumTableFilesAtLevel(int level) {
37995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    std::string property;
380179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_TRUE(
381179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level),
38295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org                         &property));
38395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    return atoi(property.c_str());
384179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
385179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
3868cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  int TotalTableFiles() {
3878cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    int result = 0;
3888cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    for (int level = 0; level < config::kNumLevels; level++) {
3898cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      result += NumTableFilesAtLevel(level);
3908cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    }
3918cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    return result;
3928cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  }
3938cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
3945fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Return spread of files per level
3955fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  std::string FilesPerLevel() {
3965fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    std::string result;
3975fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    int last_non_zero_offset = 0;
3985fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    for (int level = 0; level < config::kNumLevels; level++) {
3995fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      int f = NumTableFilesAtLevel(level);
4005fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      char buf[100];
4015fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);
4025fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      result += buf;
4035fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      if (f > 0) {
4045fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com        last_non_zero_offset = result.size();
4055fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      }
4065fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    }
4075fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    result.resize(last_non_zero_offset);
4085fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    return result;
4095fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  }
4105fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
411e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  int CountFiles() {
412e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    std::vector<std::string> files;
413e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    env_->GetChildren(dbname_, &files);
414e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    return static_cast<int>(files.size());
415e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  }
416e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
417179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint64_t Size(const Slice& start, const Slice& limit) {
418179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Range r(start, limit);
419179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    uint64_t size;
420179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    db_->GetApproximateSizes(&r, 1, &size);
421179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return size;
422179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
423179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
424b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void Compact(const Slice& start, const Slice& limit) {
4255fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    db_->CompactRange(&start, &limit);
4265fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  }
4275fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
4285fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Do n memtable compactions, each of which produces an sstable
4295fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // covering the range [small,large].
4305fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  void MakeTables(int n, const std::string& small, const std::string& large) {
4315fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    for (int i = 0; i < n; i++) {
4325fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      Put(small, "begin");
4335fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      Put(large, "end");
4345fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      dbfull()->TEST_CompactMemTable();
435b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
436b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
437b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
4388cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // Prevent pushing of new sstables into deeper levels by adding
4398cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // tables that cover a specified range to all levels.
4408cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  void FillLevels(const std::string& smallest, const std::string& largest) {
4415fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    MakeTables(config::kNumLevels, smallest, largest);
4428cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  }
4438cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
444b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void DumpFileCounts(const char* label) {
445b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stderr, "---\n%s:\n", label);
446b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stderr, "maxoverlap: %lld\n",
447b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            static_cast<long long>(
448b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org                dbfull()->TEST_MaxNextLevelOverlappingBytes()));
449b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    for (int level = 0; level < config::kNumLevels; level++) {
450b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      int num = NumTableFilesAtLevel(level);
451b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      if (num > 0) {
452b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        fprintf(stderr, "  level %3d : %d files\n", level, num);
453b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      }
454b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
455b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
456225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
4575fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  std::string DumpSSTableList() {
4585fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    std::string property;
4595fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    db_->GetProperty("leveldb.sstables", &property);
4605fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    return property;
4615fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  }
4625fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
463225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  std::string IterStatus(Iterator* iter) {
464225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    std::string result;
465225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    if (iter->Valid()) {
466225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org      result = iter->key().ToString() + "->" + iter->value().ToString();
467225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    } else {
468225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org      result = "(invalid)";
469225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    }
470225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    return result;
471225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  }
472bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org
473bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  bool DeleteAnSSTFile() {
474bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    std::vector<std::string> filenames;
475bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    ASSERT_OK(env_->GetChildren(dbname_, &filenames));
476bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    uint64_t number;
477bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    FileType type;
478bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    for (size_t i = 0; i < filenames.size(); i++) {
479bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org      if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
480bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org        ASSERT_OK(env_->DeleteFile(TableFileName(dbname_, number)));
481bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org        return true;
482bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org      }
483bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    }
484bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org    return false;
485bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  }
4862d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org
4872d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  // Returns number of files renamed.
4882d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  int RenameLDBToSST() {
4892d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    std::vector<std::string> filenames;
4902d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    ASSERT_OK(env_->GetChildren(dbname_, &filenames));
4912d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    uint64_t number;
4922d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    FileType type;
4932d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    int files_renamed = 0;
4942d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    for (size_t i = 0; i < filenames.size(); i++) {
4952d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org      if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
4962d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org        const std::string from = TableFileName(dbname_, number);
4972d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org        const std::string to = SSTTableFileName(dbname_, number);
4982d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org        ASSERT_OK(env_->RenameFile(from, to));
4992d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org        files_renamed++;
5002d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org      }
5012d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    }
5022d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org    return files_renamed;
5032d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  }
504179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
505179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
506179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, Empty) {
50799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
50899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(db_ != NULL);
50999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("foo"));
51099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
511179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
512179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
513179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, ReadWrite) {
51499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
51599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
51699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
51799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("bar", "v2"));
51899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v3"));
51999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v3", Get("foo"));
52099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("bar"));
52199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
522179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
523179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
524179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, PutDeleteGet) {
52599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
52699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1"));
52799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
52899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2"));
52999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo"));
53099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(db_->Delete(WriteOptions(), "foo"));
53199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("foo"));
53299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
533179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
534179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5358cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetFromImmutableLayer) {
53699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
53799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options = CurrentOptions();
53899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.env = env_;
53999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.write_buffer_size = 100000;  // Small write buffer
54099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen(&options);
5418cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
54299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
54399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
5448cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
5454935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    env_->delay_data_sync_.Release_Store(env_);      // Block sync calls
54699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("k1", std::string(100000, 'x'));             // Fill memtable
54799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("k2", std::string(100000, 'y'));             // Trigger compaction
54899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
5494935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    env_->delay_data_sync_.Release_Store(NULL);      // Release sync calls
55099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
5518cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
5528cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
5538cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetFromVersions) {
55499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
55599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
55699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
55799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
55899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
5598cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
5608cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
5618cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetSnapshot) {
56299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
56399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Try with both a short key and a long key
56499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int i = 0; i < 2; i++) {
56599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x');
56699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_OK(Put(key, "v1"));
56799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      const Snapshot* s1 = db_->GetSnapshot();
56899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_OK(Put(key, "v2"));
56999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ("v2", Get(key));
57099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ("v1", Get(key, s1));
57199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      dbfull()->TEST_CompactMemTable();
57299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ("v2", Get(key));
57399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ("v1", Get(key, s1));
57499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      db_->ReleaseSnapshot(s1);
57599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
57699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
5778cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
5788cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
5798cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetLevel0Ordering) {
58099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
58199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Check that we process level-0 files in correct order.  The code
58299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // below generates two level-0 files where the earlier one comes
58399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // before the later one in the level-0 file list since the earlier
58499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // one has a smaller "smallest" key.
58599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("bar", "b"));
58699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
58799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
58899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v2"));
58999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
59099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo"));
59199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
5928cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
5938cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
5948cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetOrderedByLevels) {
59599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
59699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
59799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Compact("a", "z");
59899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
59999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v2"));
60099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo"));
60199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
60299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo"));
60399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
6048cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
6058cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
6068cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, GetPicksCorrectFile) {
60799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
60899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Arrange to have multiple files in a non-level-0 level.
60999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("a", "va"));
61099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Compact("a", "b");
61199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("x", "vx"));
61299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Compact("x", "y");
61399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("f", "vf"));
61499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Compact("f", "g");
61599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("va", Get("a"));
61699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("vf", Get("f"));
61799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("vx", Get("x"));
61899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
6198cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
6208cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
621394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.comTEST(DBTest, GetEncountersEmptyLevel) {
62299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
62399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Arrange for the following to happen:
62499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    //   * sstable A in level 0
62599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    //   * nothing in level 1
62699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    //   * sstable B in level 2
62799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Then do enough Get() calls to arrange for an automatic compaction
62899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // of sstable A.  A bug would cause the compaction to be marked as
62999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // occuring at level 1 (instead of the correct level 0).
63099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
63199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Step 1: First place sstables in levels 0 and 2
63299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    int compaction_count = 0;
63399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    while (NumTableFilesAtLevel(0) == 0 ||
63499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com           NumTableFilesAtLevel(2) == 0) {
63599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2";
63699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      compaction_count++;
63799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      Put("a", "begin");
63899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      Put("z", "end");
63999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      dbfull()->TEST_CompactMemTable();
64099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
641394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
64299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Step 2: clear level 1 if necessary.
64399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactRange(1, NULL, NULL);
64499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(0), 1);
64599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(1), 0);
64699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(2), 1);
64799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
648158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    // Step 3: read a bunch of times
649158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    for (int i = 0; i < 1000; i++) {
65099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ("NOT_FOUND", Get("missing"));
65199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
652158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com
653158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    // Step 4: Wait for compaction to finish
65411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    DelayMilliseconds(1000);
655158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com
656158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
65799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
658394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com}
659394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
660225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.orgTEST(DBTest, IterEmpty) {
661225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  Iterator* iter = db_->NewIterator(ReadOptions());
662225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
663225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
664225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
665225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
666225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
667225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
668225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
669225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("foo");
670225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
671225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
672225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  delete iter;
673225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org}
674225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
675225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.orgTEST(DBTest, IterSingle) {
676225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("a", "va"));
677225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  Iterator* iter = db_->NewIterator(ReadOptions());
678225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
679225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
680225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
681225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
682225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
683225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
684225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
685225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
686225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
687225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
688225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
689225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
690225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
691225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
692225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
693225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
694225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
695225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
696225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
697225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("");
698225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
699225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
700225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
701225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
702225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("a");
703225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
704225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
705225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
706225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
707225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("b");
708225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
709225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
710225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  delete iter;
711225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org}
712225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
713225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.orgTEST(DBTest, IterMulti) {
714225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("a", "va"));
715225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("b", "vb"));
716225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("c", "vc"));
717225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  Iterator* iter = db_->NewIterator(ReadOptions());
718225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
719225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
720225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
721225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
722225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
723225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
724225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
725225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
726225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
727225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
728225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
729225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
730225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
731225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
732225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
733225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
734225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
735225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
736225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
737225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
738225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
739225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
740225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
741225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
742225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
743225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
744225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
745225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("");
746225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
747225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("a");
748225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
749225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("ax");
750225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
751225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("b");
752225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
753225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Seek("z");
754225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
755225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
756225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  // Switch from reverse to forward
757225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
758225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
759225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
760225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
761225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
762225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
763225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  // Switch from forward to reverse
764225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
765225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
766225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
767225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
768225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
769225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
770225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  // Make sure iter stays at snapshot
771225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("a",  "va2"));
772225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("a2", "va3"));
773225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("b",  "vb2"));
774225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("c",  "vc2"));
775225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Delete("b"));
776225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
777225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
778225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
779225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
780225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
781225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
782225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
783225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
784225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
785225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
786225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
787225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->vb");
788225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
789225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
790225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
791225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
792225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
793225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  delete iter;
794225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org}
795225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
796225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.orgTEST(DBTest, IterSmallAndLargeMix) {
797225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("a", "va"));
798225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("b", std::string(100000, 'b')));
799225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("c", "vc"));
800225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("d", std::string(100000, 'd')));
801225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_OK(Put("e", std::string(100000, 'e')));
802225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
803225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  Iterator* iter = db_->NewIterator(ReadOptions());
804225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
805225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToFirst();
806225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
807225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
808225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b'));
809225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
810225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
811225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
812225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd'));
813225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
814225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e'));
815225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Next();
816225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
817225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
818225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->SeekToLast();
819225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e'));
820225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
821225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd'));
822225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
823225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "c->vc");
824225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
825225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b'));
826225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
827225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "a->va");
828225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  iter->Prev();
829225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  ASSERT_EQ(IterStatus(iter), "(invalid)");
830225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
831225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  delete iter;
832225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org}
833225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
8347e50a01f8a2820ed7a50c673b5affe0131560ff5gabor@google.comTEST(DBTest, IterMultiWithDelete) {
83599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
83699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("a", "va"));
83799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("b", "vb"));
83899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("c", "vc"));
83999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Delete("b"));
84099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("b"));
8417e50a01f8a2820ed7a50c673b5affe0131560ff5gabor@google.com
84299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Iterator* iter = db_->NewIterator(ReadOptions());
84399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    iter->Seek("c");
84499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(IterStatus(iter), "c->vc");
84599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    iter->Prev();
84699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(IterStatus(iter), "a->va");
84799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    delete iter;
84899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
8497e50a01f8a2820ed7a50c673b5affe0131560ff5gabor@google.com}
8507e50a01f8a2820ed7a50c673b5affe0131560ff5gabor@google.com
851179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, Recover) {
85299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
85399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
85499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("baz", "v5"));
855179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
85699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
85799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
858179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
85999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
86099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v5", Get("baz"));
86199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("bar", "v2"));
86299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v3"));
863179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
86499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
86599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v3", Get("foo"));
86699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v4"));
86799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v4", Get("foo"));
86899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("bar"));
86999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v5", Get("baz"));
87099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
871179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
872179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
873179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, RecoveryWithEmptyLog) {
87499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
87599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));
87699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v2"));
87799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
87899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
87999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v3"));
88099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
88199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v3", Get("foo"));
88299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
883179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
884179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
8858cd4ab8303620197cf24282ae8639060efbb326egabor@google.com// Check that writes done during a memtable compaction are recovered
8868cd4ab8303620197cf24282ae8639060efbb326egabor@google.com// if the database is shutdown during the memtable compaction.
8878cd4ab8303620197cf24282ae8639060efbb326egabor@google.comTEST(DBTest, RecoverDuringMemtableCompaction) {
88899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
88999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options = CurrentOptions();
89099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.env = env_;
89199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.write_buffer_size = 1000000;
89299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen(&options);
8938cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
89499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Trigger a long memtable compaction and reopen the database during it
89599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("foo", "v1"));                         // Goes to 1st log file
89699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("big1", std::string(10000000, 'x')));  // Fills memtable
89799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("big2", std::string(1000, 'y')));      // Triggers compaction
89899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("bar", "v2"));                         // Goes to new log file
8998cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
90099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen(&options);
90199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo"));
90299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("bar"));
90399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(std::string(10000000, 'x'), Get("big1"));
90499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(std::string(1000, 'y'), Get("big2"));
90599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
9068cd4ab8303620197cf24282ae8639060efbb326egabor@google.com}
9078cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
908179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic std::string Key(int i) {
909179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  char buf[100];
910179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  snprintf(buf, sizeof(buf), "key%06d", i);
911179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return std::string(buf);
912179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
913179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
914179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, MinorCompactionsHappen) {
91599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
916179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  options.write_buffer_size = 10000;
917179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Reopen(&options);
918179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
91995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  const int N = 500;
920179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
9218cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  int starting_num_tables = TotalTableFiles();
922179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < N; i++) {
923179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put(Key(i), Key(i) + std::string(1000, 'v')));
924179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
9258cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  int ending_num_tables = TotalTableFiles();
926179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_GT(ending_num_tables, starting_num_tables);
927179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
928179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < N; i++) {
929179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i)));
930179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
931179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
932179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Reopen();
933179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
934179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < N; i++) {
935179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i)));
936179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
937179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
938179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
939179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, RecoverWithLargeLog) {
940179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  {
94199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options = CurrentOptions();
942179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Reopen(&options);
943179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put("big1", std::string(200000, '1')));
944179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put("big2", std::string(200000, '2')));
945179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put("small3", std::string(10, '3')));
946179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put("small4", std::string(10, '4')));
947179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
948179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
949179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
950179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Make sure that if we re-open with a small write buffer size that
951179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // we flush table files in the middle of a large log file.
95299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
953179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  options.write_buffer_size = 100000;
954179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Reopen(&options);
955179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(NumTableFilesAtLevel(0), 3);
956179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(std::string(200000, '1'), Get("big1"));
957179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(std::string(200000, '2'), Get("big2"));
958179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(std::string(10, '3'), Get("small3"));
959179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(std::string(10, '4'), Get("small4"));
960179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_GT(NumTableFilesAtLevel(0), 1);
961179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
962179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
963179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, CompactionsGenerateMultipleFiles) {
96499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
965179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  options.write_buffer_size = 100000000;        // Large write buffer
966179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Reopen(&options);
967179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
968179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Random rnd(301);
969179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
970179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Write 8MB (80 values, each 100K)
971179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(NumTableFilesAtLevel(0), 0);
972179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::vector<std::string> values;
973179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < 80; i++) {
974179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    values.push_back(RandomString(&rnd, 100000));
975179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put(Key(i), values[i]));
976179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
977179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
978179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Reopening moves updates to level-0
979179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Reopen(&options);
9805fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(0, NULL, NULL);
981179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
982179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(NumTableFilesAtLevel(0), 0);
983179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_GT(NumTableFilesAtLevel(1), 1);
984179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < 80; i++) {
985179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_EQ(Get(Key(i)), values[i]);
986179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
987179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
988179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
989917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.comTEST(DBTest, RepeatedWritesToSameKey) {
99099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
991917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  options.env = env_;
992917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  options.write_buffer_size = 100000;  // Small write buffer
993917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  Reopen(&options);
994917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com
995917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  // We must have at most one file per level except for level-0,
996917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  // which may have up to kL0_StopWritesTrigger files.
997917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  const int kMaxFiles = config::kNumLevels + config::kL0_StopWritesTrigger;
998917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com
999917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  Random rnd(301);
1000917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  std::string value = RandomString(&rnd, 2 * options.write_buffer_size);
1001917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  for (int i = 0; i < 5 * kMaxFiles; i++) {
1002917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com    Put("key", value);
1003917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com    ASSERT_LE(TotalTableFiles(), kMaxFiles);
1004917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com    fprintf(stderr, "after %d: %d files\n", int(i+1), TotalTableFiles());
1005917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  }
1006917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com}
1007917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com
1008b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.orgTEST(DBTest, SparseMerge) {
100999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
1010b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  options.compression = kNoCompression;
1011b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Reopen(&options);
1012b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
10138cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  FillLevels("A", "Z");
10148cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
1015b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // Suppose there is:
1016b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  //    small amount of data with prefix A
1017b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  //    large amount of data with prefix B
1018b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  //    small amount of data with prefix C
1019b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // and that recent updates have made small changes to all three prefixes.
1020b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // Check that we do not do a compaction that merges all of B in one shot.
1021b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  const std::string value(1000, 'x');
1022b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Put("A", "va");
1023b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // Write approximately 100MB of "B" values
1024b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  for (int i = 0; i < 100000; i++) {
1025b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    char key[100];
1026b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    snprintf(key, sizeof(key), "B%010d", i);
1027b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    Put(key, value);
1028b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
1029b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Put("C", "vc");
10308cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  dbfull()->TEST_CompactMemTable();
10315fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(0, NULL, NULL);
1032b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
1033b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // Make sparse update
1034b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Put("A",    "va2");
1035b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Put("B100", "bvalue2");
1036b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  Put("C",    "vc2");
1037b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  dbfull()->TEST_CompactMemTable();
1038b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
1039b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // Compactions should not cause us to create a situation where
1040b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  // a file overlaps too much data at the next level.
1041b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
10425fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(0, NULL, NULL);
1043b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
10445fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(1, NULL, NULL);
1045b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576);
1046b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org}
1047b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
1048179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic bool Between(uint64_t val, uint64_t low, uint64_t high) {
1049179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  bool result = (val >= low) && (val <= high);
1050179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (!result) {
1051179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
1052179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            (unsigned long long)(val),
1053179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            (unsigned long long)(low),
1054179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org            (unsigned long long)(high));
1055179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1056179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return result;
1057179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1058179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1059179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, ApproximateSizes) {
106099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
106199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options = CurrentOptions();
106299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.write_buffer_size = 100000000;        // Large write buffer
106399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.compression = kNoCompression;
106499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    DestroyAndReopen();
1065179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
106699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(Between(Size("", "xyz"), 0, 0));
106799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen(&options);
106899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(Between(Size("", "xyz"), 0, 0));
1069179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
107099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Write 8MB (80 values, each 100K)
107199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
107299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const int N = 80;
107399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    static const int S1 = 100000;
107499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    static const int S2 = 105000;  // Allow some expansion from metadata
107599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Random rnd(301);
107699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int i = 0; i < N; i++) {
107799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_OK(Put(Key(i), RandomString(&rnd, S1)));
107899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
1079179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
108099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // 0 because GetApproximateSizes() does not account for memtable space
108199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(Between(Size("", Key(50)), 0, 0));
10828540066c2705c6d2a0595d468a6ab041e4fc72fadgrogan@chromium.org
108399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Check sizes across recovery by reopening a few times
108499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int run = 0; run < 3; run++) {
108599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      Reopen(&options);
10861511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org
108799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      for (int compact_start = 0; compact_start < N; compact_start += 10) {
108899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        for (int i = 0; i < N; i += 10) {
108999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          ASSERT_TRUE(Between(Size("", Key(i)), S1*i, S2*i));
109099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1)));
109199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          ASSERT_TRUE(Between(Size(Key(i), Key(i+10)), S1*10, S2*10));
109299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        }
109399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_TRUE(Between(Size("", Key(50)), S1*50, S2*50));
109499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_TRUE(Between(Size("", Key(50)+".suffix"), S1*50, S2*50));
109599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
109699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        std::string cstart_str = Key(compact_start);
109799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        std::string cend_str = Key(compact_start + 9);
109899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        Slice cstart = cstart_str;
109999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        Slice cend = cend_str;
110099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        dbfull()->TEST_CompactRange(0, &cstart, &cend);
1101179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
11021511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org
110399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_EQ(NumTableFilesAtLevel(0), 0);
110499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_GT(NumTableFilesAtLevel(1), 0);
110599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
110699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
1107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1108179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1109179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) {
111099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
111199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Options options = CurrentOptions();
111299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.compression = kNoCompression;
111399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Reopen();
1114179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
111599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Random rnd(301);
111699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    std::string big1 = RandomString(&rnd, 100000);
111799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(0), RandomString(&rnd, 10000)));
111899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(1), RandomString(&rnd, 10000)));
111999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(2), big1));
112099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(3), RandomString(&rnd, 10000)));
112199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(4), big1));
112299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(5), RandomString(&rnd, 10000)));
112399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(6), RandomString(&rnd, 300000)));
112499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(7), RandomString(&rnd, 10000)));
112599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
112699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Check sizes across recovery by reopening a few times
112799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int run = 0; run < 3; run++) {
112899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      Reopen(&options);
112999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
113099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(0)), 0, 0));
113199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(1)), 10000, 11000));
113299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(2)), 20000, 21000));
113399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(3)), 120000, 121000));
113499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(4)), 130000, 131000));
113599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(5)), 230000, 231000));
113699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(6)), 240000, 241000));
113799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(7)), 540000, 541000));
113899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size("", Key(8)), 550000, 560000));
113999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
114099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000));
114199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
114299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      dbfull()->TEST_CompactRange(0, NULL, NULL);
114399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
114499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
1145179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1146179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1147179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, IteratorPinsRef) {
1148179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "hello");
1149179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1150179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Get iterator that will yield the current contents of the DB.
1151179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Iterator* iter = db_->NewIterator(ReadOptions());
1152179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1153179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Write to force compactions
1154179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "newvalue1");
1155179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 0; i < 100; i++) {
1156179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values
1157179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1158179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "newvalue2");
1159179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1160179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  iter->SeekToFirst();
1161179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(iter->Valid());
1162179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ("foo", iter->key().ToString());
1163179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ("hello", iter->value().ToString());
1164179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  iter->Next();
1165179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(!iter->Valid());
1166179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete iter;
1167179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1168179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1169179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, Snapshot) {
117099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
117199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", "v1");
117299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* s1 = db_->GetSnapshot();
117399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", "v2");
117499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* s2 = db_->GetSnapshot();
117599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", "v3");
117699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* s3 = db_->GetSnapshot();
117799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
117899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", "v4");
117999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo", s1));
118099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo", s2));
118199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v3", Get("foo", s3));
118299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v4", Get("foo"));
118399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
118499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    db_->ReleaseSnapshot(s3);
118599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v1", Get("foo", s1));
118699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo", s2));
118799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v4", Get("foo"));
1188179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
118999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    db_->ReleaseSnapshot(s1);
119099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v2", Get("foo", s2));
119199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v4", Get("foo"));
11928cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
119399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    db_->ReleaseSnapshot(s2);
119499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("v4", Get("foo"));
119599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
119699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com}
1197179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
119899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comTEST(DBTest, HiddenValuesAreRemoved) {
119999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
120099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Random rnd(301);
120199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    FillLevels("a", "z");
120299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
120399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    std::string big = RandomString(&rnd, 50000);
120499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", big);
120599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("pastfoo", "v");
120699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* snapshot = db_->GetSnapshot();
120799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("foo", "tiny");
120899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Put("pastfoo2", "v2");        // Advance sequence number one more
120999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
121099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(dbfull()->TEST_CompactMemTable());
121199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_GT(NumTableFilesAtLevel(0), 0);
121299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
121399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(big, Get("foo", snapshot));
121499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(Between(Size("", "pastfoo"), 50000, 60000));
121599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    db_->ReleaseSnapshot(snapshot);
121699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]");
121799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Slice x("x");
121899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactRange(0, NULL, &x);
121999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
122099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(NumTableFilesAtLevel(0), 0);
122199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_GE(NumTableFilesAtLevel(1), 1);
122299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactRange(1, NULL, &x);
122399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]");
1224179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
122599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000));
122699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
1227179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1228179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1229179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, DeletionMarkers1) {
1230179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "v1");
1231179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_OK(dbfull()->TEST_CompactMemTable());
1232917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  const int last = config::kMaxMemCompactLevel;
12338cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last), 1);   // foo => v1 is now in last level
12348cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
12358cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // Place a table at level last-1 to prevent merging with preceding mutation
12368cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  Put("a", "begin");
12378cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  Put("z", "end");
12388cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  dbfull()->TEST_CompactMemTable();
12398cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last), 1);
12408cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last-1), 1);
12418cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
1242179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Delete("foo");
1243179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "v2");
1244179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]");
12458cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_OK(dbfull()->TEST_CompactMemTable());  // Moves to level last-2
1246179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]");
12475fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  Slice z("z");
12485fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(last-2, NULL, &z);
1249179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // DEL eliminated, but v1 remains because we aren't compacting that level
1250179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // (DEL can be eliminated because v2 hides v1).
1251179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]");
12525fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(last-1, NULL, NULL);
12538cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // Merging last-1 w/ last, so we are the base level for "foo", so
12548cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // DEL is removed.  (as is v1).
1255179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]");
1256179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1257179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1258179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, DeletionMarkers2) {
1259179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Put("foo", "v1");
1260179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_OK(dbfull()->TEST_CompactMemTable());
1261917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com  const int last = config::kMaxMemCompactLevel;
12628cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last), 1);   // foo => v1 is now in last level
12638cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
12648cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // Place a table at level last-1 to prevent merging with preceding mutation
12658cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  Put("a", "begin");
12668cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  Put("z", "end");
12678cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  dbfull()->TEST_CompactMemTable();
12688cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last), 1);
12698cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_EQ(NumTableFilesAtLevel(last-1), 1);
12708cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
1271179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Delete("foo");
1272179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
12738cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  ASSERT_OK(dbfull()->TEST_CompactMemTable());  // Moves to level last-2
1274179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
12755fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(last-2, NULL, NULL);
12768cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // DEL kept: "last" file overlaps
1277179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]");
12785fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  dbfull()->TEST_CompactRange(last-1, NULL, NULL);
12798cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // Merging last-1 w/ last, so we are the base level for "foo", so
12808cd4ab8303620197cf24282ae8639060efbb326egabor@google.com  // DEL is removed.  (as is v1).
1281179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_EQ(AllEntriesFor("foo"), "[ ]");
1282179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1283179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
12845fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.comTEST(DBTest, OverlapInLevel0) {
128599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
128699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config";
12875fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
128899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0.
128999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("100", "v100"));
129099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("999", "v999"));
129199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
129299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Delete("100"));
129399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Delete("999"));
129499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
129599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("0,1,1", FilesPerLevel());
129699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
129799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Make files spanning the following ranges in level-0:
129899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    //  files[0]  200 .. 900
129999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    //  files[1]  300 .. 500
130099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Note that files are sorted by smallest key.
130199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("300", "v300"));
130299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("500", "v500"));
130399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
130499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("200", "v200"));
130599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("600", "v600"));
130699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put("900", "v900"));
130799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
130899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("2,1,1", FilesPerLevel());
13095fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
131099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Compact away the placeholder files we created initially
131199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactRange(1, NULL, NULL);
131299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactRange(2, NULL, NULL);
131399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("2", FilesPerLevel());
13145fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
131599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Do a memtable compaction.  Before bug-fix, the compaction would
131699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // not detect the overlap with level-0 files and would incorrectly place
131799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // the deletion in a deeper level.
131899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Delete("600"));
131999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    dbfull()->TEST_CompactMemTable();
132099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("3", FilesPerLevel());
132199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("600"));
132299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
13235fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com}
13245fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
132545b9940be332834440bd5299419f396e38085ebehans@chromium.orgTEST(DBTest, L0_CompactionBug_Issue44_a) {
132699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
132799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_OK(Put("b", "v"));
132899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
132999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_OK(Delete("b"));
133099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_OK(Delete("a"));
133199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
133299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_OK(Delete("a"));
133399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
133499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_OK(Put("a", "v"));
133599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
133699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
133799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_EQ("(a->v)", Contents());
133811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  DelayMilliseconds(1000);  // Wait for compaction to finish
133999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_EQ("(a->v)", Contents());
134045b9940be332834440bd5299419f396e38085ebehans@chromium.org}
134145b9940be332834440bd5299419f396e38085ebehans@chromium.org
134245b9940be332834440bd5299419f396e38085ebehans@chromium.orgTEST(DBTest, L0_CompactionBug_Issue44_b) {
134399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
134499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("","");
134599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
134699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Delete("e");
134799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("","");
134899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
134999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("c", "cv");
135099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
135199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("","");
135299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
135399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("","");
135411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  DelayMilliseconds(1000);  // Wait for compaction to finish
135599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
135699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("d","dv");
135799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
135899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Put("","");
135999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
136099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Delete("d");
136199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Delete("b");
136299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen();
136399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_EQ("(->)(c->cv)", Contents());
136411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  DelayMilliseconds(1000);  // Wait for compaction to finish
136599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_EQ("(->)(c->cv)", Contents());
136645b9940be332834440bd5299419f396e38085ebehans@chromium.org}
136745b9940be332834440bd5299419f396e38085ebehans@chromium.org
1368179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, ComparatorCheck) {
1369179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  class NewComparator : public Comparator {
1370179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org   public:
1371179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual const char* Name() const { return "leveldb.NewComparator"; }
1372179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual int Compare(const Slice& a, const Slice& b) const {
1373179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return BytewiseComparator()->Compare(a, b);
1374179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1375179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void FindShortestSeparator(std::string* s, const Slice& l) const {
1376179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      BytewiseComparator()->FindShortestSeparator(s, l);
1377179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1378179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void FindShortSuccessor(std::string* key) const {
1379179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      BytewiseComparator()->FindShortSuccessor(key);
1380179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1381179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  };
1382179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  NewComparator cmp;
138399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options new_options = CurrentOptions();
1384179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  new_options.comparator = &cmp;
1385179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status s = TryReopen(&new_options);
1386179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(!s.ok());
1387179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos)
1388179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      << s.ToString();
1389179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1390179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
139145b9940be332834440bd5299419f396e38085ebehans@chromium.orgTEST(DBTest, CustomComparator) {
139245b9940be332834440bd5299419f396e38085ebehans@chromium.org  class NumberComparator : public Comparator {
139345b9940be332834440bd5299419f396e38085ebehans@chromium.org   public:
139445b9940be332834440bd5299419f396e38085ebehans@chromium.org    virtual const char* Name() const { return "test.NumberComparator"; }
139545b9940be332834440bd5299419f396e38085ebehans@chromium.org    virtual int Compare(const Slice& a, const Slice& b) const {
1396ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      return ToNumber(a) - ToNumber(b);
1397ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    }
1398ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    virtual void FindShortestSeparator(std::string* s, const Slice& l) const {
1399ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ToNumber(*s);     // Check format
1400ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ToNumber(l);      // Check format
1401ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    }
1402ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    virtual void FindShortSuccessor(std::string* key) const {
1403ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ToNumber(*key);   // Check format
1404ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    }
1405ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org   private:
1406ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    static int ToNumber(const Slice& x) {
1407ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      // Check that there are no extra characters.
1408ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']')
1409ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org          << EscapeString(x);
1410ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      int val;
1411ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      char ignored;
1412ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1)
1413ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org          << EscapeString(x);
1414ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      return val;
141545b9940be332834440bd5299419f396e38085ebehans@chromium.org    }
141645b9940be332834440bd5299419f396e38085ebehans@chromium.org  };
141745b9940be332834440bd5299419f396e38085ebehans@chromium.org  NumberComparator cmp;
141899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options new_options = CurrentOptions();
141945b9940be332834440bd5299419f396e38085ebehans@chromium.org  new_options.create_if_missing = true;
142045b9940be332834440bd5299419f396e38085ebehans@chromium.org  new_options.comparator = &cmp;
142199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  new_options.filter_policy = NULL;     // Cannot use bloom filters
1422ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org  new_options.write_buffer_size = 1000;  // Compact more often
142345b9940be332834440bd5299419f396e38085ebehans@chromium.org  DestroyAndReopen(&new_options);
1424ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org  ASSERT_OK(Put("[10]", "ten"));
1425ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org  ASSERT_OK(Put("[0x14]", "twenty"));
142645b9940be332834440bd5299419f396e38085ebehans@chromium.org  for (int i = 0; i < 2; i++) {
1427ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    ASSERT_EQ("ten", Get("[10]"));
1428ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    ASSERT_EQ("ten", Get("[0xa]"));
1429ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    ASSERT_EQ("twenty", Get("[20]"));
1430ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    ASSERT_EQ("twenty", Get("[0x14]"));
143199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("[15]"));
143299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get("[0xf]"));
1433ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    Compact("[0]", "[9999]");
1434ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org  }
1435ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org
1436ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org  for (int run = 0; run < 2; run++) {
1437ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    for (int i = 0; i < 1000; i++) {
1438ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      char buf[100];
1439ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      snprintf(buf, sizeof(buf), "[%d]", i*10);
1440ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org      ASSERT_OK(Put(buf, buf));
1441ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    }
1442ac271d8b01dd3a1b6d57b1a4a0e0d28e00f67780hans@chromium.org    Compact("[0]", "[1000000]");
144345b9940be332834440bd5299419f396e38085ebehans@chromium.org  }
144445b9940be332834440bd5299419f396e38085ebehans@chromium.org}
144545b9940be332834440bd5299419f396e38085ebehans@chromium.org
14465fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.comTEST(DBTest, ManualCompaction) {
14475fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ(config::kMaxMemCompactLevel, 2)
14485fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com      << "Need to update this test to match kMaxMemCompactLevel";
14495fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14505fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  MakeTables(3, "p", "q");
14515fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("1,1,1", FilesPerLevel());
14525fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14535fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Compaction range falls before files
14545fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  Compact("", "c");
14555fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("1,1,1", FilesPerLevel());
14565fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14575fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Compaction range falls after files
14585fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  Compact("r", "z");
14595fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("1,1,1", FilesPerLevel());
14605fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14615fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Compaction range overlaps files
14625fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  Compact("p1", "p9");
14635fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("0,0,1", FilesPerLevel());
14645fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14655fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Populate a different range
14665fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  MakeTables(3, "c", "e");
14675fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("1,1,2", FilesPerLevel());
14685fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14695fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Compact just the new range
14705fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  Compact("b", "f");
14715fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("0,0,2", FilesPerLevel());
14725fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
14735fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  // Compact all
14745fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  MakeTables(1, "a", "z");
14755fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("0,1,2", FilesPerLevel());
14765fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  db_->CompactRange(NULL, NULL);
14775fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  ASSERT_EQ("0,0,1", FilesPerLevel());
14785fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com}
14795fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
1480179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, DBOpen_Options) {
1481179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string dbname = test::TmpDir() + "/db_options_test";
1482179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  DestroyDB(dbname, Options());
1483179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1484179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Does not exist, and create_if_missing == false: error
1485179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  DB* db = NULL;
1486179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Options opts;
1487179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.create_if_missing = false;
1488179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status s = DB::Open(opts, dbname, &db);
1489179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != NULL);
1490179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(db == NULL);
1491179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1492179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Does not exist, and create_if_missing == true: OK
1493179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.create_if_missing = true;
1494179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  s = DB::Open(opts, dbname, &db);
1495179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_OK(s);
1496179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(db != NULL);
1497179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1498179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete db;
1499179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  db = NULL;
1500179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1501179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Does exist, and error_if_exists == true: error
1502179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.create_if_missing = false;
1503179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.error_if_exists = true;
1504179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  s = DB::Open(opts, dbname, &db);
1505179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != NULL);
1506179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(db == NULL);
1507179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1508179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Does exist, and error_if_exists == false: OK
1509179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.create_if_missing = true;
1510179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  opts.error_if_exists = false;
1511179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  s = DB::Open(opts, dbname, &db);
1512179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_OK(s);
1513179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ASSERT_TRUE(db != NULL);
1514179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1515179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete db;
1516179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  db = NULL;
1517179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1518179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
151929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.orgTEST(DBTest, Locking) {
152029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org  DB* db2 = NULL;
152129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org  Status s = DB::Open(CurrentOptions(), dbname_, &db2);
152229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org  ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db";
152329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org}
152429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org
1525e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com// Check that number of files does not grow when we are out of space
1526e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.comTEST(DBTest, NoSpace) {
152799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
1528e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  options.env = env_;
1529e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  Reopen(&options);
1530e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
1531e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  ASSERT_OK(Put("foo", "v1"));
1532e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  ASSERT_EQ("v1", Get("foo"));
1533e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  Compact("a", "z");
1534e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  const int num_files = CountFiles();
1535e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  env_->no_space_.Release_Store(env_);   // Force out-of-space errors
15364935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  for (int i = 0; i < 10; i++) {
1537e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    for (int level = 0; level < config::kNumLevels-1; level++) {
1538e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com      dbfull()->TEST_CompactRange(level, NULL, NULL);
1539e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    }
1540e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  }
1541e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  env_->no_space_.Release_Store(NULL);
1542158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  ASSERT_LT(CountFiles(), num_files + 3);
154311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
154411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
1545158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.comTEST(DBTest, NonWritableFileSystem) {
1546158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  Options options = CurrentOptions();
1547158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  options.write_buffer_size = 1000;
1548158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  options.env = env_;
1549158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  Reopen(&options);
1550158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  ASSERT_OK(Put("foo", "v1"));
1551158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  env_->non_writable_.Release_Store(env_);  // Force errors for new files
1552158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  std::string big(100000, 'x');
1553158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  int errors = 0;
1554158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  for (int i = 0; i < 20; i++) {
1555158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    fprintf(stderr, "iter %d; errors %d\n", i, errors);
1556158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    if (!Put("foo", big).ok()) {
1557158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      errors++;
155811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org      DelayMilliseconds(100);
1559158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com    }
1560158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  }
1561158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  ASSERT_GT(errors, 0);
1562158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  env_->non_writable_.Release_Store(NULL);
1563e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com}
1564e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
15654935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.orgTEST(DBTest, WriteSyncError) {
15664935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // Check that log sync errors cause the DB to disallow future writes.
15674935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
15684935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // (a) Cause log sync calls to fail
15694935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  Options options = CurrentOptions();
15704935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  options.env = env_;
15714935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  Reopen(&options);
15724935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  env_->data_sync_error_.Release_Store(env_);
15734935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
15744935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // (b) Normal write should succeed
15754935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  WriteOptions w;
15764935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_OK(db_->Put(w, "k1", "v1"));
15774935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("v1", Get("k1"));
15784935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
15794935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // (c) Do a sync write; should fail
15804935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  w.sync = true;
15814935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok());
15824935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("v1", Get("k1"));
15834935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("NOT_FOUND", Get("k2"));
15844935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
15854935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // (d) make sync behave normally
15864935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  env_->data_sync_error_.Release_Store(NULL);
15874935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
15884935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  // (e) Do a non-sync write; should fail
15894935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  w.sync = false;
15904935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok());
15914935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("v1", Get("k1"));
15924935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("NOT_FOUND", Get("k2"));
15934935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  ASSERT_EQ("NOT_FOUND", Get("k3"));
15944935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org}
15954935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org
159685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.orgTEST(DBTest, ManifestWriteError) {
159785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // Test for the following problem:
159885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // (a) Compaction produces file F
159985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // (b) Log record containing F is written to MANIFEST file, but Sync() fails
160085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // (c) GC deletes F
160185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // (d) After reopening DB, reads fail since deleted F is named in log record
160285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
160385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // We iterate twice.  In the second iteration, everything is the
160485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  // same except the log record never makes it to the MANIFEST file.
160585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  for (int iter = 0; iter < 2; iter++) {
160685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    port::AtomicPointer* error_type = (iter == 0)
160785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        ? &env_->manifest_sync_error_
160885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org        : &env_->manifest_write_error_;
160985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
161085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    // Insert foo=>bar mapping
161185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    Options options = CurrentOptions();
161285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    options.env = env_;
161385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    options.create_if_missing = true;
161485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    options.error_if_exists = false;
161585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    DestroyAndReopen(&options);
161685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_OK(Put("foo", "bar"));
161785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_EQ("bar", Get("foo"));
161885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
161985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    // Memtable compaction (will succeed)
162085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    dbfull()->TEST_CompactMemTable();
162185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_EQ("bar", Get("foo"));
162285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    const int last = config::kMaxMemCompactLevel;
162385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_EQ(NumTableFilesAtLevel(last), 1);   // foo=>bar is now in last level
162485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
162585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    // Merging compaction (will fail)
162685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    error_type->Release_Store(env_);
162785e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    dbfull()->TEST_CompactRange(last, NULL, NULL);  // Should fail
162885e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_EQ("bar", Get("foo"));
162985e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
163085e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    // Recovery: should not lose data
163185e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    error_type->Release_Store(NULL);
163285e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    Reopen(&options);
163385e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org    ASSERT_EQ("bar", Get("foo"));
163485e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org  }
163585e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org}
163685e27d04530c0323957f28c3f47a7d9f6efeceb0dgrogan@chromium.org
1637bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.orgTEST(DBTest, MissingSSTFile) {
1638bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_OK(Put("foo", "bar"));
1639bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_EQ("bar", Get("foo"));
1640bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org
1641bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  // Dump the memtable to disk.
1642bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  dbfull()->TEST_CompactMemTable();
1643bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_EQ("bar", Get("foo"));
1644bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org
164511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  Close();
1646bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_TRUE(DeleteAnSSTFile());
1647bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  Options options = CurrentOptions();
1648bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  options.paranoid_checks = true;
1649bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  Status s = TryReopen(&options);
1650bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_TRUE(!s.ok());
1651bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org  ASSERT_TRUE(s.ToString().find("issing") != std::string::npos)
1652bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org      << s.ToString();
1653bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org}
1654bbb0263070defe02ffee97b35d0dc31d3f6297a3dgrogan@chromium.org
16552d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.orgTEST(DBTest, StillReadSST) {
16562d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_OK(Put("foo", "bar"));
16572d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_EQ("bar", Get("foo"));
16582d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org
16592d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  // Dump the memtable to disk.
16602d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  dbfull()->TEST_CompactMemTable();
16612d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_EQ("bar", Get("foo"));
16622d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  Close();
16632d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_GT(RenameLDBToSST(), 0);
16642d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  Options options = CurrentOptions();
16652d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  options.paranoid_checks = true;
16662d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  Status s = TryReopen(&options);
16672d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_TRUE(s.ok());
16682d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org  ASSERT_EQ("bar", Get("foo"));
16692d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org}
16702d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org
1671e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.comTEST(DBTest, FilesDeletedAfterCompaction) {
1672e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  ASSERT_OK(Put("foo", "v2"));
1673e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  Compact("a", "z");
1674e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  const int num_files = CountFiles();
1675e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  for (int i = 0; i < 10; i++) {
1676e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    ASSERT_OK(Put("foo", "v2"));
1677e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    Compact("a", "z");
1678e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  }
1679e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  ASSERT_EQ(CountFiles(), num_files);
1680e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com}
1681e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com
168299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comTEST(DBTest, BloomFilter) {
168399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  env_->count_random_reads_ = true;
168499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Options options = CurrentOptions();
168599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  options.env = env_;
168699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  options.block_cache = NewLRUCache(0);  // Prevent cache hits
168799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  options.filter_policy = NewBloomFilterPolicy(10);
168899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Reopen(&options);
168999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
169099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Populate multiple layers
169199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  const int N = 10000;
169299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  for (int i = 0; i < N; i++) {
169399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(i), Key(i)));
169499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
169599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Compact("a", "z");
169699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  for (int i = 0; i < N; i += 100) {
169799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_OK(Put(Key(i), Key(i)));
169899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
169999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  dbfull()->TEST_CompactMemTable();
170099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
170199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Prevent auto compactions triggered by seeks
17024935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  env_->delay_data_sync_.Release_Store(env_);
170399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
170499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Lookup present keys.  Should rarely read from small sstable.
170599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  env_->random_read_counter_.Reset();
170699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  for (int i = 0; i < N; i++) {
170799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ(Key(i), Get(Key(i)));
170899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
170999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  int reads = env_->random_read_counter_.Read();
171099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  fprintf(stderr, "%d present => %d reads\n", N, reads);
171199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_GE(reads, N);
171299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_LE(reads, N + 2*N/100);
171399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
171499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Lookup present keys.  Should rarely read from either sstable.
171599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  env_->random_read_counter_.Reset();
171699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  for (int i = 0; i < N; i++) {
171799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing"));
171899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
171999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  reads = env_->random_read_counter_.Read();
172099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  fprintf(stderr, "%d missing => %d reads\n", N, reads);
172199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  ASSERT_LE(reads, 3*N/100);
172299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
17234935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  env_->delay_data_sync_.Release_Store(NULL);
172499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Close();
172599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  delete options.block_cache;
172699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  delete options.filter_policy;
172799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com}
172899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
1729c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org// Multi-threaded test:
1730c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgnamespace {
1731c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1732c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstatic const int kNumThreads = 4;
1733c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstatic const int kTestSeconds = 10;
1734c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstatic const int kNumKeys = 1000;
1735c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1736c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstruct MTState {
1737c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  DBTest* test;
1738c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  port::AtomicPointer stop;
1739c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  port::AtomicPointer counter[kNumThreads];
1740c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  port::AtomicPointer thread_done[kNumThreads];
1741c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org};
1742c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1743c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstruct MTThread {
1744c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  MTState* state;
1745c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  int id;
1746c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org};
1747c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1748c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgstatic void MTThreadBody(void* arg) {
1749c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  MTThread* t = reinterpret_cast<MTThread*>(arg);
1750e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  int id = t->id;
1751c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  DB* db = t->state->test->db_;
1752c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  uintptr_t counter = 0;
1753e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  fprintf(stderr, "... starting thread %d\n", id);
1754e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  Random rnd(1000 + id);
1755c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  std::string value;
1756c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  char valbuf[1500];
1757c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  while (t->state->stop.Acquire_Load() == NULL) {
1758e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com    t->state->counter[id].Release_Store(reinterpret_cast<void*>(counter));
1759c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1760c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    int key = rnd.Uniform(kNumKeys);
1761c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    char keybuf[20];
1762c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    snprintf(keybuf, sizeof(keybuf), "%016d", key);
1763c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1764c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    if (rnd.OneIn(2)) {
1765c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      // Write values of the form <key, my id, counter>.
1766c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      // We add some padding for force compactions.
1767c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d",
1768e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com               key, id, static_cast<int>(counter));
1769c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));
1770c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    } else {
1771c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      // Read a value and verify that it matches the pattern written above.
1772c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      Status s = db->Get(ReadOptions(), Slice(keybuf), &value);
1773c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      if (s.IsNotFound()) {
1774c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        // Key has not yet been written
1775c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      } else {
1776c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        // Check that the writer thread counter is >= the counter in the value
1777c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ASSERT_OK(s);
1778c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        int k, w, c;
1779c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value;
1780c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ASSERT_EQ(k, key);
1781c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ASSERT_GE(w, 0);
1782c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ASSERT_LT(w, kNumThreads);
17834935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org        ASSERT_LE(static_cast<uintptr_t>(c), reinterpret_cast<uintptr_t>(
1784c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org            t->state->counter[w].Acquire_Load()));
1785c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      }
1786c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    }
1787c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    counter++;
1788c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  }
1789e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  t->state->thread_done[id].Release_Store(t);
1790e05bd5cade19e5de0f763f4f122eef9f35de3d9csanjay@google.com  fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter));
1791c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org}
1792c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
179345b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace
1794c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1795c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.orgTEST(DBTest, MultiThreaded) {
179699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
179799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Initialize state
179899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    MTState mt;
179999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    mt.test = this;
180099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    mt.stop.Release_Store(0);
180199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int id = 0; id < kNumThreads; id++) {
180299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      mt.counter[id].Release_Store(0);
180399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      mt.thread_done[id].Release_Store(0);
180499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
1805c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
180699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Start threads
180799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    MTThread thread[kNumThreads];
180899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int id = 0; id < kNumThreads; id++) {
180999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      thread[id].state = &mt;
181099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      thread[id].id = id;
181199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      env_->StartThread(MTThreadBody, &thread[id]);
181299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
1813c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
181499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Let them run for a while
181511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    DelayMilliseconds(kTestSeconds * 1000);
1816c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
181799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    // Stop the threads and wait for them to finish
181899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    mt.stop.Release_Store(&mt);
181999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int id = 0; id < kNumThreads; id++) {
182099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      while (mt.thread_done[id].Acquire_Load() == NULL) {
182111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org        DelayMilliseconds(100);
182299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
1823c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    }
182499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
1825c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org}
1826c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
1827a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgnamespace {
1828a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgtypedef std::map<std::string, std::string> KVMap;
1829a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org}
1830a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
1831179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass ModelDB: public DB {
1832179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public:
1833a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  class ModelSnapshot : public Snapshot {
1834a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org   public:
1835a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    KVMap map_;
1836a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  };
1837a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
1838179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  explicit ModelDB(const Options& options): options_(options) { }
1839179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ~ModelDB() { }
1840179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) {
1841179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return DB::Put(o, k, v);
1842179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1843179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual Status Delete(const WriteOptions& o, const Slice& key) {
1844179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return DB::Delete(o, key);
1845179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1846179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual Status Get(const ReadOptions& options,
1847179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                     const Slice& key, std::string* value) {
1848179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    assert(false);      // Not implemented
1849179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return Status::NotFound(key);
1850179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1851179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual Iterator* NewIterator(const ReadOptions& options) {
1852179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (options.snapshot == NULL) {
1853179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      KVMap* saved = new KVMap;
1854179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      *saved = map_;
1855179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return new ModelIter(saved, true);
1856179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else {
1857179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      const KVMap* snapshot_state =
1858a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org          &(reinterpret_cast<const ModelSnapshot*>(options.snapshot)->map_);
1859179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return new ModelIter(snapshot_state, false);
1860179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1861179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1862179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual const Snapshot* GetSnapshot() {
1863a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    ModelSnapshot* snapshot = new ModelSnapshot;
1864a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    snapshot->map_ = map_;
1865a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    return snapshot;
1866179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1867179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1868179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual void ReleaseSnapshot(const Snapshot* snapshot) {
1869a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    delete reinterpret_cast<const ModelSnapshot*>(snapshot);
1870179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1871179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual Status Write(const WriteOptions& options, WriteBatch* batch) {
1872a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    class Handler : public WriteBatch::Handler {
1873a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org     public:
1874a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      KVMap* map_;
1875a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      virtual void Put(const Slice& key, const Slice& value) {
1876a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org        (*map_)[key.ToString()] = value.ToString();
1877179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
1878a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      virtual void Delete(const Slice& key) {
1879a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org        map_->erase(key.ToString());
1880a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      }
1881a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    };
1882a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    Handler handler;
1883a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    handler.map_ = &map_;
1884a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    return batch->Iterate(&handler);
1885179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1886179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
188795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  virtual bool GetProperty(const Slice& property, std::string* value) {
1888179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return false;
1889179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1890179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) {
1891179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    for (int i = 0; i < n; i++) {
1892179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      sizes[i] = 0;
1893179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1894179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
18955fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  virtual void CompactRange(const Slice* start, const Slice* end) {
18965fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com  }
18975fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com
1898179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private:
1899179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  class ModelIter: public Iterator {
1900179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org   public:
1901179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ModelIter(const KVMap* map, bool owned)
1902179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        : map_(map), owned_(owned), iter_(map_->end()) {
1903179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1904179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ~ModelIter() {
1905179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (owned_) delete map_;
1906179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1907179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual bool Valid() const { return iter_ != map_->end(); }
1908179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void SeekToFirst() { iter_ = map_->begin(); }
1909179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void SeekToLast() {
1910179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (map_->empty()) {
1911179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        iter_ = map_->end();
1912179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else {
1913179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        iter_ = map_->find(map_->rbegin()->first);
1914179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
1915179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1916179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void Seek(const Slice& k) {
1917179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      iter_ = map_->lower_bound(k.ToString());
1918179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1919179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void Next() { ++iter_; }
1920179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual void Prev() { --iter_; }
1921179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual Slice key() const { return iter_->first; }
1922179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual Slice value() const { return iter_->second; }
1923179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    virtual Status status() const { return Status::OK(); }
1924179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org   private:
1925179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    const KVMap* const map_;
1926179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    const bool owned_;  // Do we own map_
1927179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    KVMap::const_iterator iter_;
1928179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  };
1929179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  const Options options_;
1930179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  KVMap map_;
1931179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
1932179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1933179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic std::string RandomKey(Random* rnd) {
1934179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int len = (rnd->OneIn(3)
1935179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org             ? 1                // Short sometimes to encourage collisions
1936179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org             : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
1937179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return test::RandomKey(rnd, len);
1938179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1939179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1940179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic bool CompareIterators(int step,
1941179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                             DB* model,
1942179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                             DB* db,
1943179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                             const Snapshot* model_snap,
1944179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org                             const Snapshot* db_snap) {
1945179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ReadOptions options;
1946179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  options.snapshot = model_snap;
1947179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Iterator* miter = model->NewIterator(options);
1948179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  options.snapshot = db_snap;
1949179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Iterator* dbiter = db->NewIterator(options);
1950179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  bool ok = true;
1951179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int count = 0;
1952179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (miter->SeekToFirst(), dbiter->SeekToFirst();
1953179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org       ok && miter->Valid() && dbiter->Valid();
1954179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org       miter->Next(), dbiter->Next()) {
1955179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    count++;
1956179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (miter->key().compare(dbiter->key()) != 0) {
1957179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n",
1958179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              step,
1959179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              EscapeString(miter->key()).c_str(),
1960179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              EscapeString(dbiter->key()).c_str());
1961179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      ok = false;
1962179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      break;
1963179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1964179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1965179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (miter->value().compare(dbiter->value()) != 0) {
1966179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n",
1967179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              step,
1968179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              EscapeString(miter->key()).c_str(),
1969179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              EscapeString(miter->value()).c_str(),
1970179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              EscapeString(miter->value()).c_str());
1971179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      ok = false;
1972179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1973179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1974179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1975179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (ok) {
1976179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (miter->Valid() != dbiter->Valid()) {
1977179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      fprintf(stderr, "step %d: Mismatch at end of iterators: %d vs. %d\n",
1978179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org              step, miter->Valid(), dbiter->Valid());
1979179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      ok = false;
1980179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
1981179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
1982179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  fprintf(stderr, "%d entries compared: ok=%d\n", count, ok);
1983179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete miter;
1984179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete dbiter;
1985179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return ok;
1986179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
1987179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1988179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTEST(DBTest, Randomized) {
1989179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Random rnd(test::RandomSeed());
199099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  do {
199199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ModelDB model(CurrentOptions());
199299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const int N = 10000;
199399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* model_snap = NULL;
199499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    const Snapshot* db_snap = NULL;
199599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    std::string k, v;
199699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int step = 0; step < N; step++) {
199799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if (step % 100 == 0) {
199899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        fprintf(stderr, "Step %d of %d\n", step, N);
199999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
200099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      // TODO(sanjay): Test Get() works
200199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      int p = rnd.Uniform(100);
200299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if (p < 45) {                               // Put
200399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        k = RandomKey(&rnd);
200499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        v = RandomString(&rnd,
200599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                         rnd.OneIn(20)
200699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                         ? 100 + rnd.Uniform(100)
200799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                         : rnd.Uniform(8));
200899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(model.Put(WriteOptions(), k, v));
200999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(db_->Put(WriteOptions(), k, v));
201099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
201199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (p < 90) {                        // Delete
201299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        k = RandomKey(&rnd);
201399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(model.Delete(WriteOptions(), k));
201499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(db_->Delete(WriteOptions(), k));
201599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
201699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
201799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else {                                    // Multi-element batch
201899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        WriteBatch b;
201999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        const int num = rnd.Uniform(8);
202099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        for (int i = 0; i < num; i++) {
202199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          if (i == 0 || !rnd.OneIn(10)) {
202299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            k = RandomKey(&rnd);
202399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          } else {
202499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            // Periodically re-use the same key from the previous iter, so
202599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            // we have multiple entries in the write batch for the same key
202699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          }
202799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          if (rnd.OneIn(2)) {
202899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            v = RandomString(&rnd, rnd.Uniform(10));
202999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            b.Put(k, v);
203099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          } else {
203199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com            b.Delete(k);
203299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com          }
2033179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        }
203499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(model.Write(WriteOptions(), &b));
203599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_OK(db_->Write(WriteOptions(), &b));
2036179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
2037179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
203899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if ((step % 100) == 0) {
203999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL));
204099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap));
204199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        // Save a snapshot from each DB this time that we'll use next
204299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        // time we compare things, to make sure the current state is
204399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        // preserved with the snapshot
204499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        if (model_snap != NULL) model.ReleaseSnapshot(model_snap);
204599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        if (db_snap != NULL) db_->ReleaseSnapshot(db_snap);
2046179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
204799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        Reopen();
204899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL));
2049179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
205099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        model_snap = model.GetSnapshot();
205199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        db_snap = db_->GetSnapshot();
205299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
2053179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
205499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    if (model_snap != NULL) model.ReleaseSnapshot(model_snap);
205599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    if (db_snap != NULL) db_->ReleaseSnapshot(db_snap);
205699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  } while (ChangeOptions());
2057179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
2058179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
2059a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgstd::string MakeKey(unsigned int num) {
2060a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  char buf[30];
2061a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  snprintf(buf, sizeof(buf), "%016u", num);
2062a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  return std::string(buf);
2063a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org}
2064a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2065a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgvoid BM_LogAndApply(int iters, int num_base_files) {
2066a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  std::string dbname = test::TmpDir() + "/leveldb_test_benchmark";
2067a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  DestroyDB(dbname, Options());
2068a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2069a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  DB* db = NULL;
2070a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  Options opts;
2071a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  opts.create_if_missing = true;
2072a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  Status s = DB::Open(opts, dbname, &db);
2073a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  ASSERT_OK(s);
2074a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  ASSERT_TRUE(db != NULL);
2075a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2076a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  delete db;
2077a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  db = NULL;
2078a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2079a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  Env* env = Env::Default();
2080a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2081394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  port::Mutex mu;
2082394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  MutexLock l(&mu);
2083394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
2084a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  InternalKeyComparator cmp(BytewiseComparator());
2085a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  Options options;
2086a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  VersionSet vset(dbname, &options, NULL, &cmp);
2087a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  ASSERT_OK(vset.Recover());
2088a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  VersionEdit vbase;
2089a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  uint64_t fnum = 1;
2090a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  for (int i = 0; i < num_base_files; i++) {
2091a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    InternalKey start(MakeKey(2*fnum), 1, kTypeValue);
2092a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion);
2093a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    vbase.AddFile(2, fnum++, 1 /* file size */, start, limit);
2094a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  }
2095394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  ASSERT_OK(vset.LogAndApply(&vbase, &mu));
2096a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2097a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  uint64_t start_micros = env->NowMicros();
2098a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2099a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  for (int i = 0; i < iters; i++) {
2100a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    VersionEdit vedit;
2101a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    vedit.DeleteFile(2, fnum);
2102a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    InternalKey start(MakeKey(2*fnum), 1, kTypeValue);
2103a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion);
2104a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    vedit.AddFile(2, fnum++, 1 /* file size */, start, limit);
2105394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com    vset.LogAndApply(&vedit, &mu);
2106a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  }
2107a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  uint64_t stop_micros = env->NowMicros();
2108a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  unsigned int us = stop_micros - start_micros;
2109a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  char buf[16];
2110a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  snprintf(buf, sizeof(buf), "%d", num_base_files);
2111a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  fprintf(stderr,
2112a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org          "BM_LogAndApply/%-6s   %8d iters : %9u us (%7.0f us / iter)\n",
2113a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org          buf, iters, us, ((float)us) / iters);
2114a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org}
2115a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
211645b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace leveldb
2117179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
2118179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgint main(int argc, char** argv) {
2119a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  if (argc > 1 && std::string(argv[1]) == "--benchmark") {
2120a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    leveldb::BM_LogAndApply(1000, 1);
2121a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    leveldb::BM_LogAndApply(1000, 100);
2122a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    leveldb::BM_LogAndApply(1000, 10000);
2123a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    leveldb::BM_LogAndApply(100, 100000);
2124a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    return 0;
2125a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  }
2126a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
2127179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return leveldb::test::RunAllTests();
2128179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
2129