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: * acquire a read lock on Object obj for Transaction tx.
035: * @param tx the transaction requesting the lock
036: * @param obj the Object to be locked
037: * @return true if successful, else false
038: *
039: */
040: public boolean readLock(TransactionImpl tx, Object obj) {
041: LockEntry writer = getWriter(obj);
042: if (writer == null) {
043: if (addReader(tx, obj))
044: return true;
045: else
046: return readLock(tx, obj);
047: }
048: if (writer.isOwnedBy(tx)) {
049: return true; // If I'm the writer, I can read.
050: } else
051: return false;
052:
053: }
054:
055: /**
056: * acquire a write lock on Object obj for Transaction tx.
057: * @param tx the transaction requesting the lock
058: * @param obj the Object to be locked
059: * @return true if successful, else false
060: *
061: */
062: public boolean writeLock(TransactionImpl tx, Object obj) {
063: LockEntry writer = getWriter(obj);
064: Collection readers = getReaders(obj);
065: if (writer == null) {
066: if (readers.size() == 0) {
067: if (setWriter(tx, obj))
068: return true;
069: else
070: return writeLock(tx, obj);
071: }
072:
073: else if (readers.size() == 1) {
074: if (((LockEntry) readers.iterator().next())
075: .isOwnedBy(tx))
076: return upgradeLock(tx, obj);
077: }
078: } else if (writer.isOwnedBy(tx)) {
079: return true; // If I'm the writer, then I can write.
080: }
081: return false;
082: }
083:
084: /**
085: * acquire a lock upgrade (from read to write) lock on Object obj for Transaction tx.
086: * @param tx the transaction requesting the lock
087: * @param obj the Object to be locked
088: * @return true if successful, else false
089: *
090: */
091: public boolean upgradeLock(TransactionImpl tx, Object obj) {
092: LockEntry writer = getWriter(obj);
093: if (writer == null) {
094: Collection readers = this .getReaders(obj);
095: if (readers.size() == 1) {
096: LockEntry reader = (LockEntry) readers.iterator()
097: .next();
098: if (reader.isOwnedBy(tx)) {
099: if (upgradeLock(reader))
100: return true;
101: else
102: return upgradeLock(tx, obj);
103: }
104: } else if (readers.size() == 0) {
105: if (setWriter(tx, obj))
106: return true;
107: else
108: return upgradeLock(tx, obj);
109: }
110:
111: } else if (writer.isOwnedBy(tx)) {
112: return true; // If I already have Write, then I've upgraded.
113: }
114:
115: return false;
116: }
117:
118: /**
119: * release a lock on Object obj for Transaction tx.
120: * @param tx the transaction releasing the lock
121: * @param obj the Object to be unlocked
122: * @return true if successful, else false
123: *
124: */
125: public boolean releaseLock(TransactionImpl tx, Object obj) {
126: LockEntry writer = getWriter(obj);
127: if (writer != null && writer.isOwnedBy(tx)) {
128: removeWriter(writer);
129: return true;
130: }
131: if (hasReadLock(tx, obj)) {
132: removeReader(tx, obj);
133: return true;
134: }
135: return false;
136: }
137:
138: /**
139: * checks whether the specified Object obj is read-locked by Transaction tx.
140: * @param tx the transaction
141: * @param obj the Object to be checked
142: * @return true if lock exists, else false
143: */
144: public boolean checkRead(TransactionImpl tx, Object obj) {
145: if (hasReadLock(tx, obj)) {
146: return true;
147: }
148: LockEntry writer = getWriter(obj);
149: if (writer != null && writer.isOwnedBy(tx)) {
150: return true;
151: } else
152: return false;
153: }
154:
155: /**
156: * checks whether the specified Object obj is write-locked by Transaction tx.
157: * @param tx the transaction
158: * @param obj the Object to be checked
159: * @return true if lock exists, else false
160: */
161: public boolean checkWrite(TransactionImpl tx, Object obj) {
162: LockEntry writer = getWriter(obj);
163: return (writer != null && writer.isOwnedBy(tx));
164: }
165: }
|