Rocksdb:使用唯一指针关闭数据库时断言`last_ref'失败

时间:2019-05-16 17:32:20

标签: rocksdb

当我尝试关闭/删除rocksdb或超出范围时,我不断得到rocksdb_column_family_error_test: /rocksdb/db/column_family.cc:1236: rocksdb::ColumnFamilySet::~ColumnFamilySet(): Assertion `last_ref' failed.。它抛出SIGABRT。也就是说,当我将std :: unique_pointers用于数据库和列系列处理程序时。我已经附上了我正在使用的测试文件,该文件模仿了我们的生产代码。主要的例外是在生产代码中,我们有一个处理数据库内容的类。无论哪种方式,关闭数据库时都会引发SIGABRT。我搜索了答案,发现了类似的问题。该问题的主要结论是,在关闭数据库之前未从数据库中释放列系列处理程序。另外,在rocksdb的先前版本中似乎与此有关。那个bug还在吗?我只是做错了什么吗?尽管不在此代码中,但我也对默认列系列的drop / destroy进行了测试。

Rockdb版本。h

#define ROCKSDB_MAJOR 6
#define ROCKSDB_MINOR 2
#define ROCKSDB_PATCH 0

下面是测试文件:

#include <gtest/gtest.h>
#include <rocksdb/db.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/table.h>

namespace testing {

namespace {
    static const std::string db_directory                   = std::string("/tmp/database");
    static const std::string kFeaturesColumnFamilyName      = "keypoints_and_descriptors";
    static const std::string kMatchesColumnFamilyName       = "image_pair_matches";
    static const std::string kIntrinsicsColumnFamilyName    = "camera_intrinsics_prior";

}  // namespace

TEST(RocksdbColumnFamilyError, RocksBasicPointers) {
    std::unique_ptr<rocksdb::Options> options_;
    std::unique_ptr<rocksdb::DB> database_;
    std::unique_ptr<rocksdb::ColumnFamilyHandle> intrinsics_prior_handle_;
    std::unique_ptr<rocksdb::ColumnFamilyHandle> features_handle_;
    std::unique_ptr<rocksdb::ColumnFamilyHandle> matches_handle_;

    options_.reset(new rocksdb::Options);
    options_->max_background_jobs = 4;
    options_->db_write_buffer_size = 1 << 30;
    options_->bytes_per_sync = 1 << 20;
    options_->compaction_pri = rocksdb::kMinOverlappingRatio;
    options_->create_if_missing = true;
    options_->level_compaction_dynamic_level_bytes = true;
    options_->statistics = rocksdb::CreateDBStatistics();

    rocksdb::BlockBasedTableOptions table_options;
    table_options.block_cache = rocksdb::NewLRUCache(512 << 20);
    table_options.block_size = 16 * 1024;
    table_options.cache_index_and_filter_blocks = true;
    table_options.pin_l0_filter_and_index_blocks_in_cache = true;
    table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
    options_->table_factory.reset(rocksdb::NewBlockBasedTableFactory(table_options));

    std::vector<rocksdb::ColumnFamilyDescriptor> column_descriptors;
    column_descriptors.emplace_back(rocksdb::kDefaultColumnFamilyName, *options_);

    // Open the DB, creating it if necessary.
    rocksdb::DB* temp_db = nullptr;
    std::vector<rocksdb::ColumnFamilyHandle*> temp_col_family_handles;
    rocksdb::Status status = rocksdb::DB::Open(*options_,
                                               db_directory,
                                               column_descriptors,
                                               &temp_col_family_handles,
                                               &temp_db);

    // Take ownership of the database object.
    database_.reset(temp_db);

    // Create intrinsics_prior_handle_
    rocksdb::ColumnFamilyHandle * intrinsics_prior_;
    database_->CreateColumnFamily(*options_, kIntrinsicsColumnFamilyName, &intrinsics_prior_);
    intrinsics_prior_handle_.reset(intrinsics_prior_);

    // Create features_handle_
    rocksdb::ColumnFamilyHandle * features_;
    database_->CreateColumnFamily(*options_, kFeaturesColumnFamilyName, &features_);
    features_handle_.reset(features_);

    // Create matches_handle_
    rocksdb::ColumnFamilyHandle * matches_;
    database_->CreateColumnFamily(*options_, kMatchesColumnFamilyName, &matches_);
    matches_handle_.reset(matches_);

    /*
     * .... proform database operation get stuff, put stuff so on ....
     */

    // Drop handles
    database_->DropColumnFamily(intrinsics_prior_handle_.get());
    database_->DropColumnFamily(features_handle_.get());
    database_->DropColumnFamily(matches_handle_.get());

    // Destroy handles
    database_->DestroyColumnFamilyHandle(intrinsics_prior_handle_.get());
    database_->DestroyColumnFamilyHandle(features_handle_.get());
    database_->DestroyColumnFamilyHandle(matches_handle_.get());

    // Close db
    database_->Close();         // Causes SIGABRT
//    delete database_.get();     // Causes SIGABRT
//    rocksdb::DestroyDB(db_directory, rocksdb::Options());   // Causes SIGABRT  // Options doesn't have any affect
    rocksdb::DestroyDB(db_directory, *options_);            // Causes SIGABRT  // Options doesn't have any affect
}

}  // namespace testing

1 个答案:

答案 0 :(得分:0)

我认为,除了删除和销毁已创建的ColumnFamilies外,还需要销毁默认的列族。

database_->DestroyColumnFamilyHandle(default_family_handle_);

不应删除默认系列。