| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/file.h" | 5 #include "net/disk_cache/file.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // operation. | 30 // operation. |
| 31 BackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, | 31 BackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, |
| 32 size_t offset, disk_cache::FileIOCallback* callback, | 32 size_t offset, disk_cache::FileIOCallback* callback, |
| 33 InFlightIO* controller) | 33 InFlightIO* controller) |
| 34 : io_completed_(true, false), callback_(callback), file_(file), buf_(buf), | 34 : io_completed_(true, false), callback_(callback), file_(file), buf_(buf), |
| 35 buf_len_(buf_len), offset_(offset), controller_(controller), | 35 buf_len_(buf_len), offset_(offset), controller_(controller), |
| 36 bytes_(0) {} | 36 bytes_(0) {} |
| 37 | 37 |
| 38 // Read and Write are the operations that can be performed asynchronously. | 38 // Read and Write are the operations that can be performed asynchronously. |
| 39 // The actual parameters for the operation are setup in the constructor of | 39 // The actual parameters for the operation are setup in the constructor of |
| 40 // the object, with the exception of |delete_buffer|, that allows a write | 40 // the object. Both methods should be called from a worker thread, by posting |
| 41 // without a callback. Both methods should be called from a worker thread, by | 41 // a task to the WorkerPool (they are RunnableMethods). When finished, |
| 42 // posting a task to the WorkerPool (they are RunnableMethods). When finished, | |
| 43 // controller->OnIOComplete() is called. | 42 // controller->OnIOComplete() is called. |
| 44 void Read(); | 43 void Read(); |
| 45 void Write(bool delete_buffer); | 44 void Write(); |
| 46 | 45 |
| 47 // This method signals the controller that this operation is finished, in the | 46 // This method signals the controller that this operation is finished, in the |
| 48 // original thread (presumably the IO-Thread). In practice, this is a | 47 // original thread (presumably the IO-Thread). In practice, this is a |
| 49 // RunableMethod that allows cancellation. | 48 // RunableMethod that allows cancellation. |
| 50 void OnIOSignalled(); | 49 void OnIOSignalled(); |
| 51 | 50 |
| 52 // Allows the cancellation of the task to notify the controller (step number 7 | 51 // Allows the cancellation of the task to notify the controller (step number 7 |
| 53 // in the diagram below). In practice, if the controller waits for the | 52 // in the diagram below). In practice, if the controller waits for the |
| 54 // operation to finish it doesn't have to wait for the final task to be | 53 // operation to finish it doesn't have to wait for the final task to be |
| 55 // processed by the message loop so calling this method prevents its delivery. | 54 // processed by the message loop so calling this method prevents its delivery. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 public: | 114 public: |
| 116 InFlightIO() : callback_thread_(MessageLoop::current()) {} | 115 InFlightIO() : callback_thread_(MessageLoop::current()) {} |
| 117 ~InFlightIO() {} | 116 ~InFlightIO() {} |
| 118 | 117 |
| 119 // These methods start an asynchronous operation. The arguments have the same | 118 // These methods start an asynchronous operation. The arguments have the same |
| 120 // semantics of the File asynchronous operations, with the exception that the | 119 // semantics of the File asynchronous operations, with the exception that the |
| 121 // operation never finishes synchronously. | 120 // operation never finishes synchronously. |
| 122 void PostRead(disk_cache::File* file, void* buf, size_t buf_len, | 121 void PostRead(disk_cache::File* file, void* buf, size_t buf_len, |
| 123 size_t offset, disk_cache::FileIOCallback* callback); | 122 size_t offset, disk_cache::FileIOCallback* callback); |
| 124 void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, | 123 void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, |
| 125 size_t offset, disk_cache::FileIOCallback* callback, | 124 size_t offset, disk_cache::FileIOCallback* callback); |
| 126 bool delete_buffer); | |
| 127 | 125 |
| 128 // Blocks the current thread until all IO operations tracked by this object | 126 // Blocks the current thread until all IO operations tracked by this object |
| 129 // complete. | 127 // complete. |
| 130 void WaitForPendingIO(); | 128 void WaitForPendingIO(); |
| 131 | 129 |
| 132 // Called on a worker thread when |operation| completes. | 130 // Called on a worker thread when |operation| completes. |
| 133 void OnIOComplete(BackgroundIO* operation); | 131 void OnIOComplete(BackgroundIO* operation); |
| 134 | 132 |
| 135 // Invokes the users' completion callback at the end of the IO operation. | 133 // Invokes the users' completion callback at the end of the IO operation. |
| 136 // |cancel_task| is true if the actual task posted to the thread is still | 134 // |cancel_task| is true if the actual task posted to the thread is still |
| (...skipping 23 matching lines...) Expand all Loading... |
| 160 int BackgroundIO::Result() { | 158 int BackgroundIO::Result() { |
| 161 return bytes_; | 159 return bytes_; |
| 162 } | 160 } |
| 163 | 161 |
| 164 void BackgroundIO::Cancel() { | 162 void BackgroundIO::Cancel() { |
| 165 DCHECK(controller_); | 163 DCHECK(controller_); |
| 166 controller_ = NULL; | 164 controller_ = NULL; |
| 167 } | 165 } |
| 168 | 166 |
| 169 // Runs on a worker thread. | 167 // Runs on a worker thread. |
| 170 void BackgroundIO::Write(bool delete_buffer) { | 168 void BackgroundIO::Write() { |
| 171 bool rv = file_->Write(buf_, buf_len_, offset_); | 169 bool rv = file_->Write(buf_, buf_len_, offset_); |
| 172 if (delete_buffer) { | |
| 173 // TODO(rvargas): remove or update this code. | |
| 174 delete[] reinterpret_cast<const char*>(buf_); | |
| 175 } | |
| 176 | 170 |
| 177 bytes_ = rv ? static_cast<int>(buf_len_) : -1; | 171 bytes_ = rv ? static_cast<int>(buf_len_) : -1; |
| 178 controller_->OnIOComplete(this); | 172 controller_->OnIOComplete(this); |
| 179 } | 173 } |
| 180 | 174 |
| 181 // Runs on the IO thread. | 175 // Runs on the IO thread. |
| 182 void BackgroundIO::OnIOSignalled() { | 176 void BackgroundIO::OnIOSignalled() { |
| 183 if (controller_) | 177 if (controller_) |
| 184 controller_->InvokeCallback(this, false); | 178 controller_->InvokeCallback(this, false); |
| 185 } | 179 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 196 if (!callback_thread_) | 190 if (!callback_thread_) |
| 197 callback_thread_ = MessageLoop::current(); | 191 callback_thread_ = MessageLoop::current(); |
| 198 | 192 |
| 199 WorkerPool::PostTask(FROM_HERE, | 193 WorkerPool::PostTask(FROM_HERE, |
| 200 NewRunnableMethod(operation.get(), &BackgroundIO::Read), | 194 NewRunnableMethod(operation.get(), &BackgroundIO::Read), |
| 201 true); | 195 true); |
| 202 } | 196 } |
| 203 | 197 |
| 204 void InFlightIO::PostWrite(disk_cache::File* file, const void* buf, | 198 void InFlightIO::PostWrite(disk_cache::File* file, const void* buf, |
| 205 size_t buf_len, size_t offset, | 199 size_t buf_len, size_t offset, |
| 206 disk_cache::FileIOCallback* callback, | 200 disk_cache::FileIOCallback* callback) { |
| 207 bool delete_buffer) { | |
| 208 scoped_refptr<BackgroundIO> operation = | 201 scoped_refptr<BackgroundIO> operation = |
| 209 new BackgroundIO(file, buf, buf_len, offset, callback, this); | 202 new BackgroundIO(file, buf, buf_len, offset, callback, this); |
| 210 io_list_.insert(operation.get()); | 203 io_list_.insert(operation.get()); |
| 211 file->AddRef(); // Balanced on InvokeCallback() | 204 file->AddRef(); // Balanced on InvokeCallback() |
| 212 | 205 |
| 213 if (!callback_thread_) | 206 if (!callback_thread_) |
| 214 callback_thread_ = MessageLoop::current(); | 207 callback_thread_ = MessageLoop::current(); |
| 215 | 208 |
| 216 WorkerPool::PostTask(FROM_HERE, | 209 WorkerPool::PostTask(FROM_HERE, |
| 217 NewRunnableMethod(operation.get(), &BackgroundIO::Write, | 210 NewRunnableMethod(operation.get(), &BackgroundIO::Write), |
| 218 delete_buffer), | |
| 219 true); | 211 true); |
| 220 } | 212 } |
| 221 | 213 |
| 222 void InFlightIO::WaitForPendingIO() { | 214 void InFlightIO::WaitForPendingIO() { |
| 223 while (!io_list_.empty()) { | 215 while (!io_list_.empty()) { |
| 224 // Block the current thread until all pending IO completes. | 216 // Block the current thread until all pending IO completes. |
| 225 IOList::iterator it = io_list_.begin(); | 217 IOList::iterator it = io_list_.begin(); |
| 226 InvokeCallback(*it, true); | 218 InvokeCallback(*it, true); |
| 227 } | 219 } |
| 228 // Unit tests can use different threads. | 220 // Unit tests can use different threads. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 | 327 |
| 336 bool File::Write(const void* buffer, size_t buffer_len, size_t offset, | 328 bool File::Write(const void* buffer, size_t buffer_len, size_t offset, |
| 337 FileIOCallback* callback, bool* completed) { | 329 FileIOCallback* callback, bool* completed) { |
| 338 DCHECK(init_); | 330 DCHECK(init_); |
| 339 if (!callback) { | 331 if (!callback) { |
| 340 if (completed) | 332 if (completed) |
| 341 *completed = true; | 333 *completed = true; |
| 342 return Write(buffer, buffer_len, offset); | 334 return Write(buffer, buffer_len, offset); |
| 343 } | 335 } |
| 344 | 336 |
| 345 return AsyncWrite(buffer, buffer_len, offset, true, callback, completed); | 337 return AsyncWrite(buffer, buffer_len, offset, callback, completed); |
| 346 } | |
| 347 | |
| 348 bool File::PostWrite(const void* buffer, size_t buffer_len, size_t offset) { | |
| 349 DCHECK(init_); | |
| 350 return AsyncWrite(buffer, buffer_len, offset, false, NULL, NULL); | |
| 351 } | 338 } |
| 352 | 339 |
| 353 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, | 340 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, |
| 354 bool notify, FileIOCallback* callback, bool* completed) { | 341 FileIOCallback* callback, bool* completed) { |
| 355 DCHECK(init_); | 342 DCHECK(init_); |
| 356 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) | 343 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) |
| 357 return false; | 344 return false; |
| 358 | 345 |
| 359 InFlightIO* io_operations = Singleton<InFlightIO>::get(); | 346 InFlightIO* io_operations = Singleton<InFlightIO>::get(); |
| 360 io_operations->PostWrite(this, buffer, buffer_len, offset, callback, !notify); | 347 io_operations->PostWrite(this, buffer, buffer_len, offset, callback); |
| 361 | 348 |
| 362 if (completed) | 349 if (completed) |
| 363 *completed = false; | 350 *completed = false; |
| 364 return true; | 351 return true; |
| 365 } | 352 } |
| 366 | 353 |
| 367 bool File::SetLength(size_t length) { | 354 bool File::SetLength(size_t length) { |
| 368 DCHECK(init_); | 355 DCHECK(init_); |
| 369 if (length > ULONG_MAX) | 356 if (length > ULONG_MAX) |
| 370 return false; | 357 return false; |
| 371 | 358 |
| 372 return 0 == ftruncate(platform_file_, length); | 359 return 0 == ftruncate(platform_file_, length); |
| 373 } | 360 } |
| 374 | 361 |
| 375 size_t File::GetLength() { | 362 size_t File::GetLength() { |
| 376 DCHECK(init_); | 363 DCHECK(init_); |
| 377 size_t ret = lseek(platform_file_, 0, SEEK_END); | 364 size_t ret = lseek(platform_file_, 0, SEEK_END); |
| 378 return ret; | 365 return ret; |
| 379 } | 366 } |
| 380 | 367 |
| 381 // Static. | 368 // Static. |
| 382 void File::WaitForPendingIO(int* num_pending_io) { | 369 void File::WaitForPendingIO(int* num_pending_io) { |
| 383 // We may be running unit tests so we should allow InFlightIO to reset the | 370 // We may be running unit tests so we should allow InFlightIO to reset the |
| 384 // message loop. | 371 // message loop. |
| 385 Singleton<InFlightIO>::get()->WaitForPendingIO(); | 372 Singleton<InFlightIO>::get()->WaitForPendingIO(); |
| 386 } | 373 } |
| 387 | 374 |
| 388 } // namespace disk_cache | 375 } // namespace disk_cache |
| OLD | NEW |