⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mrowlock.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
字号:
// You can redistribute this software and/or modify it under the terms of
// the Ozone Core License version 1 published by ozone-db.org.
//
// The original code and portions created by SMB are
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
//
// $Id: MROWLock.java,v 1.4.2.4 2004/01/15 22:02:38 per_nyfelt Exp $

package org.ozoneDB.core;

import java.io.*;
import org.ozoneDB.*;
import org.ozoneDB.DxLib.*;
import org.ozoneDB.util.*;


/**
 * This class implements a Multiple Reader One Writer lock policy.
 *
 *
 * @author <a href="http://www.softwarebuero.de/">SMB</a>
 * @author <a href="http://www.medium.net/">Medium.net</a>
 * @version $Revision: 1.4.2.4 $Date: 2004/01/15 22:02:38 $
 */
public final class MROWLock extends AbstractLock {

    protected final static long serialVersionUID = 1;
    protected final static byte subSerialVersionUID = 1;

    protected final static boolean  enableReleaseOfReadlockOnFailedWritelock = false;

    private int level = LEVEL_NONE;

    private SharedLock readLock;

    private ExclusiveLock writeLock;

    protected transient String debugInfo;


    public MROWLock() {
        reset();
    }


    public synchronized void reset() {
        level = LEVEL_NONE;
        readLock = new SharedLock();
        writeLock = new ExclusiveLock();
    }


    public void setDebugInfo(String debugInfo) {
        this.debugInfo = debugInfo;
    }

    public int tryAcquire( Transaction ta, int newLevel ) {
        if (false&&ta.env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
            ta.env.logWriter.newEntry( this, "tryAcquire(): ta.getID()="+ta.taID()+", current:" + level + " new:" + newLevel+", writeLock.getLocker()="+writeLock.getLocker()+".", LogWriter.DEBUG3 );
        }

        if (readLock.isAcquiredBy( ta ) && level == newLevel) {
            return level;
        }

        if (ta.env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
            if (false&&(newLevel>level||(!ta.taID().equals(writeLock.getLocker())))) {
                ta.env.logWriter.newEntry( this, this+".tryAcquire(): ta.getID()="+ta.taID()+", current:" + level + " new:" + newLevel+", writeLock.getLocker()="+writeLock.getLocker()+".", LogWriter.DEBUG2 );
            }
        }

        synchronized (this) {
            int prevLevel = NOT_ACQUIRED;

            if (newLevel <= LEVEL_NONE || newLevel >= LEVEL_MAX) {
                ta.env.logWriter.newEntry( this, "tryAcquire(): newLevel == " + newLevel, LogWriter.WARN );
            }

            boolean result = false;

            // no transaction holds this lock
            if (level == LEVEL_NONE) {
                prevLevel = LEVEL_NONE;

                int readLockPrevLevel;

                if ((readLockPrevLevel = readLock.tryAcquire(ta,LEVEL_READ)) != NOT_ACQUIRED) {
                    result = true;
                    if (newLevel > LEVEL_READ) {
                        if (writeLock.tryAcquire( ta, LEVEL_WRITE ) == NOT_ACQUIRED) {
                            result = false;
                            if (enableReleaseOfReadlockOnFailedWritelock) {
                                readLock.release( ta );
                            } else {
                                if (readLockPrevLevel<LEVEL_READ) { // If we had acquired the read lock only now.
                                    readLock.release(ta);
                                }
                            }
                        }
                    }
                }
            } else if (readLock.isAcquiredBy( ta )) {
                // the given ta itself holds the lock
                prevLevel = level;
                result = true;
                if (newLevel > LEVEL_READ) {
                    /*
                        The given transaction itself holds the lock, fine. But what if other transactions hold the readl lock, too?
                        I think that we cannot give the requesting transaction the write lock if other transactions are still
                        holding the read lock. In this case the requesting transaction may overwrite (and touch) data which the other
                        transactions may access.
                    */
                    if (!readLock.areMultipleLockersHoldingLocks()) {
                        if (writeLock.tryAcquire( ta, LEVEL_WRITE ) == NOT_ACQUIRED) {
                            result = false;
                            readLock.release( ta );
                        }
                    } else {
                        result = false;

                        if (enableReleaseOfReadlockOnFailedWritelock) {
                            // FIXME: I'm really unsure why I should release a read lock if just the write lock obtaining failed.
                            readLock.release(ta);
                        }
                    }
                }
            } else {
                // another ta holds a READ lock and we want READ lock too
                if (newLevel == LEVEL_READ && level == LEVEL_READ) {
                    prevLevel = LEVEL_NONE;
                    if (readLock.tryAcquire( ta, LEVEL_READ ) != NOT_ACQUIRED) {
                        result = true;
                    }
                }
            }

            if (result) {
                level = newLevel > level ? newLevel : level;
                return prevLevel;
            } else {
                return NOT_ACQUIRED;
            }
        }
    }


