Coverage Report - org.apache.commons.performance.pool.WaiterFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
WaiterFactory
0%
0/87
0%
0/20
0
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 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  
  * Object factory with configurable latencies for object lifecycle methods.
 32  
  *
 33  
  */
 34  
 public class WaiterFactory implements PoolableObjectFactory,
 35  
 KeyedPoolableObjectFactory {
 36  
     
 37  
     // TODO: implement protected getters so these can be stochastic
 38  0
     private long activateLatency = 0;
 39  0
     private long destroyLatency = 0;
 40  0
     private long makeLatency = 0;
 41  0
     private long passivateLatency = 0;
 42  0
     private long validateLatency = 0;
 43  0
     private long waiterLatency = 0;
 44  
     
 45  
     /** Count of (makes - destroys) since last reset */
 46  0
     private long activeCount = 0;
 47  
     
 48  
     /** Count of (makes - destroys) per key since last reset */
 49  0
     private Map<Object, AtomicInteger> activeCounts = 
 50  
         new HashMap<Object, AtomicInteger>();
 51  
     
 52  
     /** Maximum of (makes - destroys) - if exceeded IllegalStateException */
 53  0
     private long maxActive = Long.MAX_VALUE;
 54  
     
 55  
     /** Maximum of (makes - destroys) per key */
 56  0
     private long maxActivePerKey = Long.MAX_VALUE;
 57  
     
 58  0
     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  0
             long waiterLatency,long maxActive, long maxActivePerKey) {
 64  0
         this.activateLatency = activateLatency;
 65  0
         this.destroyLatency = destroyLatency;
 66  0
         this.makeLatency = makeLatency;
 67  0
         this.passivateLatency = passivateLatency;
 68  0
         this.validateLatency = validateLatency;
 69  0
         this.waiterLatency = waiterLatency;
 70  0
         this.maxActive = maxActive;
 71  0
         this.maxActivePerKey = maxActivePerKey;
 72  0
     }
 73  
     
 74  
     public WaiterFactory(long activateLatency, long destroyLatency,
 75  
             long makeLatency, long passivateLatency, long validateLatency,
 76  
             long waiterLatency) {
 77  0
         this(activateLatency, destroyLatency, makeLatency, passivateLatency,
 78  
                 validateLatency, waiterLatency, Long.MAX_VALUE, Long.MAX_VALUE);
 79  0
     }
 80  
     
 81  
     public WaiterFactory(long activateLatency, long destroyLatency,
 82  
             long makeLatency, long passivateLatency, long validateLatency,
 83  
             long waiterLatency,long maxActive) {
 84  0
         this(activateLatency, destroyLatency, makeLatency, passivateLatency,
 85  
                 validateLatency, waiterLatency, maxActive, Long.MAX_VALUE);
 86  0
     }
 87  
 
 88  
     public void activateObject(Object arg0) throws Exception {
 89  0
         if (logger.isLoggable(Level.FINEST)) {
 90  0
             logger.finest("activate");
 91  
         }
 92  0
         doWait(activateLatency);
 93  0
     }
 94  
 
 95  
     public void destroyObject(Object arg0) throws Exception {
 96  0
         if (logger.isLoggable(Level.FINE)) {
 97  0
             logger.fine("destroy");
 98  
         }
 99  0
         doWait(destroyLatency);
 100  0
         ((Waiter) arg0).setValid(false);
 101  
         // Decrement *after* destroy 
 102  0
         synchronized (this) {
 103  0
             activeCount--;
 104  0
         }
 105  0
     }
 106  
 
 107  
     public Object makeObject() throws Exception {
 108  
         // Increment and test *before* make
 109  0
         synchronized (this) {
 110  0
             if (activeCount >= maxActive) {
 111  0
                 throw new IllegalStateException("Too many active instances: " +
 112  
                 activeCount + " in circulation with maxActive = " + maxActive);
 113  
             } else {
 114  0
                 activeCount++;
 115  
             }
 116  0
         }
 117  0
         if (logger.isLoggable(Level.FINE)) {
 118  0
             logger.fine("makeObject");
 119  
         }
 120  0
         doWait(makeLatency);
 121  0
         return new Waiter(false, true, waiterLatency);
 122  
     }
 123  
 
 124  
     public void passivateObject(Object arg0) throws Exception {
 125  0
         if (logger.isLoggable(Level.FINEST)) {
 126  0
             logger.finest("passivate");
 127  
         }
 128  0
         ((Waiter) arg0).setActive(false);
 129  0
         doWait(passivateLatency);
 130  0
     }
 131  
 
 132  
     public boolean validateObject(Object arg0) {
 133  0
         if (logger.isLoggable(Level.FINE)) {
 134  0
             logger.fine("validate");
 135  
         }
 136  0
         doWait(validateLatency);
 137  0
         return ((Waiter) arg0).isValid();
 138  
     }
 139  
     
 140  
     protected void doWait(long latency) {
 141  
         try {
 142  0
             Thread.sleep(latency);
 143  0
         } catch (InterruptedException ex) {
 144  
             // ignore
 145  0
         }
 146  0
     }
 147  
     
 148  
     public synchronized void reset() {
 149  0
         activeCount = 0;
 150  0
         if (activeCounts.isEmpty()) {
 151  0
             return;
 152  
         }
 153  0
         Iterator it = activeCounts.keySet().iterator();
 154  0
         while (it.hasNext()) {
 155  0
             ((AtomicInteger) activeCounts.get(it.next())).getAndSet(0);
 156  
         }
 157  0
     }
 158  
 
 159  
     /**
 160  
      * @return the maxActive
 161  
      */
 162  
     public synchronized long getMaxActive() {
 163  0
         return maxActive;
 164  
     }
 165  
 
 166  
     /**
 167  
      * @param maxActive the maxActive to set
 168  
      */
 169  
     public synchronized void setMaxActive(long maxActive) {
 170  0
         this.maxActive = maxActive;
 171  0
     }
 172  
 
 173  
     // KeyedPoolableObjectFactory methods
 174  
     
 175  
     public void activateObject(Object key, Object obj) throws Exception {
 176  0
         activateObject(obj);
 177  0
     }
 178  
 
 179  
     public void destroyObject(Object key, Object obj) throws Exception {
 180  0
         destroyObject(obj);
 181  0
         ((AtomicInteger) activeCounts.get(key)).getAndDecrement(); 
 182  0
     }
 183  
 
 184  
     public Object makeObject(Object key) throws Exception {
 185  0
         synchronized (this) {
 186  0
             AtomicInteger count = (AtomicInteger) activeCounts.get(key);
 187  0
             if (count == null) {
 188  0
                 count = new AtomicInteger(1);
 189  0
                 activeCounts.put(key, count);
 190  
             } else {
 191  0
                 if (count.get() >= maxActivePerKey) {
 192  0
                     throw new IllegalStateException("Too many active " +
 193  
                     "instances for key = " + key + ": " + count.get() + 
 194  
                     " in circulation " + "with maxActivePerKey = " + 
 195  
                     maxActivePerKey);
 196  
                 } else {
 197  0
                     count.incrementAndGet();
 198  
                 }
 199  
             }
 200  0
         }
 201  0
         return makeObject();
 202  
     }
 203  
 
 204  
     public void passivateObject(Object key, Object obj) throws Exception {
 205  0
         passivateObject(obj);
 206  0
     }
 207  
 
 208  
     public boolean validateObject(Object key, Object obj) {
 209  0
         return validateObject(obj);
 210  
     }
 211  
 
 212  
 }