mock_table.h 5.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
#pragma once
#include <algorithm>
#include <set>
#include <memory>
I
Igor Canadi 已提交
11
#include <atomic>
12 13 14
#include <map>
#include <string>

A
Andres Notzli 已提交
15
#include "rocksdb/comparator.h"
16 17 18 19 20 21 22 23 24
#include "rocksdb/table.h"
#include "table/table_reader.h"
#include "table/table_builder.h"
#include "port/port.h"
#include "util/mutexlock.h"
#include "util/testharness.h"
#include "util/testutil.h"

namespace rocksdb {
I
Igor Canadi 已提交
25
namespace mock {
26

A
Andres Notzli 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
struct MockFileContentsCmp {
  MockFileContentsCmp() : icmp_(BytewiseComparator()) {}

  bool operator() (const std::string& x, const std::string& y) const {
    InternalKey ikey_x;
    InternalKey ikey_y;
    ikey_x.DecodeFrom(x);
    ikey_y.DecodeFrom(y);
    return icmp_.Compare(ikey_x, ikey_y) < 0;
  }

  InternalKeyComparator icmp_;
};

// NOTE: this currently only supports the bytewise comparator
typedef std::map<std::string, std::string, MockFileContentsCmp>
    MockFileContents;
44 45 46

struct MockTableFileSystem {
  port::Mutex mutex;
I
Igor Canadi 已提交
47
  std::map<uint32_t, MockFileContents> files;
48 49 50 51
};

class MockTableReader : public TableReader {
 public:
I
Igor Canadi 已提交
52
  explicit MockTableReader(const MockFileContents& table) : table_(table) {}
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

  Iterator* NewIterator(const ReadOptions&, Arena* arena) override;

  Status Get(const ReadOptions&, const Slice& key,
             GetContext* get_context) override;

  uint64_t ApproximateOffsetOf(const Slice& key) override { return 0; }

  virtual size_t ApproximateMemoryUsage() const override { return 0; }

  void SetupForCompaction() override {}

  std::shared_ptr<const TableProperties> GetTableProperties() const override;

  ~MockTableReader() {}

 private:
I
Igor Canadi 已提交
70
  const MockFileContents& table_;
71 72 73 74
};

class MockTableIterator : public Iterator {
 public:
I
Igor Canadi 已提交
75
  explicit MockTableIterator(const MockFileContents& table) : table_(table) {
76 77 78
    itr_ = table_.end();
  }

I
Igor Sugak 已提交
79
  bool Valid() const override { return itr_ != table_.end(); }
80

I
Igor Sugak 已提交
81
  void SeekToFirst() override { itr_ = table_.begin(); }
82

I
Igor Sugak 已提交
83
  void SeekToLast() override {
84 85 86 87
    itr_ = table_.end();
    --itr_;
  }

I
Igor Sugak 已提交
88
  void Seek(const Slice& target) override {
89 90 91 92
    std::string str_target(target.data(), target.size());
    itr_ = table_.lower_bound(str_target);
  }

I
Igor Sugak 已提交
93
  void Next() override { ++itr_; }
94

I
Igor Sugak 已提交
95
  void Prev() override {
96 97 98 99 100 101 102
    if (itr_ == table_.begin()) {
      itr_ = table_.end();
    } else {
      --itr_;
    }
  }

I
Igor Sugak 已提交
103
  Slice key() const override { return Slice(itr_->first); }
104

I
Igor Sugak 已提交
105
  Slice value() const override { return Slice(itr_->second); }
106

I
Igor Sugak 已提交
107
  Status status() const override { return Status::OK(); }
108 109

 private:
I
Igor Canadi 已提交
110 111
  const MockFileContents& table_;
  MockFileContents::const_iterator itr_;
112 113 114 115
};

class MockTableBuilder : public TableBuilder {
 public:
116 117
  MockTableBuilder(uint32_t id, MockTableFileSystem* file_system)
      : id_(id), file_system_(file_system) {}
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

  // REQUIRES: Either Finish() or Abandon() has been called.
  ~MockTableBuilder() {}

  // Add key,value to the table being constructed.
  // REQUIRES: key is after any previously added key according to comparator.
  // REQUIRES: Finish(), Abandon() have not been called
  void Add(const Slice& key, const Slice& value) override {
    table_.insert({key.ToString(), value.ToString()});
  }

  // Return non-ok iff some error has been detected.
  Status status() const override { return Status::OK(); }

  Status Finish() override {
    MutexLock lock_guard(&file_system_->mutex);
    file_system_->files.insert({id_, table_});
    return Status::OK();
  }

  void Abandon() override {}

  uint64_t NumEntries() const override { return table_.size(); }

  uint64_t FileSize() const override { return table_.size(); }

144 145 146 147
  TableProperties GetTableProperties() const override {
    return TableProperties();
  }

148 149 150
 private:
  uint32_t id_;
  MockTableFileSystem* file_system_;
I
Igor Canadi 已提交
151
  MockFileContents table_;
152 153 154 155 156 157 158
};

class MockTableFactory : public TableFactory {
 public:
  MockTableFactory();
  const char* Name() const override { return "MockTable"; }
  Status NewTableReader(const ImmutableCFOptions& ioptions,
159 160 161 162 163
                        const EnvOptions& env_options,
                        const InternalKeyComparator& internal_key,
                        unique_ptr<RandomAccessFileReader>&& file,
                        uint64_t file_size,
                        unique_ptr<TableReader>* table_reader) const override;
164 165
  TableBuilder* NewTableBuilder(
      const TableBuilderOptions& table_builder_options,
166
      WritableFileWriter* file) const override;
167

I
Igor Canadi 已提交
168 169 170 171 172 173
  // This function will directly create mock table instead of going through
  // MockTableBuilder. MockFileContents has to have a format of <internal_key,
  // value>. Those key-value pairs will then be inserted into the mock table
  Status CreateMockTable(Env* env, const std::string& fname,
                         MockFileContents file_contents);

I
Igor Sugak 已提交
174 175 176
  virtual Status SanitizeOptions(
      const DBOptions& db_opts,
      const ColumnFamilyOptions& cf_opts) const override {
177 178 179 180 181 182 183 184 185
    return Status::OK();
  }

  virtual std::string GetPrintableTableOptions() const override {
    return std::string();
  }

  // This function will assert that only a single file exists and that the
  // contents are equal to file_contents
I
Igor Canadi 已提交
186 187
  void AssertSingleFile(const MockFileContents& file_contents);
  void AssertLatestFile(const MockFileContents& file_contents);
188 189 190

 private:
  uint32_t GetAndWriteNextID(WritableFile* file) const;
191
  uint32_t GetIDFromFile(RandomAccessFileReader* file) const;
192 193 194 195 196

  mutable MockTableFileSystem file_system_;
  mutable std::atomic<uint32_t> next_id_;
};

I
Igor Canadi 已提交
197
}  // namespace mock
198
}  // namespace rocksdb