Skip to content

Commit d3a2f28

Browse files
jay-zhuangfacebook-github-bot
authored andcommitted
Add Temperature info in NewSequentialFile() (facebook#9499)
Summary: Add Temperature hints information from RocksDB in API `NewSequentialFile()`. backup and checkpoint operations need to open the source files with `NewSequentialFile()`, which will have the temperature hints. Other operations are not covered. Pull Request resolved: facebook#9499 Test Plan: Added unittest Reviewed By: pdillinger Differential Revision: D34006115 Pulled By: jay-zhuang fbshipit-source-id: 568b34602b76520e53128672bd07e9d886786a2f
1 parent 559525d commit d3a2f28

11 files changed

+247
-47
lines changed

CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,7 @@ if(WITH_TESTS)
11821182
db/db_compaction_filter_test.cc
11831183
db/db_compaction_test.cc
11841184
db/db_dynamic_level_test.cc
1185+
db/db_encryption_test.cc
11851186
db/db_flush_test.cc
11861187
db/db_inplace_update_test.cc
11871188
db/db_io_failure_test.cc
@@ -1208,6 +1209,7 @@ if(WITH_TESTS)
12081209
db/db_universal_compaction_test.cc
12091210
db/db_wal_test.cc
12101211
db/db_with_timestamp_compaction_test.cc
1212+
db/db_write_buffer_manager_test.cc
12111213
db/db_write_test.cc
12121214
db/dbformat_test.cc
12131215
db/deletefile_test.cc
@@ -1219,6 +1221,7 @@ if(WITH_TESTS)
12191221
db/file_indexer_test.cc
12201222
db/filename_test.cc
12211223
db/flush_job_test.cc
1224+
db/import_column_family_test.cc
12221225
db/listener_test.cc
12231226
db/log_test.cc
12241227
db/manual_compaction_test.cc
@@ -1314,6 +1317,7 @@ if(WITH_TESTS)
13141317
utilities/cassandra/cassandra_row_merge_test.cc
13151318
utilities/cassandra/cassandra_serialize_test.cc
13161319
utilities/checkpoint/checkpoint_test.cc
1320+
utilities/env_timed_test.cc
13171321
utilities/memory/memory_test.cc
13181322
utilities/merge_operators/string_append/stringappend_test.cc
13191323
utilities/object_registry_test.cc
@@ -1331,6 +1335,7 @@ if(WITH_TESTS)
13311335
utilities/transactions/write_unprepared_transaction_test.cc
13321336
utilities/transactions/lock/range/range_locking_test.cc
13331337
utilities/ttl/ttl_test.cc
1338+
utilities/util_merge_operators_test.cc
13341339
utilities/write_batch_with_index/write_batch_with_index_test.cc
13351340
)
13361341
endif()

HISTORY.md

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
* `ColumnFamilyOptions::OldDefaults` and `DBOptions::OldDefaults` are marked deprecated, as they are no longer maintained.
7474
* Add subcompaction callback APIs: `OnSubcompactionBegin()` and `OnSubcompactionCompleted()`.
7575
* Add file Temperature information to `FileOperationInfo` in event listener API.
76+
* Add Temperature hints information from RocksDB in API `NewSequentialFile()`. backup and checkpoint operations need to open the source files with `NewSequentialFile()`, which will have the temperature hints. Other operations are not covered.
7677

7778
### Behavior Changes
7879
* Disallow the combination of DBOptions.use_direct_io_for_flush_and_compaction == true and DBOptions.writable_file_max_buffer_size == 0. This combination can cause WritableFileWriter::Append() to loop forever, and it does not make much sense in direct IO.

db/db_test2.cc

