[jboss-svn-commits] JBoss Common SVN: r4812 - in jboss-logmanager/trunk: src/main/java/org/jboss/logmanager and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Jul 29 17:41:20 EDT 2010


Author: david.lloyd at jboss.com
Date: 2010-07-29 17:41:19 -0400 (Thu, 29 Jul 2010)
New Revision: 4812

Modified:
   jboss-logmanager/trunk/pom.xml
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggerNode.java
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggingMXBeanImpl.java
Log:
Attempt to fix JBLOGGING-44 by decoupling Logger instances from the LoggerNode tree, at the price of eliminating duplicate logger folding.

Modified: jboss-logmanager/trunk/pom.xml
===================================================================
--- jboss-logmanager/trunk/pom.xml	2010-07-29 20:58:23 UTC (rev 4811)
+++ jboss-logmanager/trunk/pom.xml	2010-07-29 21:41:19 UTC (rev 4812)
@@ -33,6 +33,12 @@
     <packaging>jar</packaging>
     <version>1.2.0.CR4-SNAPSHOT</version>
 
+    <parent>
+        <groupId>org.jboss</groupId>
+        <artifactId>jboss-parent</artifactId>
+        <version>5</version>
+    </parent>
+
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
@@ -50,26 +56,10 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>2.0.2</version>
-                <configuration>
-                    <source>1.5</source>
-                    <target>1.5</target>
-                </configuration>
             </plugin>
             <plugin>
                 <artifactId>maven-source-plugin</artifactId>
-                <version>2.1.1</version>
-                <executions>
-                    <execution>
-                        <id>attach-sources</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
             </plugin>
             <plugin>
                 <artifactId>maven-surefire-plugin</artifactId>
@@ -81,30 +71,12 @@
             </plugin>
             <plugin>
                 <artifactId>maven-enforcer-plugin</artifactId>
-                <version>1.0-beta-1</version>
-                <executions>
-                    <execution>
-                        <id>enforce-maven-environment</id>
-                        <goals>
-                            <goal>enforce</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <rules>
-                        <requireJavaVersion>
-                            <version>1.6.0</version>
-                        </requireJavaVersion>
-                    </rules>
-                </configuration>
             </plugin>
         </plugins>
-        <finalName>jboss-logmanager</finalName>
     </build>
     <reporting>
         <plugins>
             <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
                 <version>2.6.1</version>
                 <configuration>
@@ -125,11 +97,4 @@
             </plugin>
         </plugins>
     </reporting>
-    <distributionManagement>
-        <repository>
-            <id>repository.jboss.org</id>
-            <name>JBoss Maven2 Repository</name>
-            <url>http://repository.jboss.org/maven2</url>
-        </repository>
-    </distributionManagement>
 </project>

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java	2010-07-29 20:58:23 UTC (rev 4811)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LogContext.java	2010-07-29 21:41:19 UTC (rev 4812)
@@ -119,22 +119,10 @@
      * @see java.util.logging.LogManager#getLogger(String)
      */
     public Logger getLogger(String name) {
-        return rootLogger.getOrCreate(name).getOrCreateLogger();
+        return rootLogger.getOrCreate(name).createLogger();
     }
 
     /**
-     * Get a logger with the given name from this logging context if it already exists.  If no logger of the given
-     * name currently exists, {@code null} is returned.
-     *
-     * @param name the logger name
-     * @return the logger instance, or {@code null} if none exists with the given name
-     */
-    public Logger getLoggerIfExists(String name) {
-        final LoggerNode node = rootLogger.getIfExists(name);
-        return node == null ? null : node.getLogger();
-    }
-
-    /**
      * Get the {@code LoggingMXBean} associated with this log context.
      *
      * @return the {@code LoggingMXBean} instance

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java	2010-07-29 20:58:23 UTC (rev 4811)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/Logger.java	2010-07-29 21:41:19 UTC (rev 4812)
@@ -25,12 +25,6 @@
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.util.ResourceBundle;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import java.util.concurrent.locks.Lock;
 
 import java.util.logging.Filter;
 import java.util.logging.Handler;
@@ -50,38 +44,6 @@
      */
     private final LoggerNode loggerNode;
 
