Add missing table properties in plaintable GetTableProperties() (#11267)
Summary:
Plaintable will miss properties.
It should have some behavior like blockbasedtable.
Here is a unit test for reproduce this bug.
```
#include <gflags/gflags.h>
#include "rocksdb/db.h"
#include "rocksdb/options.h"
#include "rocksdb/table.h"
#include "rocksdb/slice_transform.h"
#include <iostream>
#include <thread>
#include <csignal>
const std::string kKey = "key";
DEFINE_bool(use_plaintable, true, "use plain table");
DEFINE_string(db_path, "/dev/shm/test_zyx_path", "db_path");
rocksdb::DB* db = nullptr;
class NoopTransform : public rocksdb::SliceTransform {
public:
explicit NoopTransform() {
}
virtual const char* Name() const override {
return "rocksdb.Noop";
}
virtual rocksdb::Slice Transform(const rocksdb::Slice& src) const override {
return src;
}
virtual bool InDomain(const rocksdb::Slice& src) const override {
return true;
}
virtual bool InRange(const rocksdb::Slice& dst) const override {
return true;
}
virtual bool SameResultWhenAppended(const rocksdb::Slice& prefix) const override {
return false;
}
};
class TestPropertiesCollector : public ::rocksdb::TablePropertiesCollector {
public:
explicit TestPropertiesCollector() {
}
private:
::rocksdb::Status AddUserKey(const ::rocksdb::Slice& key, const ::rocksdb::Slice& value, ::rocksdb::EntryType type,
::rocksdb::SequenceNumber seq, uint64_t file_size) override {
count++;
return ::rocksdb::Status::OK();
}
::rocksdb::Status Finish(::rocksdb::UserCollectedProperties* properties) override {
properties->insert({kKey, std::to_string(count)});
return ::rocksdb::Status::OK();
}
::rocksdb::UserCollectedProperties GetReadableProperties() const override {
::rocksdb::UserCollectedProperties properties;
properties.insert({kKey, std::to_string(count)});
return properties;
}
const char* Name() const override {
return "TestPropertiesCollector";
}
int count = 0;
};
class TestTablePropertiesCollectorFactory : public ::rocksdb::TablePropertiesCollectorFactory {
public:
explicit TestTablePropertiesCollectorFactory() {
}
private:
::rocksdb::TablePropertiesCollector* CreateTablePropertiesCollector(
::rocksdb::TablePropertiesCollectorFactory::Context context) override {
return new TestPropertiesCollector();
}
const char* Name() const override {
return "test.TablePropertiesCollectorFactory";
}
};
class TestFlushListener : rocksdb::EventListener {
public:
const char* Name() const override {
return "TestFlushListener";
}
void OnFlushCompleted(rocksdb::DB* /*db*/, const rocksdb::FlushJobInfo& flush_job_info) override {
if (flush_job_info.table_properties.user_collected_properties.find(kKey) ==
flush_job_info.table_properties.user_collected_properties.end()) {
std::cerr << "OnFlushCompleted: properties not found" << std::endl;
return;
}
std::cerr << "OnFlushCompleted: properties found "
<< flush_job_info.table_properties.user_collected_properties.at(kKey) << std::endl;
}
explicit TestFlushListener() {
}
};
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
rocksdb::DBOptions rocksdb_options;
std::shared_ptr<rocksdb::EventListener> flush_offset;
rocksdb_options.create_if_missing = true;
rocksdb_options.create_missing_column_families = true;
std::shared_ptr<::rocksdb::TablePropertiesCollectorFactory> properties_collector(
new TestTablePropertiesCollectorFactory());
rocksdb::ColumnFamilyOptions cfoptions;
cfoptions.table_properties_collector_factories.emplace_back(properties_collector);
std::shared_ptr<rocksdb::EventListener> test_cleaner;
test_cleaner.reset((rocksdb::EventListener*)new TestFlushListener());
rocksdb_options.listeners.emplace_back(test_cleaner);
std::vector<rocksdb::ColumnFamilyDescriptor> cf_desc_;
cf_desc_.emplace_back(rocksdb::kDefaultColumnFamilyName, cfoptions);
std::vector<rocksdb::ColumnFamilyHandle*> cfhs;
cfoptions.prefix_extractor.reset(new NoopTransform());
if (FLAGS_use_plaintable) {
cfoptions.table_factory.reset(rocksdb::NewPlainTableFactory());
std::cerr << "use plaintable" << std::endl;
} else {
cfoptions.table_factory.reset(rocksdb::NewBlockBasedTableFactory());
std::cerr << "use blockbasedtable" << std::endl;
}
auto s = rocksdb::DB::Open(rocksdb_options, FLAGS_db_path, cf_desc_, &cfhs, &db);
if (s.ok()) {
rocksdb::WriteOptions wops;
wops.disableWAL = true;
for (int i = 0; i < 1000000; i++) {
auto status = db->Put(wops, std::to_string(i), std::string(1024, '3'));
if (!status.ok()) {
std::cerr << "write fail " << status.getState() << std::endl;
}
}
} else {
std::cerr << "open rocksdb failed" << s.getState() << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1000));
delete db;
}
```
Pull Request resolved: https://github.com/facebook/rocksdb/pull/11267
Reviewed By: jowlyzhang
Differential Revision: D47689943
Pulled By: hx235
fbshipit-source-id: 585589cc48f8b26c7dd2323fc7ac4a0c3d4df6bb