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