| Index: net/base/file_stream_posix.cc
|
| diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc
|
| index 50b1593202a762dcc69a0a1dca1aeee1f28b46e3..8220a9f725e2cbd993515bafcccb14eddc6216d6 100644
|
| --- a/net/base/file_stream_posix.cc
|
| +++ b/net/base/file_stream_posix.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| @@ -27,6 +27,7 @@
|
| #include "base/threading/worker_pool.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "net/base/file_stream_metrics.h"
|
| +#include "net/base/file_stream_net_log_parameters.h"
|
| #include "net/base/net_errors.h"
|
|
|
| #if defined(OS_ANDROID)
|
| @@ -49,21 +50,38 @@ COMPILE_ASSERT(FROM_BEGIN == SEEK_SET &&
|
|
|
| namespace {
|
|
|
| -int RecordAndMapError(int error, FileErrorSource source, bool record_uma) {
|
| +int RecordAndMapError(int error,
|
| + FileErrorSource source,
|
| + bool record_uma,
|
| + const net::BoundNetLog& bound_net_log) {
|
| + net::Error net_error = MapSystemError(error);
|
| +
|
| + bound_net_log.AddEvent(
|
| + net::NetLog::TYPE_FILE_STREAM_ERROR,
|
| + make_scoped_refptr(
|
| + new FileStreamErrorParameters(GetFileErrorSourceName(source),
|
| + error,
|
| + net_error)));
|
| +
|
| RecordFileError(error, source, record_uma);
|
| - return MapSystemError(error);
|
| +
|
| + return net_error;
|
| }
|
|
|
| // ReadFile() is a simple wrapper around read() that handles EINTR signals and
|
| // calls MapSystemError() to map errno to net error codes.
|
| -int ReadFile(base::PlatformFile file, char* buf, int buf_len, bool record_uma) {
|
| +int ReadFile(base::PlatformFile file,
|
| + char* buf,
|
| + int buf_len,
|
| + bool record_uma,
|
| + const net::BoundNetLog& bound_net_log) {
|
| base::ThreadRestrictions::AssertIOAllowed();
|
| // read(..., 0) returns 0 to indicate end-of-file.
|
|
|
| // Loop in the case of getting interrupted by a signal.
|
| ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len)));
|
| if (res == static_cast<ssize_t>(-1))
|
| - RecordAndMapError(errno, FILE_ERROR_SOURCE_READ, record_uma);
|
| + RecordAndMapError(errno, FILE_ERROR_SOURCE_READ, record_uma, bound_net_log);
|
| return static_cast<int>(res);
|
| }
|
|
|
| @@ -71,37 +89,49 @@ void ReadFileTask(base::PlatformFile file,
|
| char* buf,
|
| int buf_len,
|
| bool record_uma,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback) {
|
| - callback.Run(ReadFile(file, buf, buf_len, record_uma));
|
| + callback.Run(ReadFile(file, buf, buf_len, record_uma, bound_net_log));
|
| }
|
|
|
| // WriteFile() is a simple wrapper around write() that handles EINTR signals and
|
| // calls MapSystemError() to map errno to net error codes. It tries to write to
|
| // completion.
|
| -int WriteFile(base::PlatformFile file, const char* buf, int buf_len,
|
| - bool record_uma) {
|
| +int WriteFile(base::PlatformFile file,
|
| + const char* buf,
|
| + int buf_len,
|
| + bool record_uma,
|
| + const net::BoundNetLog& bound_net_log) {
|
| base::ThreadRestrictions::AssertIOAllowed();
|
| ssize_t res = HANDLE_EINTR(write(file, buf, buf_len));
|
| - if (res == -1)
|
| - RecordAndMapError(errno, FILE_ERROR_SOURCE_WRITE, record_uma);
|
| + if (res == -1) {
|
| + RecordAndMapError(errno, FILE_ERROR_SOURCE_WRITE, record_uma,
|
| + bound_net_log);
|
| + }
|
| return res;
|
| }
|
|
|
| void WriteFileTask(base::PlatformFile file,
|
| const char* buf,
|
| - int buf_len, bool record_uma,
|
| + int buf_len,
|
| + bool record_uma,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback) {
|
| - callback.Run(WriteFile(file, buf, buf_len, record_uma));
|
| + callback.Run(WriteFile(file, buf, buf_len, record_uma, bound_net_log));
|
| }
|
|
|
| // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and
|
| // calls MapSystemError() to map errno to net error codes. It tries to flush to
|
| // completion.
|
| -int FlushFile(base::PlatformFile file, bool record_uma) {
|
| +int FlushFile(base::PlatformFile file,
|
| + bool record_uma,
|
| + const net::BoundNetLog& bound_net_log) {
|
| base::ThreadRestrictions::AssertIOAllowed();
|
| ssize_t res = HANDLE_EINTR(fsync(file));
|
| - if (res == -1)
|
| - RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma);
|
| + if (res == -1) {
|
| + RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma,
|
| + bound_net_log);
|
| + }
|
| return res;
|
| }
|
|
|
| @@ -138,9 +168,11 @@ class FileStream::AsyncContext {
|
| // These methods post synchronous read() and write() calls to a WorkerThread.
|
| void InitiateAsyncRead(
|
| base::PlatformFile file, char* buf, int buf_len,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback);
|
| void InitiateAsyncWrite(
|
| base::PlatformFile file, const char* buf, int buf_len,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback);
|
|
|
| const CompletionCallback& callback() const { return callback_; }
|
| @@ -207,14 +239,19 @@ FileStream::AsyncContext::~AsyncContext() {
|
|
|
| void FileStream::AsyncContext::InitiateAsyncRead(
|
| base::PlatformFile file, char* buf, int buf_len,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback) {
|
| DCHECK(callback_.is_null());
|
| callback_ = callback;
|
|
|
| base::WorkerPool::PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ReadFileTask, file, buf, buf_len,
|
| + base::Bind(&ReadFileTask,
|
| + file,
|
| + buf,
|
| + buf_len,
|
| record_uma_,
|
| + bound_net_log,
|
| base::Bind(&AsyncContext::OnBackgroundIOCompleted,
|
| base::Unretained(this))),
|
| true /* task_is_slow */);
|
| @@ -222,18 +259,21 @@ void FileStream::AsyncContext::InitiateAsyncRead(
|
|
|
| void FileStream::AsyncContext::InitiateAsyncWrite(
|
| base::PlatformFile file, const char* buf, int buf_len,
|
| + const net::BoundNetLog& bound_net_log,
|
| const CompletionCallback& callback) {
|
| DCHECK(callback_.is_null());
|
| callback_ = callback;
|
|
|
| base::WorkerPool::PostTask(
|
| FROM_HERE,
|
| - base::Bind(
|
| - &WriteFileTask,
|
| - file, buf, buf_len,
|
| - record_uma_,
|
| - base::Bind(&AsyncContext::OnBackgroundIOCompleted,
|
| - base::Unretained(this))),
|
| + base::Bind(&WriteFileTask,
|
| + file,
|
| + buf,
|
| + buf_len,
|
| + record_uma_,
|
| + bound_net_log,
|
| + base::Bind(&AsyncContext::OnBackgroundIOCompleted,
|
| + base::Unretained(this))),
|
| true /* task_is_slow */);
|
| }
|
|
|
| @@ -273,19 +313,25 @@ void FileStream::AsyncContext::RunAsynchronousCallback() {
|
|
|
| // FileStream ------------------------------------------------------------
|
|
|
| -FileStream::FileStream()
|
| +FileStream::FileStream(net::NetLog* net_log)
|
| : file_(base::kInvalidPlatformFileValue),
|
| open_flags_(0),
|
| auto_closed_(true),
|
| - record_uma_(false) {
|
| - DCHECK(!IsOpen());
|
| + record_uma_(false),
|
| + bound_net_log_(net::BoundNetLog::Make(net_log,
|
| + net::NetLog::SOURCE_FILESTREAM)) {
|
| + bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
|
| }
|
|
|
| -FileStream::FileStream(base::PlatformFile file, int flags)
|
| +FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log)
|
| : file_(file),
|
| open_flags_(flags),
|
| auto_closed_(false),
|
| - record_uma_(false) {
|
| + record_uma_(false),
|
| + bound_net_log_(net::BoundNetLog::Make(net_log,
|
| + net::NetLog::SOURCE_FILESTREAM)) {
|
| + bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
|
| +
|
| // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to
|
| // make sure we will perform asynchronous File IO to it.
|
| if (flags & base::PLATFORM_FILE_ASYNC) {
|
| @@ -296,9 +342,13 @@ FileStream::FileStream(base::PlatformFile file, int flags)
|
| FileStream::~FileStream() {
|
| if (auto_closed_)
|
| Close();
|
| +
|
| + bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
|
| }
|
|
|
| void FileStream::Close() {
|
| + bound_net_log_.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL);
|
| +
|
| // Abort any existing asynchronous operations.
|
| async_context_.reset();
|
|
|
| @@ -307,19 +357,33 @@ void FileStream::Close() {
|
| NOTREACHED();
|
| }
|
| file_ = base::kInvalidPlatformFileValue;
|
| +
|
| + bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
|
| }
|
| }
|
|
|
| -int FileStream::Open(const FilePath& path, int open_flags) {
|
| +int FileStream::Open(const FilePath& path, int open_flags) {
|
| if (IsOpen()) {
|
| DLOG(FATAL) << "File is already open!";
|
| return ERR_UNEXPECTED;
|
| }
|
|
|
| + bound_net_log_.BeginEvent(
|
| + net::NetLog::TYPE_FILE_STREAM_OPEN,
|
| + make_scoped_refptr(
|
| + new net::NetLogStringParameter("file_name",
|
| + path.AsUTF8Unsafe())));
|
| +
|
| open_flags_ = open_flags;
|
| file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL);
|
| - if (file_ == base::kInvalidPlatformFileValue)
|
| - return RecordAndMapError(errno, FILE_ERROR_SOURCE_OPEN, record_uma_);
|
| + if (file_ == base::kInvalidPlatformFileValue) {
|
| + int net_error = RecordAndMapError(errno,
|
| + FILE_ERROR_SOURCE_OPEN,
|
| + record_uma_,
|
| + bound_net_log_);
|
| + bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
|
| + return net_error;
|
| + }
|
|
|
| if (open_flags_ & base::PLATFORM_FILE_ASYNC)
|
| async_context_.reset(new AsyncContext());
|
| @@ -342,8 +406,12 @@ int64 FileStream::Seek(Whence whence, int64 offset) {
|
|
|
| off_t res = lseek(file_, static_cast<off_t>(offset),
|
| static_cast<int>(whence));
|
| - if (res == static_cast<off_t>(-1))
|
| - return RecordAndMapError(errno, FILE_ERROR_SOURCE_SEEK, record_uma_);
|
| + if (res == static_cast<off_t>(-1)) {
|
| + return RecordAndMapError(errno,
|
| + FILE_ERROR_SOURCE_SEEK,
|
| + record_uma_,
|
| + bound_net_log_);
|
| + }
|
|
|
| return res;
|
| }
|
| @@ -359,8 +427,12 @@ int64 FileStream::Available() {
|
| return cur_pos;
|
|
|
| struct stat info;
|
| - if (fstat(file_, &info) != 0)
|
| - return RecordAndMapError(errno, FILE_ERROR_SOURCE_GET_SIZE, record_uma_);
|
| + if (fstat(file_, &info) != 0) {
|
| + return RecordAndMapError(errno,
|
| + FILE_ERROR_SOURCE_GET_SIZE,
|
| + record_uma_,
|
| + bound_net_log_);
|
| + }
|
|
|
| int64 size = static_cast<int64>(info.st_size);
|
| DCHECK_GT(size, cur_pos);
|
| @@ -383,10 +455,11 @@ int FileStream::Read(
|
| DCHECK(async_context_->callback().is_null());
|
| if (record_uma_)
|
| async_context_->EnableErrorStatistics();
|
| - async_context_->InitiateAsyncRead(file_, buf, buf_len, callback);
|
| + async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_,
|
| + callback);
|
| return ERR_IO_PENDING;
|
| } else {
|
| - return ReadFile(file_, buf, buf_len, record_uma_);
|
| + return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_);
|
| }
|
| }
|
|
|
| @@ -425,10 +498,11 @@ int FileStream::Write(
|
| DCHECK(async_context_->callback().is_null());
|
| if (record_uma_)
|
| async_context_->EnableErrorStatistics();
|
| - async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback);
|
| + async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_,
|
| + callback);
|
| return ERR_IO_PENDING;
|
| } else {
|
| - return WriteFile(file_, buf, buf_len, record_uma_);
|
| + return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_);
|
| }
|
| }
|
|
|
| @@ -438,7 +512,7 @@ int64 FileStream::Truncate(int64 bytes) {
|
| if (!IsOpen())
|
| return ERR_UNEXPECTED;
|
|
|
| - // We better be open for reading.
|
| + // We'd better be open for writing.
|
| DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
|
|
|
| // Seek to the position to truncate from.
|
| @@ -451,18 +525,45 @@ int64 FileStream::Truncate(int64 bytes) {
|
| if (result == 0)
|
| return seek_position;
|
|
|
| - return RecordAndMapError(errno, FILE_ERROR_SOURCE_SET_EOF, record_uma_);
|
| + return RecordAndMapError(errno,
|
| + FILE_ERROR_SOURCE_SET_EOF,
|
| + record_uma_,
|
| + bound_net_log_);
|
| }
|
|
|
| int FileStream::Flush() {
|
| if (!IsOpen())
|
| return ERR_UNEXPECTED;
|
|
|
| - return FlushFile(file_, record_uma_);
|
| + return FlushFile(file_, record_uma_, bound_net_log_);
|
| }
|
|
|
| void FileStream::EnableErrorStatistics() {
|
| record_uma_ = true;
|
| }
|
|
|
| +void FileStream::SetBoundNetLogSource(
|
| + const net::BoundNetLog& owner_bound_net_log) {
|
| + if ((owner_bound_net_log.source().id == net::NetLog::Source::kInvalidId) &&
|
| + (bound_net_log_.source().id == net::NetLog::Source::kInvalidId)) {
|
| + // Both |BoundNetLog|s are invalid.
|
| + return;
|
| + }
|
| +
|
| + // Should never connect to itself.
|
| + DCHECK_NE(bound_net_log_.source().id, owner_bound_net_log.source().id);
|
| +
|
| + bound_net_log_.AddEvent(
|
| + net::NetLog::TYPE_FILE_STREAM_BOUND_TO_OWNER,
|
| + make_scoped_refptr(
|
| + new net::NetLogSourceParameter("source_dependency",
|
| + owner_bound_net_log.source())));
|
| +
|
| + owner_bound_net_log.AddEvent(
|
| + net::NetLog::TYPE_FILE_STREAM_SOURCE,
|
| + make_scoped_refptr(
|
| + new net::NetLogSourceParameter("source_dependency",
|
| + bound_net_log_.source())));
|
| +}
|
| +
|
| } // namespace net
|
|
|