1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 
19 #if !defined(_LOG4CXX_ROLLING_TIME_BASED_ROLLING_POLICY_H)
20 #define _LOG4CXX_ROLLING_TIME_BASED_ROLLING_POLICY_H
21 
22 #include <log4cxx/portability.h>
23 #include <log4cxx/rolling/rollingpolicybase.h>
24 #include <log4cxx/rolling/triggeringpolicy.h>
25 #include <log4cxx/writerappender.h>
26 #include <log4cxx/helpers/outputstream.h>
27 #include <apr_mmap.h>
28 
29 #if defined(_MSC_VER)
30 	#pragma warning ( push )
31 	#pragma warning ( disable: 4251 )
32 #endif
33 
34 namespace log4cxx
35 {
36 
37 namespace rolling
38 {
39 
40 
41 
42 /**
43  * <code>TimeBasedRollingPolicy</code> is both easy to configure and quite
44  * powerful.
45  *
46  * <p>In order to use  <code>TimeBasedRollingPolicy</code>, the
47  * <b>FileNamePattern</b> option must be set. It basically specifies the name of the
48  * rolled log files. The value <code>FileNamePattern</code> should consist of
49  * the name of the file, plus a suitably placed <code>%d</code> conversion
50  * specifier. The <code>%d</code> conversion specifier may contain a date and
51  * time pattern as specified by the {@link log4cxx::helpers::SimpleDateFormat} class. If
52  * the date and time pattern is ommitted, then the default pattern of
53  * "yyyy-MM-dd" is assumed. The following examples should clarify the point.
54  *
55  * <p>
56  * <table cellspacing="5px" border="1">
57  *   <tr>
58  *     <th><code>FileNamePattern</code> value</th>
59  *     <th>Rollover schedule</th>
60  *     <th>Example</th>
61  *   </tr>
62  *   <tr>
63  *     <td nowrap="true"><code>/wombat/folder/foo.%d</code></td>
64  *     <td>Daily rollover (at midnight).  Due to the omission of the optional
65  *         time and date pattern for the %d token specifier, the default pattern
66  *         of "yyyy-MM-dd" is assumed, which corresponds to daily rollover.
67  *     </td>
68  *     <td>During November 23rd, 2004, logging output will go to
69  *       the file <code>/wombat/foo.2004-11-23</code>. At midnight and for
70  *       the rest of the 24th, logging output will be directed to
71  *       <code>/wombat/foo.2004-11-24</code>.
72  *     </td>
73  *   </tr>
74  *   <tr>
75  *     <td nowrap="true"><code>/wombat/foo.%d{yyyy-MM}.log</code></td>
76  *     <td>Rollover at the beginning of each month.</td>
77  *     <td>During the month of October 2004, logging output will go to
78  *     <code>/wombat/foo.2004-10.log</code>. After midnight of October 31st
79  *     and for the rest of November, logging output will be directed to
80  *       <code>/wombat/foo.2004-11.log</code>.
81  *     </td>
82  *   </tr>
83  * </table>
84  * <h2>Automatic file compression</h2>
85  * <code>TimeBasedRollingPolicy</code> supports automatic file compression.
86  * This feature is enabled if the value of the <b>FileNamePattern</b> option
87  * ends with <code>.gz</code> or <code>.zip</code>.
88  * <p>
89  * <table cellspacing="5px" border="1">
90  *   <tr>
91  *     <th><code>FileNamePattern</code> value</th>
92  *     <th>Rollover schedule</th>
93  *     <th>Example</th>
94  *   </tr>
95  *   <tr>
96  *     <td nowrap="true"><code>/wombat/foo.%d.gz</code></td>
97  *     <td>Daily rollover (at midnight) with automatic GZIP compression of the
98  *      arcived files.</td>
99  *     <td>During November 23rd, 2004, logging output will go to
100  *       the file <code>/wombat/foo.2004-11-23</code>. However, at midnight that
101  *       file will be compressed to become <code>/wombat/foo.2004-11-23.gz</code>.
102  *       For the 24th of November, logging output will be directed to
103  *       <code>/wombat/folder/foo.2004-11-24</code> until its rolled over at the
104  *       beginning of the next day.
105  *     </td>
106  *   </tr>
107  * </table>
108  *
109  * <h2>Decoupling the location of the active log file and the archived log files</h2>
110  * <p>The <em>active file</em> is defined as the log file for the current period
111  * whereas <em>archived files</em> are thos files which have been rolled over
112  * in previous periods.
113  *
114  * <p>By setting the <b>ActiveFileName</b> option you can decouple the location
115  * of the active log file and the location of the archived log files.
116  * <p>
117  *  <table cellspacing="5px" border="1">
118  *   <tr>
119  *     <th><code>FileNamePattern</code> value</th>
120  *     <th>ActiveFileName</th>
121  *     <th>Rollover schedule</th>
122  *     <th>Example</th>
123  *   </tr>
124  *   <tr>
125  *     <td nowrap="true"><code>/wombat/foo.log.%d</code></td>
126  *     <td nowrap="true"><code>/wombat/foo.log</code></td>
127  *     <td>Daily rollover.</td>
128  *
129  *     <td>During November 23rd, 2004, logging output will go to
130  *       the file <code>/wombat/foo.log</code>. However, at midnight that file
131  *       will archived as <code>/wombat/foo.log.2004-11-23</code>. For the 24th
132  *       of November, logging output will be directed to
133  *       <code>/wombat/folder/foo.log</code> until its archived as
134  *       <code>/wombat/foo.log.2004-11-24</code> at the beginning of the next
135  *       day.
136  *     </td>
137  *   </tr>
138  * </table>
139  * <p>
140  * If configuring programatically, do not forget to call {@link #activateOptions}
141  * method before using this policy. Moreover, {@link #activateOptions} of
142  * <code> TimeBasedRollingPolicy</code> must be called <em>before</em> calling
143  * the {@link #activateOptions} method of the owning
144  * <code>RollingFileAppender</code>.
145  */
146 class LOG4CXX_EXPORT TimeBasedRollingPolicy : public RollingPolicyBase,
147 	public TriggeringPolicy
148 {
149 		DECLARE_LOG4CXX_OBJECT(TimeBasedRollingPolicy)
150 		BEGIN_LOG4CXX_CAST_MAP()
151 		LOG4CXX_CAST_ENTRY(TimeBasedRollingPolicy)
152 		LOG4CXX_CAST_ENTRY_CHAIN(RollingPolicyBase)
153 		LOG4CXX_CAST_ENTRY_CHAIN(TriggeringPolicy)
154 		END_LOG4CXX_CAST_MAP()
155 
156 	private:
157 		/**
158 		 * Time for next determination if time for rollover.
159 		 */
160 		log4cxx_time_t nextCheck;
161 
162 		/**
163 		 * File name at last rollover.
164 		 */
165 		LogString lastFileName;
166 
167 		/**
168 		 * mmap pointer
169 		 */
170 		apr_mmap_t* _mmap;
171 
172 		/*
173 		 * pool for mmap handler
174 		 * */
175 		log4cxx::helpers::Pool* _mmapPool;
176 
177 		/**
178 		 * mmap file descriptor
179 		 */
180 		apr_file_t* _file_map;
181 
182 		/**
183 		 * mmap file name
184 		 */
185 		std::string _mapFileName;
186 
187 		/*
188 		 * lock file handle
189 		 * */
190 		apr_file_t* _lock_file;
191 
192 		/**
193 		 * Check nextCheck if it has already been set
194 		 * Timebased rolling policy has an issue when working at low rps.
195 		 * Under low rps, multiple processes will not be scheduled in time for the second chance(do rolling),
196 		 * so the rolling mechanism will not be triggered even if the time period is out of date.
197 		 * This results in log entries will be accumulated for serveral minutes to be rolling.
198 		 * Adding this flag to provide rolling opportunity for a process even if it is writing the first log entry
199 		 */
200 		bool bAlreadyInitialized;
201 
202 		/*
203 		 * If the current file name contains date information, retrieve the current writting file from mmap
204 		 * */
205 		bool bRefreshCurFile;
206 
207 		/*
208 		 * mmap file name
209 		 * */
210 		LogString _fileNamePattern;
211 
212 		/**
213 		 * Length of any file type suffix (.gz, .zip).
214 		 */
215 		int suffixLength;
216 
217 	public:
218 		TimeBasedRollingPolicy();
219 		void addRef() const;
220 		void releaseRef() const;
221 		void activateOptions(log4cxx::helpers::Pool& );
222 
223 #ifdef LOG4CXX_MULTI_PROCESS
224 		virtual ~TimeBasedRollingPolicy();
225 
226 		/**
227 		 * Generate mmap file
228 		 */
229 		int createMMapFile(const std::string& lastfilename, log4cxx::helpers::Pool& pool);
230 
231 		/**
232 		 *  Detect if the mmap file is empty
233 		 */
234 		bool isMapFileEmpty(log4cxx::helpers::Pool& pool);
235 
236 		/**
237 		 *   init MMapFile
238 		 */
239 		void initMMapFile(const LogString& lastFileName, log4cxx::helpers::Pool& pool);
240 
241 		/**
242 		 *   lock MMapFile
243 		 */
244 		int lockMMapFile(int type);
245 
246 		/**
247 		 *   unlock MMapFile
248 		 */
249 		int unLockMMapFile();
250 
251 		/**
252 		 *   create MMapFile/lockFile
253 		 */
254 		const std::string createFile(const std::string& filename, const std::string& suffix, log4cxx::helpers::Pool& pool);
255 #endif
256 
257 		/**
258 		 * {@inheritDoc}
259 		 */
260 		RolloverDescriptionPtr initialize(
261 			const   LogString&              currentActiveFile,
262 			const   bool                    append,
263 			log4cxx::helpers::Pool& pool);
264 
265 		/**
266 		 * {@inheritDoc}
267 		 */
268 		RolloverDescriptionPtr rollover(
269 			const   LogString&              currentActiveFile,
270 			const   bool                    append,
271 			log4cxx::helpers::Pool& pool);
272 
273 		/**
274 		 * Determines if a rollover may be appropriate at this time.  If
275 		 * true is returned, RolloverPolicy.rollover will be called but it
276 		 * can determine that a rollover is not warranted.
277 		 *
278 		 * @param appender A reference to the appender.
279 		 * @param event A reference to the currently event.
280 		 * @param filename The filename for the currently active log file.
281 		 * @param fileLength Length of the file in bytes.
282 		 * @return true if a rollover should occur.
283 		 */
284 		virtual bool isTriggeringEvent(
285 			Appender* appender,
286 			const log4cxx::spi::LoggingEventPtr& event,
287 			const LogString& filename,
288 			size_t fileLength);
289 
290 	protected:
291 		log4cxx::pattern::PatternMap getFormatSpecifiers() const;
292 
293 };
294 
295 LOG4CXX_PTR_DEF(TimeBasedRollingPolicy);
296 
297 }
298 }
299 
300 #if defined(_MSC_VER)
301 	#pragma warning ( pop )
302 #endif
303 
304 #endif
305 
306