/*
 * Licensed to the University of California, Berkeley 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 tachyon.client;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Class representing a pool of resources to be temporarily used and returned. Inheriting classes
 * should implement the close method as well as initialize the resources in the constructor. The
 * implemented methods are thread-safe and inheriting classes should also written in a
 * thread-safe manner. See {@link tachyon.client.file.FSMasterClientPool} as an example.
 *
 * @param <T> The type of resource this pool manages.
 */
// TODO: This may fit better in the common module
public abstract class ResourcePool<T> {
  protected final Object mCapacityLock;
  protected final int mMaxCapacity;
  protected final BlockingQueue<T> mResources;
  protected int mCurrentCapacity;

  public ResourcePool(int maxCapacity) {
    mCapacityLock = new Object();
    mMaxCapacity = maxCapacity;
    mResources = new LinkedBlockingQueue<T>(maxCapacity);
  }

  /**
   * Acquires an object of type T, this operation is blocking if no clients are available.
   *
   * @return a MasterClientBase, guaranteed to be only available to the caller
   */
  public T acquire() {
    // If the resource pool is empty but capacity is not yet full, create a new resource.
    synchronized (mCapacityLock) {
      if (mResources.isEmpty() && mCurrentCapacity < mMaxCapacity) {
        T newResource = createNewResource();
        mCurrentCapacity ++;
        return newResource;
      }
    }

    // Otherwise, try to take a resource from the pool, blocking if none are available.
    try {
      return mResources.take();
    } catch (InterruptedException ie) {
      // TODO: Investigate the best way to handle this
      throw new RuntimeException(ie);
    }
  }

  /**
   * Closes the resource pool. After this call, the object should be discarded. Inheriting
   * classes should clean up all their resources here.
   */
  public abstract void close();

  /**
   * Creates a new resource which will be added to the resource pool after the user is done using
   * it. This method should only be called when the capacity of the pool has not been reached. If
   * creating the resource will take a significant amount of time, the inheriting class should
   * avoid calling this method and instead initialize all the resources in the constructor.
   *
   * @return a resource which will be added to the pool of resources.
   */
  public abstract T createNewResource();

  /**
   * Releases an object of type T, this must be called after the thread is done using a resource
   * obtained by acquire.
   *
   * @param resource the resource to be released, it should not be reused after calling this method
   */
  public void release(T resource) {
    mResources.add(resource);
  }
}

@@ -904,16 +904,62 @@
 Queue;%0A%0A
+import com.google.common.base.Preconditions;%0A%0A
 /**%0A * C
@@ -1055,22 +1055,20 @@
 sses%0A * 
-should
+must
  impleme
@@ -1233,19 +1233,16 @@
 ten in a
-%0A *
  thread-
@@ -1245,16 +1245,19 @@
 ead-safe
+%0A *
  manner.
@@ -1638,46 +1638,282 @@
 %0A%0A  
-public ResourcePool(int maxCapacity) %7B
+/**%0A   * Creates a %7B@link ResourcePool%7D instance with the specified capacity.%0A   *%0A   * @param maxCapacity the maximum of resources in this pool%0A   */%0A  public ResourcePool(int maxCapacity) %7B%0A    Preconditions.checkArgument(maxCapacity %3E 0, %22Capacity must be non-negative%22);
 %0A   
@@ -1975,16 +1975,42 @@
 pacity;%0A
+    mCurrentCapacity = 0;%0A
     mRes
@@ -2098,28 +2098,50 @@
 ect of type 
-T, t
+%7B@code T%7D from the pool. T
 his operatio
@@ -2164,114 +2164,252 @@
  no 
-clients are available.%0A   *%0A   * @return a MasterClientBase, guaranteed to be only available to the caller
+resource%0A   * is available. Each call of %7B@link #acquire%7D should be paired with another call of%0A   * %7B@link #release%7D after the use of this resource completes to return this resource to the pool.%0A   *%0A   * @return a resource taken from the pool
 %0A   
@@ -3119,21 +3119,16 @@
 ting
-%0A   *
  classes
  sho
@@ -3115,32 +3115,37 @@
 heriting classes
+%0A   *
  should clean up
@@ -3510,19 +3510,19 @@
 ould
-%0A   *
  avoid
+%0A   *
  cal
@@ -3760,17 +3760,25 @@
 of type 
-T
+%7B@code T%7D
 , this m
@@ -3823,16 +3823,21 @@
  using a
+%0A   *
  resourc
@@ -3837,21 +3837,16 @@
 resource
-%0A   *
  obtaine
@@ -3850,23 +3850,32 @@
 ined by 
+%7B@link #
 acquire
+%7D
 .%0A   *%0A 

Fix documents of ResourcePool.java