OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/disk_cache/blockfile/file.h" | 5 #include "net/disk_cache/blockfile/file.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/threading/worker_pool.h" | 10 #include "base/threading/worker_pool.h" |
11 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
12 #include "net/disk_cache/blockfile/in_flight_io.h" | 12 #include "net/disk_cache/blockfile/in_flight_io.h" |
13 #include "net/disk_cache/disk_cache.h" | 13 #include "net/disk_cache/disk_cache.h" |
14 | 14 |
15 namespace { | 15 namespace { |
16 | 16 |
17 // This class represents a single asynchronous IO operation while it is being | 17 // This class represents a single asynchronous IO operation while it is being |
18 // bounced between threads. | 18 // bounced between threads. |
19 class FileBackgroundIO : public disk_cache::BackgroundIO { | 19 class FileBackgroundIO : public disk_cache::BackgroundIO { |
20 public: | 20 public: |
21 // Other than the actual parameters for the IO operation (including the | 21 // Other than the actual parameters for the IO operation (including the |
22 // |callback| that must be notified at the end), we need the controller that | 22 // |callback| that must be notified at the end), we need the controller that |
23 // is keeping track of all operations. When done, we notify the controller | 23 // is keeping track of all operations. When done, we notify the controller |
24 // (we do NOT invoke the callback), in the worker thead that completed the | 24 // (we do NOT invoke the callback), in the worker thead that completed the |
25 // operation. | 25 // operation. |
26 FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, | 26 FileBackgroundIO(disk_cache::File* file, |
27 size_t offset, disk_cache::FileIOCallback* callback, | 27 const void* buf, |
| 28 size_t buf_len, |
| 29 size_t offset, |
| 30 disk_cache::FileIOCallback* callback, |
28 disk_cache::InFlightIO* controller) | 31 disk_cache::InFlightIO* controller) |
29 : disk_cache::BackgroundIO(controller), callback_(callback), file_(file), | 32 : disk_cache::BackgroundIO(controller), |
30 buf_(buf), buf_len_(buf_len), offset_(offset) { | 33 callback_(callback), |
31 } | 34 file_(file), |
| 35 buf_(buf), |
| 36 buf_len_(buf_len), |
| 37 offset_(offset) {} |
32 | 38 |
33 disk_cache::FileIOCallback* callback() { | 39 disk_cache::FileIOCallback* callback() { return callback_; } |
34 return callback_; | |
35 } | |
36 | 40 |
37 disk_cache::File* file() { | 41 disk_cache::File* file() { return file_; } |
38 return file_; | |
39 } | |
40 | 42 |
41 // Read and Write are the operations that can be performed asynchronously. | 43 // Read and Write are the operations that can be performed asynchronously. |
42 // The actual parameters for the operation are setup in the constructor of | 44 // The actual parameters for the operation are setup in the constructor of |
43 // the object. Both methods should be called from a worker thread, by posting | 45 // the object. Both methods should be called from a worker thread, by posting |
44 // a task to the WorkerPool (they are RunnableMethods). When finished, | 46 // a task to the WorkerPool (they are RunnableMethods). When finished, |
45 // controller->OnIOComplete() is called. | 47 // controller->OnIOComplete() is called. |
46 void Read(); | 48 void Read(); |
47 void Write(); | 49 void Write(); |
48 | 50 |
49 private: | 51 private: |
50 virtual ~FileBackgroundIO() {} | 52 virtual ~FileBackgroundIO() {} |
51 | 53 |
52 disk_cache::FileIOCallback* callback_; | 54 disk_cache::FileIOCallback* callback_; |
53 | 55 |
54 disk_cache::File* file_; | 56 disk_cache::File* file_; |
55 const void* buf_; | 57 const void* buf_; |
56 size_t buf_len_; | 58 size_t buf_len_; |
57 size_t offset_; | 59 size_t offset_; |
58 | 60 |
59 DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO); | 61 DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO); |
60 }; | 62 }; |
61 | 63 |
62 | |
63 // The specialized controller that keeps track of current operations. | 64 // The specialized controller that keeps track of current operations. |
64 class FileInFlightIO : public disk_cache::InFlightIO { | 65 class FileInFlightIO : public disk_cache::InFlightIO { |
65 public: | 66 public: |
66 FileInFlightIO() {} | 67 FileInFlightIO() {} |
67 virtual ~FileInFlightIO() {} | 68 virtual ~FileInFlightIO() {} |
68 | 69 |
69 // These methods start an asynchronous operation. The arguments have the same | 70 // These methods start an asynchronous operation. The arguments have the same |
70 // semantics of the File asynchronous operations, with the exception that the | 71 // semantics of the File asynchronous operations, with the exception that the |
71 // operation never finishes synchronously. | 72 // operation never finishes synchronously. |
72 void PostRead(disk_cache::File* file, void* buf, size_t buf_len, | 73 void PostRead(disk_cache::File* file, |
73 size_t offset, disk_cache::FileIOCallback* callback); | 74 void* buf, |
74 void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, | 75 size_t buf_len, |
75 size_t offset, disk_cache::FileIOCallback* callback); | 76 size_t offset, |
| 77 disk_cache::FileIOCallback* callback); |
| 78 void PostWrite(disk_cache::File* file, |
| 79 const void* buf, |
| 80 size_t buf_len, |
| 81 size_t offset, |
| 82 disk_cache::FileIOCallback* callback); |
76 | 83 |
77 protected: | 84 protected: |
78 // Invokes the users' completion callback at the end of the IO operation. | 85 // Invokes the users' completion callback at the end of the IO operation. |
79 // |cancel| is true if the actual task posted to the thread is still | 86 // |cancel| is true if the actual task posted to the thread is still |
80 // queued (because we are inside WaitForPendingIO), and false if said task is | 87 // queued (because we are inside WaitForPendingIO), and false if said task is |
81 // the one performing the call. | 88 // the one performing the call. |
82 virtual void OnOperationComplete(disk_cache::BackgroundIO* operation, | 89 virtual void OnOperationComplete(disk_cache::BackgroundIO* operation, |
83 bool cancel) OVERRIDE; | 90 bool cancel) OVERRIDE; |
84 | 91 |
85 private: | 92 private: |
(...skipping 15 matching lines...) Expand all Loading... |
101 // Runs on a worker thread. | 108 // Runs on a worker thread. |
102 void FileBackgroundIO::Write() { | 109 void FileBackgroundIO::Write() { |
103 bool rv = file_->Write(buf_, buf_len_, offset_); | 110 bool rv = file_->Write(buf_, buf_len_, offset_); |
104 | 111 |
105 result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE; | 112 result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE; |
106 NotifyController(); | 113 NotifyController(); |
107 } | 114 } |
108 | 115 |
109 // --------------------------------------------------------------------------- | 116 // --------------------------------------------------------------------------- |
110 | 117 |
111 void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len, | 118 void FileInFlightIO::PostRead(disk_cache::File* file, |
112 size_t offset, disk_cache::FileIOCallback *callback) { | 119 void* buf, |
| 120 size_t buf_len, |
| 121 size_t offset, |
| 122 disk_cache::FileIOCallback* callback) { |
113 scoped_refptr<FileBackgroundIO> operation( | 123 scoped_refptr<FileBackgroundIO> operation( |
114 new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); | 124 new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); |
115 file->AddRef(); // Balanced on OnOperationComplete() | 125 file->AddRef(); // Balanced on OnOperationComplete() |
116 | 126 |
117 base::WorkerPool::PostTask(FROM_HERE, | 127 base::WorkerPool::PostTask( |
118 base::Bind(&FileBackgroundIO::Read, operation.get()), true); | 128 FROM_HERE, base::Bind(&FileBackgroundIO::Read, operation.get()), true); |
119 OnOperationPosted(operation.get()); | 129 OnOperationPosted(operation.get()); |
120 } | 130 } |
121 | 131 |
122 void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf, | 132 void FileInFlightIO::PostWrite(disk_cache::File* file, |
123 size_t buf_len, size_t offset, | 133 const void* buf, |
124 disk_cache::FileIOCallback* callback) { | 134 size_t buf_len, |
| 135 size_t offset, |
| 136 disk_cache::FileIOCallback* callback) { |
125 scoped_refptr<FileBackgroundIO> operation( | 137 scoped_refptr<FileBackgroundIO> operation( |
126 new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); | 138 new FileBackgroundIO(file, buf, buf_len, offset, callback, this)); |
127 file->AddRef(); // Balanced on OnOperationComplete() | 139 file->AddRef(); // Balanced on OnOperationComplete() |
128 | 140 |
129 base::WorkerPool::PostTask(FROM_HERE, | 141 base::WorkerPool::PostTask( |
130 base::Bind(&FileBackgroundIO::Write, operation.get()), true); | 142 FROM_HERE, base::Bind(&FileBackgroundIO::Write, operation.get()), true); |
131 OnOperationPosted(operation.get()); | 143 OnOperationPosted(operation.get()); |
132 } | 144 } |
133 | 145 |
134 // Runs on the IO thread. | 146 // Runs on the IO thread. |
135 void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation, | 147 void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation, |
136 bool cancel) { | 148 bool cancel) { |
137 FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation); | 149 FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation); |
138 | 150 |
139 disk_cache::FileIOCallback* callback = op->callback(); | 151 disk_cache::FileIOCallback* callback = op->callback(); |
140 int bytes = operation->result(); | 152 int bytes = operation->result(); |
(...skipping 19 matching lines...) Expand all Loading... |
160 DCHECK(s_file_operations); | 172 DCHECK(s_file_operations); |
161 delete s_file_operations; | 173 delete s_file_operations; |
162 s_file_operations = NULL; | 174 s_file_operations = NULL; |
163 } | 175 } |
164 | 176 |
165 } // namespace | 177 } // namespace |
166 | 178 |
167 namespace disk_cache { | 179 namespace disk_cache { |
168 | 180 |
169 File::File(base::File file) | 181 File::File(base::File file) |
170 : init_(true), | 182 : init_(true), mixed_(true), base_file_(file.Pass()) { |
171 mixed_(true), | |
172 base_file_(file.Pass()) { | |
173 } | 183 } |
174 | 184 |
175 bool File::Init(const base::FilePath& name) { | 185 bool File::Init(const base::FilePath& name) { |
176 if (base_file_.IsValid()) | 186 if (base_file_.IsValid()) |
177 return false; | 187 return false; |
178 | 188 |
179 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | | 189 int flags = |
180 base::File::FLAG_WRITE; | 190 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; |
181 base_file_.Initialize(name, flags); | 191 base_file_.Initialize(name, flags); |
182 return base_file_.IsValid(); | 192 return base_file_.IsValid(); |
183 } | 193 } |
184 | 194 |
185 bool File::IsValid() const { | 195 bool File::IsValid() const { |
186 return base_file_.IsValid(); | 196 return base_file_.IsValid(); |
187 } | 197 } |
188 | 198 |
189 bool File::Read(void* buffer, size_t buffer_len, size_t offset) { | 199 bool File::Read(void* buffer, size_t buffer_len, size_t offset) { |
190 DCHECK(base_file_.IsValid()); | 200 DCHECK(base_file_.IsValid()); |
191 if (buffer_len > static_cast<size_t>(kint32max) || | 201 if (buffer_len > static_cast<size_t>(kint32max) || |
192 offset > static_cast<size_t>(kint32max)) { | 202 offset > static_cast<size_t>(kint32max)) { |
193 return false; | 203 return false; |
194 } | 204 } |
195 | 205 |
196 int ret = base_file_.Read(offset, static_cast<char*>(buffer), buffer_len); | 206 int ret = base_file_.Read(offset, static_cast<char*>(buffer), buffer_len); |
197 return (static_cast<size_t>(ret) == buffer_len); | 207 return (static_cast<size_t>(ret) == buffer_len); |
198 } | 208 } |
199 | 209 |
200 bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { | 210 bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { |
201 DCHECK(base_file_.IsValid()); | 211 DCHECK(base_file_.IsValid()); |
202 if (buffer_len > static_cast<size_t>(kint32max) || | 212 if (buffer_len > static_cast<size_t>(kint32max) || |
203 offset > static_cast<size_t>(kint32max)) { | 213 offset > static_cast<size_t>(kint32max)) { |
204 return false; | 214 return false; |
205 } | 215 } |
206 | 216 |
207 int ret = base_file_.Write(offset, static_cast<const char*>(buffer), | 217 int ret = |
208 buffer_len); | 218 base_file_.Write(offset, static_cast<const char*>(buffer), buffer_len); |
209 return (static_cast<size_t>(ret) == buffer_len); | 219 return (static_cast<size_t>(ret) == buffer_len); |
210 } | 220 } |
211 | 221 |
212 // We have to increase the ref counter of the file before performing the IO to | 222 // We have to increase the ref counter of the file before performing the IO to |
213 // prevent the completion to happen with an invalid handle (if the file is | 223 // prevent the completion to happen with an invalid handle (if the file is |
214 // closed while the IO is in flight). | 224 // closed while the IO is in flight). |
215 bool File::Read(void* buffer, size_t buffer_len, size_t offset, | 225 bool File::Read(void* buffer, |
216 FileIOCallback* callback, bool* completed) { | 226 size_t buffer_len, |
| 227 size_t offset, |
| 228 FileIOCallback* callback, |
| 229 bool* completed) { |
217 DCHECK(base_file_.IsValid()); | 230 DCHECK(base_file_.IsValid()); |
218 if (!callback) { | 231 if (!callback) { |
219 if (completed) | 232 if (completed) |
220 *completed = true; | 233 *completed = true; |
221 return Read(buffer, buffer_len, offset); | 234 return Read(buffer, buffer_len, offset); |
222 } | 235 } |
223 | 236 |
224 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) | 237 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) |
225 return false; | 238 return false; |
226 | 239 |
227 GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback); | 240 GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback); |
228 | 241 |
229 *completed = false; | 242 *completed = false; |
230 return true; | 243 return true; |
231 } | 244 } |
232 | 245 |
233 bool File::Write(const void* buffer, size_t buffer_len, size_t offset, | 246 bool File::Write(const void* buffer, |
234 FileIOCallback* callback, bool* completed) { | 247 size_t buffer_len, |
| 248 size_t offset, |
| 249 FileIOCallback* callback, |
| 250 bool* completed) { |
235 DCHECK(base_file_.IsValid()); | 251 DCHECK(base_file_.IsValid()); |
236 if (!callback) { | 252 if (!callback) { |
237 if (completed) | 253 if (completed) |
238 *completed = true; | 254 *completed = true; |
239 return Write(buffer, buffer_len, offset); | 255 return Write(buffer, buffer_len, offset); |
240 } | 256 } |
241 | 257 |
242 return AsyncWrite(buffer, buffer_len, offset, callback, completed); | 258 return AsyncWrite(buffer, buffer_len, offset, callback, completed); |
243 } | 259 } |
244 | 260 |
(...skipping 29 matching lines...) Expand all Loading... |
274 DeleteFileInFlightIO(); | 290 DeleteFileInFlightIO(); |
275 } | 291 } |
276 | 292 |
277 File::~File() { | 293 File::~File() { |
278 } | 294 } |
279 | 295 |
280 base::PlatformFile File::platform_file() const { | 296 base::PlatformFile File::platform_file() const { |
281 return base_file_.GetPlatformFile(); | 297 return base_file_.GetPlatformFile(); |
282 } | 298 } |
283 | 299 |
284 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, | 300 bool File::AsyncWrite(const void* buffer, |
285 FileIOCallback* callback, bool* completed) { | 301 size_t buffer_len, |
| 302 size_t offset, |
| 303 FileIOCallback* callback, |
| 304 bool* completed) { |
286 DCHECK(base_file_.IsValid()); | 305 DCHECK(base_file_.IsValid()); |
287 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) | 306 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) |
288 return false; | 307 return false; |
289 | 308 |
290 GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback); | 309 GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback); |
291 | 310 |
292 if (completed) | 311 if (completed) |
293 *completed = false; | 312 *completed = false; |
294 return true; | 313 return true; |
295 } | 314 } |
296 | 315 |
297 } // namespace disk_cache | 316 } // namespace disk_cache |
OLD | NEW |