| 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 |