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 set_record_uma(bool value)92 void set_record_uma(bool value) { record_uma_ = value; } file()93 base::PlatformFile file() const { return file_; } async_in_progress()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 CloseAsync(const CompletionCallback& callback); 113 114 void SeekAsync(Whence whence, 115 int64 offset, 116 const Int64CompletionCallback& callback); 117 int64 SeekSync(Whence whence, int64 offset); 118 119 void FlushAsync(const CompletionCallback& callback); 120 int FlushSync(); 121 122 private: 123 //////////////////////////////////////////////////////////////////////////// 124 // Platform-independent methods implemented in file_stream_context.cc. 125 //////////////////////////////////////////////////////////////////////////// 126 127 struct IOResult { 128 IOResult(); 129 IOResult(int64 result, int os_error); 130 static IOResult FromOSError(int64 os_error); 131 132 int64 result; 133 int os_error; // Set only when result < 0. 134 }; 135 136 struct OpenResult { 137 OpenResult(); 138 OpenResult(base::PlatformFile file, IOResult error_code); 139 base::PlatformFile file; 140 IOResult error_code; 141 }; 142 143 // Log the error from |result| to |bound_net_log_|. 144 void RecordError(const IOResult& result, FileErrorSource source) const; 145 146 void BeginOpenEvent(const base::FilePath& path); 147 148 OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); 149 150 void ProcessOpenError(const IOResult& result); 151 void OnOpenCompleted(const CompletionCallback& callback, 152 OpenResult open_result); 153 154 void CloseAndDelete(); 155 void OnCloseCompleted(); 156 157 Int64CompletionCallback IntToInt64(const CompletionCallback& callback); 158 159 // Called when asynchronous Seek() is completed. 160 // Reports error if needed and calls callback. 161 void ProcessAsyncResult(const Int64CompletionCallback& callback, 162 FileErrorSource source, 163 const IOResult& result); 164 165 // Called when asynchronous Open() or Seek() 166 // is completed. |result| contains the result or a network error code. 167 void OnAsyncCompleted(const Int64CompletionCallback& callback, int64 result); 168 169 //////////////////////////////////////////////////////////////////////////// 170 // Helper stuff which is platform-dependent but is used in the platform- 171 // independent code implemented in file_stream_context.cc. These helpers were 172 // introduced solely to implement as much of the Context methods as 173 // possible independently from platform. 174 //////////////////////////////////////////////////////////////////////////// 175 176 #if defined(OS_WIN) GetLastErrno()177 int GetLastErrno() { return GetLastError(); } 178 void OnAsyncFileOpened(); 179 #elif defined(OS_POSIX) GetLastErrno()180 int GetLastErrno() { return errno; } OnAsyncFileOpened()181 void OnAsyncFileOpened() {} CancelIo(base::PlatformFile)182 void CancelIo(base::PlatformFile) {} 183 #endif 184 185 //////////////////////////////////////////////////////////////////////////// 186 // Platform-dependent methods implemented in 187 // file_stream_context_{win,posix}.cc. 188 //////////////////////////////////////////////////////////////////////////// 189 190 // Adjusts the position from where the data is read. 191 IOResult SeekFileImpl(Whence whence, int64 offset); 192 193 // Flushes all data written to the stream. 194 IOResult FlushFileImpl(); 195 196 // Closes the file. 197 IOResult CloseFileImpl(); 198 199 #if defined(OS_WIN) 200 void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); 201 202 // Implementation of MessageLoopForIO::IOHandler. 203 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, 204 DWORD bytes_read, 205 DWORD error) OVERRIDE; 206 #elif defined(OS_POSIX) 207 // ReadFileImpl() is a simple wrapper around read() that handles EINTR 208 // signals and calls RecordAndMapError() to map errno to net error codes. 209 IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 210 211 // WriteFileImpl() is a simple wrapper around write() that handles EINTR 212 // signals and calls MapSystemError() to map errno to net error codes. 213 // It tries to write to completion. 214 IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 215 #endif 216 217 base::PlatformFile file_; 218 bool record_uma_; 219 bool async_in_progress_; 220 bool orphaned_; 221 BoundNetLog bound_net_log_; 222 scoped_refptr<base::TaskRunner> task_runner_; 223 224 #if defined(OS_WIN) 225 base::MessageLoopForIO::IOContext io_context_; 226 CompletionCallback callback_; 227 scoped_refptr<IOBuffer> in_flight_buf_; 228 FileErrorSource error_source_; 229 #endif 230 231 DISALLOW_COPY_AND_ASSIGN(Context); 232 }; 233 234 } // namespace net 235 236 #endif // NET_BASE_FILE_STREAM_CONTEXT_H_ 237 238