final _Locker localLocker() { SoftReference<_Locker> lockerRef = mLocalLockerRef.get(); _Locker locker; if (lockerRef == null || (locker = lockerRef.get()) == null) { mLocalLockerRef.set(new SoftReference<>(locker = new _Locker(this))); } return locker; }
final LockResult lockUpgradable(long indexId, byte[] key, int hash, long nanosTimeout) throws LockFailureException { return lock(TYPE_UPGRADABLE, indexId, key, hash, nanosTimeout); }
final LockResult lockExclusive(long indexId, byte[] key, int hash) throws LockFailureException { return super.lockExclusive(indexId, key, hash, mLockTimeoutNanos); }
/** * _Lock acquisition used by recovery. * * @param lock _Lock instance to insert, unless another already exists. The mIndexId, * mKey, and mHashCode fields must be set. */ final LockResult lockExclusive(_Lock lock, long nanosTimeout) throws LockFailureException { LockResult result = mManager.getLockHT(lock.mHashCode) .tryLockExclusive(this, lock, nanosTimeout); if (result.isHeld()) { return result; } throw failed(TYPE_EXCLUSIVE, result, nanosTimeout, lock.mHashCode); }
/** * @param lockType TYPE_SHARED, TYPE_UPGRADABLE, or TYPE_EXCLUSIVE */ final LockResult lock(int lockType, long indexId, byte[] key, int hash, long nanosTimeout) throws LockFailureException { LockResult result = manager().getLockHT(hash) .tryLock(lockType, this, indexId, key, hash, nanosTimeout); if (result.isHeld()) { return result; } throw failed(lockType, result, nanosTimeout); }
/** * NT == No Timeout or deadlock exception thrown * * @return {@link LockResult#TIMED_OUT_LOCK TIMED_OUT_LOCK}, {@link * LockResult#ACQUIRED ACQUIRED}, {@link LockResult#OWNED_SHARED * OWNED_SHARED}, {@link LockResult#OWNED_UPGRADABLE OWNED_UPGRADABLE}, or * {@link LockResult#OWNED_EXCLUSIVE OWNED_EXCLUSIVE} */ final LockResult lockSharedNT(long indexId, byte[] key, int hash, long nanosTimeout) throws LockFailureException { return lockNT(TYPE_SHARED, indexId, key, hash, nanosTimeout); }
@Override public final _LocalDatabase getDatabase() { return manager().mDatabaseRef.get(); }
@Override public boolean store(long indexId, byte[] key, byte[] value) throws IOException { // Must acquire the lock before task is enqueued. _Locker locker = new _Locker(mDatabase.mLockManager); locker.attach(ATTACHMENT); locker.tryLockUpgradable(indexId, key, INFINITE_TIMEOUT); runTaskAnywhere(new Worker.Task() { public void run() throws IOException { try { Index ix = getIndex(indexId); // Full exclusive lock is required. locker.lockExclusive(indexId, key, INFINITE_TIMEOUT); doStore(Transaction.BOGUS, indexId, key, value); } finally { locker.scopeUnlockAll(); } } }); return true; }
final LockResult lockUpgradable(long indexId, byte[] key, int hash) throws LockFailureException { return super.lockUpgradable(indexId, key, hash, mLockTimeoutNanos); }
/** * Returns the key of the last lock acquired, within the current scope. * * <p><i>Note: This method is intended for advanced use cases.</i> * * @return locked key; instance is not cloned * @throws IllegalStateException if no locks held */ public final byte[] lastLockedKey() { return peek().mKey; }
@Override public final LockResult lockShared(long indexId, byte[] key) throws LockFailureException { return super.lockShared(indexId, key, mLockTimeoutNanos); }
@Override public boolean store(long indexId, byte[] key, byte[] value) throws IOException { Index ix = getIndex(indexId); // Allow side-effect free operations to be performed before acquiring latch. mOpLatch.acquireShared(); // Locks must be acquired in their original order to avoid // deadlock, so don't allow another task thread to run yet. _Locker locker = mDatabase.mLockManager.localLocker(); locker.lockExclusive(indexId, key, INFINITE_TIMEOUT); // Allow another task thread to run while operation completes. nextTask(); try { while (ix != null) { try { ix.store(Transaction.BOGUS, key, value); break; } catch (ClosedIndexException e) { // User closed the shared index reference, so re-open it. ix = openIndex(indexId, null); } } } finally { locker.scopeUnlockAll(); } // Only release if no exception. mOpLatch.releaseShared(); notifyStore(ix, key, value); // Return false to prevent RedoDecoder from looping back. return false; }
/** * @param lockType TYPE_SHARED, TYPE_UPGRADABLE, or TYPE_EXCLUSIVE */ final LockResult tryLock(int lockType, long indexId, byte[] key, int hash, long nanosTimeout) throws DeadlockException { LockResult result = manager().getLockHT(hash) .tryLock(lockType, this, indexId, key, hash, nanosTimeout); if (result == LockResult.TIMED_OUT_LOCK) { _Lock waitingFor = mWaitingFor; if (waitingFor != null) { try { // Perform deadlock detection except for the fast-fail case. if (nanosTimeout != 0) { detectDeadlock(waitingFor, lockType, nanosTimeout, hash); } } finally { mWaitingFor = null; } } } return result; }
if (!locker.canAttemptUpgrade(count)) { return ILLEGAL; if (!locker.canAttemptUpgrade(count)) {
/** * _Lock acquisition used by recovery. * * @param lock _Lock instance to insert, unless another already exists. The mIndexId, * mKey, and mHashCode fields must be set. */ final LockResult lockExclusive(_Lock lock, long nanosTimeout) throws LockFailureException { LockResult result = mManager.getLockHT(lock.mHashCode) .tryLockExclusive(this, lock, nanosTimeout); if (result.isHeld()) { return result; } throw failed(TYPE_EXCLUSIVE, result, nanosTimeout); }
/** * @param lockType TYPE_SHARED, TYPE_UPGRADABLE, or TYPE_EXCLUSIVE */ final LockResult lock(int lockType, long indexId, byte[] key, int hash, long nanosTimeout) throws LockFailureException { LockResult result = manager().getLockHT(hash) .tryLock(lockType, this, indexId, key, hash, nanosTimeout); if (result.isHeld()) { return result; } throw failed(lockType, result, nanosTimeout, hash); }
/** * NT == No Timeout or deadlock exception thrown * * @return {@link LockResult#TIMED_OUT_LOCK TIMED_OUT_LOCK}, {@link * LockResult#ACQUIRED ACQUIRED}, {@link LockResult#OWNED_SHARED * OWNED_SHARED}, {@link LockResult#OWNED_UPGRADABLE OWNED_UPGRADABLE}, or * {@link LockResult#OWNED_EXCLUSIVE OWNED_EXCLUSIVE} */ final LockResult lockSharedNT(long indexId, byte[] key, int hash, long nanosTimeout) throws LockFailureException { return lockNT(TYPE_SHARED, indexId, key, hash, nanosTimeout); }
/** * Checks the lock ownership for the given key. * * <p><i>Note: This method is intended for advanced use cases.</i> * * @return {@link LockResult#UNOWNED UNOWNED}, {@link * LockResult#OWNED_SHARED OWNED_SHARED}, {@link * LockResult#OWNED_UPGRADABLE OWNED_UPGRADABLE}, or {@link * LockResult#OWNED_EXCLUSIVE OWNED_EXCLUSIVE} */ public final LockResult lockCheck(long indexId, byte[] key) { return manager().check(this, indexId, key, hash(indexId, key)); }
@Override public boolean store(long indexId, byte[] key, byte[] value) throws IOException { _Locker locker = new _Locker(mDatabase.mLockManager); locker.attach(ATTACHMENT); locker.tryLockUpgradable(indexId, key, INFINITE_TIMEOUT);
final LockResult lockUpgradable(long indexId, byte[] key, int hash) throws LockFailureException { return super.lockUpgradable(indexId, key, hash, mLockTimeoutNanos); }