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