DailyRollingFileAppender.cpp
Go to the documentation of this file.
1 /*
2  * DailyRollingFileAppender.cpp
3  *
4  * See the COPYING file for the terms of usage and distribution.
5  */
6 
7 #include "PortabilityImpl.hh"
8 #ifdef LOG4CPP_HAVE_IO_H
9 # include <io.h>
10 #endif
11 #ifdef LOG4CPP_HAVE_UNISTD_H
12 # include <unistd.h>
13 #endif
14 
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
19 #include <log4cpp/Category.hh>
20 #include <log4cpp/FactoryParams.hh>
21 #include <memory>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <iostream>
26 
27 #ifdef LOG4CPP_HAVE_SSTREAM
28 #include <sstream>
29 #include <iomanip>
30 #endif
31 
32 #ifndef WIN32 // only available on Win32
33 #include <dirent.h>
34 #endif
35 
36 namespace log4cpp {
37 
39 
41  const std::string& fileName,
42  unsigned int maxDaysToKeep,
43  bool append,
44  mode_t mode) :
45  FileAppender(name, fileName, append, mode),
46  _maxDaysToKeep(maxDaysToKeep != 0 ? maxDaysToKeep : maxDaysToKeepDefault) {
47  struct stat statBuf;
48  int res;
49  time_t t;
50 
51  // obtain last modification time
52  res = ::stat(fileName.c_str(), &statBuf);
53  if (res < 0) {
54  t = time(NULL);
55  } else {
56  t = statBuf.st_mtime;
57  }
58 #ifndef WIN32 // only available on Win32
59  localtime_r(&t, &_logsTime);
60 #else
61  localtime_s(&_logsTime, &t);
62 #endif
63  }
64 
65  void DailyRollingFileAppender::setMaxDaysToKeep(unsigned int maxDaysToKeep) {
66  _maxDaysToKeep = maxDaysToKeep;
67  }
68 
70  return _maxDaysToKeep;
71  }
72 
74  {
75  std::ostringstream filename_s;
76  ::close(_fd);
77  filename_s << _fileName << "." << _logsTime.tm_year + 1900 << "-"
78  << std::setfill('0') << std::setw(2) << _logsTime.tm_mon + 1 << "-"
79  << std::setw(2) << _logsTime.tm_mday << std::ends;
80  const std::string lastFn = filename_s.str();
81  ::rename(_fileName.c_str(), lastFn.c_str());
82 
83  _fd = ::open(_fileName.c_str(), _flags, _mode);
84 
85  const time_t oldest = time(NULL) - _maxDaysToKeep * 60 * 60 * 24;
86 
87 #ifndef WIN32
88 #define PATHDELIMITER "/"
89 #else
90 #define PATHDELIMITER "\\"
91 #endif
92  // iterate over files around log file and delete older with same prefix
93  const std::string::size_type last_delimiter = _fileName.rfind(PATHDELIMITER);
94  const std::string dirname((last_delimiter == std::string::npos)? "." : _fileName.substr(0, last_delimiter));
95  const std::string filname((last_delimiter == std::string::npos)? _fileName : _fileName.substr(last_delimiter+1, _fileName.size()-last_delimiter-1));
96 #ifndef WIN32 // only available on Win32
97  struct dirent **entries;
98  int nentries = scandir(dirname.c_str(), &entries, 0, alphasort);
99  if (nentries < 0)
100  return;
101  for (int i = 0; i < nentries; i++) {
102  struct stat statBuf;
103  int res = ::stat(entries[i]->d_name, &statBuf);
104  if ((res == -1) || (!S_ISREG(statBuf.st_mode))) {
105  free(entries[i]);
106  continue;
107  }
108  if (statBuf.st_mtime < oldest && strstr(entries[i]->d_name, filname.c_str())) {
109  const std::string fullfilename = dirname + PATHDELIMITER + entries[i]->d_name;
110  ::unlink(fullfilename.c_str());
111  std::cout << " Deleting " << fullfilename.c_str() << std::endl;
112  }
113  free(entries[i]);
114  }
115  free(entries);
116 #else
117  HANDLE hFind = INVALID_HANDLE_VALUE;
118  WIN32_FIND_DATA ffd;
119  const std::string pattern = _fileName + "*";
120 
121  hFind = FindFirstFile(pattern.c_str(), &ffd);
122  if (hFind != INVALID_HANDLE_VALUE) {
123  do {
124  struct stat statBuf;
125  const std::string fullfilename = dirname + PATHDELIMITER + ffd.cFileName;
126  int res = ::stat(fullfilename.c_str(), &statBuf);
127  if (res != -1 && statBuf.st_mtime < oldest && !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
128  std::cout << "Deleting " << fullfilename << "\n";
129  ::unlink(fullfilename.c_str());
130  }
131  } while (FindNextFile(hFind, &ffd) != 0);
132 
133  if (GetLastError() != ERROR_NO_MORE_FILES) {
134  // [XXX] some kind of error happened
135  }
136  FindClose(hFind);
137  hFind = INVALID_HANDLE_VALUE;
138  }
139 #endif
140  }
141 
143  {
144  struct tm now;
145  time_t t = time(NULL);
146 
147 #ifndef WIN32 // only available on Win32
148  bool timeok = localtime_r(&t, &now) != NULL;
149 #else
150  bool timeok = localtime_s(&now, &t) == 0;
151 #endif
152  if (timeok) {
153  if ((now.tm_mday != _logsTime.tm_mday) ||
154  (now.tm_mon != _logsTime.tm_mon) ||
155  (now.tm_year != _logsTime.tm_year)) {
156  rollOver();
157  _logsTime = now;
158  }
159  }
161  }
162 
163  std::auto_ptr<Appender> create_daily_roll_file_appender(const FactoryParams& params)
164  {
165  std::string name, filename;
166  bool append = true;
167  mode_t mode = 664;
168  unsigned int max_days_keep = 0;
169  params.get_for("daily roll file appender").required("name", name)("filename", filename)("max_days_keep", max_days_keep)
170  .optional("append", append)("mode", mode);
171 
172  return std::auto_ptr<Appender>(new DailyRollingFileAppender(name, filename, max_days_keep, append, mode));
173  }
174 }
virtual unsigned int getMaxDaysToKeep() const
const std::string _fileName
Definition: FileAppender.hh:85
virtual void _append(const LoggingEvent &event)
virtual void setMaxDaysToKeep(unsigned int maxDaysToKeep)
required_params_validator required(const char *param, T &value) const
DailyRollingFileAppender(const std::string &name, const std::string &fileName, unsigned int maxDaysToKeep=maxDaysToKeepDefault, bool append=true, mode_t mode=00644)
virtual void _append(const LoggingEvent &event)
virtual void close()
int mode_t
Definition: config-win32.h:159
details::parameter_validator get_for(const char *tag) const
#define PATHDELIMITER
optional_params_validator optional(const char *param, T &value) const
std::auto_ptr< Appender > create_daily_roll_file_appender(const FactoryParams &)


log4cpp
Author(s): Stephen Roderick, Bastiaan Bakker, Cedric Le Goater, Steve Ostlind, Marcel Harkema, Walter Stroebel, Glenn Scott and Tony Cheung
autogenerated on Sun Jun 23 2019 19:10:00