1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker
5*9507f98cSAndroid Build Coastguard Worker #include "leveldb/table.h"
6*9507f98cSAndroid Build Coastguard Worker
7*9507f98cSAndroid Build Coastguard Worker #include <map>
8*9507f98cSAndroid Build Coastguard Worker #include <string>
9*9507f98cSAndroid Build Coastguard Worker
10*9507f98cSAndroid Build Coastguard Worker #include "gtest/gtest.h"
11*9507f98cSAndroid Build Coastguard Worker #include "db/dbformat.h"
12*9507f98cSAndroid Build Coastguard Worker #include "db/memtable.h"
13*9507f98cSAndroid Build Coastguard Worker #include "db/write_batch_internal.h"
14*9507f98cSAndroid Build Coastguard Worker #include "leveldb/db.h"
15*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
16*9507f98cSAndroid Build Coastguard Worker #include "leveldb/iterator.h"
17*9507f98cSAndroid Build Coastguard Worker #include "leveldb/table_builder.h"
18*9507f98cSAndroid Build Coastguard Worker #include "table/block.h"
19*9507f98cSAndroid Build Coastguard Worker #include "table/block_builder.h"
20*9507f98cSAndroid Build Coastguard Worker #include "table/format.h"
21*9507f98cSAndroid Build Coastguard Worker #include "util/random.h"
22*9507f98cSAndroid Build Coastguard Worker #include "util/testutil.h"
23*9507f98cSAndroid Build Coastguard Worker
24*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
25*9507f98cSAndroid Build Coastguard Worker
26*9507f98cSAndroid Build Coastguard Worker // Return reverse of "key".
27*9507f98cSAndroid Build Coastguard Worker // Used to test non-lexicographic comparators.
Reverse(const Slice & key)28*9507f98cSAndroid Build Coastguard Worker static std::string Reverse(const Slice& key) {
29*9507f98cSAndroid Build Coastguard Worker std::string str(key.ToString());
30*9507f98cSAndroid Build Coastguard Worker std::string rev("");
31*9507f98cSAndroid Build Coastguard Worker for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend();
32*9507f98cSAndroid Build Coastguard Worker ++rit) {
33*9507f98cSAndroid Build Coastguard Worker rev.push_back(*rit);
34*9507f98cSAndroid Build Coastguard Worker }
35*9507f98cSAndroid Build Coastguard Worker return rev;
36*9507f98cSAndroid Build Coastguard Worker }
37*9507f98cSAndroid Build Coastguard Worker
38*9507f98cSAndroid Build Coastguard Worker namespace {
39*9507f98cSAndroid Build Coastguard Worker class ReverseKeyComparator : public Comparator {
40*9507f98cSAndroid Build Coastguard Worker public:
Name() const41*9507f98cSAndroid Build Coastguard Worker const char* Name() const override {
42*9507f98cSAndroid Build Coastguard Worker return "leveldb.ReverseBytewiseComparator";
43*9507f98cSAndroid Build Coastguard Worker }
44*9507f98cSAndroid Build Coastguard Worker
Compare(const Slice & a,const Slice & b) const45*9507f98cSAndroid Build Coastguard Worker int Compare(const Slice& a, const Slice& b) const override {
46*9507f98cSAndroid Build Coastguard Worker return BytewiseComparator()->Compare(Reverse(a), Reverse(b));
47*9507f98cSAndroid Build Coastguard Worker }
48*9507f98cSAndroid Build Coastguard Worker
FindShortestSeparator(std::string * start,const Slice & limit) const49*9507f98cSAndroid Build Coastguard Worker void FindShortestSeparator(std::string* start,
50*9507f98cSAndroid Build Coastguard Worker const Slice& limit) const override {
51*9507f98cSAndroid Build Coastguard Worker std::string s = Reverse(*start);
52*9507f98cSAndroid Build Coastguard Worker std::string l = Reverse(limit);
53*9507f98cSAndroid Build Coastguard Worker BytewiseComparator()->FindShortestSeparator(&s, l);
54*9507f98cSAndroid Build Coastguard Worker *start = Reverse(s);
55*9507f98cSAndroid Build Coastguard Worker }
56*9507f98cSAndroid Build Coastguard Worker
FindShortSuccessor(std::string * key) const57*9507f98cSAndroid Build Coastguard Worker void FindShortSuccessor(std::string* key) const override {
58*9507f98cSAndroid Build Coastguard Worker std::string s = Reverse(*key);
59*9507f98cSAndroid Build Coastguard Worker BytewiseComparator()->FindShortSuccessor(&s);
60*9507f98cSAndroid Build Coastguard Worker *key = Reverse(s);
61*9507f98cSAndroid Build Coastguard Worker }
62*9507f98cSAndroid Build Coastguard Worker };
63*9507f98cSAndroid Build Coastguard Worker } // namespace
64*9507f98cSAndroid Build Coastguard Worker static ReverseKeyComparator reverse_key_comparator;
65*9507f98cSAndroid Build Coastguard Worker
Increment(const Comparator * cmp,std::string * key)66*9507f98cSAndroid Build Coastguard Worker static void Increment(const Comparator* cmp, std::string* key) {
67*9507f98cSAndroid Build Coastguard Worker if (cmp == BytewiseComparator()) {
68*9507f98cSAndroid Build Coastguard Worker key->push_back('\0');
69*9507f98cSAndroid Build Coastguard Worker } else {
70*9507f98cSAndroid Build Coastguard Worker assert(cmp == &reverse_key_comparator);
71*9507f98cSAndroid Build Coastguard Worker std::string rev = Reverse(*key);
72*9507f98cSAndroid Build Coastguard Worker rev.push_back('\0');
73*9507f98cSAndroid Build Coastguard Worker *key = Reverse(rev);
74*9507f98cSAndroid Build Coastguard Worker }
75*9507f98cSAndroid Build Coastguard Worker }
76*9507f98cSAndroid Build Coastguard Worker
77*9507f98cSAndroid Build Coastguard Worker // An STL comparator that uses a Comparator
78*9507f98cSAndroid Build Coastguard Worker namespace {
79*9507f98cSAndroid Build Coastguard Worker struct STLLessThan {
80*9507f98cSAndroid Build Coastguard Worker const Comparator* cmp;
81*9507f98cSAndroid Build Coastguard Worker
STLLessThanleveldb::__anone8b7d7260211::STLLessThan82*9507f98cSAndroid Build Coastguard Worker STLLessThan() : cmp(BytewiseComparator()) {}
STLLessThanleveldb::__anone8b7d7260211::STLLessThan83*9507f98cSAndroid Build Coastguard Worker STLLessThan(const Comparator* c) : cmp(c) {}
operator ()leveldb::__anone8b7d7260211::STLLessThan84*9507f98cSAndroid Build Coastguard Worker bool operator()(const std::string& a, const std::string& b) const {
85*9507f98cSAndroid Build Coastguard Worker return cmp->Compare(Slice(a), Slice(b)) < 0;
86*9507f98cSAndroid Build Coastguard Worker }
87*9507f98cSAndroid Build Coastguard Worker };
88*9507f98cSAndroid Build Coastguard Worker } // namespace
89*9507f98cSAndroid Build Coastguard Worker
90*9507f98cSAndroid Build Coastguard Worker class StringSink : public WritableFile {
91*9507f98cSAndroid Build Coastguard Worker public:
92*9507f98cSAndroid Build Coastguard Worker ~StringSink() override = default;
93*9507f98cSAndroid Build Coastguard Worker
contents() const94*9507f98cSAndroid Build Coastguard Worker const std::string& contents() const { return contents_; }
95*9507f98cSAndroid Build Coastguard Worker
Close()96*9507f98cSAndroid Build Coastguard Worker Status Close() override { return Status::OK(); }
Flush()97*9507f98cSAndroid Build Coastguard Worker Status Flush() override { return Status::OK(); }
Sync()98*9507f98cSAndroid Build Coastguard Worker Status Sync() override { return Status::OK(); }
99*9507f98cSAndroid Build Coastguard Worker
Append(const Slice & data)100*9507f98cSAndroid Build Coastguard Worker Status Append(const Slice& data) override {
101*9507f98cSAndroid Build Coastguard Worker contents_.append(data.data(), data.size());
102*9507f98cSAndroid Build Coastguard Worker return Status::OK();
103*9507f98cSAndroid Build Coastguard Worker }
104*9507f98cSAndroid Build Coastguard Worker
105*9507f98cSAndroid Build Coastguard Worker private:
106*9507f98cSAndroid Build Coastguard Worker std::string contents_;
107*9507f98cSAndroid Build Coastguard Worker };
108*9507f98cSAndroid Build Coastguard Worker
109*9507f98cSAndroid Build Coastguard Worker class StringSource : public RandomAccessFile {
110*9507f98cSAndroid Build Coastguard Worker public:
StringSource(const Slice & contents)111*9507f98cSAndroid Build Coastguard Worker StringSource(const Slice& contents)
112*9507f98cSAndroid Build Coastguard Worker : contents_(contents.data(), contents.size()) {}
113*9507f98cSAndroid Build Coastguard Worker
114*9507f98cSAndroid Build Coastguard Worker ~StringSource() override = default;
115*9507f98cSAndroid Build Coastguard Worker
Size() const116*9507f98cSAndroid Build Coastguard Worker uint64_t Size() const { return contents_.size(); }
117*9507f98cSAndroid Build Coastguard Worker
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const118*9507f98cSAndroid Build Coastguard Worker Status Read(uint64_t offset, size_t n, Slice* result,
119*9507f98cSAndroid Build Coastguard Worker char* scratch) const override {
120*9507f98cSAndroid Build Coastguard Worker if (offset >= contents_.size()) {
121*9507f98cSAndroid Build Coastguard Worker return Status::InvalidArgument("invalid Read offset");
122*9507f98cSAndroid Build Coastguard Worker }
123*9507f98cSAndroid Build Coastguard Worker if (offset + n > contents_.size()) {
124*9507f98cSAndroid Build Coastguard Worker n = contents_.size() - offset;
125*9507f98cSAndroid Build Coastguard Worker }
126*9507f98cSAndroid Build Coastguard Worker std::memcpy(scratch, &contents_[offset], n);
127*9507f98cSAndroid Build Coastguard Worker *result = Slice(scratch, n);
128*9507f98cSAndroid Build Coastguard Worker return Status::OK();
129*9507f98cSAndroid Build Coastguard Worker }
130*9507f98cSAndroid Build Coastguard Worker
131*9507f98cSAndroid Build Coastguard Worker private:
132*9507f98cSAndroid Build Coastguard Worker std::string contents_;
133*9507f98cSAndroid Build Coastguard Worker };
134*9507f98cSAndroid Build Coastguard Worker
135*9507f98cSAndroid Build Coastguard Worker typedef std::map<std::string, std::string, STLLessThan> KVMap;
136*9507f98cSAndroid Build Coastguard Worker
137*9507f98cSAndroid Build Coastguard Worker // Helper class for tests to unify the interface between
138*9507f98cSAndroid Build Coastguard Worker // BlockBuilder/TableBuilder and Block/Table.
139*9507f98cSAndroid Build Coastguard Worker class Constructor {
140*9507f98cSAndroid Build Coastguard Worker public:
Constructor(const Comparator * cmp)141*9507f98cSAndroid Build Coastguard Worker explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) {}
142*9507f98cSAndroid Build Coastguard Worker virtual ~Constructor() = default;
143*9507f98cSAndroid Build Coastguard Worker
Add(const std::string & key,const Slice & value)144*9507f98cSAndroid Build Coastguard Worker void Add(const std::string& key, const Slice& value) {
145*9507f98cSAndroid Build Coastguard Worker data_[key] = value.ToString();
146*9507f98cSAndroid Build Coastguard Worker }
147*9507f98cSAndroid Build Coastguard Worker
148*9507f98cSAndroid Build Coastguard Worker // Finish constructing the data structure with all the keys that have
149*9507f98cSAndroid Build Coastguard Worker // been added so far. Returns the keys in sorted order in "*keys"
150*9507f98cSAndroid Build Coastguard Worker // and stores the key/value pairs in "*kvmap"
Finish(const Options & options,std::vector<std::string> * keys,KVMap * kvmap)151*9507f98cSAndroid Build Coastguard Worker void Finish(const Options& options, std::vector<std::string>* keys,
152*9507f98cSAndroid Build Coastguard Worker KVMap* kvmap) {
153*9507f98cSAndroid Build Coastguard Worker *kvmap = data_;
154*9507f98cSAndroid Build Coastguard Worker keys->clear();
155*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : data_) {
156*9507f98cSAndroid Build Coastguard Worker keys->push_back(kvp.first);
157*9507f98cSAndroid Build Coastguard Worker }
158*9507f98cSAndroid Build Coastguard Worker data_.clear();
159*9507f98cSAndroid Build Coastguard Worker Status s = FinishImpl(options, *kvmap);
160*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(s.ok()) << s.ToString();
161*9507f98cSAndroid Build Coastguard Worker }
162*9507f98cSAndroid Build Coastguard Worker
163*9507f98cSAndroid Build Coastguard Worker // Construct the data structure from the data in "data"
164*9507f98cSAndroid Build Coastguard Worker virtual Status FinishImpl(const Options& options, const KVMap& data) = 0;
165*9507f98cSAndroid Build Coastguard Worker
166*9507f98cSAndroid Build Coastguard Worker virtual Iterator* NewIterator() const = 0;
167*9507f98cSAndroid Build Coastguard Worker
data() const168*9507f98cSAndroid Build Coastguard Worker const KVMap& data() const { return data_; }
169*9507f98cSAndroid Build Coastguard Worker
db() const170*9507f98cSAndroid Build Coastguard Worker virtual DB* db() const { return nullptr; } // Overridden in DBConstructor
171*9507f98cSAndroid Build Coastguard Worker
172*9507f98cSAndroid Build Coastguard Worker private:
173*9507f98cSAndroid Build Coastguard Worker KVMap data_;
174*9507f98cSAndroid Build Coastguard Worker };
175*9507f98cSAndroid Build Coastguard Worker
176*9507f98cSAndroid Build Coastguard Worker class BlockConstructor : public Constructor {
177*9507f98cSAndroid Build Coastguard Worker public:
BlockConstructor(const Comparator * cmp)178*9507f98cSAndroid Build Coastguard Worker explicit BlockConstructor(const Comparator* cmp)
179*9507f98cSAndroid Build Coastguard Worker : Constructor(cmp), comparator_(cmp), block_(nullptr) {}
~BlockConstructor()180*9507f98cSAndroid Build Coastguard Worker ~BlockConstructor() override { delete block_; }
FinishImpl(const Options & options,const KVMap & data)181*9507f98cSAndroid Build Coastguard Worker Status FinishImpl(const Options& options, const KVMap& data) override {
182*9507f98cSAndroid Build Coastguard Worker delete block_;
183*9507f98cSAndroid Build Coastguard Worker block_ = nullptr;
184*9507f98cSAndroid Build Coastguard Worker BlockBuilder builder(&options);
185*9507f98cSAndroid Build Coastguard Worker
186*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : data) {
187*9507f98cSAndroid Build Coastguard Worker builder.Add(kvp.first, kvp.second);
188*9507f98cSAndroid Build Coastguard Worker }
189*9507f98cSAndroid Build Coastguard Worker // Open the block
190*9507f98cSAndroid Build Coastguard Worker data_ = builder.Finish().ToString();
191*9507f98cSAndroid Build Coastguard Worker BlockContents contents;
192*9507f98cSAndroid Build Coastguard Worker contents.data = data_;
193*9507f98cSAndroid Build Coastguard Worker contents.cachable = false;
194*9507f98cSAndroid Build Coastguard Worker contents.heap_allocated = false;
195*9507f98cSAndroid Build Coastguard Worker block_ = new Block(contents);
196*9507f98cSAndroid Build Coastguard Worker return Status::OK();
197*9507f98cSAndroid Build Coastguard Worker }
NewIterator() const198*9507f98cSAndroid Build Coastguard Worker Iterator* NewIterator() const override {
199*9507f98cSAndroid Build Coastguard Worker return block_->NewIterator(comparator_);
200*9507f98cSAndroid Build Coastguard Worker }
201*9507f98cSAndroid Build Coastguard Worker
202*9507f98cSAndroid Build Coastguard Worker private:
203*9507f98cSAndroid Build Coastguard Worker const Comparator* const comparator_;
204*9507f98cSAndroid Build Coastguard Worker std::string data_;
205*9507f98cSAndroid Build Coastguard Worker Block* block_;
206*9507f98cSAndroid Build Coastguard Worker
207*9507f98cSAndroid Build Coastguard Worker BlockConstructor();
208*9507f98cSAndroid Build Coastguard Worker };
209*9507f98cSAndroid Build Coastguard Worker
210*9507f98cSAndroid Build Coastguard Worker class TableConstructor : public Constructor {
211*9507f98cSAndroid Build Coastguard Worker public:
TableConstructor(const Comparator * cmp)212*9507f98cSAndroid Build Coastguard Worker TableConstructor(const Comparator* cmp)
213*9507f98cSAndroid Build Coastguard Worker : Constructor(cmp), source_(nullptr), table_(nullptr) {}
~TableConstructor()214*9507f98cSAndroid Build Coastguard Worker ~TableConstructor() override { Reset(); }
FinishImpl(const Options & options,const KVMap & data)215*9507f98cSAndroid Build Coastguard Worker Status FinishImpl(const Options& options, const KVMap& data) override {
216*9507f98cSAndroid Build Coastguard Worker Reset();
217*9507f98cSAndroid Build Coastguard Worker StringSink sink;
218*9507f98cSAndroid Build Coastguard Worker TableBuilder builder(options, &sink);
219*9507f98cSAndroid Build Coastguard Worker
220*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : data) {
221*9507f98cSAndroid Build Coastguard Worker builder.Add(kvp.first, kvp.second);
222*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(builder.status());
223*9507f98cSAndroid Build Coastguard Worker }
224*9507f98cSAndroid Build Coastguard Worker Status s = builder.Finish();
225*9507f98cSAndroid Build Coastguard Worker EXPECT_LEVELDB_OK(s);
226*9507f98cSAndroid Build Coastguard Worker
227*9507f98cSAndroid Build Coastguard Worker EXPECT_EQ(sink.contents().size(), builder.FileSize());
228*9507f98cSAndroid Build Coastguard Worker
229*9507f98cSAndroid Build Coastguard Worker // Open the table
230*9507f98cSAndroid Build Coastguard Worker source_ = new StringSource(sink.contents());
231*9507f98cSAndroid Build Coastguard Worker Options table_options;
232*9507f98cSAndroid Build Coastguard Worker table_options.comparator = options.comparator;
233*9507f98cSAndroid Build Coastguard Worker return Table::Open(table_options, source_, sink.contents().size(), &table_);
234*9507f98cSAndroid Build Coastguard Worker }
235*9507f98cSAndroid Build Coastguard Worker
NewIterator() const236*9507f98cSAndroid Build Coastguard Worker Iterator* NewIterator() const override {
237*9507f98cSAndroid Build Coastguard Worker return table_->NewIterator(ReadOptions());
238*9507f98cSAndroid Build Coastguard Worker }
239*9507f98cSAndroid Build Coastguard Worker
ApproximateOffsetOf(const Slice & key) const240*9507f98cSAndroid Build Coastguard Worker uint64_t ApproximateOffsetOf(const Slice& key) const {
241*9507f98cSAndroid Build Coastguard Worker return table_->ApproximateOffsetOf(key);
242*9507f98cSAndroid Build Coastguard Worker }
243*9507f98cSAndroid Build Coastguard Worker
244*9507f98cSAndroid Build Coastguard Worker private:
Reset()245*9507f98cSAndroid Build Coastguard Worker void Reset() {
246*9507f98cSAndroid Build Coastguard Worker delete table_;
247*9507f98cSAndroid Build Coastguard Worker delete source_;
248*9507f98cSAndroid Build Coastguard Worker table_ = nullptr;
249*9507f98cSAndroid Build Coastguard Worker source_ = nullptr;
250*9507f98cSAndroid Build Coastguard Worker }
251*9507f98cSAndroid Build Coastguard Worker
252*9507f98cSAndroid Build Coastguard Worker StringSource* source_;
253*9507f98cSAndroid Build Coastguard Worker Table* table_;
254*9507f98cSAndroid Build Coastguard Worker
255*9507f98cSAndroid Build Coastguard Worker TableConstructor();
256*9507f98cSAndroid Build Coastguard Worker };
257*9507f98cSAndroid Build Coastguard Worker
258*9507f98cSAndroid Build Coastguard Worker // A helper class that converts internal format keys into user keys
259*9507f98cSAndroid Build Coastguard Worker class KeyConvertingIterator : public Iterator {
260*9507f98cSAndroid Build Coastguard Worker public:
KeyConvertingIterator(Iterator * iter)261*9507f98cSAndroid Build Coastguard Worker explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) {}
262*9507f98cSAndroid Build Coastguard Worker
263*9507f98cSAndroid Build Coastguard Worker KeyConvertingIterator(const KeyConvertingIterator&) = delete;
264*9507f98cSAndroid Build Coastguard Worker KeyConvertingIterator& operator=(const KeyConvertingIterator&) = delete;
265*9507f98cSAndroid Build Coastguard Worker
~KeyConvertingIterator()266*9507f98cSAndroid Build Coastguard Worker ~KeyConvertingIterator() override { delete iter_; }
267*9507f98cSAndroid Build Coastguard Worker
Valid() const268*9507f98cSAndroid Build Coastguard Worker bool Valid() const override { return iter_->Valid(); }
Seek(const Slice & target)269*9507f98cSAndroid Build Coastguard Worker void Seek(const Slice& target) override {
270*9507f98cSAndroid Build Coastguard Worker ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);
271*9507f98cSAndroid Build Coastguard Worker std::string encoded;
272*9507f98cSAndroid Build Coastguard Worker AppendInternalKey(&encoded, ikey);
273*9507f98cSAndroid Build Coastguard Worker iter_->Seek(encoded);
274*9507f98cSAndroid Build Coastguard Worker }
SeekToFirst()275*9507f98cSAndroid Build Coastguard Worker void SeekToFirst() override { iter_->SeekToFirst(); }
SeekToLast()276*9507f98cSAndroid Build Coastguard Worker void SeekToLast() override { iter_->SeekToLast(); }
Next()277*9507f98cSAndroid Build Coastguard Worker void Next() override { iter_->Next(); }
Prev()278*9507f98cSAndroid Build Coastguard Worker void Prev() override { iter_->Prev(); }
279*9507f98cSAndroid Build Coastguard Worker
key() const280*9507f98cSAndroid Build Coastguard Worker Slice key() const override {
281*9507f98cSAndroid Build Coastguard Worker assert(Valid());
282*9507f98cSAndroid Build Coastguard Worker ParsedInternalKey key;
283*9507f98cSAndroid Build Coastguard Worker if (!ParseInternalKey(iter_->key(), &key)) {
284*9507f98cSAndroid Build Coastguard Worker status_ = Status::Corruption("malformed internal key");
285*9507f98cSAndroid Build Coastguard Worker return Slice("corrupted key");
286*9507f98cSAndroid Build Coastguard Worker }
287*9507f98cSAndroid Build Coastguard Worker return key.user_key;
288*9507f98cSAndroid Build Coastguard Worker }
289*9507f98cSAndroid Build Coastguard Worker
value() const290*9507f98cSAndroid Build Coastguard Worker Slice value() const override { return iter_->value(); }
status() const291*9507f98cSAndroid Build Coastguard Worker Status status() const override {
292*9507f98cSAndroid Build Coastguard Worker return status_.ok() ? iter_->status() : status_;
293*9507f98cSAndroid Build Coastguard Worker }
294*9507f98cSAndroid Build Coastguard Worker
295*9507f98cSAndroid Build Coastguard Worker private:
296*9507f98cSAndroid Build Coastguard Worker mutable Status status_;
297*9507f98cSAndroid Build Coastguard Worker Iterator* iter_;
298*9507f98cSAndroid Build Coastguard Worker };
299*9507f98cSAndroid Build Coastguard Worker
300*9507f98cSAndroid Build Coastguard Worker class MemTableConstructor : public Constructor {
301*9507f98cSAndroid Build Coastguard Worker public:
MemTableConstructor(const Comparator * cmp)302*9507f98cSAndroid Build Coastguard Worker explicit MemTableConstructor(const Comparator* cmp)
303*9507f98cSAndroid Build Coastguard Worker : Constructor(cmp), internal_comparator_(cmp) {
304*9507f98cSAndroid Build Coastguard Worker memtable_ = new MemTable(internal_comparator_);
305*9507f98cSAndroid Build Coastguard Worker memtable_->Ref();
306*9507f98cSAndroid Build Coastguard Worker }
~MemTableConstructor()307*9507f98cSAndroid Build Coastguard Worker ~MemTableConstructor() override { memtable_->Unref(); }
FinishImpl(const Options & options,const KVMap & data)308*9507f98cSAndroid Build Coastguard Worker Status FinishImpl(const Options& options, const KVMap& data) override {
309*9507f98cSAndroid Build Coastguard Worker memtable_->Unref();
310*9507f98cSAndroid Build Coastguard Worker memtable_ = new MemTable(internal_comparator_);
311*9507f98cSAndroid Build Coastguard Worker memtable_->Ref();
312*9507f98cSAndroid Build Coastguard Worker int seq = 1;
313*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : data) {
314*9507f98cSAndroid Build Coastguard Worker memtable_->Add(seq, kTypeValue, kvp.first, kvp.second);
315*9507f98cSAndroid Build Coastguard Worker seq++;
316*9507f98cSAndroid Build Coastguard Worker }
317*9507f98cSAndroid Build Coastguard Worker return Status::OK();
318*9507f98cSAndroid Build Coastguard Worker }
NewIterator() const319*9507f98cSAndroid Build Coastguard Worker Iterator* NewIterator() const override {
320*9507f98cSAndroid Build Coastguard Worker return new KeyConvertingIterator(memtable_->NewIterator());
321*9507f98cSAndroid Build Coastguard Worker }
322*9507f98cSAndroid Build Coastguard Worker
323*9507f98cSAndroid Build Coastguard Worker private:
324*9507f98cSAndroid Build Coastguard Worker const InternalKeyComparator internal_comparator_;
325*9507f98cSAndroid Build Coastguard Worker MemTable* memtable_;
326*9507f98cSAndroid Build Coastguard Worker };
327*9507f98cSAndroid Build Coastguard Worker
328*9507f98cSAndroid Build Coastguard Worker class DBConstructor : public Constructor {
329*9507f98cSAndroid Build Coastguard Worker public:
DBConstructor(const Comparator * cmp)330*9507f98cSAndroid Build Coastguard Worker explicit DBConstructor(const Comparator* cmp)
331*9507f98cSAndroid Build Coastguard Worker : Constructor(cmp), comparator_(cmp) {
332*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
333*9507f98cSAndroid Build Coastguard Worker NewDB();
334*9507f98cSAndroid Build Coastguard Worker }
~DBConstructor()335*9507f98cSAndroid Build Coastguard Worker ~DBConstructor() override { delete db_; }
FinishImpl(const Options & options,const KVMap & data)336*9507f98cSAndroid Build Coastguard Worker Status FinishImpl(const Options& options, const KVMap& data) override {
337*9507f98cSAndroid Build Coastguard Worker delete db_;
338*9507f98cSAndroid Build Coastguard Worker db_ = nullptr;
339*9507f98cSAndroid Build Coastguard Worker NewDB();
340*9507f98cSAndroid Build Coastguard Worker for (const auto& kvp : data) {
341*9507f98cSAndroid Build Coastguard Worker WriteBatch batch;
342*9507f98cSAndroid Build Coastguard Worker batch.Put(kvp.first, kvp.second);
343*9507f98cSAndroid Build Coastguard Worker EXPECT_TRUE(db_->Write(WriteOptions(), &batch).ok());
344*9507f98cSAndroid Build Coastguard Worker }
345*9507f98cSAndroid Build Coastguard Worker return Status::OK();
346*9507f98cSAndroid Build Coastguard Worker }
NewIterator() const347*9507f98cSAndroid Build Coastguard Worker Iterator* NewIterator() const override {
348*9507f98cSAndroid Build Coastguard Worker return db_->NewIterator(ReadOptions());
349*9507f98cSAndroid Build Coastguard Worker }
350*9507f98cSAndroid Build Coastguard Worker
db() const351*9507f98cSAndroid Build Coastguard Worker DB* db() const override { return db_; }
352*9507f98cSAndroid Build Coastguard Worker
353*9507f98cSAndroid Build Coastguard Worker private:
NewDB()354*9507f98cSAndroid Build Coastguard Worker void NewDB() {
355*9507f98cSAndroid Build Coastguard Worker std::string name = testing::TempDir() + "table_testdb";
356*9507f98cSAndroid Build Coastguard Worker
357*9507f98cSAndroid Build Coastguard Worker Options options;
358*9507f98cSAndroid Build Coastguard Worker options.comparator = comparator_;
359*9507f98cSAndroid Build Coastguard Worker Status status = DestroyDB(name, options);
360*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(status.ok()) << status.ToString();
361*9507f98cSAndroid Build Coastguard Worker
362*9507f98cSAndroid Build Coastguard Worker options.create_if_missing = true;
363*9507f98cSAndroid Build Coastguard Worker options.error_if_exists = true;
364*9507f98cSAndroid Build Coastguard Worker options.write_buffer_size = 10000; // Something small to force merging
365*9507f98cSAndroid Build Coastguard Worker status = DB::Open(options, name, &db_);
366*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(status.ok()) << status.ToString();
367*9507f98cSAndroid Build Coastguard Worker }
368*9507f98cSAndroid Build Coastguard Worker
369*9507f98cSAndroid Build Coastguard Worker const Comparator* const comparator_;
370*9507f98cSAndroid Build Coastguard Worker DB* db_;
371*9507f98cSAndroid Build Coastguard Worker };
372*9507f98cSAndroid Build Coastguard Worker
373*9507f98cSAndroid Build Coastguard Worker enum TestType { TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST };
374*9507f98cSAndroid Build Coastguard Worker
375*9507f98cSAndroid Build Coastguard Worker struct TestArgs {
376*9507f98cSAndroid Build Coastguard Worker TestType type;
377*9507f98cSAndroid Build Coastguard Worker bool reverse_compare;
378*9507f98cSAndroid Build Coastguard Worker int restart_interval;
379*9507f98cSAndroid Build Coastguard Worker };
380*9507f98cSAndroid Build Coastguard Worker
381*9507f98cSAndroid Build Coastguard Worker static const TestArgs kTestArgList[] = {
382*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, false, 16},
383*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, false, 1},
384*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, false, 1024},
385*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, true, 16},
386*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, true, 1},
387*9507f98cSAndroid Build Coastguard Worker {TABLE_TEST, true, 1024},
388*9507f98cSAndroid Build Coastguard Worker
389*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, false, 16},
390*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, false, 1},
391*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, false, 1024},
392*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, true, 16},
393*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, true, 1},
394*9507f98cSAndroid Build Coastguard Worker {BLOCK_TEST, true, 1024},
395*9507f98cSAndroid Build Coastguard Worker
396*9507f98cSAndroid Build Coastguard Worker // Restart interval does not matter for memtables
397*9507f98cSAndroid Build Coastguard Worker {MEMTABLE_TEST, false, 16},
398*9507f98cSAndroid Build Coastguard Worker {MEMTABLE_TEST, true, 16},
399*9507f98cSAndroid Build Coastguard Worker
400*9507f98cSAndroid Build Coastguard Worker // Do not bother with restart interval variations for DB
401*9507f98cSAndroid Build Coastguard Worker {DB_TEST, false, 16},
402*9507f98cSAndroid Build Coastguard Worker {DB_TEST, true, 16},
403*9507f98cSAndroid Build Coastguard Worker };
404*9507f98cSAndroid Build Coastguard Worker static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]);
405*9507f98cSAndroid Build Coastguard Worker
406*9507f98cSAndroid Build Coastguard Worker class Harness : public testing::Test {
407*9507f98cSAndroid Build Coastguard Worker public:
Harness()408*9507f98cSAndroid Build Coastguard Worker Harness() : constructor_(nullptr) {}
409*9507f98cSAndroid Build Coastguard Worker
Init(const TestArgs & args)410*9507f98cSAndroid Build Coastguard Worker void Init(const TestArgs& args) {
411*9507f98cSAndroid Build Coastguard Worker delete constructor_;
412*9507f98cSAndroid Build Coastguard Worker constructor_ = nullptr;
413*9507f98cSAndroid Build Coastguard Worker options_ = Options();
414*9507f98cSAndroid Build Coastguard Worker
415*9507f98cSAndroid Build Coastguard Worker options_.block_restart_interval = args.restart_interval;
416*9507f98cSAndroid Build Coastguard Worker // Use shorter block size for tests to exercise block boundary
417*9507f98cSAndroid Build Coastguard Worker // conditions more.
418*9507f98cSAndroid Build Coastguard Worker options_.block_size = 256;
419*9507f98cSAndroid Build Coastguard Worker if (args.reverse_compare) {
420*9507f98cSAndroid Build Coastguard Worker options_.comparator = &reverse_key_comparator;
421*9507f98cSAndroid Build Coastguard Worker }
422*9507f98cSAndroid Build Coastguard Worker switch (args.type) {
423*9507f98cSAndroid Build Coastguard Worker case TABLE_TEST:
424*9507f98cSAndroid Build Coastguard Worker constructor_ = new TableConstructor(options_.comparator);
425*9507f98cSAndroid Build Coastguard Worker break;
426*9507f98cSAndroid Build Coastguard Worker case BLOCK_TEST:
427*9507f98cSAndroid Build Coastguard Worker constructor_ = new BlockConstructor(options_.comparator);
428*9507f98cSAndroid Build Coastguard Worker break;
429*9507f98cSAndroid Build Coastguard Worker case MEMTABLE_TEST:
430*9507f98cSAndroid Build Coastguard Worker constructor_ = new MemTableConstructor(options_.comparator);
431*9507f98cSAndroid Build Coastguard Worker break;
432*9507f98cSAndroid Build Coastguard Worker case DB_TEST:
433*9507f98cSAndroid Build Coastguard Worker constructor_ = new DBConstructor(options_.comparator);
434*9507f98cSAndroid Build Coastguard Worker break;
435*9507f98cSAndroid Build Coastguard Worker }
436*9507f98cSAndroid Build Coastguard Worker }
437*9507f98cSAndroid Build Coastguard Worker
~Harness()438*9507f98cSAndroid Build Coastguard Worker ~Harness() { delete constructor_; }
439*9507f98cSAndroid Build Coastguard Worker
Add(const std::string & key,const std::string & value)440*9507f98cSAndroid Build Coastguard Worker void Add(const std::string& key, const std::string& value) {
441*9507f98cSAndroid Build Coastguard Worker constructor_->Add(key, value);
442*9507f98cSAndroid Build Coastguard Worker }
443*9507f98cSAndroid Build Coastguard Worker
Test(Random * rnd)444*9507f98cSAndroid Build Coastguard Worker void Test(Random* rnd) {
445*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> keys;
446*9507f98cSAndroid Build Coastguard Worker KVMap data;
447*9507f98cSAndroid Build Coastguard Worker constructor_->Finish(options_, &keys, &data);
448*9507f98cSAndroid Build Coastguard Worker
449*9507f98cSAndroid Build Coastguard Worker TestForwardScan(keys, data);
450*9507f98cSAndroid Build Coastguard Worker TestBackwardScan(keys, data);
451*9507f98cSAndroid Build Coastguard Worker TestRandomAccess(rnd, keys, data);
452*9507f98cSAndroid Build Coastguard Worker }
453*9507f98cSAndroid Build Coastguard Worker
TestForwardScan(const std::vector<std::string> & keys,const KVMap & data)454*9507f98cSAndroid Build Coastguard Worker void TestForwardScan(const std::vector<std::string>& keys,
455*9507f98cSAndroid Build Coastguard Worker const KVMap& data) {
456*9507f98cSAndroid Build Coastguard Worker Iterator* iter = constructor_->NewIterator();
457*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
458*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
459*9507f98cSAndroid Build Coastguard Worker for (KVMap::const_iterator model_iter = data.begin();
460*9507f98cSAndroid Build Coastguard Worker model_iter != data.end(); ++model_iter) {
461*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
462*9507f98cSAndroid Build Coastguard Worker iter->Next();
463*9507f98cSAndroid Build Coastguard Worker }
464*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
465*9507f98cSAndroid Build Coastguard Worker delete iter;
466*9507f98cSAndroid Build Coastguard Worker }
467*9507f98cSAndroid Build Coastguard Worker
TestBackwardScan(const std::vector<std::string> & keys,const KVMap & data)468*9507f98cSAndroid Build Coastguard Worker void TestBackwardScan(const std::vector<std::string>& keys,
469*9507f98cSAndroid Build Coastguard Worker const KVMap& data) {
470*9507f98cSAndroid Build Coastguard Worker Iterator* iter = constructor_->NewIterator();
471*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
472*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
473*9507f98cSAndroid Build Coastguard Worker for (KVMap::const_reverse_iterator model_iter = data.rbegin();
474*9507f98cSAndroid Build Coastguard Worker model_iter != data.rend(); ++model_iter) {
475*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
476*9507f98cSAndroid Build Coastguard Worker iter->Prev();
477*9507f98cSAndroid Build Coastguard Worker }
478*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
479*9507f98cSAndroid Build Coastguard Worker delete iter;
480*9507f98cSAndroid Build Coastguard Worker }
481*9507f98cSAndroid Build Coastguard Worker
TestRandomAccess(Random * rnd,const std::vector<std::string> & keys,const KVMap & data)482*9507f98cSAndroid Build Coastguard Worker void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,
483*9507f98cSAndroid Build Coastguard Worker const KVMap& data) {
484*9507f98cSAndroid Build Coastguard Worker static const bool kVerbose = false;
485*9507f98cSAndroid Build Coastguard Worker Iterator* iter = constructor_->NewIterator();
486*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
487*9507f98cSAndroid Build Coastguard Worker KVMap::const_iterator model_iter = data.begin();
488*9507f98cSAndroid Build Coastguard Worker if (kVerbose) std::fprintf(stderr, "---\n");
489*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < 200; i++) {
490*9507f98cSAndroid Build Coastguard Worker const int toss = rnd->Uniform(5);
491*9507f98cSAndroid Build Coastguard Worker switch (toss) {
492*9507f98cSAndroid Build Coastguard Worker case 0: {
493*9507f98cSAndroid Build Coastguard Worker if (iter->Valid()) {
494*9507f98cSAndroid Build Coastguard Worker if (kVerbose) std::fprintf(stderr, "Next\n");
495*9507f98cSAndroid Build Coastguard Worker iter->Next();
496*9507f98cSAndroid Build Coastguard Worker ++model_iter;
497*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
498*9507f98cSAndroid Build Coastguard Worker }
499*9507f98cSAndroid Build Coastguard Worker break;
500*9507f98cSAndroid Build Coastguard Worker }
501*9507f98cSAndroid Build Coastguard Worker
502*9507f98cSAndroid Build Coastguard Worker case 1: {
503*9507f98cSAndroid Build Coastguard Worker if (kVerbose) std::fprintf(stderr, "SeekToFirst\n");
504*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
505*9507f98cSAndroid Build Coastguard Worker model_iter = data.begin();
506*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
507*9507f98cSAndroid Build Coastguard Worker break;
508*9507f98cSAndroid Build Coastguard Worker }
509*9507f98cSAndroid Build Coastguard Worker
510*9507f98cSAndroid Build Coastguard Worker case 2: {
511*9507f98cSAndroid Build Coastguard Worker std::string key = PickRandomKey(rnd, keys);
512*9507f98cSAndroid Build Coastguard Worker model_iter = data.lower_bound(key);
513*9507f98cSAndroid Build Coastguard Worker if (kVerbose)
514*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "Seek '%s'\n", EscapeString(key).c_str());
515*9507f98cSAndroid Build Coastguard Worker iter->Seek(Slice(key));
516*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
517*9507f98cSAndroid Build Coastguard Worker break;
518*9507f98cSAndroid Build Coastguard Worker }
519*9507f98cSAndroid Build Coastguard Worker
520*9507f98cSAndroid Build Coastguard Worker case 3: {
521*9507f98cSAndroid Build Coastguard Worker if (iter->Valid()) {
522*9507f98cSAndroid Build Coastguard Worker if (kVerbose) std::fprintf(stderr, "Prev\n");
523*9507f98cSAndroid Build Coastguard Worker iter->Prev();
524*9507f98cSAndroid Build Coastguard Worker if (model_iter == data.begin()) {
525*9507f98cSAndroid Build Coastguard Worker model_iter = data.end(); // Wrap around to invalid value
526*9507f98cSAndroid Build Coastguard Worker } else {
527*9507f98cSAndroid Build Coastguard Worker --model_iter;
528*9507f98cSAndroid Build Coastguard Worker }
529*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
530*9507f98cSAndroid Build Coastguard Worker }
531*9507f98cSAndroid Build Coastguard Worker break;
532*9507f98cSAndroid Build Coastguard Worker }
533*9507f98cSAndroid Build Coastguard Worker
534*9507f98cSAndroid Build Coastguard Worker case 4: {
535*9507f98cSAndroid Build Coastguard Worker if (kVerbose) std::fprintf(stderr, "SeekToLast\n");
536*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
537*9507f98cSAndroid Build Coastguard Worker if (keys.empty()) {
538*9507f98cSAndroid Build Coastguard Worker model_iter = data.end();
539*9507f98cSAndroid Build Coastguard Worker } else {
540*9507f98cSAndroid Build Coastguard Worker std::string last = data.rbegin()->first;
541*9507f98cSAndroid Build Coastguard Worker model_iter = data.lower_bound(last);
542*9507f98cSAndroid Build Coastguard Worker }
543*9507f98cSAndroid Build Coastguard Worker ASSERT_EQ(ToString(data, model_iter), ToString(iter));
544*9507f98cSAndroid Build Coastguard Worker break;
545*9507f98cSAndroid Build Coastguard Worker }
546*9507f98cSAndroid Build Coastguard Worker }
547*9507f98cSAndroid Build Coastguard Worker }
548*9507f98cSAndroid Build Coastguard Worker delete iter;
549*9507f98cSAndroid Build Coastguard Worker }
550*9507f98cSAndroid Build Coastguard Worker
ToString(const KVMap & data,const KVMap::const_iterator & it)551*9507f98cSAndroid Build Coastguard Worker std::string ToString(const KVMap& data, const KVMap::const_iterator& it) {
552*9507f98cSAndroid Build Coastguard Worker if (it == data.end()) {
553*9507f98cSAndroid Build Coastguard Worker return "END";
554*9507f98cSAndroid Build Coastguard Worker } else {
555*9507f98cSAndroid Build Coastguard Worker return "'" + it->first + "->" + it->second + "'";
556*9507f98cSAndroid Build Coastguard Worker }
557*9507f98cSAndroid Build Coastguard Worker }
558*9507f98cSAndroid Build Coastguard Worker
ToString(const KVMap & data,const KVMap::const_reverse_iterator & it)559*9507f98cSAndroid Build Coastguard Worker std::string ToString(const KVMap& data,
560*9507f98cSAndroid Build Coastguard Worker const KVMap::const_reverse_iterator& it) {
561*9507f98cSAndroid Build Coastguard Worker if (it == data.rend()) {
562*9507f98cSAndroid Build Coastguard Worker return "END";
563*9507f98cSAndroid Build Coastguard Worker } else {
564*9507f98cSAndroid Build Coastguard Worker return "'" + it->first + "->" + it->second + "'";
565*9507f98cSAndroid Build Coastguard Worker }
566*9507f98cSAndroid Build Coastguard Worker }
567*9507f98cSAndroid Build Coastguard Worker
ToString(const Iterator * it)568*9507f98cSAndroid Build Coastguard Worker std::string ToString(const Iterator* it) {
569*9507f98cSAndroid Build Coastguard Worker if (!it->Valid()) {
570*9507f98cSAndroid Build Coastguard Worker return "END";
571*9507f98cSAndroid Build Coastguard Worker } else {
572*9507f98cSAndroid Build Coastguard Worker return "'" + it->key().ToString() + "->" + it->value().ToString() + "'";
573*9507f98cSAndroid Build Coastguard Worker }
574*9507f98cSAndroid Build Coastguard Worker }
575*9507f98cSAndroid Build Coastguard Worker
PickRandomKey(Random * rnd,const std::vector<std::string> & keys)576*9507f98cSAndroid Build Coastguard Worker std::string PickRandomKey(Random* rnd, const std::vector<std::string>& keys) {
577*9507f98cSAndroid Build Coastguard Worker if (keys.empty()) {
578*9507f98cSAndroid Build Coastguard Worker return "foo";
579*9507f98cSAndroid Build Coastguard Worker } else {
580*9507f98cSAndroid Build Coastguard Worker const int index = rnd->Uniform(keys.size());
581*9507f98cSAndroid Build Coastguard Worker std::string result = keys[index];
582*9507f98cSAndroid Build Coastguard Worker switch (rnd->Uniform(3)) {
583*9507f98cSAndroid Build Coastguard Worker case 0:
584*9507f98cSAndroid Build Coastguard Worker // Return an existing key
585*9507f98cSAndroid Build Coastguard Worker break;
586*9507f98cSAndroid Build Coastguard Worker case 1: {
587*9507f98cSAndroid Build Coastguard Worker // Attempt to return something smaller than an existing key
588*9507f98cSAndroid Build Coastguard Worker if (!result.empty() && result[result.size() - 1] > '\0') {
589*9507f98cSAndroid Build Coastguard Worker result[result.size() - 1]--;
590*9507f98cSAndroid Build Coastguard Worker }
591*9507f98cSAndroid Build Coastguard Worker break;
592*9507f98cSAndroid Build Coastguard Worker }
593*9507f98cSAndroid Build Coastguard Worker case 2: {
594*9507f98cSAndroid Build Coastguard Worker // Return something larger than an existing key
595*9507f98cSAndroid Build Coastguard Worker Increment(options_.comparator, &result);
596*9507f98cSAndroid Build Coastguard Worker break;
597*9507f98cSAndroid Build Coastguard Worker }
598*9507f98cSAndroid Build Coastguard Worker }
599*9507f98cSAndroid Build Coastguard Worker return result;
600*9507f98cSAndroid Build Coastguard Worker }
601*9507f98cSAndroid Build Coastguard Worker }
602*9507f98cSAndroid Build Coastguard Worker
603*9507f98cSAndroid Build Coastguard Worker // Returns nullptr if not running against a DB
db() const604*9507f98cSAndroid Build Coastguard Worker DB* db() const { return constructor_->db(); }
605*9507f98cSAndroid Build Coastguard Worker
606*9507f98cSAndroid Build Coastguard Worker private:
607*9507f98cSAndroid Build Coastguard Worker Options options_;
608*9507f98cSAndroid Build Coastguard Worker Constructor* constructor_;
609*9507f98cSAndroid Build Coastguard Worker };
610*9507f98cSAndroid Build Coastguard Worker
611*9507f98cSAndroid Build Coastguard Worker // Test empty table/block.
TEST_F(Harness,Empty)612*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, Empty) {
613*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
614*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
615*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 1);
616*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
617*9507f98cSAndroid Build Coastguard Worker }
618*9507f98cSAndroid Build Coastguard Worker }
619*9507f98cSAndroid Build Coastguard Worker
620*9507f98cSAndroid Build Coastguard Worker // Special test for a block with no restart entries. The C++ leveldb
621*9507f98cSAndroid Build Coastguard Worker // code never generates such blocks, but the Java version of leveldb
622*9507f98cSAndroid Build Coastguard Worker // seems to.
TEST_F(Harness,ZeroRestartPointsInBlock)623*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, ZeroRestartPointsInBlock) {
624*9507f98cSAndroid Build Coastguard Worker char data[sizeof(uint32_t)];
625*9507f98cSAndroid Build Coastguard Worker memset(data, 0, sizeof(data));
626*9507f98cSAndroid Build Coastguard Worker BlockContents contents;
627*9507f98cSAndroid Build Coastguard Worker contents.data = Slice(data, sizeof(data));
628*9507f98cSAndroid Build Coastguard Worker contents.cachable = false;
629*9507f98cSAndroid Build Coastguard Worker contents.heap_allocated = false;
630*9507f98cSAndroid Build Coastguard Worker Block block(contents);
631*9507f98cSAndroid Build Coastguard Worker Iterator* iter = block.NewIterator(BytewiseComparator());
632*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
633*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
634*9507f98cSAndroid Build Coastguard Worker iter->SeekToLast();
635*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
636*9507f98cSAndroid Build Coastguard Worker iter->Seek("foo");
637*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(!iter->Valid());
638*9507f98cSAndroid Build Coastguard Worker delete iter;
639*9507f98cSAndroid Build Coastguard Worker }
640*9507f98cSAndroid Build Coastguard Worker
641*9507f98cSAndroid Build Coastguard Worker // Test the empty key
TEST_F(Harness,SimpleEmptyKey)642*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleEmptyKey) {
643*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
644*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
645*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 1);
646*9507f98cSAndroid Build Coastguard Worker Add("", "v");
647*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
648*9507f98cSAndroid Build Coastguard Worker }
649*9507f98cSAndroid Build Coastguard Worker }
650*9507f98cSAndroid Build Coastguard Worker
TEST_F(Harness,SimpleSingle)651*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleSingle) {
652*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
653*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
654*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 2);
655*9507f98cSAndroid Build Coastguard Worker Add("abc", "v");
656*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
657*9507f98cSAndroid Build Coastguard Worker }
658*9507f98cSAndroid Build Coastguard Worker }
659*9507f98cSAndroid Build Coastguard Worker
TEST_F(Harness,SimpleMulti)660*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleMulti) {
661*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
662*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
663*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 3);
664*9507f98cSAndroid Build Coastguard Worker Add("abc", "v");
665*9507f98cSAndroid Build Coastguard Worker Add("abcd", "v");
666*9507f98cSAndroid Build Coastguard Worker Add("ac", "v2");
667*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
668*9507f98cSAndroid Build Coastguard Worker }
669*9507f98cSAndroid Build Coastguard Worker }
670*9507f98cSAndroid Build Coastguard Worker
TEST_F(Harness,SimpleSpecialKey)671*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleSpecialKey) {
672*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
673*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
674*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 4);
675*9507f98cSAndroid Build Coastguard Worker Add("\xff\xff", "v3");
676*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
677*9507f98cSAndroid Build Coastguard Worker }
678*9507f98cSAndroid Build Coastguard Worker }
679*9507f98cSAndroid Build Coastguard Worker
TEST_F(Harness,Randomized)680*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, Randomized) {
681*9507f98cSAndroid Build Coastguard Worker for (int i = 0; i < kNumTestArgs; i++) {
682*9507f98cSAndroid Build Coastguard Worker Init(kTestArgList[i]);
683*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed() + 5);
684*9507f98cSAndroid Build Coastguard Worker for (int num_entries = 0; num_entries < 2000;
685*9507f98cSAndroid Build Coastguard Worker num_entries += (num_entries < 50 ? 1 : 200)) {
686*9507f98cSAndroid Build Coastguard Worker if ((num_entries % 10) == 0) {
687*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "case %d of %d: num_entries = %d\n", (i + 1),
688*9507f98cSAndroid Build Coastguard Worker int(kNumTestArgs), num_entries);
689*9507f98cSAndroid Build Coastguard Worker }
690*9507f98cSAndroid Build Coastguard Worker for (int e = 0; e < num_entries; e++) {
691*9507f98cSAndroid Build Coastguard Worker std::string v;
692*9507f98cSAndroid Build Coastguard Worker Add(test::RandomKey(&rnd, rnd.Skewed(4)),
693*9507f98cSAndroid Build Coastguard Worker test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());
694*9507f98cSAndroid Build Coastguard Worker }
695*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
696*9507f98cSAndroid Build Coastguard Worker }
697*9507f98cSAndroid Build Coastguard Worker }
698*9507f98cSAndroid Build Coastguard Worker }
699*9507f98cSAndroid Build Coastguard Worker
TEST_F(Harness,RandomizedLongDB)700*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, RandomizedLongDB) {
701*9507f98cSAndroid Build Coastguard Worker Random rnd(test::RandomSeed());
702*9507f98cSAndroid Build Coastguard Worker TestArgs args = {DB_TEST, false, 16};
703*9507f98cSAndroid Build Coastguard Worker Init(args);
704*9507f98cSAndroid Build Coastguard Worker int num_entries = 100000;
705*9507f98cSAndroid Build Coastguard Worker for (int e = 0; e < num_entries; e++) {
706*9507f98cSAndroid Build Coastguard Worker std::string v;
707*9507f98cSAndroid Build Coastguard Worker Add(test::RandomKey(&rnd, rnd.Skewed(4)),
708*9507f98cSAndroid Build Coastguard Worker test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());
709*9507f98cSAndroid Build Coastguard Worker }
710*9507f98cSAndroid Build Coastguard Worker Test(&rnd);
711*9507f98cSAndroid Build Coastguard Worker
712*9507f98cSAndroid Build Coastguard Worker // We must have created enough data to force merging
713*9507f98cSAndroid Build Coastguard Worker int files = 0;
714*9507f98cSAndroid Build Coastguard Worker for (int level = 0; level < config::kNumLevels; level++) {
715*9507f98cSAndroid Build Coastguard Worker std::string value;
716*9507f98cSAndroid Build Coastguard Worker char name[100];
717*9507f98cSAndroid Build Coastguard Worker std::snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level);
718*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(db()->GetProperty(name, &value));
719*9507f98cSAndroid Build Coastguard Worker files += atoi(value.c_str());
720*9507f98cSAndroid Build Coastguard Worker }
721*9507f98cSAndroid Build Coastguard Worker ASSERT_GT(files, 0);
722*9507f98cSAndroid Build Coastguard Worker }
723*9507f98cSAndroid Build Coastguard Worker
TEST(MemTableTest,Simple)724*9507f98cSAndroid Build Coastguard Worker TEST(MemTableTest, Simple) {
725*9507f98cSAndroid Build Coastguard Worker InternalKeyComparator cmp(BytewiseComparator());
726*9507f98cSAndroid Build Coastguard Worker MemTable* memtable = new MemTable(cmp);
727*9507f98cSAndroid Build Coastguard Worker memtable->Ref();
728*9507f98cSAndroid Build Coastguard Worker WriteBatch batch;
729*9507f98cSAndroid Build Coastguard Worker WriteBatchInternal::SetSequence(&batch, 100);
730*9507f98cSAndroid Build Coastguard Worker batch.Put(std::string("k1"), std::string("v1"));
731*9507f98cSAndroid Build Coastguard Worker batch.Put(std::string("k2"), std::string("v2"));
732*9507f98cSAndroid Build Coastguard Worker batch.Put(std::string("k3"), std::string("v3"));
733*9507f98cSAndroid Build Coastguard Worker batch.Put(std::string("largekey"), std::string("vlarge"));
734*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok());
735*9507f98cSAndroid Build Coastguard Worker
736*9507f98cSAndroid Build Coastguard Worker Iterator* iter = memtable->NewIterator();
737*9507f98cSAndroid Build Coastguard Worker iter->SeekToFirst();
738*9507f98cSAndroid Build Coastguard Worker while (iter->Valid()) {
739*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),
740*9507f98cSAndroid Build Coastguard Worker iter->value().ToString().c_str());
741*9507f98cSAndroid Build Coastguard Worker iter->Next();
742*9507f98cSAndroid Build Coastguard Worker }
743*9507f98cSAndroid Build Coastguard Worker
744*9507f98cSAndroid Build Coastguard Worker delete iter;
745*9507f98cSAndroid Build Coastguard Worker memtable->Unref();
746*9507f98cSAndroid Build Coastguard Worker }
747*9507f98cSAndroid Build Coastguard Worker
Between(uint64_t val,uint64_t low,uint64_t high)748*9507f98cSAndroid Build Coastguard Worker static bool Between(uint64_t val, uint64_t low, uint64_t high) {
749*9507f98cSAndroid Build Coastguard Worker bool result = (val >= low) && (val <= high);
750*9507f98cSAndroid Build Coastguard Worker if (!result) {
751*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
752*9507f98cSAndroid Build Coastguard Worker (unsigned long long)(val), (unsigned long long)(low),
753*9507f98cSAndroid Build Coastguard Worker (unsigned long long)(high));
754*9507f98cSAndroid Build Coastguard Worker }
755*9507f98cSAndroid Build Coastguard Worker return result;
756*9507f98cSAndroid Build Coastguard Worker }
757*9507f98cSAndroid Build Coastguard Worker
TEST(TableTest,ApproximateOffsetOfPlain)758*9507f98cSAndroid Build Coastguard Worker TEST(TableTest, ApproximateOffsetOfPlain) {
759*9507f98cSAndroid Build Coastguard Worker TableConstructor c(BytewiseComparator());
760*9507f98cSAndroid Build Coastguard Worker c.Add("k01", "hello");
761*9507f98cSAndroid Build Coastguard Worker c.Add("k02", "hello2");
762*9507f98cSAndroid Build Coastguard Worker c.Add("k03", std::string(10000, 'x'));
763*9507f98cSAndroid Build Coastguard Worker c.Add("k04", std::string(200000, 'x'));
764*9507f98cSAndroid Build Coastguard Worker c.Add("k05", std::string(300000, 'x'));
765*9507f98cSAndroid Build Coastguard Worker c.Add("k06", "hello3");
766*9507f98cSAndroid Build Coastguard Worker c.Add("k07", std::string(100000, 'x'));
767*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> keys;
768*9507f98cSAndroid Build Coastguard Worker KVMap kvmap;
769*9507f98cSAndroid Build Coastguard Worker Options options;
770*9507f98cSAndroid Build Coastguard Worker options.block_size = 1024;
771*9507f98cSAndroid Build Coastguard Worker options.compression = kNoCompression;
772*9507f98cSAndroid Build Coastguard Worker c.Finish(options, &keys, &kvmap);
773*9507f98cSAndroid Build Coastguard Worker
774*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
775*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
776*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0));
777*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
778*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0));
779*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000));
780*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000));
781*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000));
782*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
783*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
784*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
785*9507f98cSAndroid Build Coastguard Worker }
786*9507f98cSAndroid Build Coastguard Worker
SnappyCompressionSupported()787*9507f98cSAndroid Build Coastguard Worker static bool SnappyCompressionSupported() {
788*9507f98cSAndroid Build Coastguard Worker std::string out;
789*9507f98cSAndroid Build Coastguard Worker Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
790*9507f98cSAndroid Build Coastguard Worker return port::Snappy_Compress(in.data(), in.size(), &out);
791*9507f98cSAndroid Build Coastguard Worker }
792*9507f98cSAndroid Build Coastguard Worker
TEST(TableTest,ApproximateOffsetOfCompressed)793*9507f98cSAndroid Build Coastguard Worker TEST(TableTest, ApproximateOffsetOfCompressed) {
794*9507f98cSAndroid Build Coastguard Worker if (!SnappyCompressionSupported()) {
795*9507f98cSAndroid Build Coastguard Worker std::fprintf(stderr, "skipping compression tests\n");
796*9507f98cSAndroid Build Coastguard Worker return;
797*9507f98cSAndroid Build Coastguard Worker }
798*9507f98cSAndroid Build Coastguard Worker
799*9507f98cSAndroid Build Coastguard Worker Random rnd(301);
800*9507f98cSAndroid Build Coastguard Worker TableConstructor c(BytewiseComparator());
801*9507f98cSAndroid Build Coastguard Worker std::string tmp;
802*9507f98cSAndroid Build Coastguard Worker c.Add("k01", "hello");
803*9507f98cSAndroid Build Coastguard Worker c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
804*9507f98cSAndroid Build Coastguard Worker c.Add("k03", "hello3");
805*9507f98cSAndroid Build Coastguard Worker c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
806*9507f98cSAndroid Build Coastguard Worker std::vector<std::string> keys;
807*9507f98cSAndroid Build Coastguard Worker KVMap kvmap;
808*9507f98cSAndroid Build Coastguard Worker Options options;
809*9507f98cSAndroid Build Coastguard Worker options.block_size = 1024;
810*9507f98cSAndroid Build Coastguard Worker options.compression = kSnappyCompression;
811*9507f98cSAndroid Build Coastguard Worker c.Finish(options, &keys, &kvmap);
812*9507f98cSAndroid Build Coastguard Worker
813*9507f98cSAndroid Build Coastguard Worker // Expected upper and lower bounds of space used by compressible strings.
814*9507f98cSAndroid Build Coastguard Worker static const int kSlop = 1000; // Compressor effectiveness varies.
815*9507f98cSAndroid Build Coastguard Worker const int expected = 2500; // 10000 * compression ratio (0.25)
816*9507f98cSAndroid Build Coastguard Worker const int min_z = expected - kSlop;
817*9507f98cSAndroid Build Coastguard Worker const int max_z = expected + kSlop;
818*9507f98cSAndroid Build Coastguard Worker
819*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, kSlop));
820*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, kSlop));
821*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, kSlop));
822*9507f98cSAndroid Build Coastguard Worker // Have now emitted a large compressible string, so adjust expected offset.
823*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), min_z, max_z));
824*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), min_z, max_z));
825*9507f98cSAndroid Build Coastguard Worker // Have now emitted two large compressible strings, so adjust expected offset.
826*9507f98cSAndroid Build Coastguard Worker ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 2 * min_z, 2 * max_z));
827*9507f98cSAndroid Build Coastguard Worker }
828*9507f98cSAndroid Build Coastguard Worker
829*9507f98cSAndroid Build Coastguard Worker } // namespace leveldb
830*9507f98cSAndroid Build Coastguard Worker
831