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    
019    import org.apache.ojb.odmg.TransactionImpl;
020    
021    import java.util.Collection;
022    
023    /**
024     * The implementation of the Serializable Locking strategy.
025     *
026     * @author Thomas Mahler & David Dixon-Peugh
027     */
028    public class SerializableStrategy extends AbstractLockStrategy
029    {
030        /**
031         * acquire a read lock on Object obj for Transaction tx.
032         * @param tx the transaction requesting the lock
033         * @param obj the Object to be locked
034         * @return true if successful, else false
035         *
036         */
037        public boolean readLock(TransactionImpl tx, Object obj)
038        {
039            LockEntry writer = getWriter(obj);
040            Collection readers = getReaders(obj);
041            if (writer == null)
042            {
043                // only one reader at a time
044                if (readers.size() == 0)
045                {
046                    if (addReader(tx, obj))
047                    {
048                        readers = getReaders(obj);
049                        if (readers.size() == 1)
050                        {
051                            return true;
052                        }
053                        else
054                        {
055                            removeReader(tx, obj);
056                            return readLock(tx, obj);
057                        }
058                    }
059                    else
060                        return readLock(tx, obj);
061                }
062                else if ((readers.size() == 1) && (((LockEntry) readers.iterator().next()).isOwnedBy(tx)))
063                {
064                    // I'm the reader, thus I am allowed to read even more !
065                    return true;
066                }
067            }
068            else if (writer.isOwnedBy(tx))
069            {
070                return true;    // If I'm the writer, I can read.
071            }
072    
073            return false;
074        }
075    
076        /**
077         * acquire a write lock on Object obj for Transaction tx.
078         * @param tx the transaction requesting the lock
079         * @param obj the Object to be locked
080         * @return true if successful, else false
081         *
082         */
083        public boolean writeLock(TransactionImpl tx, Object obj)
084        {
085            LockEntry writer = getWriter(obj);
086            Collection readers = getReaders(obj);
087            if (writer == null)
088            {
089                if (readers.size() == 0)
090                {
091                    if (setWriter(tx, obj))
092                        return true;
093                    else
094                        return writeLock(tx, obj);
095                }
096    
097                else if (readers.size() == 1)
098                {
099                    if (((LockEntry) readers.iterator().next()).isOwnedBy(tx))
100                        return upgradeLock(tx, obj);
101                }
102            }
103            else if (writer.isOwnedBy(tx))
104            {
105                return true;    // If I'm the writer, then I can write.
106            }
107            return false;
108        }
109    
110        /**
111         * acquire a lock upgrade (from read to write) lock on Object obj for Transaction tx.
112         * @param tx the transaction requesting the lock
113         * @param obj the Object to be locked
114         * @return true if successful, else false
115         *
116         */
117        public boolean upgradeLock(TransactionImpl tx, Object obj)
118        {
119            LockEntry writer = getWriter(obj);
120            if (writer == null)
121            {
122                Collection readers = getReaders(obj);
123                if (readers.size() == 1)
124                {
125                    LockEntry reader = (LockEntry) readers.iterator().next();
126                    if (reader.isOwnedBy(tx))
127                    {
128                        if (upgradeLock(reader))
129                            return true;
130                        else
131                            return upgradeLock(tx, obj);
132                    }
133                }
134                else
135                {
136                    if (readers.size() == 0)
137                    {
138                        if (setWriter(tx, obj))
139                            return true;
140                        else
141                            return upgradeLock(tx, obj);
142                    }
143                }
144            }
145            else if (writer.isOwnedBy(tx))
146            {
147                return true;    // If I already have Write, then I've upgraded.
148            }
149    
150            return false;
151        }
152    
153        /**
154         * release a lock on Object obj for Transaction tx.
155         * @param tx the transaction releasing the lock
156         * @param obj the Object to be unlocked
157         * @return true if successful, else false
158         *
159         */
160        public boolean releaseLock(TransactionImpl tx, Object obj)
161        {
162            LockEntry writer = getWriter(obj);
163            if (writer != null && writer.isOwnedBy(tx))
164            {
165                removeWriter(writer);
166                return true;
167            }
168    
169            if (hasReadLock(tx, obj))
170            {
171                removeReader(tx, obj);
172                return true;
173            }
174            else
175                return false;
176    
177        }
178    
179        /**
180         * checks whether the specified Object obj is read-locked by Transaction tx.
181         * @param tx the transaction
182         * @param obj the Object to be checked
183         * @return true if lock exists, else false
184         */
185        public boolean checkRead(TransactionImpl tx, Object obj)
186        {
187            if (hasReadLock(tx, obj))
188            {
189                return true;
190            }
191            LockEntry writer = getWriter(obj);
192            if (writer != null && writer.isOwnedBy(tx))
193            {
194                return true;
195            }
196            else
197                return false;
198        }
199    
200        /**
201         * checks whether the specified Object obj is write-locked by Transaction tx.
202         * @param tx the transaction
203         * @param obj the Object to be checked
204         * @return true if lock exists, else false
205         */
206        public boolean checkWrite(TransactionImpl tx, Object obj)
207        {
208            LockEntry writer = getWriter(obj);
209            return (writer != null && writer.isOwnedBy(tx));
210        }
211    }