KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > locks > TransactionLogicalLock


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
4  * Contact: sequoia@continuent.org
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Initial developer(s): Emmanuel Cecchet.
19  * Contributor(s): _________________________.
20  */

21
22 package org.continuent.sequoia.controller.locks;
23
24 import java.util.Iterator JavaDoc;
25 import java.util.LinkedList JavaDoc;
26 import java.util.List JavaDoc;
27
28 import org.continuent.sequoia.controller.requests.AbstractRequest;
29
30 /**
31  * This class defines a <code>TransactionLogicalLock</code> which is an
32  * exclusive lock that let the owner of the lock acquire several times the lock
33  * (but it needs to be released only once). Acquire is not blocking but just a
34  * hint whether the lock has been granted or the request has been queued.
35  *
36  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet</a>
37  * @version 1.0
38  */

39 public class TransactionLogicalLock
40 {
41   private boolean isLocked = false;
42
43   /** Transaction id of the lock holder. */
44   private long locker;
45
46   /** <code>ArrayList</code> of <code>WaitingListElement</code>. */
47   private LinkedList JavaDoc waitingList = new LinkedList JavaDoc();
48
49   /**
50    * The element stored in the waiting list is the waiting request and the
51    * transaction id of the request.
52    */

53   protected class WaitingListElement
54   {
55     /** Waiting request */
56     AbstractRequest request;
57
58     /** Transaction id of the request waiting. */
59     long transactionId;
60
61     /**
62      * Creates a new <code>WaitingListElement</code> instance.
63      *
64      * @param request the waiting request.
65      * @param transactionId the transaction id of the request waiting.
66      */

67     WaitingListElement(AbstractRequest request, long transactionId)
68     {
69       this.request = request;
70       this.transactionId = transactionId;
71     }
72
73     /**
74      * Returns the transaction id of the request waiting.
75      *
76      * @return an <code>int</code> value
77      */

78     public long getTransactionId()
79     {
80       return transactionId;
81     }
82
83     /**
84      * Returns the waiting request.
85      *
86      * @return a <code>Thread</code> value
87      */

88     public AbstractRequest getRequest()
89     {
90       return request;
91     }
92
93     /**
94      * @see java.lang.Object#toString()
95      */

96     public String JavaDoc toString()
97     {
98       return String.valueOf(transactionId);
99     }
100
101   }
102
103   /**
104    * Acquires an exclusive lock on this table. If the lock is already held by
105    * the same transaction as the given request, this method is non-blocking else
106    * the caller is blocked until the transaction holding the lock releases it at
107    * commit/rollback time.
108    *
109    * @param request request asking for the lock (timeout field is used and
110    * updated upon waiting)
111    * @return boolean true is the lock has been successfully acquired, false on
112    * timeout or error
113    * @see #release(long)
114    */

115   public boolean acquire(AbstractRequest request)
116   {
117     long tid = request.getTransactionId();
118
119     synchronized (this)
120     {
121       if (!isLocked)
122       { // Lock is free, take it
123
locker = tid;
124         isLocked = true;
125         return true;
126       }
127       else
128       {
129         if (locker == tid)
130           return true; // We already have the lock
131
else
132         { // Wait for the lock
133
if (!isWaiting(tid))
134           { // We are not yet in the waiting list, append to the queue
135
WaitingListElement wle = new WaitingListElement(request, tid);
136             waitingList.addLast(wle);
137           }
138           return false;
139         }
140       }
141     }
142   }
143
144   /**
145    * Returns the transaction id of the lock owner. The return value is undefined
146    * if the lock is not owned (usually it is the last owner).
147    *
148    * @return int the transaction id.
149    */

150   public long getLocker()
151   {
152     return locker;
153   }
154
155   /**
156    * Returns <code>true</code> if the lock is owned by someone.
157    *
158    * @return <code>boolean</code> value
159    */

160   public boolean isLocked()
161   {
162     return isLocked;
163   }
164
165   /**
166    * Returns <code>true</code> if the given transaction id is contained in
167    * this lock waiting queue.
168    *
169    * @param transactionId a transaction id
170    * @return a <code>boolean</code> value
171    */

172   public synchronized boolean isWaiting(long transactionId)
173   {
174     for (Iterator JavaDoc iter = waitingList.iterator(); iter.hasNext();)
175     {
176       WaitingListElement e = (WaitingListElement) iter.next();
177       if (e.getTransactionId() == transactionId)
178         return true;
179     }
180     return false;
181   }
182
183   /**
184    * Releases the lock on this table or remove the transaction from the waiting
185    * list if it was not holding the lock.
186    *
187    * @param transactionId the transaction releasing the lock
188    * @return true if the transaction had the lock or was in the waiting list
189    * @see #acquire(AbstractRequest)
190    */

191   public synchronized boolean release(long transactionId)
192   {
193     if (!waitingList.isEmpty())
194     {
195       if (locker == transactionId)
196       { // We were holding the lock, give it to the first in the waiting list
197
locker = ((WaitingListElement) waitingList.removeFirst())
198             .getTransactionId();
199         return true;
200       }
201
202       // We were in the waiting list, remove ourselves from the list
203
for (Iterator JavaDoc iter = waitingList.iterator(); iter.hasNext();)
204       {
205         WaitingListElement e = (WaitingListElement) iter.next();
206         if (e.getTransactionId() == transactionId)
207         {
208           iter.remove();
209           return true;
210         }
211       }
212       return false;
213     }
214     else
215     {
216       if (locker == transactionId)
217       {
218         isLocked = false;
219         return true;
220       }
221       else
222         return false;
223     }
224   }
225
226   /**
227    * Returns the list of requests waiting for this lock.
228    *
229    * @return list of <code>WaitingListElement</code> type objects.
230    */

231   protected List JavaDoc getWaitingList()
232   {
233     return waitingList;
234   }
235
236   /**
237    * @see java.lang.Object#toString()
238    */

239   public String JavaDoc toString()
240   {
241     if (!isLocked)
242       return "Not Locked";
243     else
244       return "Locked by : " + locker + " - Waiting list : " + waitingList;
245   }
246 }
Popular Tags