13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/file.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h"
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
10d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen#include "net/base/net_errors.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Structure used for asynchronous operations.
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct MyOverlapped {
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped(disk_cache::File* file, size_t offset,
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               disk_cache::FileIOCallback* callback);
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ~MyOverlapped() {}
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  OVERLAPPED* overlapped() {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return &context_.overlapped;
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO::IOContext context_;
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<disk_cache::File> file_;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::FileIOCallback* callback_;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(!offsetof(MyOverlapped, context_), starts_with_overlapped);
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Helper class to handle the IO completion notifications from the message loop.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CompletionHandler : public MessageLoopForIO::IOHandler {
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             DWORD actual_bytes, DWORD error);
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<CompletionHandler> g_completion_handler(
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    base::LINKER_INITIALIZED);
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CompletionHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      DWORD actual_bytes, DWORD error) {
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = reinterpret_cast<MyOverlapped*>(context);
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (error) {
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!actual_bytes);
46d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen    actual_bytes = static_cast<DWORD>(net::ERR_CACHE_READ_FAILURE);
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data->callback_)
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data->callback_->OnFileIOComplete(static_cast<int>(actual_bytes));
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delete data;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           disk_cache::FileIOCallback* callback) {
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(this, 0, sizeof(*this));
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  context_.handler = g_completion_handler.Pointer();
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  context_.overlapped.Offset = static_cast<DWORD>(offset);
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_ = file;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  callback_ = callback;
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile::File(base::PlatformFile file)
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : init_(true), mixed_(true), platform_file_(INVALID_HANDLE_VALUE),
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sync_platform_file_(file) {
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Init(const FilePath& name) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!init_);
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (init_)
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DWORD access = GENERIC_READ | GENERIC_WRITE | DELETE;
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  platform_file_ = CreateFile(name.value().c_str(), access, sharing, NULL,
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE == platform_file_)
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO::current()->RegisterIOHandler(
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      platform_file_, g_completion_handler.Pointer());
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = true;
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  sync_platform_file_  = CreateFile(name.value().c_str(), access, sharing, NULL,
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    OPEN_EXISTING, 0, NULL);
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE == sync_platform_file_)
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile::~File() {
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_)
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE != platform_file_)
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandle(platform_file_);
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE != sync_platform_file_)
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandle(sync_platform_file_);
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbase::PlatformFile File::platform_file() const {
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (INVALID_HANDLE_VALUE == platform_file_) ? sync_platform_file_ :
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                    platform_file_;
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::IsValid() const {
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_)
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (INVALID_HANDLE_VALUE != platform_file_ ||
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          INVALID_HANDLE_VALUE != sync_platform_file_);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Read(void* buffer, size_t buffer_len, size_t offset) {
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > LONG_MAX)
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD ret = SetFilePointer(sync_platform_file_, static_cast<LONG>(offset),
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             NULL, FILE_BEGIN);
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == ret)
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ReadFile(sync_platform_file_, buffer, size, &actual, NULL))
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return actual == size;
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD ret = SetFilePointer(sync_platform_file_, static_cast<LONG>(offset),
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             NULL, FILE_BEGIN);
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == ret)
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!WriteFile(sync_platform_file_, buffer, size, &actual, NULL))
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return actual == size;
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We have to increase the ref counter of the file before performing the IO to
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// prevent the completion to happen with an invalid handle (if the file is
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// closed while the IO is in flight).
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Read(void* buffer, size_t buffer_len, size_t offset,
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                FileIOCallback* callback, bool* completed) {
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!callback) {
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (completed)
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *completed = true;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return Read(buffer, buffer_len, offset);
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = new MyOverlapped(this, offset, callback);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ReadFile(platform_file_, buffer, size, &actual, data->overlapped())) {
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *completed = false;
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GetLastError() == ERROR_IO_PENDING)
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete data;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The operation completed already. We'll be called back anyway.
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *completed = (actual == size);
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(actual == size);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->callback_ = NULL;
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->file_ = NULL;  // There is no reason to hold on to this anymore.
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return *completed;
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Write(const void* buffer, size_t buffer_len, size_t offset,
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 FileIOCallback* callback, bool* completed) {
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!callback) {
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (completed)
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *completed = true;
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return Write(buffer, buffer_len, offset);
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return AsyncWrite(buffer, buffer_len, offset, callback, completed);
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      FileIOCallback* callback, bool* completed) {
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(callback);
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(completed);
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = new MyOverlapped(this, offset, callback);
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!WriteFile(platform_file_, buffer, size, &actual, data->overlapped())) {
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *completed = false;
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GetLastError() == ERROR_IO_PENDING)
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete data;
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The operation completed already. We'll be called back anyway.
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *completed = (actual == size);
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(actual == size);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->callback_ = NULL;
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->file_ = NULL;  // There is no reason to hold on to this anymore.
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return *completed;
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::SetLength(size_t length) {
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (length > ULONG_MAX)
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(length);
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HANDLE file = platform_file();
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == SetFilePointer(file, size, NULL, FILE_BEGIN))
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return TRUE == SetEndOfFile(file);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t File::GetLength() {
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LARGE_INTEGER size;
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HANDLE file = platform_file();
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!GetFileSizeEx(file, &size))
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (size.HighPart)
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ULONG_MAX;
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return static_cast<size_t>(size.LowPart);
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Static.
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid File::WaitForPendingIO(int* num_pending_io) {
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (*num_pending_io) {
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Asynchronous IO operations may be in flight and the completion may end
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // up calling us back so let's wait for them.
26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    MessageLoopForIO::IOHandler* handler = g_completion_handler.Pointer();
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoopForIO::current()->WaitForIOCompletion(100, handler);
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
268