file_stream_context.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. // This file defines FileStream::Context class.
  5. // The general design of FileStream is as follows: file_stream.h defines
  6. // FileStream class which basically is just an "wrapper" not containing any
  7. // specific implementation details. It re-routes all its method calls to
  8. // the instance of FileStream::Context (FileStream holds a scoped_ptr to
  9. // FileStream::Context instance). Context was extracted into a different class
  10. // to be able to do and finish all async operations even when FileStream
  11. // instance is deleted. So FileStream's destructor can schedule file
  12. // closing to be done by Context in WorkerPool (or the TaskRunner passed to
  13. // constructor) and then just return (releasing Context pointer from
  14. // scoped_ptr) without waiting for actual closing to complete.
  15. // Implementation of FileStream::Context is divided in two parts: some methods
  16. // and members are platform-independent and some depend on the platform. This
  17. // header file contains the complete definition of Context class including all
  18. // platform-dependent parts (because of that it has a lot of #if-#else
  19. // branching). Implementations of all platform-independent methods are
  20. // located in file_stream_context.cc, and all platform-dependent methods are
  21. // in file_stream_context_{win,posix}.cc. This separation provides better
  22. // readability of Context's code. And we tried to make as much Context code
  23. // platform-independent as possible. So file_stream_context_{win,posix}.cc are
  24. // much smaller than file_stream_context.cc now.
  25. #ifndef NET_BASE_FILE_STREAM_CONTEXT_H_
  26. #define NET_BASE_FILE_STREAM_CONTEXT_H_
  27. #include <stdint.h>
  28. #include "base/files/file.h"
  29. #include "base/logging.h"
  30. #include "base/memory/weak_ptr.h"
  31. #include "base/message_loop/message_pump_for_io.h"
  32. #include "base/task/single_thread_task_runner.h"
  33. #include "base/task/task_runner.h"
  34. #include "build/build_config.h"
  35. #include "net/base/completion_once_callback.h"
  36. #include "net/base/file_stream.h"
  37. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  38. #include <errno.h>
  39. #endif
  40. namespace base {
  41. class FilePath;
  42. }
  43. namespace net {
  44. class IOBuffer;
  45. #if BUILDFLAG(IS_WIN)
  46. class FileStream::Context : public base::MessagePumpForIO::IOHandler {
  47. #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  48. class FileStream::Context {
  49. #endif
  50. public:
  51. ////////////////////////////////////////////////////////////////////////////
  52. // Platform-dependent methods implemented in
  53. // file_stream_context_{win,posix}.cc.
  54. ////////////////////////////////////////////////////////////////////////////
  55. explicit Context(scoped_refptr<base::TaskRunner> task_runner);
  56. Context(base::File file, scoped_refptr<base::TaskRunner> task_runner);
  57. Context(const Context&) = delete;
  58. Context& operator=(const Context&) = delete;
  59. #if BUILDFLAG(IS_WIN)
  60. ~Context() override;
  61. #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  62. ~Context();
  63. #endif
  64. int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback);
  65. int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback);
  66. bool async_in_progress() const { return async_in_progress_; }
  67. ////////////////////////////////////////////////////////////////////////////
  68. // Platform-independent methods implemented in file_stream_context.cc.
  69. ////////////////////////////////////////////////////////////////////////////
  70. // Destroys the context. It can be deleted in the method or deletion can be
  71. // deferred if some asynchronous operation is now in progress or if file is
  72. // not closed yet.
  73. void Orphan();
  74. void Open(const base::FilePath& path,
  75. int open_flags,
  76. CompletionOnceCallback callback);
  77. void Close(CompletionOnceCallback callback);
  78. // Seeks |offset| bytes from the start of the file.
  79. void Seek(int64_t offset, Int64CompletionOnceCallback callback);
  80. void GetFileInfo(base::File::Info* file_info,
  81. CompletionOnceCallback callback);
  82. void Flush(CompletionOnceCallback callback);
  83. bool IsOpen() const;
  84. private:
  85. struct IOResult {
  86. IOResult();
  87. IOResult(int64_t result, logging::SystemErrorCode os_error);
  88. static IOResult FromOSError(logging::SystemErrorCode os_error);
  89. int64_t result;
  90. logging::SystemErrorCode os_error; // Set only when result < 0.
  91. };
  92. struct OpenResult {
  93. public:
  94. OpenResult();
  95. OpenResult(base::File file, IOResult error_code);
  96. OpenResult(OpenResult&& other);
  97. OpenResult& operator=(OpenResult&& other);
  98. OpenResult(const OpenResult&) = delete;
  99. OpenResult& operator=(const OpenResult&) = delete;
  100. base::File file;
  101. IOResult error_code;
  102. };
  103. ////////////////////////////////////////////////////////////////////////////
  104. // Platform-independent methods implemented in file_stream_context.cc.
  105. ////////////////////////////////////////////////////////////////////////////
  106. OpenResult OpenFileImpl(const base::FilePath& path, int open_flags);
  107. IOResult GetFileInfoImpl(base::File::Info* file_info);
  108. IOResult CloseFileImpl();
  109. IOResult FlushFileImpl();
  110. void OnOpenCompleted(CompletionOnceCallback callback, OpenResult open_result);
  111. void CloseAndDelete();
  112. Int64CompletionOnceCallback IntToInt64(CompletionOnceCallback callback);
  113. // Called when Open() or Seek() completes. |result| contains the result or a
  114. // network error code.
  115. void OnAsyncCompleted(Int64CompletionOnceCallback callback,
  116. const IOResult& result);
  117. ////////////////////////////////////////////////////////////////////////////
  118. // Platform-dependent methods implemented in
  119. // file_stream_context_{win,posix}.cc.
  120. ////////////////////////////////////////////////////////////////////////////
  121. // Adjusts the position from where the data is read.
  122. IOResult SeekFileImpl(int64_t offset);
  123. void OnFileOpened();
  124. #if BUILDFLAG(IS_WIN)
  125. void IOCompletionIsPending(CompletionOnceCallback callback, IOBuffer* buf);
  126. // Implementation of MessagePumpForIO::IOHandler.
  127. void OnIOCompleted(base::MessagePumpForIO::IOContext* context,
  128. DWORD bytes_read,
  129. DWORD error) override;
  130. // Invokes the user callback.
  131. void InvokeUserCallback();
  132. // Deletes an orphaned context.
  133. void DeleteOrphanedContext();
  134. // The ReadFile call on Windows can execute synchronously at times.
  135. // http://support.microsoft.com/kb/156932. This ends up blocking the calling
  136. // thread which is undesirable. To avoid this we execute the ReadFile call
  137. // on a worker thread.
  138. // The |context| parameter is a pointer to the current Context instance. It
  139. // is safe to pass this as is to the pool as the Context instance should
  140. // remain valid until the pending Read operation completes.
  141. // The |file| parameter is the handle to the file being read.
  142. // The |buf| parameter is the buffer where we want the ReadFile to read the
  143. // data into.
  144. // The |buf_len| parameter contains the number of bytes to be read.
  145. // The |overlapped| parameter is a pointer to the OVERLAPPED structure being
  146. // used.
  147. // The |origin_thread_task_runner| is a task runner instance used to post
  148. // tasks back to the originating thread.
  149. static void ReadAsync(
  150. FileStream::Context* context,
  151. HANDLE file,
  152. scoped_refptr<IOBuffer> buf,
  153. int buf_len,
  154. OVERLAPPED* overlapped,
  155. scoped_refptr<base::SingleThreadTaskRunner> origin_thread_task_runner);
  156. // This callback executes on the main calling thread. It informs the caller
  157. // about the result of the ReadFile call.
  158. // The |read_file_ret| parameter contains the return value of the ReadFile
  159. // call.
  160. // The |bytes_read| contains the number of bytes read from the file, if
  161. // ReadFile succeeds.
  162. // The |os_error| parameter contains the value of the last error returned by
  163. // the ReadFile API.
  164. void ReadAsyncResult(BOOL read_file_ret, DWORD bytes_read, DWORD os_error);
  165. #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  166. // ReadFileImpl() is a simple wrapper around read() that handles EINTR
  167. // signals and calls RecordAndMapError() to map errno to net error codes.
  168. IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
  169. // WriteFileImpl() is a simple wrapper around write() that handles EINTR
  170. // signals and calls MapSystemError() to map errno to net error codes.
  171. // It tries to write to completion.
  172. IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
  173. #endif // BUILDFLAG(IS_WIN)
  174. base::File file_;
  175. bool async_in_progress_ = false;
  176. bool orphaned_ = false;
  177. const scoped_refptr<base::TaskRunner> task_runner_;
  178. #if BUILDFLAG(IS_WIN)
  179. base::MessagePumpForIO::IOContext io_context_;
  180. CompletionOnceCallback callback_;
  181. scoped_refptr<IOBuffer> in_flight_buf_;
  182. // This flag is set to true when we receive a Read request which is queued to
  183. // the thread pool.
  184. bool async_read_initiated_ = false;
  185. // This flag is set to true when we receive a notification ReadAsyncResult()
  186. // on the calling thread which indicates that the asynchronous Read
  187. // operation is complete.
  188. bool async_read_completed_ = false;
  189. // This flag is set to true when we receive an IO completion notification for
  190. // an asynchronously initiated Read operation. OnIOComplete().
  191. bool io_complete_for_read_received_ = false;
  192. // Tracks the result of the IO completion operation. Set in OnIOComplete.
  193. int result_ = 0;
  194. #endif
  195. };
  196. } // namespace net
  197. #endif // NET_BASE_FILE_STREAM_CONTEXT_H_