1 | #pragma once
|
---|
2 | #include <plog/Appenders/IAppender.h>
|
---|
3 | #include <plog/Converters/UTF8Converter.h>
|
---|
4 | #include <plog/Util.h>
|
---|
5 | #include <algorithm>
|
---|
6 |
|
---|
7 | namespace plog
|
---|
8 | {
|
---|
9 | template<class Formatter, class Converter = UTF8Converter>
|
---|
10 | class RollingFileAppender : public IAppender
|
---|
11 | {
|
---|
12 | public:
|
---|
13 | RollingFileAppender(const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0)
|
---|
14 | : m_fileSize()
|
---|
15 | , m_maxFileSize((std::max)(static_cast<off_t>(maxFileSize), static_cast<off_t>(1000))) // set a lower limit for the maxFileSize
|
---|
16 | , m_lastFileNumber((std::max)(maxFiles - 1, 0))
|
---|
17 | , m_firstWrite(true)
|
---|
18 | {
|
---|
19 | util::splitFileName(fileName, m_fileNameNoExt, m_fileExt);
|
---|
20 | }
|
---|
21 |
|
---|
22 | #ifdef _WIN32
|
---|
23 | RollingFileAppender(const char* fileName, size_t maxFileSize = 0, int maxFiles = 0)
|
---|
24 | : m_fileSize()
|
---|
25 | , m_maxFileSize((std::max)(static_cast<off_t>(maxFileSize), static_cast<off_t>(1000))) // set a lower limit for the maxFileSize
|
---|
26 | , m_lastFileNumber((std::max)(maxFiles - 1, 0))
|
---|
27 | , m_firstWrite(true)
|
---|
28 | {
|
---|
29 | util::splitFileName(util::toWide(fileName).c_str(), m_fileNameNoExt, m_fileExt);
|
---|
30 | }
|
---|
31 | #endif
|
---|
32 |
|
---|
33 | virtual void write(const Record& record)
|
---|
34 | {
|
---|
35 | util::MutexLock lock(m_mutex);
|
---|
36 |
|
---|
37 | if (m_firstWrite)
|
---|
38 | {
|
---|
39 | openLogFile();
|
---|
40 | m_firstWrite = false;
|
---|
41 | }
|
---|
42 | else if (m_lastFileNumber > 0 && m_fileSize > m_maxFileSize && -1 != m_fileSize)
|
---|
43 | {
|
---|
44 | rollLogFiles();
|
---|
45 | }
|
---|
46 |
|
---|
47 | int bytesWritten = m_file.write(Converter::convert(Formatter::format(record)));
|
---|
48 |
|
---|
49 | if (bytesWritten > 0)
|
---|
50 | {
|
---|
51 | m_fileSize += bytesWritten;
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | private:
|
---|
56 | void rollLogFiles()
|
---|
57 | {
|
---|
58 | m_file.close();
|
---|
59 |
|
---|
60 | util::nstring lastFileName = buildFileName(m_lastFileNumber);
|
---|
61 | util::File::unlink(lastFileName.c_str());
|
---|
62 |
|
---|
63 | for (int fileNumber = m_lastFileNumber - 1; fileNumber >= 0; --fileNumber)
|
---|
64 | {
|
---|
65 | util::nstring currentFileName = buildFileName(fileNumber);
|
---|
66 | util::nstring nextFileName = buildFileName(fileNumber + 1);
|
---|
67 |
|
---|
68 | util::File::rename(currentFileName.c_str(), nextFileName.c_str());
|
---|
69 | }
|
---|
70 |
|
---|
71 | openLogFile();
|
---|
72 | }
|
---|
73 |
|
---|
74 | void openLogFile()
|
---|
75 | {
|
---|
76 | util::nstring fileName = buildFileName();
|
---|
77 | m_fileSize = m_file.open(fileName.c_str());
|
---|
78 |
|
---|
79 | if (0 == m_fileSize)
|
---|
80 | {
|
---|
81 | int bytesWritten = m_file.write(Converter::header(Formatter::header()));
|
---|
82 |
|
---|
83 | if (bytesWritten > 0)
|
---|
84 | {
|
---|
85 | m_fileSize += bytesWritten;
|
---|
86 | }
|
---|
87 | }
|
---|
88 | }
|
---|
89 |
|
---|
90 | util::nstring buildFileName(int fileNumber = 0)
|
---|
91 | {
|
---|
92 | util::nstringstream ss;
|
---|
93 | ss << m_fileNameNoExt;
|
---|
94 |
|
---|
95 | if (fileNumber > 0)
|
---|
96 | {
|
---|
97 | ss << '.' << fileNumber;
|
---|
98 | }
|
---|
99 |
|
---|
100 | if (!m_fileExt.empty())
|
---|
101 | {
|
---|
102 | ss << '.' << m_fileExt;
|
---|
103 | }
|
---|
104 |
|
---|
105 | return ss.str();
|
---|
106 | }
|
---|
107 |
|
---|
108 | private:
|
---|
109 | util::Mutex m_mutex;
|
---|
110 | util::File m_file;
|
---|
111 | off_t m_fileSize;
|
---|
112 | const off_t m_maxFileSize;
|
---|
113 | const int m_lastFileNumber;
|
---|
114 | util::nstring m_fileExt;
|
---|
115 | util::nstring m_fileNameNoExt;
|
---|
116 | bool m_firstWrite;
|
---|
117 | };
|
---|
118 | }
|
---|