diff --git a/db/db_impl.cc b/db/db_impl.cc index 294e0e4be..9061adecc 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -3497,6 +3497,33 @@ void DBImpl::GetLiveFilesMetaData(std::vector *metadata) { return versions_->GetLiveFilesMetaData(metadata); } +Status DBImpl::GetDbIdentity(std::string& identity) { + std::string idfilename = IdentityFileName(dbname_); + unique_ptr 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 // can call if they wish Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { diff --git a/db/db_impl.h b/db/db_impl.h index 15b6013d0..d7a346b6e 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -85,6 +85,8 @@ class DBImpl : public DB { virtual void GetLiveFilesMetaData( std::vector *metadata); + virtual Status GetDbIdentity(std::string& identity); + // Extra methods (for testing) that are not in the public DB interface // Compact any files in the named level that overlap [*begin, *end] diff --git a/db/db_test.cc b/db/db_test.cc index 069ab679f..5850d343f 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -1731,31 +1731,23 @@ TEST(DBTest, ManifestRollOver) { TEST(DBTest, IdentityAcrossRestarts) { do { - std::string idfilename = IdentityFileName(dbname_); - unique_ptr idfile; - const EnvOptions soptions; - ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions)); - char buffer1[100]; - Slice id1; - ASSERT_OK(idfile->Read(100, &id1, buffer1)); + std::string id1; + ASSERT_OK(db_->GetDbIdentity(id1)); Options options = CurrentOptions(); Reopen(&options); - char buffer2[100]; - Slice id2; - ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions)); - ASSERT_OK(idfile->Read(100, &id2, buffer2)); + std::string id2; + ASSERT_OK(db_->GetDbIdentity(id2)); // 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)); Reopen(&options); - char buffer3[100]; - Slice id3; - ASSERT_OK(env_->NewSequentialFile(idfilename, &idfile, soptions)); - ASSERT_OK(idfile->Read(100, &id3, buffer3)); - // id1 should NOT match id2 because identity was regenerated - ASSERT_NE(id1.ToString(0), id3.ToString()); + std::string id3; + ASSERT_OK(db_->GetDbIdentity(id3)); + // id1 should NOT match id3 because identity was regenerated + ASSERT_NE(id1.compare(id3), 0); } while (ChangeCompactOptions()); } diff --git a/include/rocksdb/db.h b/include/rocksdb/db.h index 73f9ac4da..9849d3adf 100644 --- a/include/rocksdb/db.h +++ b/include/rocksdb/db.h @@ -273,7 +273,7 @@ class DB { // 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 // 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 // use this api, else the WAL files will get // cleared aggressively and the iterator might keep getting invalid before @@ -292,6 +292,14 @@ class DB { std::vector *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: // No copying allowed DB(const DB&);