Author: dblevins
Date: Sat Apr 3 06:20:37 2010
New Revision: 930484
URL: http://svn.apache.org/viewvc?rev=930484&view=rev
Log:
For statics and logging, improved the Pool.Supplier.discard() method so that it
says why an instance was discarded: FULL, AGED, IDLE, FLUSHED
Updated docs on pooling options.
Provide the option to immediately replace aged instances
Apply MaxAgeOffset when refilling the pool after a flush
Modified:
openejb/trunk/openejb3/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
openejb/trunk/openejb3/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Pool.java
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
openejb/trunk/openejb3/container/openejb-core/src/main/resources/default.openejb.conf
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
openejb/trunk/openejb3/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
Modified:
openejb/trunk/openejb3/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
(original)
+++
openejb/trunk/openejb3/assembly/openejb-jetty/openejb-jetty-webapp/src/main/resources/META-INF/org.apache.openejb.jetty/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -102,14 +102,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -118,6 +110,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -149,6 +158,62 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
+ # Applies to MaxAge usage and would rarely be changed, but is a
+ # nice feature to understand.
+ #
+ # When the container first starts and the pool is filled to the
+ # minimum size, all those "minimum" instances will have the same
+ # creation time and therefore all expire at the same time dictated
+ # by the MaxAge setting. To protect against this sudden drop
+ # scenario and provide a more gradual expiration from the start
+ # the container will spread out the age of the instances that fill
+ # the pool to the minimum using an offset.
+ #
+ # The MaxAgeOffset is not the final value of the offset, but
+ # rather it is used in creating the offset and allows the
+ # spreading to push the initial ages into the future or into the
+ # past. The pool is filled at startup as follows:
+ #
+ # for (int i = 0; i < poolMin; i++) {
+ # long ageOffset = (maxAge / poolMin * i * maxAgeOffset) % maxAge;
+ # pool.add(new Bean(), ageOffset));
+ # }
+ #
+ # The default MaxAgeOffset is -1 which causes the initial
+ # instances in the pool to live a bit longer before expiring. As
+ # a concrete example, let's say the PoolMin is 4 and the MaxAge is
+ # 100 years. The generated offsets for the four instances created
+ # at startup would be 0, -25, -50, -75. So the first instance
+ # would be "born" at age 0, die at 100, living 100 years. The
+ # second instance would be born at -25, die at 100, living a total
+ # of 125 years. The third would live 150 years. The fourth 175
+ # years.
+ #
+ # A MaxAgeOffset of 1 would cause instances to be "born" older
+ # and therefore die sooner. Using the same example PoolMin of 4
+ # and MaxAge of 100 years, the life spans of these initial four
+ # instances would be 100, 75, 50, and 25 years respectively.
+ #
+ # A MaxAgeOffset of 0 will cause no "spreading" of the age of the
+ # first instances used to fill the pool to the minimum and these
+ # instances will of course reach their MaxAge at the same time.
+ # It is possible to set to decimal values such as -0.5, 0.5, -1.2,
+ # or 1.2.
+
+ MaxAgeOffset = -1
+
# Specifies the maximum time that an instance should be allowed to
# sit idly in the pool without use before it should be retired and
# removed.
@@ -177,6 +242,15 @@
PollInterval = 5 minutes
+ # When sweeping the pool for expired instances a thread pool is
+ # used to process calling @PreDestroy on expired instances as well
+ # as creating new instances as might be required to fill the pool
+ # to the minimum after a Flush or MaxAge expiration. The
+ # CallbackThreads setting dictates the size of the thread pool and
+ # is shared by all beans deployed in the container.
+
+ CallbackThreads = 5
+
</ServiceProvider>
Modified:
openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
(original)
+++
openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -102,14 +102,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -118,6 +110,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -149,6 +158,62 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
+ # Applies to MaxAge usage and would rarely be changed, but is a
+ # nice feature to understand.
+ #
+ # When the container first starts and the pool is filled to the
+ # minimum size, all those "minimum" instances will have the same
+ # creation time and therefore all expire at the same time dictated
+ # by the MaxAge setting. To protect against this sudden drop
+ # scenario and provide a more gradual expiration from the start
+ # the container will spread out the age of the instances that fill
+ # the pool to the minimum using an offset.
+ #
+ # The MaxAgeOffset is not the final value of the offset, but
+ # rather it is used in creating the offset and allows the
+ # spreading to push the initial ages into the future or into the
+ # past. The pool is filled at startup as follows:
+ #
+ # for (int i = 0; i < poolMin; i++) {
+ # long ageOffset = (maxAge / poolMin * i * maxAgeOffset) % maxAge;
+ # pool.add(new Bean(), ageOffset));
+ # }
+ #
+ # The default MaxAgeOffset is -1 which causes the initial
+ # instances in the pool to live a bit longer before expiring. As
+ # a concrete example, let's say the PoolMin is 4 and the MaxAge is
+ # 100 years. The generated offsets for the four instances created
+ # at startup would be 0, -25, -50, -75. So the first instance
+ # would be "born" at age 0, die at 100, living 100 years. The
+ # second instance would be born at -25, die at 100, living a total
+ # of 125 years. The third would live 150 years. The fourth 175
+ # years.
+ #
+ # A MaxAgeOffset of 1 would cause instances to be "born" older
+ # and therefore die sooner. Using the same example PoolMin of 4
+ # and MaxAge of 100 years, the life spans of these initial four
+ # instances would be 100, 75, 50, and 25 years respectively.
+ #
+ # A MaxAgeOffset of 0 will cause no "spreading" of the age of the
+ # first instances used to fill the pool to the minimum and these
+ # instances will of course reach their MaxAge at the same time.
+ # It is possible to set to decimal values such as -0.5, 0.5, -1.2,
+ # or 1.2.
+
+ MaxAgeOffset = -1
+
# Specifies the maximum time that an instance should be allowed to
# sit idly in the pool without use before it should be retired and
# removed.
@@ -177,6 +242,15 @@
PollInterval = 5 minutes
+ # When sweeping the pool for expired instances a thread pool is
+ # used to process calling @PreDestroy on expired instances as well
+ # as creating new instances as might be required to fill the pool
+ # to the minimum after a Flush or MaxAge expiration. The
+ # CallbackThreads setting dictates the size of the thread pool and
+ # is shared by all beans deployed in the container.
+
+ CallbackThreads = 5
+
</ServiceProvider>
Modified:
openejb/trunk/openejb3/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
(original)
+++
openejb/trunk/openejb3/assembly/openejb-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -102,14 +102,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -118,6 +110,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -149,6 +158,62 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
+ # Applies to MaxAge usage and would rarely be changed, but is a
+ # nice feature to understand.
+ #
+ # When the container first starts and the pool is filled to the
+ # minimum size, all those "minimum" instances will have the same
+ # creation time and therefore all expire at the same time dictated
+ # by the MaxAge setting. To protect against this sudden drop
+ # scenario and provide a more gradual expiration from the start
+ # the container will spread out the age of the instances that fill
+ # the pool to the minimum using an offset.
+ #
+ # The MaxAgeOffset is not the final value of the offset, but
+ # rather it is used in creating the offset and allows the
+ # spreading to push the initial ages into the future or into the
+ # past. The pool is filled at startup as follows:
+ #
+ # for (int i = 0; i < poolMin; i++) {
+ # long ageOffset = (maxAge / poolMin * i * maxAgeOffset) % maxAge;
+ # pool.add(new Bean(), ageOffset));
+ # }
+ #
+ # The default MaxAgeOffset is -1 which causes the initial
+ # instances in the pool to live a bit longer before expiring. As
+ # a concrete example, let's say the PoolMin is 4 and the MaxAge is
+ # 100 years. The generated offsets for the four instances created
+ # at startup would be 0, -25, -50, -75. So the first instance
+ # would be "born" at age 0, die at 100, living 100 years. The
+ # second instance would be born at -25, die at 100, living a total
+ # of 125 years. The third would live 150 years. The fourth 175
+ # years.
+ #
+ # A MaxAgeOffset of 1 would cause instances to be "born" older
+ # and therefore die sooner. Using the same example PoolMin of 4
+ # and MaxAge of 100 years, the life spans of these initial four
+ # instances would be 100, 75, 50, and 25 years respectively.
+ #
+ # A MaxAgeOffset of 0 will cause no "spreading" of the age of the
+ # first instances used to fill the pool to the minimum and these
+ # instances will of course reach their MaxAge at the same time.
+ # It is possible to set to decimal values such as -0.5, 0.5, -1.2,
+ # or 1.2.
+
+ MaxAgeOffset = -1
+
# Specifies the maximum time that an instance should be allowed to
# sit idly in the pool without use before it should be retired and
# removed.
@@ -177,6 +242,15 @@
PollInterval = 5 minutes
+ # When sweeping the pool for expired instances a thread pool is
+ # used to process calling @PreDestroy on expired instances as well
+ # as creating new instances as might be required to fill the pool
+ # to the minimum after a Flush or MaxAge expiration. The
+ # CallbackThreads setting dictates the size of the thread pool and
+ # is shared by all beans deployed in the container.
+
+ CallbackThreads = 5
+
</ServiceProvider>
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainerFactory.java
Sat Apr 3 06:20:37 2010
@@ -97,6 +97,14 @@ public class StatelessContainerFactory {
pool.setPollInterval(interval);
}
+ public void setReplaceAged(boolean replaceAged) {
+ pool.setReplaceAged(replaceAged);
+ }
+
+ public void setMaxAgeOffset(double maxAgeOffset) {
+ pool.setMaxAgeOffset(maxAgeOffset);
+ }
+
public StatelessContainer create() {
return new StatelessContainer(id, securityService, accessTimeout,
pool, callbackThreads);
}
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
Sat Apr 3 06:20:37 2010
@@ -88,7 +88,7 @@ public class StatelessInstanceManager {
this.deploymentInfo = deploymentInfo;
}
- public void discard(Instance instance) {
+ public void discard(Instance instance, Pool.Event reason) {
ThreadContext ctx = new ThreadContext(deploymentInfo, null);
ThreadContext oldCallContext = ThreadContext.enter(ctx);
try {
@@ -398,9 +398,7 @@ public class StatelessInstanceManager {
if (obj == null) continue;
- long offset = 0;
-
- if (maxAge > 0) offset = ((long) (maxAge / min * i *
maxAgeOffset)) % maxAge;
+ long offset = maxAge > 0 ? ((long) (maxAge / min * i *
maxAgeOffset)) % maxAge : 0l;
data.getPool().add(obj, offset);
}
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=930484&r1=930483&r2=930484&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
Sat Apr 3 06:20:37 2010
@@ -59,9 +59,11 @@ public class Pool<T> {
private final AtomicInteger poolVersion = new AtomicInteger();
private final Supplier<T> supplier;
private final AtomicReference<Timer> timer = new AtomicReference<Timer>();
- private Pool<T>.Eviction evictor;
- private long interval;
-
+ private final Sweeper sweeper;
+ private final long interval;
+ private final boolean replaceAged;
+ private double maxAgeOffset;
+
public static class Builder<T> {
private int max = 10;
@@ -73,6 +75,7 @@ public class Pool<T> {
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;
@@ -84,6 +87,7 @@ public class Pool<T> {
this.executor = that.executor;
this.supplier = that.supplier;
this.maxAgeOffset = that.maxAgeOffset;
+ this.replaceAged = that.replaceAged;
}
public Builder() {
@@ -93,6 +97,10 @@ public class Pool<T> {
return min;
}
+ public void setReplaceAged(boolean replaceAged) {
+ this.replaceAged = replaceAged;
+ }
+
public void setPoolMax(int max) {
this.max = max;
}
@@ -147,15 +155,15 @@ public class Pool<T> {
}
public Pool<T> build() {
- return new Pool(max, min, strict, maxAge.getTime(MILLISECONDS),
idleTimeout.getTime(MILLISECONDS), interval.getTime(MILLISECONDS), executor,
supplier);
+ return new Pool(max, min, strict, maxAge.getTime(MILLISECONDS),
idleTimeout.getTime(MILLISECONDS), interval.getTime(MILLISECONDS), executor,
supplier, false);
}
}
public Pool(int max, int min, boolean strict) {
- this(max, min, strict, 0, 0, 0, null, null);
+ this(max, min, strict, 0, 0, 0, null, null, false);
}
- public Pool(int max, int min, boolean strict, long maxAge, long
idleTimeout, long interval, Executor executor, Supplier<T> supplier) {
+ public Pool(int max, int min, boolean strict, long maxAge, long
idleTimeout, long interval, Executor executor, Supplier<T> supplier, boolean
replaceAged) {
if (min > max) greater("max", max, "min", min);
if (maxAge != 0 && idleTimeout > maxAge) greater("MaxAge", maxAge,
"IdleTimeout", idleTimeout);
this.executor = executor != null ? executor : createExecutor();
@@ -164,16 +172,16 @@ public class Pool<T> {
this.minimum = new Semaphore(min);
this.instances = new Semaphore(max);
this.maxAge = maxAge;
-
+ this.replaceAged = replaceAged;
if (interval == 0) interval = 5 * 60 * 1000; // five minutes
this.interval = interval;
- evictor = new Eviction(idleTimeout, max);
+ sweeper = new Sweeper(idleTimeout, max);
}
public Pool start() {
if (timer.compareAndSet(null, new Timer("PoolEviction@" + hashCode(),
true))) {
- timer.get().scheduleAtFixedRate(evictor, 0, this.interval);
+ timer.get().scheduleAtFixedRate(sweeper, 0, this.interval);
}
return this;
}
@@ -309,7 +317,7 @@ public class Pool<T> {
return push(new Entry<T>(obj, offset, poolVersion.get()));
}
- if (obj != null) supplier.discard(obj);
+ if (obj != null) supplier.discard(obj, Event.FULL);
return false;
}
@@ -320,6 +328,7 @@ public class Pool<T> {
private boolean push(Entry<T> entry, boolean sweeper) {
boolean added = false;
boolean release = true;
+ Event event = Event.FULL;
final T obj = (entry == null) ? null : entry.active.getAndSet(null);
@@ -334,7 +343,9 @@ public class Pool<T> {
final boolean flushed = entry.version != this.poolVersion.get();
if (aged || flushed) {
- if (entry.hasHardReference()) {
+ if (aged) event = Event.AGED;
+ if (flushed) event = Event.FLUSHED;
+ if (entry.hasHardReference() || aged && replaceAged) {
// Don't release the lock, this
// entry will be directly replaced
release = false;
@@ -364,9 +375,9 @@ public class Pool<T> {
// if the caller is the PoolEviction thread, we do not
// want to be calling discard() directly and should just
// queue it up instead.
- executor.execute(new Discard(obj));
+ executor.execute(new Discard(obj, event));
} else {
- supplier.discard(obj);
+ supplier.discard(obj, event);
}
}
@@ -495,14 +506,14 @@ public class Pool<T> {
}
}
- private final class Eviction extends TimerTask {
+ private final class Sweeper extends TimerTask {
private final AtomicInteger previousVersion = new
AtomicInteger(poolVersion.get());
private final long idleTimeout;
private final boolean timeouts;
private final int max;
- private Eviction(long idleTimeout, int max) {
+ private Sweeper(long idleTimeout, int max) {
this.idleTimeout = idleTimeout;
timeouts = maxAge > 0 || idleTimeout > 0;
this.max = max;
@@ -558,10 +569,10 @@ public class Pool<T> {
// Entry is too old, expire it
iter.remove();
- final Expired expired = new Expired(entry);
+ final Expired expired = new Expired(entry, aged ?
Event.AGED : Event.FLUSHED);
expiredList.add(expired);
- if (!expired.entry.hasHardReference()) {
+ if (!expired.entry.hasHardReference() && !(aged &&
replaceAged)) {
expired.tryDiscard();
}
@@ -612,7 +623,7 @@ public class Pool<T> {
if (idleTimeout > 0 && idle > idleTimeout) {
// too lazy -- timed out
- final Expired expired = new Expired(entry);
+ final Expired expired = new Expired(entry, Event.AGED);
expiredList.add(expired);
@@ -629,24 +640,40 @@ public class Pool<T> {
// If there are any "min" pool instances left over
// we need to queue up creation of a replacement
+ List<Expired> replace = new ArrayList<Expired>();
+
for (Expired expired : expiredList) {
- executor.execute(new Discard(expired.entry.get()));
+ executor.execute(new Discard(expired.entry.get(),
expired.event));
- if (expired.entry.hasHardReference()) {
- executor.execute(new Replace(expired.entry));
+ if (expired.entry.hasHardReference() || expired.aged() &&
replaceAged) {
+ replace.add(expired);
}
}
+ for (int i = 0; i < replace.size(); i++) {
+ long offset = maxAge > 0 ? ((long) (maxAge / replace.size() *
i * maxAgeOffset)) % maxAge : 0l;
+ executor.execute(new Replace(replace.get(i).entry, offset));
+ }
}
}
+ public static enum Event {
+ FULL, IDLE, AGED, FLUSHED
+ }
+
private class Expired {
private final Entry<T> entry;
private final AtomicBoolean discarded = new AtomicBoolean();
+ private final Event event;
- private Expired(Entry<T> entry) {
+ private Expired(Entry<T> entry, Event event) {
this.entry = entry;
+ this.event = event;
+ }
+
+ public boolean aged() {
+ return event == Event.AGED;
}
public boolean tryDiscard() {
@@ -670,9 +697,15 @@ public class Pool<T> {
private class Replace implements Runnable {
private final Entry<T> expired;
+ private final long offset;
private Replace(Entry<T> expired) {
+ this(expired, 0);
+ }
+
+ private Replace(Entry<T> expired, long offset) {
this.expired = expired;
+ this.offset = offset;
}
public void run() {
@@ -682,8 +715,8 @@ public class Pool<T> {
if (t == null) {
discard(expired);
} else {
- final Entry entry = new Entry(t, 0 , poolVersion.get());
- entry.hard.set(t);
+ final Entry entry = new Entry(t, offset,
poolVersion.get());
+ if (expired.hasHardReference()) entry.hard.set(t);
push(entry);
}
} catch (Throwable e) {
@@ -696,27 +729,29 @@ public class Pool<T> {
private class Discard implements Runnable {
private final T expired;
+ private final Event event;
- private Discard(T expired) {
+ private Discard(T expired, Event event) {
if (expired == null) throw new NullPointerException("expired
object cannot be null");
this.expired = expired;
+ this.event = event;
}
public void run() {
- supplier.discard(expired);
+ supplier.discard(expired, event);
}
}
public static interface Supplier<T> {
- void discard(T t);
+ void discard(T t, Event reason);
T create();
}
private static class NoSupplier implements Supplier {
- public void discard(Object o) {
+ public void discard(Object o, Event reason) {
}
public Object create() {
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -95,14 +95,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -111,6 +103,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -142,6 +151,62 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
+ # Applies to MaxAge usage and would rarely be changed, but is a
+ # nice feature to understand.
+ #
+ # When the container first starts and the pool is filled to the
+ # minimum size, all those "minimum" instances will have the same
+ # creation time and therefore all expire at the same time dictated
+ # by the MaxAge setting. To protect against this sudden drop
+ # scenario and provide a more gradual expiration from the start
+ # the container will spread out the age of the instances that fill
+ # the pool to the minimum using an offset.
+ #
+ # The MaxAgeOffset is not the final value of the offset, but
+ # rather it is used in creating the offset and allows the
+ # spreading to push the initial ages into the future or into the
+ # past. The pool is filled at startup as follows:
+ #
+ # for (int i = 0; i < poolMin; i++) {
+ # long ageOffset = (maxAge / poolMin * i * maxAgeOffset) % maxAge;
+ # pool.add(new Bean(), ageOffset));
+ # }
+ #
+ # The default MaxAgeOffset is -1 which causes the initial
+ # instances in the pool to live a bit longer before expiring. As
+ # a concrete example, let's say the PoolMin is 4 and the MaxAge is
+ # 100 years. The generated offsets for the four instances created
+ # at startup would be 0, -25, -50, -75. So the first instance
+ # would be "born" at age 0, die at 100, living 100 years. The
+ # second instance would be born at -25, die at 100, living a total
+ # of 125 years. The third would live 150 years. The fourth 175
+ # years.
+ #
+ # A MaxAgeOffset of 1 would cause instances to be "born" older
+ # and therefore die sooner. Using the same example PoolMin of 4
+ # and MaxAge of 100 years, the life spans of these initial four
+ # instances would be 100, 75, 50, and 25 years respectively.
+ #
+ # A MaxAgeOffset of 0 will cause no "spreading" of the age of the
+ # first instances used to fill the pool to the minimum and these
+ # instances will of course reach their MaxAge at the same time.
+ # It is possible to set to decimal values such as -0.5, 0.5, -1.2,
+ # or 1.2.
+
+ MaxAgeOffset = -1
+
# Specifies the maximum time that an instance should be allowed to
# sit idly in the pool without use before it should be retired and
# removed.
@@ -170,6 +235,15 @@
PollInterval = 5 minutes
+ # When sweeping the pool for expired instances a thread pool is
+ # used to process calling @PreDestroy on expired instances as well
+ # as creating new instances as might be required to fill the pool
+ # to the minimum after a Flush or MaxAge expiration. The
+ # CallbackThreads setting dictates the size of the thread pool and
+ # is shared by all beans deployed in the container.
+
+ CallbackThreads = 5
+
</ServiceProvider>
<!--
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -97,14 +97,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -113,6 +105,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -144,6 +153,18 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
# Applies to MaxAge usage and would rarely be changed, but is a
# nice feature to understand.
#
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/resources/default.openejb.conf
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/default.openejb.conf?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/resources/default.openejb.conf
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/resources/default.openejb.conf
Sat Apr 3 06:20:37 2010
@@ -77,22 +77,31 @@
AccessTimeout = 0 milliseconds
+ # Specifies the size of the bean pools for this stateless
+ # SessionBean container. If StrictPooling is not used, instances
+ # will still be created beyond this number if there is demand, but
+ # they will not be returned to the pool and instead will be
+ # immediately destroyed.
+
+ PoolSize 10
+
# Specifies the minimum number of bean instances that should be
# in the pool for each bean. Pools are prefilled to the minimum
# on startup. Pool "shrinking" is achived through SoftReferences
# and natural vm garbage collection. All but the minimum are allowed
# to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
PoolMin 0
- # Specifies the maximum number of bean instances that should be
- # in the pool for each bean. If StrictPooling is not used, instances
- # will still be created beyond this number if there is demand, but
- # they will not be returned to the pool and instead will be
- # immediately destroyed.
-
- PoolSize 10
-
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -140,18 +149,6 @@
IdleTimeout = 0 minutes
- # The frequency in which the container will sweep the pool and
- # evict expired instances. Eviction is how the IdleTimeout,
- # MaxAge, and pool "flush" functionality is enforced. Higher
- # intervals are better. Expired instances in use while the pool
- # is swept will still be evicted upon return to the pool.
- #
- # Usable time units: nanoseconds, microsecons, milliseconds,
- # seconds, minutes, hours, days. Or any combination such as
- # "1 hour and 27 minutes and 10 seconds"
-
- PollInterval = 5 minutes
-
</Container>
Modified:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PoolTest.java
Sat Apr 3 06:20:37 2010
@@ -27,8 +27,6 @@ import static java.util.concurrent.TimeU
import java.util.concurrent.TimeoutException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
-import java.io.File;
-import java.io.IOException;
/**
* @version $Rev$ $Date$
@@ -109,7 +107,7 @@ public class PoolTest extends TestCase {
builder.setPoolMax(0);
builder.setStrictPooling(false);
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
}
@@ -285,7 +283,7 @@ public class PoolTest extends TestCase {
builder.setIdleTimeout(new Duration(idleTimeout,
TimeUnit.MILLISECONDS));
builder.setPollInterval(new Duration(sweepInterval,
TimeUnit.MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
discarded.add(bean);
discard.countDown();
@@ -371,7 +369,7 @@ public class PoolTest extends TestCase {
builder.setPoolMax(max);
builder.setPollInterval(new Duration(sweepInterval,
TimeUnit.MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
discarded.add(bean);
discard.countDown();
@@ -507,7 +505,7 @@ public class PoolTest extends TestCase {
builder.setMaxAge(new Duration(maxAge, MILLISECONDS));
builder.setPollInterval(new Duration(sweepInterval, MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
discarded.add(bean);
countDown(discard, bean, "discarded");
@@ -659,7 +657,7 @@ public class PoolTest extends TestCase {
builder.setPoolMax(max);
builder.setPollInterval(new Duration(poll, TimeUnit.MILLISECONDS));
builder.setSupplier(new Pool.Supplier() {
- public void discard(Object o) {
+ public void discard(Object o, Pool.Event reason) {
discarded.countDown();
}
@@ -816,7 +814,7 @@ public class PoolTest extends TestCase {
builder.setMaxAge(new Duration(maxAge, MILLISECONDS));
builder.setPollInterval(new Duration(poll, MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean o) {
+ public void discard(Bean o, Pool.Event reason) {
countDown(discarded, o, "discarded");
}
@@ -976,7 +974,7 @@ public class PoolTest extends TestCase {
builder.setPoolMax(max);
builder.setPollInterval(new Duration(sweepInterval,
TimeUnit.MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
}
@@ -1115,7 +1113,7 @@ public class PoolTest extends TestCase {
builder.setMaxAge(new Duration(maxAge, MILLISECONDS));
builder.setPollInterval(new Duration(sweepInterval, MILLISECONDS));
builder.setSupplier(new Pool.Supplier<Bean>() {
- public void discard(Bean bean) {
+ public void discard(Bean bean, Pool.Event reason) {
bean.discard();
}
Modified:
openejb/trunk/openejb3/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=930484&r1=930483&r2=930484&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
(original)
+++
openejb/trunk/openejb3/container/openejb-osgi/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
Sat Apr 3 06:20:37 2010
@@ -97,14 +97,6 @@
AccessTimeout = 0 milliseconds
- # Specifies the minimum number of bean instances that should be
- # in the pool for each bean. Pools are prefilled to the minimum
- # on startup. Pool "shrinking" is achived through SoftReferences
- # and natural vm garbage collection. All but the minimum are allowed
- # to be garbage collected by the VM when memory is needed.
-
- PoolMin 0
-
# Specifies the size of the bean pools for this stateless
# SessionBean container. If StrictPooling is not used, instances
# will still be created beyond this number if there is demand, but
@@ -113,6 +105,23 @@
PoolSize 10
+ # Specifies the minimum number of bean instances that should be
+ # in the pool for each bean. Pools are prefilled to the minimum
+ # on startup. Pool "shrinking" is achived through SoftReferences
+ # and natural vm garbage collection. All but the minimum are allowed
+ # to be garbage collected by the VM when memory is needed.
+ #
+ # The minimum pool size is rigidly maintained. The minimum side
+ # of the pool is not eligible for IdleTimeout, but is subject to
+ # MaxAge and flushing. When the pool is flushed, the pool is
+ # immediately refilled to the minimum size with MaxAgeOffset
+ # applied. When an instance from the minimum side of the pool
+ # reaches it's MaxAge, it is also immediately replaced.
+ # Replacement is done in a background queue using the number of
+ # threads specified by CallbackThreads.
+
+ PoolMin 0
+
# StrictPooling tells the container what to do when the pool
# reaches it's maximum size and there are incoming requests that
# need instances.
@@ -144,6 +153,62 @@
MaxAge = 0 hours
+ # Instances from the minimum side of the pool are always replaced
+ # when they reach their MaxAge. When this option is enabled, any
+ # instances in the pool that expire due to reaching their MaxAge
+ # will be replaced immediately so that the pool will remain at
+ # it's current size. Replacement is done in a background queue so
+ # that incoming threads will not have to wait for instance
+ # creation. The aim of his option is to prevent user requests
+ # from paying the instance creation cost as MaxAge is enforced,
+ # potentially while under heavy load.
+
+ ReplaceAged = true
+
+ # Applies to MaxAge usage and would rarely be changed, but is a
+ # nice feature to understand.
+ #
+ # When the container first starts and the pool is filled to the
+ # minimum size, all those "minimum" instances will have the same
+ # creation time and therefore all expire at the same time dictated
+ # by the MaxAge setting. To protect against this sudden drop
+ # scenario and provide a more gradual expiration from the start
+ # the container will spread out the age of the instances that fill
+ # the pool to the minimum using an offset.
+ #
+ # The MaxAgeOffset is not the final value of the offset, but
+ # rather it is used in creating the offset and allows the
+ # spreading to push the initial ages into the future or into the
+ # past. The pool is filled at startup as follows:
+ #
+ # for (int i = 0; i < poolMin; i++) {
+ # long ageOffset = (maxAge / poolMin * i * maxAgeOffset) % maxAge;
+ # pool.add(new Bean(), ageOffset));
+ # }
+ #
+ # The default MaxAgeOffset is -1 which causes the initial
+ # instances in the pool to live a bit longer before expiring. As
+ # a concrete example, let's say the PoolMin is 4 and the MaxAge is
+ # 100 years. The generated offsets for the four instances created
+ # at startup would be 0, -25, -50, -75. So the first instance
+ # would be "born" at age 0, die at 100, living 100 years. The
+ # second instance would be born at -25, die at 100, living a total
+ # of 125 years. The third would live 150 years. The fourth 175
+ # years.
+ #
+ # A MaxAgeOffset of 1 would cause instances to be "born" older
+ # and therefore die sooner. Using the same example PoolMin of 4
+ # and MaxAge of 100 years, the life spans of these initial four
+ # instances would be 100, 75, 50, and 25 years respectively.
+ #
+ # A MaxAgeOffset of 0 will cause no "spreading" of the age of the
+ # first instances used to fill the pool to the minimum and these
+ # instances will of course reach their MaxAge at the same time.
+ # It is possible to set to decimal values such as -0.5, 0.5, -1.2,
+ # or 1.2.
+
+ MaxAgeOffset = -1
+
# Specifies the maximum time that an instance should be allowed to
# sit idly in the pool without use before it should be retired and
# removed.
@@ -172,6 +237,15 @@
PollInterval = 5 minutes
+ # When sweeping the pool for expired instances a thread pool is
+ # used to process calling @PreDestroy on expired instances as well
+ # as creating new instances as might be required to fill the pool
+ # to the minimum after a Flush or MaxAge expiration. The
+ # CallbackThreads setting dictates the size of the thread pool and
+ # is shared by all beans deployed in the container.
+
+ CallbackThreads = 5
+
</ServiceProvider>