diff options
Diffstat (limited to 'chromium/net/base/file_stream_context.h')
-rw-r--r-- | chromium/net/base/file_stream_context.h | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/chromium/net/base/file_stream_context.h b/chromium/net/base/file_stream_context.h new file mode 100644 index 00000000000..15c25bb8d4a --- /dev/null +++ b/chromium/net/base/file_stream_context.h @@ -0,0 +1,232 @@ +// 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 (or the TaskRunner passed to +// constructor) 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/message_loop.h" +#include "base/platform_file.h" +#include "base/task_runner.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 + +namespace base { +class FilePath; +} + +namespace net { + +class IOBuffer; + +#if defined(OS_WIN) +class FileStream::Context : public base::MessageLoopForIO::IOHandler { +#elif defined(OS_POSIX) +class FileStream::Context { +#endif + public: + //////////////////////////////////////////////////////////////////////////// + // Platform-dependent methods implemented in + // file_stream_context_{win,posix}.cc. + //////////////////////////////////////////////////////////////////////////// + + Context(const BoundNetLog& bound_net_log, + const scoped_refptr<base::TaskRunner>& task_runner); + Context(base::PlatformFile file, + const BoundNetLog& bound_net_log, + int open_flags, + const scoped_refptr<base::TaskRunner>& task_runner); +#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 base::FilePath& path, + int open_flags, + const CompletionCallback& callback); + int OpenSync(const base::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: + //////////////////////////////////////////////////////////////////////////// + // Platform-independent methods implemented in file_stream_context.cc. + //////////////////////////////////////////////////////////////////////////// + + struct IOResult { + IOResult(); + IOResult(int64 result, int os_error); + static IOResult FromOSError(int64 os_error); + + int64 result; + int os_error; // Set only when result < 0. + }; + + struct OpenResult { + OpenResult(); + OpenResult(base::PlatformFile file, IOResult error_code); + base::PlatformFile file; + IOResult error_code; + }; + + // Log the error from |result| to |bound_net_log_|. + void RecordError(const IOResult& result, FileErrorSource source) const; + + void BeginOpenEvent(const base::FilePath& path); + + OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); + + void ProcessOpenError(const IOResult& result); + void OnOpenCompleted(const CompletionCallback& callback, + OpenResult open_result); + + void CloseAndDelete(); + void OnCloseCompleted(); + + Int64CompletionCallback IntToInt64(const CompletionCallback& callback); + + // Called when asynchronous Seek() is completed. + // Reports error if needed and calls callback. + void ProcessAsyncResult(const Int64CompletionCallback& callback, + FileErrorSource source, + const IOResult& 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. + IOResult SeekFileImpl(Whence whence, int64 offset); + + // Flushes all data written to the stream. + IOResult FlushFileImpl(); + +#if defined(OS_WIN) + void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); + + // Implementation of MessageLoopForIO::IOHandler. + virtual void OnIOCompleted(base::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. + IOResult 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. + IOResult 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_; + scoped_refptr<base::TaskRunner> task_runner_; + +#if defined(OS_WIN) + base::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_ + |