001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 018package org.apache.logging.log4j.core.config; 019 020import java.util.Objects; 021import java.util.concurrent.locks.ReadWriteLock; 022import java.util.concurrent.locks.ReentrantReadWriteLock; 023 024import org.apache.logging.log4j.Level; 025import org.apache.logging.log4j.Marker; 026import org.apache.logging.log4j.core.LogEvent; 027import org.apache.logging.log4j.core.impl.LocationAware; 028import org.apache.logging.log4j.message.Message; 029import org.apache.logging.log4j.util.Supplier; 030 031/** 032 * ReliabilityStrategy that uses read/write locks to prevent the LoggerConfig from stopping while it is in use. 033 */ 034public class LockingReliabilityStrategy implements ReliabilityStrategy, LocationAwareReliabilityStrategy { 035 private final LoggerConfig loggerConfig; 036 private final ReadWriteLock reconfigureLock = new ReentrantReadWriteLock(); 037 private volatile boolean isStopping = false; 038 039 public LockingReliabilityStrategy(final LoggerConfig loggerConfig) { 040 this.loggerConfig = Objects.requireNonNull(loggerConfig, "loggerConfig was null"); 041 } 042 043 /* 044 * (non-Javadoc) 045 * 046 * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier, 047 * java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level, 048 * org.apache.logging.log4j.message.Message, java.lang.Throwable) 049 */ 050 @Override 051 public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn, 052 final Marker marker, final Level level, final Message data, final Throwable t) { 053 054 final LoggerConfig config = getActiveLoggerConfig(reconfigured); 055 try { 056 config.log(loggerName, fqcn, marker, level, data, t); 057 } finally { 058 config.getReliabilityStrategy().afterLogEvent(); 059 } 060 } 061 062 /* 063 * (non-Javadoc) 064 * 065 * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier, 066 * java.lang.String, java.lang.String, java.lang.StackTraceElement, org.apache.logging.log4j.Marker, 067 * org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable) 068 */ 069 @Override 070 public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn, 071 final StackTraceElement location, final Marker marker, final Level level, final Message data, 072 final Throwable t) { 073 final LoggerConfig config = getActiveLoggerConfig(reconfigured); 074 try { 075 config.log(loggerName, fqcn, location, marker, level, data, t); 076 } finally { 077 config.getReliabilityStrategy().afterLogEvent(); 078 } 079 } 080 081 /* 082 * (non-Javadoc) 083 * 084 * @see org.apache.logging.log4j.core.config.ReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier, 085 * org.apache.logging.log4j.core.LogEvent) 086 */ 087 @Override 088 public void log(final Supplier<LoggerConfig> reconfigured, final LogEvent event) { 089 final LoggerConfig config = getActiveLoggerConfig(reconfigured); 090 try { 091 config.log(event); 092 } finally { 093 config.getReliabilityStrategy().afterLogEvent(); 094 } 095 } 096 097 /* 098 * (non-Javadoc) 099 * 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}