1 /* 2 * Category.cpp 3 * 4 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved. 5 * Copyright 2000, Bastiaan Bakker. All rights reserved. 6 * 7 * See the COPYING file for the terms of usage and distribution. 8 */ 9 10 #include "PortabilityImpl.hh" 11 12 #ifdef LOG4CPP_HAVE_UNISTD_H 13 # include <unistd.h> 14 #endif 15 16 #include <log4cpp/Category.hh> 17 #include <log4cpp/HierarchyMaintainer.hh> 18 #include <log4cpp/NDC.hh> 19 #include "StringUtil.hh" 20 21 namespace log4cpp { 22 getRoot()23 Category& Category::getRoot() { 24 return getInstance(""); 25 } 26 setRootPriority(Priority::Value priority)27 void Category::setRootPriority(Priority::Value priority) { 28 getRoot().setPriority(priority); 29 } 30 getRootPriority()31 Priority::Value Category::getRootPriority() throw() { 32 return getRoot().getPriority(); 33 } 34 getInstance(const std::string & name)35 Category& Category::getInstance(const std::string& name) { 36 return HierarchyMaintainer::getDefaultMaintainer().getInstance(name); 37 } 38 exists(const std::string & name)39 Category* Category::exists(const std::string& name) { 40 return HierarchyMaintainer::getDefaultMaintainer().getExistingInstance(name); 41 } 42 getCurrentCategories()43 std::vector<Category*>* Category::getCurrentCategories() { 44 return HierarchyMaintainer::getDefaultMaintainer(). 45 getCurrentCategories(); 46 } 47 shutdown()48 void Category::shutdown() { 49 HierarchyMaintainer::getDefaultMaintainer().shutdown(); 50 } 51 shutdownForced()52 void Category::shutdownForced() { 53 HierarchyMaintainer::getDefaultMaintainer().shutdown(); 54 Appender::_deleteAllAppenders(); 55 } 56 57 Category(const std::string & name,Category * parent,Priority::Value priority)58 Category::Category(const std::string& name, Category* parent, Priority::Value priority) : 59 _name(name), 60 _parent(parent), 61 _priority(priority), 62 _isAdditive(true) { 63 } 64 ~Category()65 Category::~Category() { 66 removeAllAppenders(); 67 } 68 getName() const69 const std::string& Category::getName() const throw() { 70 return _name; 71 } 72 getPriority() const73 Priority::Value Category::getPriority() const throw() { 74 return _priority; 75 } 76 setPriority(Priority::Value priority)77 void Category::setPriority(Priority::Value priority) { 78 if ((priority < Priority::NOTSET) || (getParent() != NULL)) { 79 _priority = priority; 80 } else { 81 /* caller tried to set NOTSET priority to root Category. 82 Bad caller! 83 */ 84 throw std::invalid_argument("cannot set priority NOTSET on Root Category"); 85 } 86 } 87 getChainedPriority() const88 Priority::Value Category::getChainedPriority() const throw() { 89 // REQUIRE(rootCategory->getPriority() != Priority::NOTSET) 90 91 const Category* c = this; 92 while(c->getPriority() >= Priority::NOTSET) { 93 c = c->getParent(); 94 } 95 96 return c->getPriority(); 97 } 98 addAppender(Appender * appender)99 void Category::addAppender(Appender* appender) { 100 if (appender) { 101 threading::ScopedLock lock(_appenderSetMutex); 102 { 103 AppenderSet::iterator i = _appender.find(appender); 104 if (_appender.end() == i) { 105 // not found 106 _appender.insert(appender); 107 _ownsAppender[appender] = true; 108 } 109 } 110 } else { 111 throw std::invalid_argument("NULL appender"); 112 } 113 } 114 addAppender(Appender & appender)115 void Category::addAppender(Appender& appender) { 116 threading::ScopedLock lock(_appenderSetMutex); 117 { 118 AppenderSet::iterator i = _appender.find(&appender); 119 if (_appender.end() == i) { 120 _appender.insert(&appender); 121 _ownsAppender[&appender] = false; 122 } 123 } 124 } 125 getAppender() const126 Appender* Category::getAppender() const { 127 threading::ScopedLock lock(_appenderSetMutex); 128 { 129 AppenderSet::const_iterator i = _appender.begin(); 130 return (_appender.end() == i) ? NULL : *i; 131 } 132 } 133 getAppender(const std::string & name) const134 Appender* Category::getAppender(const std::string& name) const { 135 threading::ScopedLock lock(_appenderSetMutex); 136 { 137 AppenderSet::const_iterator i = _appender.begin(); 138 if (_appender.end() != i) { 139 // found 140 return((*i)->getAppender(name)); 141 } 142 else { 143 return(NULL); 144 } 145 } 146 } 147 getAllAppenders() const148 AppenderSet Category::getAllAppenders() const { 149 threading::ScopedLock lock(_appenderSetMutex); 150 { 151 return _appender; 152 } 153 } 154 removeAllAppenders()155 void Category::removeAllAppenders() { 156 threading::ScopedLock lock(_appenderSetMutex); 157 { 158 for (AppenderSet::iterator i = _appender.begin(); 159 i != _appender.end(); i++) { 160 // found 161 OwnsAppenderMap::iterator i2; 162 if (ownsAppender(*i, i2)) { 163 delete (*i); 164 } 165 } 166 167 _ownsAppender.clear(); 168 _appender.clear(); 169 } 170 } 171 removeAppender(Appender * appender)172 void Category::removeAppender(Appender* appender) { 173 threading::ScopedLock lock(_appenderSetMutex); 174 { 175 AppenderSet::iterator i = _appender.find(appender); 176 if (_appender.end() != i) { 177 OwnsAppenderMap::iterator i2; 178 if (ownsAppender(*i, i2)) { 179 _ownsAppender.erase(i2); 180 delete (*i); 181 } 182 _appender.erase(i); 183 } else { 184 // appender not found 185 } 186 } 187 } 188 ownsAppender(Appender * appender) const189 bool Category::ownsAppender(Appender* appender) const throw() { 190 bool owned = false; 191 192 threading::ScopedLock lock(_appenderSetMutex); 193 { 194 if (NULL != appender) { 195 OwnsAppenderMap::const_iterator i = 196 _ownsAppender.find(appender); 197 if (_ownsAppender.end() != i) { 198 owned = (*i).second; 199 } 200 } 201 } 202 203 return owned; 204 } 205 206 /* assume lock is held */ ownsAppender(Appender * appender,Category::OwnsAppenderMap::iterator & i2)207 bool Category::ownsAppender(Appender* appender, 208 Category::OwnsAppenderMap::iterator& i2) throw() { 209 bool owned = false; 210 211 if (NULL != appender) { 212 OwnsAppenderMap::iterator i = _ownsAppender.find(appender); 213 if (_ownsAppender.end() != i) { 214 owned = (*i).second; 215 if (owned) { 216 i2 = i; 217 } 218 } 219 } 220 221 return owned; 222 } 223 callAppenders(const LoggingEvent & event)224 void Category::callAppenders(const LoggingEvent& event) throw() { 225 threading::ScopedLock lock(_appenderSetMutex); 226 { 227 if (!_appender.empty()) { 228 for(AppenderSet::const_iterator i = _appender.begin(); 229 i != _appender.end(); i++) { 230 (*i)->doAppend(event); 231 } 232 } 233 } 234 if (getAdditivity() && (getParent() != NULL)) { 235 getParent()->callAppenders(event); 236 } 237 } 238 setAdditivity(bool additivity)239 void Category::setAdditivity(bool additivity) { 240 _isAdditive = additivity; 241 } 242 getAdditivity() const243 bool Category::getAdditivity() const throw() { 244 return _isAdditive; 245 } 246 getParent()247 Category* Category::getParent() throw() { 248 return _parent; 249 } 250 getParent() const251 const Category* Category::getParent() const throw() { 252 return _parent; 253 } 254 _logUnconditionally(Priority::Value priority,const char * format,va_list arguments)255 void Category::_logUnconditionally(Priority::Value priority, 256 const char* format, 257 va_list arguments) throw() { 258 _logUnconditionally2(priority, StringUtil::vform(format, arguments)); 259 } 260 _logUnconditionally2(Priority::Value priority,const std::string & message)261 void Category::_logUnconditionally2(Priority::Value priority, 262 const std::string& message) throw() { 263 LoggingEvent event(getName(), message, NDC::get(), priority); 264 callAppenders(event); 265 } 266 isPriorityEnabled(Priority::Value priority) const267 bool Category::isPriorityEnabled(Priority::Value priority) const throw() { 268 return(getChainedPriority() >= priority); 269 } 270 log(Priority::Value priority,const char * stringFormat,...)271 void Category::log(Priority::Value priority, 272 const char* stringFormat, ...) throw() { 273 if (isPriorityEnabled(priority)) { 274 va_list va; 275 va_start(va, stringFormat); 276 _logUnconditionally(priority, stringFormat, va); 277 va_end(va); 278 } 279 } 280 log(Priority::Value priority,const std::string & message)281 void Category::log(Priority::Value priority, 282 const std::string& message) throw() { 283 if (isPriorityEnabled(priority)) 284 _logUnconditionally2(priority, message); 285 } 286 logva(Priority::Value priority,const char * stringFormat,va_list va)287 void Category::logva(Priority::Value priority, 288 const char* stringFormat, 289 va_list va) throw() { 290 if (isPriorityEnabled(priority)) { 291 _logUnconditionally(priority, stringFormat, va); 292 } 293 } 294 debug(const char * stringFormat,...)295 void Category::debug(const char* stringFormat, ...) throw() { 296 if (isPriorityEnabled(Priority::DEBUG)) { 297 va_list va; 298 va_start(va,stringFormat); 299 _logUnconditionally(Priority::DEBUG, stringFormat, va); 300 va_end(va); 301 } 302 } 303 debug(const std::string & message)304 void Category::debug(const std::string& message) throw() { 305 if (isPriorityEnabled(Priority::DEBUG)) 306 _logUnconditionally2(Priority::DEBUG, message); 307 } 308 info(const char * stringFormat,...)309 void Category::info(const char* stringFormat, ...) throw() { 310 if (isPriorityEnabled(Priority::INFO)) { 311 va_list va; 312 va_start(va,stringFormat); 313 _logUnconditionally(Priority::INFO, stringFormat, va); 314 va_end(va); 315 } 316 } 317 info(const std::string & message)318 void Category::info(const std::string& message) throw() { 319 if (isPriorityEnabled(Priority::INFO)) 320 _logUnconditionally2(Priority::INFO, message); 321 } 322 notice(const char * stringFormat,...)323 void Category::notice(const char* stringFormat, ...) throw() { 324 if (isPriorityEnabled(Priority::NOTICE)) { 325 va_list va; 326 va_start(va,stringFormat); 327 _logUnconditionally(Priority::NOTICE, stringFormat, va); 328 va_end(va); 329 } 330 } 331 notice(const std::string & message)332 void Category::notice(const std::string& message) throw() { 333 if (isPriorityEnabled(Priority::NOTICE)) 334 _logUnconditionally2(Priority::NOTICE, message); 335 } 336 warn(const char * stringFormat,...)337 void Category::warn(const char* stringFormat, ...) throw() { 338 if (isPriorityEnabled(Priority::WARN)) { 339 va_list va; 340 va_start(va,stringFormat); 341 _logUnconditionally(Priority::WARN, stringFormat, va); 342 va_end(va); 343 } 344 } 345 warn(const std::string & message)346 void Category::warn(const std::string& message) throw() { 347 if (isPriorityEnabled(Priority::WARN)) 348 _logUnconditionally2(Priority::WARN, message); 349 } 350 error(const char * stringFormat,...)351 void Category::error(const char* stringFormat, ...) throw() { 352 if (isPriorityEnabled(Priority::ERROR)) { 353 va_list va; 354 va_start(va,stringFormat); 355 _logUnconditionally(Priority::ERROR, stringFormat, va); 356 va_end(va); 357 } 358 } 359 error(const std::string & message)360 void Category::error(const std::string& message) throw() { 361 if (isPriorityEnabled(Priority::ERROR)) 362 _logUnconditionally2(Priority::ERROR, message); 363 } 364 crit(const char * stringFormat,...)365 void Category::crit(const char* stringFormat, ...) throw() { 366 if (isPriorityEnabled(Priority::CRIT)) { 367 va_list va; 368 va_start(va,stringFormat); 369 _logUnconditionally(Priority::CRIT, stringFormat, va); 370 va_end(va); 371 } 372 } 373 crit(const std::string & message)374 void Category::crit(const std::string& message) throw() { 375 if (isPriorityEnabled(Priority::CRIT)) 376 _logUnconditionally2(Priority::CRIT, message); 377 } 378 alert(const char * stringFormat,...)379 void Category::alert(const char* stringFormat, ...) throw() { 380 if (isPriorityEnabled(Priority::ALERT)) { 381 va_list va; 382 va_start(va,stringFormat); 383 _logUnconditionally(Priority::ALERT, stringFormat, va); 384 va_end(va); 385 } 386 } 387 alert(const std::string & message)388 void Category::alert(const std::string& message) throw() { 389 if (isPriorityEnabled(Priority::ALERT)) 390 _logUnconditionally2(Priority::ALERT, message); 391 } 392 emerg(const char * stringFormat,...)393 void Category::emerg(const char* stringFormat, ...) throw() { 394 if (isPriorityEnabled(Priority::EMERG)) { 395 va_list va; 396 va_start(va,stringFormat); 397 _logUnconditionally(Priority::EMERG, stringFormat, va); 398 va_end(va); 399 } 400 } 401 emerg(const std::string & message)402 void Category::emerg(const std::string& message) throw() { 403 if (isPriorityEnabled(Priority::EMERG)) 404 _logUnconditionally2(Priority::EMERG, message); 405 } 406 fatal(const char * stringFormat,...)407 void Category::fatal(const char* stringFormat, ...) throw() { 408 if (isPriorityEnabled(Priority::FATAL)) { 409 va_list va; 410 va_start(va,stringFormat); 411 _logUnconditionally(Priority::FATAL, stringFormat, va); 412 va_end(va); 413 } 414 } 415 fatal(const std::string & message)416 void Category::fatal(const std::string& message) throw() { 417 if (isPriorityEnabled(Priority::FATAL)) 418 _logUnconditionally2(Priority::FATAL, message); 419 } 420 getStream(Priority::Value priority)421 CategoryStream Category::getStream(Priority::Value priority) { 422 return CategoryStream(*this, isPriorityEnabled(priority) ? 423 priority : Priority::NOTSET); 424 } 425 operator <<(Priority::Value priority)426 CategoryStream Category::operator<<(Priority::Value priority) { 427 return getStream(priority); 428 } 429 } 430 431