KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > LockingQueue


1 /**
2  * com.mckoi.database.LockingQueue 11 May 1998
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import com.mckoi.debug.*;
28 import java.util.ArrayList JavaDoc;
29
30 /**
31  * This class is used in the 'LockingMechanism' class. It maintains a queue
32  * of threads that have locked the table this queue refers to. A lock means
33  * the table is either pending to be accessed, or the data in the table is
34  * being used.
35  * <p>
36  * A write lock in the queue stops any concurrently running threads from
37  * accessing the tables. A read lock can go ahead only if there is no write
38  * lock in the queue below it.
39  * <p>
40  * The rules are simple, and allow for reading of tables to happen concurrently
41  * and writing to happen sequentually. Once a table is pending being written
42  * to, it must be guarenteed that no thread can read the table while the write
43  * is happening.
44  * <p>
45  * @author Tobias Downer
46  */

47
48 final class LockingQueue {
49
50   /**
51    * The DataTable this queue is 'protecting'
52    */

53   private DataTable parent_table;
54
55   /**
56    * This is the queue that stores the table locks.
57    */

58   private ArrayList JavaDoc queue;
59
60   /**
61    * The Constructor.
62    */

63   LockingQueue(DataTable table) {
64     parent_table = table;
65     queue = new ArrayList JavaDoc();
66   }
67
68   /**
69    * Returns the DataTable object the queue is 'attached' to.
70    */

71   DataTable getTable() {
72     return parent_table;
73   }
74
75   /**
76    * Adds a lock to the queue.
77    * NOTE: This method is thread safe since it is only called from the
78    * LockingMechanism synchronized methods.
79    * SYNCHRONIZED: This has to be synchronized because we don't want new locks
80    * being added while a 'checkAccess' is happening.
81    */

82   synchronized void addLock(Lock lock) {
83     queue.add(lock);
84   }
85
86   /**
87    * Removes a lock from the queue. This also does a 'notifyAll()' to kick any
88    * threads that might be blocking in the 'checkAccess' method.
89    * SYNCHRONIZED: This has to be synchronized because we don't want locks to
90    * be removed while a 'checkAccess' is happening.
91    */

92   synchronized void removeLock(Lock lock) {
93     queue.remove(lock);
94     // Notify the table that we have released a lock from it.
95
lock.getTable().notifyReleaseRWLock(lock.getType());
96 // System.out.println("Removing lock: " + lock);
97
notifyAll();
98   }
99
100   /**
101    * Looks at the queue and _blocks_ if the access to the table by the means
102    * specified in the lock is allowed or not.
103    * The rules for determining this are as follows:
104    * <p>
105    * 1) If the lock is a READ lock and there is a WRITE lock 'infront' of
106    * this lock on the queue then block.
107    * 2) If the lock is a WRITE lock and the lock isn't at the front of the
108    * queue then block.
109    * 3) Retry when a lock is released from the queue.
110    */

111   void checkAccess(Lock lock) {
112     boolean blocked;
113     int index, i;
114     Lock test_lock;
115
116     synchronized (this) {
117
118       // Error checking. The queue must contain the lock.
119
if (!queue.contains(lock)) {
120         throw new Error JavaDoc("Queue does not contain the given lock");
121       }
122
123       // If 'READ'
124
if (lock.getType() == Lock.READ) {
125
126         do {
127           blocked = false;
128
129           index = queue.indexOf(lock);
130           for (i = index - 1; i >= 0 && blocked == false; --i) {
131             test_lock = (Lock) queue.get(i);
132             if (test_lock.getType() == Lock.WRITE) {
133               blocked = true;
134             }
135           }
136
137           if (blocked == true) {
138             getTable().Debug().write(Lvl.INFORMATION, this,
139                                      "Blocking on read.");
140 // System.out.println("READ BLOCK: " + queue);
141
try {
142               wait();
143             } catch (InterruptedException JavaDoc ignore) {}
144           }
145
146         } while (blocked == true);
147
148       }
149
150       // Else must be 'WRITE'
151
else {
152
153         do {
154           blocked = false;
155
156           index = queue.indexOf(lock);
157           if (index != 0) {
158             blocked = true;
159             getTable().Debug().write(Lvl.INFORMATION, this,
160                                      "Blocking on write.");
161 // System.out.println("WRITE BLOCK: " + queue);
162
try {
163               wait();
164             } catch (InterruptedException JavaDoc ignore) {}
165           }
166
167         } while (blocked == true);
168
169       }
170
171       // Notify the Lock table that we've got a lock on it.
172
lock.getTable().notifyAddRWLock(lock.getType());
173
174     } /* synchronized (this) */
175
176   }
177
178   public synchronized String JavaDoc toString() {
179     StringBuffer JavaDoc str = new StringBuffer JavaDoc("[LockingQueue]: (");
180     for (int i = 0; i < queue.size(); ++i) {
181       str.append(queue.get(i));
182       str.append(", ");
183     }
184     str.append(")");
185     return new String JavaDoc(str);
186   }
187
188 }
189
Popular Tags