Author: markt Date: Thu Aug 1 14:12:31 2013 New Revision: 1509240 URL: http://svn.apache.org/r1509240 Log: First pass at switching GOP and GKOP to a listener for swallowed exceptions rather than JMX notifications.
Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java (with props) Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java?rev=1509240&view=auto ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java (added) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java Thu Aug 1 14:12:31 2013 @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.pool2; + +/** + * Pools that unavoidably swallow exceptions may be configured with an instance + * of this listener so the user may receive notification of when this happens. + * The listener should not throw an exception when called but pools calling + * listeners should protect themselves against exceptions anyway. + */ +public interface SwallowedExceptionListener { + + void onSwallowException(Exception e); +} Propchange: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java?rev=1509240&r1=1509239&r2=1509240&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java Thu Aug 1 14:12:31 2013 @@ -21,12 +21,10 @@ import java.io.StringWriter; import java.io.Writer; import java.lang.management.ManagementFactory; import java.util.ArrayList; -import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import javax.management.InstanceAlreadyExistsException; @@ -37,7 +35,6 @@ import javax.management.MBeanRegistratio import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; -import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; @@ -45,6 +42,7 @@ import javax.management.NotificationList import javax.management.ObjectName; import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.SwallowedExceptionListener; /** * Base class that provides common functionality for {@link GenericObjectPool} @@ -73,7 +71,6 @@ public abstract class BaseGenericObjectP * so that rolling means may be calculated. */ public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100; - private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10; // Configuration attributes private volatile int maxTotal = @@ -118,8 +115,6 @@ public abstract class BaseGenericObjectP private final ObjectName oname; private final NotificationBroadcasterSupport jmxNotificationSupport; private final String creationStackTrace; - private final Deque<String> swallowedExceptions = new LinkedList<String>(); - private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0); private final AtomicLong borrowedCount = new AtomicLong(0); private final AtomicLong returnedCount = new AtomicLong(0); final AtomicLong createdCount = new AtomicLong(0); @@ -131,6 +126,7 @@ public abstract class BaseGenericObjectP private final LinkedList<Long> waitTimes = new LinkedList<Long>(); // @GuardedBy("activeTimes") - except in initStats() private final Object maxBorrowWaitTimeMillisLock = new Object(); private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock") + private SwallowedExceptionListener swallowedExceptionListener = null; /** @@ -151,11 +147,6 @@ public abstract class BaseGenericObjectP this.oname = null; } - // Populate the swallowed exceptions queue - for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) { - swallowedExceptions.add(null); - } - // Populate the creation stack trace this.creationStackTrace = getStackTrace(new Exception()); @@ -633,10 +624,10 @@ public abstract class BaseGenericObjectP * <p>Starts the evictor with the given delay. If there is an evictor * running when this method is called, it is stopped and replaced with a * new evictor with the specified delay.</p> - * + * * <p>This method needs to be final, since it is called from a constructor. * See POOL-195.</p> - * + * * @param delay time in milliseconds before start and between eviction runs */ final void startEvictor(long delay) { @@ -686,21 +677,6 @@ public abstract class BaseGenericObjectP } /** - * Lists the most recent exceptions that have been swallowed by the pool - * implementation. Exceptions are typically swallowed when a problem occurs - * while destroying an object. - * @return array containing stack traces of recently swallowed exceptions - */ - public final String[] getSwallowedExceptions() { - List<String> temp = - new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE); - synchronized (swallowedExceptions) { - temp.addAll(swallowedExceptions); - } - return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]); - } - - /** * The total number of objects successfully borrowed from this pool over the * lifetime of the pool. * @return the borrowed object count @@ -801,6 +777,26 @@ public abstract class BaseGenericObjectP public abstract int getNumIdle(); /** + * The listener used (if any) to receive notifications of exceptions + * unavoidably swallowed by the pool. + */ + public SwallowedExceptionListener getSwallowedExceptionListener() { + return swallowedExceptionListener; + } + + /** + * The listener used (if any) to receive notifications of exceptions + * unavoidably swallowed by the pool. + * + * @param swallowedExceptionListener The listener or <code>null</code> + * for no listener + */ + public void setSwallowedExceptionListener( + SwallowedExceptionListener swallowedExceptionListener) { + this.swallowedExceptionListener = swallowedExceptionListener; + } + + /** * Returns the {@link NotificationBroadcasterSupport} for the pool * @return JMX notification broadcaster */ @@ -814,19 +810,20 @@ public abstract class BaseGenericObjectP * @param e exception to be swallowed */ final void swallowException(Exception e) { - String msg = getStackTrace(e); + SwallowedExceptionListener listener = getSwallowedExceptionListener(); - ObjectName oname = getJmxName(); - if (oname != null && !isClosed()) { - Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION, - oname, swallowedExcpetionCount.incrementAndGet(), msg); - getJmxNotificationSupport().sendNotification(n); + if (listener == null) { + return; } - // Add the exception the queue, removing the oldest - synchronized (swallowedExceptions) { - swallowedExceptions.addLast(msg); - swallowedExceptions.pollFirst(); + try { + listener.onSwallowException(e); + } catch (OutOfMemoryError oome) { + throw oome; + } catch (VirtualMachineError vme) { + throw vme; + } catch (Throwable t) { + // Ignore. Enjoy the irony. } } @@ -883,12 +880,12 @@ public abstract class BaseGenericObjectP /** * Registers the pool with the platform MBean server. - * The registered name will be + * The registered name will be * <code>jmxNameBase + jmxNamePrefix + i</code> where i is the least * integer greater than or equal to 1 such that the name is not already * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException * returning null. - * + * * @param jmxNameBase base JMX name for this pool * @param jmxNamePrefix name prefix * @return registered ObjectName, null if registration fails Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java?rev=1509240&r1=1509239&r2=1509240&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java Thu Aug 1 14:12:31 2013 @@ -138,10 +138,6 @@ public interface GenericKeyedObjectPoolM */ long getMaxBorrowWaitTimeMillis(); /** - * See {@link GenericKeyedObjectPool#getSwallowedExceptions()} - */ - String[] getSwallowedExceptions(); - /** * See {@link GenericKeyedObjectPool#getCreationStackTrace()} */ String getCreationStackTrace(); Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java?rev=1509240&r1=1509239&r2=1509240&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java Thu Aug 1 14:12:31 2013 @@ -129,10 +129,6 @@ public interface GenericObjectPoolMXBean */ long getMaxBorrowWaitTimeMillis(); /** - * See {@link GenericObjectPool#getSwallowedExceptions()} - */ - String[] getSwallowedExceptions(); - /** * See {@link GenericObjectPool#getCreationStackTrace()} */ String getCreationStackTrace();