Add a table factory that can read DB with both of PlainTable and BlockBasedTable in it
Summary: The new table factory is used if users want to convert a DB from one table format to the other. A user can use this table to open a DB written using one table format and write new files to another table format. Test Plan: add a unit test Reviewers: haobo, igor Reviewed By: igor Subscribers: dhruba, ljin, yhchiang, leveldb Differential Revision: https://reviews.facebook.net/D19017
This commit is contained in:
parent
4f18bfe376
commit
200e4b4a72
@ -8,6 +8,7 @@
|
|||||||
### New Features
|
### New Features
|
||||||
* Hash index for block-based table will be materialized and reconstructed more efficiently. Previously hash index is constructed by scanning the whole table during every table open.
|
* Hash index for block-based table will be materialized and reconstructed more efficiently. Previously hash index is constructed by scanning the whole table during every table open.
|
||||||
* FIFO compaction style
|
* FIFO compaction style
|
||||||
|
* Add AdaptiveTableFactory, which is used to convert from a DB of PlainTable to BlockBasedTabe, or vise versa. It can be created using NewAdaptiveTableFactory()
|
||||||
|
|
||||||
## 3.0.0 (05/05/2014)
|
## 3.0.0 (05/05/2014)
|
||||||
|
|
||||||
|
@ -847,6 +847,47 @@ TEST(PlainTableDBTest, CompactionTrigger) {
|
|||||||
ASSERT_EQ(NumTableFilesAtLevel(1), 1);
|
ASSERT_EQ(NumTableFilesAtLevel(1), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PlainTableDBTest, AdaptiveTable) {
|
||||||
|
Options options = CurrentOptions();
|
||||||
|
options.create_if_missing = true;
|
||||||
|
|
||||||
|
options.table_factory.reset(NewPlainTableFactory());
|
||||||
|
DestroyAndReopen(&options);
|
||||||
|
|
||||||
|
ASSERT_OK(Put("1000000000000foo", "v1"));
|
||||||
|
ASSERT_OK(Put("0000000000000bar", "v2"));
|
||||||
|
ASSERT_OK(Put("1000000000000foo", "v3"));
|
||||||
|
dbfull()->TEST_FlushMemTable();
|
||||||
|
|
||||||
|
options.create_if_missing = false;
|
||||||
|
std::shared_ptr<TableFactory> dummy_factory;
|
||||||
|
options.table_factory.reset(
|
||||||
|
NewAdaptiveTableFactory(dummy_factory, dummy_factory, false));
|
||||||
|
Reopen(&options);
|
||||||
|
ASSERT_EQ("v3", Get("1000000000000foo"));
|
||||||
|
ASSERT_EQ("v2", Get("0000000000000bar"));
|
||||||
|
|
||||||
|
ASSERT_OK(Put("2000000000000foo", "v4"));
|
||||||
|
ASSERT_OK(Put("3000000000000bar", "v5"));
|
||||||
|
dbfull()->TEST_FlushMemTable();
|
||||||
|
ASSERT_EQ("v4", Get("2000000000000foo"));
|
||||||
|
ASSERT_EQ("v5", Get("3000000000000bar"));
|
||||||
|
|
||||||
|
Reopen(&options);
|
||||||
|
ASSERT_EQ("v3", Get("1000000000000foo"));
|
||||||
|
ASSERT_EQ("v2", Get("0000000000000bar"));
|
||||||
|
ASSERT_EQ("v4", Get("2000000000000foo"));
|
||||||
|
ASSERT_EQ("v5", Get("3000000000000bar"));
|
||||||
|
|
||||||
|
options.table_factory.reset(NewBlockBasedTableFactory());
|
||||||
|
Reopen(&options);
|
||||||
|
ASSERT_NE("v3", Get("1000000000000foo"));
|
||||||
|
|
||||||
|
options.table_factory.reset(NewPlainTableFactory());
|
||||||
|
Reopen(&options);
|
||||||
|
ASSERT_NE("v5", Get("3000000000000bar"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -203,4 +203,19 @@ class TableFactory {
|
|||||||
WritableFile* file, CompressionType compression_type) const = 0;
|
WritableFile* file, CompressionType compression_type) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef ROCKSDB_LITE
|
||||||
|
// Create a special table factory that can open both of block based table format
|
||||||
|
// and plain table, based on setting inside the SST files. It should be used to
|
||||||
|
// convert a DB from one table format to another.
|
||||||
|
// @block_based_table_factory: block based table factory to use. If NULL, use
|
||||||
|
// a default one.
|
||||||
|
// @plain_table_factory: plain table factory to use. If NULL, use a default one.
|
||||||
|
// @table_factory_to_write: the table factory used when writing to new files.
|
||||||
|
extern TableFactory* NewAdaptiveTableFactory(
|
||||||
|
std::shared_ptr<TableFactory> block_based_table_factory = nullptr,
|
||||||
|
std::shared_ptr<TableFactory> plain_table_factory = nullptr,
|
||||||
|
std::shared_ptr<TableFactory> table_factory_to_write = nullptr);
|
||||||
|
|
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
73
table/adaptive_table_factory.cc
Normal file
73
table/adaptive_table_factory.cc
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef ROCKSDB_LITE
|
||||||
|
#include "table/adaptive_table_factory.h"
|
||||||
|
|
||||||
|
#include "table/format.h"
|
||||||
|
|
||||||
|
namespace rocksdb {
|
||||||
|
|
||||||
|
AdaptiveTableFactory::AdaptiveTableFactory(
|
||||||
|
std::shared_ptr<TableFactory> block_based_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> plain_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> table_factory_to_write)
|
||||||
|
: block_based_table_factory_(block_based_table_factory),
|
||||||
|
plain_table_factory_(plain_table_factory),
|
||||||
|
table_factory_to_write_(table_factory_to_write) {
|
||||||
|
if (!plain_table_factory_) {
|
||||||
|
plain_table_factory_.reset(NewPlainTableFactory());
|
||||||
|
}
|
||||||
|
if (!block_based_table_factory_) {
|
||||||
|
block_based_table_factory_.reset(NewBlockBasedTableFactory());
|
||||||
|
}
|
||||||
|
if (!table_factory_to_write_) {
|
||||||
|
table_factory_to_write_ = block_based_table_factory_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const uint64_t kPlainTableMagicNumber;
|
||||||
|
extern const uint64_t kLegacyPlainTableMagicNumber;
|
||||||
|
extern const uint64_t kBlockBasedTableMagicNumber;
|
||||||
|
extern const uint64_t kLegacyBlockBasedTableMagicNumber;
|
||||||
|
|
||||||
|
Status AdaptiveTableFactory::NewTableReader(
|
||||||
|
const Options& options, const EnvOptions& soptions,
|
||||||
|
const InternalKeyComparator& icomp, unique_ptr<RandomAccessFile>&& file,
|
||||||
|
uint64_t file_size, unique_ptr<TableReader>* table) const {
|
||||||
|
Footer footer;
|
||||||
|
auto s = ReadFooterFromFile(file.get(), file_size, &footer);
|
||||||
|
if (!s.ok()) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (footer.table_magic_number() == kPlainTableMagicNumber ||
|
||||||
|
footer.table_magic_number() == kLegacyPlainTableMagicNumber) {
|
||||||
|
return plain_table_factory_->NewTableReader(
|
||||||
|
options, soptions, icomp, std::move(file), file_size, table);
|
||||||
|
} else if (footer.table_magic_number() == kBlockBasedTableMagicNumber ||
|
||||||
|
footer.table_magic_number() == kLegacyBlockBasedTableMagicNumber) {
|
||||||
|
return block_based_table_factory_->NewTableReader(
|
||||||
|
options, soptions, icomp, std::move(file), file_size, table);
|
||||||
|
} else {
|
||||||
|
return Status::NotSupported("Unidentified table format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TableBuilder* AdaptiveTableFactory::NewTableBuilder(
|
||||||
|
const Options& options, const InternalKeyComparator& internal_comparator,
|
||||||
|
WritableFile* file, CompressionType compression_type) const {
|
||||||
|
return table_factory_to_write_->NewTableBuilder(options, internal_comparator,
|
||||||
|
file, compression_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern TableFactory* NewAdaptiveTableFactory(
|
||||||
|
std::shared_ptr<TableFactory> block_based_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> plain_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> table_factory_to_write) {
|
||||||
|
return new AdaptiveTableFactory(
|
||||||
|
block_based_table_factory, plain_table_factory, table_factory_to_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rocksdb
|
||||||
|
#endif // ROCKSDB_LITE
|
50
table/adaptive_table_factory.h
Normal file
50
table/adaptive_table_factory.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ROCKSDB_LITE
|
||||||
|
|
||||||
|
#include "rocksdb/options.h"
|
||||||
|
#include "rocksdb/table.h"
|
||||||
|
|
||||||
|
namespace rocksdb {
|
||||||
|
|
||||||
|
struct Options;
|
||||||
|
struct EnvOptions;
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
class Status;
|
||||||
|
class RandomAccessFile;
|
||||||
|
class WritableFile;
|
||||||
|
class Table;
|
||||||
|
class TableBuilder;
|
||||||
|
|
||||||
|
class AdaptiveTableFactory : public TableFactory {
|
||||||
|
public:
|
||||||
|
~AdaptiveTableFactory() {}
|
||||||
|
|
||||||
|
explicit AdaptiveTableFactory(
|
||||||
|
std::shared_ptr<TableFactory> block_based_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> plain_table_factory,
|
||||||
|
std::shared_ptr<TableFactory> table_factory_to_write);
|
||||||
|
const char* Name() const override { return "AdaptiveTableFactory"; }
|
||||||
|
Status NewTableReader(const Options& options, const EnvOptions& soptions,
|
||||||
|
const InternalKeyComparator& internal_comparator,
|
||||||
|
unique_ptr<RandomAccessFile>&& file, uint64_t file_size,
|
||||||
|
unique_ptr<TableReader>* table) const override;
|
||||||
|
TableBuilder* NewTableBuilder(const Options& options,
|
||||||
|
const InternalKeyComparator& icomparator,
|
||||||
|
WritableFile* file,
|
||||||
|
CompressionType compression_type) const
|
||||||
|
override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<TableFactory> block_based_table_factory_;
|
||||||
|
std::shared_ptr<TableFactory> plain_table_factory_;
|
||||||
|
std::shared_ptr<TableFactory> table_factory_to_write_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rocksdb
|
||||||
|
#endif // ROCKSDB_LITE
|
Loading…
Reference in New Issue
Block a user