-    /**
-     * The handlers for this logger.  May only be updated using the {@link #handlersUpdater} atomic updater.  The array
-     * instance should not be modified (treat as immutable).
-     */
-    @SuppressWarnings({ "UnusedDeclaration" })
-    private volatile Handler[] handlers;
-
-    /**
-     * Flag to specify whether parent handlers are used.
-     */
-    private volatile boolean useParentHandlers = true;
-
-    /**
-     * The filter for this logger instance.
-     */
-    private volatile Filter filter;
-
-    /**
-     * The attachments map.
-     */
-    private volatile Map<AttachmentKey, Object> attachments = Collections.emptyMap();
-
-    /**
-     * The atomic updater for the {@link #handlers} field.
-     */
-    private static final AtomicArray<Logger, Handler> handlersUpdater = AtomicArray.create(AtomicReferenceFieldUpdater.newUpdater(Logger.class, Handler[].class, "handlers"), Handler.class);
-
-    /**
-     * The atomic updater for the {@link #attachments} field.
-     */
-    private static final AtomicReferenceFieldUpdater<Logger, Map> attachmentsUpdater = AtomicReferenceFieldUpdater.newUpdater(Logger.class, Map.class, "attachments");
-
     private static final String LOGGER_CLASS_NAME = Logger.class.getName();
 
     /**
@@ -127,7 +89,6 @@
         // We maintain our own level
         super.setLevel(Level.ALL);
         this.loggerNode = loggerNode;
-        handlersUpdater.clear(this);
     }
 
     // Serialization
@@ -141,61 +102,24 @@
     /** {@inheritDoc} */
     public void setFilter(Filter filter) throws SecurityException {
         LogContext.checkAccess();
-        this.filter = filter;
+        loggerNode.setFilter(filter);
     }
 
     /** {@inheritDoc} */
     public Filter getFilter() {
-        return filter;
+        return loggerNode.getFilter();
     }
 
     // Level mgmt
 
     /**
-     * The actual level.  May only be modified when the logmanager's level change lock is held; in addition, changing
-     * this field must be followed immediately by recursively updating the effective loglevel of the child tree.
-     */
-    private volatile Level level;
-    /**
-     * The effective level.  May only be modified when the logmanager's level change lock is held; in addition, changing
-     * this field must be followed immediately by recursively updating the effective loglevel of the child tree.
-     */
-    private volatile int effectiveLevel = INFO_INT;
-
-    /**
      * {@inheritDoc}  This implementation grabs a lock, so that only one thread may update the log level of any
      * logger at a time, in order to allow readers to never block (though there is a window where retrieving the
      * log level reflects an older effective level than the actual level).
      */
     public void setLevel(Level newLevel) throws SecurityException {
         LogContext.checkAccess();
-        final LogContext context = loggerNode.getContext();
-        final Lock lock = context.treeLock;
-        lock.lock();
-        try {
-            final int oldEffectiveLevel = effectiveLevel;
-            final int newEffectiveLevel;
-            if (newLevel != null) {
-                level = newLevel;
-                newEffectiveLevel = newLevel.intValue();
-            } else {
-                final Logger parent = (Logger) getParent();
-                if (parent == null) {
-                    level = Level.INFO;
-                    newEffectiveLevel = INFO_INT;
-                } else {
-                    level = null;
-                    newEffectiveLevel = parent.effectiveLevel;
-                }
-            }
-            effectiveLevel = newEffectiveLevel;
-            if (oldEffectiveLevel != newEffectiveLevel) {
-                // our level changed, recurse down to children
-                loggerNode.updateChildEffectiveLevel(newEffectiveLevel);
-            }
-        } finally {
-            lock.unlock();
-        }
+        loggerNode.setLevel(newLevel);
     }
 
     /**
@@ -210,35 +134,22 @@
     }
 
     /**
-     * Update the effective level if it is inherited from a parent.  Must only be called while the logmanager's level
-     * change lock is held.
-     *
-     * @param newLevel the new effective level
-     */
-    void setEffectiveLevel(int newLevel) {
-        if (level == null) {
-            effectiveLevel = newLevel;
-            loggerNode.updateChildEffectiveLevel(newLevel);
-        }
-    }
-
-    /**
      * Get the effective numerical log level, inherited from the parent.
      *
      * @return the effective level
      */
     public int getEffectiveLevel() {
-        return effectiveLevel;
+        return loggerNode.getEffectiveLevel();
     }
 
     /** {@inheritDoc} */
     public Level getLevel() {
-        return level;
+        return loggerNode.getLevel();
     }
 
     /** {@inheritDoc} */
     public boolean isLoggable(Level level) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         return level.intValue() >= effectiveLevel && effectiveLevel != OFF_INT;
     }
 
@@ -253,11 +164,7 @@
      */
     @SuppressWarnings({ "unchecked" })
     public <V> V getAttachment(AttachmentKey<V> key) {
-        if (key == null) {
-            throw new NullPointerException("key is null");
-        }
-        final Map<AttachmentKey, Object> attachments = this.attachments;
-        return (V) attachments.get(key);
+        return loggerNode.getAttachment(key);
     }
 
     /**
@@ -270,29 +177,9 @@
      * @return the old attachment, if there was one
      * @throws SecurityException if a security manager exists and if the caller does not have {@code LoggingPermission(control)}
      */
