Author: tschoening
Date: Sun Feb 9 18:26:33 2014
New Revision: 1566343
URL: http://svn.apache.org/r1566343
Log:
LOGCXX-412: Log4cxx doesn't roll normally when working under multiple processes
environment
Modified:
incubator/log4cxx/trunk/src/changes/changes.xml
incubator/log4cxx/trunk/src/main/cpp/fixedwindowrollingpolicy.cpp
incubator/log4cxx/trunk/src/main/cpp/outputstream.cpp
incubator/log4cxx/trunk/src/main/cpp/outputstreamwriter.cpp
incubator/log4cxx/trunk/src/main/cpp/rollingfileappender.cpp
incubator/log4cxx/trunk/src/main/cpp/timebasedrollingpolicy.cpp
incubator/log4cxx/trunk/src/main/cpp/writer.cpp
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/fileoutputstream.h
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstream.h
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstreamwriter.h
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/writer.h
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingpolicybase.h
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
incubator/log4cxx/trunk/src/main/include/log4cxx/writerappender.h
Modified: incubator/log4cxx/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/changes/changes.xml?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/changes/changes.xml (original)
+++ incubator/log4cxx/trunk/src/changes/changes.xml Sun Feb 9 18:26:33 2014
@@ -62,6 +62,7 @@
<action issue="LOGCXX-367" type="fix">Build fails on
Linux with g++ 4.4</action>
<action issue="LOGCXX-381" type="fix">Pkgconfig can't
find dependencies properly if log4cxx built statically</action>
<action issue="LOGCXX-382" type="fix">Mingw build type
conversion error</action>
+ <action issue="LOGCXX-412" type="fix">Log4cxx doesn't
roll normally when working under multiple processes environment</action>
<action issue="LOGCXX-413" type="fix">log4cxx doesn't
compile on openembedded (due to Alex Zbarcea)</action>
<action issue="LOGCXX-414" type="fix">possibly wrong
use of autotools docdir (due to Alex Zbarcea)</action>
<action issue="LOGCXX-415" type="fix">Empty XML
configuration file causes crash</action>
Modified: incubator/log4cxx/trunk/src/main/cpp/fixedwindowrollingpolicy.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/fixedwindowrollingpolicy.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/fixedwindowrollingpolicy.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/fixedwindowrollingpolicy.cpp Sun Feb
9 18:26:33 2014
@@ -160,8 +160,13 @@ RolloverDescriptionPtr FixedWindowRollin
new FileRenameAction(
File().setPath(currentFileName), File().setPath(renameTo), false);
+#ifdef LOG4CXX_MULTI_PROCESS
+ desc = new RolloverDescription(
+ currentFileName, true, renameAction, compressAction);
+#else
desc = new RolloverDescription(
currentFileName, false, renameAction, compressAction);
+#endif
}
return desc;
Modified: incubator/log4cxx/trunk/src/main/cpp/outputstream.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/outputstream.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/outputstream.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/outputstream.cpp Sun Feb 9 18:26:33
2014
@@ -17,6 +17,7 @@
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/outputstream.h>
+#include <stdexcept>
using namespace log4cxx;
using namespace log4cxx::helpers;
@@ -28,3 +29,13 @@ OutputStream::OutputStream() {
OutputStream::~OutputStream() {
}
+
+#ifdef LOG4CXX_MULTI_PROCESS
+apr_file_t* OutputStream::getFilePtr(){
+ throw std::logic_error("getFilePtr must be implemented in the derived
class that you are using");
+}
+
+OutputStream& OutputStream::getFileOutPutStreamPtr(){
+ throw std::logic_error("getFileOutPutStreamPtr must be implemented in the
derived class that you are using");
+}
+#endif
Modified: incubator/log4cxx/trunk/src/main/cpp/outputstreamwriter.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/outputstreamwriter.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/outputstreamwriter.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/outputstreamwriter.cpp Sun Feb 9
18:26:33 2014
@@ -58,9 +58,15 @@ void OutputStreamWriter::flush(Pool& p)
void OutputStreamWriter::write(const LogString& str, Pool& p) {
if (str.length() > 0) {
+#ifdef LOG4CXX_MULTI_PROCESS
+ size_t bufSize = str.length() * 2;
+ char *rawbuf = new char[bufSize];
+ ByteBuffer buf(rawbuf, (size_t) bufSize);
+#else
enum { BUFSIZE = 1024 };
char rawbuf[BUFSIZE];
ByteBuffer buf(rawbuf, (size_t) BUFSIZE);
+#endif
enc->reset();
LogString::const_iterator iter = str.begin();
while(iter != str.end()) {
@@ -69,10 +75,14 @@ void OutputStreamWriter::write(const Log
out->write(buf, p);
buf.clear();
}
+
CharsetEncoder::encode(enc, str, iter, buf);
enc->flush(buf);
buf.flip();
out->write(buf, p);
+#ifdef LOG4CXX_MULTI_PROCESS
+ delete []rawbuf;
+#endif
}
}
Modified: incubator/log4cxx/trunk/src/main/cpp/rollingfileappender.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/rollingfileappender.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/rollingfileappender.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/rollingfileappender.cpp Sun Feb 9
18:26:33 2014
@@ -19,6 +19,19 @@
#pragma warning ( disable: 4231 4251 4275 4786 )
#endif
+#ifdef LOG4CXX_MULTI_PROCESS
+#include <apr_portable.h>
+#include <libgen.h>
+#include <apr_file_io.h>
+#include <apr_atomic.h>
+#include <apr_mmap.h>
+#ifndef MAX_FILE_LEN
+#define MAX_FILE_LEN 2048
+#endif
+#include <log4cxx/pattern/filedatepatternconverter.h>
+#include <log4cxx/helpers/date.h>
+#endif
+
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/synchronized.h>
@@ -41,7 +54,7 @@ IMPLEMENT_LOG4CXX_OBJECT(RollingFileAppe
/**
* Construct a new instance.
*/
-RollingFileAppenderSkeleton::RollingFileAppenderSkeleton() {
+RollingFileAppenderSkeleton::RollingFileAppenderSkeleton() : _event(NULL){
}
RollingFileAppender::RollingFileAppender() {
@@ -115,9 +128,20 @@ void RollingFileAppenderSkeleton::activa
+ getName());
}
}
-
}
+#ifdef LOG4CXX_MULTI_PROCESS
+void RollingFileAppenderSkeleton::releaseFileLock(apr_file_t* lock_file){
+ if (lock_file){
+ apr_status_t stat = apr_file_unlock(lock_file);
+ if (stat != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("flock: unlock failed"));
+ }
+ apr_file_close(lock_file);
+ lock_file = NULL;
+ }
+}
+#endif
/**
Implements the usual roll over behaviour.
@@ -134,105 +158,196 @@ void RollingFileAppenderSkeleton::activa
* @return true if rollover performed.
*/
bool RollingFileAppenderSkeleton::rollover(Pool& p) {
- //
- // can't roll without a policy
- //
- if (rollingPolicy != NULL) {
+ //
+ // can't roll without a policy
+ //
+ if (rollingPolicy != NULL) {
+
+ {
+ synchronized sync(mutex);
-{
- synchronized sync(mutex);
- try {
- RolloverDescriptionPtr rollover1(rollingPolicy->rollover(getFile(),
p));
-
- if (rollover1 != NULL) {
- if (rollover1->getActiveFileName() == getFile()) {
- closeWriter();
-
- bool success = true;
-
- if (rollover1->getSynchronous() != NULL) {
- success = false;
-
- try {
- success = rollover1->getSynchronous()->execute(p);
- } catch (std::exception& ex) {
- LogLog::warn(LOG4CXX_STR("Exception on rollover"));
- }
+#ifdef LOG4CXX_MULTI_PROCESS
+ std::string fileName(getFile());
+ RollingPolicyBase *basePolicy = dynamic_cast<RollingPolicyBase*
>(&(*rollingPolicy));
+ apr_time_t n = apr_time_now();
+ ObjectPtr obj(new Date(n));
+ LogString fileNamePattern;
+ if (basePolicy){
+ if (basePolicy->getPatternConverterList().size()){
+
(*(basePolicy->getPatternConverterList().begin()))->format(obj,
fileNamePattern, p);
+ fileName = std::string(fileNamePattern);
+ }
}
- if (success) {
- if (rollover1->getAppend()) {
- fileLength =
File().setPath(rollover1->getActiveFileName()).length(p);
- } else {
- fileLength = 0;
- }
-
- //
- // async action not yet implemented
- //
- ActionPtr asyncAction(rollover1->getAsynchronous());
- if (asyncAction != NULL) {
- asyncAction->execute(p);
- }
-
- setFile(
- rollover1->getActiveFileName(), rollover1->getAppend(),
- bufferedIO, bufferSize, p);
- } else {
- setFile(
- rollover1->getActiveFileName(), true, bufferedIO, bufferSize,
p);
+ bool bAlreadyRolled = true;
+ char szDirName[MAX_FILE_LEN] = {'\0'};
+ char szBaseName[MAX_FILE_LEN] = {'\0'};
+ char szUid[MAX_FILE_LEN] = {'\0'};
+ memcpy(szDirName, fileName.c_str(), fileName.size() > MAX_FILE_LEN
? MAX_FILE_LEN : fileName.size());
+ memcpy(szBaseName, fileName.c_str(), fileName.size() >
MAX_FILE_LEN ? MAX_FILE_LEN : fileName.size());
+ apr_uid_t uid;
+ apr_gid_t groupid;
+ apr_status_t stat = apr_uid_current(&uid, &groupid,
pool.getAPRPool());
+ if (stat == APR_SUCCESS){
+ snprintf(szUid, MAX_FILE_LEN, "%u", uid);
}
- } else {
- OutputStreamPtr os(new FileOutputStream(
- rollover1->getActiveFileName(), rollover1->getAppend()));
- WriterPtr newWriter(createWriter(os));
- closeWriter();
- setFile(rollover1->getActiveFileName());
- setWriter(newWriter);
-
- bool success = true;
-
- if (rollover1->getSynchronous() != NULL) {
- success = false;
-
- try {
- success = rollover1->getSynchronous()->execute(p);
- } catch (std::exception& ex) {
- LogLog::warn(LOG4CXX_STR("Exception during rollover"));
- }
+
+ const std::string lockname = std::string(::dirname(szDirName)) +
"/." + ::basename(szBaseName) + szUid + ".lock";
+ apr_file_t* lock_file;
+ stat = apr_file_open(&lock_file, lockname.c_str(), APR_CREATE |
APR_READ | APR_WRITE, APR_OS_DEFAULT, p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ std::string err = "lockfile return error: open lockfile
failed. ";
+ err += (strerror(errno));
+ LogLog::warn(LOG4CXX_STR(err.c_str()));
+ bAlreadyRolled = false;
+ lock_file = NULL;
+ }else{
+ stat = apr_file_lock(lock_file, APR_FLOCK_EXCLUSIVE);
+ if (stat != APR_SUCCESS){
+ std::string err = "apr_file_lock: lock failed. ";
+ err += (strerror(errno));
+ LogLog::warn(LOG4CXX_STR(err.c_str()));
+ bAlreadyRolled = false;
+ }
+ else {
+ if (_event)
+ triggeringPolicy->isTriggeringEvent(this, *_event,
getFile(), getFileLength());
+ }
}
- if (success) {
- if (rollover1->getAppend()) {
- fileLength =
File().setPath(rollover1->getActiveFileName()).length(p);
- } else {
- fileLength = 0;
- }
-
- //
- // async action not yet implemented
- //
- ActionPtr asyncAction(rollover1->getAsynchronous());
- if (asyncAction != NULL) {
- asyncAction->execute(p);
- }
+ if (bAlreadyRolled){
+ apr_finfo_t finfo1, finfo2;
+ apr_status_t st1, st2;
+ apr_file_t* _fd =
getWriter()->getOutPutStreamPtr()->getFileOutPutStreamPtr().getFilePtr();
+ st1 = apr_file_info_get(&finfo1, APR_FINFO_IDENT, _fd);
+ if (st1 != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("apr_file_info_get failed"));
+ }
+
+ st2 = apr_stat(&finfo2, std::string(getFile()).c_str(),
APR_FINFO_IDENT, p.getAPRPool());
+ if (st2 != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("apr_stat failed."));
+ }
+
+ bAlreadyRolled = ((st1 == APR_SUCCESS) && (st2 == APR_SUCCESS)
+ && ((finfo1.device != finfo2.device) || (finfo1.inode !=
finfo2.inode)));
}
+
+ if (!bAlreadyRolled){
+#endif
+ try {
+ RolloverDescriptionPtr
rollover1(rollingPolicy->rollover(getFile(), p));
+ if (rollover1 != NULL) {
+ if (rollover1->getActiveFileName() == getFile()) {
+ closeWriter();
+
+ bool success = true;
+ if (rollover1->getSynchronous() != NULL) {
+ success = false;
+
+ try {
+ success =
rollover1->getSynchronous()->execute(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception on
rollover"));
+ }
+ }
+
+ if (success) {
+ if (rollover1->getAppend()) {
+ fileLength =
File().setPath(rollover1->getActiveFileName()).length(p);
+ } else {
+ fileLength = 0;
+ }
+
+ //
+ // async action not yet implemented
+ //
+ ActionPtr
asyncAction(rollover1->getAsynchronous());
+ if (asyncAction != NULL) {
+ asyncAction->execute(p);
+ }
+
+ setFile(
+ rollover1->getActiveFileName(),
rollover1->getAppend(),
+ bufferedIO, bufferSize, p);
+ } else {
+ setFile(
+ rollover1->getActiveFileName(), true,
bufferedIO, bufferSize, p);
+ }
+ } else {
+ OutputStreamPtr os(new FileOutputStream(
+ rollover1->getActiveFileName(),
rollover1->getAppend()));
+ WriterPtr newWriter(createWriter(os));
+ closeWriter();
+ setFile(rollover1->getActiveFileName());
+ setWriter(newWriter);
+
+ bool success = true;
+
+ if (rollover1->getSynchronous() != NULL) {
+ success = false;
+
+ try {
+ success =
rollover1->getSynchronous()->execute(p);
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during
rollover"));
+ }
+ }
+
+ if (success) {
+ if (rollover1->getAppend()) {
+ fileLength =
File().setPath(rollover1->getActiveFileName()).length(p);
+ } else {
+ fileLength = 0;
+ }
+
+ //
+ // async action not yet implemented
+ //
+ ActionPtr
asyncAction(rollover1->getAsynchronous());
+ if (asyncAction != NULL) {
+ asyncAction->execute(p);
+ }
+ }
- writeHeader(p);
- }
+ writeHeader(p);
+ }
- return true;
+#ifdef LOG4CXX_MULTI_PROCESS
+ releaseFileLock(lock_file);
+#endif
+ return true;
+ }
+ } catch (std::exception& ex) {
+ LogLog::warn(LOG4CXX_STR("Exception during rollover"));
+ }
+#ifdef LOG4CXX_MULTI_PROCESS
+ }else{
+ reopenLatestFile(p);
+ }
+ releaseFileLock(lock_file);
+#endif
}
- } catch (std::exception& ex) {
- LogLog::warn(LOG4CXX_STR("Exception during rollover"));
- }
}
+ return false;
+}
- }
-
- return false;
+#ifdef LOG4CXX_MULTI_PROCESS
+/**
+ * re-open current file when its own handler has been renamed
+ */
+void RollingFileAppenderSkeleton::reopenLatestFile(Pool& p){
+ closeWriter();
+ OutputStreamPtr os(new FileOutputStream(getFile(), true));
+ WriterPtr newWriter(createWriter(os));
+ setFile(getFile());
+ setWriter(newWriter);
+ fileLength = File().setPath(getFile()).length(p);
+ writeHeader(p);
}
+#endif
+
/**
* {@inheritDoc}
*/
@@ -248,11 +363,38 @@ void RollingFileAppenderSkeleton::subApp
// is not provided. However appender should still be in good
// condition and the append should still happen.
try {
- rollover(p);
+ _event = &(const_cast<LoggingEventPtr &>(event));
+ rollover(p);
} catch (std::exception& ex) {
LogLog::warn(LOG4CXX_STR("Exception during rollover attempt."));
}
}
+
+#ifdef LOG4CXX_MULTI_PROCESS
+ //do re-check before every write
+ //
+ apr_finfo_t finfo1, finfo2;
+ apr_status_t st1, st2;
+ apr_file_t* _fd =
getWriter()->getOutPutStreamPtr()->getFileOutPutStreamPtr().getFilePtr();
+ st1 = apr_file_info_get(&finfo1, APR_FINFO_IDENT, _fd);
+ if (st1 != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("apr_file_info_get failed"));
+ }
+
+ st2 = apr_stat(&finfo2, std::string(getFile()).c_str(), APR_FINFO_IDENT,
p.getAPRPool());
+ if (st2 != APR_SUCCESS){
+ std::string err = "apr_stat failed. file:" + std::string(getFile());
+ LogLog::warn(LOG4CXX_STR(err.c_str()));
+ }
+
+ bool bAlreadyRolled = ((st1 == APR_SUCCESS) && (st2 == APR_SUCCESS)
+ && ((finfo1.device != finfo2.device) || (finfo1.inode != finfo2.inode)));
+
+ if (bAlreadyRolled){
+ reopenLatestFile(p);
+ }
+#endif
+
FileAppender::subAppend(event, p);
}
@@ -345,10 +487,17 @@ class CountingOutputStream : public Outp
void write(ByteBuffer& buf, Pool& p) {
os->write(buf, p);
if (rfa != 0) {
+#ifndef LOG4CXX_MULTI_PROCESS
rfa->incrementFileLength(buf.limit());
+#else
+ rfa->setFileLength(File().setPath(rfa->getFile()).length(p));
+#endif
}
}
+#ifdef LOG4CXX_MULTI_PROCESS
+ OutputStream& getFileOutPutStreamPtr() { return *os;}
+#endif
};
}
}
@@ -375,6 +524,12 @@ size_t RollingFileAppenderSkeleton::getF
return fileLength;
}
+#ifdef LOG4CXX_MULTI_PROCESS
+void RollingFileAppenderSkeleton::setFileLength(size_t length){
+ fileLength = length;
+}
+#endif
+
/**
* Increments estimated byte length of current active log file.
* @param increment additional bytes written to log file.
Modified: incubator/log4cxx/trunk/src/main/cpp/timebasedrollingpolicy.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/timebasedrollingpolicy.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/timebasedrollingpolicy.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/timebasedrollingpolicy.cpp Sun Feb 9
18:26:33 2014
@@ -18,6 +18,10 @@
#pragma warning ( disable: 4231 4251 4275 4786 )
#endif
+#ifdef LOG4CXX_MULTI_PROCESS
+#include <libgen.h>
+#endif
+
#include <log4cxx/logstring.h>
#include <log4cxx/rolling/timebasedrollingpolicy.h>
#include <log4cxx/pattern/filedatepatternconverter.h>
@@ -27,6 +31,8 @@
#include <log4cxx/helpers/exception.h>
#include <log4cxx/rolling/gzcompressaction.h>
#include <log4cxx/rolling/zipcompressaction.h>
+#include <log4cxx/rolling/rollingfileappenderskeleton.h>
+#include<iostream>
#ifndef INT64_C
#define INT64_C(x) x ## LL
@@ -34,7 +40,6 @@
#include <apr_time.h>
-
using namespace log4cxx;
using namespace log4cxx::rolling;
using namespace log4cxx::helpers;
@@ -42,8 +47,110 @@ using namespace log4cxx::pattern;
IMPLEMENT_LOG4CXX_OBJECT(TimeBasedRollingPolicy)
-TimeBasedRollingPolicy::TimeBasedRollingPolicy() {
+#ifdef LOG4CXX_MULTI_PROCESS
+#define MMAP_FILE_SUFFIX ".map"
+#define LOCK_FILE_SUFFIX ".maplck"
+#define MAX_FILE_LEN 2048
+
+bool TimeBasedRollingPolicy::isMapFileEmpty(log4cxx::helpers::Pool& pool){
+ apr_finfo_t finfo;
+ apr_status_t st = apr_stat(&finfo, _mapFileName.c_str(), APR_FINFO_SIZE,
pool.getAPRPool());
+ if (st != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("apr_stat failed."));
+ }
+ if (st == APR_SUCCESS && !finfo.size)
+ return true;
+ return false;
+}
+
+void TimeBasedRollingPolicy::initMMapFile(const LogString& lastFileName,
log4cxx::helpers::Pool& pool){
+ int iRet = 0;
+ if (!_mmap){
+ iRet = createMMapFile(std::string(_fileNamePattern), pool);
+ }
+ if (!iRet && isMapFileEmpty(pool)) {
+ lockMMapFile(APR_FLOCK_EXCLUSIVE);
+ memset(_mmap->mm, 0, MAX_FILE_LEN);
+ memcpy(_mmap->mm, std::string(lastFileName).c_str(),
std::string(lastFileName).size());
+ unLockMMapFile();
+ }
+}
+
+const std::string TimeBasedRollingPolicy::createFile(const std::string&
fileName, const std::string& suffix, log4cxx::helpers::Pool& pool) {
+ char szUid[MAX_FILE_LEN] = {'\0'};
+ char szBaseName[MAX_FILE_LEN] = {'\0'};
+ char szDirName[MAX_FILE_LEN] = {'\0'};
+ memcpy(szDirName, fileName.c_str(), fileName.size() > MAX_FILE_LEN ?
MAX_FILE_LEN : fileName.size());
+ memcpy(szBaseName, fileName.c_str(), fileName.size() > MAX_FILE_LEN ?
MAX_FILE_LEN : fileName.size());
+
+ apr_uid_t uid;
+ apr_gid_t groupid;
+ apr_status_t stat = apr_uid_current(&uid, &groupid, pool.getAPRPool());
+ if (stat == APR_SUCCESS){
+ snprintf(szUid, MAX_FILE_LEN, "%u", uid);
+ }
+ return std::string(::dirname(szDirName)) + "/." + ::basename(szBaseName) +
szUid + suffix;
+}
+
+int TimeBasedRollingPolicy::createMMapFile(const std::string& fileName,
log4cxx::helpers::Pool& pool){
+ _mapFileName = createFile(fileName, MMAP_FILE_SUFFIX, pool);
+
+ apr_status_t stat = apr_file_open(&_file_map, _mapFileName.c_str(),
APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, _mmapPool->getAPRPool());
+ if (stat != APR_SUCCESS){
+ std::string err(std::string("open mmap file failed. ") +
std::string(strerror(errno)) + ". Check the privilege or try to remove " +
_mapFileName + " if exist.");
+ LogLog::warn(LOG4CXX_STR(err.c_str()));
+ return -1;
+ }
+
+ if (isMapFileEmpty(pool)){
+ stat = apr_file_trunc(_file_map, MAX_FILE_LEN + 1);
+ if (stat != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("apr_file_trunc failed."));
+ apr_file_close(_file_map);
+ return -1;
+ }
+ }
+
+ stat = apr_mmap_create(&_mmap, _file_map, 0, MAX_FILE_LEN, APR_MMAP_WRITE |
APR_MMAP_READ, _mmapPool->getAPRPool());
+ if (stat != APR_SUCCESS){
+ LogLog::warn(LOG4CXX_STR("mmap failed."));
+ apr_file_close(_file_map);
+ return -1;
+ }
+
+ return 0;
+}
+
+int TimeBasedRollingPolicy::lockMMapFile(int type)
+{
+ apr_status_t stat = apr_file_lock(_lock_file, type);
+ if (stat != APR_SUCCESS) {
+ LogLog::warn(LOG4CXX_STR("apr_file_lock for mmap failed."));
+ }
+}
+int TimeBasedRollingPolicy::unLockMMapFile()
+{
+ apr_status_t stat = apr_file_unlock(_lock_file);
+ if (stat != APR_SUCCESS) {
+ LogLog::warn(LOG4CXX_STR("apr_file_unlock for mmap failed."));
+ }
+}
+
+#endif
+
+TimeBasedRollingPolicy::TimeBasedRollingPolicy()
+#ifdef LOG4CXX_MULTI_PROCESS
+ :_mmap(NULL), _file_map(NULL), bAlreadyInitialized(false), _mmapPool(new
Pool()), _lock_file(NULL), bRefreshCurFile(false)
+#endif
+{
+}
+
+#ifdef LOG4CXX_MULTI_PROCESS
+TimeBasedRollingPolicy::~TimeBasedRollingPolicy() {
+ //no-need to delete mmap
+ delete _mmapPool;
}
+#endif
void TimeBasedRollingPolicy::addRef() const {
TriggeringPolicy::addRef();
@@ -75,6 +182,24 @@ void TimeBasedRollingPolicy::activateOpt
formatFileName(obj, buf, pool);
lastFileName = buf;
+#ifdef LOG4CXX_MULTI_PROCESS
+ if (getPatternConverterList().size()){
+ (*(getPatternConverterList().begin()))->format(obj, _fileNamePattern,
pool);
+ }else{
+ _fileNamePattern = lastFileName;
+ }
+
+ if (!_lock_file) {
+ const std::string lockname = createFile(std::string(_fileNamePattern),
LOCK_FILE_SUFFIX, *_mmapPool);
+ apr_status_t stat = apr_file_open(&_lock_file, lockname.c_str(),
APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, (*_mmapPool).getAPRPool());
+ if (stat != APR_SUCCESS) {
+ LogLog::warn(LOG4CXX_STR("open lock file failed."));
+ }
+ }
+
+ initMMapFile(lastFileName, *_mmapPool);
+#endif
+
suffixLength = 0;
if (lastFileName.length() >= 3) {
@@ -120,6 +245,7 @@ RolloverDescriptionPtr TimeBasedRollingP
return new RolloverDescription(
currentActiveFile, append, noAction, noAction);
} else {
+ bRefreshCurFile = true;
return new RolloverDescription(
lastFileName.substr(0, lastFileName.length() - suffixLength), append,
noAction, noAction);
@@ -140,6 +266,19 @@ RolloverDescriptionPtr TimeBasedRollingP
LogString newFileName(buf);
+#ifdef LOG4CXX_MULTI_PROCESS
+ bAlreadyInitialized = true;
+ if (_mmap && !isMapFileEmpty(*_mmapPool)){
+ lockMMapFile(APR_FLOCK_SHARED);
+ LogString mapLastFile((char *)_mmap->mm);
+ lastFileName = mapLastFile;
+ unLockMMapFile();
+ }else{
+ _mmap = NULL;
+ initMMapFile(lastFileName, *_mmapPool);
+ }
+#endif
+
//
// if file names haven't changed, no rollover
//
@@ -178,18 +317,48 @@ RolloverDescriptionPtr TimeBasedRollingP
File().setPath(lastBaseName), File().setPath(lastFileName), true);
}
+#ifdef LOG4CXX_MULTI_PROCESS
+ if (_mmap && !isMapFileEmpty(*_mmapPool)){
+ lockMMapFile(APR_FLOCK_EXCLUSIVE);
+ memset(_mmap->mm, 0, MAX_FILE_LEN);
+ memcpy(_mmap->mm, std::string(newFileName).c_str(),
std::string(newFileName).size());
+ unLockMMapFile();
+ }else{
+ _mmap = NULL;
+ initMMapFile(newFileName, *_mmapPool);
+ }
+#else
lastFileName = newFileName;
+#endif
+#ifdef LOG4CXX_MULTI_PROCESS
+ return new RolloverDescription(
+ nextActiveFile, true, renameAction, compressAction);
+#else
return new RolloverDescription(
nextActiveFile, false, renameAction, compressAction);
+#endif
}
bool TimeBasedRollingPolicy::isTriggeringEvent(
- Appender* /* appender */,
+ Appender* appender,
const log4cxx::spi::LoggingEventPtr& /* event */,
- const LogString& /* filename */,
+ const LogString& filename ,
size_t /* fileLength */) {
+#ifdef LOG4CXX_MULTI_PROCESS
+ if (bRefreshCurFile && _mmap && !isMapFileEmpty(*_mmapPool)) {
+ lockMMapFile(APR_FLOCK_SHARED);
+ LogString mapCurrent((char *)_mmap->mm);
+ unLockMMapFile();
+ LogString mapCurrentBase(mapCurrent.substr(0, mapCurrent.length() -
suffixLength));
+ if (!mapCurrentBase.empty() && mapCurrentBase != filename) {
+ dynamic_cast<FileAppender *>(appender)->setFile(mapCurrentBase);
+ }
+ }
+ return ((apr_time_now()) > nextCheck) || (!bAlreadyInitialized);
+#else
return apr_time_now() > nextCheck;
+#endif
}
Modified: incubator/log4cxx/trunk/src/main/cpp/writer.cpp
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/cpp/writer.cpp?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/cpp/writer.cpp (original)
+++ incubator/log4cxx/trunk/src/main/cpp/writer.cpp Sun Feb 9 18:26:33 2014
@@ -17,6 +17,7 @@
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/writer.h>
+#include <stdexcept>
using namespace log4cxx::helpers;
@@ -27,3 +28,9 @@ Writer::Writer() {
Writer::~Writer() {
}
+
+#ifdef LOG4CXX_MULTI_PROCESS
+OutputStreamPtr Writer::getOutPutStreamPtr(){
+ throw std::logic_error("getOutPutStreamPtr must be implemented in the
derived class that you are using");
+}
+#endif
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/fileoutputstream.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/fileoutputstream.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/fileoutputstream.h
(original)
+++ incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/fileoutputstream.h
Sun Feb 9 18:26:33 2014
@@ -52,6 +52,9 @@ namespace log4cxx
virtual void flush(Pool& p);
virtual void write(ByteBuffer& buf, Pool& p);
+#ifdef LOG4CXX_MULTI_PROCESS
+ apr_file_t* getFilePtr() { return fileptr; }
+#endif
private:
FileOutputStream(const FileOutputStream&);
FileOutputStream& operator=(const FileOutputStream&);
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstream.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstream.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstream.h
(original)
+++ incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstream.h Sun
Feb 9 18:26:33 2014
@@ -19,6 +19,9 @@
#define _LOG4CXX_HELPERS_OUTPUTSTREAM_H
#include <log4cxx/helpers/objectimpl.h>
+#ifdef LOG4CXX_MULTI_PROCESS
+#include <apr_file_io.h>
+#endif
namespace log4cxx
{
@@ -45,6 +48,10 @@ namespace log4cxx
virtual void close(Pool& p) = 0;
virtual void flush(Pool& p) = 0;
virtual void write(ByteBuffer& buf, Pool& p) = 0;
+#ifdef LOG4CXX_MULTI_PROCESS
+ virtual apr_file_t* getFilePtr();
+ virtual OutputStream& getFileOutPutStreamPtr();
+#endif
private:
OutputStream(const OutputStream&);
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstreamwriter.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstreamwriter.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
---
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstreamwriter.h
(original)
+++
incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/outputstreamwriter.h
Sun Feb 9 18:26:33 2014
@@ -52,6 +52,10 @@ namespace log4cxx
virtual void write(const LogString& str, Pool& p);
LogString getEncoding() const;
+#ifdef LOG4CXX_MULTI_PROCESS
+ OutputStreamPtr getOutPutStreamPtr() { return out; }
+#endif
+
private:
OutputStreamWriter(const OutputStreamWriter&);
OutputStreamWriter& operator=(const OutputStreamWriter&);
Modified: incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/writer.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/writer.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/writer.h (original)
+++ incubator/log4cxx/trunk/src/main/include/log4cxx/helpers/writer.h Sun Feb
9 18:26:33 2014
@@ -19,6 +19,7 @@
#define _LOG4CXX_HELPERS_WRITER_H
#include <log4cxx/helpers/objectimpl.h>
+#include <log4cxx/helpers/outputstream.h>
namespace log4cxx
{
@@ -44,6 +45,9 @@ namespace log4cxx
virtual void close(Pool& p) = 0;
virtual void flush(Pool& p) = 0;
virtual void write(const LogString& str, Pool& p) = 0;
+#ifdef LOG4CXX_MULTI_PROCESS
+ virtual OutputStreamPtr getOutPutStreamPtr();
+#endif
private:
Writer(const Writer&);
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
---
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
(original)
+++
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingfileappenderskeleton.h
Sun Feb 9 18:26:33 2014
@@ -57,6 +57,10 @@ namespace log4cxx {
*/
size_t fileLength;
+ /**
+ * save the loggingevent
+ */
+ spi::LoggingEventPtr* _event;
public:
/**
* The default constructor simply calls its {@link
@@ -133,6 +137,25 @@ namespace log4cxx {
* @return byte length of current active log file.
*/
size_t getFileLength() const;
+
+#ifdef LOG4CXX_MULTI_PROCESS
+ /**
+ * Set byte length of current active log file.
+ * @return void
+ */
+ void setFileLength(size_t length);
+
+ /**
+ * Release the file lock
+ * @return void
+ */
+ void releaseFileLock(apr_file_t* lock_file);
+ /**
+ * re-open the latest file when its own handler has been renamed
+ * @return void
+ */
+ void reopenLatestFile(log4cxx::helpers::Pool& p);
+#endif
/**
* Increments estimated byte length of current active log file.
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingpolicybase.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingpolicybase.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
---
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingpolicybase.h
(original)
+++
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/rollingpolicybase.h
Sun Feb 9 18:26:33 2014
@@ -96,6 +96,9 @@ namespace log4cxx {
LogString getFileNamePattern() const;
+#ifdef LOG4CXX_MULTI_PROCESS
+ PatternConverterList getPatternConverterList() { return
patternConverters; }
+#endif
protected:
/**
* Parse file name pattern.
Modified:
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
---
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
(original)
+++
incubator/log4cxx/trunk/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
Sun Feb 9 18:26:33 2014
@@ -22,6 +22,9 @@
#include <log4cxx/portability.h>
#include <log4cxx/rolling/rollingpolicybase.h>
#include <log4cxx/rolling/triggeringpolicy.h>
+#include <log4cxx/writerappender.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <apr_mmap.h>
namespace log4cxx {
@@ -157,6 +160,50 @@ namespace log4cxx {
LogString lastFileName;
/**
+ * mmap pointer
+ */
+ apr_mmap_t* _mmap;
+
+ /*
+ * pool for mmap handler
+ * */
+ log4cxx::helpers::Pool* _mmapPool;
+
+ /**
+ * mmap file descriptor
+ */
+ apr_file_t* _file_map;
+
+ /**
+ * mmap file name
+ */
+ std::string _mapFileName;
+
+ /*
+ * lock file handle
+ * */
+ apr_file_t* _lock_file;
+ /**
+ * Check nextCheck if it has already been set
+ * Timebased rolling policy has an issue when working at low rps.
+ * Under low rps, multiple processes will not be scheduled in time for
the second chance(do rolling),
+ * so the rolling mechanism will not be triggered even if the time
period is out of date.
+ * This results in log entries will be accumulated for serveral
minutes to be rolling.
+ * Adding this flag to provide rolling opportunity for a process even
if it is writing the first log entry
+ */
+ bool bAlreadyInitialized;
+
+ /*
+ * If the current file name contains date information, retrieve the
current writting file from mmap
+ * */
+ bool bRefreshCurFile;
+
+ /*
+ * mmap file name
+ * */
+ LogString _fileNamePattern;
+
+ /**
* Length of any file type suffix (.gz, .zip).
*/
int suffixLength;
@@ -166,6 +213,41 @@ namespace log4cxx {
void addRef() const;
void releaseRef() const;
void activateOptions(log4cxx::helpers::Pool& );
+
+#ifdef LOG4CXX_MULTI_PROCESS
+ virtual ~TimeBasedRollingPolicy();
+
+ /**
+ * Generate mmap file
+ */
+ int createMMapFile(const std::string& lastfilename,
log4cxx::helpers::Pool& pool);
+
+ /**
+ * Detect if the mmap file is empty
+ */
+ bool isMapFileEmpty(log4cxx::helpers::Pool& pool);
+
+ /**
+ * init MMapFile
+ */
+ void initMMapFile(const LogString& lastFileName,
log4cxx::helpers::Pool& pool);
+
+ /**
+ * lock MMapFile
+ */
+ int lockMMapFile(int type);
+
+ /**
+ * unlock MMapFile
+ */
+ int unLockMMapFile();
+
+ /**
+ * create MMapFile/lockFile
+ */
+ const std::string createFile(const std::string& filename, const
std::string& suffix, log4cxx::helpers::Pool& pool);
+#endif
+
/**
* Initialize the policy and return any initial actions for rolling
file appender.
*
Modified: incubator/log4cxx/trunk/src/main/include/log4cxx/writerappender.h
URL:
http://svn.apache.org/viewvc/incubator/log4cxx/trunk/src/main/include/log4cxx/writerappender.h?rev=1566343&r1=1566342&r2=1566343&view=diff
==============================================================================
--- incubator/log4cxx/trunk/src/main/include/log4cxx/writerappender.h (original)
+++ incubator/log4cxx/trunk/src/main/include/log4cxx/writerappender.h Sun Feb
9 18:26:33 2014
@@ -179,6 +179,9 @@ namespace log4cxx
<p>
@param writer An already opened Writer. */
void setWriter(const log4cxx::helpers::WriterPtr& writer);
+#ifdef LOG4CXX_MULTI_PROCESS
+ const log4cxx::helpers::WriterPtr getWriter() { return writer;
};
+#endif
virtual bool requiresLayout() const;