Summary: Add a new class SstFileTracker that will be notified whenever a DB add/delete/move and sst file, it will also replace DeleteScheduler SstFileTracker can be used later to abort writes when we exceed a specific size Test Plan: unit tests Reviewers: rven, anthony, yhchiang, sdong Reviewed By: sdong Subscribers: igor, lovro, march, dhruba Differential Revision: https://reviews.facebook.net/D50469main
parent
45768ade4f
commit
d6c838f1e1
@ -1,67 +0,0 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once |
||||
|
||||
#include <map> |
||||
#include <string> |
||||
#include <memory> |
||||
|
||||
#include "rocksdb/status.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class Env; |
||||
class Logger; |
||||
|
||||
// DeleteScheduler allow the DB to enforce a rate limit on file deletion,
|
||||
// Instead of deleteing files immediately, files are moved to trash_dir
|
||||
// and deleted in a background thread that apply sleep penlty between deletes
|
||||
// if they are happening in a rate faster than rate_bytes_per_sec,
|
||||
//
|
||||
// Rate limiting can be turned off by setting rate_bytes_per_sec = 0, In this
|
||||
// case DeleteScheduler will delete files immediately.
|
||||
class DeleteScheduler { |
||||
public: |
||||
virtual ~DeleteScheduler() {} |
||||
|
||||
// Return delete rate limit in bytes per second
|
||||
virtual int64_t GetRateBytesPerSecond() = 0; |
||||
|
||||
// Move file to trash directory and schedule it's deletion
|
||||
virtual Status DeleteFile(const std::string& fname) = 0; |
||||
|
||||
// Return a map containing errors that happened in the background thread
|
||||
// file_path => error status
|
||||
virtual std::map<std::string, Status> GetBackgroundErrors() = 0; |
||||
|
||||
// Wait for all files being deleteing in the background to finish or for
|
||||
// destructor to be called.
|
||||
virtual void WaitForEmptyTrash() = 0; |
||||
}; |
||||
|
||||
// Create a new DeleteScheduler that can be shared among multiple RocksDB
|
||||
// instances to control the file deletion rate.
|
||||
//
|
||||
// @env: Pointer to Env object, please see "rocksdb/env.h".
|
||||
// @trash_dir: Path to the directory where deleted files will be moved into
|
||||
// to be deleted in a background thread while applying rate limiting. If this
|
||||
// directory dont exist, it will be created. This directory should not be
|
||||
// used by any other process or any other DeleteScheduler.
|
||||
// @rate_bytes_per_sec: How many bytes should be deleted per second, If this
|
||||
// value is set to 1024 (1 Kb / sec) and we deleted a file of size 4 Kb
|
||||
// in 1 second, we will wait for another 3 seconds before we delete other
|
||||
// files, Set to 0 to disable rate limiting.
|
||||
// @info_log: If not nullptr, info_log will be used to log errors.
|
||||
// @delete_exisitng_trash: If set to true, the newly created DeleteScheduler
|
||||
// will delete files that already exist in trash_dir.
|
||||
// @status: If not nullptr, status will contain any errors that happened during
|
||||
// creating the missing trash_dir or deleting existing files in trash.
|
||||
extern DeleteScheduler* NewDeleteScheduler( |
||||
Env* env, const std::string& trash_dir, int64_t rate_bytes_per_sec, |
||||
std::shared_ptr<Logger> info_log = nullptr, |
||||
bool delete_exisitng_trash = true, Status* status = nullptr); |
||||
|
||||
} // namespace rocksdb
|
@ -0,0 +1,64 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
#include <unordered_map> |
||||
|
||||
#include "rocksdb/status.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class Env; |
||||
class Logger; |
||||
|
||||
// SstFileManager is used to track SST files in the DB and control there
|
||||
// deletion rate.
|
||||
// All SstFileManager public functions are thread-safe.
|
||||
class SstFileManager { |
||||
public: |
||||
virtual ~SstFileManager() {} |
||||
|
||||
// Return the total size of all tracked files.
|
||||
// thread-safe
|
||||
virtual uint64_t GetTotalSize() = 0; |
||||
|
||||
// Return a map containing all tracked files and there corresponding sizes.
|
||||
// thread-safe
|
||||
virtual std::unordered_map<std::string, uint64_t> GetTrackedFiles() = 0; |
||||
|
||||
// Return delete rate limit in bytes per second.
|
||||
// thread-safe
|
||||
virtual int64_t GetDeleteRateBytesPerSecond() = 0; |
||||
}; |
||||
|
||||
// Create a new SstFileManager that can be shared among multiple RocksDB
|
||||
// instances to track SST file and control there deletion rate.
|
||||
//
|
||||
// @param env: Pointer to Env object, please see "rocksdb/env.h".
|
||||
// @param info_log: If not nullptr, info_log will be used to log errors.
|
||||
//
|
||||
// == Deletion rate limiting specific arguments ==
|
||||
// @param trash_dir: Path to the directory where deleted files will be moved
|
||||
// to be deleted in a background thread while applying rate limiting. If this
|
||||
// directory dont exist, it will be created. This directory should not be
|
||||
// used by any other process or any other SstFileManager, Set to "" to
|
||||
// disable deletion rate limiting.
|
||||
// @param rate_bytes_per_sec: How many bytes should be deleted per second, If
|
||||
// this value is set to 1024 (1 Kb / sec) and we deleted a file of size 4 Kb
|
||||
// in 1 second, we will wait for another 3 seconds before we delete other
|
||||
// files, Set to 0 to disable deletion rate limiting.
|
||||
// @param delete_exisitng_trash: If set to true, the newly created
|
||||
// SstFileManager will delete files that already exist in trash_dir.
|
||||
// @param status: If not nullptr, status will contain any errors that happened
|
||||
// during creating the missing trash_dir or deleting existing files in trash.
|
||||
extern SstFileManager* NewSstFileManager( |
||||
Env* env, std::shared_ptr<Logger> info_log = nullptr, |
||||
std::string trash_dir = "", int64_t rate_bytes_per_sec = 0, |
||||
bool delete_exisitng_trash = true, Status* status = nullptr); |
||||
|
||||
} // namespace rocksdb
|
@ -0,0 +1,143 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#include "util/sst_file_manager_impl.h" |
||||
|
||||
#include <vector> |
||||
|
||||
#include "port/port.h" |
||||
#include "rocksdb/env.h" |
||||
#include "util/mutexlock.h" |
||||
#include "util/sync_point.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
SstFileManagerImpl::SstFileManagerImpl(Env* env, std::shared_ptr<Logger> logger, |
||||
const std::string& trash_dir, |
||||
int64_t rate_bytes_per_sec) |
||||
: env_(env), |
||||
logger_(logger), |
||||
total_files_size_(0), |
||||
delete_scheduler_(env, trash_dir, rate_bytes_per_sec, logger.get(), |
||||
this) {} |
||||
|
||||
SstFileManagerImpl::~SstFileManagerImpl() {} |
||||
|
||||
Status SstFileManagerImpl::OnAddFile(const std::string& file_path) { |
||||
uint64_t file_size; |
||||
Status s = env_->GetFileSize(file_path, &file_size); |
||||
if (s.ok()) { |
||||
MutexLock l(&mu_); |
||||
OnAddFileImpl(file_path, file_size); |
||||
} |
||||
TEST_SYNC_POINT("SstFileManagerImpl::OnAddFile"); |
||||
return s; |
||||
} |
||||
|
||||
Status SstFileManagerImpl::OnDeleteFile(const std::string& file_path) { |
||||
{ |
||||
MutexLock l(&mu_); |
||||
OnDeleteFileImpl(file_path); |
||||
} |
||||
TEST_SYNC_POINT("SstFileManagerImpl::OnDeleteFile"); |
||||
return Status::OK(); |
||||
} |
||||
|
||||
Status SstFileManagerImpl::OnMoveFile(const std::string& old_path, |
||||
const std::string& new_path) { |
||||
{ |
||||
MutexLock l(&mu_); |
||||
OnAddFileImpl(new_path, tracked_files_[old_path]); |
||||
OnDeleteFileImpl(old_path); |
||||
} |
||||
TEST_SYNC_POINT("SstFileManagerImpl::OnMoveFile"); |
||||
return Status::OK(); |
||||
} |
||||
|
||||
uint64_t SstFileManagerImpl::GetTotalSize() { |
||||
MutexLock l(&mu_); |
||||
return total_files_size_; |
||||
} |
||||
|
||||
std::unordered_map<std::string, uint64_t> |
||||
SstFileManagerImpl::GetTrackedFiles() { |
||||
MutexLock l(&mu_); |
||||
return tracked_files_; |
||||
} |
||||
|
||||
int64_t SstFileManagerImpl::GetDeleteRateBytesPerSecond() { |
||||
return delete_scheduler_.GetRateBytesPerSecond(); |
||||
} |
||||
|
||||
Status SstFileManagerImpl::ScheduleFileDeletion(const std::string& file_path) { |
||||
return delete_scheduler_.DeleteFile(file_path); |
||||
} |
||||
|
||||
void SstFileManagerImpl::WaitForEmptyTrash() { |
||||
delete_scheduler_.WaitForEmptyTrash(); |
||||
} |
||||
|
||||
void SstFileManagerImpl::OnAddFileImpl(const std::string& file_path, |
||||
uint64_t file_size) { |
||||
auto tracked_file = tracked_files_.find(file_path); |
||||
if (tracked_file != tracked_files_.end()) { |
||||
// File was added before, we will just update the size
|
||||
total_files_size_ -= tracked_file->second; |
||||
total_files_size_ += file_size; |
||||
} else { |
||||
total_files_size_ += file_size; |
||||
} |
||||
tracked_files_[file_path] = file_size; |
||||
} |
||||
|
||||
void SstFileManagerImpl::OnDeleteFileImpl(const std::string& file_path) { |
||||
auto tracked_file = tracked_files_.find(file_path); |
||||
if (tracked_file == tracked_files_.end()) { |
||||
// File is not tracked
|
||||
return; |
||||
} |
||||
|
||||
total_files_size_ -= tracked_file->second; |
||||
tracked_files_.erase(tracked_file); |
||||
} |
||||
|
||||
SstFileManager* NewSstFileManager(Env* env, std::shared_ptr<Logger> info_log, |
||||
std::string trash_dir, |
||||
int64_t rate_bytes_per_sec, |
||||
bool delete_exisitng_trash, Status* status) { |
||||
SstFileManagerImpl* res = |
||||
new SstFileManagerImpl(env, info_log, trash_dir, rate_bytes_per_sec); |
||||
|
||||
Status s; |
||||
if (trash_dir != "" && rate_bytes_per_sec > 0) { |
||||
s = env->CreateDirIfMissing(trash_dir); |
||||
if (s.ok() && delete_exisitng_trash) { |
||||
std::vector<std::string> files_in_trash; |
||||
s = env->GetChildren(trash_dir, &files_in_trash); |
||||
if (s.ok()) { |
||||
for (const std::string& trash_file : files_in_trash) { |
||||
if (trash_file == "." || trash_file == "..") { |
||||
continue; |
||||
} |
||||
|
||||
std::string path_in_trash = trash_dir + "/" + trash_file; |
||||
res->OnAddFile(path_in_trash); |
||||
Status file_delete = res->ScheduleFileDeletion(path_in_trash); |
||||
if (s.ok() && !file_delete.ok()) { |
||||
s = file_delete; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (status) { |
||||
*status = s; |
||||
} |
||||
|
||||
return res; |
||||
} |
||||
|
||||
} // namespace rocksdb
|
@ -0,0 +1,77 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
|
||||
#include "port/port.h" |
||||
|
||||
#include "rocksdb/sst_file_manager.h" |
||||
#include "util/delete_scheduler.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class Env; |
||||
class Logger; |
||||
|
||||
// SstFileManager is used to track SST files in the DB and control there
|
||||
// deletion rate.
|
||||
// All SstFileManager public functions are thread-safe.
|
||||
class SstFileManagerImpl : public SstFileManager { |
||||
public: |
||||
explicit SstFileManagerImpl(Env* env, std::shared_ptr<Logger> logger, |
||||
const std::string& trash_dir, |
||||
int64_t rate_bytes_per_sec); |
||||
|
||||
~SstFileManagerImpl(); |
||||
|
||||
// DB will call OnAddFile whenever a new sst file is added.
|
||||
Status OnAddFile(const std::string& file_path); |
||||
|
||||
// DB will call OnDeleteFile whenever an sst file is deleted.
|
||||
Status OnDeleteFile(const std::string& file_path); |
||||
|
||||
// DB will call OnMoveFile whenever an sst file is move to a new path.
|
||||
Status OnMoveFile(const std::string& old_path, const std::string& new_path); |
||||
|
||||
// Return the total size of all tracked files.
|
||||
uint64_t GetTotalSize() override; |
||||
|
||||
// Return a map containing all tracked files and there corresponding sizes.
|
||||
std::unordered_map<std::string, uint64_t> GetTrackedFiles() override; |
||||
|
||||
// Return delete rate limit in bytes per second.
|
||||
virtual int64_t GetDeleteRateBytesPerSecond() override; |
||||
|
||||
// Move file to trash directory and schedule it's deletion.
|
||||
virtual Status ScheduleFileDeletion(const std::string& file_path); |
||||
|
||||
// Wait for all files being deleteing in the background to finish or for
|
||||
// destructor to be called.
|
||||
virtual void WaitForEmptyTrash(); |
||||
|
||||
private: |
||||
// REQUIRES: mutex locked
|
||||
void OnAddFileImpl(const std::string& file_path, uint64_t file_size); |
||||
// REQUIRES: mutex locked
|
||||
void OnDeleteFileImpl(const std::string& file_path); |
||||
|
||||
Env* env_; |
||||
std::shared_ptr<Logger> logger_; |
||||
// Mutex to protect tracked_files_, total_files_size_
|
||||
port::Mutex mu_; |
||||
// The summation of the sizes of all files in tracked_files_ map
|
||||
uint64_t total_files_size_; |
||||
// A map containing all tracked files and there sizes
|
||||
// file_path => file_size
|
||||
std::unordered_map<std::string, uint64_t> tracked_files_; |
||||
// DeleteScheduler used to throttle file deletition, if SstFileManagerImpl was
|
||||
// created with rate_bytes_per_sec == 0 or trash_dir == "", delete_scheduler_
|
||||
// rate limiting will be disabled and will simply delete the files.
|
||||
DeleteScheduler delete_scheduler_; |
||||
}; |
||||
|
||||
} // namespace rocksdb
|
Loading…
Reference in new issue