Skip to content

Commit eb7120e

Browse files
committed
Implement DBCloud::ListColumnFamilies()
Summary: We need to load cloud manifest before calling into DB::ListColumnFamilies(). Test Plan: Added a unit test Reviewers: #sys-eng_team, dhruba Differential Revision: https://rockset.phacility.com/D11081
1 parent 7645dfb commit eb7120e

File tree

3 files changed

+114
-19
lines changed

3 files changed

+114
-19
lines changed

cloud/db_cloud_impl.cc

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,17 @@ Status DBCloud::Open(const Options& opt, const std::string& local_dbname,
120120
local_dbname); // MJR: TODO: Move into sanitize
121121
}
122122

123-
st = cenv->SanitizeDirectory(options, local_dbname, read_only);
123+
// If cloud manifest is already loaded, this means the directory has been
124+
// sanitized (possibly by the call to ListColumnFamilies())
125+
if (cenv->GetCloudManifest() == nullptr) {
126+
st = cenv->SanitizeDirectory(options, local_dbname, read_only);
124127

125-
if (st.ok()) {
126-
st = cenv->LoadCloudManifest(local_dbname, read_only);
127-
}
128-
if (!st.ok()) {
129-
return st;
128+
if (st.ok()) {
129+
st = cenv->LoadCloudManifest(local_dbname, read_only);
130+
}
131+
if (!st.ok()) {
132+
return st;
133+
}
130134
}
131135
// If a persistent cache path is specified, then we set it in the options.
132136
if (!persistent_cache_path.empty() && persistent_cache_size_gb) {
@@ -403,5 +407,25 @@ Status DBCloudImpl::ExecuteRemoteCompactionRequest(
403407
return Status::OK();
404408
}
405409

410+
Status DBCloud::ListColumnFamilies(const DBOptions& db_options,
411+
const std::string& name,
412+
std::vector<std::string>* column_families) {
413+
CloudEnvImpl* cenv = static_cast<CloudEnvImpl*>(db_options.env);
414+
415+
Env* local_env = cenv->GetBaseEnv();
416+
local_env->CreateDirIfMissing(name);
417+
418+
Status st;
419+
st = cenv->SanitizeDirectory(db_options, name, false);
420+
if (st.ok()) {
421+
st = cenv->LoadCloudManifest(name, false);
422+
}
423+
if (st.ok()) {
424+
st = DB::ListColumnFamilies(db_options, name, column_families);
425+
}
426+
427+
return st;
428+
}
429+
406430
} // namespace ROCKSDB_NAMESPACE
407431
#endif // ROCKSDB_LITE

cloud/db_cloud_test.cc

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,24 @@ class CloudTest : public testing::Test {
130130

131131
// Open database via the cloud interface
132132
void OpenDB() {
133+
// default column family
134+
ColumnFamilyOptions cfopt = options_;
135+
std::vector<ColumnFamilyDescriptor> column_families;
136+
column_families.emplace_back(
137+
ColumnFamilyDescriptor(kDefaultColumnFamilyName, cfopt));
138+
139+
OpenWithColumnFamilies({kDefaultColumnFamilyName});
140+
}
141+
142+
void CreateColumnFamilies(const std::vector<std::string>& cfs) {
143+
size_t cfi = handles_.size();
144+
handles_.resize(cfi + cfs.size());
145+
for (auto cf : cfs) {
146+
ASSERT_OK(db_->CreateColumnFamily(options_, cf, &handles_[cfi++]));
147+
}
148+
}
149+
150+
void OpenWithColumnFamilies(const std::vector<std::string>& cfs) {
133151
ASSERT_TRUE(cloud_env_options_.credentials.HasValid().ok());
134152

135153
// Create new AWS env
@@ -139,23 +157,15 @@ class CloudTest : public testing::Test {
139157
// Sleep for a second because S3 is eventual consistency.
140158
std::this_thread::sleep_for(std::chrono::seconds(1));
141159

142-
// default column family
143-
ColumnFamilyOptions cfopt = options_;
144-
std::vector<ColumnFamilyDescriptor> column_families;
145-
column_families.emplace_back(
146-
ColumnFamilyDescriptor(kDefaultColumnFamilyName, cfopt));
147-
std::vector<ColumnFamilyHandle*> handles;
148-
149160
ASSERT_TRUE(db_ == nullptr);
161+
std::vector<ColumnFamilyDescriptor> column_families;
162+
for (size_t i = 0; i < cfs.size(); ++i) {
163+
column_families.emplace_back(cfs[i], options_);
164+
}
150165
ASSERT_OK(DBCloud::Open(options_, dbname_, column_families,
151166
persistent_cache_path_, persistent_cache_size_gb_,
152-
&handles, &db_));
167+
&handles_, &db_));
153168
ASSERT_OK(db_->GetDbIdentity(dbid_));
154-
155-
// Delete the handle for the default column family because the DBImpl
156-
// always holds a reference to it.
157-
ASSERT_TRUE(handles.size() > 0);
158-
delete handles[0];
159169
}
160170

161171
// Creates and Opens a clone
@@ -224,6 +234,10 @@ class CloudTest : public testing::Test {
224234
}
225235

226236
void CloseDB() {
237+
for (auto h : handles_) {
238+
delete h;
239+
}
240+
handles_.clear();
227241
if (db_) {
228242
db_->Flush(FlushOptions()); // convert pending writes to sst files
229243
delete db_;
@@ -288,6 +302,8 @@ class CloudTest : public testing::Test {
288302
uint64_t persistent_cache_size_gb_;
289303
DBCloud* db_;
290304
std::unique_ptr<CloudEnv> aenv_;
305+
306+
std::vector<ColumnFamilyHandle*> handles_;
291307
};
292308

293309
//
@@ -422,6 +438,53 @@ TEST_F(CloudTest, Newdb) {
422438
CloseDB();
423439
}
424440

441+
TEST_F(CloudTest, ColumnFamilies) {
442+
// Put one key-value
443+
OpenDB();
444+
445+
CreateColumnFamilies({"cf1", "cf2"});
446+
447+
ASSERT_OK(db_->Put(WriteOptions(), handles_[0], "hello", "a"));
448+
ASSERT_OK(db_->Put(WriteOptions(), handles_[1], "hello", "b"));
449+
ASSERT_OK(db_->Put(WriteOptions(), handles_[2], "hello", "c"));
450+
451+
auto validate = [&]() {
452+
std::string value;
453+
ASSERT_OK(db_->Get(ReadOptions(), handles_[0], "hello", &value));
454+
ASSERT_EQ(value, "a");
455+
ASSERT_OK(db_->Get(ReadOptions(), handles_[1], "hello", &value));
456+
ASSERT_EQ(value, "b");
457+
ASSERT_OK(db_->Get(ReadOptions(), handles_[2], "hello", &value));
458+
ASSERT_EQ(value, "c");
459+
};
460+
461+
validate();
462+
463+
CloseDB();
464+
OpenWithColumnFamilies({kDefaultColumnFamilyName, "cf1", "cf2"});
465+
466+
validate();
467+
CloseDB();
468+
469+
// destory local state
470+
DestroyDir(dbname_);
471+
472+
// new aws env
473+
CreateAwsEnv();
474+
options_.env = aenv_.get();
475+
476+
std::vector<std::string> families;
477+
ASSERT_OK(DBCloud::ListColumnFamilies(options_, dbname_, &families));
478+
std::sort(families.begin(), families.end());
479+
ASSERT_TRUE(families == std::vector<std::string>(
480+
{"cf1", "cf2", kDefaultColumnFamilyName}));
481+
482+
483+
OpenWithColumnFamilies({kDefaultColumnFamilyName, "cf1", "cf2"});
484+
validate();
485+
CloseDB();
486+
}
487+
425488
//
426489
// Create and read from a clone.
427490
//

include/rocksdb/cloud/db_cloud.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ class DBCloud : public StackableDB {
6262
const PluggableCompactionParam& inputParams,
6363
PluggableCompactionResult* result, bool sanitize) = 0;
6464

65+
// ListColumnFamilies will open the DB specified by argument name
66+
// and return the list of all column families in that DB
67+
// through column_families argument. The ordering of
68+
// column families in column_families is unspecified.
69+
static Status ListColumnFamilies(const DBOptions& db_options,
70+
const std::string& name,
71+
std::vector<std::string>* column_families);
72+
6573
virtual ~DBCloud() {}
6674

6775
protected:

0 commit comments

Comments
 (0)