1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This file defines FileStream::Context class. 6 // The general design of FileStream is as follows: file_stream.h defines 7 // FileStream class which basically is just an "wrapper" not containing any 8 // specific implementation details. It re-routes all its method calls to 9 // the instance of FileStream::Context (FileStream holds a scoped_ptr to 10 // FileStream::Context instance). Context was extracted into a different class 11 // to be able to do and finish all async operations even when FileStream 12 // instance is deleted. So FileStream's destructor can schedule file 13 // closing to be done by Context in WorkerPool (or the TaskRunner passed to 14 // constructor) and then just return (releasing Context pointer from 15 // scoped_ptr) without waiting for actual closing to complete. 16 // Implementation of FileStream::Context is divided in two parts: some methods 17 // and members are platform-independent and some depend on the platform. This 18 // header file contains the complete definition of Context class including all 19 // platform-dependent parts (because of that it has a lot of #if-#else 20 // branching). Implementations of all platform-independent methods are 21 // located in file_stream_context.cc, and all platform-dependent methods are 22 // in file_stream_context_{win,posix}.cc. This separation provides better 23 // readability of Context's code. And we tried to make as much Context code 24 // platform-independent as possible. So file_stream_context_{win,posix}.cc are 25 // much smaller than file_stream_context.cc now. 26 27 #ifndef NET_BASE_FILE_STREAM_CONTEXT_H_ 28 #define NET_BASE_FILE_STREAM_CONTEXT_H_ 29 30 #include "base/files/file.h" 31 #include "base/message_loop/message_loop.h" 32 #include "base/move.h" 33 #include "base/task_runner.h" 34 #include "net/base/completion_callback.h" 35 #include "net/base/file_stream.h" 36 37 #if defined(OS_POSIX) 38 #include <errno.h> 39 #endif 40 41 namespace base { 42 class FilePath; 43 } 44 45 namespace net { 46 47 class IOBuffer; 48 49 #if defined(OS_WIN) 50 class FileStream::Context : public base::MessageLoopForIO::IOHandler { 51 #elif defined(OS_POSIX) 52 class FileStream::Context { 53 #endif 54 public: 55 //////////////////////////////////////////////////////////////////////////// 56 // Platform-dependent methods implemented in 57 // file_stream_context_{win,posix}.cc. 58 //////////////////////////////////////////////////////////////////////////// 59 60 explicit Context(const scoped_refptr<base::TaskRunner>& task_runner); 61 Context(base::File file, const scoped_refptr<base::TaskRunner>& task_runner); 62 #if defined(OS_WIN) 63 virtual ~Context(); 64 #elif defined(OS_POSIX) 65 ~Context(); 66 #endif 67 68 int Read(IOBuffer* buf, 69 int buf_len, 70 const CompletionCallback& callback); 71 72 int Write(IOBuffer* buf, 73 int buf_len, 74 const CompletionCallback& callback); 75 76 const base::File& file() const { return file_; } 77 bool async_in_progress() const { return async_in_progress_; } 78 79 //////////////////////////////////////////////////////////////////////////// 80 // Platform-independent methods implemented in file_stream_context.cc. 81 //////////////////////////////////////////////////////////////////////////// 82 83 // Destroys the context. It can be deleted in the method or deletion can be 84 // deferred if some asynchronous operation is now in progress or if file is 85 // not closed yet. 86 void Orphan(); 87 88 void Open(const base::FilePath& path, 89 int open_flags, 90 const CompletionCallback& callback); 91 92 void Close(const CompletionCallback& callback); 93 94 void Seek(base::File::Whence whence, 95 int64 offset, 96 const Int64CompletionCallback& callback); 97 98 void Flush(const CompletionCallback& callback); 99 100 private: 101 struct IOResult { 102 IOResult(); 103 IOResult(int64 result, int os_error); 104 static IOResult FromOSError(int64 os_error); 105 106 int64 result; 107 int os_error; // Set only when result < 0. 108 }; 109 110 struct OpenResult { 111 MOVE_ONLY_TYPE_FOR_CPP_03(OpenResult, RValue) 112 public: 113 OpenResult(); 114 OpenResult(base::File file, IOResult error_code); 115 // C++03 move emulation of this type. 116 OpenResult(RValue other); 117 OpenResult& operator=(RValue other); 118 119 base::File file; 120 IOResult error_code; 121 }; 122 123 //////////////////////////////////////////////////////////////////////////// 124 // Platform-independent methods implemented in file_stream_context.cc. 125 //////////////////////////////////////////////////////////////////////////// 126 127 OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); 128 129 IOResult CloseFileImpl(); 130 131 IOResult FlushFileImpl(); 132 133 void OnOpenCompleted(const CompletionCallback& callback, 134 OpenResult open_result); 135 136 void CloseAndDelete(); 137 138 Int64CompletionCallback IntToInt64(const CompletionCallback& callback); 139 140 // Called when Open() or Seek() completes. |result| contains the result or a 141 // network error code. 142 void OnAsyncCompleted(const Int64CompletionCallback& callback, 143 const IOResult& result); 144 145 //////////////////////////////////////////////////////////////////////////// 146 // Platform-dependent methods implemented in 147 // file_stream_context_{win,posix}.cc. 148 //////////////////////////////////////////////////////////////////////////// 149 150 // Adjusts the position from where the data is read. 151 IOResult SeekFileImpl(base::File::Whence whence, int64 offset); 152 153 void OnFileOpened(); 154 155 #if defined(OS_WIN) 156 void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); 157 158 // Implementation of MessageLoopForIO::IOHandler. 159 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, 160 DWORD bytes_read, 161 DWORD error) OVERRIDE; 162 #elif defined(OS_POSIX) 163 // ReadFileImpl() is a simple wrapper around read() that handles EINTR 164 // signals and calls RecordAndMapError() to map errno to net error codes. 165 IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 166 167 // WriteFileImpl() is a simple wrapper around write() that handles EINTR 168 // signals and calls MapSystemError() to map errno to net error codes. 169 // It tries to write to completion. 170 IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 171 #endif 172 173 base::File file_; 174 bool async_in_progress_; 175 bool orphaned_; 176 scoped_refptr<base::TaskRunner> task_runner_; 177 178 #if defined(OS_WIN) 179 base::MessageLoopForIO::IOContext io_context_; 180 CompletionCallback callback_; 181 scoped_refptr<IOBuffer> in_flight_buf_; 182 #endif 183 184 DISALLOW_COPY_AND_ASSIGN(Context); 185 }; 186 187 } // namespace net 188 189 #endif // NET_BASE_FILE_STREAM_CONTEXT_H_ 190