001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Core License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: SharedLock.java,v 1.2 2002/06/08 00:49:38 mediumnet Exp $
008:
009: package org.ozoneDB.core;
010:
011: import java.io.*;
012: import org.ozoneDB.*;
013: import org.ozoneDB.DxLib.*;
014: import org.ozoneDB.util.*;
015:
016: /**
017: * This class implements a non-exclusive lock policy. Multiple transactions may
018: * hold this lock.
019: *
020: *
021: * @author <a href="http://www.softwarebuero.de/">SMB</a>
022: * @version $Revision: 1.2 $Date: 2002/06/08 00:49:38 $
023: */
024: public final class SharedLock extends AbstractLock {
025:
026: protected final static long serialVersionUID = 1;
027: protected final static byte subSerialVersionUID = 1;
028:
029: private int level = LEVEL_NONE;
030:
031: private transient int prevLevel = LEVEL_NONE;
032:
033: /**
034: * All transactions that hold this lock. Holds TransactionIDs.
035: */
036: public DxSet lockers;
037:
038: public SharedLock() {
039: reset();
040: }
041:
042: public synchronized void reset() {
043: level = prevLevel = LEVEL_NONE;
044: lockers = new DxHashSet(8);
045: }
046:
047: public int tryAcquire(Transaction ta, int newLevel) {
048: if (false && ta.env.logWriter.hasTarget(LogWriter.DEBUG3)) {
049: ta.env.logWriter.newEntry(this , "tryAcquire(): current:"
050: + level + " new:" + newLevel, LogWriter.DEBUG3);
051: }
052: synchronized (this ) {
053: int prevLevel = level(ta);
054: lockers.add(ta.taID());
055:
056: if (!lockers.contains(ta.taID())) {
057: throw new RuntimeException(
058: "tryAcquire(): unable to add ta to lockers.");
059: //ta.env.logWriter.newEntry (this, "tryAcquire(): unable to add ta to lockers.", LogWriter.WARN);
060: }
061: level = newLevel > level ? newLevel : level;
062: return prevLevel;
063: }
064: }
065:
066: public void release(Transaction ta) {
067: if (false && ta.env.logWriter.hasTarget(LogWriter.DEBUG3)) {
068: ta.env.logWriter.newEntry(this , "release()",
069: LogWriter.DEBUG3);
070: }
071: synchronized (this ) {
072: if (!lockers.remove(ta.taID)) {
073: throw new RuntimeException(
074: "release(): transaction does not hold the lock.");
075: }
076: if (lockers.isEmpty()) {
077: level = LEVEL_NONE;
078: }
079: if (false && ta.env.logWriter.hasTarget(LogWriter.DEBUG3)) {
080: ta.env.logWriter.newEntry(this , "release(): count="
081: + lockers.count() + ", level=" + level,
082: LogWriter.DEBUG3);
083: }
084: }
085: }
086:
087: public boolean isAcquiredBy(Transaction ta) {
088: return lockers != null ? lockers.contains(ta.taID()) : false;
089: }
090:
091: public DxCollection lockerIDs() {
092: return lockers != null ? lockers : new DxHashSet();
093: }
094:
095: public int level(Transaction ta) {
096: if (ta != null) {
097: return isAcquiredBy(ta) ? level : LEVEL_NONE;
098: } else {
099: return level;
100: }
101: }
102:
103: public int previousLevel() {
104: return prevLevel;
105: }
106:
107: public boolean areMultipleLockersHoldingLocks() {
108: return lockers.count() >= 2;
109: }
110:
111: public boolean hasChanged() {
112: return level > prevLevel;
113: }
114:
115: public String toString() {
116: return "SharedLock[lockers=" + lockers + "]";
117: }
118: }
|