All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.txn.ThreadLocker Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.txn;

import java.util.Iterator;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.OperationFailureException;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.EnvironmentImpl;

/**
 * Extends BasicLocker to share locks among all lockers for the same thread.
 * This locker is used when a JE entry point is called with a null transaction
 * parameter.
 */
public class ThreadLocker extends BasicLocker {

    /**
     * Set to allow this locker to be used by multiple threads.  This mode
     * should only be set temporarily, for example, while locking in
     * lockAfterLsnChange.
     */
    private boolean allowMultithreadedAccess;

    /**
     * Creates a ThreadLocker.
     */
    public ThreadLocker(EnvironmentImpl env) {
        super(env);
        lockManager.registerThreadLocker(this);
    }

    public static ThreadLocker createThreadLocker(EnvironmentImpl env,
                                                  boolean replicated)
        throws DatabaseException {

        return (env.isReplicated() && replicated) ?
               env.createRepThreadLocker() :
               new ThreadLocker(env);
    }

    @Override
    void close() {
        super.close();
        lockManager.unregisterThreadLocker(this);
    }

    /**
     * Checks for preemption in all thread lockers for this thread.
     */
    @Override
    public void checkPreempted(final Locker allowPreemptedLocker) 
        throws OperationFailureException {

        final Iterator iter =
            lockManager.getThreadLockers(thread);
        while (iter.hasNext()) {
            final ThreadLocker locker = iter.next();
            locker.throwIfPreempted(allowPreemptedLocker);
        }
    }

    /**
     * Set the allowMultithreadedAccess mode during execution of this method
     * because a ThreadLocker is not normally allowed to perform locking from
     * more than one thread.
     */
    @Override
    public synchronized void lockAfterLsnChange(long oldLsn,
                                                long newLsn,
                                                DatabaseImpl dbImpl) {
        final boolean oldVal = allowMultithreadedAccess;
        allowMultithreadedAccess = true;
        try {
            super.lockAfterLsnChange(oldLsn, newLsn, dbImpl);
        } finally {
            allowMultithreadedAccess = oldVal;
        }
    }

    /**
     * Check that this locker is not used in the wrong thread.
     *
     * @throws IllegalStateException via all Cursor methods that use a
     * non-transactional locker.
     */
    @Override
    protected synchronized void checkState(boolean ignoreCalledByAbort) {
        if (!allowMultithreadedAccess && thread != Thread.currentThread()) {
            throw new IllegalStateException
                ("Non-transactional Cursors may not be used in multiple " +
                 "threads; Cursor was created in " + thread +
                 " but used in " + Thread.currentThread());
        }
    }

    /**
     * Returns a new non-transactional locker that shares locks with this
     * locker by virtue of being a ThreadLocker for the same thread.
     */
    @Override
    public Locker newNonTxnLocker()
        throws DatabaseException {

        checkState(false);
        return newEmptyThreadLockerClone();
    }

    public ThreadLocker newEmptyThreadLockerClone() {
        return new ThreadLocker(envImpl);
    }

    /**
     * Returns whether this locker can share locks with the given locker.
     * Locks are shared when both lockers are ThreadLocker instances for the
     * same thread.
     */
    @Override
    public boolean sharesLocksWith(Locker other) {

        if (super.sharesLocksWith(other)) {
            return true;
        } else if (other instanceof ThreadLocker) {
            return thread == other.thread;
        } else {
            return false;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy