github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/sstable/testdata/make-table.cc (about)

     1  // Copyright 2011 The LevelDB-Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This program adds N lines from infile to a leveldb table at outfile.
     6  // The h.txt infile was generated via:
     7  // cat hamlet-act-1.txt | tr '[:upper:]' '[:lower:]' | grep -o -E '\w+' | sort | uniq -c > infile
     8  //
     9  // To build and run:
    10  // g++ make-table.cc -lleveldb && ./a.out
    11  
    12  #include <fstream>
    13  #include <iostream>
    14  #include <string>
    15  
    16  #include "rocksdb/env.h"
    17  #include "rocksdb/filter_policy.h"
    18  #include "rocksdb/slice_transform.h"
    19  #include "rocksdb/sst_file_writer.h"
    20  #include "rocksdb/table.h"
    21  
    22  const char* infile = "h.txt";
    23  
    24  // A dummy prefix extractor that cuts off the last two bytes for keys of
    25  // length three or over. This is not a valid prefix extractor and barely
    26  // enough to do a little bit of unit testing.
    27  //
    28  // TODO(tbg): write some test infra using CockroachDB MVCC data.
    29  class PrefixExtractor : public rocksdb::SliceTransform {
    30   public:
    31    PrefixExtractor() {}
    32  
    33    virtual const char* Name() const { return "leveldb.BytewiseComparator"; }
    34  
    35    virtual rocksdb::Slice Transform(const rocksdb::Slice& src) const {
    36      auto sl = rocksdb::Slice(src.data(), src.size());
    37      return sl;
    38    }
    39  
    40    virtual bool InDomain(const rocksdb::Slice& src) const { return true; }
    41  };
    42  
    43  class KeyCountPropertyCollector : public rocksdb::TablePropertiesCollector {
    44   public:
    45    KeyCountPropertyCollector()
    46        : count_(0) {
    47    }
    48  
    49    rocksdb::Status AddUserKey(const rocksdb::Slice&, const rocksdb::Slice&,
    50                               rocksdb::EntryType type, rocksdb::SequenceNumber,
    51                               uint64_t) override {
    52      count_++;
    53      return rocksdb::Status::OK();
    54    }
    55  
    56    rocksdb::Status Finish(rocksdb::UserCollectedProperties* properties) override {
    57      char buf[16];
    58      sprintf(buf, "%d", count_);
    59      *properties = rocksdb::UserCollectedProperties{
    60        {"test.key-count", buf},
    61      };
    62      return rocksdb::Status::OK();
    63    }
    64  
    65    const char* Name() const override { return "KeyCountPropertyCollector"; }
    66  
    67    rocksdb::UserCollectedProperties GetReadableProperties() const override {
    68      return rocksdb::UserCollectedProperties{};
    69    }
    70  
    71   private:
    72    int count_;
    73  };
    74  
    75  class KeyCountPropertyCollectorFactory : public rocksdb::TablePropertiesCollectorFactory {
    76    virtual rocksdb::TablePropertiesCollector* CreateTablePropertiesCollector(
    77        rocksdb::TablePropertiesCollectorFactory::Context context) override {
    78      return new KeyCountPropertyCollector();
    79    }
    80    const char* Name() const override { return "KeyCountPropertyCollector"; }
    81  };
    82  
    83  int write() {
    84    for (int i = 0; i < 10; ++i) {
    85      rocksdb::Options options;
    86      rocksdb::BlockBasedTableOptions table_options;
    87      const char* outfile;
    88  
    89      table_options.block_size = 2048;
    90      table_options.index_shortening = rocksdb::BlockBasedTableOptions::IndexShorteningMode::kShortenSeparatorsAndSuccessor;
    91  
    92      switch (i) {
    93        case 0:
    94          outfile = "h.ldb";
    95          table_options.format_version = 0;
    96          table_options.whole_key_filtering = false;
    97          break;
    98  
    99        case 1:
   100          outfile = "h.sst";
   101          options.table_properties_collector_factories.emplace_back(
   102              new KeyCountPropertyCollectorFactory);
   103          table_options.whole_key_filtering = false;
   104          break;
   105  
   106        case 2:
   107          outfile = "h.no-compression.sst";
   108          options.table_properties_collector_factories.emplace_back(
   109              new KeyCountPropertyCollectorFactory);
   110          options.compression = rocksdb::kNoCompression;
   111          table_options.whole_key_filtering = false;
   112          break;
   113  
   114        case 3:
   115          outfile = "h.block-bloom.no-compression.sst";
   116          options.compression = rocksdb::kNoCompression;
   117          table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, true));
   118          table_options.whole_key_filtering = true;
   119          break;
   120  
   121        case 4:
   122          outfile = "h.table-bloom.no-compression.sst";
   123          options.compression = rocksdb::kNoCompression;
   124          table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
   125          table_options.whole_key_filtering = true;
   126          break;
   127  
   128        case 5:
   129          // TODO(peter): unused at this time
   130          //
   131          // outfile = "h.block-bloom.no-compression.prefix_extractor.sst";
   132          // options.compression = rocksdb::kNoCompression;
   133          // options.prefix_extractor.reset(new PrefixExtractor);
   134          // table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, true));
   135          // table_options.whole_key_filtering = true;
   136          // break;
   137          continue;
   138  
   139        case 6:
   140          // TODO(peter): unused at this time
   141          //
   142          // outfile = "h.table-bloom.no-compression.prefix_extractor.sst";
   143          // options.compression = rocksdb::kNoCompression;
   144          // options.prefix_extractor.reset(new PrefixExtractor);
   145          // table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
   146          // table_options.whole_key_filtering = true;
   147          // break;
   148          continue;
   149  
   150        case 7:
   151          // TODO(peter): unused at this time
   152          //
   153          // outfile = "h.block-bloom.no-compression.prefix_extractor.no_whole_key_filter.sst";
   154          // options.compression = rocksdb::kNoCompression;
   155          // options.prefix_extractor.reset(new PrefixExtractor);
   156          // table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, true));
   157          // table_options.whole_key_filtering = false;
   158          // break;
   159          continue;
   160  
   161        case 8:
   162          outfile = "h.table-bloom.no-compression.prefix_extractor.no_whole_key_filter.sst";
   163          options.compression = rocksdb::kNoCompression;
   164          options.prefix_extractor.reset(new PrefixExtractor);
   165          table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
   166          table_options.whole_key_filtering = false;
   167          break;
   168  
   169        case 9:
   170          outfile = "h.no-compression.two_level_index.sst";
   171          options.table_properties_collector_factories.emplace_back(
   172              new KeyCountPropertyCollectorFactory);
   173          options.compression = rocksdb::kNoCompression;
   174          table_options.index_type = rocksdb::BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
   175          // Use small metadata_block_size to stress two_level_index.
   176          table_options.metadata_block_size = 128;
   177          table_options.whole_key_filtering = false;
   178          break;
   179  
   180        default:
   181          continue;
   182      }
   183  
   184      options.table_factory.reset(rocksdb::NewBlockBasedTableFactory(table_options));
   185  
   186      std::unique_ptr<rocksdb::SstFileWriter> tb(new rocksdb::SstFileWriter({}, options));
   187      rocksdb::Status status = tb->Open(outfile);
   188      if (!status.ok()) {
   189        std::cerr << "SstFileWriter::Open: " << status.ToString() << std::endl;
   190        return 1;
   191      }
   192  
   193      int rangeDelLength = 0;
   194      int rangeDelCounter = 0;
   195      std::ifstream in(infile);
   196      std::string s;
   197      std::string rangeDelStart;
   198      for (int i = 0; getline(in, s); i++) {
   199        std::string key(s, 8);
   200        std::string val(s, 0, 7);
   201        val = val.substr(1 + val.rfind(' '));
   202        tb->Put(key.c_str(), val.c_str());
   203        // Add range deletions of increasing length.
   204        if (i % 100 == 0) {
   205          rangeDelStart = key;
   206          rangeDelCounter = 0;
   207          rangeDelLength++;
   208        }
   209        rangeDelCounter++;
   210  
   211        if (rangeDelCounter == rangeDelLength) {
   212          tb->DeleteRange(rangeDelStart, key.c_str());
   213        }
   214      }
   215  
   216      rocksdb::ExternalSstFileInfo info;
   217      status = tb->Finish(&info);
   218      if (!status.ok()) {
   219        std::cerr << "TableBuilder::Finish: " << status.ToString() << std::endl;
   220        return 1;
   221      }
   222  
   223      std::cout << outfile << ": wrote " << info.num_entries << " entries, " << info.file_size << "b" << std::endl;
   224    }
   225    return 0;
   226  }
   227  
   228  int main(int argc, char** argv) {
   229    return write();
   230  }