/*
* Category.cpp
*
* Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
* Copyright 2000, Bastiaan Bakker. All rights reserved.
*
* See the COPYING file for the terms of usage and distribution.
*/
#include "PortabilityImpl.hh"
#ifdef LOG4CPP_HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <log4cpp/Category.hh>
#include <log4cpp/HierarchyMaintainer.hh>
#include <log4cpp/NDC.hh>
#include "StringUtil.hh"
namespace log4cpp {
Category& Category::getRoot() {
return getInstance("");
}
void Category::setRootPriority(Priority::Value priority) {
getRoot().setPriority(priority);
}
Priority::Value Category::getRootPriority() LOG4CPP_NOTHROW {
return getRoot().getPriority();
}
Category& Category::getInstance(const std::string& name) {
return HierarchyMaintainer::getDefaultMaintainer().getInstance(name);
}
Category* Category::exists(const std::string& name) {
return HierarchyMaintainer::getDefaultMaintainer().getExistingInstance(name);
}
std::vector<Category*>* Category::getCurrentCategories() {
return HierarchyMaintainer::getDefaultMaintainer().
getCurrentCategories();
}
void Category::shutdown() {
HierarchyMaintainer::getDefaultMaintainer().shutdown();
}
void Category::shutdownForced() {
HierarchyMaintainer::getDefaultMaintainer().shutdown();
Appender::_deleteAllAppenders();
}
Category::Category(const std::string& name, Category* parent, Priority::Value priority) :
_name(name),
_parent(parent),
_priority(priority),
_isAdditive(true) {
}
Category::~Category() {
removeAllAppenders();
}
const std::string& Category::getName() const LOG4CPP_NOTHROW {
return _name;
}
Priority::Value Category::getPriority() const LOG4CPP_NOTHROW {
return _priority;
}
void Category::setPriority(Priority::Value priority) {
if ((priority < Priority::NOTSET) || (getParent() != NULL)) {
_priority = priority;
} else {
/* caller tried to set NOTSET priority to root Category.
Bad caller!
*/
throw std::invalid_argument("cannot set priority NOTSET on Root Category");
}
}
Priority::Value Category::getChainedPriority() const LOG4CPP_NOTHROW {
// REQUIRE(rootCategory->getPriority() != Priority::NOTSET)
const Category* c = this;
while(c->getPriority() >= Priority::NOTSET) {
c = c->getParent();
}
return c->getPriority();
}
void Category::addAppender(Appender* appender) {
if (appender) {
threading::ScopedLock lock(_appenderSetMutex);
{
AppenderSet::iterator i = _appender.find(appender);
if (_appender.end() == i) {
// not found
_appender.insert(appender);
_ownsAppender[appender] = true;
}
}
} else {
throw std::invalid_argument("NULL appender");
}
}
void Category::addAppender(Appender& appender) {
threading::ScopedLock lock(_appenderSetMutex);
{
AppenderSet::iterator i = _appender.find(&appender);
if (_appender.end() == i) {
_appender.insert(&appender);
_ownsAppender[&appender] = false;
}
}
}
Appender* Category::getAppender() const {
threading::ScopedLock lock(_appenderSetMutex);
{
AppenderSet::const_iterator i = _appender.begin();
return (_appender.end() == i) ? NULL : *i;
}
}
Appender* Category::getAppender(const std::string& name) const {
threading::ScopedLock lock(_appenderSetMutex);
{
AppenderSet::const_iterator i = _appender.begin();
if (_appender.end() != i) {
// found
return((*i)->getAppender(name));
}
else {
return(NULL);
}
}
}
AppenderSet Category::getAllAppenders() const {
threading::ScopedLock lock(_appenderSetMutex);
{
return _appender;
}
}
void Category::removeAllAppenders() {
threading::ScopedLock lock(_appenderSetMutex);
{
for (AppenderSet::iterator i = _appender.begin();
i != _appender.end(); i++) {
// found
OwnsAppenderMap::iterator i2;
if (ownsAppender(*i, i2)) {
delete (*i);
}
}
_ownsAppender.clear();
_appender.clear();
}
}
void Category::removeAppender(Appender* appender) {
threading::ScopedLock lock(_appenderSetMutex);
{
AppenderSet::iterator i = _appender.find(appender);
if (_appender.end() != i) {
OwnsAppenderMap::iterator i2;
if (ownsAppender(*i, i2)) {
_ownsAppender.erase(i2);
delete (*i);
}
_appender.erase(i);
} else {
// appender not found
}
}
}
bool Category::ownsAppender(Appender* appender) const LOG4CPP_NOTHROW {
bool owned = false;
threading::ScopedLock lock(_appenderSetMutex);
{
if (NULL != appender) {
OwnsAppenderMap::const_iterator i =
_ownsAppender.find(appender);
if (_ownsAppender.end() != i) {
owned = (*i).second;
}
}
}
return owned;
}
/* assume lock is held */
bool Category::ownsAppender(Appender* appender,
Category::OwnsAppenderMap::iterator& i2) LOG4CPP_NOTHROW {
bool owned = false;
if (NULL != appender) {
OwnsAppenderMap::iterator i = _ownsAppender.find(appender);
if (_ownsAppender.end() != i) {
owned = (*i).second;
if (owned) {
i2 = i;
}
}
}
return owned;
}
void Category::callAppenders(const LoggingEvent& event) LOG4CPP_NOTHROW {
threading::ScopedLock lock(_appenderSetMutex);
{
if (!_appender.empty()) {
for(AppenderSet::const_iterator i = _appender.begin();
i != _appender.end(); i++) {
(*i)->doAppend(event);
}
}
}
if (getAdditivity() && (getParent() != NULL)) {
getParent()->callAppenders(event);
}
}
void Category::setAdditivity(bool additivity) {
_isAdditive = additivity;
}
bool Category::getAdditivity() const LOG4CPP_NOTHROW {
return _isAdditive;
}
Category* Category::getParent() LOG4CPP_NOTHROW {
return _parent;
}
const Category* Category::getParent() const LOG4CPP_NOTHROW {
return _parent;
}
void Category::_logUnconditionally(Priority::Value priority,
const char* format,
va_list arguments) LOG4CPP_NOTHROW {
_logUnconditionally2(priority, StringUtil::vform(format, arguments));
}
void Category::_logUnconditionally2(Priority::Value priority,
const std::string& message) LOG4CPP_NOTHROW {
LoggingEvent event(getName(), message, NDC::get(), priority);
callAppenders(event);
}
bool Category::isPriorityEnabled(Priority::Value priority) const LOG4CPP_NOTHROW {
return(getChainedPriority() >= priority);
}
void Category::log(Priority::Value priority,
const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(priority)) {
va_list va;
va_start(va, stringFormat);
_logUnconditionally(priority, stringFormat, va);
va_end(va);
}
}
void Category::log(Priority::Value priority,
const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(priority))
_logUnconditionally2(priority, message);
}
void Category::logva(Priority::Value priority,
const char* stringFormat,
va_list va) LOG4CPP_NOTHROW {
if (isPriorityEnabled(priority)) {
_logUnconditionally(priority, stringFormat, va);
}
}
void Category::debug(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::DEBUG)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::DEBUG, stringFormat, va);
va_end(va);
}
}
void Category::debug(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::DEBUG))
_logUnconditionally2(Priority::DEBUG, message);
}
void Category::info(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::INFO)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::INFO, stringFormat, va);
va_end(va);
}
}
void Category::info(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::INFO))
_logUnconditionally2(Priority::INFO, message);
}
void Category::notice(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::NOTICE)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::NOTICE, stringFormat, va);
va_end(va);
}
}
void Category::notice(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::NOTICE))
_logUnconditionally2(Priority::NOTICE, message);
}
void Category::warn(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::WARN)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::WARN, stringFormat, va);
va_end(va);
}
}
void Category::warn(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::WARN))
_logUnconditionally2(Priority::WARN, message);
}
void Category::error(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::ERROR)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::ERROR, stringFormat, va);
va_end(va);
}
}
void Category::error(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::ERROR))
_logUnconditionally2(Priority::ERROR, message);
}
void Category::crit(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::CRIT)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::CRIT, stringFormat, va);
va_end(va);
}
}
void Category::crit(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::CRIT))
_logUnconditionally2(Priority::CRIT, message);
}
void Category::alert(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::ALERT)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::ALERT, stringFormat, va);
va_end(va);
}
}
void Category::alert(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::ALERT))
_logUnconditionally2(Priority::ALERT, message);
}
void Category::emerg(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::EMERG)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::EMERG, stringFormat, va);
va_end(va);
}
}
void Category::emerg(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::EMERG))
_logUnconditionally2(Priority::EMERG, message);
}
void Category::fatal(const char* stringFormat, ...) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::FATAL)) {
va_list va;
va_start(va,stringFormat);
_logUnconditionally(Priority::FATAL, stringFormat, va);
va_end(va);
}
}
void Category::fatal(const std::string& message) LOG4CPP_NOTHROW {
if (isPriorityEnabled(Priority::FATAL))
_logUnconditionally2(Priority::FATAL, message);
}
CategoryStream Category::getStream(Priority::Value priority) {
return CategoryStream(*this, isPriorityEnabled(priority) ?
priority : Priority::NOTSET);
}
CategoryStream Category::operator<<(Priority::Value priority) {
return getStream(priority);
}
}