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 #include "net/base/file_stream_whence.h" 37 38 #if defined(OS_POSIX) 39 #include <errno.h> 40 #endif 41 42 namespace base { 43 class FilePath; 44 } 45 46 namespace net { 47 48 class IOBuffer; 49 50 #if defined(OS_WIN) 51 class FileStream::Context : public base::MessageLoopForIO::IOHandler { 52 #elif defined(OS_POSIX) 53 class FileStream::Context { 54 #endif 55 public: 56 //////////////////////////////////////////////////////////////////////////// 57 // Platform-dependent methods implemented in 58 // file_stream_context_{win,posix}.cc. 59 //////////////////////////////////////////////////////////////////////////// 60 61 explicit Context(const scoped_refptr<base::TaskRunner>& task_runner); 62 Context(base::File file, const scoped_refptr<base::TaskRunner>& task_runner); 63 #if defined(OS_WIN) 64 virtual ~Context(); 65 #elif defined(OS_POSIX) 66 ~Context(); 67 #endif 68 69 int ReadAsync(IOBuffer* buf, 70 int buf_len, 71 const CompletionCallback& callback); 72 73 int WriteAsync(IOBuffer* buf, 74 int buf_len, 75 const CompletionCallback& callback); 76 77 //////////////////////////////////////////////////////////////////////////// 78 // Inline methods. 79 //////////////////////////////////////////////////////////////////////////// 80 file()81 const base::File& file() const { return file_; } async_in_progress()82 bool async_in_progress() const { return async_in_progress_; } 83 84 //////////////////////////////////////////////////////////////////////////// 85 // Platform-independent methods implemented in file_stream_context.cc. 86 //////////////////////////////////////////////////////////////////////////// 87 88 // Destroys the context. It can be deleted in the method or deletion can be 89 // deferred if some asynchronous operation is now in progress or if file is 90 // not closed yet. 91 void Orphan(); 92 93 void OpenAsync(const base::FilePath& path, 94 int open_flags, 95 const CompletionCallback& callback); 96 97 void CloseAsync(const CompletionCallback& callback); 98 99 void SeekAsync(Whence whence, 100 int64 offset, 101 const Int64CompletionCallback& callback); 102 103 void FlushAsync(const CompletionCallback& callback); 104 105 private: 106 //////////////////////////////////////////////////////////////////////////// 107 // Platform-independent methods implemented in file_stream_context.cc. 108 //////////////////////////////////////////////////////////////////////////// 109 110 struct IOResult { 111 IOResult(); 112 IOResult(int64 result, int os_error); 113 static IOResult FromOSError(int64 os_error); 114 115 int64 result; 116 int os_error; // Set only when result < 0. 117 }; 118 119 struct OpenResult { 120 MOVE_ONLY_TYPE_FOR_CPP_03(OpenResult, RValue) 121 public: 122 OpenResult(); 123 OpenResult(base::File file, IOResult error_code); 124 // C++03 move emulation of this type. 125 OpenResult(RValue other); 126 OpenResult& operator=(RValue other); 127 128 base::File file; 129 IOResult error_code; 130 }; 131 132 OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); 133 134 IOResult CloseFileImpl(); 135 136 void OnOpenCompleted(const CompletionCallback& callback, 137 OpenResult open_result); 138 139 void CloseAndDelete(); 140 141 Int64CompletionCallback IntToInt64(const CompletionCallback& callback); 142 143 // Called when asynchronous Open() or Seek() 144 // is completed. |result| contains the result or a network error code. 145 void OnAsyncCompleted(const Int64CompletionCallback& callback, 146 const IOResult& result); 147 148 //////////////////////////////////////////////////////////////////////////// 149 // Helper stuff which is platform-dependent but is used in the platform- 150 // independent code implemented in file_stream_context.cc. These helpers were 151 // introduced solely to implement as much of the Context methods as 152 // possible independently from platform. 153 //////////////////////////////////////////////////////////////////////////// 154 155 #if defined(OS_WIN) GetLastErrno()156 int GetLastErrno() { return GetLastError(); } 157 void OnAsyncFileOpened(); 158 #elif defined(OS_POSIX) GetLastErrno()159 int GetLastErrno() { return errno; } OnAsyncFileOpened()160 void OnAsyncFileOpened() {} CancelIo(base::PlatformFile)161 void CancelIo(base::PlatformFile) {} 162 #endif 163 164 //////////////////////////////////////////////////////////////////////////// 165 // Platform-dependent methods implemented in 166 // file_stream_context_{win,posix}.cc. 167 //////////////////////////////////////////////////////////////////////////// 168 169 // Adjusts the position from where the data is read. 170 IOResult SeekFileImpl(Whence whence, int64 offset); 171 172 // Flushes all data written to the stream. 173 IOResult FlushFileImpl(); 174 175 #if defined(OS_WIN) 176 void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); 177 178 // Implementation of MessageLoopForIO::IOHandler. 179 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, 180 DWORD bytes_read, 181 DWORD error) OVERRIDE; 182 #elif defined(OS_POSIX) 183 // ReadFileImpl() is a simple wrapper around read() that handles EINTR 184 // signals and calls RecordAndMapError() to map errno to net error codes. 185 IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 186 187 // WriteFileImpl() is a simple wrapper around write() that handles EINTR 188 // signals and calls MapSystemError() to map errno to net error codes. 189 // It tries to write to completion. 190 IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 191 #endif 192 193 base::File file_; 194 bool async_in_progress_; 195 bool orphaned_; 196 scoped_refptr<base::TaskRunner> task_runner_; 197 198 #if defined(OS_WIN) 199 base::MessageLoopForIO::IOContext io_context_; 200 CompletionCallback callback_; 201 scoped_refptr<IOBuffer> in_flight_buf_; 202 #endif 203 204 DISALLOW_COPY_AND_ASSIGN(Context); 205 }; 206 207 } // namespace net 208 209 #endif // NET_BASE_FILE_STREAM_CONTEXT_H_ 210