1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 #pragma once 7 8 #ifndef ROCKSDB_LITE 9 10 #include <map> 11 #include <queue> 12 #include <string> 13 #include <thread> 14 15 #include "monitoring/instrumented_mutex.h" 16 #include "port/port.h" 17 18 #include "rocksdb/file_system.h" 19 #include "rocksdb/status.h" 20 21 namespace rocksdb { 22 23 class Env; 24 class Logger; 25 class SstFileManagerImpl; 26 27 // DeleteScheduler allows the DB to enforce a rate limit on file deletion, 28 // Instead of deleteing files immediately, files are marked as trash 29 // and deleted in a background thread that apply sleep penlty between deletes 30 // if they are happening in a rate faster than rate_bytes_per_sec, 31 // 32 // Rate limiting can be turned off by setting rate_bytes_per_sec = 0, In this 33 // case DeleteScheduler will delete files immediately. 34 class DeleteScheduler { 35 public: 36 DeleteScheduler(Env* env, FileSystem* fs, int64_t rate_bytes_per_sec, 37 Logger* info_log, SstFileManagerImpl* sst_file_manager, 38 double max_trash_db_ratio, uint64_t bytes_max_delete_chunk); 39 40 ~DeleteScheduler(); 41 42 // Return delete rate limit in bytes per second GetRateBytesPerSecond()43 int64_t GetRateBytesPerSecond() { return rate_bytes_per_sec_.load(); } 44 45 // Set delete rate limit in bytes per second SetRateBytesPerSecond(int64_t bytes_per_sec)46 void SetRateBytesPerSecond(int64_t bytes_per_sec) { 47 rate_bytes_per_sec_.store(bytes_per_sec); 48 } 49 50 // Mark file as trash directory and schedule it's deletion. If force_bg is 51 // set, it forces the file to always be deleted in the background thread, 52 // except when rate limiting is disabled 53 Status DeleteFile(const std::string& fname, const std::string& dir_to_sync, 54 const bool force_bg = false); 55 56 // Wait for all files being deleteing in the background to finish or for 57 // destructor to be called. 58 void WaitForEmptyTrash(); 59 60 // Return a map containing errors that happened in BackgroundEmptyTrash 61 // file_path => error status 62 std::map<std::string, Status> GetBackgroundErrors(); 63 GetTotalTrashSize()64 uint64_t GetTotalTrashSize() { return total_trash_size_.load(); } 65 66 // Return trash/DB size ratio where new files will be deleted immediately GetMaxTrashDBRatio()67 double GetMaxTrashDBRatio() { 68 return max_trash_db_ratio_.load(); 69 } 70 71 // Update trash/DB size ratio where new files will be deleted immediately SetMaxTrashDBRatio(double r)72 void SetMaxTrashDBRatio(double r) { 73 assert(r >= 0); 74 max_trash_db_ratio_.store(r); 75 } 76 77 static const std::string kTrashExtension; 78 static bool IsTrashFile(const std::string& file_path); 79 80 // Check if there are any .trash filse in path, and schedule their deletion 81 // Or delete immediately if sst_file_manager is nullptr 82 static Status CleanupDirectory(Env* env, SstFileManagerImpl* sfm, 83 const std::string& path); 84 85 private: 86 Status MarkAsTrash(const std::string& file_path, std::string* path_in_trash); 87 88 Status DeleteTrashFile(const std::string& path_in_trash, 89 const std::string& dir_to_sync, 90 uint64_t* deleted_bytes, bool* is_complete); 91 92 void BackgroundEmptyTrash(); 93 94 Env* env_; 95 FileSystem* fs_; 96 97 // total size of trash files 98 std::atomic<uint64_t> total_trash_size_; 99 // Maximum number of bytes that should be deleted per second 100 std::atomic<int64_t> rate_bytes_per_sec_; 101 // Mutex to protect queue_, pending_files_, bg_errors_, closing_ 102 InstrumentedMutex mu_; 103 104 struct FileAndDir { FileAndDirFileAndDir105 FileAndDir(const std::string& f, const std::string& d) : fname(f), dir(d) {} 106 std::string fname; 107 std::string dir; // empty will be skipped. 108 }; 109 110 // Queue of trash files that need to be deleted 111 std::queue<FileAndDir> queue_; 112 // Number of trash files that are waiting to be deleted 113 int32_t pending_files_; 114 uint64_t bytes_max_delete_chunk_; 115 // Errors that happened in BackgroundEmptyTrash (file_path => error) 116 std::map<std::string, Status> bg_errors_; 117 118 bool num_link_error_printed_ = false; 119 // Set to true in ~DeleteScheduler() to force BackgroundEmptyTrash to stop 120 bool closing_; 121 // Condition variable signaled in these conditions 122 // - pending_files_ value change from 0 => 1 123 // - pending_files_ value change from 1 => 0 124 // - closing_ value is set to true 125 InstrumentedCondVar cv_; 126 // Background thread running BackgroundEmptyTrash 127 std::unique_ptr<port::Thread> bg_thread_; 128 // Mutex to protect threads from file name conflicts 129 InstrumentedMutex file_move_mu_; 130 Logger* info_log_; 131 SstFileManagerImpl* sst_file_manager_; 132 // If the trash size constitutes for more than this fraction of the total DB 133 // size we will start deleting new files passed to DeleteScheduler 134 // immediately 135 std::atomic<double> max_trash_db_ratio_; 136 static const uint64_t kMicrosInSecond = 1000 * 1000LL; 137 }; 138 139 } // namespace rocksdb 140 141 #endif // ROCKSDB_LITE 142