+169
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "rocksdb/persistent_cache.h"
2222
#include "rocksdb/trace_record.h"
2323
#include "rocksdb/trace_record_result.h"
24+
#include "rocksdb/utilities/backup_engine.h"
2425
#include "rocksdb/utilities/replayer.h"
2526
#include "rocksdb/wal_filter.h"
2627
#include "test_util/testutil.h"
@@ -6899,6 +6900,174 @@ TEST_F(DBTest2, LastLevelStatistics) {
68996900
ASSERT_EQ(options.statistics->getTickerCount(LAST_LEVEL_READ_COUNT),
69006901
options.statistics->getTickerCount(WARM_FILE_READ_COUNT));
69016902
}
6903+
6904+
class FileTemperatureTestFS : public FileSystemWrapper {
6905+
public:
6906+
explicit FileTemperatureTestFS(SpecialEnv* env)
6907+
: FileSystemWrapper(env->GetFileSystem()) {}
6908+
6909+
static const char* kClassName() { return "TestFileSystem"; }
6910+
const char* Name() const override { return kClassName(); }
6911+
6912+
IOStatus NewSequentialFile(const std::string& fname, const FileOptions& opts,
6913+
std::unique_ptr<FSSequentialFile>* result,
6914+
IODebugContext* dbg) override {
6915+
auto filename = GetFileName(fname);
6916+
uint64_t number;
6917+
FileType type;
6918+
auto r = ParseFileName(filename, &number, &type);
6919+
assert(r);
6920+
if (type == kTableFile) {
6921+
auto emplaced =
6922+
requested_sst_file_temperatures_.emplace(number, opts.temperature);
6923+
assert(emplaced.second); // assume no duplication
6924+
}
6925+
return target()->NewSequentialFile(fname, opts, result, dbg);
6926+
}
6927+
6928+
IOStatus LinkFile(const std::string& s, const std::string& t,
6929+
const IOOptions& options, IODebugContext* dbg) override {
6930+
auto filename = GetFileName(s);
6931+
uint64_t number;
6932+
FileType type;
6933+
auto r = ParseFileName(filename, &number, &type);
6934+
assert(r);
6935+
// return not supported to force checkpoint copy the file instead of just
6936+
// link
6937+
if (type == kTableFile) {
6938+
return IOStatus::NotSupported();
6939+
}
6940+
return target()->LinkFile(s, t, options, dbg);
6941+
}
6942+
6943+
const std::map<uint64_t, Temperature>& RequestedSstFileTemperatures() {
6944+
return requested_sst_file_temperatures_;
6945+
}
6946+
6947+
void ClearRequestedFileTemperatures() {
6948+
requested_sst_file_temperatures_.clear();
6949+
}
6950+
6951+
private:
6952+
std::map<uint64_t, Temperature> requested_sst_file_temperatures_;
6953+
6954+
std::string GetFileName(const std::string& fname) {
6955+
auto filename = fname.substr(fname.find_last_of(kFilePathSeparator) + 1);
6956+
// workaround only for Windows that the file path could contain both Windows
6957+
// FilePathSeparator and '/'
6958+
filename = filename.substr(filename.find_last_of('/') + 1);
6959+
return filename;
6960+
}
6961+
};
6962+
6963+
TEST_F(DBTest2, BackupFileTemperature) {
6964+
std::shared_ptr<FileTemperatureTestFS> test_fs =
6965+
std::make_shared<FileTemperatureTestFS>(env_);
6966+
std::unique_ptr<Env> backup_env(new CompositeEnvWrapper(env_, test_fs));
6967+
Options options = CurrentOptions();
6968+
options.bottommost_temperature = Temperature::kWarm;
6969+
options.level0_file_num_compaction_trigger = 2;
6970+
Reopen(options);
6971+
6972+
// generate a bottommost file and a non-bottommost file
6973+
ASSERT_OK(Put("foo", "bar"));
6974+
ASSERT_OK(Put("bar", "bar"));
6975+
ASSERT_OK(Flush());
6976+
ASSERT_OK(Put("foo", "bar"));
6977+
ASSERT_OK(Put("bar", "bar"));
6978+
ASSERT_OK(Flush());
6979+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
6980+
ASSERT_OK(Put("foo", "bar"));
6981+
ASSERT_OK(Put("bar", "bar"));
6982+
ASSERT_OK(Flush());
6983+
auto size = GetSstSizeHelper(Temperature::kWarm);
6984+
ASSERT_GT(size, 0);
6985+
6986+
std::map<uint64_t, Temperature> temperatures;
6987+
std::vector<LiveFileStorageInfo> infos;
6988+
ASSERT_OK(
6989+
dbfull()->GetLiveFilesStorageInfo(LiveFilesStorageInfoOptions(), &infos));
6990+
for (auto info : infos) {
6991+
temperatures.emplace(info.file_number, info.temperature);
6992+
}
6993+
BackupEngine* backup_engine;
6994+
auto backup_options = BackupEngineOptions(
6995+
dbname_ + kFilePathSeparator + "tempbk", backup_env.get());
6996+
auto s = BackupEngine::Open(backup_env.get(), backup_options, &backup_engine);
6997+
ASSERT_OK(s);
6998+
s = backup_engine->CreateNewBackup(db_);
6999+
ASSERT_OK(s);
7000+
7001+
// checking src file src_temperature hints: 2 sst files: 1 sst is kWarm,
7002+
// another is kUnknown
7003+
auto file_temperatures = test_fs->RequestedSstFileTemperatures();
7004+
ASSERT_EQ(file_temperatures.size(), 2);
7005+
bool has_only_one_warm_sst = false;
7006+
for (const auto& file_temperature : file_temperatures) {
7007+
ASSERT_EQ(temperatures.at(file_temperature.first), file_temperature.second);
7008+
if (file_temperature.second == Temperature::kWarm) {
7009+
ASSERT_FALSE(has_only_one_warm_sst);
7010+
has_only_one_warm_sst = true;
7011+
}
7012+
}
7013+
ASSERT_TRUE(has_only_one_warm_sst);
7014+
Close();
7015+
}
7016+
7017+
TEST_F(DBTest2, CheckpointFileTemperature) {
7018+
std::shared_ptr<FileTemperatureTestFS> test_fs =
7019+
std::make_shared<FileTemperatureTestFS>(env_);
7020+
std::unique_ptr<Env> env(new CompositeEnvWrapper(env_, test_fs));
7021+
Options options = CurrentOptions();
7022+
options.bottommost_temperature = Temperature::kWarm;
7023+
options.level0_file_num_compaction_trigger = 2;
7024+
options.env = env.get();
7025+
Reopen(options);
7026+
7027+
// generate a bottommost file and a non-bottommost file
7028+
ASSERT_OK(Put("foo", "bar"));
7029+
ASSERT_OK(Put("bar", "bar"));
7030+
ASSERT_OK(Flush());
7031+
ASSERT_OK(Put("foo", "bar"));
7032+
ASSERT_OK(Put("bar", "bar"));
7033+
ASSERT_OK(Flush());
7034+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
7035+
ASSERT_OK(Put("foo", "bar"));
7036+
ASSERT_OK(Put("bar", "bar"));
7037+
ASSERT_OK(Flush());
7038+
auto size = GetSstSizeHelper(Temperature::kWarm);
7039+
ASSERT_GT(size, 0);
7040+
7041+
std::map<uint64_t, Temperature> temperatures;
7042+
std::vector<LiveFileStorageInfo> infos;
7043+
ASSERT_OK(
7044+
dbfull()->GetLiveFilesStorageInfo(LiveFilesStorageInfoOptions(), &infos));
7045+
for (auto info : infos) {
7046+
temperatures.emplace(info.file_number, info.temperature);
7047+
}
7048+
7049+
test_fs->ClearRequestedFileTemperatures();
7050+
Checkpoint* checkpoint;
7051+
ASSERT_OK(Checkpoint::Create(db_, &checkpoint));
7052+
ASSERT_OK(
7053+
checkpoint->CreateCheckpoint(dbname_ + kFilePathSeparator + "tempcp"));
7054+
7055+
// checking src file src_temperature hints: 2 sst files: 1 sst is kWarm,
7056+
// another is kUnknown
7057+
auto file_temperatures = test_fs->RequestedSstFileTemperatures();
7058+
ASSERT_EQ(file_temperatures.size(), 2);
7059+
bool has_only_one_warm_sst = false;
7060+
for (const auto& file_temperature : file_temperatures) {
7061+
ASSERT_EQ(temperatures.at(file_temperature.first), file_temperature.second);
7062+
if (file_temperature.second == Temperature::kWarm) {
7063+
ASSERT_FALSE(has_only_one_warm_sst);
7064+
has_only_one_warm_sst = true;
7065+
}
7066+
}
7067+
ASSERT_TRUE(has_only_one_warm_sst);
7068+
delete checkpoint;
7069+
Close();
7070+
}
69027071
#endif // ROCKSDB_LITE
69037072

