108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org// Copyright (c) 2013 The LevelDB Authors. All rights reserved. 208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org// Use of this source code is governed by a BSD-style license that can be 308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors. 408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org#include "leveldb/db.h" 608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org#include "db/db_impl.h" 708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org#include "leveldb/cache.h" 808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org#include "util/testharness.h" 908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org#include "util/testutil.h" 1008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 1108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgnamespace leveldb { 1208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 1308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgclass AutoCompactTest { 1408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org public: 1508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org std::string dbname_; 1608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org Cache* tiny_cache_; 1708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org Options options_; 1808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DB* db_; 1908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 2008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org AutoCompactTest() { 2108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org dbname_ = test::TmpDir() + "/autocompact_test"; 2208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org tiny_cache_ = NewLRUCache(100); 2308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org options_.block_cache = tiny_cache_; 2408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DestroyDB(dbname_, options_); 2508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org options_.create_if_missing = true; 2608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org options_.compression = kNoCompression; 2708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_OK(DB::Open(options_, dbname_, &db_)); 2808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 2908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 3008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ~AutoCompactTest() { 3108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org delete db_; 3208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DestroyDB(dbname_, Options()); 3308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org delete tiny_cache_; 3408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 3508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 3608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org std::string Key(int i) { 3708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org char buf[100]; 3808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org snprintf(buf, sizeof(buf), "key%06d", i); 3908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org return std::string(buf); 4008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 4108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 4208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org uint64_t Size(const Slice& start, const Slice& limit) { 4308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org Range r(start, limit); 4408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org uint64_t size; 4508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org db_->GetApproximateSizes(&r, 1, &size); 4608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org return size; 4708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 4808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 4908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org void DoReads(int n); 5008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org}; 5108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 5208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgstatic const int kValueSize = 200 * 1024; 5308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgstatic const int kTotalSize = 100 * 1024 * 1024; 5408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgstatic const int kCount = kTotalSize / kValueSize; 5508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 5608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org// Read through the first n keys repeatedly and check that they get 5708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org// compacted (verified by checking the size of the key space). 5808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgvoid AutoCompactTest::DoReads(int n) { 5908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org std::string value(kValueSize, 'x'); 6008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DBImpl* dbi = reinterpret_cast<DBImpl*>(db_); 6108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 6208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Fill database 6308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org for (int i = 0; i < kCount; i++) { 6408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_OK(db_->Put(WriteOptions(), Key(i), value)); 6508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 6608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_OK(dbi->TEST_CompactMemTable()); 6708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 6808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Delete everything 6908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org for (int i = 0; i < kCount; i++) { 7008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_OK(db_->Delete(WriteOptions(), Key(i))); 7108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 7208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_OK(dbi->TEST_CompactMemTable()); 7308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 7408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Get initial measurement of the space we will be reading. 7508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org const int64_t initial_size = Size(Key(0), Key(n)); 7608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org const int64_t initial_other_size = Size(Key(n), Key(kCount)); 7708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 7808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Read until size drops significantly. 7908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org std::string limit_key = Key(n); 8008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org for (int read = 0; true; read++) { 8108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_LT(read, 100) << "Taking too long to compact"; 8208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org Iterator* iter = db_->NewIterator(ReadOptions()); 8308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org for (iter->SeekToFirst(); 8408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org iter->Valid() && iter->key().ToString() < limit_key; 8508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org iter->Next()) { 8608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Drop data 8708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 8808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org delete iter; 8908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Wait a little bit to allow any triggered compactions to complete. 9008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org Env::Default()->SleepForMicroseconds(1000000); 9108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org uint64_t size = Size(Key(0), Key(n)); 9208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n", 9308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0); 9408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org if (size <= initial_size/10) { 9508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org break; 9608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 9708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org } 9808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 9908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // Verify that the size of the key space not touched by the reads 10008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org // is pretty much unchanged. 10108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org const int64_t final_other_size = Size(Key(n), Key(kCount)); 10208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_LE(final_other_size, initial_other_size + 1048576); 10308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org ASSERT_GE(final_other_size, initial_other_size/5 - 1048576); 10408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org} 10508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 10608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgTEST(AutoCompactTest, ReadAll) { 10708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DoReads(kCount); 10808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org} 10908595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 11008595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgTEST(AutoCompactTest, ReadHalf) { 11108595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org DoReads(kCount/2); 11208595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org} 11308595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 11408595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org} // namespace leveldb 11508595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org 11608595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.orgint main(int argc, char** argv) { 11708595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org return leveldb::test::RunAllTests(); 11808595b9e51ded54851b7664bd38affad63a67838dgrogan@chromium.org} 119