Home | History | Annotate | Download | only in base
      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 
     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