-    @SuppressWarnings({ "unchecked" })
     public <V> V attach(AttachmentKey<V> key, V value) throws SecurityException {
         LogContext.checkAccess();
-        if (key == null) {
-            throw new NullPointerException("key is null");
-        }
-        if (value == null) {
-            throw new NullPointerException("value is null");
-        }
-        Map<AttachmentKey, Object> oldAttachments;
-        Map<AttachmentKey, Object> newAttachments;
-        V old;
-        do {
-            oldAttachments = attachments;
-            if (oldAttachments.isEmpty() || oldAttachments.size() == 1 && oldAttachments.containsKey(key)) {
-                old = (V) oldAttachments.get(key);
-                newAttachments = Collections.<AttachmentKey, Object>singletonMap(key, value);
-            } else {
-                newAttachments = new HashMap<AttachmentKey, Object>(oldAttachments);
-                old = (V) newAttachments.put(key, value);
-            }
-        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
-        return old;
+        return loggerNode.attach(key, value);
     }
 
     /**
@@ -308,27 +195,7 @@
     @SuppressWarnings({ "unchecked" })
     public <V> V attachIfAbsent(AttachmentKey<V> key, V value) throws SecurityException {
         LogContext.checkAccess();
-        if (key == null) {
-            throw new NullPointerException("key is null");
-        }
-        if (value == null) {
-            throw new NullPointerException("value is null");
-        }
-        Map<AttachmentKey, Object> oldAttachments;
-        Map<AttachmentKey, Object> newAttachments;
-        do {
-            oldAttachments = attachments;
-            if (oldAttachments.isEmpty()) {
-                newAttachments = Collections.<AttachmentKey, Object>singletonMap(key, value);
-            } else {
-                if (oldAttachments.containsKey(key)) {
-                    return (V) oldAttachments.get(key);
-                }
-                newAttachments = new HashMap<AttachmentKey, Object>(oldAttachments);
-                newAttachments.put(key, value);
-            }
-        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
-        return null;
+        return loggerNode.attachIfAbsent(key, value);
     }
 
     /**
@@ -342,37 +209,7 @@
     @SuppressWarnings({ "unchecked" })
     public <V> V detach(AttachmentKey<V> key) throws SecurityException {
         LogContext.checkAccess();
-        if (key == null) {
-            throw new NullPointerException("key is null");
-        }
-        Map<AttachmentKey, Object> oldAttachments;
-        Map<AttachmentKey, Object> newAttachments;
-        V result;
-        do {
-            oldAttachments = attachments;
-            result = (V) oldAttachments.get(key);
-            if (result == null) {
-                return null;
-            }
-            final int size = oldAttachments.size();
-            if (size == 1) {
-                // special case - the new map is empty
-                newAttachments = Collections.emptyMap();
-            } else if (size == 2) {
-                // special case - the new map is a singleton
-                final Iterator<Map.Entry<AttachmentKey,Object>> it = oldAttachments.entrySet().iterator();
-                // find the entry that we are not removing
-                Map.Entry<AttachmentKey, Object> entry = it.next();
-                if (entry.getKey() == key) {
-                    // must be the next one
-                    entry = it.next();
-                }
-                newAttachments = Collections.singletonMap(entry.getKey(), entry.getValue());
-            } else {
-                newAttachments = new HashMap<AttachmentKey, Object>(oldAttachments);
-            }
-        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
-        return result;
+        return loggerNode.detach(key);
     }
 
     // Handler mgmt
@@ -383,7 +220,7 @@
         if (handler == null) {
             throw new NullPointerException("handler is null");
         }
-        handlersUpdater.add(this, handler);
+        loggerNode.addHandler(handler);
     }
 
     /** {@inheritDoc} */
@@ -392,12 +229,12 @@
         if (handler == null) {
             return;
         }
-        handlersUpdater.remove(this, handler, true);
+        loggerNode.removeHandler(handler);
     }
 
     /** {@inheritDoc} */
     public Handler[] getHandlers() {
-        final Handler[] handlers = this.handlers;
+        final Handler[] handlers = loggerNode.getHandlers();
         return handlers.length > 0 ? handlers.clone() : handlers;
     }
 
