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

📄 transaction.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
// 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: Transaction.java,v 1.30 2004/03/08 19:20:17 wieslawf Exp $
package org.ozoneDB.core;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.ozoneDB.*;
import org.ozoneDB.DxLib.DxIterator;
import org.ozoneDB.DxLib.DxSet;
import org.ozoneDB.core.DbRemote.DbCommand;
import org.ozoneDB.core.dr.Lockable;
import org.ozoneDB.core.dr.Locker;
import org.ozoneDB.data.SimpleArrayList;
import org.ozoneDB.util.LogWriter;

/**
 * This class represents an internal transaction.<p>
 *
 * Most methods of this class are synchronized. In fact, this is not strictly
 * needed because a transaction is invoked by one thread (associated with this
 * transaction) only.<p>
 *
 * All public methods are wrapped into try/catch statements to convert thrown
 * exception into OzoneInternalException. So the client gets OzoneRemoteException, if an
 * object could not be found or something; OzoneInternalException, if there was a
 * critical internal error; any other exceptions were thrown by the user code.
 *
 *
 * @author <a href="http://www.softwarebuero.de/">SMB</a>
 * @author <A HREF="http://www.medium.net/">Medium.net</A>
 * @version $Revision: 1.30 $Date: 2004/03/08 19:20:17 $
 */
public abstract class Transaction implements Locker {

    /** Status of a transaction: transaction is not active. */
    public final static int STATUS_NONE = 1;

    /** Status of a transaction: transaction has been started. */
    public final static int STATUS_STARTED = 2;

    /** Status of a transaction: transaction is about to prepare. */
    public final static int STATUS_PREPARING = 3;

    /** Status of a transaction: transaction has been successfully prepared. */
    public final static int STATUS_PREPARED = 4;

    /** Status of a transaction: transaction is about to commit.*/
    public final static int STATUS_COMMITING = 5;

    /** Status of a transaction: transaction has been successfully committed. */
    public final static int STATUS_COMMITED = 6;

    /** Status of a transaction: transaction is about to abort. */
    public final static int STATUS_ABORTING = 7;

    /** Status of a transaction: transaction has been aborted. */
    public final static int STATUS_ABORTED = 8;

    public final static int HASHTABLE_INIT_SIZE = 100;

    /**
     * The environment of this object.
     */
    protected transient Env env;

    protected TransactionID taID;

    protected String ownerName;

    protected User owner;

    protected int status;

    protected boolean rollbackOnly;

    protected int maxLockLevel;

    protected int commandCount;

    /**
     * The ID of the object (container) that blocks this transaction.
     */
    protected ObjectID blocker;
    
    protected long blockTimeout;

    protected long startTime;

    protected int acquireCount;

    protected boolean stopped;

    /**
     Are we deadlocked?
     */
    protected boolean deadlocked;

    /**
     The minimum deadlockWaitTimeMaximum can have. (default: 1 second)
     */
    protected final static long deadlockWaitTimeMaximumMinimum = 1 * 1000;

    /**
     The maximum deadlockWaitTimeMaximum can have. (default: 30 minutes)
     */
    protected final static long deadlockWaitTimeMaximumMaximum = 30 * 60 * 1000;

    /**
     The maximum time (in milliseconds) to wait after a deadlock.
     */
    protected long deadlockWaitTimeMaximum;

    /**
     Is this thread sleeping?
     */
    protected boolean sleeping;

    /**
     The list of {@link ObjectContainer}s which are called by this transactions but where the call
     is not completed. The last object called is represented by the {@link ObjectContainer} with
     the greatest index in the list.
     */
    protected SimpleArrayList callStack;


    /**
     * Construct a new transaction.
     *
     *
     * @param env Environment of this transaction.
     * @param owner User that has started this transaction.
     */
    protected Transaction(Env env, User owner) {
        this.env = env;
        taID = new TransactionID(env.keyGenerator.nextID());
        this.owner = owner;

        callStack = new SimpleArrayList(40);
        reset();
    }


    /**
     * Construct a new transaction. THIS TRANSACTION CAN BE USED FOR TESTING
     * ONLY!
     */
    protected Transaction(TransactionID _taID) {
        taID = _taID;
        reset();
    }


    public synchronized void stop() {
        stopped = true;
    }


    public void reset() {
        startTime = System.currentTimeMillis();
        status = STATUS_STARTED;
        commandCount = 0;
        callStack.clear();
        deadlocked = false;
        if (deadlockWaitTimeMaximum == 0) {
            deadlockWaitTimeMaximum = deadlockWaitTimeMaximumMinimum;
        }
    }

