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

Unified Diff: net/base/file_stream_context.h

Issue 10701050: net: Implement canceling of all async operations in FileStream. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 1 month 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
Index: net/base/file_stream_context.h
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..244c25f4c40d97d5a52a73b0f4805967673cf8ad
--- /dev/null
+++ b/net/base/file_stream_context.h
@@ -0,0 +1,230 @@
+// 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.
+
+// This file defines FileStream::Context class.
+// The general design of FileStream is as follows: file_stream.h defines
+// FileStream class which basically is just an "wrapper" not containing any
+// specific implementation details. It re-routes all its method calls to
+// the instance of FileStream::Context (FileStream holds a scoped_ptr to
+// FileStream::Context instance). Context was extracted into a different class
+// to be able to do and finish all async operations even when FileStream
+// instance is deleted. So FileStream's destructor can schedule file
+// closing to be done by Context in WorkerPool and then just return (releasing
+// Context pointer from scoped_ptr) without waiting for actual closing to
+// complete.
+// Implementation of FileStream::Context is divided in two parts: some methods
+// and members are platform-independent and some depend on the platform. This
+// header file contains the complete definition of Context class including all
+// platform-dependent parts (because of that it has a lot of #if-#else
+// branching). Implementations of all platform-independent methods are
+// located in file_stream_context.cc, and all platform-dependent methods are
+// in file_stream_context_{win,posix}.cc. This separation provides better
+// readability of Context's code. And we tried to make as much Context code
+// platform-independent as possible. So file_stream_context_{win,posix}.cc are
+// much smaller than file_stream_context.cc now.
+
+#ifndef NET_BASE_FILE_STREAM_CONTEXT_H_
+#define NET_BASE_FILE_STREAM_CONTEXT_H_
+
+#include "base/message_loop.h"
+#include "base/platform_file.h"
+#include "net/base/completion_callback.h"
+#include "net/base/file_stream.h"
+#include "net/base/file_stream_metrics.h"
+#include "net/base/file_stream_whence.h"
+#include "net/base/net_log.h"
+
+#if defined(OS_POSIX)
+#include <errno.h>
+#endif
+
+class FilePath;
+
+namespace net {
+
+class IOBuffer;
+
+#if defined(OS_WIN)
+class FileStream::Context : public MessageLoopForIO::IOHandler {
+#elif defined(OS_POSIX)
+class FileStream::Context {
+#endif
+ public:
+ ////////////////////////////////////////////////////////////////////////////
+ // Platform-dependent methods implemented in
+ // file_stream_context_{win,posix}.cc.
+ ////////////////////////////////////////////////////////////////////////////
+
+ explicit Context(const BoundNetLog& bound_net_log);
+ Context(base::PlatformFile file,
+ const BoundNetLog& bound_net_log,
+ int open_flags);
+#if defined(OS_WIN)
+ virtual ~Context();
+#elif defined(OS_POSIX)
+ ~Context();
+#endif
+
+ int64 GetFileSize() const;
+
+ int ReadAsync(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback);
+ int ReadSync(char* buf, int buf_len);
+
+ int WriteAsync(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback);
+ int WriteSync(const char* buf, int buf_len);
+
+ int Truncate(int64 bytes);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Inline methods.
+ ////////////////////////////////////////////////////////////////////////////
+
+ void set_record_uma(bool value) { record_uma_ = value; }
+ base::PlatformFile file() const { return file_; }
+ bool async_in_progress() const { return async_in_progress_; }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Platform-independent methods implemented in file_stream_context.cc.
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Destroys the context. It can be deleted in the method or deletion can be
+ // deferred if some asynchronous operation is now in progress or if file is
+ // not closed yet.
+ void Orphan();
+
+ void OpenAsync(const FilePath& path,
+ int open_flags,
+ const CompletionCallback& callback);
+ int OpenSync(const FilePath& path, int open_flags);
+
+ void CloseSync();
+
+ void SeekAsync(Whence whence,
+ int64 offset,
+ const Int64CompletionCallback& callback);
+ int64 SeekSync(Whence whence, int64 offset);
+
+ void FlushAsync(const CompletionCallback& callback);
+ int FlushSync();
+
+ private:
+ ////////////////////////////////////////////////////////////////////////////
+ // Error code that is platform-dependent but is used in the platform-
+ // independent code implemented in file_stream_context.cc.
+ ////////////////////////////////////////////////////////////////////////////
+ enum {
+#if defined(OS_WIN)
+ ERROR_BAD_FILE = ERROR_INVALID_HANDLE
+#elif defined(OS_POSIX)
+ ERROR_BAD_FILE = EBADF
+#endif
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Platform-independent methods implemented in file_stream_context.cc.
+ ////////////////////////////////////////////////////////////////////////////
+
+ struct OpenResult {
+ base::PlatformFile file;
+ int error_code;
+ };
+
+ // Map system error into network error code and log it with |bound_net_log_|.
+ int RecordAndMapError(int error, FileErrorSource source) const;
+
+ void BeginOpenEvent(const FilePath& path);
+
+ OpenResult OpenFileImpl(const FilePath& path, int open_flags);
+
+ int ProcessOpenError(int error_code);
+ void OnOpenCompleted(const CompletionCallback& callback, OpenResult result);
+
+ void CloseAndDelete();
+ void OnCloseCompleted();
+
+ Int64CompletionCallback IntToInt64(const CompletionCallback& callback);
+
+ // Checks for IO error that probably happened in async methods.
+ // If there was error reports it.
+ void CheckForIOError(int64* result, FileErrorSource source);
+
+ // Called when asynchronous Seek() is completed.
+ // Reports error if needed and calls callback.
+ void ProcessAsyncResult(const Int64CompletionCallback& callback,
+ FileErrorSource source,
+ int64 result);
+
+ // Called when asynchronous Open() or Seek()
+ // is completed. |result| contains the result or a network error code.
+ void OnAsyncCompleted(const Int64CompletionCallback& callback, int64 result);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Helper stuff which is platform-dependent but is used in the platform-
+ // independent code implemented in file_stream_context.cc. These helpers were
+ // introduced solely to implement as much of the Context methods as
+ // possible independently from platform.
+ ////////////////////////////////////////////////////////////////////////////
+
+#if defined(OS_WIN)
+ int GetLastErrno() { return GetLastError(); }
+ void OnAsyncFileOpened();
+#elif defined(OS_POSIX)
+ int GetLastErrno() { return errno; }
+ void OnAsyncFileOpened() {}
+ void CancelIo(base::PlatformFile) {}
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Platform-dependent methods implemented in
+ // file_stream_context_{win,posix}.cc.
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Adjusts the position from where the data is read.
+ int64 SeekFileImpl(Whence whence, int64 offset);
+
+ // Flushes all data written to the stream.
+ int64 FlushFileImpl();
+
+#if defined(OS_WIN)
+ void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf);
+
+ // Implementation of MessageLoopForIO::IOHandler
+ virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
+ DWORD bytes_read,
+ DWORD error) OVERRIDE;
+#elif defined(OS_POSIX)
+ // ReadFileImpl() is a simple wrapper around read() that handles EINTR
+ // signals and calls RecordAndMapError() to map errno to net error codes.
+ int64 ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
+
+ // WriteFileImpl() 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.
+ int64 WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
+#endif
+
+ base::PlatformFile file_;
+ bool record_uma_;
+ bool async_in_progress_;
+ bool orphaned_;
+ BoundNetLog bound_net_log_;
+
+#if defined(OS_WIN)
+ MessageLoopForIO::IOContext io_context_;
+ CompletionCallback callback_;
+ scoped_refptr<IOBuffer> in_flight_buf_;
+ FileErrorSource error_source_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(Context);
+};
+
+} // namespace net
+
+#endif // NET_BASE_FILE_STREAM_CONTEXT_H_
+

Powered by Google App Engine
This is Rietveld 408576698