diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-11 21:06:39 +0200 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-11 21:06:39 +0200 |
| commit | efb33d6494d88c27c8766553b6a963ddf2654458 (patch) | |
| tree | 76dd5e56b79191074998c0fb6bf7b81276116a4b /ext/Log4Qt/src/appenderskeleton.cpp | |
| parent | 072da88eee57e5d16f0b75c7b90c8a0bc6a60cb3 (diff) | |
Included Log4Qt in project
Diffstat (limited to 'ext/Log4Qt/src/appenderskeleton.cpp')
| -rw-r--r-- | ext/Log4Qt/src/appenderskeleton.cpp | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/ext/Log4Qt/src/appenderskeleton.cpp b/ext/Log4Qt/src/appenderskeleton.cpp new file mode 100644 index 0000000..78be62c --- /dev/null +++ b/ext/Log4Qt/src/appenderskeleton.cpp @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * package: + * file: appenderskeleton.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * Copyright 2007 Martin Heinrich + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "appenderskeleton.h" + +#include <QtCore/QDebug> +#include "layout.h" +#include "loggingevent.h" +#include "logmanager.h" +#include "spi/filter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + ***************************************************************************/ + + + /*! + * \brief The class RecursionGuardLocker controls a boolean flag. + * + * It is a helper class to control a boolean flag. The class sets the flag + * on creation and resets it on destruction. + */ + class RecursionGuardLocker + { + public: + RecursionGuardLocker(bool *pGuard); + ~RecursionGuardLocker(); + private: + RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented + RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented + private: + bool *mpGuard; + }; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: RecursionGuardLocker + ***************************************************************************/ + + + inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard) + { + Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null"); + + mpGuard = pGuard; + *mpGuard = true; + } + + + inline RecursionGuardLocker::~RecursionGuardLocker() + { + *mpGuard = false; + } + + + /************************************************************************** + * Class implementation: AppenderSkeleton + **************************************************************************/ + + + AppenderSkeleton::AppenderSkeleton(QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(true), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + AppenderSkeleton::AppenderSkeleton(const bool isActive, + QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(isActive), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + void AppenderSkeleton::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"), + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return; + } + mIsActive = true; + } + + + void AppenderSkeleton::addFilter(Filter *pFilter) + { + if(!pFilter) + { + logger()->warn("Adding null Filter to Appender '%1'", name()); + return; + } + + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = pFilter; + if (mpHeadFilter) + mpHeadFilter->setNext(pFilter); + else + mpHeadFilter = pFilter; + } + + + void AppenderSkeleton::clearFilters() + { + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = 0; + mpHeadFilter = 0; + } + + + void AppenderSkeleton::close() + { + QMutexLocker locker(&mObjectGuard); + + mIsClosed = true; + mIsActive = false; + } + + void AppenderSkeleton::customEvent(QEvent* event) + { + if (event->type() == LoggingEvent::eventId) { + LoggingEvent *logEvent = static_cast<LoggingEvent*>(event); + doAppend(*logEvent); + return ; + } + QObject::customEvent(event); + } + + void AppenderSkeleton::doAppend(const LoggingEvent &rEvent) + { + // The mutex serialises concurrent access from multiple threads. + // - e.g. two threads using the same logger + // - e.g. two threads using different logger with the same appender + // + // A call from the same thread will pass the mutex (QMutex::Recursive) + // and get to the recursion guard. The recursion guard blocks recursive + // invocation and prevents a possible endless loop. + // - e.g. an appender logs an error with a logger that uses it + + QMutexLocker locker(&mObjectGuard); + + if (mAppendRecursionGuard) + return; + + RecursionGuardLocker recursion_locker(&mAppendRecursionGuard); + + if (!checkEntryConditions()) + return; + if (!isAsSevereAsThreshold(rEvent.level())) + return; + + Filter *p_filter = mpHeadFilter; + while(p_filter) + { + Filter::Decision decision = p_filter->decide(rEvent); + if (decision == Filter::ACCEPT) + break; + else if (decision == Filter::DENY) + return; + else + p_filter = p_filter->next(); + } + + append(rEvent); + } + + + bool AppenderSkeleton::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!isActive()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"), + APPENDER_NOT_ACTIVATED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (isClosed()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"), + APPENDER_CLOSED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"), + APPENDER_USE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt |
