summaryrefslogtreecommitdiffstats
path: root/net/base/file_stream_win.cc
diff options
context:
space:
mode:
authorsatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-17 22:10:34 +0000
committersatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-17 22:10:34 +0000
commite3d66fde2328cc9220c25b51d06cc17b2f8522e7 (patch)
treec5da44e3c8bfcc898eb19e3176f57491fba16523 /net/base/file_stream_win.cc
parent17cb8a80ed6014b9071fb2a7daef0dc52bf8ab45 (diff)
downloadchromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.zip
chromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.tar.gz
chromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.tar.bz2
net: Add FileStream::Open() and Close() that perform asynchronously.
However, these aren't used yet. Clients of FileStream that reads/writes files asynchronously should be migrated to use the new functions. BUG=72001,114783 TEST=net_unittests. Review URL: https://chromiumcodereview.appspot.com/9415031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122601 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/file_stream_win.cc')
-rw-r--r--net/base/file_stream_win.cc163
1 files changed, 143 insertions, 20 deletions
diff --git a/net/base/file_stream_win.cc b/net/base/file_stream_win.cc
index aa2b045..8ee7cbe 100644
--- a/net/base/file_stream_win.cc
+++ b/net/base/file_stream_win.cc
@@ -11,6 +11,7 @@
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/worker_pool.h"
#include "net/base/file_stream_metrics.h"
#include "net/base/file_stream_net_log_parameters.h"
#include "net/base/io_buffer.h"
@@ -56,6 +57,47 @@ int RecordAndMapError(int error,
return net_error;
}
+// Opens a file with some network logging.
+// The opened file and the result code are written to |file| and |result|.
+void OpenFile(const FilePath& path,
+ int open_flags,
+ bool record_uma,
+ const net::BoundNetLog& bound_net_log,
+ base::PlatformFile* file,
+ int* result) {
+ bound_net_log.BeginEvent(
+ net::NetLog::TYPE_FILE_STREAM_OPEN,
+ make_scoped_refptr(
+ new net::NetLogStringParameter("file_name",
+ path.AsUTF8Unsafe())));
+
+ *file = base::CreatePlatformFile(path, open_flags, NULL, NULL);
+ if (*file == INVALID_HANDLE_VALUE) {
+ DWORD error = GetLastError();
+ LOG(WARNING) << "Failed to open file: " << error;
+ *result = RecordAndMapError(error,
+ FILE_ERROR_SOURCE_OPEN,
+ record_uma,
+ bound_net_log);
+ bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
+ return;
+ }
+}
+
+// Closes a file with some network logging.
+void CloseFile(base::PlatformFile file,
+ const net::BoundNetLog& bound_net_log) {
+ bound_net_log.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ return;
+
+ CancelIo(file);
+
+ if (!base::ClosePlatformFile(file))
+ NOTREACHED();
+ bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
+}
+
} // namespace
// FileStream::AsyncContext ----------------------------------------------
@@ -153,7 +195,8 @@ FileStream::FileStream(net::NetLog* net_log)
auto_closed_(true),
record_uma_(false),
bound_net_log_(net::BoundNetLog::Make(net_log,
- net::NetLog::SOURCE_FILESTREAM)) {
+ net::NetLog::SOURCE_FILESTREAM)),
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
}
@@ -163,7 +206,8 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log)
auto_closed_(false),
record_uma_(false),
bound_net_log_(net::BoundNetLog::Make(net_log,
- net::NetLog::SOURCE_FILESTREAM)) {
+ net::NetLog::SOURCE_FILESTREAM)),
+ weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
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
@@ -176,18 +220,54 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log)
}
FileStream::~FileStream() {
- if (auto_closed_)
- CloseSync();
+ if (auto_closed_) {
+ if (async_context_.get()) {
+ // Make sure we don't have a request in flight.
+ DCHECK(async_context_->callback().is_null());
+
+ // Close the file in the background.
+ const bool posted = base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&CloseFile, file_, bound_net_log_),
+ true /* task_is_slow */);
+ DCHECK(posted);
+ } else {
+ CloseSync();
+ }
+ }
bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL);
}
+void FileStream::Close(const CompletionCallback& callback) {
+ DCHECK(callback_.is_null());
+ callback_ = callback;
+
+ // Make sure we don't have a request in flight. Unlike CloseSync(), don't
+ // abort existing asynchronous operations, as it'd block.
+ DCHECK(async_context_.get());
+ DCHECK(async_context_->callback().is_null());
+
+ const bool posted = base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&CloseFile, file_, bound_net_log_),
+ base::Bind(&FileStream::OnClosed, weak_ptr_factory_.GetWeakPtr()),
+ true /* task_is_slow */);
+ DCHECK(posted);
+}
+
void FileStream::CloseSync() {
+ // The logic here is similar to CloseFile() but async_context_.reset() is
+ // caled in this function.
+
bound_net_log_.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL);
if (file_ != INVALID_HANDLE_VALUE)
CancelIo(file_);
+ // TODO(satorux): Remove this once all async clients are migrated to use
+ // Close(). crbug.com/114783
async_context_.reset();
+
if (file_ != INVALID_HANDLE_VALUE) {
if (!base::ClosePlatformFile(file_))
NOTREACHED();
@@ -197,31 +277,50 @@ void FileStream::CloseSync() {
}
}
-int FileStream::OpenSync(const FilePath& path, int open_flags) {
+int FileStream::Open(const FilePath& path, int open_flags,
+ const CompletionCallback& callback) {
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())));
+ DCHECK(callback_.is_null());
+ callback_ = callback;
open_flags_ = open_flags;
- file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL);
- if (file_ == INVALID_HANDLE_VALUE) {
- DWORD error = GetLastError();
- LOG(WARNING) << "Failed to open file: " << error;
- int net_error = RecordAndMapError(error,
- FILE_ERROR_SOURCE_OPEN,
- record_uma_,
- bound_net_log_);
- bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL);
- return net_error;
+ DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
+
+ base::PlatformFile* file =
+ new base::PlatformFile(base::kInvalidPlatformFileValue);
+ int* result = new int(OK);
+ const bool posted = base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&OpenFile, path, open_flags, record_uma_, bound_net_log_,
+ file, result),
+ base::Bind(&FileStream::OnOpened,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(file),
+ base::Owned(result)),
+ true /* task_is_slow */);
+ DCHECK(posted);
+ return ERR_IO_PENDING;
+}
+
+int FileStream::OpenSync(const FilePath& path, int open_flags) {
+ if (IsOpen()) {
+ DLOG(FATAL) << "File is already open!";
+ return ERR_UNEXPECTED;
}
+ open_flags_ = open_flags;
+
+ int result = OK;
+ OpenFile(path, open_flags_, record_uma_, bound_net_log_, &file_, &result);
+ if (result != OK)
+ return result;
+
+ // TODO(satorux): Remove this once all async clients are migrated to use
+ // Open(). crbug.com/114783
if (open_flags_ & base::PLATFORM_FILE_ASYNC) {
async_context_.reset(new AsyncContext(bound_net_log_));
if (record_uma_)
@@ -515,4 +614,28 @@ void FileStream::SetBoundNetLogSource(
bound_net_log_.source())));
}
+void FileStream::OnClosed() {
+ file_ = INVALID_HANDLE_VALUE;
+
+ CompletionCallback temp = callback_;
+ callback_.Reset();
+ temp.Run(OK);
+}
+
+void FileStream::OnOpened(base::PlatformFile* file, int* result) {
+ file_ = *file;
+
+ if (*result == OK) {
+ async_context_.reset(new AsyncContext(bound_net_log_));
+ if (record_uma_)
+ async_context_->EnableErrorStatistics();
+ MessageLoopForIO::current()->RegisterIOHandler(file_,
+ async_context_.get());
+ }
+
+ CompletionCallback temp = callback_;
+ callback_.Reset();
+ temp.Run(*result);
+}
+
} // namespace net