/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.twitter.distributedlog.lock; import com.twitter.distributedlog.exceptions.LockingException; import com.twitter.distributedlog.exceptions.OwnershipAcquireFailedException; import com.twitter.util.Future; import scala.runtime.BoxedUnit; import java.util.concurrent.TimeUnit; /** * One time lock. * <p>The lock is only alive during a given period. It should * be not usable if the lock is expired. * <p>Listener could be registered by {@link #setLockListener(LockListener)} * to receive state changes of the lock. */ public interface SessionLock { /** * Set lock listener for lock state changes. * <p>Typically a listener should be set before try locking. * * @param lockListener * lock listener for state changes. */ SessionLock setLockListener(LockListener lockListener); /** * Whether the lock is held or not? * * @return true if the lock is held, otherwise false. */ boolean isLockHeld(); /** * Whether the lock is expired or not? * <p>If a lock is expired, it will not be reusable any more. Because it is an one-time lock. * * @return true if the lock is expired, otherwise false. */ boolean isLockExpired(); /** * Acquire the lock if it is free within given waiting time. * <p> * Calling this method will attempt to acquire the lock. If the lock * is already acquired by others, the caller will wait for <i>timeout</i> * period. If the caller could claim the lock within <i>timeout</i> period, * the caller acquire the lock. Otherwise, it would fail with {@link OwnershipAcquireFailedException}. * <p> * {@link #unlock()} should be called to unlock a claimed lock. The caller * doesn't need to unlock to clean up resources if <i>tryLock</i> fails. * <p> * <i>tryLock</i> here is effectively the combination of following asynchronous calls. * <pre> * ZKDistributedLock lock = ...; * Future<LockWaiter> attemptFuture = lock.asyncTryLock(...); * * boolean acquired = waiter.waitForAcquireQuietly(); * if (acquired) { * // ... * } else { * // ... * } * </pre> * * @param timeout * timeout period to wait for claiming ownership * @param unit * unit of timeout period * @throws OwnershipAcquireFailedException if the lock is already acquired by others * @throws LockingException when encountered other lock related issues. */ void tryLock(long timeout, TimeUnit unit) throws OwnershipAcquireFailedException, LockingException; /** * Acquire the lock in asynchronous way. * <p> * Calling this method will attempt to place a lock waiter to acquire this lock. * The future returned by this method represents the result of this attempt. It doesn't mean * the caller acquired the lock or not. The application should check {@link LockWaiter#getAcquireFuture()} * to see if it acquired the lock or not. * * @param timeout * timeout period to wait for claiming ownership * @param unit * unit of timeout period * @return lock waiter representing this attempt of acquiring lock. * @see #tryLock(long, TimeUnit) */ Future<LockWaiter> asyncTryLock(long timeout, TimeUnit unit); /** * Release a claimed lock. * * @see #tryLock(long, TimeUnit) */ void unlock(); /** * Release a claimed lock in the asynchronous way. * * @return future representing the result of unlock operation. * @see #unlock() */ Future<BoxedUnit> asyncUnlock(); }