    protected synchronized boolean acquire( Transaction ta, int newLevel ) {
        int prevLevel = readLock.tryAcquire( ta, LEVEL_READ );
        if (newLevel > LEVEL_READ && prevLevel > NOT_ACQUIRED) {
            prevLevel = writeLock.tryAcquire( ta, LEVEL_WRITE );
            if (prevLevel == NOT_ACQUIRED) {
                readLock.release( ta );
            }
        }
        return prevLevel != NOT_ACQUIRED;
    }


    public void release( Transaction ta ) {
        if (false&&ta.env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
            ta.env.logWriter.newEntry( this, this+".release(): ta.getID()="+ta.taID()+".", LogWriter.DEBUG2 );
        }

        if (level == LEVEL_NONE) {
            ta.env.logWriter.newEntry( this, this+".release(): current level is LEVEL_NONE.", new Exception(),LogWriter.WARN );
        }

        synchronized (this) {
            if (writeLock.isAcquiredBy( ta )) {
                writeLock.release( ta );
                level = LEVEL_READ;
            }
            if (readLock.isAcquiredBy( ta )) {
                readLock.release( ta );
                if (readLock.level( null ) == LEVEL_NONE) {
                    level = LEVEL_NONE;
                }
            }
        }

    /*
        DxIterator it = lockers.iterator();
        while (it.next() != null) {
            TransactionID taID = (TransactionID)it.object();
            if (ta.env.transactionManager.taForID (taID) == null) {
                System.out.println ("*********** INPROPER LOCK ********");
                it.removeObject();
                }
            }
     */
    }


    public boolean isAcquiredBy( Transaction ta ) {
        switch (level) {
        case LEVEL_NONE: {
            return false;
            }
        case LEVEL_READ: {
            return readLock.isAcquiredBy( ta );
            }
        default: {
            return writeLock.isAcquiredBy( ta );
            }
        }
    }

    public TransactionID getWriteLockingTransactionID() {
        return level < LEVEL_WRITE ? null : writeLock.getLocker();
    }

    public DxCollection lockerIDs() {
        switch (level) {
        case LEVEL_NONE: {
            return new DxArrayBag();
            }
        default: {
            // since all write lockers are read lockers too, we can
            // return readlocker no metter what the lock level is
            return readLock.lockerIDs();
            }
        }
    }


    public int level( Transaction ta ) {
        if (ta == null) {
            return level;
        } else {
            switch (level) {
            case LEVEL_NONE: {
                return LEVEL_NONE;
                }
            case LEVEL_READ: {
                return readLock.isAcquiredBy( ta ) ? level : LEVEL_NONE;
                }
            default: {
                return writeLock.isAcquiredBy( ta ) ? level : LEVEL_NONE;
                }
            }
        }
    }

    public String toString() {
        return "MROWLock[" + debugInfo + ",writeLock.getLocker()="
                + writeLock.getLocker() + ",readLock=" + readLock + ",level=" + level + "]";
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -