Remove IsHighDPIEnabled, move EnableHighDPISupport to only place it's used
[chromium-blink-merge.git] / net / disk_cache / blockfile / file_win.cc
blobbf313128b4631d5bb517a9c54d8fa6657b957c7d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/disk_cache/blockfile/file.h"
7 #include "base/files/file_path.h"
8 #include "base/lazy_instance.h"
9 #include "base/message_loop/message_loop.h"
10 #include "net/base/net_errors.h"
11 #include "net/disk_cache/disk_cache.h"
13 namespace {
15 // Structure used for asynchronous operations.
16 struct MyOverlapped {
17 MyOverlapped(disk_cache::File* file, size_t offset,
18 disk_cache::FileIOCallback* callback);
19 ~MyOverlapped() {}
20 OVERLAPPED* overlapped() {
21 return &context_.overlapped;
24 base::MessageLoopForIO::IOContext context_;
25 scoped_refptr<disk_cache::File> file_;
26 disk_cache::FileIOCallback* callback_;
29 COMPILE_ASSERT(!offsetof(MyOverlapped, context_), starts_with_overlapped);
31 // Helper class to handle the IO completion notifications from the message loop.
32 class CompletionHandler : public base::MessageLoopForIO::IOHandler {
33 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
34 DWORD actual_bytes,
35 DWORD error);
38 static base::LazyInstance<CompletionHandler> g_completion_handler =
39 LAZY_INSTANCE_INITIALIZER;
41 void CompletionHandler::OnIOCompleted(
42 base::MessageLoopForIO::IOContext* context,
43 DWORD actual_bytes,
44 DWORD error) {
45 MyOverlapped* data = reinterpret_cast<MyOverlapped*>(context);
47 if (error) {
48 DCHECK(!actual_bytes);
49 actual_bytes = static_cast<DWORD>(net::ERR_CACHE_READ_FAILURE);
50 NOTREACHED();
53 if (data->callback_)
54 data->callback_->OnFileIOComplete(static_cast<int>(actual_bytes));
56 delete data;
59 MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
60 disk_cache::FileIOCallback* callback) {
61 memset(this, 0, sizeof(*this));
62 context_.handler = g_completion_handler.Pointer();
63 context_.overlapped.Offset = static_cast<DWORD>(offset);
64 file_ = file;
65 callback_ = callback;
68 } // namespace
70 namespace disk_cache {
72 File::File(base::File file)
73 : init_(true),
74 mixed_(true),
75 sync_base_file_(file.Pass()) {
78 bool File::Init(const base::FilePath& name) {
79 DCHECK(!init_);
80 if (init_)
81 return false;
83 DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
84 DWORD access = GENERIC_READ | GENERIC_WRITE | DELETE;
85 base_file_ =
86 base::File(CreateFile(name.value().c_str(), access, sharing, NULL,
87 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL));
89 if (!base_file_.IsValid())
90 return false;
92 base::MessageLoopForIO::current()->RegisterIOHandler(
93 base_file_.GetPlatformFile(), g_completion_handler.Pointer());
95 init_ = true;
96 sync_base_file_ =
97 base::File(CreateFile(name.value().c_str(), access, sharing, NULL,
98 OPEN_EXISTING, 0, NULL));
100 if (!sync_base_file_.IsValid())
101 return false;
103 return true;
106 bool File::IsValid() const {
107 if (!init_)
108 return false;
109 return base_file_.IsValid() || sync_base_file_.IsValid();
112 bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
113 DCHECK(init_);
114 if (buffer_len > ULONG_MAX || offset > LONG_MAX)
115 return false;
117 int ret = sync_base_file_.Read(offset, static_cast<char*>(buffer),
118 buffer_len);
119 return static_cast<int>(buffer_len) == ret;
122 bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
123 DCHECK(init_);
124 if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
125 return false;
127 int ret = sync_base_file_.Write(offset, static_cast<const char*>(buffer),
128 buffer_len);
129 return static_cast<int>(buffer_len) == ret;
132 // We have to increase the ref counter of the file before performing the IO to
133 // prevent the completion to happen with an invalid handle (if the file is
134 // closed while the IO is in flight).
135 bool File::Read(void* buffer, size_t buffer_len, size_t offset,
136 FileIOCallback* callback, bool* completed) {
137 DCHECK(init_);
138 if (!callback) {
139 if (completed)
140 *completed = true;
141 return Read(buffer, buffer_len, offset);
144 if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
145 return false;
147 MyOverlapped* data = new MyOverlapped(this, offset, callback);
148 DWORD size = static_cast<DWORD>(buffer_len);
150 DWORD actual;
151 if (!ReadFile(base_file_.GetPlatformFile(), buffer, size, &actual,
152 data->overlapped())) {
153 *completed = false;
154 if (GetLastError() == ERROR_IO_PENDING)
155 return true;
156 delete data;
157 return false;
160 // The operation completed already. We'll be called back anyway.
161 *completed = (actual == size);
162 DCHECK_EQ(size, actual);
163 data->callback_ = NULL;
164 data->file_ = NULL; // There is no reason to hold on to this anymore.
165 return *completed;
168 bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
169 FileIOCallback* callback, bool* completed) {
170 DCHECK(init_);
171 if (!callback) {
172 if (completed)
173 *completed = true;
174 return Write(buffer, buffer_len, offset);
177 return AsyncWrite(buffer, buffer_len, offset, callback, completed);
180 File::~File() {
183 base::PlatformFile File::platform_file() const {
184 DCHECK(init_);
185 return base_file_.IsValid() ? base_file_.GetPlatformFile() :
186 sync_base_file_.GetPlatformFile();
189 bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
190 FileIOCallback* callback, bool* completed) {
191 DCHECK(init_);
192 DCHECK(callback);
193 DCHECK(completed);
194 if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
195 return false;
197 MyOverlapped* data = new MyOverlapped(this, offset, callback);
198 DWORD size = static_cast<DWORD>(buffer_len);
200 DWORD actual;
201 if (!WriteFile(base_file_.GetPlatformFile(), buffer, size, &actual,
202 data->overlapped())) {
203 *completed = false;
204 if (GetLastError() == ERROR_IO_PENDING)
205 return true;
206 delete data;
207 return false;
210 // The operation completed already. We'll be called back anyway.
211 *completed = (actual == size);
212 DCHECK_EQ(size, actual);
213 data->callback_ = NULL;
214 data->file_ = NULL; // There is no reason to hold on to this anymore.
215 return *completed;
218 bool File::SetLength(size_t length) {
219 DCHECK(init_);
220 if (length > ULONG_MAX)
221 return false;
223 DWORD size = static_cast<DWORD>(length);
224 HANDLE file = platform_file();
225 if (INVALID_SET_FILE_POINTER == SetFilePointer(file, size, NULL, FILE_BEGIN))
226 return false;
228 return TRUE == SetEndOfFile(file);
231 size_t File::GetLength() {
232 DCHECK(init_);
233 LARGE_INTEGER size;
234 HANDLE file = platform_file();
235 if (!GetFileSizeEx(file, &size))
236 return 0;
237 if (size.HighPart)
238 return ULONG_MAX;
240 return static_cast<size_t>(size.LowPart);
243 // Static.
244 void File::WaitForPendingIO(int* num_pending_io) {
245 while (*num_pending_io) {
246 // Asynchronous IO operations may be in flight and the completion may end
247 // up calling us back so let's wait for them.
248 base::MessageLoopForIO::IOHandler* handler = g_completion_handler.Pointer();
249 base::MessageLoopForIO::current()->WaitForIOCompletion(100, handler);
253 // Static.
254 void File::DropPendingIO() {
257 } // namespace disk_cache