| OLD | NEW |
| (Empty) |
| 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/memory/weak_ptr.h" | |
| 32 #include "base/message_loop/message_loop.h" | |
| 33 #include "base/move.h" | |
| 34 #include "base/task_runner.h" | |
| 35 #include "net/base/completion_callback.h" | |
| 36 #include "net/base/file_stream.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 Read(IOBuffer* buf, | |
| 70 int buf_len, | |
| 71 const CompletionCallback& callback); | |
| 72 | |
| 73 int Write(IOBuffer* buf, | |
| 74 int buf_len, | |
| 75 const CompletionCallback& callback); | |
| 76 | |
| 77 const base::File& file() const { return file_; } | |
| 78 bool async_in_progress() const { return async_in_progress_; } | |
| 79 | |
| 80 //////////////////////////////////////////////////////////////////////////// | |
| 81 // Platform-independent methods implemented in file_stream_context.cc. | |
| 82 //////////////////////////////////////////////////////////////////////////// | |
| 83 | |
| 84 // Destroys the context. It can be deleted in the method or deletion can be | |
| 85 // deferred if some asynchronous operation is now in progress or if file is | |
| 86 // not closed yet. | |
| 87 void Orphan(); | |
| 88 | |
| 89 void Open(const base::FilePath& path, | |
| 90 int open_flags, | |
| 91 const CompletionCallback& callback); | |
| 92 | |
| 93 void Close(const CompletionCallback& callback); | |
| 94 | |
| 95 void Seek(base::File::Whence whence, | |
| 96 int64 offset, | |
| 97 const Int64CompletionCallback& callback); | |
| 98 | |
| 99 void Flush(const CompletionCallback& callback); | |
| 100 | |
| 101 private: | |
| 102 struct IOResult { | |
| 103 IOResult(); | |
| 104 IOResult(int64 result, logging::SystemErrorCode os_error); | |
| 105 static IOResult FromOSError(logging::SystemErrorCode os_error); | |
| 106 | |
| 107 int64 result; | |
| 108 logging::SystemErrorCode os_error; // Set only when result < 0. | |
| 109 }; | |
| 110 | |
| 111 struct OpenResult { | |
| 112 MOVE_ONLY_TYPE_FOR_CPP_03(OpenResult, RValue) | |
| 113 public: | |
| 114 OpenResult(); | |
| 115 OpenResult(base::File file, IOResult error_code); | |
| 116 // C++03 move emulation of this type. | |
| 117 OpenResult(RValue other); | |
| 118 OpenResult& operator=(RValue other); | |
| 119 | |
| 120 base::File file; | |
| 121 IOResult error_code; | |
| 122 }; | |
| 123 | |
| 124 //////////////////////////////////////////////////////////////////////////// | |
| 125 // Platform-independent methods implemented in file_stream_context.cc. | |
| 126 //////////////////////////////////////////////////////////////////////////// | |
| 127 | |
| 128 OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); | |
| 129 | |
| 130 IOResult CloseFileImpl(); | |
| 131 | |
| 132 IOResult FlushFileImpl(); | |
| 133 | |
| 134 void OnOpenCompleted(const CompletionCallback& callback, | |
| 135 OpenResult open_result); | |
| 136 | |
| 137 void CloseAndDelete(); | |
| 138 | |
| 139 Int64CompletionCallback IntToInt64(const CompletionCallback& callback); | |
| 140 | |
| 141 // Called when Open() or Seek() completes. |result| contains the result or a | |
| 142 // network error code. | |
| 143 void OnAsyncCompleted(const Int64CompletionCallback& callback, | |
| 144 const IOResult& result); | |
| 145 | |
| 146 //////////////////////////////////////////////////////////////////////////// | |
| 147 // Platform-dependent methods implemented in | |
| 148 // file_stream_context_{win,posix}.cc. | |
| 149 //////////////////////////////////////////////////////////////////////////// | |
| 150 | |
| 151 // Adjusts the position from where the data is read. | |
| 152 IOResult SeekFileImpl(base::File::Whence whence, int64 offset); | |
| 153 | |
| 154 void OnFileOpened(); | |
| 155 | |
| 156 #if defined(OS_WIN) | |
| 157 void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf); | |
| 158 | |
| 159 // Implementation of MessageLoopForIO::IOHandler. | |
| 160 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, | |
| 161 DWORD bytes_read, | |
| 162 DWORD error) override; | |
| 163 | |
| 164 // Invokes the user callback. | |
| 165 void InvokeUserCallback(); | |
| 166 | |
| 167 // Deletes an orphaned context. | |
| 168 void DeleteOrphanedContext(); | |
| 169 | |
| 170 // The ReadFile call on Windows can execute synchonously at times. | |
| 171 // http://support.microsoft.com/kb/156932. This ends up blocking the calling | |
| 172 // thread which is undesirable. To avoid this we execute the ReadFile call | |
| 173 // on a worker thread. | |
| 174 // The |context| parameter is a pointer to the current Context instance. It | |
| 175 // is safe to pass this as is to the pool as the Context instance should | |
| 176 // remain valid until the pending Read operation completes. | |
| 177 // The |file| parameter is the handle to the file being read. | |
| 178 // The |buf| parameter is the buffer where we want the ReadFile to read the | |
| 179 // data into. | |
| 180 // The |buf_len| parameter contains the number of bytes to be read. | |
| 181 // The |overlapped| parameter is a pointer to the OVERLAPPED structure being | |
| 182 // used. | |
| 183 // The |origin_thread_loop| is a MessageLoopProxy instance used to post tasks | |
| 184 // back to the originating thread. | |
| 185 static void ReadAsync( | |
| 186 FileStream::Context* context, | |
| 187 HANDLE file, | |
| 188 scoped_refptr<net::IOBuffer> buf, | |
| 189 int buf_len, | |
| 190 OVERLAPPED* overlapped, | |
| 191 scoped_refptr<base::MessageLoopProxy> origin_thread_loop); | |
| 192 | |
| 193 // This callback executes on the main calling thread. It informs the caller | |
| 194 // about the result of the ReadFile call. | |
| 195 // The |read_file_ret| parameter contains the return value of the ReadFile | |
| 196 // call. | |
| 197 // The |bytes_read| contains the number of bytes read from the file, if | |
| 198 // ReadFile succeeds. | |
| 199 // The |os_error| parameter contains the value of the last error returned by | |
| 200 // the ReadFile API. | |
| 201 void ReadAsyncResult(BOOL read_file_ret, DWORD bytes_read, DWORD os_error); | |
| 202 | |
| 203 #elif defined(OS_POSIX) | |
| 204 // ReadFileImpl() is a simple wrapper around read() that handles EINTR | |
| 205 // signals and calls RecordAndMapError() to map errno to net error codes. | |
| 206 IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); | |
| 207 | |
| 208 // WriteFileImpl() is a simple wrapper around write() that handles EINTR | |
| 209 // signals and calls MapSystemError() to map errno to net error codes. | |
| 210 // It tries to write to completion. | |
| 211 IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); | |
| 212 #endif | |
| 213 | |
| 214 base::File file_; | |
| 215 bool async_in_progress_; | |
| 216 bool orphaned_; | |
| 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 // This flag is set to true when we receive a Read request which is queued to | |
| 224 // the thread pool. | |
| 225 bool async_read_initiated_; | |
| 226 // This flag is set to true when we receive a notification ReadAsyncResult() | |
| 227 // on the calling thread which indicates that the asynchronous Read | |
| 228 // operation is complete. | |
| 229 bool async_read_completed_; | |
| 230 // This flag is set to true when we receive an IO completion notification for | |
| 231 // an asynchonously initiated Read operaton. OnIOComplete(). | |
| 232 bool io_complete_for_read_received_; | |
| 233 // Tracks the result of the IO completion operation. Set in OnIOComplete. | |
| 234 int result_; | |
| 235 #endif | |
| 236 | |
| 237 DISALLOW_COPY_AND_ASSIGN(Context); | |
| 238 }; | |
| 239 | |
| 240 } // namespace net | |
| 241 | |
| 242 #endif // NET_BASE_FILE_STREAM_CONTEXT_H_ | |
| OLD | NEW |