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
43namespace base {
44class FilePath;
45}
46
47namespace net {
48
49class IOBuffer;
50
51#if defined(OS_WIN)
52class FileStream::Context : public base::MessageLoopForIO::IOHandler {
53#elif defined(OS_POSIX)
54class 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 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)
177  int GetLastErrno() { return GetLastError(); }
178  void OnAsyncFileOpened();
179#elif defined(OS_POSIX)
180  int GetLastErrno() { return errno; }
181  void OnAsyncFileOpened() {}
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