You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
12 KiB

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