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 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 7 // Use of this source code is governed by a BSD-style license that can be 8 // found in the LICENSE file. See the AUTHORS file for names of contributors. 9 10 #pragma once 11 12 #include <string> 13 #include <vector> 14 15 #include "db/log_writer.h" 16 #include "db/column_family.h" 17 18 namespace ROCKSDB_NAMESPACE { 19 20 class MemTable; 21 struct SuperVersion; 22 23 struct SuperVersionContext { 24 struct WriteStallNotification { 25 WriteStallInfo write_stall_info; 26 const ImmutableCFOptions* immutable_cf_options; 27 }; 28 29 autovector<SuperVersion*> superversions_to_free; 30 #ifndef ROCKSDB_DISABLE_STALL_NOTIFICATION 31 autovector<WriteStallNotification> write_stall_notifications; 32 #endif 33 std::unique_ptr<SuperVersion> 34 new_superversion; // if nullptr no new superversion 35 36 explicit SuperVersionContext(bool create_superversion = false) 37 : new_superversion(create_superversion ? new SuperVersion() : nullptr) {} 38 SuperVersionContextSuperVersionContext39 explicit SuperVersionContext(SuperVersionContext&& other) 40 : superversions_to_free(std::move(other.superversions_to_free)), 41 #ifndef ROCKSDB_DISABLE_STALL_NOTIFICATION 42 write_stall_notifications(std::move(other.write_stall_notifications)), 43 #endif 44 new_superversion(std::move(other.new_superversion)) { 45 } 46 NewSuperVersionSuperVersionContext47 void NewSuperVersion() { 48 new_superversion = std::unique_ptr<SuperVersion>(new SuperVersion()); 49 } 50 HaveSomethingToDeleteSuperVersionContext51 inline bool HaveSomethingToDelete() const { 52 #ifndef ROCKSDB_DISABLE_STALL_NOTIFICATION 53 return !superversions_to_free.empty() || 54 !write_stall_notifications.empty(); 55 #else 56 return !superversions_to_free.empty(); 57 #endif 58 } 59 PushWriteStallNotificationSuperVersionContext60 void PushWriteStallNotification( 61 WriteStallCondition old_cond, WriteStallCondition new_cond, 62 const std::string& name, const ImmutableCFOptions* ioptions) { 63 #if !defined(ROCKSDB_LITE) && !defined(ROCKSDB_DISABLE_STALL_NOTIFICATION) 64 WriteStallNotification notif; 65 notif.write_stall_info.cf_name = name; 66 notif.write_stall_info.condition.prev = old_cond; 67 notif.write_stall_info.condition.cur = new_cond; 68 notif.immutable_cf_options = ioptions; 69 write_stall_notifications.push_back(notif); 70 #else 71 (void)old_cond; 72 (void)new_cond; 73 (void)name; 74 (void)ioptions; 75 #endif // !defined(ROCKSDB_LITE) && !defined(ROCKSDB_DISABLE_STALL_NOTIFICATION) 76 } 77 CleanSuperVersionContext78 void Clean() { 79 #if !defined(ROCKSDB_LITE) && !defined(ROCKSDB_DISABLE_STALL_NOTIFICATION) 80 // notify listeners on changed write stall conditions 81 for (auto& notif : write_stall_notifications) { 82 for (auto& listener : notif.immutable_cf_options->listeners) { 83 listener->OnStallConditionsChanged(notif.write_stall_info); 84 } 85 } 86 write_stall_notifications.clear(); 87 #endif // !ROCKSDB_LITE 88 // free superversions 89 for (auto s : superversions_to_free) { 90 delete s; 91 } 92 superversions_to_free.clear(); 93 } 94 ~SuperVersionContextSuperVersionContext95 ~SuperVersionContext() { 96 #ifndef ROCKSDB_DISABLE_STALL_NOTIFICATION 97 assert(write_stall_notifications.empty()); 98 #endif 99 assert(superversions_to_free.empty()); 100 } 101 }; 102 103 struct JobContext { HaveSomethingToDeleteJobContext104 inline bool HaveSomethingToDelete() const { 105 return full_scan_candidate_files.size() || sst_delete_files.size() || 106 log_delete_files.size() || manifest_delete_files.size(); 107 } 108 HaveSomethingToCleanJobContext109 inline bool HaveSomethingToClean() const { 110 bool sv_have_sth = false; 111 for (const auto& sv_ctx : superversion_contexts) { 112 if (sv_ctx.HaveSomethingToDelete()) { 113 sv_have_sth = true; 114 break; 115 } 116 } 117 return memtables_to_free.size() > 0 || logs_to_free.size() > 0 || 118 sv_have_sth; 119 } 120 121 // Structure to store information for candidate files to delete. 122 struct CandidateFileInfo { 123 std::string file_name; 124 std::string file_path; CandidateFileInfoJobContext::CandidateFileInfo125 CandidateFileInfo(std::string name, std::string path) 126 : file_name(std::move(name)), file_path(std::move(path)) {} 127 bool operator==(const CandidateFileInfo& other) const { 128 return file_name == other.file_name && 129 file_path == other.file_path; 130 } 131 }; 132 133 // Unique job id 134 int job_id; 135 136 // a list of all files that we'll consider deleting 137 // (every once in a while this is filled up with all files 138 // in the DB directory) 139 // (filled only if we're doing full scan) 140 std::vector<CandidateFileInfo> full_scan_candidate_files; 141 142 // the list of all live sst files that cannot be deleted 143 std::vector<FileDescriptor> sst_live; 144 145 // a list of sst files that we need to delete 146 std::vector<ObsoleteFileInfo> sst_delete_files; 147 148 // a list of log files that we need to delete 149 std::vector<uint64_t> log_delete_files; 150 151 // a list of log files that we need to preserve during full purge since they 152 // will be reused later 153 std::vector<uint64_t> log_recycle_files; 154 155 // a list of manifest files that we need to delete 156 std::vector<std::string> manifest_delete_files; 157 158 // a list of memtables to be free 159 autovector<MemTable*> memtables_to_free; 160 161 // contexts for installing superversions for multiple column families 162 std::vector<SuperVersionContext> superversion_contexts; 163 164 autovector<log::Writer*> logs_to_free; 165 166 // the current manifest_file_number, log_number and prev_log_number 167 // that corresponds to the set of files in 'live'. 168 uint64_t manifest_file_number; 169 uint64_t pending_manifest_file_number; 170 uint64_t log_number; 171 uint64_t prev_log_number; 172 173 uint64_t min_pending_output = 0; 174 uint64_t prev_total_log_size = 0; 175 size_t num_alive_log_files = 0; 176 uint64_t size_log_to_delete = 0; 177 178 // Snapshot taken before flush/compaction job. 179 std::unique_ptr<ManagedSnapshot> job_snapshot; 180 181 explicit JobContext(int _job_id, bool create_superversion = false) { 182 job_id = _job_id; 183 manifest_file_number = 0; 184 pending_manifest_file_number = 0; 185 log_number = 0; 186 prev_log_number = 0; 187 superversion_contexts.emplace_back( 188 SuperVersionContext(create_superversion)); 189 } 190 191 // For non-empty JobContext Clean() has to be called at least once before 192 // before destruction (see asserts in ~JobContext()). Should be called with 193 // unlocked DB mutex. Destructor doesn't call Clean() to avoid accidentally 194 // doing potentially slow Clean() with locked DB mutex. CleanJobContext195 void Clean() { 196 // free superversions 197 for (auto& sv_context : superversion_contexts) { 198 sv_context.Clean(); 199 } 200 // free pending memtables 201 for (auto m : memtables_to_free) { 202 delete m; 203 } 204 for (auto l : logs_to_free) { 205 delete l; 206 } 207 208 memtables_to_free.clear(); 209 logs_to_free.clear(); 210 job_snapshot.reset(); 211 } 212 ~JobContextJobContext213 ~JobContext() { 214 assert(memtables_to_free.size() == 0); 215 assert(logs_to_free.size() == 0); 216 } 217 }; 218 219 } // namespace ROCKSDB_NAMESPACE 220