1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.performance.pool;
19
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Iterator;
23 import java.util.logging.Logger;
24 import java.util.logging.Level;
25 import java.util.concurrent.atomic.AtomicInteger;
26
27 import org.apache.commons.pool.PoolableObjectFactory;
28 import org.apache.commons.pool.KeyedPoolableObjectFactory;
29
30
31
32
33
34 public class WaiterFactory implements PoolableObjectFactory,
35 KeyedPoolableObjectFactory {
36
37
38 private long activateLatency = 0;
39 private long destroyLatency = 0;
40 private long makeLatency = 0;
41 private long passivateLatency = 0;
42 private long validateLatency = 0;
43 private long waiterLatency = 0;
44
45
46 private long activeCount = 0;
47
48
49 private Map<Object, AtomicInteger> activeCounts =
50 new HashMap<Object, AtomicInteger>();
51
52
53 private long maxActive = Long.MAX_VALUE;
54
55
56 private long maxActivePerKey = Long.MAX_VALUE;
57
58 protected static final Logger logger =
59 Logger.getLogger(WaiterFactory.class.getName());
60
61 public WaiterFactory(long activateLatency, long destroyLatency,
62 long makeLatency, long passivateLatency, long validateLatency,
63 long waiterLatency,long maxActive, long maxActivePerKey) {
64 this.activateLatency = activateLatency;
65 this.destroyLatency = destroyLatency;
66 this.makeLatency = makeLatency;
67 this.passivateLatency = passivateLatency;
68 this.validateLatency = validateLatency;
69 this.waiterLatency = waiterLatency;
70 this.maxActive = maxActive;
71 this.maxActivePerKey = maxActivePerKey;
72 }
73
74 public WaiterFactory(long activateLatency, long destroyLatency,
75 long makeLatency, long passivateLatency, long validateLatency,
76 long waiterLatency) {
77 this(activateLatency, destroyLatency, makeLatency, passivateLatency,
78 validateLatency, waiterLatency, Long.MAX_VALUE, Long.MAX_VALUE);
79 }
80
81 public WaiterFactory(long activateLatency, long destroyLatency,
82 long makeLatency, long passivateLatency, long validateLatency,
83 long waiterLatency,long maxActive) {
84 this(activateLatency, destroyLatency, makeLatency, passivateLatency,
85 validateLatency, waiterLatency, maxActive, Long.MAX_VALUE);
86 }
87
88 public void activateObject(Object arg0) throws Exception {
89 if (logger.isLoggable(Level.FINEST)) {
90 logger.finest("activate");
91 }
92 doWait(activateLatency);
93 }
94
95 public void destroyObject(Object arg0) throws Exception {
96 if (logger.isLoggable(Level.FINE)) {
97 logger.fine("destroy");
98 }
99 doWait(destroyLatency);
100 ((Waiter) arg0).setValid(false);
101
102 synchronized (this) {
103 activeCount--;
104 }
105 }
106
107 public Object makeObject() throws Exception {
108
109 synchronized (this) {
110 if (activeCount >= maxActive) {
111 throw new IllegalStateException("Too many active instances: " +
112 activeCount + " in circulation with maxActive = " + maxActive);
113 } else {
114 activeCount++;
115 }
116 }
117 if (logger.isLoggable(Level.FINE)) {
118 logger.fine("makeObject");
119 }
120 doWait(makeLatency);
121 return new Waiter(false, true, waiterLatency);
122 }
123
124 public void passivateObject(Object arg0) throws Exception {
125 if (logger.isLoggable(Level.FINEST)) {
126 logger.finest("passivate");
127 }
128 ((Waiter) arg0).setActive(false);
129 doWait(passivateLatency);
130 }
131
132 public boolean validateObject(Object arg0) {
133 if (logger.isLoggable(Level.FINE)) {
134 logger.fine("validate");
135 }
136 doWait(validateLatency);
137 return ((Waiter) arg0).isValid();
138 }
139
140 protected void doWait(long latency) {
141 try {
142 Thread.sleep(latency);
143 } catch (InterruptedException ex) {
144
145 }
146 }
147
148 public synchronized void reset() {
149 activeCount = 0;
150 if (activeCounts.isEmpty()) {
151 return;
152 }
153 Iterator it = activeCounts.keySet().iterator();
154 while (it.hasNext()) {
155 ((AtomicInteger) activeCounts.get(it.next())).getAndSet(0);
156 }
157 }
158
159
160
161
162 public synchronized long getMaxActive() {
163 return maxActive;
164 }
165
166
167
168
169 public synchronized void setMaxActive(long maxActive) {
170 this.maxActive = maxActive;
171 }
172
173
174
175 public void activateObject(Object key, Object obj) throws Exception {
176 activateObject(obj);
177 }
178
179 public void destroyObject(Object key, Object obj) throws Exception {
180 destroyObject(obj);
181 ((AtomicInteger) activeCounts.get(key)).getAndDecrement();
182 }
183
184 public Object makeObject(Object key) throws Exception {
185 synchronized (this) {
186 AtomicInteger count = (AtomicInteger) activeCounts.get(key);
187 if (count == null) {
188 count = new AtomicInteger(1);
189 activeCounts.put(key, count);
190 } else {
191 if (count.get() >= maxActivePerKey) {
192 throw new IllegalStateException("Too many active " +
193 "instances for key = " + key + ": " + count.get() +
194 " in circulation " + "with maxActivePerKey = " +
195 maxActivePerKey);
196 } else {
197 count.incrementAndGet();
198 }
199 }
200 }
201 return makeObject();
202 }
203
204 public void passivateObject(Object key, Object obj) throws Exception {
205 passivateObject(obj);
206 }
207
208 public boolean validateObject(Object key, Object obj) {
209 return validateObject(obj);
210 }
211
212 }