View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  
18  package org.apache.logging.log4j.core.config;
19  
20  import java.util.Objects;
21  import java.util.concurrent.locks.ReadWriteLock;
22  import java.util.concurrent.locks.ReentrantReadWriteLock;
23  
24  import org.apache.logging.log4j.Level;
25  import org.apache.logging.log4j.Marker;
26  import org.apache.logging.log4j.core.LogEvent;
27  import org.apache.logging.log4j.core.impl.LocationAware;
28  import org.apache.logging.log4j.message.Message;
29  import org.apache.logging.log4j.util.Supplier;
30  
31  /**
32   * ReliabilityStrategy that uses read/write locks to prevent the LoggerConfig from stopping while it is in use.
33   */
34  public class LockingReliabilityStrategy implements ReliabilityStrategy, LocationAwareReliabilityStrategy {
35      private final LoggerConfig loggerConfig;
36      private final ReadWriteLock reconfigureLock = new ReentrantReadWriteLock();
37      private volatile boolean isStopping = false;
38  
39      public LockingReliabilityStrategy(final LoggerConfig loggerConfig) {
40          this.loggerConfig = Objects.requireNonNull(loggerConfig, "loggerConfig was null");
41      }
42  
43      /*
44       * (non-Javadoc)
45       *
46       * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
47       * java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level,
48       * org.apache.logging.log4j.message.Message, java.lang.Throwable)
49       */
50      @Override
51      public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn,
52              final Marker marker, final Level level, final Message data, final Throwable t) {
53  
54          final LoggerConfig config = getActiveLoggerConfig(reconfigured);
55          try {
56              config.log(loggerName, fqcn, marker, level, data, t);
57          } finally {
58              config.getReliabilityStrategy().afterLogEvent();
59          }
60      }
61  
62      /*
63       * (non-Javadoc)
64       *
65       * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
66       * java.lang.String, java.lang.String, java.lang.StackTraceElement, org.apache.logging.log4j.Marker,
67       * org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable)
68       */
69      @Override
70      public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn,
71          final StackTraceElement location, final Marker marker, final Level level, final Message data,
72          final Throwable t) {
73          final LoggerConfig config = getActiveLoggerConfig(reconfigured);
74          try {
75              config.log(loggerName, fqcn, location, marker, level, data, t);
76          } finally {
77              config.getReliabilityStrategy().afterLogEvent();
78          }
79      }
80  
81      /*
82       * (non-Javadoc)
83       *
84       * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier,
85       * org.apache.logging.log4j.core.LogEvent)
86       */
87      @Override
88      public void log(final Supplier<LoggerConfig> reconfigured, final LogEvent event) {
89          final LoggerConfig config = getActiveLoggerConfig(reconfigured);
90          try {
91              config.log(event);
92          } finally {
93              config.getReliabilityStrategy().afterLogEvent();
94          }
95      }
96  
97      /*
98       * (non-Javadoc)
99       *
100      * @see
101      * org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeLogEvent(org.apache.logging.log4j.core.config.
102      * LoggerConfig, org.apache.logging.log4j.util.Supplier)
103      */
104     @Override
105     public LoggerConfig getActiveLoggerConfig(final Supplier<LoggerConfig> next) {
106         LoggerConfig result = this.loggerConfig;
107         if (!beforeLogEvent()) {
108             result = next.get();
109             return result == this.loggerConfig ? result : result.getReliabilityStrategy().getActiveLoggerConfig(next);
110         }
111         return result;
112     }
113 
114     private boolean beforeLogEvent() {
115         reconfigureLock.readLock().lock();
116         if (isStopping) {
117             reconfigureLock.readLock().unlock();
118             return false;
119         }
120         return true;
121     }
122 
123     @Override
124     public void afterLogEvent() {
125         reconfigureLock.readLock().unlock();
126     }
127 
128     /*
129      * (non-Javadoc)
130      *
131      * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopAppenders()
132      */
133     @Override
134     public void beforeStopAppenders() {
135         reconfigureLock.writeLock().lock();
136         try {
137             isStopping = true;
138         } finally {
139             reconfigureLock.writeLock().unlock();
140         }
141     }
142 
143     /*
144      * (non-Javadoc)
145      *
146      * @see
147      * org.apache.logging.log4j.core.config.ReliabilityStrategy#beforeStopConfiguration(org.apache.logging.log4j.core
148      * .config.Configuration)
149      */
150     @Override
151     public void beforeStopConfiguration(final Configuration configuration) {
152         // no action
153     }
154 
155 }