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. GetNumFiles()70 size_t GetNumFiles() { return file_names_.size(); } 71 72 protected: GetMaxFileSize()73 size_t GetMaxFileSize() const { return max_file_size_; } 74 SetMaxFileSize(size_t size)75 void SetMaxFileSize(size_t size) { max_file_size_ = size; } 76 GetRotationIndex()77 size_t GetRotationIndex() const { return rotation_index_; } 78 SetRotationIndex(size_t index)79 void SetRotationIndex(size_t index) { rotation_index_ = index; } 80 OnRotation()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); ~CallSessionFileRotatingStream()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