You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2010/05/06 17:13:47 UTC
svn commit: r941772 - in
/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb:
monitoring/ util/
Author: dblevins
Date: Thu May 6 15:13:47 2010
New Revision: 941772
URL: http://svn.apache.org/viewvc?rev=941772&view=rev
Log:
OPENEJB-1272: JMX Monitoring
OPENEJB-1273: JMX: Stateless Pool Stats
Added:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java (with props)
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java (with props)
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java (with props)
Removed:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanExporter.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/MBeanInfoBuilder.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ObjectNames.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Managed.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java
Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java?rev=941772&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java Thu May 6 15:13:47 2010
@@ -0,0 +1,65 @@
+/**
+ * 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.openejb.monitoring;
+
+//import org.apache.commons.math.stat.descriptive.SynchronizedDescriptiveStatistics;
+//import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.TimeUnit;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+
+/**
+ * @version $Rev$ $Date$
+*/
+@Managed(append = true)
+public class Event {
+ private final AtomicLong count = new AtomicLong();
+ private final AtomicLong last = new AtomicLong();
+// private final SynchronizedDescriptiveStatistics frequency = new SynchronizedDescriptiveStatistics(2000);
+
+ public void record() {
+ long start = last.getAndSet(System.nanoTime());
+// frequency.addValue(millis(start - last.get()));
+ count.incrementAndGet();
+ }
+
+ @Managed
+ public long get() {
+ return count.get();
+ }
+
+ @Managed
+ public String getLatest() {
+ long last = millis(this.last.get());
+
+ if (last <= 0) return "-";
+
+ DateFormat format = SimpleDateFormat.getDateTimeInstance();
+ return format.format(new Date(last));
+ }
+
+// public DescriptiveStatistics getFrequency() {
+// return frequency;
+// }
+
+ private long millis(long nanos) {
+ return TimeUnit.MILLISECONDS.convert(nanos, TimeUnit.NANOSECONDS);
+ }
+}
Propchange: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Event.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Managed.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Managed.java?rev=941772&r1=941771&r2=941772&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Managed.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/Managed.java Thu May 6 15:13:47 2010
@@ -22,7 +22,8 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface Managed {
String description() default "";
+ boolean append() default false;
}
\ No newline at end of file
Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java?rev=941772&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java Thu May 6 15:13:47 2010
@@ -0,0 +1,250 @@
+/**
+ * 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.openejb.monitoring;
+
+import org.apache.xbean.finder.ClassFinder;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanAttributeInfo;
+import javax.management.AttributeNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ReflectionException;
+import javax.management.Attribute;
+import javax.management.InvalidAttributeValueException;
+import javax.management.AttributeList;
+import javax.management.MBeanInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanNotificationInfo;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Collections;
+import java.util.Comparator;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @version $Rev$ $Date$
+*/
+class ManagedMBean implements DynamicMBean {
+
+ private final List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
+ private final Map<String, Member> map = new HashMap<String, Member>();
+
+ ManagedMBean(Object managed) {
+ scan(managed, "");
+
+ for (Member member : map.values()) {
+ attributes.add(new MBeanAttributeInfo(member.getName(), member.getType().getName(), "", true, false, false));
+ }
+
+ Collections.sort(attributes, new Comparator<MBeanAttributeInfo>(){
+ public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ }
+
+ private void scan(Object managed, String prefix) {
+ ClassFinder finder = new ClassFinder(managed.getClass());
+
+ List<Field> fields = finder.findAnnotatedFields(Managed.class);
+ for (Field field : fields) {
+ scan(new FieldMember(field, managed, prefix));
+ }
+
+ List<Method> methods = finder.findAnnotatedMethods(Managed.class);
+ for (Method method : methods) {
+ scan(new MethodMember(method, managed, prefix));
+ }
+ }
+
+ private void scan(Member member) {
+ Class<?> type = member.getType();
+
+ Managed managed = type.getAnnotation(Managed.class);
+ if (managed != null) {
+ try {
+ String s = "";
+ if (managed.append()) s = member.getName();
+ scan(member.get(), s);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ } else {
+ map.put(member.getName(), member);
+ }
+ }
+
+ public Object getAttribute(String s) throws AttributeNotFoundException, MBeanException, ReflectionException {
+ try {
+ Member member = map.get(s);
+
+ if (member == null) throw new AttributeNotFoundException(s);
+
+ return member.get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new ReflectionException(e);
+ }
+ }
+
+ public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+ }
+
+ public AttributeList getAttributes(String[] strings) {
+ AttributeList list = new AttributeList(strings.length);
+ for (String attribute : strings) {
+ try {
+ list.add(new Attribute(attribute, getAttribute(attribute)));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return list;
+ }
+
+ public AttributeList setAttributes(AttributeList attributeList) {
+ return new AttributeList();
+ }
+
+ public Object invoke(String s, Object[] objects, String[] strings) throws MBeanException, ReflectionException {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ return new MBeanInfo(this.getClass().getName(), "The description", attributes.toArray(new MBeanAttributeInfo[0]), new MBeanConstructorInfo[0], new MBeanOperationInfo[0], new MBeanNotificationInfo[0]);
+ }
+
+ /**
+ * Small utility interface used to allow polymorphing
+ * of java.lang.reflect.Method and java.lang.reflect.Field
+ * so that each can be treated as injection targets using
+ * the same code.
+ */
+ public static interface Member {
+ Object get() throws IllegalAccessException, InvocationTargetException;
+
+ String getName();
+
+ Class getType();
+ }
+
+ /**
+ * Implementation of Member for java.lang.reflect.Method
+ * Used for injection targets that are annotated methods
+ */
+ public static class MethodMember implements Member {
+ private final Method getter;
+ private final Object target;
+ private final String prefix;
+
+ public MethodMember(Method getter, Object target, String prefix) {
+ getter.setAccessible(true);
+ this.getter = getter;
+ this.target = target;
+ this.prefix = prefix;
+ }
+
+ public Class getType() {
+ return getter.getReturnType();
+ }
+
+ public Class getDeclaringClass() {
+ return getter.getDeclaringClass();
+ }
+
+ /**
+ * The method name needs to be changed from "getFoo" to "foo"
+ *
+ * @return
+ */
+ public String getName() {
+ StringBuilder name = new StringBuilder(getter.getName());
+
+ // remove 'get'
+ name.delete(0, 3);
+
+ if (!"".equals(prefix)){
+ if (!"".equals(name.toString())) name.insert(0, ".");
+ name.insert(0, prefix);
+ }
+
+ return name.toString();
+ }
+
+ public String toString() {
+ return getter.toString();
+ }
+
+ public Object get() throws IllegalAccessException, InvocationTargetException {
+ return getter.invoke(target);
+ }
+ }
+
+ /**
+ * Implementation of Member for java.lang.reflect.Field
+ * Used for injection targets that are annotated fields
+ */
+ public static class FieldMember implements Member {
+ private final Field field;
+ private final Object target;
+ private final String prefix;
+
+ public FieldMember(Field field, Object target, String prefix) {
+ field.setAccessible(true);
+ this.field = field;
+ this.target = target;
+ this.prefix = prefix;
+ }
+
+ public Class getType() {
+ return field.getType();
+ }
+
+ public String toString() {
+ return field.toString();
+ }
+
+ public Class getDeclaringClass() {
+ return field.getDeclaringClass();
+ }
+
+ public String getName() {
+ StringBuilder name = new StringBuilder(field.getName());
+
+ name.setCharAt(0, Character.toUpperCase(name.charAt(0)));
+
+ if (!"".equals(prefix)){
+ if (!"".equals(name.toString())) name.insert(0, ".");
+ name.insert(0, prefix);
+ }
+
+ return name.toString();
+ }
+
+ public Object get() throws IllegalAccessException {
+ return field.get(target);
+ }
+ }
+
+}
Propchange: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ManagedMBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java?rev=941772&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java Thu May 6 15:13:47 2010
@@ -0,0 +1,102 @@
+/**
+ * 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.openejb.monitoring;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.openejb.util.Pool;
+import org.apache.openejb.util.Duration;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ScratchPad {
+
+ public static void main(String[] args) throws Exception {
+ new ScratchPad().main();
+ }
+
+ public void main() throws Exception {
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ Pool.Builder builder = new Pool.Builder();
+ builder.setPoolMin(4);
+ builder.setIdleTimeout(new Duration("30 seconds"));
+ builder.setPollInterval(new Duration("15 seconds"));
+ builder.setMaxAge(new Duration("2 minutes"));
+ builder.setSupplier(new Pool.Supplier(){
+ public void discard(Object o, Pool.Event reason) {
+ }
+
+ public Object create() {
+ return "";
+ }
+ });
+ Pool pool = builder.build();
+ pool.start();
+ pool.add("");
+ pool.add("");
+ pool.add("");
+ pool.add("");
+ pool.add("");
+ pool.add("");
+
+ server.registerMBean(new ManagedMBean(pool), new ObjectName("something:name=Pool"));
+
+// while ("".equals("")) {
+// object.tick(System.currentTimeMillis() % 1000);
+// Thread.sleep(287);
+// }
+
+// server.createMBean()
+ while (true) {
+ List<Pool.Entry> entries = new ArrayList<Pool.Entry>();
+
+ try {
+ while (true) {
+ entries.add(pool.pop(1, TimeUnit.SECONDS));
+ snooze();
+ }
+ } catch (TimeoutException e) {
+ }
+
+ for (Pool.Entry entry : entries) {
+ pool.push(entry);
+ snooze();
+ }
+ }
+// new CountDownLatch(1).await();
+
+ }
+
+ private void snooze() {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ }
+ }
+
+}
Propchange: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/monitoring/ScratchPad.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java?rev=941772&r1=941771&r2=941772&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java Thu May 6 15:13:47 2010
@@ -16,6 +16,8 @@
*/
package org.apache.openejb.util;
+import org.apache.openejb.monitoring.Managed;
+
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Iterator;
@@ -50,120 +52,41 @@ import java.util.concurrent.atomic.Atomi
*/
public class Pool<T> {
+ // TODO: replace System.currentTimeMillis() with System.nanoTime()
+
private final LinkedList<Entry> pool = new LinkedList<Entry>();
private final Semaphore instances;
private final Semaphore available;
private final Semaphore minimum;
private final Executor executor;
+
+ @Managed
private final long maxAge;
+
+ @Managed
private final AtomicInteger poolVersion = new AtomicInteger();
+
private final Supplier<T> supplier;
private final AtomicReference<Timer> timer = new AtomicReference<Timer>();
private final Sweeper sweeper;
- private final long interval;
- private final boolean replaceAged;
- private double maxAgeOffset;
-
- public static class Builder<T> {
-
- private int max = 10;
- private int min = 0;
- private boolean strict = true;
- private Duration maxAge = new Duration(0, MILLISECONDS);
- private double maxAgeOffset = -1;
- private Duration idleTimeout = new Duration(0, MILLISECONDS);
- private Duration interval = new Duration(5 * 60, TimeUnit.SECONDS);
- private Supplier<T> supplier;
- private Executor executor;
- private boolean replaceAged;
-
- public Builder(Builder<T> that) {
- this.max = that.max;
- this.min = that.min;
- this.strict = that.strict;
- this.maxAge = that.maxAge;
- this.idleTimeout = that.idleTimeout;
- this.interval = that.interval;
- this.executor = that.executor;
- this.supplier = that.supplier;
- this.maxAgeOffset = that.maxAgeOffset;
- this.replaceAged = that.replaceAged;
- }
-
- public Builder() {
- }
-
- public int getMin() {
- return min;
- }
-
- public void setReplaceAged(boolean replaceAged) {
- this.replaceAged = replaceAged;
- }
-
- public void setPoolMax(int max) {
- this.max = max;
- }
-
- /**
- * Alias for pool size
- * @param max
- * @return
- */
- public void setPoolSize(int max) {
- setPoolMax(max);
- }
-
- public void setPoolMin(int min) {
- this.min = min;
- }
-
- public void setStrictPooling(boolean strict) {
- this.strict = strict;
- }
-
- public void setMaxAge(Duration maxAge) {
- this.maxAge = maxAge;
- }
-
- public Duration getMaxAge() {
- return maxAge;
- }
-
- public void setMaxAgeOffset(double maxAgeOffset) {
- this.maxAgeOffset = maxAgeOffset;
- }
-
- public double getMaxAgeOffset() {
- return maxAgeOffset;
- }
-
- public void setIdleTimeout(Duration idleTimeout) {
- this.idleTimeout = idleTimeout;
- }
- public void setPollInterval(Duration interval) {
- this.interval = interval;
- }
+ @Managed
+ private final long interval;
- public void setSupplier(Supplier<T> supplier) {
- this.supplier = supplier;
- }
+ @Managed
+ private final boolean replaceAged;
- public void setExecutor(Executor executor) {
- this.executor = executor;
- }
+ @Managed
+ private double maxAgeOffset;
- public Pool<T> build() {
- return new Pool(max, min, strict, maxAge.getTime(MILLISECONDS), idleTimeout.getTime(MILLISECONDS), interval.getTime(MILLISECONDS), executor, supplier, false);
- }
- }
+ @Managed
+ private final Stats stats;
public Pool(int max, int min, boolean strict) {
- this(max, min, strict, 0, 0, 0, null, null, false);
+ this(max, min, strict, 0, 0, 0, null, null, false, -1);
}
- public Pool(int max, int min, boolean strict, long maxAge, long idleTimeout, long interval, Executor executor, Supplier<T> supplier, boolean replaceAged) {
+ public Pool(int max, int min, boolean strict, long maxAge, long idleTimeout, long interval, Executor executor, Supplier<T> supplier, boolean replaceAged, double maxAgeOffset) {
if (min > max) greater("max", max, "min", min);
if (maxAge != 0 && idleTimeout > maxAge) greater("MaxAge", maxAge, "IdleTimeout", idleTimeout);
this.executor = executor != null ? executor : createExecutor();
@@ -172,11 +95,12 @@ public class Pool<T> {
this.minimum = new Semaphore(min);
this.instances = new Semaphore(max);
this.maxAge = maxAge;
+ this.maxAgeOffset = maxAgeOffset;
this.replaceAged = replaceAged;
if (interval == 0) interval = 5 * 60 * 1000; // five minutes
this.interval = interval;
-
- sweeper = new Sweeper(idleTimeout, max);
+ this.sweeper = new Sweeper(idleTimeout, max);
+ this.stats = new Stats(min, max, idleTimeout);
}
public Pool start() {
@@ -204,6 +128,7 @@ public class Pool<T> {
}
public void flush() {
+ stats.flushes.record();
poolVersion.incrementAndGet();
}
@@ -220,7 +145,10 @@ public class Pool<T> {
* @throws TimeoutException if no instance could be obtained within the timeout
*/
public Entry<T> pop(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
- if (!available.tryAcquire(timeout, unit)) throw new TimeoutException("Waited " + timeout + " " + unit);
+ if (!available.tryAcquire(timeout, unit)) {
+ stats.accessTimeouts.record();
+ throw new TimeoutException("Waited " + timeout + " " + unit);
+ }
Entry<T> entry = null;
while (entry == null) {
@@ -242,6 +170,7 @@ public class Pool<T> {
if (notBusy) return entry;
} else {
// the SoftReference was garbage collected
+ stats.garbageCollected.record();
instances.release();
}
@@ -317,7 +246,7 @@ public class Pool<T> {
return push(new Entry<T>(obj, offset, poolVersion.get()));
}
- if (obj != null) supplier.discard(obj, Event.FULL);
+ if (obj != null) new Discard(obj, Event.FULL).run();
return false;
}
@@ -377,7 +306,7 @@ public class Pool<T> {
// queue it up instead.
executor.execute(new Discard(obj, event));
} else {
- supplier.discard(obj, event);
+ new Discard(obj, event).run();
}
}
@@ -521,6 +450,8 @@ public class Pool<T> {
public void run() {
+ stats.sweeps.record();
+
final int currentVersion = poolVersion.get();
final boolean isCurrent = previousVersion.getAndSet(currentVersion) == currentVersion;
@@ -723,6 +654,8 @@ public class Pool<T> {
// Retry and logging should be done in
// the Supplier implementation
discard(expired);
+ } finally {
+ stats.replaced.record();
}
}
}
@@ -738,6 +671,12 @@ public class Pool<T> {
}
public void run() {
+ switch (event) {
+ case AGED: stats.aged.record(); break;
+ case FLUSHED: stats.flushed.record(); break;
+ case FULL: stats.overdrafts.record(); break;
+ case IDLE: stats.idleTimeouts.record(); break;
+ }
supplier.discard(expired, event);
}
}
@@ -810,7 +749,7 @@ public class Pool<T> {
@Override
public int availablePermits() {
- return 0;
+ return Integer.MAX_VALUE;
}
@Override
@@ -822,4 +761,160 @@ public class Pool<T> {
protected void reducePermits(int reduction) {
}
}
+
+ @Managed
+ private class Stats {
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event sweeps = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event flushes = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event accessTimeouts = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event garbageCollected = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event idleTimeouts = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event aged = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event flushed = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event overdrafts = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final org.apache.openejb.monitoring.Event replaced = new org.apache.openejb.monitoring.Event();
+
+ @Managed
+ private final int minSize;
+
+ @Managed
+ private final int maxSize;
+
+ @Managed
+ private long idleTimeout;
+
+ private Stats(int minSize, int maxSize, long idleTimeout) {
+ this.minSize = minSize;
+ this.maxSize = maxSize;
+ this.idleTimeout = idleTimeout;
+ }
+
+ @Managed
+ private long getAvailable() {
+ return available.availablePermits();
+ }
+
+ @Managed
+ private int getInstances() {
+ return maxSize - Pool.this.instances.availablePermits();
+ }
+
+ @Managed
+ private int getMinimumInstances() {
+ return minSize - minimum.availablePermits();
+ }
+ }
+
+ public static class Builder<T> {
+
+ private int max = 10;
+ private int min = 0;
+ private boolean strict = true;
+ private Duration maxAge = new Duration(0, MILLISECONDS);
+ private double maxAgeOffset = -1;
+ private Duration idleTimeout = new Duration(0, MILLISECONDS);
+ private Duration interval = new Duration(5 * 60, TimeUnit.SECONDS);
+ private Supplier<T> supplier;
+ private Executor executor;
+ private boolean replaceAged;
+
+ public Builder(Builder<T> that) {
+ this.max = that.max;
+ this.min = that.min;
+ this.strict = that.strict;
+ this.maxAge = that.maxAge;
+ this.idleTimeout = that.idleTimeout;
+ this.interval = that.interval;
+ this.executor = that.executor;
+ this.supplier = that.supplier;
+ this.maxAgeOffset = that.maxAgeOffset;
+ this.replaceAged = that.replaceAged;
+ }
+
+ public Builder() {
+ }
+
+ public int getMin() {
+ return min;
+ }
+
+ public void setReplaceAged(boolean replaceAged) {
+ this.replaceAged = replaceAged;
+ }
+
+ public void setPoolMax(int max) {
+ this.max = max;
+ }
+
+ /**
+ * Alias for pool size
+ * @param max
+ * @return
+ */
+ public void setPoolSize(int max) {
+ setPoolMax(max);
+ }
+
+ public void setPoolMin(int min) {
+ this.min = min;
+ }
+
+ public void setStrictPooling(boolean strict) {
+ this.strict = strict;
+ }
+
+ public void setMaxAge(Duration maxAge) {
+ this.maxAge = maxAge;
+ }
+
+ public Duration getMaxAge() {
+ return maxAge;
+ }
+
+ public void setMaxAgeOffset(double maxAgeOffset) {
+ this.maxAgeOffset = maxAgeOffset;
+ }
+
+ public double getMaxAgeOffset() {
+ return maxAgeOffset;
+ }
+
+ public void setIdleTimeout(Duration idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ public void setPollInterval(Duration interval) {
+ this.interval = interval;
+ }
+
+ public void setSupplier(Supplier<T> supplier) {
+ this.supplier = supplier;
+ }
+
+ public void setExecutor(Executor executor) {
+ this.executor = executor;
+ }
+
+ public Pool<T> build() {
+ return new Pool(max, min, strict, maxAge.getTime(MILLISECONDS), idleTimeout.getTime(MILLISECONDS), interval.getTime(MILLISECONDS), executor, supplier, false, maxAgeOffset);
+ }
+ }
}