I still like the work I did with executor services, so I'll leave it at
that ;-) Sure it turns out there is a bug on reconfigure but it's fixable
without throwing it all out. I'm swamped at work ATM so I cannot spend time
dealing with too much FOSS this week (as was last week). Good luck :-)

Gary

On Thu, Jan 12, 2017 at 8:01 AM, Remko Popma <remko.po...@gmail.com> wrote:

> Some feedback:
> 1. Why remove Log4jThreadFactory.createThreadFactory?
> CassandraRule was using it and now needs to use the constructor.
>
> 2. The ConfigurationScheduler may create a thread pool with size zero.
> ConfigurationScheduler::incrementScheduledItems is only called if
> monitorInterval is positive, or if a plugin with the @Scheduled annotation
> is configured (not sure I'm reading that right), or if a
> CronTriggeringPolicy is configured. If none of these are true, but a
> RollingFile appender is configured, I think there will be a problem.
>
> 3. Generally, I think RollingFileManager AsyncActions (compress) should
> not be submitted to the ConfigurationScheduler: this executor will usually
> only have one thread so these actions will execute one by one sequentially.
> If many files need to be rolled over and compressed at the same time, I
> think this work should be done in parallel as much as possible.Therefore, I
> think it's better to create new (non-daemon) threads for the rollover async
> actions.
>
> 4. (Not your change, I noticed during review): ConfigurationScheduler
> catches InterruptedException but does not restore the interrupted flag.
> Should be:
> ...
> } catch (InterruptedException ie) {
> ...
>     // Preserve interrupt status
>     Thread.currentThread().interrupt();
> }
>
>
> On Thu, Jan 12, 2017 at 8:36 PM, <mi...@apache.org> wrote:
>
>> Repository: logging-log4j2
>> Updated Branches:
>>   refs/heads/LOG4J2-1748and1780-remove-ExecutorService-from-LoggerContext
>> [created] 162a5e33a
>>
>>
>> LOG4J2-1748 and LOG4J2-1780 Remove ExecutorServices from LoggerContext
>>
>>
>> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
>> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit
>> /162a5e33
>> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/162a5e33
>> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/162a5e33
>>
>> Branch: refs/heads/LOG4J2-1748and1780-remove-ExecutorService-from-Lo
>> ggerContext
>> Commit: 162a5e33ace3f1b4adf0726502083d0efb1e799a
>> Parents: a6f9d12
>> Author: Mikael Ståldal <mikael.stal...@magine.com>
>> Authored: Thu Jan 12 12:14:18 2017 +0100
>> Committer: Mikael Ståldal <mikael.stal...@magine.com>
>> Committed: Thu Jan 12 12:32:00 2017 +0100
>>
>> ----------------------------------------------------------------------
>>  .../logging/log4j/core/LoggerContext.java       | 97
>> +-------------------
>>  .../core/appender/mom/kafka/KafkaManager.java   | 11 ++-
>>  .../appender/rolling/RollingFileManager.java    |  2 +-
>>  .../core/config/AbstractConfiguration.java      |  4 +-
>>  .../core/config/ConfigurationScheduler.java     | 51 +++++++---
>>  .../core/config/ConfiguratonFileWatcher.java    |  7 +-
>>  .../logging/log4j/core/config/Configurator.java |  4 +-
>>  .../log4j/core/util/Log4jThreadFactory.java     | 11 ---
>>  .../nosql/appender/cassandra/CassandraRule.java |  2 +-
>>  src/site/xdoc/manual/configuration.xml.vm       |  4 +-
>>  10 files changed, 59 insertions(+), 134 deletions(-)
>> ----------------------------------------------------------------------
>>
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/LoggerContext.java
>> ----------------------------------------------------------------------
>> diff --git 
>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/Log
>> gerContext.java
>> index 2322376..9797cc6 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Log
>> gerContext.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Log
>> gerContext.java
>> @@ -26,13 +26,6 @@ import java.util.Collection;
>>  import java.util.Objects;
>>  import java.util.concurrent.ConcurrentMap;
>>  import java.util.concurrent.CopyOnWriteArrayList;
>> -import java.util.concurrent.ExecutorService;
>> -import java.util.concurrent.Executors;
>> -import java.util.concurrent.Future;
>> -import java.util.concurrent.RejectedExecutionException;
>> -import java.util.concurrent.SynchronousQueue;
>> -import java.util.concurrent.ThreadFactory;
>> -import java.util.concurrent.ThreadPoolExecutor;
>>  import java.util.concurrent.TimeUnit;
>>  import java.util.concurrent.locks.Lock;
>>  import java.util.concurrent.locks.ReentrantLock;
>> @@ -49,7 +42,6 @@ import org.apache.logging.log4j.core.
>> impl.Log4jLogEvent;
>>  import org.apache.logging.log4j.core.jmx.Server;
>>  import org.apache.logging.log4j.core.util.Cancellable;
>>  import org.apache.logging.log4j.core.util.ExecutorServices;
>> -import org.apache.logging.log4j.core.util.Log4jThreadFactory;
>>  import org.apache.logging.log4j.core.util.NetUtils;
>>  import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
>>  import org.apache.logging.log4j.message.MessageFactory;
>> @@ -92,8 +84,6 @@ public class LoggerContext extends AbstractLifeCycle
>>       * reference is updated.
>>       */
>>      private volatile Configuration configuration = new
>> DefaultConfiguration();
>> -    private ExecutorService executorService;
>> -    private ExecutorService executorServiceDeamons;
>>      private Object externalContext;
>>      private String contextName;
>>      private volatile URI configLocation;
>> @@ -326,8 +316,8 @@ public class LoggerContext extends AbstractLifeCycle
>>       * Log4j can start threads to perform certain actions like file
>> rollovers, calling this method with a positive timeout will
>>       * block until the rollover thread is done.
>>       *
>> -     * @param timeout the maximum time to wait, or 0 which mean that
>> each apppender uses its default timeout, and don't wait for background
>> -    tasks
>> +     * @param timeout the maximum time to wait, or 0 which mean that
>> each apppender uses its default timeout, and wait for
>> +     *                background tasks for one second
>>       * @param timeUnit
>>       *            the time unit of the timeout argument
>>       * @return {@code true} if the logger context terminated and {@code
>> false} if the timeout elapsed before
>> @@ -338,8 +328,6 @@ public class LoggerContext extends AbstractLifeCycle
>>      public boolean stop(final long timeout, final TimeUnit timeUnit) {
>>          LOGGER.debug("Stopping LoggerContext[name={}, {}]...",
>> getName(), this);
>>          configLock.lock();
>> -        final boolean shutdownEs;
>> -        final boolean shutdownEsd;
>>          try {
>>              if (this.isStopped()) {
>>                  return true;
>> @@ -366,16 +354,12 @@ public class LoggerContext extends AbstractLifeCycle
>>              }
>>              externalContext = null;
>>              LogManager.getFactory().removeContext(this);
>> -            final String source = "LoggerContext \'" + getName() + "\'";
>> -            shutdownEs = ExecutorServices.shutdown(executorService,
>> timeout, timeUnit, source);
>> -            // Do not wait for daemon threads
>> -            shutdownEsd = ExecutorServices.shutdown(executorServiceDeamons,
>> 0, timeUnit, source);
>>          } finally {
>>              configLock.unlock();
>>              this.setStopped();
>>          }
>>          LOGGER.debug("Stopped LoggerContext[name={}, {}]...", getName(),
>> this);
>> -        return shutdownEs && shutdownEsd;
>> +        return true;
>>      }
>>
>>      /**
>> @@ -548,9 +532,6 @@ public class LoggerContext extends AbstractLifeCycle
>>          try {
>>              final Configuration prev = this.configuration;
>>              config.addListener(this);
>> -            executorService = createNonDaemonThreadPool(Log4
>> jThreadFactory.createThreadFactory(contextName));
>> -            // Daemon threads do not prevent the application from
>> shutting down so the default keep-alive time is fine.
>> -            executorServiceDeamons = Executors.newCachedThreadPool(
>> Log4jThreadFactory.createDaemonThreadFactory(contextName));
>>
>>              final ConcurrentMap<String, String> map =
>> config.getComponent(Configuration.CONTEXT_PROPERTIES);
>>
>> @@ -586,30 +567,6 @@ public class LoggerContext extends AbstractLifeCycle
>>          }
>>      }
>>
>> -    /**
>> -     * Returns an {@code ExecutorService} whose keep-alive time is one
>> second by default, unless another
>> -     * value is specified for system property {@code
>> log4j.nondaemon.threads.keepAliveSeconds}.
>> -     * <p>
>> -     * LOG4J2-1748: ThreadPool for non-daemon threads should use a short
>> keep-alive time to prevent
>> -     * applications from being able to shut down promptly after a
>> rollover.
>> -     * </p>
>> -     *
>> -     * @param threadFactory thread factory to use
>> -     * @return a new cached thread pool
>> -     */
>> -    private ExecutorService createNonDaemonThreadPool(final
>> ThreadFactory threadFactory) {
>> -        final String PROP = "log4j.nondaemon.threads.keepAliveSeconds";
>> -        final int keepAliveTimeSeconds = 
>> PropertiesUtil.getProperties().getIntegerProperty(PROP,
>> 1);
>> -        return createThreadPool(threadFactory, keepAliveTimeSeconds);
>> -    }
>> -
>> -    private ExecutorService createThreadPool(final ThreadFactory
>> threadFactory, final int keepAliveTimeSeconds) {
>> -        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
>> -                keepAliveTimeSeconds, TimeUnit.SECONDS,
>> -                new SynchronousQueue<Runnable>(),
>> -                threadFactory);
>> -    }
>> -
>>      private void firePropertyChangeEvent(final PropertyChangeEvent
>> event) {
>>          for (final PropertyChangeListener listener :
>> propertyChangeListeners) {
>>              listener.propertyChange(event);
>> @@ -719,52 +676,4 @@ public class LoggerContext extends AbstractLifeCycle
>>          return new Logger(ctx, name, messageFactory);
>>      }
>>
>> -    /**
>> -     * Gets the executor service to submit normal tasks.
>> -     *
>> -     * @return the ExecutorService to submit normal tasks.
>> -     */
>> -    public ExecutorService getExecutorService() {
>> -        return executorService;
>> -    }
>> -
>> -    /**
>> -     * Gets the executor service to submit daemon tasks.
>> -     *
>> -     * @return the ExecutorService to submit normal daemon tasks.
>> -     */
>> -    public ExecutorService getExecutorServiceDeamons() {
>> -        return executorServiceDeamons;
>> -    }
>> -
>> -    /**
>> -     * Submits a Runnable task for normal execution and returns a Future
>> representing that task. The Future's
>> -     * {@code get} method will return {@code null} upon
>> <em>successful</em> completion.
>> -     *
>> -     * @param task the task to submit
>> -     * @return a Future representing pending completion of the task
>> -     * @throws RejectedExecutionException if the task cannot be
>> -     *         scheduled for execution
>> -     * @throws NullPointerException if the task is null
>> -     */
>> -    public Future<?> submit(final Runnable task) {
>> -        return executorService.submit(task);
>> -    }
>> -
>> -    /**
>> -     * Submits a Runnable task for daemon execution and returns a Future
>> representing that task. The Future's
>> -     * {@code get} method will return {@code null} upon
>> <em>successful</em> completion.
>> -     *
>> -     * @param task
>> -     *            the task to submit
>> -     * @return a Future representing pending completion of the task
>> -     * @throws RejectedExecutionException
>> -     *             if the task cannot be scheduled for execution
>> -     * @throws NullPointerException
>> -     *             if the task is null
>> -     */
>> -    public Future<?> submitDaemon(final Runnable task) {
>> -        return executorServiceDeamons.submit(task);
>> -    }
>> -
>>  }
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/appender/mom/kafka/KafkaManager.java
>> ----------------------------------------------------------------------
>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/mom/kafka/KafkaManager.java b/log4j-core/src/main/java/org
>> /apache/logging/log4j/core/appender/mom/kafka/KafkaManager.java
>> index 616191c..b293f2a 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/mom/kafka/KafkaManager.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/mom/kafka/KafkaManager.java
>> @@ -30,6 +30,7 @@ import org.apache.kafka.clients.produ
>> cer.RecordMetadata;
>>  import org.apache.logging.log4j.core.LoggerContext;
>>  import org.apache.logging.log4j.core.appender.AbstractManager;
>>  import org.apache.logging.log4j.core.config.Property;
>> +import org.apache.logging.log4j.core.util.Log4jThread;
>>
>>  public class KafkaManager extends AbstractManager {
>>
>> @@ -73,17 +74,19 @@ public class KafkaManager extends AbstractManager {
>>      private void closeProducer(final long timeout, final TimeUnit
>> timeUnit) {
>>          if (producer != null) {
>>              // This thread is a workaround for this Kafka issue:
>> https://issues.apache.org/jira/browse/KAFKA-1660
>> -            final Runnable task = new Runnable() {
>> +           final Thread closeThread = new Log4jThread(new Runnable() {
>>                  @Override
>>                  public void run() {
>>                      if (producer != null) {
>>                          producer.close();
>>                      }
>>                  }
>> -            };
>> +            }, "KafkaManager-CloseThread");
>> +            closeThread.setDaemon(true); // avoid blocking JVM shutdown
>> +            closeThread.start();
>>              try {
>> -                getLoggerContext().submitDaemon(task).get(timeout,
>> timeUnit);
>> -            } catch (InterruptedException | ExecutionException |
>> TimeoutException e) {
>> +                closeThread.join(timeUnit.toMillis(timeout));
>> +            } catch (final InterruptedException ignore) {
>>                  // ignore
>>              }
>>          }
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/appender/rolling/RollingFileManager.java
>> ----------------------------------------------------------------------
>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/rolling/RollingFileManager.java b/log4j-core/src/main/java/org
>> /apache/logging/log4j/core/appender/rolling/RollingFileManager.java
>> index 10cb79e..e9c7790 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/rolling/RollingFileManager.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/app
>> ender/rolling/RollingFileManager.java
>> @@ -296,7 +296,7 @@ public class RollingFileManager extends FileManager {
>>
>>                  if (success && descriptor.getAsynchronous() != null) {
>>                      LOGGER.debug("RollingFileManager executing async
>> {}", descriptor.getAsynchronous());
>> -                    future = LoggerContext.getContext(false).submit(new
>> AsyncAction(descriptor.getAsynchronous(), this));
>> +                    future = LoggerContext.getContext(false
>> ).getConfiguration().getScheduler().submit(new
>> AsyncAction(descriptor.getAsynchronous(), this));
>>                  }
>>                  return true;
>>              }
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/config/AbstractConfiguration.java
>> ----------------------------------------------------------------------
>> diff --git 
>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/AbstractConfiguration.java
>> index 3a6a58e..e5e149e 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/AbstractConfiguration.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/AbstractConfiguration.java
>> @@ -373,9 +373,9 @@ public abstract class AbstractConfiguration extends
>> AbstractFilterable implement
>>          root.clearAppenders();
>>
>>          if (watchManager.isStarted()) {
>> -            watchManager.stop();
>> +            watchManager.stop(timeout, timeUnit);
>>          }
>> -        configurationScheduler.stop();
>> +        configurationScheduler.stop(timeout, timeUnit);
>>
>>          if (advertiser != null && advertisement != null) {
>>              advertiser.unadvertise(advertisement);
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/config/ConfigurationScheduler.java
>> ----------------------------------------------------------------------
>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfigurationScheduler.java b/log4j-core/src/main/java/org
>> /apache/logging/log4j/core/config/ConfigurationScheduler.java
>> index 6c639f2..4af83a5 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfigurationScheduler.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfigurationScheduler.java
>> @@ -17,9 +17,9 @@
>>  package org.apache.logging.log4j.core.config;
>>
>>  import java.util.Date;
>> -import java.util.List;
>>  import java.util.Queue;
>>  import java.util.concurrent.Callable;
>> +import java.util.concurrent.Future;
>>  import java.util.concurrent.ScheduledExecutorService;
>>  import java.util.concurrent.ScheduledFuture;
>>  import java.util.concurrent.ScheduledThreadPoolExecutor;
>> @@ -39,6 +39,7 @@ public class ConfigurationScheduler extends
>> AbstractLifeCycle {
>>      private static final Logger LOGGER = StatusLogger.getLogger();
>>      private static final String SIMPLE_NAME = "Log4j2 " +
>> ConfigurationScheduler.class.getSimpleName();
>>      private static final int MAX_SCHEDULED_ITEMS = 5;
>> +    private static final long DEFAULT_SHUTDOWN_TIMEOUT_MILLIS = 1000;
>>      private ScheduledExecutorService executorService;
>>
>>      private int scheduledItems = 0;
>> @@ -52,14 +53,17 @@ public class ConfigurationScheduler extends
>> AbstractLifeCycle {
>>      public boolean stop(final long timeout, final TimeUnit timeUnit) {
>>          setStopping();
>>          if (isExecutorServiceSet()) {
>> +            long timeoutToUse = timeout > 0 ? timeout :
>> DEFAULT_SHUTDOWN_TIMEOUT_MILLIS;
>> +            TimeUnit timeUnitToUse = timeout > 0 ? timeUnit :
>> TimeUnit.MILLISECONDS;
>> +
>>              LOGGER.debug("{} shutting down threads in {}", SIMPLE_NAME,
>> getExecutorService());
>>              executorService.shutdown();
>>              try {
>> -                executorService.awaitTermination(timeout, timeUnit);
>> +                executorService.awaitTermination(timeoutToUse,
>> timeUnitToUse);
>>              } catch (InterruptedException ie) {
>>                  executorService.shutdownNow();
>>                  try {
>> -                    executorService.awaitTermination(timeout, timeUnit);
>> +                    executorService.awaitTermination(timeoutToUse,
>> timeUnitToUse);
>>                  } catch (InterruptedException inner) {
>>                      LOGGER.warn("ConfigurationScheduler stopped but
>> some scheduled services may not have completed.");
>>                  }
>> @@ -95,6 +99,28 @@ public class ConfigurationScheduler extends
>> AbstractLifeCycle {
>>      }
>>
>>      /**
>> +     * Creates and executes a Future that becomes enabled immediately.
>> +     * @param <V> The result type returned by this Future
>> +     * @param callable the function to execute.
>> +     * @return a Future that can be used to extract result or cancel.
>> +     *
>> +     */
>> +    public <V> Future<V> submit(final Callable<V> callable) {
>> +        return getExecutorService().submit(callable);
>> +    }
>> +
>> +    /**
>> +     * Creates and executes a Future that becomes enabled immediately.
>> +     * @param runnable the function to execute.
>> +     * @return a Future representing pending completion of the task and
>> whose get() method will return null
>> +     * upon completion.
>> +     */
>> +    public Future<?> submit(final Runnable runnable) {
>> +        return getExecutorService().submit(runnable);
>> +    }
>> +
>> +
>> +    /**
>>       * Creates and executes a ScheduledFuture that becomes enabled after
>> the given delay.
>>       * @param <V> The result type returned by this Future
>>       * @param callable the function to execute.
>> @@ -183,18 +209,13 @@ public class ConfigurationScheduler extends
>> AbstractLifeCycle {
>>
>>      private ScheduledExecutorService getExecutorService() {
>>          if (executorService == null) {
>> -            if (scheduledItems > 0) {
>> -                LOGGER.debug("{} starting {} threads", SIMPLE_NAME,
>> scheduledItems);
>> -                scheduledItems = Math.min(scheduledItems,
>> MAX_SCHEDULED_ITEMS);
>> -                ScheduledThreadPoolExecutor executor = new
>> ScheduledThreadPoolExecutor(scheduledItems,
>> -                        Log4jThreadFactory.createDaemo
>> nThreadFactory("Scheduled"));
>> -                executor.setContinueExistingPe
>> riodicTasksAfterShutdownPolicy(false);
>> -                executor.setExecuteExistingDel
>> ayedTasksAfterShutdownPolicy(false);
>> -                this.executorService = executor;
>> -
>> -            } else {
>> -                LOGGER.debug("{}: No scheduled items", SIMPLE_NAME);
>> -            }
>> +            LOGGER.debug("{} starting {} threads", SIMPLE_NAME,
>> scheduledItems);
>> +            scheduledItems = Math.min(scheduledItems,
>> MAX_SCHEDULED_ITEMS);
>> +            ScheduledThreadPoolExecutor executor = new
>> ScheduledThreadPoolExecutor(scheduledItems + 1,
>> +                    Log4jThreadFactory.createDaemo
>> nThreadFactory("Scheduled"));
>> +            executor.setContinueExistingPeriodicTasksAfterShutdownPolicy
>> (false);
>> +            executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(f
>> alse);
>> +            this.executorService = executor;
>>          }
>>          return executorService;
>>      }
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/config/ConfiguratonFileWatcher.java
>> ----------------------------------------------------------------------
>> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfiguratonFileWatcher.java b/log4j-core/src/main/java/org
>> /apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
>> index b32f9d0..38491f2 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfiguratonFileWatcher.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/ConfiguratonFileWatcher.java
>> @@ -19,8 +19,8 @@ package org.apache.logging.log4j.core.config;
>>  import java.io.File;
>>  import java.util.List;
>>
>> -import org.apache.logging.log4j.core.LoggerContext;
>>  import org.apache.logging.log4j.core.util.FileWatcher;
>> +import org.apache.logging.log4j.core.util.Log4jThreadFactory;
>>
>>  /**
>>   * Watcher for configuration files. Causes a reconfiguration when a file
>> changes.
>> @@ -29,10 +29,12 @@ public class ConfiguratonFileWatcher implements
>> FileWatcher {
>>
>>      private final Reconfigurable reconfigurable;
>>      private final List<ConfigurationListener> configurationListeners;
>> +    private final Log4jThreadFactory threadFactory;
>>
>>      public ConfiguratonFileWatcher(final Reconfigurable reconfigurable,
>> final List<ConfigurationListener> configurationListeners) {
>>          this.reconfigurable = reconfigurable;
>>          this.configurationListeners = configurationListeners;
>> +        this.threadFactory = Log4jThreadFactory.createDaemo
>> nThreadFactory("ConfiguratonFileWatcher");
>>      }
>>
>>      public List<ConfigurationListener> getListeners() {
>> @@ -43,7 +45,8 @@ public class ConfiguratonFileWatcher implements
>> FileWatcher {
>>      @Override
>>      public void fileModified(final File file) {
>>          for (final ConfigurationListener configurationListener :
>> configurationListeners) {
>> -            LoggerContext.getContext(false).submitDaemon(new
>> ReconfigurationRunnable(configurationListener, reconfigurable));
>> +            final Thread thread = threadFactory.newThread(new
>> ReconfigurationRunnable(configurationListener, reconfigurable));
>> +            thread.start();
>>          }
>>      }
>>
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/config/Configurator.java
>> ----------------------------------------------------------------------
>> diff --git 
>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/Configurator.java
>> index 28dd85f..63d8a81 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/Configurator.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/con
>> fig/Configurator.java
>> @@ -331,8 +331,8 @@ public final class Configurator {
>>      /**
>>       * Shuts down the given logger context. This request does not wait
>> for Log4j tasks to complete.
>>       * <p>
>> -     * Log4j starts threads to perform certain actions like file
>> rollovers; calling this method will not wait until the
>> -     * rollover thread is done. When this method returns, these tasks'
>> status are undefined, the tasks may be done or
>> +     * Log4j starts threads to perform certain actions like file
>> rollovers; calling this method will wait up to one second
>> +     * until the rollover thread is done. When this method returns,
>> these tasks' status are undefined, the tasks may be done or
>>       * not.
>>       * </p>
>>       *
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-core/src/main/java/org/apache/logging/log4j/co
>> re/util/Log4jThreadFactory.java
>> ----------------------------------------------------------------------
>> diff --git 
>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Log4jThreadFactory.java
>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/uti
>> l/Log4jThreadFactory.java
>> index 3715243..2318feb 100644
>> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/uti
>> l/Log4jThreadFactory.java
>> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/uti
>> l/Log4jThreadFactory.java
>> @@ -40,17 +40,6 @@ public class Log4jThreadFactory implements
>> ThreadFactory {
>>          return new Log4jThreadFactory(threadFactoryName, true,
>> Thread.NORM_PRIORITY);
>>      }
>>
>> -    /**
>> -     * Creates a new thread factory.
>> -     *
>> -     * @param threadFactoryName
>> -     *            The thread factory name.
>> -     * @return a new daemon thread factory.
>> -     */
>> -    public static Log4jThreadFactory createThreadFactory(final String
>> threadFactoryName) {
>> -        return new Log4jThreadFactory(threadFactoryName, false,
>> Thread.NORM_PRIORITY);
>> -    }
>> -
>>      private static final AtomicInteger FACTORY_NUMBER = new
>> AtomicInteger(1);
>>      private static final AtomicInteger THREAD_NUMBER = new
>> AtomicInteger(1);
>>      private final boolean daemon;
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/log4j-nosql/src/test/java/org/apache/logging/log4j/n
>> osql/appender/cassandra/CassandraRule.java
>> ----------------------------------------------------------------------
>> diff --git a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>> ppender/cassandra/CassandraRule.java b/log4j-nosql/src/test/java/or
>> g/apache/logging/log4j/nosql/appender/cassandra/CassandraRule.java
>> index bec97ea..900f794 100644
>> --- a/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>> ppender/cassandra/CassandraRule.java
>> +++ b/log4j-nosql/src/test/java/org/apache/logging/log4j/nosql/a
>> ppender/cassandra/CassandraRule.java
>> @@ -37,7 +37,7 @@ import org.junit.rules.ExternalResource;
>>   */
>>  public class CassandraRule extends ExternalResource {
>>
>> -    private static final ThreadFactory THREAD_FACTORY =
>> Log4jThreadFactory.createThreadFactory("Cassandra");
>> +    private static final ThreadFactory THREAD_FACTORY = new
>> Log4jThreadFactory("Cassandra", false, Thread.NORM_PRIORITY);
>>
>>      private final CountDownLatch latch = new CountDownLatch(1);
>>      private final Cancellable embeddedCassandra = new
>> EmbeddedCassandra(latch);
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1
>> 62a5e33/src/site/xdoc/manual/configuration.xml.vm
>> ----------------------------------------------------------------------
>> diff --git a/src/site/xdoc/manual/configuration.xml.vm
>> b/src/site/xdoc/manual/configuration.xml.vm
>> index ec73bac..3075839 100644
>> --- a/src/site/xdoc/manual/configuration.xml.vm
>> +++ b/src/site/xdoc/manual/configuration.xml.vm
>> @@ -410,8 +410,8 @@ public class Bar {
>>                <tr>
>>                   <td>shutdownTimeout</td>
>>                   <td>Specifies how many milliseconds appenders and
>> background tasks will get to shutdown when the JVM shuts
>> -                 down. Default is zero which mean that each appender
>> uses its default timeout, and don't wait for background
>> -                 tasks. Not all appenders will honor this, it is a hint
>> and not an absolute guarantee that the shutdown
>> +                 down. Default is zero which mean that each appender
>> uses its default timeout, and wait for background
>> +                 tasks for one second. Not all appenders will honor
>> this, it is a hint and not an absolute guarantee that the shutdown
>>                   procedure will not take longer. Setting this too low
>> increase the risk of losing outstanding log events
>>                   not yet written to the final destination. See <a
>> class="javadoc"
>>                   href="../log4j-core/target/sit
>> e/apidocs/org/apache/logging/log4j/core/LoggerContext.html#stop(long,
>> java.util.concurrent.TimeUnit)">LoggerContext.stop(long,
>> java.util.concurrent.TimeUnit)</a>.
>>
>>
>


-- 
E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
Java Persistence with Hibernate, Second Edition
<https://www.amazon.com/gp/product/1617290459/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1617290459&linkCode=as2&tag=garygregory-20&linkId=cadb800f39946ec62ea2b1af9fe6a2b8>

<http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1617290459>
JUnit in Action, Second Edition
<https://www.amazon.com/gp/product/1935182021/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1935182021&linkCode=as2&tag=garygregory-20&linkId=31ecd1f6b6d1eaf8886ac902a24de418%22>

<http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1935182021>
Spring Batch in Action
<https://www.amazon.com/gp/product/1935182951/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1935182951&linkCode=%7B%7BlinkCode%7D%7D&tag=garygregory-20&linkId=%7B%7Blink_id%7D%7D%22%3ESpring+Batch+in+Action>
<http:////ir-na.amazon-adsystem.com/e/ir?t=garygregory-20&l=am2&o=1&a=1935182951>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Reply via email to