View Javadoc
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.pool2;
19  
20  import java.util.concurrent.atomic.AtomicInteger;
21  
22  /**
23   * <p>Object created by {@link WaiterFactory}. Maintains active / valid state,
24   * last passivated and idle times.  Waits with configurable latency when
25   * {@link #doWait()} method is called.</p>
26   *
27   * <p>This class is *not* threadsafe.</p>
28   */
29  public class Waiter {
30      private static final AtomicInteger instanceCount = new AtomicInteger();
31      /** TODO Reuse Apache Commons Lang ThreadUtils */
32      public static void sleepQuietly(final long millis) {
33          try {
34              Thread.sleep(millis);
35          } catch (final InterruptedException e) {
36              // be quiet
37          }
38      }
39      private boolean active;
40      private boolean valid;
41      private long latency;
42      private long lastPassivatedMillis;
43      private long lastIdleTimeMillis;
44      private long passivationCount;
45      private long validationCount;
46  
47      private final int id = instanceCount.getAndIncrement();
48  
49      public Waiter(final boolean active, final boolean valid, final long latency) {
50          this.active = active;
51          this.valid = valid;
52          this.latency = latency;
53          this.lastPassivatedMillis = System.currentTimeMillis();
54      }
55  
56      /**
57       * Wait for {@link #getLatency()} milliseconds.
58       */
59      public void doWait() {
60          sleepQuietly(latency);
61      }
62  
63      @Override
64      public boolean equals(final Object obj) {
65          if (!(obj instanceof Waiter)) {
66              return false;
67          }
68          return obj.hashCode() == id;
69      }
70  
71      /**
72       * <p>Returns the last idle time for this instance in ms.</p>
73       *
74       * <p>When an instance is created, and each subsequent time it is passivated,
75       * the {@link #getLastPassivatedMillis() lastPassivated} property is updated with the
76       * current time.  When the next activation occurs, {@code lastIdleTime} is
77       * updated with the elapsed time since passivation.<p>
78       *
79       * @return last idle time
80       */
81      public long getLastIdleTimeMillis() {
82          return lastIdleTimeMillis;
83      }
84  
85      /**
86       * <p>Returns the system time of this instance's last passivation.</p>
87       *
88       * <p>When an instance is created, this field is initialized to the system time.</p>
89       *
90       * @return time of last passivation
91       */
92      public long getLastPassivatedMillis() {
93          return lastPassivatedMillis;
94      }
95  
96      public long getLatency() {
97          return latency;
98      }
99  
100     /**
101      * @return how many times this instance has been passivated
102      */
103     public long getPassivationCount() {
104         return passivationCount;
105     }
106 
107     /**
108      * @return how many times this instance has been validated
109      */
110     public long getValidationCount() {
111         return validationCount;
112     }
113 
114     @Override
115     public int hashCode() {
116         return id;
117     }
118 
119     /**
120      * Whether or not the instance is active.
121      *
122      * @return true if the last lifecycle event for this instance was activation.
123      */
124     public boolean isActive() {
125         return active;
126     }
127 
128     public boolean isValid() {
129         validationCount++;
130         return valid;
131     }
132 
133     /**
134      * <p>Sets the active state and updates {@link #getLastIdleTimeMillis() lastIdleTime}
135      * or {@link #getLastPassivatedMillis() lastPassivated} as appropriate.</p>
136      *
137      * <p>If the active state is changing from inactive to active, lastIdleTime
138      * is updated with the current time minus lastPassivated.  If the state is
139      * changing from active to inactive, lastPassivated is updated with the
140      * current time.</p>
141      *
142      * <p>{@link WaiterFactory#activateObject(PooledObject)} and
143      * {@link WaiterFactory#passivateObject(PooledObject)} invoke this method on
144      * their actual parameter, passing {@code true} and {@code false},
145      * respectively.</p>
146      *
147      * @param active new active state
148      */
149     public void setActive(final boolean active) {
150         final boolean activeState = this.active;
151         if (activeState == active) {
152             return;
153         }
154         this.active = active;
155         final long currentTimeMillis = System.currentTimeMillis();
156         if (active) {  // activating
157             lastIdleTimeMillis = currentTimeMillis - lastPassivatedMillis;
158         } else {       // passivating
159             lastPassivatedMillis = currentTimeMillis;
160             passivationCount++;
161         }
162     }
163 
164     public void setLatency(final long latency) {
165         this.latency = latency;
166     }
167 
168     public void setValid(final boolean valid) {
169         this.valid = valid;
170     }
171 
172     @Override
173     public String toString() {
174         final StringBuilder buff = new StringBuilder();
175         buff.append("ID = " + id + '\n');
176         buff.append("valid = " + valid + '\n');
177         buff.append("active = " + active + '\n');
178         buff.append("lastPassivated = " + lastPassivatedMillis + '\n');
179         buff.append("lastIdleTimeMs = " + lastIdleTimeMillis + '\n');
180         buff.append("latency = " + latency + '\n');
181         return buff.toString();
182     }
183 }