@@ -408,26 +245,25 @@
      */
     public Handler[] clearHandlers() throws SecurityException {
         LogContext.checkAccess();
-        final Handler[] handlers = this.handlers;
-        handlersUpdater.clear(this);
-        return handlers.length > 0 ? handlers.clone() : handlers;
+        return loggerNode.clearHandlers();
     }
 
     /** {@inheritDoc} */
     public void setUseParentHandlers(boolean useParentHandlers) {
-        this.useParentHandlers = useParentHandlers;
+        loggerNode.setUseParentHandlers(useParentHandlers);
     }
 
     /** {@inheritDoc} */
     public boolean getUseParentHandlers() {
-        return useParentHandlers;
+        return loggerNode.getUseParentHandlers();
     }
 
     // Parent/child
 
     /** {@inheritDoc} */
     public Logger getParent() {
-        return loggerNode.getParentLogger();
+        final LoggerNode parentNode = loggerNode.getParent();
+        return parentNode == null ? null : parentNode.createLogger();
     }
 
     /**
@@ -440,19 +276,19 @@
 
     // Logger
 
-    private static final int OFF_INT = Level.OFF.intValue();
+    static final int OFF_INT = Level.OFF.intValue();
 
-    private static final int SEVERE_INT = Level.SEVERE.intValue();
-    private static final int WARNING_INT = Level.WARNING.intValue();
-    private static final int INFO_INT = Level.INFO.intValue();
-    private static final int CONFIG_INT = Level.CONFIG.intValue();
-    private static final int FINE_INT = Level.FINE.intValue();
-    private static final int FINER_INT = Level.FINER.intValue();
-    private static final int FINEST_INT = Level.FINEST.intValue();
+    static final int SEVERE_INT = Level.SEVERE.intValue();
+    static final int WARNING_INT = Level.WARNING.intValue();
+    static final int INFO_INT = Level.INFO.intValue();
+    static final int CONFIG_INT = Level.CONFIG.intValue();
+    static final int FINE_INT = Level.FINE.intValue();
+    static final int FINER_INT = Level.FINER.intValue();
+    static final int FINEST_INT = Level.FINEST.intValue();
 
     /** {@inheritDoc} */
     public void log(LogRecord record) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (record.getLevel().intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -461,7 +297,7 @@
 
     /** {@inheritDoc} */
     public void entering(final String sourceClass, final String sourceMethod) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final ExtLogRecord rec = new ExtLogRecord(Level.FINER, "ENTRY", LOGGER_CLASS_NAME);
@@ -472,7 +308,7 @@
 
     /** {@inheritDoc} */
     public void entering(final String sourceClass, final String sourceMethod, final Object param1) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final ExtLogRecord rec = new ExtLogRecord(Level.FINER, "ENTRY {0}", LOGGER_CLASS_NAME);
@@ -484,7 +320,7 @@
 
     /** {@inheritDoc} */
     public void entering(final String sourceClass, final String sourceMethod, final Object[] params) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final StringBuilder builder = new StringBuilder("ENTRY");
@@ -500,7 +336,7 @@
 
     /** {@inheritDoc} */
     public void exiting(final String sourceClass, final String sourceMethod) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final ExtLogRecord rec = new ExtLogRecord(Level.FINER, "RETURN", LOGGER_CLASS_NAME);
@@ -511,7 +347,7 @@
 
     /** {@inheritDoc} */
     public void exiting(final String sourceClass, final String sourceMethod, final Object result) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final ExtLogRecord rec = new ExtLogRecord(Level.FINER, "RETURN {0}", LOGGER_CLASS_NAME);
@@ -523,7 +359,7 @@
 
     /** {@inheritDoc} */
     public void throwing(final String sourceClass, final String sourceMethod, final Throwable thrown) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         final ExtLogRecord rec = new ExtLogRecord(Level.FINER, "THROW", LOGGER_CLASS_NAME);
@@ -535,7 +371,7 @@
 
     /** {@inheritDoc} */
     public void severe(final String msg) {
-        if (SEVERE_INT < effectiveLevel) {
+        if (SEVERE_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.SEVERE, msg, LOGGER_CLASS_NAME));
@@ -543,7 +379,7 @@
 
     /** {@inheritDoc} */
     public void warning(final String msg) {
-        if (WARNING_INT < effectiveLevel) {
+        if (WARNING_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.WARNING, msg, LOGGER_CLASS_NAME));
@@ -551,7 +387,7 @@
 
     /** {@inheritDoc} */
     public void info(final String msg) {
-        if (INFO_INT < effectiveLevel) {
+        if (INFO_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.INFO, msg, LOGGER_CLASS_NAME));
@@ -559,7 +395,7 @@
 
     /** {@inheritDoc} */
     public void config(final String msg) {
-        if (CONFIG_INT < effectiveLevel) {
+        if (CONFIG_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.CONFIG, msg, LOGGER_CLASS_NAME));
@@ -567,7 +403,7 @@
 
     /** {@inheritDoc} */
     public void fine(final String msg) {
-        if (FINE_INT < effectiveLevel) {
+        if (FINE_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.FINE, msg, LOGGER_CLASS_NAME));
@@ -575,7 +411,7 @@
 
     /** {@inheritDoc} */
     public void finer(final String msg) {
-        if (FINER_INT < effectiveLevel) {
+        if (FINER_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.FINER, msg, LOGGER_CLASS_NAME));
@@ -583,7 +419,7 @@
 
     /** {@inheritDoc} */
     public void finest(final String msg) {
-        if (FINEST_INT < effectiveLevel) {
+        if (FINEST_INT < loggerNode.getEffectiveLevel()) {
             return;
         }
         logRaw(new ExtLogRecord(Level.FINEST, msg, LOGGER_CLASS_NAME));
@@ -591,7 +427,7 @@
 
     /** {@inheritDoc} */
     public void log(final Level level, final String msg) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -600,7 +436,7 @@
 
     /** {@inheritDoc} */
     public void log(final Level level, final String msg, final Object param1) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -611,7 +447,7 @@
 
     /** {@inheritDoc} */
     public void log(final Level level, final String msg, final Object[] params) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -622,7 +458,7 @@
 
     /** {@inheritDoc} */
     public void log(final Level level, final String msg, final Throwable thrown) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -633,7 +469,7 @@
 
     /** {@inheritDoc} */
     public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -645,7 +481,7 @@
 
     /** {@inheritDoc} */
     public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Object param1) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -658,7 +494,7 @@
 
     /** {@inheritDoc} */
     public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Object[] params) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -671,7 +507,7 @@
 
     /** {@inheritDoc} */
     public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Throwable thrown) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -684,7 +520,7 @@
 
     /** {@inheritDoc} */
     public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName, final String msg) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -697,7 +533,7 @@
 
     /** {@inheritDoc} */
     public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName, final String msg, final Object param1) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -711,7 +547,7 @@
 
     /** {@inheritDoc} */
     public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName, final String msg, final Object[] params) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -725,7 +561,7 @@
 
     /** {@inheritDoc} */
     public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName, final String msg, final Throwable thrown) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -767,7 +603,7 @@
      * @param t the throwable, if any
      */
     public void log(final String fqcn, final Level level, final String message, final String bundleName, final ExtLogRecord.FormatStyle style, final Object[] params, final Throwable t) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level == null || fqcn == null || message == null || level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -789,7 +625,7 @@
      * @param t the throwable, if any
      */
     public void log(final String fqcn, final Level level, final String message, final ExtLogRecord.FormatStyle style, final Object[] params, final Throwable t) {
-        final int effectiveLevel = this.effectiveLevel;
+        final int effectiveLevel = loggerNode.getEffectiveLevel();
         if (level == null || fqcn == null || message == null || level.intValue() < effectiveLevel || effectiveLevel == OFF_INT) {
             return;
         }
@@ -831,7 +667,7 @@
             record.setResourceBundleName(bundleName);
             record.setResourceBundle(bundle);
         }
-        final Filter filter = this.filter;
+        final Filter filter = loggerNode.getFilter();
         try {
             if (filter != null && ! filter.isLoggable(record)) {
                 return;
@@ -842,21 +678,7 @@
             // todo - error handler
             // treat an errored filter as "pass" (I guess?)
         }
-        for (Logger current = this; current != null; current = current.getParent()) {
-            final Handler[] handlers = current.handlers;
-            if (handlers != null) {
-                for (Handler handler : handlers) try {
-                    handler.publish(record);
-                } catch (VirtualMachineError e) {
-                    throw e;
-                } catch (Throwable t) {
-                    // todo - error handler
-                }
-            }
-            if (! current.useParentHandlers) {
-                break;
-            }
-        }
+        loggerNode.publish(record);
     }
 
     /**

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggerNode.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggerNode.java	2010-07-29 20:58:23 UTC (rev 4811)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggerNode.java	2010-07-29 21:41:19 UTC (rev 4812)
@@ -22,13 +22,21 @@
 
 package org.jboss.logmanager;
 
-import java.lang.ref.WeakReference;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.locks.Lock;
 
+import java.util.logging.Filter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+
 /**
  * A node in the tree of logger names.  Maintains weak references to children and a strong reference to its parent.
  */
@@ -48,21 +56,54 @@
     private final String fullName;
 
     /**
-     * A weak reference to the logger instance.  Only update using {@link #loggerRefUpdater}.
+     * The map of names to child nodes.  The child node references are weak.
      */
-    private volatile LoggerRef loggerRef = null;
+    private final ConcurrentMap<String, LoggerNode> children = new CopyOnWriteWeakMap<String, LoggerNode>();
 
     /**
-     * The atomic updater for {@link #loggerRef}.
+     * The handlers for this logger.  May only be updated using the {@link #handlersUpdater} atomic updater.  The array
+     * instance should not be modified (treat as immutable).
      */
-    private static final AtomicReferenceFieldUpdater<LoggerNode, LoggerRef> loggerRefUpdater = AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, LoggerRef.class, "loggerRef");
+    @SuppressWarnings({ "UnusedDeclaration" })
+    private volatile Handler[] handlers;
 
     /**
-     * The map of names to child nodes.  The child node references are weak.
+     * Flag to specify whether parent handlers are used.
      */
-    private final ConcurrentMap<String, LoggerNode> children = new CopyOnWriteWeakMap<String, LoggerNode>();
+    private volatile boolean useParentHandlers = true;
 
     /**
+     * The filter for this logger instance.
+     */
+    private volatile Filter filter;
+
+    /**
+     * The attachments map.
+     */
+    private volatile Map<Logger.AttachmentKey, Object> attachments = Collections.emptyMap();
+
+    /**
+     * The atomic updater for the {@link #handlers} field.
+     */
+    private static final AtomicArray<LoggerNode, Handler> handlersUpdater = AtomicArray.create(AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, Handler[].class, "handlers"), Handler.class);
+
+    /**
+     * The atomic updater for the {@link #attachments} field.
+     */
+    private static final AtomicReferenceFieldUpdater<LoggerNode, Map> attachmentsUpdater = AtomicReferenceFieldUpdater.newUpdater(LoggerNode.class, Map.class, "attachments");
+
+    /**
+     * The actual level.  May only be modified when the context's level change lock is held; in addition, changing
+     * this field must be followed immediately by recursively updating the effective loglevel of the child tree.
+     */
+    private volatile java.util.logging.Level level;
+    /**
+     * The effective level.  May only be modified when the context's level change lock is held; in addition, changing
+     * this field must be followed immediately by recursively updating the effective loglevel of the child tree.
+     */
+    private volatile int effectiveLevel = Logger.INFO_INT;
+
+    /**
      * Construct a new root instance.
      *
      * @param context the logmanager
@@ -70,6 +111,7 @@
     LoggerNode(final LogContext context) {
         parent = null;
         fullName = "";
+        handlersUpdater.clear(this);
         this.context = context;
     }
 
@@ -86,6 +128,7 @@
             throw new IllegalArgumentException("nodeName is empty, or just whitespace");
         }
         this.parent = parent;
+        handlersUpdater.clear(this);
         if (parent.parent == null) {
             fullName = nodeName;
         } else {
@@ -146,30 +189,7 @@
         }
     }
 
-    /**
-     * Get or create a logger instance for this node.
-     *
-     * @return a logger instance
-     */
-    Logger getOrCreateLogger() {
-        final String fullName = this.fullName;
-        final LoggerNode parent = this.parent;
-        for (;;) {
-            final LoggerRef loggerRef = this.loggerRef;
-            if (loggerRef != null) {
-                final Logger logger = loggerRef.get();
-                if (logger != null) {
-                    return logger;
-                }
-            }
-            final Logger logger = createLogger(fullName);
-            if (loggerRefUpdater.compareAndSet(this, loggerRef, parent == null ? new StrongLoggerRef(logger) : new WeakLoggerRef(logger))) {
-                return logger;
-            }
-        }
-    }
-
-    private Logger createLogger(final String fullName) {
+    Logger createLogger() {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             return AccessController.doPrivileged(new PrivilegedAction<Logger>() {
@@ -189,16 +209,6 @@
     }
 
     /**
-     * Get a logger instance for this node.
-     *
-     * @return a logger instance
-     */
-    Logger getLogger() {
-        final LoggerRef loggerRef = this.loggerRef;
-        return loggerRef == null ? null : loggerRef.get();
-    }
-
-    /**
      * Get the children of this logger.
      *
      * @return the children
@@ -208,23 +218,6 @@
     }
 
     /**
-     * Return the logger instance of the parent logger node, or {@code null} if this is the root logger node.
-     *
-     * @return the parent logger instance, or {@code null} for none
-     */
-    Logger getParentLogger() {
-        LoggerNode node = parent;
-        while (node != null) {
-            final Logger instance = node.getLogger();
-            if (instance != null) {
-                return instance;
-            }
-            node = node.parent;
-        }
-        return null;
-    }
-
-    /**
      * Get the log context.
      *
      * @return the log context
@@ -234,44 +227,211 @@
     }
 
     /**
-     * Recursively update the effective log level of all log instances on all children.  The recursion depth will be proportionate to the
-     * log node nesting depth so stack use should not be an issue.  Must only be called while the log context's level
+     * Update the effective level if it is inherited from a parent.  Must only be called while the logmanager's level
      * change lock is held.
      *
      * @param newLevel the new effective level
      */
-    void updateChildEffectiveLevel(int newLevel) {
-        for (LoggerNode node : children.values()) {
-            if (node != null) {
-                final Logger instance = node.getLogger();
-                if (instance != null) {
-                    instance.setEffectiveLevel(newLevel);
+    void setEffectiveLevel(int newLevel) {
+        if (level == null) {
+            effectiveLevel = newLevel;
+            for (LoggerNode node : children.values()) {
+                if (node != null) {
+                    node.setEffectiveLevel(newLevel);
+                }
+            }
+        }
+    }
+
+    void setFilter(final Filter filter) {
+        this.filter = filter;
+    }
+
+    Filter getFilter() {
+        return filter;
+    }
+
+    int getEffectiveLevel() {
+        return effectiveLevel;
+    }
+
+    Handler[] getHandlers() {
+        return handlers;
+    }
+
+    Handler[] clearHandlers() {
+        final Handler[] handlers = this.handlers;
+        handlersUpdater.clear(this);
+        return handlers.length > 0 ? handlers.clone() : handlers;
+    }
+
+    void removeHandler(final Handler handler) {
+        handlersUpdater.remove(this, handler, true);
+    }
+
+    void addHandler(final Handler handler) {
+        handlersUpdater.add(this, handler);
+    }
+
+    boolean getUseParentHandlers() {
+        return useParentHandlers;
+    }
+
+    void setUseParentHandlers(final boolean useParentHandlers) {
+        this.useParentHandlers = useParentHandlers;
+    }
+
+    void publish(final ExtLogRecord record) {
+        for (Handler handler : handlers) try {
+            handler.publish(record);
+        } catch (VirtualMachineError e) {
+            throw e;
+        } catch (Throwable t) {
+            // todo - error handler
+        }
+        if (useParentHandlers) {
+            final LoggerNode parent = this.parent;
+            if (parent != null) parent.publish(record);
+        }
+    }
+
+    void setLevel(final Level newLevel) {
+        final LogContext context = this.context;
+        final Lock lock = context.treeLock;
+        lock.lock();
+        try {
+            final int oldEffectiveLevel = effectiveLevel;
+            final int newEffectiveLevel;
+            if (newLevel != null) {
+                level = newLevel;
+                newEffectiveLevel = newLevel.intValue();
+            } else {
+                final LoggerNode parent = this.parent;
+                if (parent == null) {
+                    level = Level.INFO;
+                    newEffectiveLevel = Logger.INFO_INT;
                 } else {
-                    node.updateChildEffectiveLevel(newLevel);
+                    level = null;
+                    newEffectiveLevel = parent.effectiveLevel;
                 }
             }
+            effectiveLevel = newEffectiveLevel;
+            if (oldEffectiveLevel != newEffectiveLevel) {
+                // our level changed, recurse down to children
+                for (LoggerNode node : children.values()) {
+                    if (node != null) {
+                        node.setEffectiveLevel(newEffectiveLevel);
+                    }
+                }
+            }
+        } finally {
+            lock.unlock();
         }
+
     }
 
-    private interface LoggerRef {
-        Logger get();
+    Level getLevel() {
+        return level;
     }
 
-    private static final class WeakLoggerRef extends WeakReference<Logger> implements LoggerRef {
-        private WeakLoggerRef(Logger referent) {
-            super(referent);
+    @SuppressWarnings({ "unchecked" })
+    <V> V getAttachment(final Logger.AttachmentKey<V> key) {
+        if (key == null) {
+            throw new NullPointerException("key is null");
         }
+        final Map<Logger.AttachmentKey, Object> attachments = this.attachments;
+        return (V) attachments.get(key);
     }
 
-    private static final class StrongLoggerRef implements LoggerRef {
-        private final Logger logger;
+    @SuppressWarnings({ "unchecked" })
+    <V> V attach(final Logger.AttachmentKey<V> key, final V value) {
+        if (key == null) {
+            throw new NullPointerException("key is null");
+        }
+        if (value == null) {
+            throw new NullPointerException("value is null");
+        }
+        Map<Logger.AttachmentKey, Object> oldAttachments;
+        Map<Logger.AttachmentKey, Object> newAttachments;
+        V old;
+        do {
+            oldAttachments = attachments;
+            if (oldAttachments.isEmpty() || oldAttachments.size() == 1 && oldAttachments.containsKey(key)) {
+                old = (V) oldAttachments.get(key);
+                newAttachments = Collections.<Logger.AttachmentKey, Object>singletonMap(key, value);
+            } else {
+                newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
+                old = (V) newAttachments.put(key, value);
+            }
+        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
+        return old;
+    }
 
-        private StrongLoggerRef(final Logger logger) {
-            this.logger = logger;
+    @SuppressWarnings({ "unchecked" })
+    <V> V attachIfAbsent(final Logger.AttachmentKey<V> key, final V value) {
+        if (key == null) {
+            throw new NullPointerException("key is null");
         }
+        if (value == null) {
+            throw new NullPointerException("value is null");
+        }
+        Map<Logger.AttachmentKey, Object> oldAttachments;
+        Map<Logger.AttachmentKey, Object> newAttachments;
+        do {
+            oldAttachments = attachments;
+            if (oldAttachments.isEmpty()) {
+                newAttachments = Collections.<Logger.AttachmentKey, Object>singletonMap(key, value);
+            } else {
+                if (oldAttachments.containsKey(key)) {
+                    return (V) oldAttachments.get(key);
+                }
+                newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
+                newAttachments.put(key, value);
+            }
+        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
+        return null;
+    }
 
-        public Logger get() {
-            return logger;
+    @SuppressWarnings({ "unchecked" })
+    public <V> V detach(final Logger.AttachmentKey<V> key) {
+        if (key == null) {
+            throw new NullPointerException("key is null");
         }
+        Map<Logger.AttachmentKey, Object> oldAttachments;
+        Map<Logger.AttachmentKey, Object> newAttachments;
+        V result;
+        do {
+            oldAttachments = attachments;
+            result = (V) oldAttachments.get(key);
+            if (result == null) {
+                return null;
+            }
+            final int size = oldAttachments.size();
+            if (size == 1) {
+                // special case - the new map is empty
+                newAttachments = Collections.emptyMap();
+            } else if (size == 2) {
+                // special case - the new map is a singleton
+                final Iterator<Map.Entry<Logger.AttachmentKey,Object>> it = oldAttachments.entrySet().iterator();
+                // find the entry that we are not removing
+                Map.Entry<Logger.AttachmentKey, Object> entry = it.next();
+                if (entry.getKey() == key) {
+                    // must be the next one
+                    entry = it.next();
+                }
+                newAttachments = Collections.singletonMap(entry.getKey(), entry.getValue());
+            } else {
+                newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
+            }
+        } while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
+        return result;
     }
+
+    String getFullName() {
+        return fullName;
+    }
+
+    LoggerNode getParent() {
+        return parent;
+    }
 }

Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggingMXBeanImpl.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggingMXBeanImpl.java	2010-07-29 20:58:23 UTC (rev 4811)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/LoggingMXBeanImpl.java	2010-07-29 21:41:19 UTC (rev 4812)
@@ -36,12 +36,9 @@
     }
 
     private void getAllNames(List<String> names, LoggerNode node) {
-        final Logger logger = node.getLogger();
-        if (logger != null) {
-            names.add(logger.getName());
-        }
+        names.add(node.getFullName());
         for (LoggerNode loggerNode : node.getChildren()) {
-            getAllNames(names, loggerNode);
+            if (loggerNode != null) getAllNames(names, loggerNode);
         }
     }
 
@@ -53,25 +50,25 @@
     }
 
     public String getLoggerLevel(final String loggerName) {
-        final Logger logger = context.getLoggerIfExists(loggerName);
-        final Level level = logger == null ? null : logger.getLevel();
+        final LoggerNode loggerNode = context.getRootLoggerNode().getIfExists(loggerName);
+        final Level level = loggerNode == null ? null : loggerNode.getLevel();
         return level == null ? "" : level.getName();
     }
 
     public void setLoggerLevel(final String loggerName, final String levelName) {
-        final Logger logger = context.getLoggerIfExists(loggerName);
-        if (logger == null) {
+        final LoggerNode loggerNode = context.getRootLoggerNode().getIfExists(loggerName);
+        if (loggerNode == null) {
             throw new IllegalArgumentException("logger \"" + loggerName + "\" does not exist");
         }
-        logger.setLevel(levelName == null ? null : context.getLevelForName(levelName));
+        loggerNode.setLevel(levelName == null ? null : context.getLevelForName(levelName));
     }
 
     public String getParentLoggerName(final String loggerName) {
-        final Logger logger = context.getLoggerIfExists(loggerName);
-        if (logger == null) {
-            return null;
+        final int dotIdx = loggerName.lastIndexOf('.');
+        if (dotIdx == -1) {
+            return "";
+        } else {
+            return loggerName.substring(0, dotIdx);
         }
-        final Logger parent = logger.getParent();
-        return parent == null ? "" : parent.getName();
     }
 }



More information about the jboss-svn-commits mailing list