View Javadoc

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-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: LeaseManager.java,v 1.4 2005/12/26 04:45:30 tanderson Exp $
44   */
45  package org.exolab.jms.lease;
46  
47  
48  import org.exolab.jms.service.BasicService;
49  import org.exolab.jms.service.ServiceException;
50  import org.exolab.jms.common.util.OrderedQueue;
51  
52  
53  /***
54   * The LeaseManager is responsible for creating and managing the lease objects.
55   * The Leasemanager is a singleton. When a BaseLease object is created it is
56   * added to the queue according to the duration (i.e. leases with shorter
57   * durations are placed at the top of the queue.
58   * <p>
59   * When the lease expires the LeeaseManager calls the leasee's associated
60   * listener(s).
61   *
62   * @version     $Revision: 1.4 $ $Date: 2005/12/26 04:45:30 $
63   * @author      <a href="mailto:jima@comware.com.au">Jim Alateras</a>
64   */
65  public class LeaseManager extends BasicService {
66  
67      /***
68       * An ordered list of leases.
69       */
70      private OrderedQueue _queue = null;
71  
72      /***
73       * Helper for waiting for leases to expire.
74       */
75      private final Object _waiter = new Object();
76  
77  
78      /***
79       * Create a new sorted tree set using the lease comparator as the
80       * sorting functor.
81       */
82      public LeaseManager() {
83          super("LeaseManager");
84          _queue = new OrderedQueue(new LeaseComparator());
85      }
86  
87      /***
88       * Add a lease.
89       *
90       * @param lease the lease to add
91       */
92      public void addLease(BaseLease lease) {
93          synchronized (_queue) {
94              _queue.add(lease);
95              if (_queue.firstElement() == lease) {
96                  // inserted before the first element, so reset scan
97                  synchronized (_waiter) {
98                      _waiter.notify();
99                  }
100             }
101         }
102     }
103 
104     /***
105      * Remove a lease.
106      *
107      * @param       lease           lease to remove
108      * @return      boolean         true if successful; false otherwise
109      */
110     public boolean removeLease(BaseLease lease) {
111         boolean result = false;
112 
113         synchronized (_queue) {
114             result = _queue.remove(lease);
115         }
116         if (result) {
117             synchronized (_waiter) {
118                 _waiter.notify();
119             }
120         }
121 
122         return result;
123     }
124 
125     /***
126      * Renew the lease on the specified object
127      *
128      * @param lease the lease to renew
129      * @param duration the new duration of the lease in ms
130      */
131     public BaseLease renewLease(BaseLease lease, long duration) {
132         BaseLease newlease = null;
133 
134         if ((lease != null) && (duration > 0)) {
135             synchronized (_queue) {
136                 // check that the lease hasn't expired yet.
137                 if (_queue.remove(lease)) {
138                     lease.setDuration(duration);
139                     _queue.add(lease);
140                     newlease = lease;
141                     synchronized (_waiter) {
142                         _waiter.notify();
143                     }
144                 }
145             }
146         }
147 
148         return newlease;
149     }
150 
151     /***
152      * Remove all the leases from the queue. Do not expire any of them
153      */
154     public void removeAll() {
155         synchronized (_queue) {
156             _queue.clear();
157         }
158     }
159 
160     /***
161      * The run method will search for expired leases, remove them from the
162      * list and notify listeners
163      */
164     public void run() {
165         while (!Thread.interrupted()) {
166             expire();
167 
168             // wait until a lease is available, or the service is terminated
169             synchronized (_waiter) {
170                 try {
171                     _waiter.wait();
172                 } catch (InterruptedException terminate) {
173                     break;
174                 }
175             }
176         }
177     }
178 
179     /***
180      * Stop the service.
181      *
182      * @throws ServiceException if the service fails to stop
183      */
184     public void doStop() throws ServiceException {
185         synchronized (_waiter) {
186             _waiter.notifyAll();
187         }
188     }
189 
190     /***
191      * Expires active leases
192      */
193     protected void expire() {
194         while (_queue.size() > 0) {
195             BaseLease lease = null;
196             boolean expired = false;
197             synchronized (_queue) {
198                 lease = (BaseLease) _queue.firstElement();
199                 if (lease == null) {
200                     continue;
201                 }
202                 
203                 if (lease.getExpiryTime() <= System.currentTimeMillis()) {
204                     // remove from the list and notify listeners
205                     _queue.removeFirstElement();
206                     expired = true;
207                 }
208             }
209 
210             if (expired) {
211                 lease.notifyLeaseExpired();
212             } else {
213                 // wait until the first element in the list is
214                 // ready to expire
215                 long time = lease.getExpiryTime() - 
216                     System.currentTimeMillis();
217                 
218                 if (time > 0) {
219                     try {
220                         synchronized (_waiter) {
221                             _waiter.wait(time);
222                         }
223                     } catch (InterruptedException ignore) {
224                     }
225                 }
226             }
227         }
228     }
229 
230 }