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_NAMESPACE { 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 MaybeCreateBackgroundThread(); 49 } 50 51 // Mark file as trash directory and schedule it's deletion. If force_bg is 52 // set, it forces the file to always be deleted in the background thread, 53 // except when rate limiting is disabled 54 Status DeleteFile(const std::string& fname, const std::string& dir_to_sync, 55 const bool force_bg = false); 56 57 // Wait for all files being deleteing in the background to finish or for 58 // destructor to be called. 59 void WaitForEmptyTrash(); 60 61 // Return a map containing errors that happened in BackgroundEmptyTrash 62 // file_path => error status 63 std::map<std::string, Status> GetBackgroundErrors(); 64 GetTotalTrashSize()65 uint64_t GetTotalTrashSize() { return total_trash_size_.load(); } 66 67 // Return trash/DB size ratio where new files will be deleted immediately GetMaxTrashDBRatio()68 double GetMaxTrashDBRatio() { 69 return max_trash_db_ratio_.load(); 70 } 71 72 // Update trash/DB size ratio where new files will be deleted immediately SetMaxTrashDBRatio(double r)73 void SetMaxTrashDBRatio(double r) { 74 assert(r >= 0); 75 max_trash_db_ratio_.store(r); 76 } 77 78 static const std::string kTrashExtension; 79 static bool IsTrashFile(const std::string& file_path); 80 81 // Check if there are any .trash filse in path, and schedule their deletion 82 // Or delete immediately if sst_file_manager is nullptr 83 static Status CleanupDirectory(Env* env, SstFileManagerImpl* sfm, 84 const std::string& path); 85 86 private: 87 Status MarkAsTrash(const std::string& file_path, std::string* path_in_trash); 88 89 Status DeleteTrashFile(const std::string& path_in_trash, 90 const std::string& dir_to_sync, 91 uint64_t* deleted_bytes, bool* is_complete); 92 93 void BackgroundEmptyTrash(); 94 95 void MaybeCreateBackgroundThread(); 96 97 Env* env_; 98 FileSystem* fs_; 99 100 // total size of trash files 101 std::atomic<uint64_t> total_trash_size_; 102 // Maximum number of bytes that should be deleted per second 103 std::atomic<int64_t> rate_bytes_per_sec_; 104 // Mutex to protect queue_, pending_files_, bg_errors_, closing_ 105 InstrumentedMutex mu_; 106 107 struct FileAndDir { FileAndDirFileAndDir108 FileAndDir(const std::string& f, const std::string& d) : fname(f), dir(d) {} 109 std::string fname; 110 std::string dir; // empty will be skipped. 111 }; 112 113 // Queue of trash files that need to be deleted 114 std::queue<FileAndDir> queue_; 115 // Number of trash files that are waiting to be deleted 116 int32_t pending_files_; 117 uint64_t bytes_max_delete_chunk_; 118 // Errors that happened in BackgroundEmptyTrash (file_path => error) 119 std::map<std::string, Status> bg_errors_; 120 121 bool num_link_error_printed_ = false; 122 // Set to true in ~DeleteScheduler() to force BackgroundEmptyTrash to stop 123 bool closing_; 124 // Condition variable signaled in these conditions 125 // - pending_files_ value change from 0 => 1 126 // - pending_files_ value change from 1 => 0 127 // - closing_ value is set to true 128 InstrumentedCondVar cv_; 129 // Background thread running BackgroundEmptyTrash 130 std::unique_ptr<port::Thread> bg_thread_; 131 // Mutex to protect threads from file name conflicts 132 InstrumentedMutex file_move_mu_; 133 Logger* info_log_; 134 SstFileManagerImpl* sst_file_manager_; 135 // If the trash size constitutes for more than this fraction of the total DB 136 // size we will start deleting new files passed to DeleteScheduler 137 // immediately 138 std::atomic<double> max_trash_db_ratio_; 139 static const uint64_t kMicrosInSecond = 1000 * 1000LL; 140 }; 141 142 } // namespace ROCKSDB_NAMESPACE 143 144 #endif // ROCKSDB_LITE 145