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

Unified Diff: net/base/file_stream_posix.cc

Issue 9949011: Make FileStream::Seek async and add FileStream::SeekSync for sync operation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 8 years, 8 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/file_stream_posix.h ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/file_stream_posix.cc
diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc
index 6c9b13511ec3767c95873782f8fb86fe6d311306..0fe801d2f6ebf3a065ecb8cf4f6f30acad9a6aed 100644
--- a/net/base/file_stream_posix.cc
+++ b/net/base/file_stream_posix.cc
@@ -125,6 +125,37 @@ void CloseFileAndSignal(base::PlatformFile* file,
on_io_complete->Signal();
}
+// Adjusts the position from where the data is read.
+void SeekFile(base::PlatformFile file,
+ Whence whence,
+ int64 offset,
+ int64* result,
+ bool record_uma,
+ const net::BoundNetLog& bound_net_log) {
+ off_t res = lseek(file, static_cast<off_t>(offset),
+ static_cast<int>(whence));
+ if (res == static_cast<off_t>(-1)) {
+ *result = RecordAndMapError(errno,
+ FILE_ERROR_SOURCE_SEEK,
+ record_uma,
+ bound_net_log);
+ return;
+ }
+ *result = res;
+}
+
+// Seeks a file by calling SeekSync() and signals the completion.
+void SeekFileAndSignal(base::PlatformFile file,
+ Whence whence,
+ int64 offset,
+ int64* result,
+ bool record_uma,
+ base::WaitableEvent* on_io_complete,
+ const net::BoundNetLog& bound_net_log) {
+ SeekFile(file, whence, offset, result, record_uma, bound_net_log);
+ on_io_complete->Signal();
+}
+
// ReadFile() is a simple wrapper around read() that handles EINTR signals and
// calls MapSystemError() to map errno to net error codes.
void ReadFile(base::PlatformFile file,
@@ -203,6 +234,20 @@ int FlushFile(base::PlatformFile file,
return res;
}
+// Called when Read(), Write() or Seek() is completed.
+// |result| contains the result or a network error code.
+template <typename R>
+void OnIOComplete(const base::WeakPtr<FileStreamPosix>& stream,
+ const base::Callback<void(R)>& callback,
+ R* result) {
+ if (!stream.get())
+ return;
+
+ // Reset this before Run() as Run() may issue a new async operation.
+ stream->ResetOnIOComplete();
+ callback.Run(*result);
+}
+
} // namespace
// FileStreamPosix ------------------------------------------------------------
@@ -257,10 +302,8 @@ FileStreamPosix::~FileStreamPosix() {
void FileStreamPosix::Close(const CompletionCallback& callback) {
DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
- DCHECK(callback_.is_null());
-
- callback_ = callback;
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
DCHECK(!on_io_complete_.get());
on_io_complete_.reset(new base::WaitableEvent(
false /* manual_reset */, false /* initially_signaled */));
@@ -273,7 +316,8 @@ void FileStreamPosix::Close(const CompletionCallback& callback) {
base::Bind(&CloseFileAndSignal, &file_, on_io_complete_.get(),
bound_net_log_),
base::Bind(&FileStreamPosix::OnClosed,
- weak_ptr_factory_.GetWeakPtr()),
+ weak_ptr_factory_.GetWeakPtr(),
+ callback),
true /* task_is_slow */);
DCHECK(posted);
@@ -301,12 +345,10 @@ int FileStreamPosix::Open(const FilePath& path, int open_flags,
return ERR_UNEXPECTED;
}
- DCHECK(callback_.is_null());
- callback_ = callback;
-
open_flags_ = open_flags;
DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
DCHECK(!on_io_complete_.get());
on_io_complete_.reset(new base::WaitableEvent(
false /* manual_reset */, false /* initially_signaled */));
@@ -320,9 +362,8 @@ int FileStreamPosix::Open(const FilePath& path, int open_flags,
base::Bind(&OpenFileAndSignal,
path, open_flags, record_uma_, &file_, result,
on_io_complete_.get(), bound_net_log_),
- base::Bind(&FileStreamPosix::OnIOComplete,
- weak_ptr_factory_.GetWeakPtr(),
- base::Owned(result)),
+ base::Bind(&OnIOComplete<int>, weak_ptr_factory_.GetWeakPtr(),
+ callback, base::Owned(result)),
true /* task_is_slow */);
DCHECK(posted);
return ERR_IO_PENDING;
@@ -349,7 +390,33 @@ bool FileStreamPosix::IsOpen() const {
return file_ != base::kInvalidPlatformFileValue;
}
-int64 FileStreamPosix::Seek(Whence whence, int64 offset) {
+int FileStreamPosix::Seek(Whence whence, int64 offset,
+ const Int64CompletionCallback& callback) {
+ if (!IsOpen())
+ return ERR_UNEXPECTED;
+
+ // Make sure we're async and we have no other in-flight async operations.
+ DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
+ DCHECK(!on_io_complete_.get());
+
+ on_io_complete_.reset(new base::WaitableEvent(
+ false /* manual_reset */, false /* initially_signaled */));
+
+ int64* result = new int64(-1);
+ const bool posted = base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&SeekFileAndSignal, file_, whence, offset, result,
+ record_uma_, on_io_complete_.get(), bound_net_log_),
+ base::Bind(&OnIOComplete<int64>,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback, base::Owned(result)),
+ true /* task is slow */);
+ DCHECK(posted);
+ return ERR_IO_PENDING;
+}
+
+int64 FileStreamPosix::SeekSync(Whence whence, int64 offset) {
base::ThreadRestrictions::AssertIOAllowed();
if (!IsOpen())
@@ -357,18 +424,11 @@ int64 FileStreamPosix::Seek(Whence whence, int64 offset) {
// If we're in async, make sure we don't have a request in flight.
DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC) ||
- callback_.is_null());
-
- 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_,
- bound_net_log_);
- }
+ !on_io_complete_.get());
- return res;
+ off_t result = -1;
+ SeekFile(file_, whence, offset, &result, record_uma_, bound_net_log_);
+ return result;
}
int64 FileStreamPosix::Available() {
@@ -377,7 +437,7 @@ int64 FileStreamPosix::Available() {
if (!IsOpen())
return ERR_UNEXPECTED;
- int64 cur_pos = Seek(FROM_CURRENT, 0);
+ int64 cur_pos = SeekSync(FROM_CURRENT, 0);
if (cur_pos < 0)
return cur_pos;
@@ -404,22 +464,23 @@ int FileStreamPosix::Read(
DCHECK_GT(buf_len, 0);
DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
- // Make sure we don't have a request in flight.
- DCHECK(callback_.is_null());
- callback_ = callback;
- int* result = new int(OK);
- scoped_refptr<IOBuffer> buf = in_buf;
+ // Make sure we don't have a request in flight.
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
DCHECK(!on_io_complete_.get());
+
on_io_complete_.reset(new base::WaitableEvent(
false /* manual_reset */, false /* initially_signaled */));
+
+ int* result = new int(OK);
+ scoped_refptr<IOBuffer> buf = in_buf;
const bool posted = base::WorkerPool::PostTaskAndReply(
FROM_HERE,
base::Bind(&ReadFileAndSignal, file_, buf, buf_len,
record_uma_, result, on_io_complete_.get(), bound_net_log_),
- base::Bind(&FileStreamPosix::OnIOComplete,
+ base::Bind(&OnIOComplete<int>,
weak_ptr_factory_.GetWeakPtr(),
- base::Owned(result)),
+ callback, base::Owned(result)),
true /* task is slow */);
DCHECK(posted);
return ERR_IO_PENDING;
@@ -469,22 +530,22 @@ int FileStreamPosix::Write(
DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
// write(..., 0) will return 0, which indicates end-of-file.
DCHECK_GT(buf_len, 0);
- // Make sure we don't have a request in flight.
- DCHECK(callback_.is_null());
- callback_ = callback;
- int* result = new int(OK);
- scoped_refptr<IOBuffer> buf = in_buf;
+ // Make sure we don't have a request in flight.
+ DCHECK(!weak_ptr_factory_.HasWeakPtrs());
DCHECK(!on_io_complete_.get());
on_io_complete_.reset(new base::WaitableEvent(
false /* manual_reset */, false /* initially_signaled */));
+
+ int* result = new int(OK);
+ scoped_refptr<IOBuffer> buf = in_buf;
const bool posted = base::WorkerPool::PostTaskAndReply(
FROM_HERE,
base::Bind(&WriteFileAndSignal, file_, buf, buf_len,
record_uma_, result, on_io_complete_.get(), bound_net_log_),
- base::Bind(&FileStreamPosix::OnIOComplete,
+ base::Bind(&OnIOComplete<int>,
weak_ptr_factory_.GetWeakPtr(),
- base::Owned(result)),
+ callback, base::Owned(result)),
true /* task is slow */);
DCHECK(posted);
return ERR_IO_PENDING;
@@ -515,7 +576,7 @@ int64 FileStreamPosix::Truncate(int64 bytes) {
DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
// Seek to the position to truncate from.
- int64 seek_position = Seek(FROM_BEGIN, bytes);
+ int64 seek_position = SeekSync(FROM_BEGIN, bytes);
if (seek_position != bytes)
return ERR_UNEXPECTED;
@@ -569,19 +630,17 @@ base::PlatformFile FileStreamPosix::GetPlatformFileForTesting() {
return file_;
}
-void FileStreamPosix::OnClosed() {
- file_ = base::kInvalidPlatformFileValue;
- int result = OK;
- OnIOComplete(&result);
+void FileStreamPosix::ResetOnIOComplete() {
+ on_io_complete_.reset();
+ weak_ptr_factory_.InvalidateWeakPtrs();
}
-void FileStreamPosix::OnIOComplete(int* result) {
- CompletionCallback temp_callback = callback_;
- callback_.Reset();
+void FileStreamPosix::OnClosed(const CompletionCallback& callback) {
+ file_ = base::kInvalidPlatformFileValue;
// Reset this before Run() as Run() may issue a new async operation.
- on_io_complete_.reset();
- temp_callback.Run(*result);
+ ResetOnIOComplete();
+ callback.Run(OK);
}
void FileStreamPosix::WaitForIOCompletion() {
« no previous file with comments | « net/base/file_stream_posix.h ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698