/src/logging-log4cxx/src/main/cpp/timebasedrollingpolicy.cpp
Line | Count | Source |
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 | | #define NOMINMAX /* tell windows to not define min/max macros */ |
18 | | #include <log4cxx/log4cxx.h> |
19 | | #include <log4cxx/logstring.h> |
20 | | #include <log4cxx/rolling/timebasedrollingpolicy.h> |
21 | | #include <log4cxx/pattern/filedatepatternconverter.h> |
22 | | #include <log4cxx/helpers/date.h> |
23 | | #include <log4cxx/rolling/filerenameaction.h> |
24 | | #include <log4cxx/helpers/loglog.h> |
25 | | #include <log4cxx/helpers/exception.h> |
26 | | #include <log4cxx/rolling/gzcompressaction.h> |
27 | | #include <log4cxx/rolling/zipcompressaction.h> |
28 | | #include <log4cxx/helpers/stringhelper.h> |
29 | | #include <log4cxx/helpers/optionconverter.h> |
30 | | #include <log4cxx/helpers/transcoder.h> |
31 | | #include <log4cxx/fileappender.h> |
32 | | #include <algorithm> |
33 | | #include <iostream> |
34 | | #include <apr_mmap.h> |
35 | | |
36 | | using namespace LOG4CXX_NS; |
37 | | using namespace LOG4CXX_NS::rolling; |
38 | | using namespace LOG4CXX_NS::helpers; |
39 | | using namespace LOG4CXX_NS::pattern; |
40 | | |
41 | | IMPLEMENT_LOG4CXX_OBJECT(TimeBasedRollingPolicy) |
42 | | |
43 | | struct TimeBasedRollingPolicy::TimeBasedRollingPolicyPrivate{ |
44 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
45 | | TimeBasedRollingPolicyPrivate() : |
46 | | _mmap(nullptr), |
47 | | _file_map(nullptr), |
48 | | _lock_file(nullptr), |
49 | | bAlreadyInitialized(false), |
50 | | bRefreshCurFile(false){} |
51 | | #else |
52 | 0 | TimeBasedRollingPolicyPrivate(){} |
53 | | #endif |
54 | | |
55 | | /** |
56 | | * Time for next determination if time for rollover. |
57 | | */ |
58 | | log4cxx_time_t nextCheck{0}; |
59 | | |
60 | | /** |
61 | | * File name at last rollover. |
62 | | */ |
63 | | LogString lastFileName; |
64 | | |
65 | | /** |
66 | | * Length of any file type suffix (.gz, .zip). |
67 | | */ |
68 | | int suffixLength{0}; |
69 | | |
70 | | /** |
71 | | * mmap pointer |
72 | | */ |
73 | | apr_mmap_t* _mmap; |
74 | | |
75 | | /* |
76 | | * pool for mmap handler |
77 | | * */ |
78 | | LOG4CXX_NS::helpers::Pool _mmapPool; |
79 | | |
80 | | /** |
81 | | * mmap file descriptor |
82 | | */ |
83 | | apr_file_t* _file_map; |
84 | | |
85 | | /** |
86 | | * mmap file name |
87 | | */ |
88 | | std::string _mapFileName; |
89 | | |
90 | | /* |
91 | | * lock file handle |
92 | | * */ |
93 | | apr_file_t* _lock_file; |
94 | | |
95 | | /** |
96 | | * Check nextCheck if it has already been set |
97 | | * Timebased rolling policy has an issue when working at low rps. |
98 | | * Under low rps, multiple processes will not be scheduled in time for the second chance(do rolling), |
99 | | * so the rolling mechanism will not be triggered even if the time period is out of date. |
100 | | * This results in log entries will be accumulated for serveral minutes to be rolling. |
101 | | * Adding this flag to provide rolling opportunity for a process even if it is writing the first log entry |
102 | | */ |
103 | | bool bAlreadyInitialized; |
104 | | |
105 | | /* |
106 | | * If the current file name contains date information, retrieve the current writting file from mmap |
107 | | * */ |
108 | | bool bRefreshCurFile; |
109 | | |
110 | | /* |
111 | | * mmap file name |
112 | | * */ |
113 | | LogString _fileNamePattern; |
114 | | |
115 | | bool multiprocess = false; |
116 | | bool throwIOExceptionOnForkFailure = true; |
117 | | }; |
118 | | |
119 | | |
120 | | #define MMAP_FILE_SUFFIX ".map" |
121 | | #define LOCK_FILE_SUFFIX ".maplck" |
122 | | #define MAX_FILE_LEN 2048 |
123 | | |
124 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
125 | | namespace |
126 | | { |
127 | | LogString readMappedFileName(apr_mmap_t* mmap) |
128 | | { |
129 | | if (!mmap || !mmap->mm) |
130 | | { |
131 | | return LogString(); |
132 | | } |
133 | | |
134 | | const auto* first = static_cast<const logchar*>(mmap->mm); |
135 | | const auto* last = first + (MAX_FILE_LEN / sizeof(logchar)); |
136 | | const auto* terminator = std::find(first, last, logchar(0)); |
137 | | |
138 | | if (terminator == last) |
139 | | { |
140 | | LogLog::warn(LOG4CXX_STR("Ignoring invalid multiprocess rolling map file: missing string terminator")); |
141 | | return LogString(); |
142 | | } |
143 | | |
144 | | return LogString(first, terminator); |
145 | | } |
146 | | } |
147 | | |
148 | | bool TimeBasedRollingPolicy::isMapFileEmpty(LOG4CXX_NS::helpers::Pool& pool) |
149 | | { |
150 | | apr_finfo_t finfo; |
151 | | apr_status_t st = apr_stat(&finfo, m_priv->_mapFileName.c_str(), APR_FINFO_SIZE, pool.getAPRPool()); |
152 | | |
153 | | if (st != APR_SUCCESS) |
154 | | { |
155 | | LogLog::warn(helpers::Exception::makeMessage(LOG4CXX_STR("apr_stat"), st)); |
156 | | } |
157 | | |
158 | | if (st == APR_SUCCESS && (0 == finfo.size || |
159 | | (m_priv->_mmap && 0 == *static_cast<logchar*>(m_priv->_mmap->mm)))) |
160 | | { |
161 | | return true; |
162 | | } |
163 | | |
164 | | return false; |
165 | | } |
166 | | |
167 | | void TimeBasedRollingPolicy::initMMapFile(const LogString& lastFileName, LOG4CXX_NS::helpers::Pool& pool) |
168 | | { |
169 | | int iRet = 0; |
170 | | |
171 | | if (!m_priv->_mmap) |
172 | | { |
173 | | LOG4CXX_ENCODE_CHAR(mapFile, m_priv->_fileNamePattern); |
174 | | iRet = createMMapFile(mapFile, pool); |
175 | | } |
176 | | |
177 | | if (!iRet && isMapFileEmpty(pool)) |
178 | | { |
179 | | lockMMapFile(APR_FLOCK_EXCLUSIVE); |
180 | | memset(m_priv->_mmap->mm, 0, MAX_FILE_LEN); |
181 | | size_t byteCount = sizeof (logchar) * lastFileName.size(); |
182 | | if (byteCount <= MAX_FILE_LEN - sizeof (logchar)) |
183 | | memcpy(m_priv->_mmap->mm, lastFileName.c_str(), byteCount); |
184 | | unLockMMapFile(); |
185 | | } |
186 | | } |
187 | | |
188 | | const std::string TimeBasedRollingPolicy::createFile(const std::string& fileName, const std::string& suffix, LOG4CXX_NS::helpers::Pool& pool) |
189 | | { |
190 | | char szUid[MAX_FILE_LEN] = "0000"; |
191 | | #ifndef _WIN32 // The uid provided by the Windows version of apr_uid_current is not a constant value |
192 | | apr_uid_t uid; |
193 | | apr_gid_t groupid; |
194 | | if (APR_SUCCESS == apr_uid_current(&uid, &groupid, pool.getAPRPool())) |
195 | | snprintf(szUid, MAX_FILE_LEN, "%u", uid); |
196 | | #endif |
197 | | return fileName + szUid + suffix; |
198 | | } |
199 | | |
200 | | int TimeBasedRollingPolicy::createMMapFile(const std::string& fileName, LOG4CXX_NS::helpers::Pool& pool) |
201 | | { |
202 | | m_priv->_mapFileName = createFile(fileName, MMAP_FILE_SUFFIX, pool); |
203 | | |
204 | | apr_status_t stat = apr_file_open(&m_priv->_file_map, m_priv->_mapFileName.c_str(), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, m_priv->_mmapPool.getAPRPool()); |
205 | | |
206 | | if (stat != APR_SUCCESS) |
207 | | { |
208 | | LogString msg = helpers::Exception::makeMessage(LOG4CXX_STR("apr_file_open"), stat); |
209 | | msg += LOG4CXX_STR(". Check the privilege or try to remove ["); |
210 | | helpers::Transcoder::decode(m_priv->_mapFileName, msg); |
211 | | msg += LOG4CXX_STR("] if it exists."); |
212 | | LogLog::warn(msg); |
213 | | return -1; |
214 | | } |
215 | | |
216 | | if (isMapFileEmpty(pool)) |
217 | | { |
218 | | stat = apr_file_trunc(m_priv->_file_map, MAX_FILE_LEN + 1); |
219 | | |
220 | | if (stat != APR_SUCCESS) |
221 | | { |
222 | | LogLog::warn(helpers::Exception::makeMessage(LOG4CXX_STR("apr_file_trunc"), stat)); |
223 | | apr_file_close(m_priv->_file_map); |
224 | | return -1; |
225 | | } |
226 | | } |
227 | | |
228 | | stat = apr_mmap_create(&m_priv->_mmap, m_priv->_file_map, 0, MAX_FILE_LEN, APR_MMAP_WRITE | APR_MMAP_READ, m_priv->_mmapPool.getAPRPool()); |
229 | | |
230 | | if (stat != APR_SUCCESS) |
231 | | { |
232 | | LogLog::warn(helpers::Exception::makeMessage(LOG4CXX_STR("apr_mmap_create"), stat)); |
233 | | apr_file_close(m_priv->_file_map); |
234 | | return -1; |
235 | | } |
236 | | |
237 | | return 0; |
238 | | } |
239 | | |
240 | | int TimeBasedRollingPolicy::lockMMapFile(int type) |
241 | | { |
242 | | apr_status_t stat = apr_file_lock(m_priv->_lock_file, type); |
243 | | |
244 | | if (stat != APR_SUCCESS) |
245 | | { |
246 | | LogLog::warn(helpers::Exception::makeMessage(LOG4CXX_STR("apr_file_lock for mmap"), stat)); |
247 | | } |
248 | | |
249 | | return stat; |
250 | | } |
251 | | |
252 | | int TimeBasedRollingPolicy::unLockMMapFile() |
253 | | { |
254 | | apr_status_t stat = apr_file_unlock(m_priv->_lock_file); |
255 | | |
256 | | if (stat != APR_SUCCESS) |
257 | | { |
258 | | LogLog::warn(helpers::Exception::makeMessage(LOG4CXX_STR("apr_file_unlock for mmap"), stat)); |
259 | | } |
260 | | |
261 | | return stat; |
262 | | } |
263 | | #else |
264 | 0 | int TimeBasedRollingPolicy::createMMapFile(const std::string&, LOG4CXX_NS::helpers::Pool&) { |
265 | 0 | return 0; |
266 | 0 | } |
267 | | |
268 | 0 | bool TimeBasedRollingPolicy::isMapFileEmpty(LOG4CXX_NS::helpers::Pool&){ |
269 | 0 | return true; |
270 | 0 | } |
271 | | |
272 | 0 | void TimeBasedRollingPolicy::initMMapFile(const LogString&, LOG4CXX_NS::helpers::Pool&){} |
273 | | |
274 | 0 | int TimeBasedRollingPolicy::lockMMapFile(int){ |
275 | 0 | return 0; |
276 | 0 | } |
277 | | |
278 | 0 | int TimeBasedRollingPolicy::unLockMMapFile(){ |
279 | 0 | return 0; |
280 | 0 | } |
281 | | |
282 | 0 | const std::string TimeBasedRollingPolicy::createFile(const std::string&, const std::string&, LOG4CXX_NS::helpers::Pool&){ |
283 | 0 | return ""; |
284 | 0 | } |
285 | | #endif |
286 | | |
287 | | TimeBasedRollingPolicy::TimeBasedRollingPolicy() : |
288 | 0 | m_priv(std::make_unique<TimeBasedRollingPolicyPrivate>()) |
289 | 0 | { |
290 | 0 | } Unexecuted instantiation: log4cxx::rolling::TimeBasedRollingPolicy::TimeBasedRollingPolicy() Unexecuted instantiation: log4cxx::rolling::TimeBasedRollingPolicy::TimeBasedRollingPolicy() |
291 | | |
292 | 0 | TimeBasedRollingPolicy::~TimeBasedRollingPolicy(){} |
293 | | |
294 | | void TimeBasedRollingPolicy::activateOptions( LOG4CXX_ACTIVATE_OPTIONS_FORMAL_PARAMETERS ) |
295 | 0 | { |
296 | | // find out period from the filename pattern |
297 | 0 | if (getFileNamePattern().length() > 0) |
298 | 0 | { |
299 | 0 | parseFileNamePattern(); |
300 | 0 | } |
301 | 0 | else |
302 | 0 | { |
303 | 0 | LogLog::warn( |
304 | 0 | LOG4CXX_STR("The FileNamePattern option must be set before using TimeBasedRollingPolicy. ")); |
305 | 0 | throw IllegalStateException(); |
306 | 0 | } |
307 | | |
308 | 0 | PatternConverterPtr dtc(getDatePatternConverter()); |
309 | |
|
310 | 0 | if (dtc == NULL) |
311 | 0 | { |
312 | 0 | throw NullPointerException(LOG4CXX_STR("DatePatternConverter")); |
313 | 0 | } |
314 | | |
315 | 0 | Pool pool; |
316 | 0 | LogString buf; |
317 | 0 | ObjectPtr obj = std::make_shared<Date>(); |
318 | 0 | formatFileName(obj, buf); |
319 | 0 | m_priv->lastFileName = buf; |
320 | |
|
321 | 0 | m_priv->suffixLength = 0; |
322 | |
|
323 | 0 | if (m_priv->lastFileName.length() >= 3) |
324 | 0 | { |
325 | 0 | if (m_priv->lastFileName.compare(m_priv->lastFileName.length() - 3, 3, LOG4CXX_STR(".gz")) == 0) |
326 | 0 | { |
327 | 0 | m_priv->suffixLength = 3; |
328 | 0 | } |
329 | 0 | else if (m_priv->lastFileName.length() >= 4 && m_priv->lastFileName.compare(m_priv->lastFileName.length() - 4, 4, LOG4CXX_STR(".zip")) == 0) |
330 | 0 | { |
331 | 0 | m_priv->suffixLength = 4; |
332 | 0 | } |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | | |
337 | | #define RULES_PUT(spec, cls) \ |
338 | 0 | specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), (PatternConstructor) cls ::newInstance)) |
339 | | |
340 | | LOG4CXX_NS::pattern::PatternMap TimeBasedRollingPolicy::getFormatSpecifiers() const |
341 | 0 | { |
342 | 0 | PatternMap specs; |
343 | 0 | RULES_PUT("d", FileDatePatternConverter); |
344 | 0 | RULES_PUT("date", FileDatePatternConverter); |
345 | 0 | return specs; |
346 | 0 | } |
347 | | |
348 | | /** |
349 | | * {@inheritDoc} |
350 | | */ |
351 | | RolloverDescriptionPtr TimeBasedRollingPolicy::initialize( LOG4CXX_ROLLING_POLICY_INITIALIZE_FORMAL_PARAMETERS ) |
352 | 0 | { |
353 | 0 | Date now; |
354 | 0 | log4cxx_time_t n = now.getTime(); |
355 | 0 | m_priv->nextCheck = now.getNextSecond(); |
356 | |
|
357 | 0 | File currentFile(currentActiveFile); |
358 | |
|
359 | 0 | LogString buf; |
360 | 0 | ObjectPtr obj = std::make_shared<Date>(currentFile.exists() ? currentFile.lastModified() : n); |
361 | 0 | formatFileName(obj, buf); |
362 | 0 | m_priv->lastFileName = buf; |
363 | |
|
364 | 0 | ActionPtr noAction; |
365 | |
|
366 | 0 | if (currentActiveFile.length() > 0) |
367 | 0 | { |
368 | 0 | return std::make_shared<RolloverDescription>( |
369 | 0 | currentActiveFile, append, noAction, noAction); |
370 | 0 | } |
371 | 0 | else |
372 | 0 | { |
373 | 0 | m_priv->bRefreshCurFile = true; |
374 | 0 | return std::make_shared<RolloverDescription>( |
375 | 0 | m_priv->lastFileName.substr(0, m_priv->lastFileName.length() - m_priv->suffixLength), append, |
376 | 0 | noAction, noAction); |
377 | 0 | } |
378 | 0 | } |
379 | | |
380 | | RolloverDescriptionPtr TimeBasedRollingPolicy::rollover( LOG4CXX_ROLLING_POLICY_ROLLOVER_FORMAL_PARAMETERS ) |
381 | 0 | { |
382 | 0 | Date now; |
383 | 0 | log4cxx_time_t n = now.getTime(); |
384 | 0 | m_priv->nextCheck = now.getNextSecond(); |
385 | |
|
386 | 0 | LogString buf; |
387 | 0 | ObjectPtr obj = std::make_shared<Date>(n); |
388 | 0 | formatFileName(obj, buf); |
389 | |
|
390 | 0 | LogString newFileName(buf); |
391 | |
|
392 | 0 | if( m_priv->multiprocess ){ |
393 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
394 | | |
395 | | if (!m_priv->bAlreadyInitialized) |
396 | | { |
397 | | if (getPatternConverterList().size()) |
398 | | { |
399 | | (*(getPatternConverterList().begin()))->format(obj, m_priv->_fileNamePattern); |
400 | | } |
401 | | else |
402 | | { |
403 | | m_priv->_fileNamePattern = m_priv->lastFileName; |
404 | | } |
405 | | |
406 | | if (!m_priv->_lock_file) |
407 | | { |
408 | | LOG4CXX_ENCODE_CHAR(mapFile, m_priv->_fileNamePattern); |
409 | | const std::string lockname = createFile(mapFile, LOCK_FILE_SUFFIX, m_priv->_mmapPool); |
410 | | apr_status_t stat = apr_file_open(&m_priv->_lock_file, lockname.c_str(), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, m_priv->_mmapPool.getAPRPool()); |
411 | | |
412 | | if (stat != APR_SUCCESS) |
413 | | { |
414 | | LOG4CXX_DECODE_CHAR(msg, lockname); |
415 | | msg += LOG4CXX_STR(": apr_file_open"); |
416 | | LogLog::warn(helpers::Exception::makeMessage(msg, stat)); |
417 | | } |
418 | | } |
419 | | |
420 | | initMMapFile(m_priv->lastFileName, m_priv->_mmapPool); |
421 | | } |
422 | | m_priv->bAlreadyInitialized = true; |
423 | | |
424 | | if (m_priv->_mmap && !isMapFileEmpty(m_priv->_mmapPool)) |
425 | | { |
426 | | lockMMapFile(APR_FLOCK_SHARED); |
427 | | LogString mapLastFile(readMappedFileName(m_priv->_mmap)); |
428 | | unLockMMapFile(); |
429 | | if (!mapLastFile.empty()) |
430 | | m_priv->lastFileName = mapLastFile; |
431 | | } |
432 | | else |
433 | | { |
434 | | m_priv->_mmap = NULL; |
435 | | initMMapFile(m_priv->lastFileName, m_priv->_mmapPool); |
436 | | } |
437 | | #endif |
438 | 0 | } |
439 | | |
440 | | // |
441 | | // if file names haven't changed, no rollover |
442 | | // |
443 | 0 | if (newFileName == m_priv->lastFileName) |
444 | 0 | { |
445 | 0 | RolloverDescriptionPtr desc; |
446 | 0 | return desc; |
447 | 0 | } |
448 | | |
449 | 0 | ActionPtr renameAction; |
450 | 0 | ActionPtr compressAction; |
451 | 0 | LogString lastBaseName( |
452 | 0 | m_priv->lastFileName.substr(0, m_priv->lastFileName.length() - m_priv->suffixLength)); |
453 | 0 | LogString nextActiveFile( |
454 | 0 | newFileName.substr(0, newFileName.length() - m_priv->suffixLength)); |
455 | |
|
456 | 0 | if(getCreateIntermediateDirectories()){ |
457 | 0 | File compressedFile(m_priv->lastFileName); |
458 | 0 | File compressedParent (compressedFile.getParent()); |
459 | 0 | compressedParent.mkdirs(); |
460 | 0 | } |
461 | | |
462 | | // |
463 | | // if currentActiveFile is not lastBaseName then |
464 | | // active file name is not following file pattern |
465 | | // and requires a rename plus maintaining the same name |
466 | 0 | if (currentActiveFile != lastBaseName) |
467 | 0 | { |
468 | 0 | renameAction = std::make_shared<FileRenameAction>( |
469 | 0 | File().setPath(currentActiveFile), File().setPath(lastBaseName), true); |
470 | 0 | nextActiveFile = currentActiveFile; |
471 | 0 | } |
472 | |
|
473 | 0 | if (m_priv->suffixLength == 3) |
474 | 0 | { |
475 | 0 | GZCompressActionPtr comp = std::make_shared<GZCompressAction>( |
476 | 0 | File().setPath(lastBaseName), File().setPath(m_priv->lastFileName), true); |
477 | 0 | comp->setThrowIOExceptionOnForkFailure(m_priv->throwIOExceptionOnForkFailure); |
478 | 0 | compressAction = comp; |
479 | 0 | } |
480 | |
|
481 | 0 | if (m_priv->suffixLength == 4) |
482 | 0 | { |
483 | 0 | ZipCompressActionPtr comp = std::make_shared<ZipCompressAction>( |
484 | 0 | File().setPath(lastBaseName), File().setPath(m_priv->lastFileName), true); |
485 | 0 | comp->setThrowIOExceptionOnForkFailure(m_priv->throwIOExceptionOnForkFailure); |
486 | 0 | compressAction = comp; |
487 | 0 | } |
488 | |
|
489 | 0 | if( m_priv->multiprocess ){ |
490 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
491 | | size_t byteCount = sizeof (logchar) * newFileName.size(); |
492 | | if (MAX_FILE_LEN - sizeof (logchar) < byteCount) |
493 | | { |
494 | | LogString msg(newFileName + LOG4CXX_STR(": cannot exceed ")); |
495 | | StringHelper::toString(MAX_FILE_LEN / sizeof (logchar), msg); |
496 | | msg += LOG4CXX_STR(" characters"); |
497 | | throw IllegalArgumentException(msg); |
498 | | } |
499 | | if (m_priv->_mmap && !isMapFileEmpty(m_priv->_mmapPool)) |
500 | | { |
501 | | lockMMapFile(APR_FLOCK_EXCLUSIVE); |
502 | | memset(m_priv->_mmap->mm, 0, MAX_FILE_LEN); |
503 | | memcpy(m_priv->_mmap->mm, newFileName.c_str(), byteCount); |
504 | | unLockMMapFile(); |
505 | | } |
506 | | else |
507 | | { |
508 | | m_priv->_mmap = NULL; |
509 | | initMMapFile(newFileName, m_priv->_mmapPool); |
510 | | } |
511 | | #endif |
512 | 0 | }else{ |
513 | 0 | m_priv->lastFileName = newFileName; |
514 | 0 | } |
515 | |
|
516 | 0 | return std::make_shared<RolloverDescription>(nextActiveFile, append, renameAction, compressAction); |
517 | 0 | } |
518 | | |
519 | | bool TimeBasedRollingPolicy::isTriggeringEvent( |
520 | | Appender* appender, |
521 | | const LOG4CXX_NS::spi::LoggingEventPtr& /* event */, |
522 | | const LogString& filename, |
523 | | size_t /* fileLength */) |
524 | 0 | { |
525 | 0 | if( m_priv->multiprocess ){ |
526 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
527 | | if (m_priv->bRefreshCurFile && m_priv->_mmap && !isMapFileEmpty(m_priv->_mmapPool)) |
528 | | { |
529 | | lockMMapFile(APR_FLOCK_SHARED); |
530 | | LogString mapCurrent(readMappedFileName(m_priv->_mmap)); |
531 | | unLockMMapFile(); |
532 | | |
533 | | if (!mapCurrent.empty() && static_cast<size_t>(m_priv->suffixLength) <= mapCurrent.length()) |
534 | | { |
535 | | LogString mapCurrentBase(mapCurrent.substr(0, mapCurrent.length() - m_priv->suffixLength)); |
536 | | |
537 | | if (!mapCurrentBase.empty() && mapCurrentBase != filename) |
538 | | { |
539 | | if (auto fappend = dynamic_cast<FileAppender*>(appender)) |
540 | | fappend->setFile(mapCurrentBase); |
541 | | } |
542 | | } |
543 | | } |
544 | | |
545 | | return ( Date::currentTime() > m_priv->nextCheck) || (!m_priv->bAlreadyInitialized); |
546 | | #endif |
547 | 0 | } |
548 | |
|
549 | 0 | return Date::currentTime() > m_priv->nextCheck; |
550 | 0 | } |
551 | | |
552 | 0 | void TimeBasedRollingPolicy::setMultiprocess(bool multiprocess){ |
553 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
554 | | // If we don't have the multiprocess stuff, disregard any attempt to set this value |
555 | | m_priv->multiprocess = multiprocess; |
556 | | #endif |
557 | 0 | } |
558 | | |
559 | | void TimeBasedRollingPolicy::setOption(const LogString& option, |
560 | | const LogString& value) |
561 | 0 | { |
562 | 0 | if (StringHelper::equalsIgnoreCase(option, |
563 | 0 | LOG4CXX_STR("THROWIOEXCEPTIONONFORKFAILURE"), |
564 | 0 | LOG4CXX_STR("throwioexceptiononforkfailure"))) |
565 | 0 | { |
566 | 0 | m_priv->throwIOExceptionOnForkFailure = OptionConverter::toBoolean(value, true); |
567 | 0 | } |
568 | 0 | else |
569 | 0 | { |
570 | 0 | RollingPolicyBase::setOption(option, value); |
571 | 0 | } |
572 | 0 | } |
573 | | |
574 | | /** |
575 | | * Was the name in shared memory set by this process? |
576 | | */ |
577 | | bool TimeBasedRollingPolicy::isLastFileNameUnchanged() |
578 | 0 | { |
579 | 0 | bool result = true; |
580 | 0 | if( m_priv->multiprocess ){ |
581 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
582 | | if (m_priv->_mmap) |
583 | | { |
584 | | lockMMapFile(APR_FLOCK_SHARED); |
585 | | LogString mapCurrent(readMappedFileName(m_priv->_mmap)); |
586 | | unLockMMapFile(); |
587 | | result = (mapCurrent == m_priv->lastFileName); |
588 | | } |
589 | | #endif |
590 | 0 | } |
591 | 0 | return result; |
592 | 0 | } |
593 | | |
594 | | /** |
595 | | * Load the name (set by some other process) from shared memory |
596 | | */ |
597 | | void TimeBasedRollingPolicy::loadLastFileName() |
598 | 0 | { |
599 | 0 | if( m_priv->multiprocess ){ |
600 | | #if LOG4CXX_HAS_MULTIPROCESS_ROLLING_FILE_APPENDER |
601 | | if (m_priv->_mmap) |
602 | | { |
603 | | lockMMapFile(APR_FLOCK_SHARED); |
604 | | LogString mapLastFile(readMappedFileName(m_priv->_mmap)); |
605 | | unLockMMapFile(); |
606 | | if (!mapLastFile.empty()) |
607 | | m_priv->lastFileName = mapLastFile; |
608 | | } |
609 | | #endif |
610 | 0 | } |
611 | 0 | } |