69047073
// WAL recovery mode is WALRecoveryMode::kPointInTimeRecovery.

db/external_sst_file_ingestion_job.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,9 @@ Status ExternalSstFileIngestionJob::Prepare(
151151
TEST_SYNC_POINT_CALLBACK("ExternalSstFileIngestionJob::Prepare:CopyFile",
152152
nullptr);
153153
// CopyFile also sync the new file.
154-
status = CopyFile(fs_.get(), path_outside_db, path_inside_db, 0,
155-
db_options_.use_fsync, io_tracer_);
154+
status =
155+
CopyFile(fs_.get(), path_outside_db, path_inside_db, 0,
156+
db_options_.use_fsync, io_tracer_, Temperature::kUnknown);
156157
}
157158
TEST_SYNC_POINT("ExternalSstFileIngestionJob::Prepare:FileAdded");
158159
if (!status.ok()) {

db/import_column_family_job.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ Status ImportColumnFamilyJob::Prepare(uint64_t next_file_number,
100100
}
101101
}
102102
if (!hardlink_files) {
103-
status = CopyFile(fs_.get(), path_outside_db, path_inside_db, 0,
104-
db_options_.use_fsync, io_tracer_);
103+
status =
104+
CopyFile(fs_.get(), path_outside_db, path_inside_db, 0,
105+
db_options_.use_fsync, io_tracer_, Temperature::kUnknown);
105106
}
106107
if (!status.ok()) {
107108
break;

db_stress_tool/expected_state.cc

+5-4
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,9 @@ Status FileExpectedStateManager::SaveAtAndAfter(DB* db) {
269269

270270
// Populate a tempfile and then rename it to atomically create "<seqno>.state"
271271
// with contents from "LATEST.state"
272-
Status s =
273-
CopyFile(FileSystem::Default(), latest_file_path, state_file_temp_path,
274-
0 /* size */, false /* use_fsync */);
272+
Status s = CopyFile(FileSystem::Default(), latest_file_path,
273+
state_file_temp_path, 0 /* size */, false /* use_fsync */,
274+
nullptr /* io_tracer */, Temperature::kUnknown);
275275
if (s.ok()) {
276276
s = FileSystem::Default()->RenameFile(state_file_temp_path, state_file_path,
277277
IOOptions(), nullptr /* dbg */);
@@ -481,7 +481,8 @@ Status FileExpectedStateManager::Restore(DB* db) {
481481
// "LATEST.state". Start off by creating a tempfile so we can later make the
482482
// new "LATEST.state" appear atomically using `RenameFile()`.
483483
s = CopyFile(FileSystem::Default(), state_file_path, latest_file_temp_path,
484-
0 /* size */, false /* use_fsync */);
484+
0 /* size */, false /* use_fsync */, nullptr /* io_tracer */,
485+
Temperature::kUnknown);
485486
}
486487

487488
{

file/file_util.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ namespace ROCKSDB_NAMESPACE {
1919
// Utility function to copy a file up to a specified length
2020
IOStatus CopyFile(FileSystem* fs, const std::string& source,
2121
const std::string& destination, uint64_t size, bool use_fsync,
22-
const std::shared_ptr<IOTracer>& io_tracer) {
23-
const FileOptions soptions;
22+
const std::shared_ptr<IOTracer>& io_tracer,
23+
const Temperature temperature) {
24+
FileOptions soptions;
2425
IOStatus io_s;
2526
std::unique_ptr<SequentialFileReader> src_reader;
2627
std::unique_ptr<WritableFileWriter> dest_writer;
2728

2829
{
30+
soptions.temperature = temperature;
2931
std::unique_ptr<FSSequentialFile> srcfile;
3032
io_s = fs->NewSequentialFile(source, soptions, &srcfile, nullptr);
3133
if (!io_s.ok()) {

file/file_util.h

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@ namespace ROCKSDB_NAMESPACE {
2222
extern IOStatus CopyFile(FileSystem* fs, const std::string& source,
2323
const std::string& destination, uint64_t size,
2424
bool use_fsync,
25-
const std::shared_ptr<IOTracer>& io_tracer = nullptr);
25+
const std::shared_ptr<IOTracer>& io_tracer,
26+
const Temperature temperature);
2627
inline IOStatus CopyFile(const std::shared_ptr<FileSystem>& fs,
2728
const std::string& source,
2829
const std::string& destination, uint64_t size,
2930
bool use_fsync,
30-
const std::shared_ptr<IOTracer>& io_tracer = nullptr) {
31-
return CopyFile(fs.get(), source, destination, size, use_fsync, io_tracer);
31+
const std::shared_ptr<IOTracer>& io_tracer,
32+
const Temperature temperature) {
33+
return CopyFile(fs.get(), source, destination, size, use_fsync, io_tracer,
34+
temperature);
3235
}
33-
3436
extern IOStatus CreateFile(FileSystem* fs, const std::string& destination,
3537
const std::string& contents, bool use_fsync);
3638

0 commit comments

Comments
 (0)