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