001 package org.apache.ojb.odmg.locking;
002
003 /* Copyright 2002-2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 import org.apache.ojb.odmg.TransactionImpl;
019
020 import java.util.Collection;
021
022 /**
023 * The implementation of the Repeatable Reads Locking strategy.
024 * Locks are obtained for reading and modifying the database.
025 * Locks on all modified objects are held until EOT.
026 * Locks obtained for reading data are held until EOT.
027 * Allows:
028 * Phantom Reads
029 *
030 * @author Thomas Mahler & David Dixon-Peugh
031 */
032 public class RepeatableReadStrategy extends AbstractLockStrategy
033 {
034 /**
035 * acquire a read lock on Object obj for Transaction tx.
036 * @param tx the transaction requesting the lock
037 * @param obj the Object to be locked
038 * @return true if successful, else false
039 *
040 */
041 public boolean readLock(TransactionImpl tx, Object obj)
042 {
043 LockEntry writer = getWriter(obj);
044 if (writer == null)
045 {
046 if (addReader(tx, obj))
047 return true;
048 else
049 return readLock(tx, obj);
050 }
051 if (writer.isOwnedBy(tx))
052 {
053 return true; // If I'm the writer, I can read.
054 }
055 else
056 return false;
057
058 }
059
060 /**
061 * acquire a write lock on Object obj for Transaction tx.
062 * @param tx the transaction requesting the lock
063 * @param obj the Object to be locked
064 * @return true if successful, else false
065 *
066 */
067 public boolean writeLock(TransactionImpl tx, Object obj)
068 {
069 LockEntry writer = getWriter(obj);
070 Collection readers = getReaders(obj);
071 if (writer == null)
072 {
073 if (readers.size() == 0)
074 {
075 if (setWriter(tx, obj))
076 return true;
077 else
078 return writeLock(tx, obj);
079 }
080
081 else if (readers.size() == 1)
082 {
083 if (((LockEntry) readers.iterator().next()).isOwnedBy(tx))
084 return upgradeLock(tx, obj);
085 }
086 }
087 else if (writer.isOwnedBy(tx))
088 {
089 return true; // If I'm the writer, then I can write.
090 }
091 return false;
092 }
093
094
095 /**
096 * acquire a lock upgrade (from read to write) lock on Object obj for Transaction tx.
097 * @param tx the transaction requesting the lock
098 * @param obj the Object to be locked
099 * @return true if successful, else false
100 *
101 */
102 public boolean upgradeLock(TransactionImpl tx, Object obj)
103 {
104 LockEntry writer = getWriter(obj);
105 if (writer == null)
106 {
107 Collection readers = this.getReaders(obj);
108 if (readers.size() == 1)
109 {
110 LockEntry reader = (LockEntry) readers.iterator().next();
111 if (reader.isOwnedBy(tx))
112 {
113 if (upgradeLock(reader))
114 return true;
115 else
116 return upgradeLock(tx, obj);
117 }
118 }
119 else if (readers.size() == 0)
120 {
121 if (setWriter(tx, obj))
122 return true;
123 else
124 return upgradeLock(tx, obj);
125 }
126
127
128 }
129 else if (writer.isOwnedBy(tx))
130 {
131 return true; // If I already have Write, then I've upgraded.
132 }
133
134 return false;
135 }
136
137 /**
138 * release a lock on Object obj for Transaction tx.
139 * @param tx the transaction releasing the lock
140 * @param obj the Object to be unlocked
141 * @return true if successful, else false
142 *
143 */
144 public boolean releaseLock(TransactionImpl tx, Object obj)
145 {
146 LockEntry writer = getWriter(obj);
147 if (writer != null && writer.isOwnedBy(tx))
148 {
149 removeWriter(writer);
150 return true;
151 }
152 if (hasReadLock(tx, obj))
153 {
154 removeReader(tx, obj);
155 return true;
156 }
157 return false;
158 }
159
160 /**
161 * checks whether the specified Object obj is read-locked by Transaction tx.
162 * @param tx the transaction
163 * @param obj the Object to be checked
164 * @return true if lock exists, else false
165 */
166 public boolean checkRead(TransactionImpl tx, Object obj)
167 {
168 if (hasReadLock(tx, obj))
169 {
170 return true;
171 }
172 LockEntry writer = getWriter(obj);
173 if (writer != null && writer.isOwnedBy(tx))
174 {
175 return true;
176 }
177 else
178 return false;
179 }
180
181 /**
182 * checks whether the specified Object obj is write-locked by Transaction tx.
183 * @param tx the transaction
184 * @param obj the Object to be checked
185 * @return true if lock exists, else false
186 */
187 public boolean checkWrite(TransactionImpl tx, Object obj)
188 {
189 LockEntry writer = getWriter(obj);
190 return (writer != null && writer.isOwnedBy(tx));
191 }
192 }