| 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 "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/singleton.h" | 9 #include "base/singleton.h" |
| 10 #include "net/disk_cache/disk_cache.h" | 10 #include "net/disk_cache/disk_cache.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 // Structure used for asynchronous operations. | 14 // Structure used for asynchronous operations. |
| 15 struct MyOverlapped { | 15 struct MyOverlapped { |
| 16 MyOverlapped(disk_cache::File* file, size_t offset, | 16 MyOverlapped(disk_cache::File* file, size_t offset, |
| 17 disk_cache::FileIOCallback* callback); | 17 disk_cache::FileIOCallback* callback); |
| 18 ~MyOverlapped(); | 18 ~MyOverlapped() {} |
| 19 OVERLAPPED* overlapped() { | 19 OVERLAPPED* overlapped() { |
| 20 return &context_.overlapped; | 20 return &context_.overlapped; |
| 21 } | 21 } |
| 22 | 22 |
| 23 MessageLoopForIO::IOContext context_; | 23 MessageLoopForIO::IOContext context_; |
| 24 scoped_refptr<disk_cache::File> file_; | 24 scoped_refptr<disk_cache::File> file_; |
| 25 disk_cache::FileIOCallback* callback_; | 25 disk_cache::FileIOCallback* callback_; |
| 26 const void* buffer_; | |
| 27 bool delete_buffer_; // Delete the user buffer at completion. | |
| 28 }; | 26 }; |
| 29 | 27 |
| 30 COMPILE_ASSERT(!offsetof(MyOverlapped, context_), starts_with_overlapped); | 28 COMPILE_ASSERT(!offsetof(MyOverlapped, context_), starts_with_overlapped); |
| 31 | 29 |
| 32 // Helper class to handle the IO completion notifications from the message loop. | 30 // Helper class to handle the IO completion notifications from the message loop. |
| 33 class CompletionHandler : public MessageLoopForIO::IOHandler { | 31 class CompletionHandler : public MessageLoopForIO::IOHandler { |
| 34 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 32 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 35 DWORD actual_bytes, DWORD error); | 33 DWORD actual_bytes, DWORD error); |
| 36 }; | 34 }; |
| 37 | 35 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 53 | 51 |
| 54 MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset, | 52 MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset, |
| 55 disk_cache::FileIOCallback* callback) { | 53 disk_cache::FileIOCallback* callback) { |
| 56 memset(this, 0, sizeof(*this)); | 54 memset(this, 0, sizeof(*this)); |
| 57 context_.handler = Singleton<CompletionHandler>::get(); | 55 context_.handler = Singleton<CompletionHandler>::get(); |
| 58 context_.overlapped.Offset = static_cast<DWORD>(offset); | 56 context_.overlapped.Offset = static_cast<DWORD>(offset); |
| 59 file_ = file; | 57 file_ = file; |
| 60 callback_ = callback; | 58 callback_ = callback; |
| 61 } | 59 } |
| 62 | 60 |
| 63 MyOverlapped::~MyOverlapped() { | |
| 64 if (delete_buffer_) { | |
| 65 DCHECK(!callback_); | |
| 66 // This whole thing could be updated to use IOBuffer, but PostWrite is not | |
| 67 // used at the moment. TODO(rvargas): remove or update this code. | |
| 68 delete[] reinterpret_cast<const char*>(buffer_); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 } // namespace | 61 } // namespace |
| 73 | 62 |
| 74 namespace disk_cache { | 63 namespace disk_cache { |
| 75 | 64 |
| 76 File::File(base::PlatformFile file) | 65 File::File(base::PlatformFile file) |
| 77 : init_(true), mixed_(true), platform_file_(INVALID_HANDLE_VALUE), | 66 : init_(true), mixed_(true), platform_file_(INVALID_HANDLE_VALUE), |
| 78 sync_platform_file_(file) { | 67 sync_platform_file_(file) { |
| 79 } | 68 } |
| 80 | 69 |
| 81 bool File::Init(const FilePath& name) { | 70 bool File::Init(const FilePath& name) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 189 |
| 201 bool File::Write(const void* buffer, size_t buffer_len, size_t offset, | 190 bool File::Write(const void* buffer, size_t buffer_len, size_t offset, |
| 202 FileIOCallback* callback, bool* completed) { | 191 FileIOCallback* callback, bool* completed) { |
| 203 DCHECK(init_); | 192 DCHECK(init_); |
| 204 if (!callback) { | 193 if (!callback) { |
| 205 if (completed) | 194 if (completed) |
| 206 *completed = true; | 195 *completed = true; |
| 207 return Write(buffer, buffer_len, offset); | 196 return Write(buffer, buffer_len, offset); |
| 208 } | 197 } |
| 209 | 198 |
| 210 return AsyncWrite(buffer, buffer_len, offset, true, callback, completed); | 199 return AsyncWrite(buffer, buffer_len, offset, callback, completed); |
| 211 } | |
| 212 | |
| 213 bool File::PostWrite(const void* buffer, size_t buffer_len, size_t offset) { | |
| 214 DCHECK(init_); | |
| 215 return AsyncWrite(buffer, buffer_len, offset, false, NULL, NULL); | |
| 216 } | 200 } |
| 217 | 201 |
| 218 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, | 202 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, |
| 219 bool notify, FileIOCallback* callback, bool* completed) { | 203 FileIOCallback* callback, bool* completed) { |
| 220 DCHECK(init_); | 204 DCHECK(init_); |
| 205 DCHECK(callback); |
| 206 DCHECK(completed); |
| 221 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) | 207 if (buffer_len > ULONG_MAX || offset > ULONG_MAX) |
| 222 return false; | 208 return false; |
| 223 | 209 |
| 224 MyOverlapped* data = new MyOverlapped(this, offset, callback); | 210 MyOverlapped* data = new MyOverlapped(this, offset, callback); |
| 225 bool dummy_completed; | |
| 226 if (!callback) { | |
| 227 DCHECK(!notify); | |
| 228 data->delete_buffer_ = true; | |
| 229 data->buffer_ = buffer; | |
| 230 completed = &dummy_completed; | |
| 231 } | |
| 232 | |
| 233 DWORD size = static_cast<DWORD>(buffer_len); | 211 DWORD size = static_cast<DWORD>(buffer_len); |
| 234 | 212 |
| 235 DWORD actual; | 213 DWORD actual; |
| 236 if (!WriteFile(platform_file_, buffer, size, &actual, data->overlapped())) { | 214 if (!WriteFile(platform_file_, buffer, size, &actual, data->overlapped())) { |
| 237 *completed = false; | 215 *completed = false; |
| 238 if (GetLastError() == ERROR_IO_PENDING) | 216 if (GetLastError() == ERROR_IO_PENDING) |
| 239 return true; | 217 return true; |
| 240 delete data; | 218 delete data; |
| 241 return false; | 219 return false; |
| 242 } | 220 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 void File::WaitForPendingIO(int* num_pending_io) { | 256 void File::WaitForPendingIO(int* num_pending_io) { |
| 279 while (*num_pending_io) { | 257 while (*num_pending_io) { |
| 280 // Asynchronous IO operations may be in flight and the completion may end | 258 // Asynchronous IO operations may be in flight and the completion may end |
| 281 // up calling us back so let's wait for them. | 259 // up calling us back so let's wait for them. |
| 282 MessageLoopForIO::IOHandler* handler = Singleton<CompletionHandler>::get(); | 260 MessageLoopForIO::IOHandler* handler = Singleton<CompletionHandler>::get(); |
| 283 MessageLoopForIO::current()->WaitForIOCompletion(100, handler); | 261 MessageLoopForIO::current()->WaitForIOCompletion(100, handler); |
| 284 } | 262 } |
| 285 } | 263 } |
| 286 | 264 |
| 287 } // namespace disk_cache | 265 } // namespace disk_cache |
| OLD | NEW |