Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef WEBRTC_BASE_FILEROTATINGSTREAM_H_
     12 #define WEBRTC_BASE_FILEROTATINGSTREAM_H_
     13 
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "webrtc/base/constructormagic.h"
     18 #include "webrtc/base/stream.h"
     19 
     20 namespace rtc {
     21 
     22 // FileRotatingStream writes to a file in the directory specified in the
     23 // constructor. It rotates the files once the current file is full. The
     24 // individual file size and the number of files used is configurable in the
     25 // constructor. Open() must be called before using this stream.
     26 class FileRotatingStream : public StreamInterface {
     27  public:
     28   // Use this constructor for reading a directory previously written to with
     29   // this stream.
     30   FileRotatingStream(const std::string& dir_path,
     31                      const std::string& file_prefix);
     32 
     33   // Use this constructor for writing to a directory. Files in the directory
     34   // matching the prefix will be deleted on open.
     35   FileRotatingStream(const std::string& dir_path,
     36                      const std::string& file_prefix,
     37                      size_t max_file_size,
     38                      size_t num_files);
     39 
     40   ~FileRotatingStream() override;
     41 
     42   // StreamInterface methods.
     43   StreamState GetState() const override;
     44   StreamResult Read(void* buffer,
     45                     size_t buffer_len,
     46                     size_t* read,
     47                     int* error) override;
     48   StreamResult Write(const void* data,
     49                      size_t data_len,
     50                      size_t* written,
     51                      int* error) override;
     52   bool Flush() override;
     53   // Returns the total file size currently used on disk.
     54   bool GetSize(size_t* size) const override;
     55   void Close() override;
     56 
     57   // Opens the appropriate file(s). Call this before using the stream.
     58   bool Open();
     59 
     60   // Disabling buffering causes writes to block until disk is updated. This is
     61   // enabled by default for performance.
     62   bool DisableBuffering();
     63 
     64   // Returns the path used for the i-th newest file, where the 0th file is the
     65   // newest file. The file may or may not exist, this is just used for
     66   // formatting. Index must be less than GetNumFiles().
     67   std::string GetFilePath(size_t index) const;
     68 
     69   // Returns the number of files that will used by this stream.
     70   size_t GetNumFiles() { return file_names_.size(); }
     71 
     72  protected:
     73   size_t GetMaxFileSize() const { return max_file_size_; }
     74 
     75   void SetMaxFileSize(size_t size) { max_file_size_ = size; }
     76 
     77   size_t GetRotationIndex() const { return rotation_index_; }
     78 
     79   void SetRotationIndex(size_t index) { rotation_index_ = index; }
     80 
     81   virtual void OnRotation() {}
     82 
     83  private:
     84   enum Mode { kRead, kWrite };
     85 
     86   FileRotatingStream(const std::string& dir_path,
     87                      const std::string& file_prefix,
     88                      size_t max_file_size,
     89                      size_t num_files,
     90                      Mode mode);
     91 
     92   bool OpenCurrentFile();
     93   void CloseCurrentFile();
     94 
     95   // Rotates the files by creating a new current file, renaming the
     96   // existing files, and deleting the oldest one. e.g.
     97   // file_0 -> file_1
     98   // file_1 -> file_2
     99   // file_2 -> delete
    100   // create new file_0
    101   void RotateFiles();
    102 
    103   // Returns a list of file names in the directory beginning with the prefix.
    104   std::vector<std::string> GetFilesWithPrefix() const;
    105   // Private version of GetFilePath.
    106   std::string GetFilePath(size_t index, size_t num_files) const;
    107 
    108   const std::string dir_path_;
    109   const std::string file_prefix_;
    110   const Mode mode_;
    111 
    112   // FileStream is used to write to the current file.
    113   scoped_ptr<FileStream> file_stream_;
    114   // Convenience storage for file names so we don't generate them over and over.
    115   std::vector<std::string> file_names_;
    116   size_t max_file_size_;
    117   size_t current_file_index_;
    118   // The rotation index indicates the index of the file that will be
    119   // deleted first on rotation. Indices lower than this index will be rotated.
    120   size_t rotation_index_;
    121   // Number of bytes written to current file. We need this because with
    122   // buffering the file size read from disk might not be accurate.
    123   size_t current_bytes_written_;
    124   bool disable_buffering_;
    125 
    126   RTC_DISALLOW_COPY_AND_ASSIGN(FileRotatingStream);
    127 };
    128 
    129 // CallSessionFileRotatingStream is meant to be used in situations where we will
    130 // have limited disk space. Its purpose is to read and write logs up to a
    131 // maximum size. Once the maximum size is exceeded, logs from the middle are
    132 // deleted whereas logs from the beginning and end are preserved. The reason for
    133 // this is because we anticipate that in WebRTC the beginning and end of the
    134 // logs are most useful for call diagnostics.
    135 //
    136 // This implementation simply writes to a single file until
    137 // |max_total_log_size| / 2 bytes are written to it, and subsequently writes to
    138 // a set of rotating files. We do this by inheriting FileRotatingStream and
    139 // setting the appropriate internal variables so that we don't delete the last
    140 // (earliest) file on rotate, and that that file's size is bigger.
    141 //
    142 // Open() must be called before using this stream.
    143 class CallSessionFileRotatingStream : public FileRotatingStream {
    144  public:
    145   // Use this constructor for reading a directory previously written to with
    146   // this stream.
    147   explicit CallSessionFileRotatingStream(const std::string& dir_path);
    148   // Use this constructor for writing to a directory. Files in the directory
    149   // matching what's used by the stream will be deleted. |max_total_log_size|
    150   // must be at least 4.
    151   CallSessionFileRotatingStream(const std::string& dir_path,
    152                                 size_t max_total_log_size);
    153   ~CallSessionFileRotatingStream() override {}
    154 
    155  protected:
    156   void OnRotation() override;
    157 
    158  private:
    159   static size_t GetRotatingLogSize(size_t max_total_log_size);
    160   static size_t GetNumRotatingLogFiles(size_t max_total_log_size);
    161   static const char* kLogPrefix;
    162   static const size_t kRotatingLogFileDefaultSize;
    163 
    164   const size_t max_total_log_size_;
    165   size_t num_rotations_;
    166 
    167   RTC_DISALLOW_COPY_AND_ASSIGN(CallSessionFileRotatingStream);
    168 };
    169 
    170 }  // namespace rtc
    171 
    172 #endif  // WEBRTC_BASE_FILEROTATINGSTREAM_H_
    173