提交 18802689 编写于 作者: M Mayank Agarwal

Make an API to get database identity from the IDENTITY file

Summary: This would enable rocksdb users to get the db identity without depending on implementation details(storing that in IDENTITY file)

Test Plan: db/db_test (has identity checks)

Reviewers: dhruba, haobo, igor, kailiu

Reviewed By: dhruba

CC: leveldb

Differential Revision: https://reviews.facebook.net/D14463
上级 fa88cbc7
...@@ -3497,6 +3497,33 @@ void DBImpl::GetLiveFilesMetaData(std::vector<LiveFileMetaData> *metadata) { ...@@ -3497,6 +3497,33 @@ void DBImpl::GetLiveFilesMetaData(std::vector<LiveFileMetaData> *metadata) {
return versions_->GetLiveFilesMetaData(metadata); return versions_->GetLiveFilesMetaData(metadata);
} }
Status DBImpl::GetDbIdentity(std::string& identity) {
std::string idfilename = IdentityFileName(dbname_);
unique_ptr<SequentialFile> idfile;
const EnvOptions soptions;
Status s = env_->NewSequentialFile(idfilename, &idfile, soptions);
if (!s.ok()) {
return s;
}
uint64_t file_size;
s = env_->GetFileSize(idfilename, &file_size);
if (!s.ok()) {
return s;
}
char buffer[file_size];
Slice id;
s = idfile->Read(file_size, &id, buffer);
if (!s.ok()) {
return s;
}
identity.assign(id.ToString());
// If last character is '\n' remove it from identity
if (identity.size() > 0 && identity.back() == '\n') {
identity.pop_back();
}
return s;
}
// Default implementations of convenience methods that subclasses of DB // Default implementations of convenience methods that subclasses of DB
// can call if they wish // can call if they wish
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) {
......
...@@ -85,6 +85,8 @@ class DBImpl : public DB { ...@@ -85,6 +85,8 @@ class DBImpl : public DB {
virtual void GetLiveFilesMetaData( virtual void GetLiveFilesMetaData(
std::vector<LiveFileMetaData> *metadata); std::vector<LiveFileMetaData> *metadata);
virtual Status GetDbIdentity(std::string& identity);
// Extra methods (for testing) that are not in the public DB interface // Extra methods (for testing) that are not in the public DB interface
// Compact any files in the named level that overlap [*begin, *end] // Compact any files in the named level that overlap [*begin, *end]
......
...@@ -1731,31 +1731,23 @@ TEST(DBTest, ManifestRollOver) { ...@@ -1731,31 +1731,23 @@ TEST(DBTest, ManifestRollOver) {
TEST(DBTest, IdentityAcrossRestarts) { TEST(DBTest, IdentityAcrossRestarts) {
do { do {
std::string idfilename = IdentityFileName(dbname_); std::string id1;
unique_ptr<SequentialFile> idfile; ASSERT_OK(db_->GetDbIdentity(id1));
const EnvOptions soptions;
ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions));
char buffer1[100];
Slice id1;
ASSERT_OK(idfile->Read(100, &id1, buffer1));
Options options = CurrentOptions(); Options options = CurrentOptions();
Reopen(&options); Reopen(&options);
char buffer2[100]; std::string id2;
Slice id2; ASSERT_OK(db_->GetDbIdentity(id2));
ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions));
ASSERT_OK(idfile->Read(100, &id2, buffer2));
// id1 should match id2 because identity was not regenerated // id1 should match id2 because identity was not regenerated
ASSERT_EQ(id1.ToString(), id2.ToString()); ASSERT_EQ(id1.compare(id2), 0);
std::string idfilename = IdentityFileName(dbname_);
ASSERT_OK(env_->DeleteFile(idfilename)); ASSERT_OK(env_->DeleteFile(idfilename));
Reopen(&options); Reopen(&options);
char buffer3[100]; std::string id3;
Slice id3; ASSERT_OK(db_->GetDbIdentity(id3));
ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions)); // id1 should NOT match id3 because identity was regenerated
ASSERT_OK(idfile->Read(100, &id3, buffer3)); ASSERT_NE(id1.compare(id3), 0);
// id1 should NOT match id2 because identity was regenerated
ASSERT_NE(id1.ToString(0), id3.ToString());
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
......
...@@ -273,7 +273,7 @@ class DB { ...@@ -273,7 +273,7 @@ class DB {
// Sets iter to an iterator that is positioned at a write-batch containing // Sets iter to an iterator that is positioned at a write-batch containing
// seq_number. If the sequence number is non existent, it returns an iterator // seq_number. If the sequence number is non existent, it returns an iterator
// at the first available seq_no after the requested seq_no // at the first available seq_no after the requested seq_no
// Returns Status::Ok if iterator is valid // Returns Status::OK if iterator is valid
// Must set WAL_ttl_seconds or WAL_size_limit_MB to large values to // Must set WAL_ttl_seconds or WAL_size_limit_MB to large values to
// use this api, else the WAL files will get // use this api, else the WAL files will get
// cleared aggressively and the iterator might keep getting invalid before // cleared aggressively and the iterator might keep getting invalid before
...@@ -292,6 +292,14 @@ class DB { ...@@ -292,6 +292,14 @@ class DB {
std::vector<LiveFileMetaData> *metadata) { std::vector<LiveFileMetaData> *metadata) {
} }
// Sets the globally unique ID created at database creation time by invoking
// Env::GenerateUniqueId(), in identity. Returns Status::OK if identity could
// be set properly
virtual Status GetDbIdentity(std::string& identity) {
identity.clear();
return Status::OK();
}
private: private:
// No copying allowed // No copying allowed
DB(const DB&); DB(const DB&);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册