Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions db/db_impl/db_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "db/arena_wrapped_db_iter.h"
#include "db/attribute_group_iterator_impl.h"
#include "db/blob/blob_constants.h"
#include "db/blob/blob_fetcher.h"
#include "db/blob/blob_file_partition_manager.h"
#include "db/blob/blob_index.h"
Expand Down Expand Up @@ -8773,13 +8774,26 @@ Status DBImpl::CreateColumnFamilyWithImport(

std::string cf_comparator_name = options.comparator->Name();

// Import only brings SST files, never blob files, so any blob reference in
// the new column family would dangle.
if (options.enable_blob_files) {
return Status::NotSupported(
"CreateColumnFamilyWithImport does not support blob files");
}

size_t total_file_num = 0;
std::vector<std::vector<LiveFileMetaData*>> metadata_files(metadatas.size());
for (size_t i = 0; i < metadatas.size(); i++) {
if (cf_comparator_name != metadatas[i]->db_comparator_name) {
return Status::InvalidArgument("Comparator name mismatch");
}
for (auto& file : metadatas[i]->files) {
if (file.oldest_blob_file_number != kInvalidBlobFileNumber) {
return Status::NotSupported(
"CreateColumnFamilyWithImport does not support files that "
"reference blob files: " +
file.name);
}
metadata_files[i].push_back((LiveFileMetaData*)&file);
}
total_file_num += metadatas[i]->files.size();
Expand Down
67 changes: 67 additions & 0 deletions db/import_column_family_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <functional>
#include <utility>

#include "db/blob/blob_constants.h"
#include "db/db_test_util.h"
#include "port/port.h"
#include "port/stack_trace.h"
Expand Down Expand Up @@ -1214,6 +1215,72 @@ TEST_F(ImportColumnFamilyTest, ImportFileTimesAndRejectTooOldFile) {
std::make_pair(now - 10100, now - 10100));
}
}

TEST_F(ImportColumnFamilyTest, ImportRejectsBlobFiles) {
Options options = CurrentOptions();
CreateAndReopenWithCF({"koko"}, options);

for (int i = 0; i < 10; ++i) {
ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
}
ASSERT_OK(Flush(1));

Checkpoint* checkpoint;
ASSERT_OK(Checkpoint::Create(db_.get(), &checkpoint));
ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir_,
&metadata_ptr_));
ASSERT_NE(metadata_ptr_, nullptr);

ImportColumnFamilyOptions import_options;

// The new column family must not use blob files, even if the imported files
// do not reference any.
Options blob_options = options;
blob_options.enable_blob_files = true;
Status s = db_->CreateColumnFamilyWithImport(
blob_options, "toto", import_options, *metadata_ptr_, &import_cfh_);
ASSERT_TRUE(s.IsNotSupported()) << s.ToString();
ASSERT_EQ(import_cfh_, nullptr);

// A normal import still works, and the rejected import left no column
// family behind under the same name.
ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "toto", import_options,
*metadata_ptr_, &import_cfh_));
ASSERT_NE(import_cfh_, nullptr);
for (int i = 0; i < 10; ++i) {
std::string value;
ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value));
ASSERT_EQ(Key(i) + "_val", value);
}

// Export a column family whose SST files reference blob files. Import never
// brings the blob files, so it is rejected.
ASSERT_OK(dbfull()->SetOptions(
handles_[1], {{"enable_blob_files", "true"}, {"min_blob_size", "0"}}));
for (int i = 0; i < 10; ++i) {
ASSERT_OK(Put(1, Key(i), Key(i) + "_blob"));
}
ASSERT_OK(Flush(1));
ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir2_,
&metadata_ptr2_));
ASSERT_NE(metadata_ptr2_, nullptr);
delete checkpoint;

bool references_blob = false;
for (const auto& file : metadata_ptr2_->files) {
if (file.oldest_blob_file_number != kInvalidBlobFileNumber) {
references_blob = true;
}
}
ASSERT_TRUE(references_blob);

s = db_->CreateColumnFamilyWithImport(options, "yoyo", import_options,
*metadata_ptr2_, &import_cfh2_);
ASSERT_TRUE(s.IsNotSupported()) << s.ToString();
ASSERT_NE(std::string(s.getState()).find("reference blob files"),
std::string::npos);
ASSERT_EQ(import_cfh2_, nullptr);
}
} // namespace ROCKSDB_NAMESPACE

int main(int argc, char** argv) {
Expand Down
3 changes: 3 additions & 0 deletions include/rocksdb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -2778,6 +2778,9 @@ class DB {
// On error return, column family handle returned will be nullptr.
// ColumnFamily will be present on successful return and will not be present
// on error return. ColumnFamily may be present on any crash during this call.
// Blob files are not supported: import never brings blob files, so it
// returns NotSupported if `options.enable_blob_files` is true or if any
// file in `metadata` references blob files (oldest_blob_file_number != 0).
virtual Status CreateColumnFamilyWithImport(
const ColumnFamilyOptions& options, const std::string& column_family_name,
const ImportColumnFamilyOptions& import_options,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`DB::CreateColumnFamilyWithImport()` now returns `NotSupported` when the new column family has `enable_blob_files = true`, or when any imported file references blob files (`oldest_blob_file_number` is set in its metadata, for example an export of a BlobDB column family). Import never brings blob files, so such imports used to succeed but leave blob references that point to missing files.
Loading