KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > MROWLock


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id: MROWLock.java,v 1.4.2.4 2004/01/15 22:02:38 per_nyfelt Exp $
8

9 package org.ozoneDB.core;
10
11 import java.io.*;
12 import org.ozoneDB.*;
13 import org.ozoneDB.DxLib.*;
14 import org.ozoneDB.util.*;
15
16
17 /**
18  * This class implements a Multiple Reader One Writer lock policy.
19  *
20  *
21  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
22  * @author <a HREF="http://www.medium.net/">Medium.net</a>
23  * @version $Revision: 1.4.2.4 $Date: 2004/01/15 22:02:38 $
24  */

25 public final class MROWLock extends AbstractLock {
26
27     protected final static long serialVersionUID = 1;
28     protected final static byte subSerialVersionUID = 1;
29
30     protected final static boolean enableReleaseOfReadlockOnFailedWritelock = false;
31
32     private int level = LEVEL_NONE;
33
34     private SharedLock readLock;
35
36     private ExclusiveLock writeLock;
37
38     protected transient String JavaDoc debugInfo;
39
40
41     public MROWLock() {
42         reset();
43     }
44
45
46     public synchronized void reset() {
47         level = LEVEL_NONE;
48         readLock = new SharedLock();
49         writeLock = new ExclusiveLock();
50     }
51
52
53     public void setDebugInfo(String JavaDoc debugInfo) {
54         this.debugInfo = debugInfo;
55     }
56
57     public int tryAcquire( Transaction ta, int newLevel ) {
58         if (false&&ta.env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
59             ta.env.logWriter.newEntry( this, "tryAcquire(): ta.getID()="+ta.taID()+", current:" + level + " new:" + newLevel+", writeLock.getLocker()="+writeLock.getLocker()+".", LogWriter.DEBUG3 );
60         }
61
62         if (readLock.isAcquiredBy( ta ) && level == newLevel) {
63             return level;
64         }
65
66         if (ta.env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
67             if (false&&(newLevel>level||(!ta.taID().equals(writeLock.getLocker())))) {
68                 ta.env.logWriter.newEntry( this, this+".tryAcquire(): ta.getID()="+ta.taID()+", current:" + level + " new:" + newLevel+", writeLock.getLocker()="+writeLock.getLocker()+".", LogWriter.DEBUG2 );
69             }
70         }
71
72         synchronized (this) {
73             int prevLevel = NOT_ACQUIRED;
74
75             if (newLevel <= LEVEL_NONE || newLevel >= LEVEL_MAX) {
76                 ta.env.logWriter.newEntry( this, "tryAcquire(): newLevel == " + newLevel, LogWriter.WARN );
77             }
78
79             boolean result = false;
80
81             // no transaction holds this lock
82
if (level == LEVEL_NONE) {
83                 prevLevel = LEVEL_NONE;
84
85                 int readLockPrevLevel;
86
87                 if ((readLockPrevLevel = readLock.tryAcquire(ta,LEVEL_READ)) != NOT_ACQUIRED) {
88                     result = true;
89                     if (newLevel > LEVEL_READ) {
90                         if (writeLock.tryAcquire( ta, LEVEL_WRITE ) == NOT_ACQUIRED) {
91                             result = false;
92                             if (enableReleaseOfReadlockOnFailedWritelock) {
93                                 readLock.release( ta );
94                             } else {
95                                 if (readLockPrevLevel<LEVEL_READ) { // If we had acquired the read lock only now.
96
readLock.release(ta);
97                                 }
98                             }
99                         }
100                     }
101                 }
102             } else if (readLock.isAcquiredBy( ta )) {
103                 // the given ta itself holds the lock
104
prevLevel = level;
105                 result = true;
106                 if (newLevel > LEVEL_READ) {
107                     /*
108                         The given transaction itself holds the lock, fine. But what if other transactions hold the readl lock, too?
109                         I think that we cannot give the requesting transaction the write lock if other transactions are still
110                         holding the read lock. In this case the requesting transaction may overwrite (and touch) data which the other
111                         transactions may access.
112                     */

113                     if (!readLock.areMultipleLockersHoldingLocks()) {
114                         if (writeLock.tryAcquire( ta, LEVEL_WRITE ) == NOT_ACQUIRED) {
115                             result = false;
116                             readLock.release( ta );
117                         }
118                     } else {
119                         result = false;
120
121                         if (enableReleaseOfReadlockOnFailedWritelock) {
122                             // FIXME: I'm really unsure why I should release a read lock if just the write lock obtaining failed.
123
readLock.release(ta);
124                         }
125                     }
126                 }
127             } else {
128                 // another ta holds a READ lock and we want READ lock too
129
if (newLevel == LEVEL_READ && level == LEVEL_READ) {
130                     prevLevel = LEVEL_NONE;
131                     if (readLock.tryAcquire( ta, LEVEL_READ ) != NOT_ACQUIRED) {
132                         result = true;
133                     }
134                 }
135             }
136
137             if (result) {
138                 level = newLevel > level ? newLevel : level;
139                 return prevLevel;
140             } else {
141                 return NOT_ACQUIRED;
142             }
143         }
144     }
145
146
147     protected synchronized boolean acquire( Transaction ta, int newLevel ) {
148         int prevLevel = readLock.tryAcquire( ta, LEVEL_READ );
149         if (newLevel > LEVEL_READ && prevLevel > NOT_ACQUIRED) {
150             prevLevel = writeLock.tryAcquire( ta, LEVEL_WRITE );
151             if (prevLevel == NOT_ACQUIRED) {
152                 readLock.release( ta );
153             }
154         }
155         return prevLevel != NOT_ACQUIRED;
156     }
157
158
159     public void release( Transaction ta ) {
160         if (false&&ta.env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
161             ta.env.logWriter.newEntry( this, this+".release(): ta.getID()="+ta.taID()+".", LogWriter.DEBUG2 );
162         }
163
164         if (level == LEVEL_NONE) {
165             ta.env.logWriter.newEntry( this, this+".release(): current level is LEVEL_NONE.", new Exception JavaDoc(),LogWriter.WARN );
166         }
167
168         synchronized (this) {
169             if (writeLock.isAcquiredBy( ta )) {
170                 writeLock.release( ta );
171                 level = LEVEL_READ;
172             }
173             if (readLock.isAcquiredBy( ta )) {
174                 readLock.release( ta );
175                 if (readLock.level( null ) == LEVEL_NONE) {
176                     level = LEVEL_NONE;
177                 }
178             }
179         }
180
181     /*
182         DxIterator it = lockers.iterator();
183         while (it.next() != null) {
184             TransactionID taID = (TransactionID)it.object();
185             if (ta.env.transactionManager.taForID (taID) == null) {
186                 System.out.println ("*********** INPROPER LOCK ********");
187                 it.removeObject();
188                 }
189             }
190      */

191     }
192
193
194     public boolean isAcquiredBy( Transaction ta ) {
195         switch (level) {
196         case LEVEL_NONE: {
197             return false;
198             }
199         case LEVEL_READ: {
200             return readLock.isAcquiredBy( ta );
201             }
202         default: {
203             return writeLock.isAcquiredBy( ta );
204             }
205         }
206     }
207
208     public TransactionID getWriteLockingTransactionID() {
209         return level < LEVEL_WRITE ? null : writeLock.getLocker();
210     }
211
212     public DxCollection lockerIDs() {
213         switch (level) {
214         case LEVEL_NONE: {
215             return new DxArrayBag();
216             }
217         default: {
218             // since all write lockers are read lockers too, we can
219
// return readlocker no metter what the lock level is
220
return readLock.lockerIDs();
221             }
222         }
223     }
224
225
226     public int level( Transaction ta ) {
227         if (ta == null) {
228             return level;
229         } else {
230             switch (level) {
231             case LEVEL_NONE: {
232                 return LEVEL_NONE;
233                 }
234             case LEVEL_READ: {
235                 return readLock.isAcquiredBy( ta ) ? level : LEVEL_NONE;
236                 }
237             default: {
238                 return writeLock.isAcquiredBy( ta ) ? level : LEVEL_NONE;
239                 }
240             }
241         }
242     }
243
244     public String JavaDoc toString() {
245         return "MROWLock[" + debugInfo + ",writeLock.getLocker()="
246                 + writeLock.getLocker() + ",readLock=" + readLock + ",level=" + level + "]";
247     }
248 }
249
Popular Tags