1 // -*- C++ -*- 2 // Module: Log4CPLUS 3 // File: hierarchy.h 4 // Created: 6/2001 5 // Author: Tad E. Smith 6 // 7 // 8 // Copyright 2001-2013 Tad E. Smith 9 // 10 // Licensed under the Apache License, Version 2.0 (the "License"); 11 // you may not use this file except in compliance with the License. 12 // You may obtain a copy of the License at 13 // 14 // http://www.apache.org/licenses/LICENSE-2.0 15 // 16 // Unless required by applicable law or agreed to in writing, software 17 // distributed under the License is distributed on an "AS IS" BASIS, 18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 // See the License for the specific language governing permissions and 20 // limitations under the License. 21 22 /** @file */ 23 24 #ifndef LOG4CPLUS_HIERARCHY_HEADER_ 25 #define LOG4CPLUS_HIERARCHY_HEADER_ 26 27 #include <log4cplus/config.hxx> 28 29 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) 30 #pragma once 31 #endif 32 33 #include <log4cplus/logger.h> 34 #include <log4cplus/thread/syncprims.h> 35 #include <map> 36 #include <memory> 37 #include <vector> 38 39 40 namespace log4cplus { 41 // Forward Declarations 42 class HierarchyLocker; 43 44 /** 45 * This class is specialized in retrieving loggers by name and 46 * also maintaining the logger hierarchy. 47 * 48 * <em>The casual user should not have to deal with this class 49 * directly.</em> However, if you are in an environment where 50 * multiple applications run in the same process, then read on. 51 * 52 * The structure of the logger hierarchy is maintained by the 53 * {@link #getInstance} method. The hierarchy is such that children 54 * link to their parent but parents do not have any pointers to their 55 * children. Moreover, loggers can be instantiated in any order, in 56 * particular descendant before ancestor. 57 * 58 * In case a descendant is created before a particular ancestor, 59 * then it creates a provision node for the ancestor and adds itself 60 * to the provision node. Other descendants of the same ancestor add 61 * themselves to the previously created provision node. 62 */ 63 class LOG4CPLUS_EXPORT Hierarchy 64 { 65 public: 66 // DISABLE_OFF should be set to a value lower than all possible 67 // priorities. 68 static const LogLevel DISABLE_OFF; 69 static const LogLevel DISABLE_OVERRIDE; 70 71 // Ctors 72 /** 73 * Create a new Logger hierarchy. 74 */ 75 Hierarchy(); 76 77 // Dtor 78 virtual ~Hierarchy(); 79 80 // Methods 81 /** 82 * This call will clear all logger definitions from the internal 83 * hashtable. Invoking this method will irrevocably mess up the 84 * logger hierarchy. 85 * 86 * You should <em>really</em> know what you are doing before 87 * invoking this method. 88 */ 89 virtual void clear(); 90 91 /** 92 * Returns <code>true </code>if the named logger exists 93 * (in the default hierarchy). 94 * 95 * @param name The name of the logger to search for. 96 */ 97 virtual bool exists(const log4cplus::tstring& name); 98 99 /** 100 * Similar to {@link #disable(LogLevel)} except that the LogLevel 101 * argument is given as a log4cplus::tstring. 102 */ 103 virtual void disable(const log4cplus::tstring& loglevelStr); 104 105 /** 106 * Disable all logging requests of LogLevel <em>equal to or 107 * below</em> the ll parameter <code>p</code>, for 108 * <em>all</em> loggers in this hierarchy. Logging requests of 109 * higher LogLevel then <code>p</code> remain unaffected. 110 * 111 * Nevertheless, if the 112 * BasicConfigurator::DISABLE_OVERRIDE_KEY property is set to 113 * true, then logging requests are evaluated as usual. 114 * 115 * The "disable" family of methods are there for speed. They 116 * allow printing methods such as debug, info, etc. to return 117 * immediately after an integer comparison without walking the 118 * logger hierarchy. In most modern computers an integer 119 * comparison is measured in nanoseconds where as a logger walk is 120 * measured in units of microseconds. 121 */ 122 virtual void disable(LogLevel ll); 123 124 /** 125 * Disable all logging requests regardless of logger and LogLevel. 126 * This method is equivalent to calling {@link #disable} with the 127 * argument FATAL_LOG_LEVEL, the highest possible LogLevel. 128 */ 129 virtual void disableAll(); 130 131 /** 132 * Disable all Debug logging requests regardless of logger. 133 * This method is equivalent to calling {@link #disable} with the 134 * argument DEBUG_LOG_LEVEL. 135 */ 136 virtual void disableDebug(); 137 138 /** 139 * Disable all Info logging requests regardless of logger. 140 * This method is equivalent to calling {@link #disable} with the 141 * argument INFO_LOG_LEVEL. 142 */ 143 virtual void disableInfo(); 144 145 /** 146 * Undoes the effect of calling any of {@link #disable}, {@link 147 * #disableAll}, {@link #disableDebug} and {@link #disableInfo} 148 * methods. More precisely, invoking this method sets the Logger 149 * class internal variable called <code>disable</code> to its 150 * default "off" value. 151 */ 152 virtual void enableAll(); 153 154 /** 155 * Return a new logger instance named as the first parameter using 156 * the default factory. 157 * 158 * If a logger of that name already exists, then it will be 159 * returned. Otherwise, a new logger will be instantiated and 160 * then linked with its existing ancestors as well as children. 161 * 162 * @param name The name of the logger to retrieve. 163 */ 164 virtual Logger getInstance(const log4cplus::tstring& name); 165 166 /** 167 * Return a new logger instance named as the first parameter using 168 * <code>factory</code>. 169 * 170 * If a logger of that name already exists, then it will be 171 * returned. Otherwise, a new logger will be instantiated by the 172 * <code>factory</code> parameter and linked with its existing 173 * ancestors as well as children. 174 * 175 * @param name The name of the logger to retrieve. 176 * @param factory The factory that will make the new logger instance. 177 */ 178 virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); 179 180 /** 181 * Returns all the currently defined loggers in this hierarchy. 182 * 183 * The root logger is <em>not</em> included in the returned list. 184 */ 185 virtual LoggerList getCurrentLoggers(); 186 187 /** 188 * Is the LogLevel specified by <code>level</code> enabled? 189 */ 190 virtual bool isDisabled(LogLevel level); 191 192 /** 193 * Get the root of this hierarchy. 194 */ 195 virtual Logger getRoot() const; 196 197 /** 198 * Reset all values contained in this hierarchy instance to their 199 * default. This removes all appenders from all loggers, sets 200 * the LogLevel of all non-root loggers to <code>NOT_SET_LOG_LEVEL</code>, 201 * sets their additivity flag to <code>true</code> and sets the LogLevel 202 * of the root logger to DEBUG_LOG_LEVEL. Moreover, message disabling 203 * is set its default "off" value. 204 * 205 * Existing loggers are not removed. They are just reset. 206 * 207 * This method should be used sparingly and with care as it will 208 * block all logging until it is completed.</p> 209 */ 210 virtual void resetConfiguration(); 211 212 /** 213 * Set the default LoggerFactory instance. 214 */ 215 virtual void setLoggerFactory(std::auto_ptr<spi::LoggerFactory> factory); 216 217 /** 218 * Returns the default LoggerFactory instance. 219 */ 220 virtual spi::LoggerFactory* getLoggerFactory(); 221 222 /** 223 * Shutting down a hierarchy will <em>safely</em> close and remove 224 * all appenders in all loggers including the root logger. 225 * 226 * Some appenders such as SocketAppender need to be closed before the 227 * application exits. Otherwise, pending logging events might be 228 * lost. 229 * 230 * The <code>shutdown</code> method is careful to close nested 231 * appenders before closing regular appenders. This is allows 232 * configurations where a regular appender is attached to a logger 233 * and again to a nested appender. 234 */ 235 virtual void shutdown(); 236 237 private: 238 // Types 239 typedef std::vector<Logger> ProvisionNode; 240 typedef std::map<log4cplus::tstring, ProvisionNode> ProvisionNodeMap; 241 typedef std::map<log4cplus::tstring, Logger> LoggerMap; 242 243 // Methods 244 /** 245 * This is the implementation of the <code>getInstance()</code> method. 246 * NOTE: This method does not lock the <code>hashtable_mutex</code>. 247 */ 248 LOG4CPLUS_PRIVATE 249 virtual Logger getInstanceImpl(const log4cplus::tstring& name, 250 spi::LoggerFactory& factory); 251 252 /** 253 * This is the implementation of the <code>getCurrentLoggers()</code>. 254 * NOTE: This method does not lock the <code>hashtable_mutex</code>. 255 */ 256 LOG4CPLUS_PRIVATE 257 virtual void initializeLoggerList(LoggerList& list) const; 258 259 /** 260 * This method loops through all the *potential* parents of 261 * logger'. There 3 possible cases: 262 * 263 * 1) No entry for the potential parent of 'logger' exists 264 * 265 * We create a ProvisionNode for this potential parent and insert 266 * 'logger' in that provision node. 267 * 268 * 2) There is an entry of type Logger for the potential parent. 269 * 270 * The entry is 'logger's nearest existing parent. We update logger's 271 * parent field with this entry. We also break from the loop 272 * because updating our parent's parent is our parent's 273 * responsibility. 274 * 275 * 3) There entry is of type ProvisionNode for this potential parent. 276 * 277 * We add 'logger' to the list of children for this potential parent. 278 */ 279 LOG4CPLUS_PRIVATE void updateParents(Logger const & logger); 280 281 /** 282 * We update the links for all the children that placed themselves 283 * in the provision node 'pn'. The second argument 'logger' is a 284 * reference for the newly created Logger, parent of all the 285 * children in 'pn' 286 * 287 * We loop on all the children 'c' in 'pn': 288 * 289 * If the child 'c' has been already linked to a child of 290 * 'logger' then there is no need to update 'c'. 291 * 292 * Otherwise, we set logger's parent field to c's parent and set 293 * c's parent field to logger. 294 */ 295 LOG4CPLUS_PRIVATE void updateChildren(ProvisionNode& pn, 296 Logger const & logger); 297 298 // Data 299 thread::Mutex hashtable_mutex; 300 std::auto_ptr<spi::LoggerFactory> defaultFactory; 301 ProvisionNodeMap provisionNodes; 302 LoggerMap loggerPtrs; 303 Logger root; 304 305 int disableValue; 306 307 bool emittedNoAppenderWarning; 308 309 // Disallow copying of instances of this class 310 Hierarchy(const Hierarchy&); 311 Hierarchy& operator=(const Hierarchy&); 312 313 // Friends 314 friend class log4cplus::spi::LoggerImpl; 315 friend class log4cplus::HierarchyLocker; 316 }; 317 318 319 LOG4CPLUS_EXPORT Hierarchy & getDefaultHierarchy (); 320 321 322 } // end namespace log4cplus 323 324 #endif // LOG4CPLUS_HIERARCHY_HEADER_ 325 326