file_rotating_stream.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #ifndef RTC_BASE_FILE_ROTATING_STREAM_H_
  11. #define RTC_BASE_FILE_ROTATING_STREAM_H_
  12. #include <stddef.h>
  13. #include <memory>
  14. #include <string>
  15. #include <vector>
  16. #include "rtc_base/constructor_magic.h"
  17. #include "rtc_base/stream.h"
  18. #include "rtc_base/system/file_wrapper.h"
  19. namespace rtc {
  20. // FileRotatingStream writes to a file in the directory specified in the
  21. // constructor. It rotates the files once the current file is full. The
  22. // individual file size and the number of files used is configurable in the
  23. // constructor. Open() must be called before using this stream.
  24. class FileRotatingStream : public StreamInterface {
  25. public:
  26. // Use this constructor for reading a directory previously written to with
  27. // this stream.
  28. FileRotatingStream(const std::string& dir_path,
  29. const std::string& file_prefix);
  30. // Use this constructor for writing to a directory. Files in the directory
  31. // matching the prefix will be deleted on open.
  32. FileRotatingStream(const std::string& dir_path,
  33. const std::string& file_prefix,
  34. size_t max_file_size,
  35. size_t num_files);
  36. ~FileRotatingStream() override;
  37. // StreamInterface methods.
  38. StreamState GetState() const override;
  39. StreamResult Read(void* buffer,
  40. size_t buffer_len,
  41. size_t* read,
  42. int* error) override;
  43. StreamResult Write(const void* data,
  44. size_t data_len,
  45. size_t* written,
  46. int* error) override;
  47. bool Flush() override;
  48. void Close() override;
  49. // Opens the appropriate file(s). Call this before using the stream.
  50. bool Open();
  51. // Disabling buffering causes writes to block until disk is updated. This is
  52. // enabled by default for performance.
  53. bool DisableBuffering();
  54. // Returns the path used for the i-th newest file, where the 0th file is the
  55. // newest file. The file may or may not exist, this is just used for
  56. // formatting. Index must be less than GetNumFiles().
  57. std::string GetFilePath(size_t index) const;
  58. // Returns the number of files that will used by this stream.
  59. size_t GetNumFiles() const { return file_names_.size(); }
  60. protected:
  61. size_t GetMaxFileSize() const { return max_file_size_; }
  62. void SetMaxFileSize(size_t size) { max_file_size_ = size; }
  63. size_t GetRotationIndex() const { return rotation_index_; }
  64. void SetRotationIndex(size_t index) { rotation_index_ = index; }
  65. virtual void OnRotation() {}
  66. private:
  67. bool OpenCurrentFile();
  68. void CloseCurrentFile();
  69. // Rotates the files by creating a new current file, renaming the
  70. // existing files, and deleting the oldest one. e.g.
  71. // file_0 -> file_1
  72. // file_1 -> file_2
  73. // file_2 -> delete
  74. // create new file_0
  75. void RotateFiles();
  76. // Private version of GetFilePath.
  77. std::string GetFilePath(size_t index, size_t num_files) const;
  78. const std::string dir_path_;
  79. const std::string file_prefix_;
  80. // File we're currently writing to.
  81. webrtc::FileWrapper file_;
  82. // Convenience storage for file names so we don't generate them over and over.
  83. std::vector<std::string> file_names_;
  84. size_t max_file_size_;
  85. size_t current_file_index_;
  86. // The rotation index indicates the index of the file that will be
  87. // deleted first on rotation. Indices lower than this index will be rotated.
  88. size_t rotation_index_;
  89. // Number of bytes written to current file. We need this because with
  90. // buffering the file size read from disk might not be accurate.
  91. size_t current_bytes_written_;
  92. bool disable_buffering_;
  93. RTC_DISALLOW_COPY_AND_ASSIGN(FileRotatingStream);
  94. };
  95. // CallSessionFileRotatingStream is meant to be used in situations where we will
  96. // have limited disk space. Its purpose is to write logs up to a
  97. // maximum size. Once the maximum size is exceeded, logs from the middle are
  98. // deleted whereas logs from the beginning and end are preserved. The reason for
  99. // this is because we anticipate that in WebRTC the beginning and end of the
  100. // logs are most useful for call diagnostics.
  101. //
  102. // This implementation simply writes to a single file until
  103. // |max_total_log_size| / 2 bytes are written to it, and subsequently writes to
  104. // a set of rotating files. We do this by inheriting FileRotatingStream and
  105. // setting the appropriate internal variables so that we don't delete the last
  106. // (earliest) file on rotate, and that that file's size is bigger.
  107. //
  108. // Open() must be called before using this stream.
  109. // To read the logs produced by this class, one can use the companion class
  110. // CallSessionFileRotatingStreamReader.
  111. class CallSessionFileRotatingStream : public FileRotatingStream {
  112. public:
  113. // Use this constructor for writing to a directory. Files in the directory
  114. // matching what's used by the stream will be deleted. |max_total_log_size|
  115. // must be at least 4.
  116. CallSessionFileRotatingStream(const std::string& dir_path,
  117. size_t max_total_log_size);
  118. ~CallSessionFileRotatingStream() override {}
  119. protected:
  120. void OnRotation() override;
  121. private:
  122. static size_t GetRotatingLogSize(size_t max_total_log_size);
  123. static size_t GetNumRotatingLogFiles(size_t max_total_log_size);
  124. static const size_t kRotatingLogFileDefaultSize;
  125. const size_t max_total_log_size_;
  126. size_t num_rotations_;
  127. RTC_DISALLOW_COPY_AND_ASSIGN(CallSessionFileRotatingStream);
  128. };
  129. // This is a convenience class, to read all files produced by a
  130. // FileRotatingStream, all in one go. Typical use calls GetSize and ReadData
  131. // only once. The list of file names to read is based on the contents of the log
  132. // directory at construction time.
  133. class FileRotatingStreamReader {
  134. public:
  135. FileRotatingStreamReader(const std::string& dir_path,
  136. const std::string& file_prefix);
  137. ~FileRotatingStreamReader();
  138. size_t GetSize() const;
  139. size_t ReadAll(void* buffer, size_t size) const;
  140. private:
  141. std::vector<std::string> file_names_;
  142. };
  143. class CallSessionFileRotatingStreamReader : public FileRotatingStreamReader {
  144. public:
  145. CallSessionFileRotatingStreamReader(const std::string& dir_path);
  146. };
  147. } // namespace rtc
  148. #endif // RTC_BASE_FILE_ROTATING_STREAM_H_