1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2000-2001,2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: LeaseManager.java,v 1.22 2003/10/29 04:58:32 tanderson Exp $
44 *
45 * Date Author Changes
46 * 3/01/2000 jima Created
47 */
48 package org.exolab.jms.lease;
49
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54 import org.exolab.core.service.BasicService;
55 import org.exolab.core.service.ServiceException;
56 import org.exolab.core.service.ServiceState;
57 import org.exolab.core.util.OrderedQueue;
58 import org.exolab.jms.message.MessageHandle;
59
60
61 /***
62 * The LeaseManager is responsible for creating and managing the lease objects.
63 * The Leasemanager is a singleton. When a BaseLease object is created it is
64 * added to the queue according to the duration (i.e. leases with shorter
65 * durations are placed at the top of the queue.
66 * <p>
67 * When the lease expires the LeeaseManager calls the leasee's associated
68 * listener(s).
69 * <p>
70 * We need to cater for persistence and non-persistent leases
71 *
72 * @version $Revision: 1.22 $ $Date: 2003/10/29 04:58:32 $
73 * @author <a href="mailto:jima@intalio.com">Jim Alateras</a>
74 */
75 public class LeaseManager extends BasicService {
76
77 /***
78 * The name of the LeaseManagerThread that scans and removes expired leases
79 */
80 private static final String LEASE_MANAGER_THREAD_NAME =
81 "LeaseManagerReaper";
82
83 /***
84 * An ordered list of leases
85 */
86 private OrderedQueue _queue = null;
87
88 /***
89 * The singleton instance of the LeaseManager
90 */
91 private static LeaseManager _instance = new LeaseManager();
92
93 /***
94 * Helper for waiting for leases to expire
95 */
96 private final Object _waiter = new Object();
97
98 /***
99 * The logger
100 */
101 private static final Log _log = LogFactory.getLog(LeaseManager.class);
102
103
104 /***
105 * Create a new sorted tree set using the lease comparator as the
106 * sorting functor.
107 */
108 protected LeaseManager() {
109 super(LEASE_MANAGER_THREAD_NAME);
110 _queue = new OrderedQueue(new LeaseComparator());
111 }
112
113 /***
114 * Return the singleton instance of the LeaseManager
115 *
116 * @return LeaseManager
117 */
118 public static LeaseManager instance() {
119 return _instance;
120 }
121
122 /***
123 * Create a message lease with the specified duration and the nominated
124 * listener. The listener does not to be specified but is merely a
125 * convenience argument.
126 * <p>
127 * The object must be non-null and the duration must be greater than zero.
128 *
129 * @param handle message handle
130 * @param duration lease duration
131 * @param listener object that implements the LeaseEvent-
132 * ListenerIfc
133 * @return MessageLease creared lease object or null if no lease
134 * is created
135 */
136 public MessageLease createMessageLease(MessageHandle handle,
137 long duration,
138 LeaseEventListenerIfc listener) {
139 MessageLease result = null;
140
141 if ((handle != null) && (duration > 0)) {
142 result = new MessageLease(handle, duration, listener);
143 addLease(result);
144 }
145
146 return result;
147 }
148
149 /***
150 * Create a lease on any object for the specified duration. If a listener
151 * is also provided then add it to the lease. Insert the lease in the queue
152 * and return an instance of the created lease.
153 * <p>
154 * The object must be non-null and the duration must be greater than zero.
155 *
156 * @param object leased object
157 * @param duration lease duration
158 * @param listener object that implements the LeaseEvent-
159 * ListenerIfc
160 * @return BaseLease creared lease object or null if no lease
161 * is created
162 */
163 public BaseLease createLease(Object object, long duration,
164 LeaseEventListenerIfc listener) {
165 BaseLease result = null;
166
167 if ((object != null) && (duration > 0)) {
168 result = new BaseLease(object, duration, listener);
169 addLease(result);
170 }
171
172 return result;
173 }
174
175 /***
176 * Remove the specified lease.
177 *
178 * @param lease lease to remove
179 * @return boolean true if successful; false otherwise
180 */
181 public boolean removeLease(BaseLease lease) {
182 boolean result = false;
183
184 synchronized (_queue) {
185 result = _queue.remove(lease);
186 }
187 if (result) {
188 synchronized (_waiter) {
189 _waiter.notify();
190 }
191 }
192
193 return result;
194 }
195
196 /***
197 * Renew the lease on the specified object
198 *
199 * @param object object's whose lease we want to renew
200 * @param duration the new duration of the lease in ms
201 */
202 public BaseLease renewLease(BaseLease lease, long duration) {
203 BaseLease newlease = null;
204
205 if ((lease != null) && (duration > 0)) {
206 synchronized (_queue) {
207 // check that the lease hasn't expired yet.
208 if (_queue.remove(lease)) {
209 lease.setDuration(duration);
210 _queue.add(lease);
211 newlease = lease;
212 synchronized (_waiter) {
213 _waiter.notify();
214 }
215 }
216 }
217 }
218
219 return newlease;
220 }
221
222 /***
223 * Remove all the leases from the queue. Do not expire any of them
224 */
225 public void removeAll() {
226 synchronized (_queue) {
227 _queue.clear();
228 }
229 }
230
231 /***
232 * Returns the number of active leases
233 *
234 * @return the number of leases
235 */
236 public int getLeaseCount() {
237 return _queue.size();
238 }
239
240 /***
241 * The run method will search for expired leases, remove them from the
242 * list and notify listeners
243 */
244 public void run() {
245 while (getState() != ServiceState.STOPPED) {
246 expire();
247
248 // wait until a lease is available, or the service is terminated
249 synchronized (_waiter) {
250 try {
251 _waiter.wait();
252 } catch (InterruptedException ignore) {
253 }
254 }
255 }
256 }
257
258 /***
259 * Stop the service.
260 *
261 * @throws ServiceException if the service fails to stop
262 */
263 public void stop() throws ServiceException {
264 super.stop();
265 synchronized (_waiter) {
266 _waiter.notifyAll();
267 }
268 }
269
270 /***
271 * Expires active leases
272 */
273 protected void expire() {
274 while (_queue.size() > 0) {
275 BaseLease lease = null;
276 boolean expired = false;
277 synchronized (_queue) {
278 lease = (BaseLease) _queue.firstElement();
279 if (lease == null) {
280 continue;
281 }
282
283 if (lease.getExpiryTime() <= System.currentTimeMillis()) {
284 // remove from the list and notify listeners
285 _queue.removeFirstElement();
286 expired = true;
287 }
288 }
289
290 if (expired) {
291 lease.notifyLeaseExpired();
292 } else {
293 // wait until the first element in the list is
294 // ready to expire
295 long time = lease.getExpiryTime() -
296 System.currentTimeMillis();
297
298 if (time > 0) {
299 try {
300 synchronized (_waiter) {
301 _waiter.wait(time);
302 }
303 } catch (InterruptedException ignore) {
304 }
305 }
306 }
307 }
308 }
309
310 /***
311 * Add a lease
312 *
313 * @param lease the lease to add
314 */
315 protected void addLease(BaseLease lease) {
316 synchronized (_queue) {
317 _queue.add(lease);
318 if (_queue.firstElement() == lease) {
319 // inserted before the first element, so reset scan
320 synchronized (_waiter) {
321 _waiter.notify();
322 }
323 }
324 }
325 }
326
327
328 } //-- LeaseManager
This page was automatically generated by Maven