OLD | NEW |
---|---|
1 // Copyright (c) 2011 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 // For 64-bit file access (off_t = off64_t, lseek64, etc). | 5 // For 64-bit file access (off_t = off64_t, lseek64, etc). |
6 #define _FILE_OFFSET_BITS 64 | 6 #define _FILE_OFFSET_BITS 64 |
7 | 7 |
8 #include "net/base/file_stream.h" | 8 #include "net/base/file_stream.h" |
9 | 9 |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
12 #include <fcntl.h> | 12 #include <fcntl.h> |
13 #include <unistd.h> | 13 #include <unistd.h> |
14 #include <errno.h> | 14 #include <errno.h> |
15 | 15 |
16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
17 #include "base/bind.h" | 17 #include "base/bind.h" |
18 #include "base/bind_helpers.h" | 18 #include "base/bind_helpers.h" |
19 #include "base/callback.h" | 19 #include "base/callback.h" |
20 #include "base/eintr_wrapper.h" | 20 #include "base/eintr_wrapper.h" |
21 #include "base/file_path.h" | 21 #include "base/file_path.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/message_loop.h" | 23 #include "base/message_loop.h" |
24 #include "base/metrics/histogram.h" | 24 #include "base/metrics/histogram.h" |
25 #include "base/string_util.h" | 25 #include "base/string_util.h" |
26 #include "base/threading/thread_restrictions.h" | 26 #include "base/threading/thread_restrictions.h" |
27 #include "base/threading/worker_pool.h" | 27 #include "base/threading/worker_pool.h" |
28 #include "base/synchronization/waitable_event.h" | 28 #include "base/synchronization/waitable_event.h" |
29 #include "net/base/file_stream_metrics.h" | 29 #include "net/base/file_stream_metrics.h" |
30 #include "net/base/file_stream_net_log_parameters.h" | |
30 #include "net/base/net_errors.h" | 31 #include "net/base/net_errors.h" |
31 | 32 |
32 #if defined(OS_ANDROID) | 33 #if defined(OS_ANDROID) |
33 // Android's bionic libc only supports the LFS transitional API. | 34 // Android's bionic libc only supports the LFS transitional API. |
34 #define off_t off64_t | 35 #define off_t off64_t |
35 #define lseek lseek64 | 36 #define lseek lseek64 |
36 #define stat stat64 | 37 #define stat stat64 |
37 #define fstat fstat64 | 38 #define fstat fstat64 |
38 #endif | 39 #endif |
39 | 40 |
40 namespace net { | 41 namespace net { |
41 | 42 |
42 // We cast back and forth, so make sure it's the size we're expecting. | 43 // We cast back and forth, so make sure it's the size we're expecting. |
43 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); | 44 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); |
44 | 45 |
45 // Make sure our Whence mappings match the system headers. | 46 // Make sure our Whence mappings match the system headers. |
46 COMPILE_ASSERT(FROM_BEGIN == SEEK_SET && | 47 COMPILE_ASSERT(FROM_BEGIN == SEEK_SET && |
47 FROM_CURRENT == SEEK_CUR && | 48 FROM_CURRENT == SEEK_CUR && |
48 FROM_END == SEEK_END, whence_matches_system); | 49 FROM_END == SEEK_END, whence_matches_system); |
49 | 50 |
50 namespace { | 51 namespace { |
51 | 52 |
52 int RecordAndMapError(int error, FileErrorSource source, bool record_uma) { | 53 int RecordAndMapError(int error, |
54 FileErrorSource source, | |
55 bool record_uma, | |
56 const net::BoundNetLog& bound_net_log) { | |
57 bound_net_log.AddEvent( | |
58 net::NetLog::TYPE_FILE_STREAM_ERROR, | |
59 make_scoped_refptr( | |
60 new FileStreamErrorParameters( | |
61 GetFileErrorSourceName(source), | |
mmenke
2012/01/31 22:33:51
You might want to just pass |source|, and only cal
ahendrickson
2012/01/31 23:14:33
Unless someone feels strongly about it, I'm going
| |
62 error, | |
63 MapSystemError(error)))); | |
64 | |
53 RecordFileError(error, source, record_uma); | 65 RecordFileError(error, source, record_uma); |
54 return MapSystemError(error); | 66 return MapSystemError(error); |
55 } | 67 } |
56 | 68 |
57 // ReadFile() is a simple wrapper around read() that handles EINTR signals and | 69 // ReadFile() is a simple wrapper around read() that handles EINTR signals and |
58 // calls MapSystemError() to map errno to net error codes. | 70 // calls MapSystemError() to map errno to net error codes. |
59 int ReadFile(base::PlatformFile file, char* buf, int buf_len, bool record_uma) { | 71 int ReadFile(base::PlatformFile file, |
72 char* buf, | |
73 int buf_len, | |
74 bool record_uma, | |
75 const net::BoundNetLog& bound_net_log) { | |
60 base::ThreadRestrictions::AssertIOAllowed(); | 76 base::ThreadRestrictions::AssertIOAllowed(); |
61 // read(..., 0) returns 0 to indicate end-of-file. | 77 // read(..., 0) returns 0 to indicate end-of-file. |
62 | 78 |
63 // Loop in the case of getting interrupted by a signal. | 79 // Loop in the case of getting interrupted by a signal. |
64 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len))); | 80 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len))); |
65 if (res == static_cast<ssize_t>(-1)) | 81 if (res == static_cast<ssize_t>(-1)) |
66 RecordAndMapError(errno, FILE_ERROR_SOURCE_READ, record_uma); | 82 RecordAndMapError(errno, FILE_ERROR_SOURCE_READ, record_uma, bound_net_log); |
67 return static_cast<int>(res); | 83 return static_cast<int>(res); |
68 } | 84 } |
69 | 85 |
70 void ReadFileTask(base::PlatformFile file, | 86 void ReadFileTask(base::PlatformFile file, |
71 char* buf, | 87 char* buf, |
72 int buf_len, | 88 int buf_len, |
73 bool record_uma, | 89 bool record_uma, |
90 const net::BoundNetLog& bound_net_log, | |
74 const CompletionCallback& callback) { | 91 const CompletionCallback& callback) { |
75 callback.Run(ReadFile(file, buf, buf_len, record_uma)); | 92 callback.Run(ReadFile(file, buf, buf_len, record_uma, bound_net_log)); |
76 } | 93 } |
77 | 94 |
78 // WriteFile() is a simple wrapper around write() that handles EINTR signals and | 95 // WriteFile() is a simple wrapper around write() that handles EINTR signals and |
79 // calls MapSystemError() to map errno to net error codes. It tries to write to | 96 // calls MapSystemError() to map errno to net error codes. It tries to write to |
80 // completion. | 97 // completion. |
81 int WriteFile(base::PlatformFile file, const char* buf, int buf_len, | 98 int WriteFile(base::PlatformFile file, |
82 bool record_uma) { | 99 const char* buf, |
100 int buf_len, | |
101 bool record_uma, | |
102 const net::BoundNetLog& bound_net_log) { | |
83 base::ThreadRestrictions::AssertIOAllowed(); | 103 base::ThreadRestrictions::AssertIOAllowed(); |
84 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len)); | 104 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len)); |
85 if (res == -1) | 105 if (res == -1) { |
86 RecordAndMapError(errno, FILE_ERROR_SOURCE_WRITE, record_uma); | 106 RecordAndMapError(errno, FILE_ERROR_SOURCE_WRITE, record_uma, |
107 bound_net_log); | |
108 } | |
87 return res; | 109 return res; |
88 } | 110 } |
89 | 111 |
90 void WriteFileTask(base::PlatformFile file, | 112 void WriteFileTask(base::PlatformFile file, |
91 const char* buf, | 113 const char* buf, |
92 int buf_len, bool record_uma, | 114 int buf_len, |
115 bool record_uma, | |
116 const net::BoundNetLog& bound_net_log, | |
93 const CompletionCallback& callback) { | 117 const CompletionCallback& callback) { |
94 callback.Run(WriteFile(file, buf, buf_len, record_uma)); | 118 callback.Run(WriteFile(file, buf, buf_len, record_uma, bound_net_log)); |
95 } | 119 } |
96 | 120 |
97 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and | 121 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and |
98 // calls MapSystemError() to map errno to net error codes. It tries to flush to | 122 // calls MapSystemError() to map errno to net error codes. It tries to flush to |
99 // completion. | 123 // completion. |
100 int FlushFile(base::PlatformFile file, bool record_uma) { | 124 int FlushFile(base::PlatformFile file, |
125 bool record_uma, | |
126 const net::BoundNetLog& bound_net_log) { | |
101 base::ThreadRestrictions::AssertIOAllowed(); | 127 base::ThreadRestrictions::AssertIOAllowed(); |
102 ssize_t res = HANDLE_EINTR(fsync(file)); | 128 ssize_t res = HANDLE_EINTR(fsync(file)); |
103 if (res == -1) | 129 if (res == -1) { |
104 RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma); | 130 RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma, |
131 bound_net_log); | |
132 } | |
105 return res; | 133 return res; |
106 } | 134 } |
107 | 135 |
108 } // namespace | 136 } // namespace |
109 | 137 |
110 // Cancelable wrapper around a Closure. | 138 // Cancelable wrapper around a Closure. |
111 class CancelableCallback { | 139 class CancelableCallback { |
112 public: | 140 public: |
113 explicit CancelableCallback(const base::Closure& callback) | 141 explicit CancelableCallback(const base::Closure& callback) |
114 : canceled_(false), | 142 : canceled_(false), |
(...skipping 16 matching lines...) Expand all Loading... | |
131 // FileStream::AsyncContext ---------------------------------------------- | 159 // FileStream::AsyncContext ---------------------------------------------- |
132 | 160 |
133 class FileStream::AsyncContext { | 161 class FileStream::AsyncContext { |
134 public: | 162 public: |
135 AsyncContext(); | 163 AsyncContext(); |
136 ~AsyncContext(); | 164 ~AsyncContext(); |
137 | 165 |
138 // These methods post synchronous read() and write() calls to a WorkerThread. | 166 // These methods post synchronous read() and write() calls to a WorkerThread. |
139 void InitiateAsyncRead( | 167 void InitiateAsyncRead( |
140 base::PlatformFile file, char* buf, int buf_len, | 168 base::PlatformFile file, char* buf, int buf_len, |
169 const net::BoundNetLog& bound_net_log, | |
141 const CompletionCallback& callback); | 170 const CompletionCallback& callback); |
142 void InitiateAsyncWrite( | 171 void InitiateAsyncWrite( |
143 base::PlatformFile file, const char* buf, int buf_len, | 172 base::PlatformFile file, const char* buf, int buf_len, |
173 const net::BoundNetLog& bound_net_log, | |
144 const CompletionCallback& callback); | 174 const CompletionCallback& callback); |
145 | 175 |
146 const CompletionCallback& callback() const { return callback_; } | 176 const CompletionCallback& callback() const { return callback_; } |
147 | 177 |
148 // Called by the WorkerPool thread executing the IO after the IO completes. | 178 // Called by the WorkerPool thread executing the IO after the IO completes. |
149 // This method queues RunAsynchronousCallback() on the MessageLoop and signals | 179 // This method queues RunAsynchronousCallback() on the MessageLoop and signals |
150 // |background_io_completed_callback_|, in case the destructor is waiting. In | 180 // |background_io_completed_callback_|, in case the destructor is waiting. In |
151 // that case, the destructor will call RunAsynchronousCallback() instead, and | 181 // that case, the destructor will call RunAsynchronousCallback() instead, and |
152 // cancel |message_loop_task_|. | 182 // cancel |message_loop_task_|. |
153 // |result| is the result of the Read/Write task. | 183 // |result| is the result of the Read/Write task. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 if (need_to_wait) { | 230 if (need_to_wait) { |
201 // We want to see if we block the message loop for too long. | 231 // We want to see if we block the message loop for too long. |
202 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", | 232 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", |
203 base::TimeTicks::Now() - start); | 233 base::TimeTicks::Now() - start); |
204 } | 234 } |
205 } | 235 } |
206 } | 236 } |
207 | 237 |
208 void FileStream::AsyncContext::InitiateAsyncRead( | 238 void FileStream::AsyncContext::InitiateAsyncRead( |
209 base::PlatformFile file, char* buf, int buf_len, | 239 base::PlatformFile file, char* buf, int buf_len, |
240 const net::BoundNetLog& bound_net_log, | |
210 const CompletionCallback& callback) { | 241 const CompletionCallback& callback) { |
211 DCHECK(callback_.is_null()); | 242 DCHECK(callback_.is_null()); |
212 callback_ = callback; | 243 callback_ = callback; |
213 | 244 |
214 base::WorkerPool::PostTask( | 245 base::WorkerPool::PostTask( |
215 FROM_HERE, | 246 FROM_HERE, |
216 base::Bind(&ReadFileTask, file, buf, buf_len, | 247 base::Bind(&ReadFileTask, |
248 file, | |
249 buf, | |
250 buf_len, | |
217 record_uma_, | 251 record_uma_, |
252 bound_net_log, | |
218 base::Bind(&AsyncContext::OnBackgroundIOCompleted, | 253 base::Bind(&AsyncContext::OnBackgroundIOCompleted, |
219 base::Unretained(this))), | 254 base::Unretained(this))), |
220 true /* task_is_slow */); | 255 true /* task_is_slow */); |
221 } | 256 } |
222 | 257 |
223 void FileStream::AsyncContext::InitiateAsyncWrite( | 258 void FileStream::AsyncContext::InitiateAsyncWrite( |
224 base::PlatformFile file, const char* buf, int buf_len, | 259 base::PlatformFile file, const char* buf, int buf_len, |
260 const net::BoundNetLog& bound_net_log, | |
225 const CompletionCallback& callback) { | 261 const CompletionCallback& callback) { |
226 DCHECK(callback_.is_null()); | 262 DCHECK(callback_.is_null()); |
227 callback_ = callback; | 263 callback_ = callback; |
228 | 264 |
229 base::WorkerPool::PostTask( | 265 base::WorkerPool::PostTask( |
230 FROM_HERE, | 266 FROM_HERE, |
231 base::Bind( | 267 base::Bind(&WriteFileTask, |
232 &WriteFileTask, | 268 file, |
233 file, buf, buf_len, | 269 buf, |
234 record_uma_, | 270 buf_len, |
235 base::Bind(&AsyncContext::OnBackgroundIOCompleted, | 271 record_uma_, |
236 base::Unretained(this))), | 272 bound_net_log, |
273 base::Bind(&AsyncContext::OnBackgroundIOCompleted, | |
274 base::Unretained(this))), | |
237 true /* task_is_slow */); | 275 true /* task_is_slow */); |
238 } | 276 } |
239 | 277 |
240 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) { | 278 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) { |
241 result_ = result; | 279 result_ = result; |
242 message_loop_task_ = new CancelableCallback( | 280 message_loop_task_ = new CancelableCallback( |
243 base::Bind(&AsyncContext::RunAsynchronousCallback, | 281 base::Bind(&AsyncContext::RunAsynchronousCallback, |
244 base::Unretained(this))); | 282 base::Unretained(this))); |
245 message_loop_->PostTask(FROM_HERE, | 283 message_loop_->PostTask(FROM_HERE, |
246 base::Bind(&CancelableCallback::Run, | 284 base::Bind(&CancelableCallback::Run, |
(...skipping 19 matching lines...) Expand all Loading... | |
266 | 304 |
267 DCHECK(!callback_.is_null()); | 305 DCHECK(!callback_.is_null()); |
268 CompletionCallback temp; | 306 CompletionCallback temp; |
269 std::swap(temp, callback_); | 307 std::swap(temp, callback_); |
270 background_io_completed_.Reset(); | 308 background_io_completed_.Reset(); |
271 temp.Run(result_); | 309 temp.Run(result_); |
272 } | 310 } |
273 | 311 |
274 // FileStream ------------------------------------------------------------ | 312 // FileStream ------------------------------------------------------------ |
275 | 313 |
276 FileStream::FileStream() | 314 FileStream::FileStream(net::NetLog* net_log) |
277 : file_(base::kInvalidPlatformFileValue), | 315 : file_(base::kInvalidPlatformFileValue), |
278 open_flags_(0), | 316 open_flags_(0), |
279 auto_closed_(true), | 317 auto_closed_(true), |
280 record_uma_(false) { | 318 record_uma_(false), |
281 DCHECK(!IsOpen()); | 319 bound_net_log_(net::BoundNetLog::Make(net_log, |
320 net::NetLog::SOURCE_FILESTREAM)) { | |
321 bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); | |
282 } | 322 } |
283 | 323 |
284 FileStream::FileStream(base::PlatformFile file, int flags) | 324 FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log) |
285 : file_(file), | 325 : file_(file), |
286 open_flags_(flags), | 326 open_flags_(flags), |
287 auto_closed_(false), | 327 auto_closed_(false), |
288 record_uma_(false) { | 328 record_uma_(false), |
329 bound_net_log_(net::BoundNetLog::Make(net_log, | |
330 net::NetLog::SOURCE_FILESTREAM)) { | |
331 bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); | |
332 | |
289 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to | 333 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to |
290 // make sure we will perform asynchronous File IO to it. | 334 // make sure we will perform asynchronous File IO to it. |
291 if (flags & base::PLATFORM_FILE_ASYNC) { | 335 if (flags & base::PLATFORM_FILE_ASYNC) { |
292 async_context_.reset(new AsyncContext()); | 336 async_context_.reset(new AsyncContext()); |
293 } | 337 } |
294 } | 338 } |
295 | 339 |
296 FileStream::~FileStream() { | 340 FileStream::~FileStream() { |
297 if (auto_closed_) | 341 if (auto_closed_) |
298 Close(); | 342 Close(); |
343 | |
344 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); | |
299 } | 345 } |
300 | 346 |
301 void FileStream::Close() { | 347 void FileStream::Close() { |
348 bound_net_log_.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); | |
349 | |
302 // Abort any existing asynchronous operations. | 350 // Abort any existing asynchronous operations. |
303 async_context_.reset(); | 351 async_context_.reset(); |
304 | 352 |
305 if (file_ != base::kInvalidPlatformFileValue) { | 353 if (file_ != base::kInvalidPlatformFileValue) { |
306 if (close(file_) != 0) { | 354 if (close(file_) != 0) { |
307 NOTREACHED(); | 355 NOTREACHED(); |
308 } | 356 } |
309 file_ = base::kInvalidPlatformFileValue; | 357 file_ = base::kInvalidPlatformFileValue; |
358 | |
359 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); | |
310 } | 360 } |
311 } | 361 } |
312 | 362 |
313 int FileStream::Open(const FilePath& path, int open_flags) { | 363 int FileStream::Open(const FilePath& path, int open_flags) { |
314 if (IsOpen()) { | 364 if (IsOpen()) { |
315 DLOG(FATAL) << "File is already open!"; | 365 DLOG(FATAL) << "File is already open!"; |
316 return ERR_UNEXPECTED; | 366 return ERR_UNEXPECTED; |
317 } | 367 } |
318 | 368 |
369 bound_net_log_.BeginEvent( | |
370 net::NetLog::TYPE_FILE_STREAM_OPEN, | |
371 make_scoped_refptr( | |
372 new net::NetLogStringParameter("file_name", | |
373 path.AsUTF8Unsafe()))); | |
374 | |
319 open_flags_ = open_flags; | 375 open_flags_ = open_flags; |
320 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); | 376 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); |
321 if (file_ == base::kInvalidPlatformFileValue) | 377 if (file_ == base::kInvalidPlatformFileValue) { |
322 return RecordAndMapError(errno, FILE_ERROR_SOURCE_OPEN, record_uma_); | 378 int net_error = RecordAndMapError(errno, |
379 FILE_ERROR_SOURCE_OPEN, | |
380 record_uma_, | |
381 bound_net_log_); | |
382 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); | |
383 return net_error; | |
384 } | |
323 | 385 |
324 if (open_flags_ & base::PLATFORM_FILE_ASYNC) | 386 if (open_flags_ & base::PLATFORM_FILE_ASYNC) |
325 async_context_.reset(new AsyncContext()); | 387 async_context_.reset(new AsyncContext()); |
326 | 388 |
327 return OK; | 389 return OK; |
328 } | 390 } |
329 | 391 |
330 bool FileStream::IsOpen() const { | 392 bool FileStream::IsOpen() const { |
331 return file_ != base::kInvalidPlatformFileValue; | 393 return file_ != base::kInvalidPlatformFileValue; |
332 } | 394 } |
333 | 395 |
334 int64 FileStream::Seek(Whence whence, int64 offset) { | 396 int64 FileStream::Seek(Whence whence, int64 offset) { |
335 base::ThreadRestrictions::AssertIOAllowed(); | 397 base::ThreadRestrictions::AssertIOAllowed(); |
336 | 398 |
337 if (!IsOpen()) | 399 if (!IsOpen()) |
338 return ERR_UNEXPECTED; | 400 return ERR_UNEXPECTED; |
339 | 401 |
340 // If we're in async, make sure we don't have a request in flight. | 402 // If we're in async, make sure we don't have a request in flight. |
341 DCHECK(!async_context_.get() || async_context_->callback().is_null()); | 403 DCHECK(!async_context_.get() || async_context_->callback().is_null()); |
342 | 404 |
343 off_t res = lseek(file_, static_cast<off_t>(offset), | 405 off_t res = lseek(file_, static_cast<off_t>(offset), |
344 static_cast<int>(whence)); | 406 static_cast<int>(whence)); |
345 if (res == static_cast<off_t>(-1)) | 407 if (res == static_cast<off_t>(-1)) { |
346 return RecordAndMapError(errno, FILE_ERROR_SOURCE_SEEK, record_uma_); | 408 return RecordAndMapError(errno, |
409 FILE_ERROR_SOURCE_SEEK, | |
410 record_uma_, | |
411 bound_net_log_); | |
412 } | |
347 | 413 |
348 return res; | 414 return res; |
349 } | 415 } |
350 | 416 |
351 int64 FileStream::Available() { | 417 int64 FileStream::Available() { |
352 base::ThreadRestrictions::AssertIOAllowed(); | 418 base::ThreadRestrictions::AssertIOAllowed(); |
353 | 419 |
354 if (!IsOpen()) | 420 if (!IsOpen()) |
355 return ERR_UNEXPECTED; | 421 return ERR_UNEXPECTED; |
356 | 422 |
357 int64 cur_pos = Seek(FROM_CURRENT, 0); | 423 int64 cur_pos = Seek(FROM_CURRENT, 0); |
358 if (cur_pos < 0) | 424 if (cur_pos < 0) |
359 return cur_pos; | 425 return cur_pos; |
360 | 426 |
361 struct stat info; | 427 struct stat info; |
362 if (fstat(file_, &info) != 0) | 428 if (fstat(file_, &info) != 0) { |
363 return RecordAndMapError(errno, FILE_ERROR_SOURCE_GET_SIZE, record_uma_); | 429 return RecordAndMapError(errno, |
430 FILE_ERROR_SOURCE_GET_SIZE, | |
431 record_uma_, | |
432 bound_net_log_); | |
433 } | |
364 | 434 |
365 int64 size = static_cast<int64>(info.st_size); | 435 int64 size = static_cast<int64>(info.st_size); |
366 DCHECK_GT(size, cur_pos); | 436 DCHECK_GT(size, cur_pos); |
367 | 437 |
368 return size - cur_pos; | 438 return size - cur_pos; |
369 } | 439 } |
370 | 440 |
371 int FileStream::Read( | 441 int FileStream::Read( |
372 char* buf, int buf_len, const CompletionCallback& callback) { | 442 char* buf, int buf_len, const CompletionCallback& callback) { |
373 if (!IsOpen()) | 443 if (!IsOpen()) |
374 return ERR_UNEXPECTED; | 444 return ERR_UNEXPECTED; |
375 | 445 |
376 // read(..., 0) will return 0, which indicates end-of-file. | 446 // read(..., 0) will return 0, which indicates end-of-file. |
377 DCHECK_GT(buf_len, 0); | 447 DCHECK_GT(buf_len, 0); |
378 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | 448 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); |
379 | 449 |
380 if (async_context_.get()) { | 450 if (async_context_.get()) { |
381 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 451 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
382 // If we're in async, make sure we don't have a request in flight. | 452 // If we're in async, make sure we don't have a request in flight. |
383 DCHECK(async_context_->callback().is_null()); | 453 DCHECK(async_context_->callback().is_null()); |
384 if (record_uma_) | 454 if (record_uma_) |
385 async_context_->EnableErrorStatistics(); | 455 async_context_->EnableErrorStatistics(); |
386 async_context_->InitiateAsyncRead(file_, buf, buf_len, callback); | 456 async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_, |
457 callback); | |
387 return ERR_IO_PENDING; | 458 return ERR_IO_PENDING; |
388 } else { | 459 } else { |
389 return ReadFile(file_, buf, buf_len, record_uma_); | 460 return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_); |
390 } | 461 } |
391 } | 462 } |
392 | 463 |
393 int FileStream::ReadUntilComplete(char *buf, int buf_len) { | 464 int FileStream::ReadUntilComplete(char *buf, int buf_len) { |
394 int to_read = buf_len; | 465 int to_read = buf_len; |
395 int bytes_total = 0; | 466 int bytes_total = 0; |
396 | 467 |
397 do { | 468 do { |
398 int bytes_read = Read(buf, to_read, CompletionCallback()); | 469 int bytes_read = Read(buf, to_read, CompletionCallback()); |
399 if (bytes_read <= 0) { | 470 if (bytes_read <= 0) { |
(...skipping 18 matching lines...) Expand all Loading... | |
418 | 489 |
419 if (!IsOpen()) | 490 if (!IsOpen()) |
420 return ERR_UNEXPECTED; | 491 return ERR_UNEXPECTED; |
421 | 492 |
422 if (async_context_.get()) { | 493 if (async_context_.get()) { |
423 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 494 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
424 // If we're in async, make sure we don't have a request in flight. | 495 // If we're in async, make sure we don't have a request in flight. |
425 DCHECK(async_context_->callback().is_null()); | 496 DCHECK(async_context_->callback().is_null()); |
426 if (record_uma_) | 497 if (record_uma_) |
427 async_context_->EnableErrorStatistics(); | 498 async_context_->EnableErrorStatistics(); |
428 async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback); | 499 async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_, |
500 callback); | |
429 return ERR_IO_PENDING; | 501 return ERR_IO_PENDING; |
430 } else { | 502 } else { |
431 return WriteFile(file_, buf, buf_len, record_uma_); | 503 return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_); |
432 } | 504 } |
433 } | 505 } |
434 | 506 |
435 int64 FileStream::Truncate(int64 bytes) { | 507 int64 FileStream::Truncate(int64 bytes) { |
436 base::ThreadRestrictions::AssertIOAllowed(); | 508 base::ThreadRestrictions::AssertIOAllowed(); |
437 | 509 |
438 if (!IsOpen()) | 510 if (!IsOpen()) |
439 return ERR_UNEXPECTED; | 511 return ERR_UNEXPECTED; |
440 | 512 |
441 // We better be open for reading. | 513 // We'd better be open for writing. |
442 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 514 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); |
443 | 515 |
444 // Seek to the position to truncate from. | 516 // Seek to the position to truncate from. |
445 int64 seek_position = Seek(FROM_BEGIN, bytes); | 517 int64 seek_position = Seek(FROM_BEGIN, bytes); |
446 if (seek_position != bytes) | 518 if (seek_position != bytes) |
447 return ERR_UNEXPECTED; | 519 return ERR_UNEXPECTED; |
448 | 520 |
449 // And truncate the file. | 521 // And truncate the file. |
450 int result = ftruncate(file_, bytes); | 522 int result = ftruncate(file_, bytes); |
451 if (result == 0) | 523 if (result == 0) |
452 return seek_position; | 524 return seek_position; |
453 | 525 |
454 return RecordAndMapError(errno, FILE_ERROR_SOURCE_SET_EOF, record_uma_); | 526 return RecordAndMapError(errno, |
527 FILE_ERROR_SOURCE_SET_EOF, | |
528 record_uma_, | |
529 bound_net_log_); | |
455 } | 530 } |
456 | 531 |
457 int FileStream::Flush() { | 532 int FileStream::Flush() { |
458 if (!IsOpen()) | 533 if (!IsOpen()) |
459 return ERR_UNEXPECTED; | 534 return ERR_UNEXPECTED; |
460 | 535 |
461 return FlushFile(file_, record_uma_); | 536 return FlushFile(file_, record_uma_, bound_net_log_); |
462 } | 537 } |
463 | 538 |
464 void FileStream::EnableErrorStatistics() { | 539 void FileStream::EnableErrorStatistics() { |
465 record_uma_ = true; | 540 record_uma_ = true; |
466 } | 541 } |
467 | 542 |
543 void FileStream::SetBoundNetLogSource( | |
544 const net::BoundNetLog& owner_bound_net_log) { | |
545 if (owner_bound_net_log.source().id == net::NetLog::Source::kInvalidId) | |
546 return; | |
547 | |
548 if (owner_bound_net_log.source().id == bound_net_log_.source().id) | |
549 return; | |
550 | |
551 bound_net_log_.AddEvent( | |
552 net::NetLog::TYPE_FILE_STREAM_BOUND_TO_OWNER, | |
553 make_scoped_refptr( | |
554 new net::NetLogSourceParameter("source_dependency", | |
555 owner_bound_net_log.source()))); | |
556 | |
557 owner_bound_net_log.AddEvent( | |
558 net::NetLog::TYPE_FILE_STREAM_SOURCE, | |
559 make_scoped_refptr( | |
560 new net::NetLogSourceParameter("source_dependency", | |
561 bound_net_log_.source()))); | |
562 } | |
563 | |
468 } // namespace net | 564 } // namespace net |
OLD | NEW |