ceki 2003/06/03 13:30:56 Modified: src/java/org/apache/log4j Category.java Log: Modified the Category implementation to use ReaderWrtierLock. Revision Changes Path 1.74 +110 -74 jakarta-log4j/src/java/org/apache/log4j/Category.java Index: Category.java =================================================================== RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/Category.java,v retrieving revision 1.73 retrieving revision 1.74 diff -u -r1.73 -r1.74 --- Category.java 22 May 2003 21:26:24 -0000 1.73 +++ Category.java 3 Jun 2003 20:30:56 -0000 1.74 @@ -65,6 +65,7 @@ import org.apache.log4j.helpers.AppenderAttachableImpl; import org.apache.log4j.helpers.NullEnumeration; +import org.apache.log4j.helpers.ReaderWriterLock; import org.apache.log4j.spi.AppenderAttachable; import org.apache.log4j.spi.LoggerRepository; import org.apache.log4j.spi.LoggingEvent; @@ -78,7 +79,7 @@ * <font color="#AA2222"><b>This class has been deprecated and replaced by the * [EMAIL PROTECTED] Logger}<em>subclass</em>.</b></font> It will be kept around to * preserve backward compatibility until mid 2003. - * + * * <p> * <code>Logger</code> is a subclass of Category, i.e. it extends Category. In * other words, a logger <em>is</em> a category. Thus, all operations that @@ -87,7 +88,7 @@ * Logger object. However, methods that previously accepted category objects * still continue to accept category objects. * </p> - * + * * <p> * For example, the following are all legal and will work as expected. * <pre> @@ -97,17 +98,17 @@ * Logger logger = Logger.getLogger("foo.bar") * </pre> * </p> - * + * * <p> * The first form is deprecated and should be avoided. * </p> - * + * * <p> * <b>There is absolutely no need for new client code to use or refer to the * <code>Category</code> class.</b> Whenever possible, please avoid referring * to it or using it. * </p> - * + * * <p> * See the <a href="../../../../manual.html">short manual</a> for an * introduction on this class. @@ -150,6 +151,7 @@ */ protected volatile Category parent; protected ResourceBundle resourceBundle; + protected ReaderWriterLock lock; // Categories need to know what Hierarchy they are in protected LoggerRepository repository; @@ -168,7 +170,7 @@ /** * This constructor created a new <code>Category</code> instance and sets * its name. - * + * * <p> * It is intended to be used by sub-classes only. You should not create * categories directly. @@ -178,30 +180,37 @@ */ protected Category(String name) { this.name = name; + lock = new ReaderWriterLock(); } /** * Add <code>newAppender</code> to the list of appenders of this Category * instance. - * + * * <p> * If <code>newAppender</code> is already in the list of appenders, then it * won't be added again. * </p> */ - public synchronized void addAppender(Appender newAppender) { + public void addAppender(Appender newAppender) { + // BEGIN - WRITE LOCK + lock.getWriteLock(); + if (aai == null) { aai = new AppenderAttachableImpl(); } aai.addAppender(newAppender); + lock.releaseWriteLock(); + + // END - WRITE LOCK repository.fireAddAppenderEvent((Logger) this, newAppender); } /** * If <code>assertion</code> parameter is <code>false</code>, then logs * <code>msg</code> as an [EMAIL PROTECTED] #error(Object) error} statement. - * + * * <p> * The <code>assert</code> method has been renamed to <code>assertLog</code> * because <code>assert</code> is a language reserved word in JDK 1.4. @@ -221,7 +230,7 @@ /** * Call the appenders in the hierrachy starting at <code>this</code>. If no * appenders could be found, emit a warning. - * + * * <p> * This method calls all the appenders inherited from the hierarchy * circumventing any evaluation of whether to log or not to log the @@ -234,16 +243,20 @@ int writes = 0; for (Category c = this; c != null; c = c.parent) { - // Protected against simultaneous call to addAppender, removeAppender,... - synchronized (c) { + try { + // Protect against simultaneous writes operations such as + // addAppender, removeAppender,... + c.lock.getReadLock(); + if (c.aai != null) { writes += c.aai.appendLoopOnAppenders(event); } - - if (!c.additive) { - break; - } - } + } finally { + c.lock.releaseReadLock(); + } + if (!c.additive) { + break; + } } if (writes == 0) { @@ -257,7 +270,7 @@ * * @since 1.0 */ - synchronized void closeNestedAppenders() { + void closeNestedAppenders() { Enumeration enum = this.getAllAppenders(); if (enum != null) { @@ -273,7 +286,7 @@ /** * Log a message object with the [EMAIL PROTECTED] Level#DEBUG DEBUG} level. - * + * * <p> * This method first checks if this category is <code>DEBUG</code> enabled * by comparing the level of this category with the [EMAIL PROTECTED] Level#DEBUG @@ -284,7 +297,7 @@ * also higher in the hierarchy depending on the value of the additivity * flag. * </p> - * + * * <p> * <b>WARNING</b> Note that passing a [EMAIL PROTECTED] Throwable} to this method will * print the name of the <code>Throwable</code> but no stack trace. To @@ -307,7 +320,7 @@ /** * Log a message object with the <code>DEBUG</code> level including the * stack trace of the [EMAIL PROTECTED] Throwable}<code>t</code> passed as parameter. - * + * * <p> * See [EMAIL PROTECTED] #debug(Object)} form for more detailed information. * </p> @@ -327,7 +340,7 @@ /** * Log a message object with the [EMAIL PROTECTED] Level#ERROR ERROR} Level. - * + * * <p> * This method first checks if this category is <code>ERROR</code> enabled * by comparing the level of this category with [EMAIL PROTECTED] Level#ERROR ERROR} @@ -337,7 +350,7 @@ * call all the registered appenders in this category and also higher in * the hierarchy depending on the value of the additivity flag. * </p> - * + * * <p> * <b>WARNING</b> Note that passing a [EMAIL PROTECTED] Throwable} to this method will * print the name of the <code>Throwable</code> but no stack trace. To @@ -360,7 +373,7 @@ /** * Log a message object with the <code>ERROR</code> level including the * stack trace of the [EMAIL PROTECTED] Throwable}<code>t</code> passed as parameter. - * + * * <p> * See [EMAIL PROTECTED] #error(Object)} form for more detailed information. * </p> @@ -391,7 +404,7 @@ /** * Log a message object with the [EMAIL PROTECTED] Level#FATAL FATAL} Level. - * + * * <p> * This method first checks if this category is <code>FATAL</code> enabled * by comparing the level of this category with [EMAIL PROTECTED] Level#FATAL FATAL} @@ -401,7 +414,7 @@ * call all the registered appenders in this category and also higher in * the hierarchy depending on the value of the additivity flag. * </p> - * + * * <p> * <b>WARNING</b> Note that passing a [EMAIL PROTECTED] Throwable} to this method will * print the name of the Throwable but no stack trace. To print a stack @@ -423,7 +436,7 @@ /** * Log a message object with the <code>FATAL</code> level including the * stack trace of the [EMAIL PROTECTED] Throwable}<code>t</code> passed as parameter. - * + * * <p> * See [EMAIL PROTECTED] #fatal(Object)} for more detailed information. * </p> @@ -464,34 +477,41 @@ * * @return Enumeration An enumeration of the appenders in this category. */ - public synchronized Enumeration getAllAppenders() { + public Enumeration getAllAppenders() { + Enumeration result; + lock.getReadLock(); if (aai == null) { - return NullEnumeration.getInstance(); + result = NullEnumeration.getInstance(); } else { - return aai.getAllAppenders(); + result = aai.getAllAppenders(); } + return result; } /** * Look for the appender named as <code>name</code>. - * + * * <p> * Return the appender with that name if in the list. Return * <code>null</code> otherwise. * </p> */ - public synchronized Appender getAppender(String name) { + public Appender getAppender(String name) { + lock.getReadLock(); if ((aai == null) || (name == null)) { return null; } - - return aai.getAppender(name); + + Appender appender = aai.getAppender(name); + lock.releaseReadLock(); + + return appender; } /** * Starting from this category, search the category hierarchy for a non-null * level and return it. Otherwise, return the level of the root category. - * + * * <p> * The Category class is designed so that this method executes as quickly as * possible. @@ -523,7 +543,7 @@ /** * Returns all the currently defined categories in the default hierarchy as * an [EMAIL PROTECTED] java.util.Enumeration Enumeration}. - * + * * <p> * The root category is <em>not</em> included in the returned [EMAIL PROTECTED] * Enumeration}. @@ -604,7 +624,7 @@ /** * Returns the parent of this category. Note that the parent of a given * category may change during the lifetime of the category. - * + * * <p> * The root category will return <code>null</code>. * </p> @@ -633,12 +653,12 @@ /** * Return the root of the default category hierrachy. - * + * * <p> * The root category is always instantiated and available. It's name is * "root". * </p> - * + * * <p> * Nevertheless, calling [EMAIL PROTECTED] #getInstance Category.getInstance("root")} * does not retrieve the root category but a category just under root named @@ -651,7 +671,7 @@ /** * Return the <em>inherited</em>[EMAIL PROTECTED] ResourceBundle} for this category. - * + * * <p> * This method walks the hierarchy to find the appropriate resource bundle. * It will return the resource bundle attached to the closest ancestor of @@ -676,7 +696,7 @@ * Returns the string resource coresponding to <code>key</code> in this * category's inherited resource bundle. See also [EMAIL PROTECTED] * #getResourceBundle}. - * + * * <p> * If the resource cannot be found, then an [EMAIL PROTECTED] #error error} message * will be logged complaining about the missing resource. @@ -706,7 +726,7 @@ /** * Log a message object with the [EMAIL PROTECTED] Level#INFO INFO} Level. - * + * * <p> * This method first checks if this category is <code>INFO</code> enabled by * comparing the level of this category with [EMAIL PROTECTED] Level#INFO INFO} Level. @@ -716,7 +736,7 @@ * call all the registered appenders in this category and also higher in * the hierarchy depending on the value of the additivity flag. * </p> - * + * * <p> * <b>WARNING</b> Note that passing a [EMAIL PROTECTED] Throwable} to this method will * print the name of the Throwable but no stack trace. To print a stack @@ -738,7 +758,7 @@ /** * Log a message object with the <code>INFO</code> level including the stack * trace of the [EMAIL PROTECTED] Throwable}<code>t</code> passed as parameter. - * + * * <p> * See [EMAIL PROTECTED] #info(Object)} for more detailed information. * </p> @@ -760,42 +780,49 @@ * Is the appender passed as parameter attached to this category? */ public boolean isAttached(Appender appender) { + boolean result; + + lock.getReadLock(); + if ((appender == null) || (aai == null)) { - return false; + result = false; } else { - return aai.isAttached(appender); + result = aai.isAttached(appender); } + + lock.releaseReadLock(); + return result; } /** * Check whether this category is enabled for the <code>DEBUG</code> Level. - * + * * <p> * This function is intended to lessen the computational cost of disabled * log debug statements. * </p> - * + * * <p> * For some <code>cat</code> Category object, when you write, * <pre> * cat.debug("This is entry number: " + i ); * </pre> * </p> - * + * * <p> * You incur the cost constructing the message, concatenatiion in this case, * regardless of whether the message is logged or not. * </p> - * + * * <p> * If you are worried about speed, then you should write * <pre> - * if(cat.isDebugEnabled()) { - * cat.debug("This is entry number: " + i ); - * } + * if(cat.isDebugEnabled()) { + * cat.debug("This is entry number: " + i ); + * } * </pre> * </p> - * + * * <p> * This way you will not incur the cost of parameter construction if * debugging is disabled for <code>cat</code>. On the other hand, if the @@ -951,26 +978,32 @@ * <p>Removed appenders are closed.</p> * <p>This is useful when re-reading configuration information.</p> */ - public synchronized void removeAllAppenders() { + public void removeAllAppenders() { + lock.getWriteLock(); + if (aai != null) { aai.removeAllAppenders(); aai = null; } + lock.releaseWriteLock(); } /** * Remove the appender passed as parameter form the list of appenders. - * + * * <p>Does <em>not</em> close the appender.</p> - * + * * @since 0.8.2 */ - public synchronized void removeAppender(Appender appender) { + public void removeAppender(Appender appender) { + lock.getWriteLock(); + if ((appender == null) || (aai == null)) { - return; + // Nothing to do + } else { + aai.removeAppender(appender); } - - aai.removeAppender(appender); + lock.releaseWriteLock(); } /** @@ -981,12 +1014,15 @@ * * @since 0.8.2 */ - public synchronized void removeAppender(String name) { + public void removeAppender(String name) { + lock.getWriteLock(); + if ((name == null) || (aai == null)) { - return; + // nothing to do + } else { + aai.removeAppender(name); } - - aai.removeAppender(name); + lock.releaseWriteLock(); } /** @@ -1011,12 +1047,12 @@ * <code>Level.DEBUG</code>, <code>Level.INFO</code>, * <code>Level.WARN</code>, <code>Level.ERROR</code>, * <code>Level.FATAL</code> as a parameter, you need to case them as Level. - * + * * <p> * As in * <pre> logger.setLevel((Level) Level.DEBUG); </pre> * </p> - * + * * <p> * Null values are admitted. * </p> @@ -1027,7 +1063,7 @@ /** * Set the level of this Category. - * + * * <p> * Null values are admitted. * </p> @@ -1052,13 +1088,13 @@ /** * Calling this method will <em>safely</em> close and remove all appenders * in all the categories including root contained in the default hierachy. - * + * * <p> * Some appenders such as [EMAIL PROTECTED] org.apache.log4j.net.SocketAppender} and * [EMAIL PROTECTED] AsyncAppender} need to be closed before the application exists. * Otherwise, pending logging events might be lost. * </p> - * + * * <p> * The <code>shutdown</code> method is careful to close nested appenders * before closing regular appenders. This is allows configurations where a @@ -1075,7 +1111,7 @@ /** * Log a message object with the [EMAIL PROTECTED] Level#WARN WARN} Level. - * + * * <p> * This method first checks if this category is <code>WARN</code> enabled by * comparing the level of this category with [EMAIL PROTECTED] Level#WARN WARN} Level. @@ -1085,13 +1121,13 @@ * call all the registered appenders in this category and also higher in * the hieararchy depending on the value of the additivity flag. * </p> - * + * * <p> * <b>WARNING</b> Note that passing a [EMAIL PROTECTED] Throwable} to this method will * print the name of the Throwable but no stack trace. To print a stack * trace use the [EMAIL PROTECTED] #warn(Object, Throwable)} form instead. * </p> - * + * * <p></p> * * @param message the message object to log. @@ -1109,7 +1145,7 @@ /** * Log a message with the <code>WARN</code> level including the stack trace * of the [EMAIL PROTECTED] Throwable}<code>t</code> passed as parameter. - * + * * <p> * See [EMAIL PROTECTED] #warn(Object)} for more detailed information. * </p>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]