// Copyright 2017 JanusGraph Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.janusgraph.diskstorage.locking;
import org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction;
import org.janusgraph.diskstorage.util.KeyColumn;
/**
* Threadsafe discretionary locking within and between processes JanusGraph.
* <p>
* Locks are identified {@link KeyColumn} instances.
* {@code KeyColumn#equals(Object)} should be used to determine whether two
* {@code KeyColumn} instances refer to the same or different locks.
* <p>
* Threads taking locks are identified by {@link StoreTransaction} instances.
* Either {@code equals(...)} or reference equality (the {@code ==} operator)
* can be used to compare these instances.
* <p>
* This interface follows a three-step locking model that supports both
* nonblocking and blocking locking primitives. Not all JanusGraph
* {@code StoreTransaction}s will need locks and use this interface. For those
* {@code StoreTransaction}s that do take one or more locks, JanusGraph will call the
* methods on this interface in the following order. {@code tx} refers to the
* same {@code StoreTransaction} instance in each step.
*
* <ol>
* <li>{@code writeLock(kc, tx)} one or more times per distinct
* {@code KeyColumn kc}
* <li>{@code checkLocks(tx)} once if the user commits {@code tx} or never if
* the user aborts {@code tx}
* <li>{@code deleteLocks(tx)} once, regardless of whether
* {@code checkLocks(tx)} was called
* </ol>
*
* <p>
* The first step, {@code writeLocks}, attempts to take a lock. This may, but
* need not necessarily, indicate whether the attempt succeeded or failed. The
* second step, {@code checkLocks}, returns if all previous {@code writeLocks}
* succeeded or throws an exception if one or more failed. The final step,
* {@code deleteLocks}, releases all locks and associated resources held by the
* {@code tx}.
* <p>
* All implementations of this interface must be safe for concurrent use by
* different threads. However, implementations may assume that, for any given
* {@code StoreTransaction tx}, all calls to this interface's methods with
* argument {@code tx} will either come from a single thread or multiple threads
* using external synchronization to provide the same effect.
*/
public interface Locker {
/**
* Attempt to acquire/take/claim/write the lock named by {@code lockID}.
* <p>
* Returns on success and throws an exception on failure.
*
* @param lockID
* the lock to acquire
* @param tx
* the transaction attempting to acquire the lock
* @throws TemporaryLockingException
* a failure likely to disappear if the call is retried
* @throws PermanentLockingException
* a failure unlikely to disappear if the call is retried
*/
public void writeLock(KeyColumn lockID, StoreTransaction tx)
throws TemporaryLockingException, PermanentLockingException;
/**
* Verify that all previous {@link #writeLock(KeyColumn, StoreTransaction)}
* calls with {@code tx} actually succeeded.
* <p>
* Returns on success and throws an exception on failure.
*
* @param tx
* the transaction attempting to check the result of previous
* {@code writeLock(..., tx)} calls in which it was the
* {@code tx} argument
* @throws TemporaryLockingException
* a failure likely to disappear if the call is retried
* @throws PermanentLockingException
* a failure unlikely to disappear if the call is retried
*/
public void checkLocks(StoreTransaction tx)
throws TemporaryLockingException, PermanentLockingException;
/**
* Release every lock currently held by {@code tx}.
* <p>
* Returns on success and throws an exception on failure.
*
* @param tx
* the transaction attempting to delete locks taken in previous
* {@code writeLock(..., tx)} calls in which it was the
* {@code tx} argument
* @throws TemporaryLockingException
* a failure likely to disappear if the call is retried
* @throws PermanentLockingException
* a failure unlikely to disappear if the call is retried
*/
public void deleteLocks(StoreTransaction tx)
throws TemporaryLockingException, PermanentLockingException;
}