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 SeekAsync(Whence whence,
    113                  int64 offset,
    114                  const Int64CompletionCallback& callback);
    115   int64 SeekSync(Whence whence, int64 offset);
    116 
    117   void FlushAsync(const CompletionCallback& callback);
    118   int FlushSync();
    119 
    120  private:
    121   ////////////////////////////////////////////////////////////////////////////
    122   // Platform-independent methods implemented in file_stream_context.cc.
    123   ////////////////////////////////////////////////////////////////////////////
    124 
    125   struct IOResult {
    126     IOResult();
    127     IOResult(int64 result, int os_error);
    128     static IOResult FromOSError(int64 os_error);
    129 
    130     int64 result;
    131     int os_error;  // Set only when result < 0.
    132   };
    133 
    134   struct OpenResult {
    135     OpenResult();
    136     OpenResult(base::PlatformFile file, IOResult error_code);
    137     base::PlatformFile file;
    138     IOResult error_code;
    139   };
    140 
    141   // Log the error from |result| to |bound_net_log_|.
    142   void RecordError(const IOResult& result, FileErrorSource source) const;
    143 
    144   void BeginOpenEvent(const base::FilePath& path);
    145 
    146   OpenResult OpenFileImpl(const base::FilePath& path, int open_flags);
    147 
    148   void ProcessOpenError(const IOResult& result);
    149   void OnOpenCompleted(const CompletionCallback& callback,
    150                        OpenResult open_result);
    151 
    152   void CloseAndDelete();
    153   void OnCloseCompleted();
    154 
    155   Int64CompletionCallback IntToInt64(const CompletionCallback& callback);
    156 
    157   // Called when asynchronous Seek() is completed.
    158   // Reports error if needed and calls callback.
    159   void ProcessAsyncResult(const Int64CompletionCallback& callback,
    160                           FileErrorSource source,
    161                           const IOResult& result);
    162 
    163   // Called when asynchronous Open() or Seek()
    164   // is completed. |result| contains the result or a network error code.
    165   void OnAsyncCompleted(const Int64CompletionCallback& callback, int64 result);
    166 
    167   ////////////////////////////////////////////////////////////////////////////
    168   // Helper stuff which is platform-dependent but is used in the platform-
    169   // independent code implemented in file_stream_context.cc. These helpers were
    170   // introduced solely to implement as much of the Context methods as
    171   // possible independently from platform.
    172   ////////////////////////////////////////////////////////////////////////////
    173 
    174 #if defined(OS_WIN)
    175   int GetLastErrno() { return GetLastError(); }
    176   void OnAsyncFileOpened();
    177 #elif defined(OS_POSIX)
    178   int GetLastErrno() { return errno; }
    179   void OnAsyncFileOpened() {}
    180   void CancelIo(base::PlatformFile) {}
    181 #endif
    182 
    183   ////////////////////////////////////////////////////////////////////////////
    184   // Platform-dependent methods implemented in
    185   // file_stream_context_{win,posix}.cc.
    186   ////////////////////////////////////////////////////////////////////////////
    187 
    188   // Adjusts the position from where the data is read.
    189   IOResult SeekFileImpl(Whence whence, int64 offset);
    190 
    191   // Flushes all data written to the stream.
    192   IOResult FlushFileImpl();
    193 
    194 #if defined(OS_WIN)
    195   void IOCompletionIsPending(const CompletionCallback& callback, IOBuffer* buf);
    196 
    197   // Implementation of MessageLoopForIO::IOHandler.
    198   virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
    199                              DWORD bytes_read,
    200                              DWORD error) OVERRIDE;
    201 #elif defined(OS_POSIX)
    202   // ReadFileImpl() is a simple wrapper around read() that handles EINTR
    203   // signals and calls RecordAndMapError() to map errno to net error codes.
    204   IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
    205 
    206   // WriteFileImpl() is a simple wrapper around write() that handles EINTR
    207   // signals and calls MapSystemError() to map errno to net error codes.
    208   // It tries to write to completion.
    209   IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len);
    210 #endif
    211 
    212   base::PlatformFile file_;
    213   bool record_uma_;
    214   bool async_in_progress_;
    215   bool orphaned_;
    216   BoundNetLog bound_net_log_;
    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   FileErrorSource error_source_;
    224 #endif
    225 
    226   DISALLOW_COPY_AND_ASSIGN(Context);
    227 };
    228 
    229 }  // namespace net
    230 
    231 #endif  // NET_BASE_FILE_STREAM_CONTEXT_H_
    232 
    233