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 }