OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/base/file_stream_context.h" | 5 #include "net/base/file_stream_context.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/task_runner.h" | 12 #include "base/task_runner.h" |
13 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
14 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
15 | 15 |
16 namespace net { | 16 namespace net { |
17 | 17 |
18 // Ensure that we can just use our Whence values directly. | |
19 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); | |
20 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); | |
21 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); | |
22 | |
23 namespace { | 18 namespace { |
24 | 19 |
25 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { | 20 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { |
26 overlapped->Offset = offset.LowPart; | 21 overlapped->Offset = offset.LowPart; |
27 overlapped->OffsetHigh = offset.HighPart; | 22 overlapped->OffsetHigh = offset.HighPart; |
28 } | 23 } |
29 | 24 |
30 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { | 25 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { |
31 LARGE_INTEGER offset; | 26 LARGE_INTEGER offset; |
32 offset.LowPart = overlapped->Offset; | 27 offset.LowPart = overlapped->Offset; |
(...skipping 16 matching lines...) Expand all Loading... | |
49 FileStream::Context::Context(base::File file, | 44 FileStream::Context::Context(base::File file, |
50 const scoped_refptr<base::TaskRunner>& task_runner) | 45 const scoped_refptr<base::TaskRunner>& task_runner) |
51 : io_context_(), | 46 : io_context_(), |
52 file_(file.Pass()), | 47 file_(file.Pass()), |
53 async_in_progress_(false), | 48 async_in_progress_(false), |
54 orphaned_(false), | 49 orphaned_(false), |
55 task_runner_(task_runner) { | 50 task_runner_(task_runner) { |
56 io_context_.handler = this; | 51 io_context_.handler = this; |
57 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); | 52 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); |
58 if (file_.IsValid()) { | 53 if (file_.IsValid()) { |
59 // TODO(hashimoto): Check that file_ is async. | 54 // TODO(hashimoto): Check that file_ is async. |
wtc
2014/06/19 18:20:49
Should we remove this TODO comment? It makes more
rvargas (doing something else)
2014/06/19 18:46:43
I thought about it, but this is really related to
| |
60 OnAsyncFileOpened(); | 55 OnFileOpened(); |
61 } | 56 } |
62 } | 57 } |
63 | 58 |
64 FileStream::Context::~Context() { | 59 FileStream::Context::~Context() { |
65 } | 60 } |
66 | 61 |
67 int FileStream::Context::ReadAsync(IOBuffer* buf, | 62 int FileStream::Context::Read(IOBuffer* buf, |
68 int buf_len, | 63 int buf_len, |
69 const CompletionCallback& callback) { | 64 const CompletionCallback& callback) { |
70 DCHECK(!async_in_progress_); | 65 DCHECK(!async_in_progress_); |
71 | 66 |
72 DWORD bytes_read; | 67 DWORD bytes_read; |
73 if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len, | 68 if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len, |
74 &bytes_read, &io_context_.overlapped)) { | 69 &bytes_read, &io_context_.overlapped)) { |
75 IOResult error = IOResult::FromOSError(GetLastError()); | 70 IOResult error = IOResult::FromOSError(GetLastError()); |
76 if (error.os_error == ERROR_IO_PENDING) { | 71 if (error.os_error == ERROR_IO_PENDING) { |
77 IOCompletionIsPending(callback, buf); | 72 IOCompletionIsPending(callback, buf); |
78 } else if (error.os_error == ERROR_HANDLE_EOF) { | 73 } else if (error.os_error == ERROR_HANDLE_EOF) { |
79 return 0; // Report EOF by returning 0 bytes read. | 74 return 0; // Report EOF by returning 0 bytes read. |
80 } else { | 75 } else { |
81 LOG(WARNING) << "ReadFile failed: " << error.os_error; | 76 LOG(WARNING) << "ReadFile failed: " << error.os_error; |
82 } | 77 } |
83 return error.result; | 78 return error.result; |
84 } | 79 } |
85 | 80 |
86 IOCompletionIsPending(callback, buf); | 81 IOCompletionIsPending(callback, buf); |
87 return ERR_IO_PENDING; | 82 return ERR_IO_PENDING; |
88 } | 83 } |
89 | 84 |
90 int FileStream::Context::WriteAsync(IOBuffer* buf, | 85 int FileStream::Context::Write(IOBuffer* buf, |
91 int buf_len, | 86 int buf_len, |
92 const CompletionCallback& callback) { | 87 const CompletionCallback& callback) { |
93 DWORD bytes_written = 0; | 88 DWORD bytes_written = 0; |
94 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, | 89 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, |
95 &bytes_written, &io_context_.overlapped)) { | 90 &bytes_written, &io_context_.overlapped)) { |
96 IOResult error = IOResult::FromOSError(GetLastError()); | 91 IOResult error = IOResult::FromOSError(GetLastError()); |
97 if (error.os_error == ERROR_IO_PENDING) { | 92 if (error.os_error == ERROR_IO_PENDING) { |
98 IOCompletionIsPending(callback, buf); | 93 IOCompletionIsPending(callback, buf); |
99 } else { | 94 } else { |
100 LOG(WARNING) << "WriteFile failed: " << error.os_error; | 95 LOG(WARNING) << "WriteFile failed: " << error.os_error; |
101 } | 96 } |
102 return error.result; | 97 return error.result; |
103 } | 98 } |
104 | 99 |
105 IOCompletionIsPending(callback, buf); | 100 IOCompletionIsPending(callback, buf); |
106 return ERR_IO_PENDING; | 101 return ERR_IO_PENDING; |
107 } | 102 } |
108 | 103 |
109 void FileStream::Context::OnAsyncFileOpened() { | 104 FileStream::Context::IOResult FileStream::Context::SeekFileImpl( |
110 base::MessageLoopForIO::current()->RegisterIOHandler(file_.GetPlatformFile(), | 105 base::File::Whence whence, |
111 this); | 106 int64 offset) { |
112 } | 107 LARGE_INTEGER result; |
113 | 108 result.QuadPart = file_.Seek(whence, offset); |
114 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence, | 109 if (result.QuadPart >= 0) { |
115 int64 offset) { | 110 SetOffset(&io_context_.overlapped, result); |
116 LARGE_INTEGER distance, res; | 111 return IOResult(result.QuadPart, 0); |
117 distance.QuadPart = offset; | |
118 DWORD move_method = static_cast<DWORD>(whence); | |
119 if (SetFilePointerEx(file_.GetPlatformFile(), distance, &res, move_method)) { | |
120 SetOffset(&io_context_.overlapped, res); | |
121 return IOResult(res.QuadPart, 0); | |
122 } | 112 } |
123 | 113 |
124 return IOResult::FromOSError(GetLastError()); | 114 return IOResult::FromOSError(GetLastError()); |
125 } | 115 } |
126 | 116 |
127 FileStream::Context::IOResult FileStream::Context::FlushFileImpl() { | 117 void FileStream::Context::OnFileOpened() { |
128 if (FlushFileBuffers(file_.GetPlatformFile())) | 118 base::MessageLoopForIO::current()->RegisterIOHandler(file_.GetPlatformFile(), |
129 return IOResult(OK, 0); | 119 this); |
130 | |
131 return IOResult::FromOSError(GetLastError()); | |
132 } | 120 } |
133 | 121 |
134 void FileStream::Context::IOCompletionIsPending( | 122 void FileStream::Context::IOCompletionIsPending( |
135 const CompletionCallback& callback, | 123 const CompletionCallback& callback, |
136 IOBuffer* buf) { | 124 IOBuffer* buf) { |
137 DCHECK(callback_.is_null()); | 125 DCHECK(callback_.is_null()); |
138 callback_ = callback; | 126 callback_ = callback; |
139 in_flight_buf_ = buf; // Hold until the async operation ends. | 127 in_flight_buf_ = buf; // Hold until the async operation ends. |
140 async_in_progress_ = true; | 128 async_in_progress_ = true; |
141 } | 129 } |
(...skipping 26 matching lines...) Expand all Loading... | |
168 } | 156 } |
169 | 157 |
170 CompletionCallback temp_callback = callback_; | 158 CompletionCallback temp_callback = callback_; |
171 callback_.Reset(); | 159 callback_.Reset(); |
172 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; | 160 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; |
173 in_flight_buf_ = NULL; | 161 in_flight_buf_ = NULL; |
174 temp_callback.Run(result); | 162 temp_callback.Run(result); |
175 } | 163 } |
176 | 164 |
177 } // namespace net | 165 } // namespace net |
OLD | NEW |