• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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