    protected void setDeadlockWaitTimeMaximum(long to) {
        deadlockWaitTimeMaximum = to;
    }

    protected long getDeadlockWaitTimeMaximum() {
        return deadlockWaitTimeMaximum;
    }

    protected long increaseDeadlockWaitTimeMaximum() {
        long newDeadlockWaitTimeMaximum = (long) (getDeadlockWaitTimeMaximum() * 1.5);

        if (newDeadlockWaitTimeMaximum > deadlockWaitTimeMaximumMaximum) {
            newDeadlockWaitTimeMaximum = deadlockWaitTimeMaximumMaximum;
        }

        setDeadlockWaitTimeMaximum(newDeadlockWaitTimeMaximum);

        return newDeadlockWaitTimeMaximum;
    }

    public void setDeadlocked(boolean to) {
//      env.logWriter.newEntry(this,toString()+".setDeadlocked("+to+").", LogWriter.DEBUG2);
        deadlocked = to;
    }

    public boolean isDeadlocked() {
        return deadlocked;
    }

    public int status() {
        return status;
    }


    public User owner() {
        return owner;
    }


    public int maxLockLevel() {
        return maxLockLevel;
    }

    /**
     The corresponding method to {@link #acquireObject}.
     <DIV>
     It calls on passivate and unpins the container
     </DIV>
     */
    public void releaseObject(ObjectContainer objectContainer) {
        if (objectContainer.isPinned()) {
            callOnPassivateIfNeeded(objectContainer);
            objectContainer.unpin();
        } else {
            if (env.logWriter.hasTarget(LogWriter.DEBUG)) {
                env.logWriter.newEntry(this, toString() + " debris from aborted cluster, " + objectContainer, LogWriter.DEBUG);
            }
        }
    }

    protected void callOnPassivateIfNeeded(ObjectContainer container) {
        if (container.shouldOnPassivateBeCalled()) {
                container.invokeOnPassivate();
        }
    }


    /**
     * Set a lock on the container specified by the given object ID and join
     * the container to this transaction.
     * If a container is returned, it is pinned. Thus, it has to be unpinned by the caller.
     *
     *
     * @param id ObjectID of the container which we try to join to this transaction.
     * @param lockLevel The lock level we need on this object (container).
     * @return The container for the specified id, if all was ok.
     * @throws ObjectNotFoundException If there is no such object.
     */
    public ObjectContainer acquireObject(ObjectID id, int lockLevel) throws ObjectNotFoundException, IOException, ClassNotFoundException, TransactionException, TransactionError {

        // this is not good style but this method is a hotspot and we should
        // do all we can to make it fast
        if (env.transactionManager.exclusiveThread != null &&
                env.transactionManager.exclusiveThread != Thread.currentThread()) {
            env.transactionManager.checkExclusion();
        }

        ObjectContainer container = env.storeManager.containerForID(this, id);

        if (container == null) {
            throw new ObjectNotFoundException("No such object ID: " + id);
        }

        boolean allright = false;

        try {
            container = acquireContainer(container, lockLevel);

            callOnActivateIfNeeded(container);

            allright = true;
            return container;
        } catch (Exception e) {
            throw new TransactionException(e.getMessage(), e);
        } finally {
            if (!allright) {
                container.unpin();
            }
        }
    }

    protected void callOnActivateIfNeeded(ObjectContainer container) {
        if (container.shouldOnActivateBeCalled()) {

            // We should intercept invocations here, if we had arguments and return values. But we don't.
            // env.getGarbageCollector().interceptInvocationPre(this, container, args);

            // try {
                container.invokeOnActivate();
            // } finally {
            //     env.getGarbageCollector().interceptInvocationPost(this, container, result);
            // }
        }
    }


    protected ObjectContainer acquireContainer(ObjectContainer container, int lockLevel) throws PermissionError, TransactionException, TransactionError, IOException, ObjectNotFoundException, ClassNotFoundException {

        if (stopped == true) {
            throw new TransactionException("Stopped.", TransactionException.STOPPED);
        }

        maxLockLevel = lockLevel > maxLockLevel ? lockLevel : maxLockLevel;

        acquireCount++;

        // this should help to let the following code execute without
        // interrupt and so ensure that the container that we retrieve from
        // the store is not deactivated while this method is running

⌨️ 快捷键说明

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