content: /*
   * 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 org.apache.distributedlog.lock;
  
  import java.util.concurrent.CompletableFuture;
  import java.util.concurrent.TimeUnit;
  import org.apache.distributedlog.exceptions.LockingException;
  import org.apache.distributedlog.exceptions.OwnershipAcquireFailedException;
  
  /**
   * 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 = ...;
       *     CompletableFuture&lt;LockWaiter&gt; 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)
       */
      CompletableFuture<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()
       */
      CompletableFuture<Void> asyncUnlock();
  
  }
  