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