1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_BACKEND_IO_H_ 6 #define NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_BACKEND_IO_H_ 7 8 #include <stdint.h> 9 10 #include <string> 11 12 #include "base/memory/raw_ptr.h" 13 #include "base/memory/scoped_refptr.h" 14 #include "base/task/single_thread_task_runner.h" 15 #include "base/time/time.h" 16 #include "net/base/completion_once_callback.h" 17 #include "net/base/io_buffer.h" 18 #include "net/disk_cache/blockfile/in_flight_io.h" 19 #include "net/disk_cache/blockfile/rankings.h" 20 #include "net/disk_cache/disk_cache.h" 21 22 namespace base { 23 class Location; 24 } 25 26 namespace disk_cache { 27 28 class BackendImpl; 29 class EntryImpl; 30 class InFlightBackendIO; 31 32 // This class represents a single asynchronous disk cache IO operation while it 33 // is being bounced between threads. 34 class BackendIO : public BackgroundIO { 35 public: 36 BackendIO(InFlightBackendIO* controller, 37 BackendImpl* backend, 38 net::CompletionOnceCallback callback); 39 40 BackendIO(InFlightBackendIO* controller, 41 BackendImpl* backend, 42 EntryResultCallback callback); 43 44 BackendIO(InFlightBackendIO* controller, 45 BackendImpl* backend, 46 RangeResultCallback callback); 47 48 BackendIO(const BackendIO&) = delete; 49 BackendIO& operator=(const BackendIO&) = delete; 50 51 // Runs the actual operation on the background thread. 52 void ExecuteOperation(); 53 54 // Callback implementation. 55 void OnIOComplete(int result); 56 57 // Called when we are finishing this operation. If |cancel| is true, the user 58 // callback will not be invoked. 59 void OnDone(bool cancel); 60 61 // Returns true if this operation is directed to an entry (vs. the backend). 62 bool IsEntryOperation(); 63 has_callback()64 bool has_callback() const { return !callback_.is_null(); } 65 void RunCallback(int result); 66 has_entry_result_callback()67 bool has_entry_result_callback() const { 68 return !entry_result_callback_.is_null(); 69 } 70 void RunEntryResultCallback(); 71 has_range_result_callback()72 bool has_range_result_callback() const { 73 return !range_result_callback_.is_null(); 74 } 75 void RunRangeResultCallback(); 76 77 // The operations we proxy: 78 void Init(); 79 void OpenOrCreateEntry(const std::string& key); 80 void OpenEntry(const std::string& key); 81 void CreateEntry(const std::string& key); 82 void DoomEntry(const std::string& key); 83 void DoomAllEntries(); 84 void DoomEntriesBetween(const base::Time initial_time, 85 const base::Time end_time); 86 void DoomEntriesSince(const base::Time initial_time); 87 void CalculateSizeOfAllEntries(); 88 void OpenNextEntry(Rankings::Iterator* iterator); 89 void EndEnumeration(std::unique_ptr<Rankings::Iterator> iterator); 90 void OnExternalCacheHit(const std::string& key); 91 void CloseEntryImpl(EntryImpl* entry); 92 void DoomEntryImpl(EntryImpl* entry); 93 void FlushQueue(); // Dummy operation. 94 void RunTask(base::OnceClosure task); 95 void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 96 int buf_len); 97 void WriteData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 98 int buf_len, bool truncate); 99 void ReadSparseData(EntryImpl* entry, 100 int64_t offset, 101 net::IOBuffer* buf, 102 int buf_len); 103 void WriteSparseData(EntryImpl* entry, 104 int64_t offset, 105 net::IOBuffer* buf, 106 int buf_len); 107 void GetAvailableRange(EntryImpl* entry, int64_t offset, int len); 108 void CancelSparseIO(EntryImpl* entry); 109 void ReadyForSparseIO(EntryImpl* entry); 110 111 private: 112 BackendIO(InFlightBackendIO* controller, BackendImpl* backend); 113 114 // There are two types of operations to proxy: regular backend operations are 115 // executed sequentially (queued by the message loop). On the other hand, 116 // operations targeted to a given entry can be long lived and support multiple 117 // simultaneous users (multiple reads or writes to the same entry), and they 118 // are subject to throttling, so we keep an explicit queue. 119 enum Operation { 120 OP_NONE = 0, 121 OP_INIT, 122 OP_OPEN_OR_CREATE, 123 OP_OPEN, 124 OP_CREATE, 125 OP_DOOM, 126 OP_DOOM_ALL, 127 OP_DOOM_BETWEEN, 128 OP_DOOM_SINCE, 129 OP_SIZE_ALL, 130 OP_OPEN_NEXT, 131 OP_END_ENUMERATION, 132 OP_ON_EXTERNAL_CACHE_HIT, 133 OP_CLOSE_ENTRY, 134 OP_DOOM_ENTRY, 135 OP_FLUSH_QUEUE, 136 OP_RUN_TASK, 137 OP_MAX_BACKEND, 138 OP_READ, 139 OP_WRITE, 140 OP_READ_SPARSE, 141 OP_WRITE_SPARSE, 142 OP_GET_RANGE, 143 OP_CANCEL_IO, 144 OP_IS_READY 145 }; 146 147 ~BackendIO() override; 148 149 // Returns true if this operation returns an entry. 150 bool ReturnsEntry(); 151 152 // Returns the time that has passed since the operation was created. 153 base::TimeDelta ElapsedTime() const; 154 155 void ExecuteBackendOperation(); 156 void ExecuteEntryOperation(); 157 158 raw_ptr<BackendImpl, DanglingUntriaged> backend_; 159 net::CompletionOnceCallback callback_; 160 Operation operation_ = OP_NONE; 161 162 // Used for ops that open or create entries. 163 EntryResultCallback entry_result_callback_; 164 // if set, already has the user's ref added. 165 raw_ptr<EntryImpl, DanglingUntriaged> out_entry_ = nullptr; 166 bool out_entry_opened_ = false; 167 168 // For GetAvailableRange 169 RangeResultCallback range_result_callback_; 170 RangeResult range_result_; 171 172 // The arguments of all the operations we proxy: 173 std::string key_; 174 base::Time initial_time_; 175 base::Time end_time_; 176 raw_ptr<Rankings::Iterator> iterator_ = nullptr; 177 std::unique_ptr<Rankings::Iterator> scoped_iterator_; 178 raw_ptr<EntryImpl, DanglingUntriaged> entry_ = nullptr; 179 int index_ = 0; 180 int offset_ = 0; 181 scoped_refptr<net::IOBuffer> buf_; 182 int buf_len_ = 0; 183 bool truncate_ = false; 184 int64_t offset64_ = 0; 185 base::TimeTicks start_time_; 186 base::OnceClosure task_; 187 188 scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_; 189 }; 190 191 // The specialized controller that keeps track of current operations. 192 class InFlightBackendIO : public InFlightIO { 193 public: 194 InFlightBackendIO( 195 BackendImpl* backend, 196 const scoped_refptr<base::SingleThreadTaskRunner>& background_thread); 197 198 InFlightBackendIO(const InFlightBackendIO&) = delete; 199 InFlightBackendIO& operator=(const InFlightBackendIO&) = delete; 200 201 ~InFlightBackendIO() override; 202 203 // Proxied operations. 204 void Init(net::CompletionOnceCallback callback); 205 void OpenOrCreateEntry(const std::string& key, EntryResultCallback callback); 206 void OpenEntry(const std::string& key, EntryResultCallback callback); 207 void CreateEntry(const std::string& key, EntryResultCallback callback); 208 void DoomEntry(const std::string& key, net::CompletionOnceCallback callback); 209 void DoomAllEntries(net::CompletionOnceCallback callback); 210 void DoomEntriesBetween(const base::Time initial_time, 211 const base::Time end_time, 212 net::CompletionOnceCallback callback); 213 void DoomEntriesSince(const base::Time initial_time, 214 net::CompletionOnceCallback callback); 215 void CalculateSizeOfAllEntries(net::CompletionOnceCallback callback); 216 void OpenNextEntry(Rankings::Iterator* iterator, 217 EntryResultCallback callback); 218 void EndEnumeration(std::unique_ptr<Rankings::Iterator> iterator); 219 void OnExternalCacheHit(const std::string& key); 220 void CloseEntryImpl(EntryImpl* entry); 221 void DoomEntryImpl(EntryImpl* entry); 222 void FlushQueue(net::CompletionOnceCallback callback); 223 void RunTask(base::OnceClosure task, net::CompletionOnceCallback callback); 224 void ReadData(EntryImpl* entry, 225 int index, 226 int offset, 227 net::IOBuffer* buf, 228 int buf_len, 229 net::CompletionOnceCallback callback); 230 void WriteData(EntryImpl* entry, 231 int index, 232 int offset, 233 net::IOBuffer* buf, 234 int buf_len, 235 bool truncate, 236 net::CompletionOnceCallback callback); 237 void ReadSparseData(EntryImpl* entry, 238 int64_t offset, 239 net::IOBuffer* buf, 240 int buf_len, 241 net::CompletionOnceCallback callback); 242 void WriteSparseData(EntryImpl* entry, 243 int64_t offset, 244 net::IOBuffer* buf, 245 int buf_len, 246 net::CompletionOnceCallback callback); 247 void GetAvailableRange(EntryImpl* entry, 248 int64_t offset, 249 int len, 250 RangeResultCallback callback); 251 void CancelSparseIO(EntryImpl* entry); 252 void ReadyForSparseIO(EntryImpl* entry, net::CompletionOnceCallback callback); 253 254 // Blocks until all operations are cancelled or completed. 255 void WaitForPendingIO(); 256 background_thread()257 scoped_refptr<base::SingleThreadTaskRunner> background_thread() { 258 return background_thread_; 259 } 260 261 // Returns true if the current sequence is the background thread. BackgroundIsCurrentSequence()262 bool BackgroundIsCurrentSequence() { 263 return background_thread_->RunsTasksInCurrentSequence(); 264 } 265 266 base::WeakPtr<InFlightBackendIO> GetWeakPtr(); 267 268 protected: 269 void OnOperationComplete(BackgroundIO* operation, bool cancel) override; 270 271 private: 272 void PostOperation(const base::Location& from_here, BackendIO* operation); 273 raw_ptr<BackendImpl> backend_; 274 scoped_refptr<base::SingleThreadTaskRunner> background_thread_; 275 base::WeakPtrFactory<InFlightBackendIO> ptr_factory_{this}; 276 }; 277 278 } // namespace disk_cache 279 280 #endif // NET_DISK_CACHE_BLOCKFILE_IN_FLIGHT_BACKEND_IO_H_ 281