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_SPARSE_CONTROL_H_ 6 #define NET_DISK_CACHE_BLOCKFILE_SPARSE_CONTROL_H_ 7 8 #include <stdint.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/compiler_specific.h" 14 #include "base/memory/raw_ptr.h" 15 #include "net/base/completion_once_callback.h" 16 #include "net/disk_cache/blockfile/bitmap.h" 17 #include "net/disk_cache/blockfile/disk_format.h" 18 #include "net/disk_cache/disk_cache.h" 19 20 namespace net { 21 class IOBuffer; 22 class DrainableIOBuffer; 23 } 24 25 namespace disk_cache { 26 27 class EntryImpl; 28 29 // This class provides support for the sparse capabilities of the disk cache. 30 // Basically, sparse IO is directed from EntryImpl to this class, and we split 31 // the operation into multiple small pieces, sending each one to the 32 // appropriate entry. An instance of this class is associated with each entry 33 // used directly for sparse operations (the entry passed in to the constructor). 34 class SparseControl { 35 public: 36 typedef net::CompletionOnceCallback CompletionOnceCallback; 37 38 // The operation to perform. 39 enum SparseOperation { 40 kNoOperation, 41 kReadOperation, 42 kWriteOperation, 43 kGetRangeOperation 44 }; 45 46 explicit SparseControl(EntryImpl* entry); 47 48 SparseControl(const SparseControl&) = delete; 49 SparseControl& operator=(const SparseControl&) = delete; 50 51 ~SparseControl(); 52 53 // Initializes the object for the current entry. If this entry already stores 54 // sparse data, or can be used to do it, it updates the relevant information 55 // on disk and returns net::OK. Otherwise it returns a net error code. 56 int Init(); 57 58 // Performs a quick test to see if the entry is sparse or not, without 59 // generating disk IO (so the answer provided is only a best effort). 60 bool CouldBeSparse() const; 61 62 // Performs an actual sparse read or write operation for this entry. |op| is 63 // the operation to perform, |offset| is the desired sparse offset, |buf| and 64 // |buf_len| specify the actual data to use and |callback| is the callback 65 // to use for asynchronous operations. See the description of the Read / 66 // WriteSparseData for details about the arguments. The return value is the 67 // number of bytes read or written, or a net error code. 68 int StartIO(SparseOperation op, 69 int64_t offset, 70 net::IOBuffer* buf, 71 int buf_len, 72 CompletionOnceCallback callback); 73 74 // Implements Entry::GetAvailableRange(). 75 RangeResult GetAvailableRange(int64_t offset, int len); 76 77 // Cancels the current sparse operation (if any). 78 void CancelIO(); 79 80 // Returns OK if the entry can be used for new IO or ERR_IO_PENDING if we are 81 // busy. If the entry is busy, we'll invoke the callback when we are ready 82 // again. See disk_cache::Entry::ReadyToUse() for more info. 83 int ReadyToUse(CompletionOnceCallback completion_callback); 84 85 // Deletes the children entries of |entry|. 86 static void DeleteChildren(EntryImpl* entry); 87 88 private: 89 // Creates a new sparse entry or opens an aready created entry from disk. 90 // These methods just read / write the required info from disk for the current 91 // entry, and verify that everything is correct. The return value is a net 92 // error code. 93 int CreateSparseEntry(); 94 int OpenSparseEntry(int data_len); 95 96 // Opens and closes a child entry. A child entry is a regular EntryImpl object 97 // with a key derived from the key of the resource to store and the range 98 // stored by that child. 99 bool OpenChild(); 100 void CloseChild(); 101 std::string GenerateChildKey(); 102 103 // Deletes the current child and continues the current operation (open). 104 bool KillChildAndContinue(const std::string& key, bool fatal); 105 106 // Continues the current operation (open) without a current child. 107 bool ContinueWithoutChild(const std::string& key); 108 109 // Returns true if the required child is tracked by the parent entry, i.e. it 110 // was already created. 111 bool ChildPresent(); 112 113 // Sets the bit for the current child to the provided |value|. In other words, 114 // starts or stops tracking this child. 115 void SetChildBit(bool value); 116 117 // Writes to disk the tracking information for this entry. 118 void WriteSparseData(); 119 120 // Verify that the range to be accessed for the current child is appropriate. 121 // Returns false if an error is detected or there is no need to perform the 122 // current IO operation (for instance if the required range is not stored by 123 // the child). 124 bool VerifyRange(); 125 126 // Updates the contents bitmap for the current range, based on the result of 127 // the current operation. 128 void UpdateRange(int result); 129 130 // Returns the number of bytes stored at |block_index|, if its allocation-bit 131 // is off (because it is not completely filled). 132 int PartialBlockLength(int block_index) const; 133 134 // Initializes the sparse info for the current child. 135 void InitChildData(); 136 137 // Iterates through all the children needed to complete the current operation. 138 void DoChildrenIO(); 139 140 // Performs a single operation with the current child. Returns true when we 141 // should move on to the next child and false when we should interrupt our 142 // work. 143 bool DoChildIO(); 144 145 // Performs the required work for GetAvailableRange for one child. 146 int DoGetAvailableRange(); 147 148 // Performs the required work after a single IO operations finishes. 149 void DoChildIOCompleted(int result); 150 151 // Invoked by the callback of asynchronous operations. 152 void OnChildIOCompleted(int result); 153 154 // Reports to the user that we are done. 155 void DoUserCallback(); 156 void DoAbortCallbacks(); 157 158 raw_ptr<EntryImpl> entry_; // The sparse entry. 159 scoped_refptr<EntryImpl> child_; // The current child entry. 160 SparseOperation operation_ = kNoOperation; 161 bool pending_ = false; // True if any child IO operation returned pending. 162 bool finished_ = false; 163 bool init_ = false; 164 bool range_found_ = false; // True if GetAvailableRange found something. 165 bool abort_ = false; // True if we should abort the current operation ASAP. 166 167 SparseHeader sparse_header_; // Data about the children of entry_. 168 Bitmap children_map_; // The actual bitmap of children. 169 SparseData child_data_; // Parent and allocation map of child_. 170 Bitmap child_map_; // The allocation map as a bitmap. 171 172 CompletionOnceCallback user_callback_; 173 std::vector<CompletionOnceCallback> abort_callbacks_; 174 int64_t offset_ = 0; // Current sparse offset. 175 scoped_refptr<net::DrainableIOBuffer> user_buf_; 176 int buf_len_ = 0; // Bytes to read or write. 177 int child_offset_ = 0; // Offset to use for the current child. 178 int child_len_ = 0; // Bytes to read or write for this child. 179 int result_ = 0; 180 }; 181 182 } // namespace disk_cache 183 184 #endif // NET_DISK_CACHE_BLOCKFILE_SPARSE_CONTROL_H_ 185