Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: net/base/file_stream_win.cc

Issue 8843: Add write and read/write support to FileStream (renamed from FileInputStream)... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/file_stream_unittest.cc ('k') | net/base/upload_data_stream.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:mergeinfo
Merged /branches/chrome_webkit_merge_branch/net/base/file_input_stream_win.cc:r69-2775
OLDNEW
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "net/base/file_input_stream.h" 5 #include "net/base/file_stream.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 // Ensure that we can just use our Whence values directly. 15 // Ensure that we can just use our Whence values directly.
(...skipping 22 matching lines...) Expand all
38 case ERROR_ACCESS_DENIED: 38 case ERROR_ACCESS_DENIED:
39 return ERR_ACCESS_DENIED; 39 return ERR_ACCESS_DENIED;
40 case ERROR_SUCCESS: 40 case ERROR_SUCCESS:
41 return OK; 41 return OK;
42 default: 42 default:
43 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 43 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
44 return ERR_FAILED; 44 return ERR_FAILED;
45 } 45 }
46 } 46 }
47 47
48 // FileInputStream::AsyncContext ---------------------------------------------- 48 // FileStream::AsyncContext ----------------------------------------------
49 49
50 class FileInputStream::AsyncContext : public MessageLoopForIO::IOHandler { 50 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler {
51 public: 51 public:
52 AsyncContext(FileInputStream* owner) 52 AsyncContext(FileStream* owner)
53 : owner_(owner), overlapped_(), callback_(NULL) { 53 : owner_(owner), overlapped_(), callback_(NULL) {
54 overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 54 overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
55 } 55 }
56 56
57 ~AsyncContext() { 57 ~AsyncContext() {
58 if (callback_) 58 if (callback_)
59 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL); 59 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
60 CloseHandle(overlapped_.hEvent); 60 CloseHandle(overlapped_.hEvent);
61 } 61 }
62 62
63 void IOCompletionIsPending(CompletionCallback* callback); 63 void IOCompletionIsPending(CompletionCallback* callback);
64 64
65 OVERLAPPED* overlapped() { return &overlapped_; } 65 OVERLAPPED* overlapped() { return &overlapped_; }
66 CompletionCallback* callback() const { return callback_; } 66 CompletionCallback* callback() const { return callback_; }
67 67
68 private: 68 private:
69 // MessageLoopForIO::IOHandler implementation: 69 // MessageLoopForIO::IOHandler implementation:
70 virtual void OnIOCompleted(OVERLAPPED* context, DWORD bytes_read, 70 virtual void OnIOCompleted(OVERLAPPED* context, DWORD num_bytes,
71 DWORD error); 71 DWORD error);
72 72
73 FileInputStream* owner_; 73 FileStream* owner_;
74 OVERLAPPED overlapped_; 74 OVERLAPPED overlapped_;
75 CompletionCallback* callback_; 75 CompletionCallback* callback_;
76 }; 76 };
77 77
78 void FileInputStream::AsyncContext::IOCompletionIsPending( 78 void FileStream::AsyncContext::IOCompletionIsPending(
79 CompletionCallback* callback) { 79 CompletionCallback* callback) {
80 DCHECK(!callback_); 80 DCHECK(!callback_);
81 callback_ = callback; 81 callback_ = callback;
82 82
83 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, this); 83 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, this);
84 } 84 }
85 85
86 void FileInputStream::AsyncContext::OnIOCompleted(OVERLAPPED* context, 86 void FileStream::AsyncContext::OnIOCompleted(OVERLAPPED* context,
87 DWORD bytes_read, 87 DWORD num_bytes,
88 DWORD error) { 88 DWORD error) {
89 DCHECK(&overlapped_ == context); 89 DCHECK(&overlapped_ == context);
90 DCHECK(callback_); 90 DCHECK(callback_);
91 91
92 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL); 92 MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
93 93
94 HANDLE handle = owner_->handle_; 94 HANDLE handle = owner_->file_;
95 95
96 int result = static_cast<int>(bytes_read); 96 int result = static_cast<int>(num_bytes);
97 if (error && error != ERROR_HANDLE_EOF) 97 if (error && error != ERROR_HANDLE_EOF)
98 result = MapErrorCode(error); 98 result = MapErrorCode(error);
99 99
100 if (bytes_read) 100 if (num_bytes)
101 IncrementOffset(&overlapped_, bytes_read); 101 IncrementOffset(&overlapped_, num_bytes);
102 102
103 CompletionCallback* temp = NULL; 103 CompletionCallback* temp = NULL;
104 std::swap(temp, callback_); 104 std::swap(temp, callback_);
105 temp->Run(result); 105 temp->Run(result);
106 } 106 }
107 107
108 // FileInputStream ------------------------------------------------------------ 108 // FileStream ------------------------------------------------------------
109 109
110 FileInputStream::FileInputStream() : handle_(INVALID_HANDLE_VALUE) { 110 FileStream::FileStream() : file_(INVALID_HANDLE_VALUE) {
111 } 111 }
112 112
113 FileInputStream::~FileInputStream() { 113 FileStream::~FileStream() {
114 Close(); 114 Close();
115 } 115 }
116 116
117 void FileInputStream::Close() { 117 void FileStream::Close() {
118 if (handle_ != INVALID_HANDLE_VALUE) { 118 if (file_ != INVALID_HANDLE_VALUE) {
119 CloseHandle(handle_); 119 CloseHandle(file_);
120 handle_ = INVALID_HANDLE_VALUE; 120 file_ = INVALID_HANDLE_VALUE;
121 } 121 }
122 async_context_.reset(); 122 async_context_.reset();
123 } 123 }
124 124
125 int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) { 125 int FileStream::Open(const std::wstring& path, int open_flags) {
126 if (IsOpen()) { 126 if (IsOpen()) {
127 DLOG(FATAL) << "File is already open!"; 127 DLOG(FATAL) << "File is already open!";
128 return ERR_UNEXPECTED; 128 return ERR_UNEXPECTED;
129 } 129 }
130 130
131 // Optimize for streaming, not seeking. If someone does a lot of random 131 open_flags_ = open_flags;
132 // access operations, then we should consider revising this. 132 file_ = base::CreatePlatformFile(path, open_flags_, NULL);
133 DWORD create_file_flags = FILE_FLAG_SEQUENTIAL_SCAN; 133 if (file_ == INVALID_HANDLE_VALUE) {
134
135 if (asynchronous_mode)
136 create_file_flags |= FILE_FLAG_OVERLAPPED;
137
138 handle_ =
139 CreateFile(path.c_str(), GENERIC_READ | SYNCHRONIZE,
140 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
141 NULL, OPEN_EXISTING, create_file_flags, NULL);
142 if (handle_ == INVALID_HANDLE_VALUE) {
143 DWORD error = GetLastError(); 134 DWORD error = GetLastError();
144 LOG(WARNING) << "Failed to open file: " << error; 135 LOG(WARNING) << "Failed to open file: " << error;
145 return MapErrorCode(error); 136 return MapErrorCode(error);
146 } 137 }
147 138
148 if (asynchronous_mode) { 139 if (open_flags_ & base::PLATFORM_FILE_ASYNC) {
149 async_context_.reset(new AsyncContext(this)); 140 async_context_.reset(new AsyncContext(this));
150 MessageLoopForIO::current()->RegisterIOHandler(handle_, 141 MessageLoopForIO::current()->RegisterIOHandler(file_,
151 async_context_.get()); 142 async_context_.get());
152 } 143 }
153 144
154 return OK; 145 return OK;
155 } 146 }
156 147
157 bool FileInputStream::IsOpen() const { 148 bool FileStream::IsOpen() const {
158 return handle_ != INVALID_HANDLE_VALUE; 149 return file_ != INVALID_HANDLE_VALUE;
159 } 150 }
160 151
161 int64 FileInputStream::Seek(Whence whence, int64 offset) { 152 int64 FileStream::Seek(Whence whence, int64 offset) {
162 if (!IsOpen()) 153 if (!IsOpen())
163 return ERR_UNEXPECTED; 154 return ERR_UNEXPECTED;
164 DCHECK(!async_context_.get() || !async_context_->callback()); 155 DCHECK(!async_context_.get() || !async_context_->callback());
165 156
166 LARGE_INTEGER distance, result; 157 LARGE_INTEGER distance, result;
167 distance.QuadPart = offset; 158 distance.QuadPart = offset;
168 DWORD move_method = static_cast<DWORD>(whence); 159 DWORD move_method = static_cast<DWORD>(whence);
169 if (!SetFilePointerEx(handle_, distance, &result, move_method)) { 160 if (!SetFilePointerEx(file_, distance, &result, move_method)) {
170 DWORD error = GetLastError(); 161 DWORD error = GetLastError();
171 LOG(WARNING) << "SetFilePointerEx failed: " << error; 162 LOG(WARNING) << "SetFilePointerEx failed: " << error;
172 return MapErrorCode(error); 163 return MapErrorCode(error);
173 } 164 }
174 if (async_context_.get()) 165 if (async_context_.get())
175 SetOffset(async_context_->overlapped(), result); 166 SetOffset(async_context_->overlapped(), result);
176 return result.QuadPart; 167 return result.QuadPart;
177 } 168 }
178 169
179 int64 FileInputStream::Available() { 170 int64 FileStream::Available() {
180 if (!IsOpen()) 171 if (!IsOpen())
181 return ERR_UNEXPECTED; 172 return ERR_UNEXPECTED;
182 173
183 int64 cur_pos = Seek(FROM_CURRENT, 0); 174 int64 cur_pos = Seek(FROM_CURRENT, 0);
184 if (cur_pos < 0) 175 if (cur_pos < 0)
185 return cur_pos; 176 return cur_pos;
186 177
187 LARGE_INTEGER file_size; 178 LARGE_INTEGER file_size;
188 if (!GetFileSizeEx(handle_, &file_size)) { 179 if (!GetFileSizeEx(file_, &file_size)) {
189 DWORD error = GetLastError(); 180 DWORD error = GetLastError();
190 LOG(WARNING) << "GetFileSizeEx failed: " << error; 181 LOG(WARNING) << "GetFileSizeEx failed: " << error;
191 return MapErrorCode(error); 182 return MapErrorCode(error);
192 } 183 }
193 184
194 return file_size.QuadPart - cur_pos; 185 return file_size.QuadPart - cur_pos;
195 } 186 }
196 187
197 int FileInputStream::Read( 188 int FileStream::Read(
198 char* buf, int buf_len, CompletionCallback* callback) { 189 char* buf, int buf_len, CompletionCallback* callback) {
199 if (!IsOpen()) 190 if (!IsOpen())
200 return ERR_UNEXPECTED; 191 return ERR_UNEXPECTED;
192 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
201 193
202 OVERLAPPED* overlapped = NULL; 194 OVERLAPPED* overlapped = NULL;
203 if (async_context_.get()) { 195 if (async_context_.get()) {
204 DCHECK(!async_context_->callback()); 196 DCHECK(!async_context_->callback());
205 overlapped = async_context_->overlapped(); 197 overlapped = async_context_->overlapped();
206 } 198 }
207 199
208 int rv; 200 int rv;
209 201
210 DWORD bytes_read; 202 DWORD bytes_read;
211 if (!ReadFile(handle_, buf, buf_len, &bytes_read, overlapped)) { 203 if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) {
212 DWORD error = GetLastError(); 204 DWORD error = GetLastError();
213 if (async_context_.get() && error == ERROR_IO_PENDING) { 205 if (async_context_.get() && error == ERROR_IO_PENDING) {
214 async_context_->IOCompletionIsPending(callback); 206 async_context_->IOCompletionIsPending(callback);
215 rv = ERR_IO_PENDING; 207 rv = ERR_IO_PENDING;
216 } else if (error == ERROR_HANDLE_EOF) { 208 } else if (error == ERROR_HANDLE_EOF) {
217 rv = 0; // Report EOF by returning 0 bytes read. 209 rv = 0; // Report EOF by returning 0 bytes read.
218 } else { 210 } else {
219 LOG(WARNING) << "ReadFile failed: " << error; 211 LOG(WARNING) << "ReadFile failed: " << error;
220 rv = MapErrorCode(error); 212 rv = MapErrorCode(error);
221 } 213 }
222 } else { 214 } else {
223 if (overlapped) 215 if (overlapped)
224 IncrementOffset(overlapped, bytes_read); 216 IncrementOffset(overlapped, bytes_read);
225 rv = static_cast<int>(bytes_read); 217 rv = static_cast<int>(bytes_read);
226 } 218 }
227 return rv; 219 return rv;
228 } 220 }
229 221
222 int FileStream::Write(
223 const char* buf, int buf_len, CompletionCallback* callback) {
224 if (!IsOpen())
225 return ERR_UNEXPECTED;
226 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
227
228 OVERLAPPED* overlapped = NULL;
229 if (async_context_.get()) {
230 DCHECK(!async_context_->callback());
231 overlapped = async_context_->overlapped();
232 }
233
234 int rv;
235 DWORD bytes_written;
236 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) {
237 DWORD error = GetLastError();
238 if (async_context_.get() && error == ERROR_IO_PENDING) {
239 async_context_->IOCompletionIsPending(callback);
240 rv = ERR_IO_PENDING;
241 } else {
242 LOG(WARNING) << "WriteFile failed: " << error;
243 rv = MapErrorCode(error);
244 }
245 } else {
246 if (overlapped)
247 IncrementOffset(overlapped, bytes_written);
248 rv = static_cast<int>(bytes_written);
249 }
250 return rv;
251 }
252
230 } // namespace net 253 } // namespace net
254
OLDNEW
« no previous file with comments | « net/base/file_stream_unittest.cc ('k') | net/base/upload_data_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698