mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
11.38.2013 7bcb81dd86201dc52b82ce18cfa00af463683a8f
Partial fix for OPENDJ-885: Replication replay may lose changes if it can't acquire a writeLock

* remove a bunch of dead code in our entry cache implementations. OPENDJ-885 requires that we no longer use timeouts when using the LockManager. Our entry caches were one such place where we used the lock manager with timeouts. However, on closer examination I found that we never use the locking capabilities of our entry caches, so a simple fix is to remove the dead functionality
12 files modified
845 ■■■■■ changed files
opends/src/server/org/opends/server/api/EntryCache.java 233 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/EntryContainer.java 30 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/DefaultEntryCache.java 168 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/FIFOEntryCache.java 25 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java 63 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java 18 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/LockManager.java 9 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CommonEntryCacheTestCase.java 169 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java 38 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java 25 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java 56 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/EntryCache.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.opends.server.api;
import org.opends.messages.Message;
@@ -33,15 +34,12 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.atomic.AtomicLong;
import org.opends.server.config.ConfigException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockType;
import org.opends.server.types.LockManager;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.admin.std.server.EntryCacheCfg;
@@ -101,10 +99,6 @@
  private Set<SearchFilter> includeFilters =
       new HashSet<SearchFilter>(0);
  // The maximum length of time to try to obtain a lock before giving
  // up.
  private long lockTimeout = LockManager.DEFAULT_TIMEOUT;
  /**
   * Arbitrary number of cache hits for monitoring.
   */
@@ -210,11 +204,7 @@
  /**
   * Retrieves the entry with the specified DN from the cache.  The
   * caller should have already acquired a read or write lock for the
   * entry if such protection is needed.
   * Note that this method is called from @see #getEntry(DN entryDN,
   * LockType lockType, List lockList)
   * Retrieves the entry with the specified DN from the cache.
   *
   * @param  entryDN  The DN of the entry to retrieve.
   *
@@ -226,192 +216,28 @@
  /**
   * Retrieves the entry with the specified DN from the cache,
   * obtaining a lock on the entry before it is returned.  If the
   * entry is present in the cache, then a lock will be obtained for
   * that entry and appended to the provided list before the entry is
   * returned.  If the entry is not present, then no lock will be
   * obtained.  Note that although this method is declared non-final
   * it is not recommended for subclasses to implement this method.
   *
   * @param  entryDN   The DN of the entry to retrieve.
   * @param  lockType  The type of lock to obtain (it may be
   *                   {@code NONE}).
   * @param  lockList  The list to which the obtained lock will be
   *                   added (note that no lock will be added if the
   *                   lock type was {@code NONE}).
   *
   * @return  The requested entry if it is present in the cache, or
   *          {@code null} if it is not present.
   */
  public Entry getEntry(DN entryDN,
                        LockType lockType,
                        List<Lock> lockList) {
    if (!containsEntry(entryDN)) {
      // Indicate cache miss.
      cacheMisses.getAndIncrement();
      return null;
    }
    // Obtain a lock for the entry before actually retrieving the
    // entry itself thus preventing any stale entries being returned,
    // see Issue #1589 for more details.  If an error occurs, then
    // make sure no lock is held and return null. Otherwise, return
    // the entry.
    switch (lockType)
    {
      case READ:
        // Try to obtain a read lock for the entry.
        Lock readLock = LockManager.lockRead(entryDN, lockTimeout);
        if (readLock == null)
        {
          // We couldn't get the lock, so we have to return null.
          return null;
        }
        else
        {
          try
          {
            lockList.add(readLock);
            // and load.
            Entry entry = getEntry(entryDN);
            if (entry == null)
            {
              lockList.remove(readLock);
              LockManager.unlock(entryDN, readLock);
              return null;
            }
            return entry;
          }
          catch (Exception e)
          {
            if (debugEnabled())
            {
              TRACER.debugCaught(DebugLogLevel.ERROR, e);
            }
            // The attempt to add the lock to the list failed,
            // so we need to release the lock and return null.
            try
            {
              LockManager.unlock(entryDN, readLock);
            }
            catch (Exception e2)
            {
              if (debugEnabled())
              {
                TRACER.debugCaught(DebugLogLevel.ERROR, e2);
              }
            }
            return null;
          }
        }
      case WRITE:
        // Try to obtain a write lock for the entry.
        Lock writeLock = LockManager.lockWrite(entryDN, lockTimeout);
        if (writeLock == null)
        {
          // We couldn't get the lock, so we have to return null.
          return null;
        }
        else
        {
          try
          {
            lockList.add(writeLock);
            // and load.
            Entry entry = getEntry(entryDN);
            if (entry == null)
            {
              lockList.remove(writeLock);
              LockManager.unlock(entryDN, writeLock);
              return null;
            }
            return entry;
          }
          catch (Exception e)
          {
            if (debugEnabled())
            {
              TRACER.debugCaught(DebugLogLevel.ERROR, e);
            }
            // The attempt to add the lock to the list failed,
            // so we need to release the lock and return null.
            try
            {
              LockManager.unlock(entryDN, writeLock);
            }
            catch (Exception e2)
            {
              if (debugEnabled())
              {
                TRACER.debugCaught(DebugLogLevel.ERROR, e2);
              }
            }
            return null;
          }
        }
      case NONE:
        // We don't need to obtain a lock, so just return the entry.
        Entry entry = getEntry(entryDN);
        if (entry == null)
        {
          return null;
        }
        return entry;
      default:
        // This is an unknown type of lock, so we'll return null.
        return null;
    }
  }
  /**
   * Retrieves the requested entry if it is present in the cache,
   * obtaining a lock on the entry before it is returned.  If the
   * entry is present in the cache, then a lock  will be obtained for
   * that entry and appended to the provided list before the entry is
   * returned.  If the entry is not present, then no lock will be
   * obtained.  Note that although this method is declared non-final
   * it is not recommended for subclasses to implement this method.
   * Retrieves the requested entry if it is present in the cache.
   *
   * @param  backend   The backend associated with the entry to
   *                   retrieve.
   * @param  entryID   The entry ID within the provided backend for
   *                   the specified entry.
   * @param  lockType  The type of lock to obtain (it may be
   *                   {@code NONE}).
   * @param  lockList  The list to which the obtained lock will be
   *                   added (note that no lock will be added if the
   *                   lock type was {@code NONE}).
   *
   * @return  The requested entry if it is present in the cache, or
   *          {@code null} if it is not present.
   */
  public Entry getEntry(Backend backend, long entryID,
                                 LockType lockType,
                                 List<Lock> lockList) {
  public Entry getEntry(Backend backend, long entryID)
  {
    // Translate given backend/entryID pair to entryDN.
    DN entryDN = getEntryDN(backend, entryID);
    if (entryDN == null) {
    if (entryDN == null)
    {
      // Indicate cache miss.
      cacheMisses.getAndIncrement();
      return null;
    }
    // Delegate to by DN lock and load method.
    return getEntry(entryDN, lockType, lockList);
    return getEntry(entryDN);
  }
@@ -615,34 +441,6 @@
  /**
   * Retrieves the maximum length of time in milliseconds to wait for
   * a lock before giving up.
   *
   * @return  The maximum length of time in milliseconds to wait for a
   *          lock before giving up.
   */
  public long getLockTimeout()
  {
    return lockTimeout;
  }
  /**
   * Specifies the maximum length of time in milliseconds to wait for
   * a lock before giving up.
   *
   * @param  lockTimeout  The maximum length of time in milliseconds
   *                      to wait for a lock before giving up.
   */
  public void setLockTimeout(long lockTimeout)
  {
    this.lockTimeout = lockTimeout;
  }
  /**
   * Retrieves the set of search filters that may be used to determine
   * whether an entry should be excluded from the cache.
   *
@@ -789,4 +587,19 @@
    return true;
  }
  /**
   * Return a verbose string representation of the current cache maps. This is
   * useful primary for debugging and diagnostic purposes such as in the entry
   * cache unit tests.
   * <p>
   * This method is invoked by unit tests for debugging.
   *
   * @return String verbose string representation of the current cache maps in
   *         the following format: dn:id:backend one cache entry map
   *         representation per line or <CODE>null</CODE> if all maps are empty.
   */
  public abstract String toVerboseString();
}
opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -1283,7 +1283,6 @@
    DatabaseEntry data = new DatabaseEntry();
    DatabaseEntry key = new DatabaseEntry(begin);
    List<Lock> lockList = new ArrayList<Lock>(1);
    int lookthroughCount = 0;
    int lookthroughLimit =
@@ -1337,10 +1336,8 @@
            Entry entry;
            Entry cacheEntry;
            // Try the entry cache first. Note no need to take a lock.
            lockList.clear();
            cacheEntry = entryCache.getEntry(backend, entryID.longValue(),
                LockType.NONE, lockList);
            // Try the entry cache first.
            cacheEntry = entryCache.getEntry(backend, entryID.longValue());
            if (cacheEntry == null)
            {
@@ -1495,23 +1492,14 @@
    // Iterate through the index candidates.
    if (continueSearch)
    {
      List<Lock> lockList = new ArrayList<Lock>();
      Iterator<EntryID> iterator = entryIDList.iterator(begin);
      while (iterator.hasNext())
      {
        EntryID id = iterator.next();
        Entry entry;
        Entry cacheEntry;
        // Try the entry cache first. Note no need to take a lock.
        lockList.clear();
        cacheEntry = entryCache.getEntry(backend, id.longValue(),
            LockType.NONE, lockList);
        // Release any entry lock whatever happens during this block.
        // (This is actually redundant since we did not take a lock).
        try
        {
        // Try the entry cache first.
        Entry cacheEntry = entryCache.getEntry(backend, id.longValue());
          if (cacheEntry == null)
          {
            // Fetch the candidate entry from the database.
@@ -1613,18 +1601,8 @@
            }
          }
        }
        finally
        {
          // Release any entry lock acquired by the entry cache
          // (This is actually redundant since we did not take a lock).
          for (Lock lock : lockList)
          {
            lock.unlock();
          }
        }
        searchOperation.checkIfCanceled(false);
      }
    }
    // Before we return success from the search we must ensure the base entry
    // exists. However, if we have returned at least one entry or subordinate
opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
@@ -23,18 +23,17 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
import java.lang.reflect.Method;
import org.opends.messages.Message;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.concurrent.locks.Lock;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.EntryCacheCfg;
@@ -50,7 +49,6 @@
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockType;
import org.opends.server.types.ResultCode;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -110,7 +108,7 @@
  @Override
  public void finalizeEntryCache()
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      entryCache.finalizeEntryCache();
    }
    // ReInitialize cache order array.
@@ -128,7 +126,7 @@
      return false;
    }
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      if (entryCache.containsEntry(entryDN)) {
        return true;
      }
@@ -142,52 +140,23 @@
   * {@inheritDoc}
   */
  @Override
  public Entry getEntry(DN entryDN,
                        LockType lockType,
                        List<Lock> lockList)
  public Entry getEntry(Backend backend, long entryID)
  {
    Entry entry = null;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder) {
      entry = entryCache.getEntry(entryDN, lockType, lockList);
      if (entry != null) {
        break;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder)
    {
      Entry entry = entryCache.getEntry(backend, entryID);
      if (entry != null)
      {
        return entry.duplicate(true);
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
      cacheMisses.getAndIncrement();
    }
    return (entry != null ? entry.duplicate(true) : null);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Entry getEntry(Backend backend, long entryID,
                                 LockType lockType,
                                 List<Lock> lockList)
    if (cacheOrder.length != 0)
  {
    Entry entry = null;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder) {
      entry = entryCache.getEntry(backend, entryID, lockType,
          lockList);
      if (entry != null) {
        break;
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
      cacheMisses.getAndIncrement();
    }
    return (entry != null ? entry.duplicate(true) : null);
    return null;
  }
@@ -197,21 +166,21 @@
  @Override
  public Entry getEntry(DN entryDN)
  {
    Entry entry = null;
    for (EntryCache entryCache : cacheOrder) {
      entry = entryCache.getEntry(entryDN);
      if (entry != null) {
        break;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder)
    {
      Entry entry = entryCache.getEntry(entryDN);
      if (entry != null)
      {
        return entry.duplicate(true);
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
    if (cacheOrder.length != 0)
    {
      cacheMisses.getAndIncrement();
    }
    return (entry != null ? entry.duplicate(true) : null);
    return null;
  }
@@ -222,17 +191,16 @@
  @Override
  public long getEntryID(DN entryDN)
  {
    long entryID = -1;
    for (EntryCache entryCache : cacheOrder) {
      entryID = entryCache.getEntryID(entryDN);
      if (entryID != -1) {
        break;
      }
    }
    for (EntryCache<?> entryCache : cacheOrder)
    {
      long entryID = entryCache.getEntryID(entryDN);
      if (entryID != -1)
      {
    return entryID;
  }
    }
    return -1;
  }
@@ -242,17 +210,16 @@
  @Override
  public DN getEntryDN(Backend backend, long entryID)
  {
    DN entryDN = null;
    for (EntryCache entryCache : cacheOrder) {
      entryDN = entryCache.getEntryDN(backend, entryID);
      if (entryDN != null) {
        break;
      }
    }
    for (EntryCache<?> entryCache : cacheOrder)
    {
      DN entryDN = entryCache.getEntryDN(backend, entryID);
      if (entryDN != null)
      {
    return entryDN;
  }
    }
    return null;
  }
@@ -262,7 +229,7 @@
  @Override
  public void putEntry(Entry entry, Backend backend, long entryID)
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      // The first cache in the order which can take this entry
      // gets it.
      if (entryCache.filtersAllowCaching(entry)) {
@@ -281,7 +248,7 @@
  @Override
  public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      // The first cache in the order which can take this entry
      // gets it.
      if (entryCache.filtersAllowCaching(entry)) {
@@ -301,7 +268,7 @@
  @Override
  public void removeEntry(DN entryDN)
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      if (entryCache.containsEntry(entryDN)) {
        entryCache.removeEntry(entryDN);
        break;
@@ -317,7 +284,7 @@
  @Override
  public void clear()
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      entryCache.clear();
    }
  }
@@ -330,7 +297,7 @@
  @Override
  public void clearBackend(Backend backend)
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      entryCache.clearBackend(backend);
    }
  }
@@ -343,7 +310,7 @@
  @Override
  public void clearSubtree(DN baseDN)
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      entryCache.clearSubtree(baseDN);
    }
  }
@@ -356,7 +323,7 @@
  @Override
  public void handleLowMemory()
  {
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      entryCache.handleLowMemory();
    }
  }
@@ -413,7 +380,7 @@
    // implementations.
    Long currentEntryCacheCount = new Long(0);
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      // Get cache hits and counts from every active cache.
      entryCacheHits += entryCache.getCacheHits();
      currentEntryCacheCount += entryCache.getCacheCount();
@@ -447,7 +414,7 @@
  {
    Long cacheCount = new Long(0);
    for (EntryCache entryCache : cacheOrder) {
    for (EntryCache<?> entryCache : cacheOrder) {
      cacheCount += entryCache.getCacheCount();
    }
@@ -457,41 +424,20 @@
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
   * @return String verbose string representation of the current cache
   *                maps in the following format: dn:id:backend
   *                one cache entry map representation per line
   *                or <CODE>null</CODE> if all maps are empty.
   * {@inheritDoc}
   */
  private String toVerboseString()
  public String toVerboseString()
  {
    StringBuilder sb = new StringBuilder();
    for (EntryCache entryCache : cacheOrder) {
      final Method[] cacheMethods =
        entryCache.getClass().getDeclaredMethods();
      for (int i = 0; i < cacheMethods.length; ++i) {
        if (cacheMethods[i].getName().equals("toVerboseString")) {
          cacheMethods[i].setAccessible(true);
          try {
            Object cacheVerboseString =
              cacheMethods[i].invoke(entryCache, (Object[]) null);
            if (cacheVerboseString != null) {
              sb.append((String) cacheVerboseString);
            }
          } catch (Exception e) {
            if (debugEnabled()) {
              TRACER.debugCaught(DebugLogLevel.ERROR, e);
    for (EntryCache<?> entryCache : cacheOrder)
    {
      String s = entryCache.toVerboseString();
      if (s != null)
      {
        sb.append(s);
            }
          }
        }
      }
    }
    String verboseString = sb.toString();
    return (verboseString.length() > 0 ? verboseString : null);
  }
opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2012 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -53,6 +53,7 @@
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockManager;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.Attribute;
import org.opends.server.util.ServerConstants;
@@ -126,6 +127,10 @@
  // Currently registered configuration object.
  private FIFOEntryCacheCfg registeredConfiguration;
  // The maximum length of time to try to obtain a lock before giving
  // up.
  private long lockTimeout = LockManager.DEFAULT_TIMEOUT;
  /**
@@ -320,7 +325,7 @@
    // Obtain a lock on the cache.  If this fails, then don't do anything.
    try
    {
      if (!cacheWriteLock.tryLock(getLockTimeout(), TimeUnit.MILLISECONDS))
      if (!cacheWriteLock.tryLock(lockTimeout, TimeUnit.MILLISECONDS))
      {
        return;
      }
@@ -450,7 +455,7 @@
    // Obtain a lock on the cache.  If this fails, then don't do anything.
    try
    {
      if (!cacheWriteLock.tryLock(getLockTimeout(), TimeUnit.MILLISECONDS))
      if (!cacheWriteLock.tryLock(lockTimeout, TimeUnit.MILLISECONDS))
      {
        // We can't rule out the possibility of a conflict, so return false.
        return false;
@@ -1026,11 +1031,9 @@
    {
      maxEntries       = newMaxEntries;
      maxAllowedMemory = newMaxAllowedMemory;
      setLockTimeout(newLockTimeout);
      lockTimeout = newLockTimeout;
      setIncludeFilters(newIncludeFilters);
      setExcludeFilters(newExcludeFilters);
      registeredConfiguration = configuration;
    }
@@ -1083,15 +1086,9 @@
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
   * @return String verbose string representation of the current cache
   *                maps in the following format: dn:id:backend
   *                one cache entry map representation per line
   *                or <CODE>null</CODE> if all maps are empty.
   * {@inheritDoc}
   */
  private String toVerboseString()
  public String toVerboseString()
  {
    StringBuilder sb = new StringBuilder();
opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2012 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -169,7 +169,7 @@
  // Class database, catalog and binding for serialization.
  private Database entryCacheClassDB;
  private StoredClassCatalog classCatalog;
  private EntryBinding entryCacheDataBinding;
  private EntryBinding<FileSystemEntryCacheIndex> entryCacheDataBinding;
  // JE naming constants.
  private static final String ENTRYCACHEDBNAME = "EntryCacheDB";
@@ -187,6 +187,10 @@
  // Currently registered configuration object.
  private FileSystemEntryCacheCfg registeredConfiguration;
  // The maximum length of time to try to obtain a lock before giving
  // up.
  private long lockTimeout = LockManager.DEFAULT_TIMEOUT;
  /**
   * Creates a new instance of this entry cache.
   */
@@ -207,7 +211,6 @@
   * {@inheritDoc}
   */
  @Override
  @SuppressWarnings("unchecked")
  public void initializeEntryCache(FileSystemEntryCacheCfg configuration)
          throws ConfigException, InitializationException {
@@ -304,9 +307,8 @@
      classCatalog = new StoredClassCatalog(entryCacheClassDB);
      //This line causes an unchecked call error if the SuppressWarnings
      //annotation is removed at the beginning of this method.
      entryCacheDataBinding =
          new SerialBinding(classCatalog,
          FileSystemEntryCacheIndex.class);
      entryCacheDataBinding = new SerialBinding<FileSystemEntryCacheIndex>(
          classCatalog, FileSystemEntryCacheIndex.class);
      // Get the root configuration object.
      ServerManagementContext managementContext =
@@ -336,9 +338,7 @@
          if (OperationStatus.SUCCESS ==
              entryCacheDB.get(null, indexKey, indexData, LockMode.DEFAULT)) {
            entryCacheIndex =
                (FileSystemEntryCacheIndex)
                entryCacheDataBinding.entryToObject(indexData);
            entryCacheIndex = entryCacheDataBinding.entryToObject(indexData);
          } else {
            throw new CacheIndexNotFoundException();
          }
@@ -434,7 +434,6 @@
   * {@inheritDoc}
   */
  @Override
  @SuppressWarnings("unchecked")
  public void finalizeEntryCache() {
    cacheWriteLock.lock();
@@ -590,17 +589,18 @@
   */
  @Override
  public DN getEntryDN(Backend backend, long entryID) {
    DN entryDN = null;
    cacheReadLock.lock();
    try {
      // Get the map for the provided backend.  If it isn't present, then
      // return null.
      Map map = entryCacheIndex.backendMap.get(backend.getBackendID());
      if ( !(map == null) ) {
      Map<Long, String> map = entryCacheIndex.backendMap.get(backend
          .getBackendID());
      if (map != null)
      {
        // Get the entry DN from the map by its ID.  If it isn't present,
        // then return null.
        entryDN = DN.decode((String) map.get(entryID));
        entryDN = DN.decode(map.get(entryID));
      }
    } catch (Exception e) {
      // Ignore.
@@ -706,7 +706,6 @@
   * {@inheritDoc}
   */
  @Override
  @SuppressWarnings("unchecked")
  public void clear() {
    cacheWriteLock.lock();
@@ -732,8 +731,8 @@
          classCatalog = new StoredClassCatalog(entryCacheClassDB);
          //This line causes an unchecked call error if the SuppressWarnings
          //annotation is removed at the beginning of this method.
          entryCacheDataBinding = new SerialBinding(classCatalog,
            FileSystemEntryCacheIndex.class);
          entryCacheDataBinding = new SerialBinding<FileSystemEntryCacheIndex>(
              classCatalog, FileSystemEntryCacheIndex.class);
        }
      } catch (Exception e) {
        if (debugEnabled()) {
@@ -1142,7 +1141,7 @@
          );
      // Iterate through native JE properties.
      try {
        Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS;
        Map<String, ConfigParam> paramsMap = EnvironmentParams.SUPPORTED_PARAMS;
        // If this entry cache is disabled then there is no open JE
        // environment to check against, skip mutable check if so.
        if (configuration.isEnabled()) {
@@ -1156,7 +1155,7 @@
            if (st.countTokens() == 2) {
              String jePropertyName = st.nextToken();
              String jePropertyValue = st.nextToken();
              ConfigParam param = (ConfigParam) paramsMap.get(jePropertyName);
              ConfigParam param = paramsMap.get(jePropertyName);
              if (!param.isMutable()) {
                String oldValue = oldEnvConfig.getConfigParam(param.getName());
                String newValue = jePropertyValue;
@@ -1262,7 +1261,7 @@
      encodeConfig     = new EntryEncodeConfig(true,
        newCompactEncoding, newCompactEncoding);
      setLockTimeout(newLockTimeout);
      lockTimeout = newLockTimeout;
      setIncludeFilters(newIncludeFilters);
      setExcludeFilters(newExcludeFilters);
@@ -1368,7 +1367,7 @@
                               ByteStringBuilder entryBytes) {
    try {
      // Obtain a lock on the cache.  If this fails, then don't do anything.
      if (!cacheWriteLock.tryLock(getLockTimeout(), TimeUnit.MILLISECONDS)) {
      if (!cacheWriteLock.tryLock(lockTimeout, TimeUnit.MILLISECONDS)) {
        return false;
      }
      // See if the current fs space usage is within acceptable constraints. If
@@ -1488,15 +1487,9 @@
  }
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
   * @return String verbose string representation of the current cache
   *                maps in the following format: dn:id:backend
   *                one cache entry map representation per line
   *                or <CODE>null</CODE> if all maps are empty.
   * {@inheritDoc}
   */
  private String toVerboseString()
  public String toVerboseString()
  {
    StringBuilder sb = new StringBuilder();
@@ -1580,7 +1573,7 @@
   * @return boolean {@code true} if the eldest entry should be removed
   *                 from the map; {@code false} if it should be retained.
   */
  protected boolean removeEldestEntry(Map.Entry eldest) {
  protected boolean removeEldestEntry(Map.Entry<String, Long> eldest) {
    // Check if we hit the limit on max entries and if so remove
    // the eldest entry otherwise do nothing.
    if (entryCacheIndex.dnMap.size() > maxEntries.longValue()) {
@@ -1588,8 +1581,8 @@
      cacheWriteLock.lock();
      try {
        // Remove the the eldest entry from supporting maps.
        String entryStringDN = (String) eldest.getKey();
        long entryID = ((Long) eldest.getValue()).longValue();
        String entryStringDN = eldest.getKey();
        long entryID = eldest.getValue();
        cacheEntryKey.setData(entryStringDN.getBytes("UTF-8"));
        Set<String> backendSet = entryCacheIndex.backendMap.keySet();
        Iterator<String> backendIterator = backendSet.iterator();
@@ -1630,9 +1623,6 @@
  private class CacheIndexNotFoundException extends OpenDsException {
    static final long serialVersionUID = 6444756053577853869L;
    public CacheIndexNotFoundException() {}
    public CacheIndexNotFoundException(Message message) {
      super(message);
    }
  }
  /**
@@ -1643,9 +1633,6 @@
  private class CacheIndexImpairedException extends OpenDsException {
    static final long serialVersionUID = -369455697709478407L;
    public CacheIndexImpairedException() {}
    public CacheIndexImpairedException(Message message) {
      super(message);
    }
  }
}
opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -55,11 +55,9 @@
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockManager;
import org.opends.server.types.SearchFilter;
import org.opends.server.util.ServerConstants;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.ExtensionMessages.*;
@@ -116,7 +114,6 @@
    setExcludeFilters(new HashSet<SearchFilter>());
    setIncludeFilters(new HashSet<SearchFilter>());
    setLockTimeout(LockManager.DEFAULT_TIMEOUT);
    referenceQueue = new ReferenceQueue<CacheEntry>();
  }
@@ -562,13 +559,11 @@
  {
    // Local variables to read configuration.
    DN                    newConfigEntryDN;
    long                  newLockTimeout;
    HashSet<SearchFilter> newIncludeFilters = null;
    HashSet<SearchFilter> newExcludeFilters = null;
    // Read configuration.
    newConfigEntryDN = configuration.dn();
    newLockTimeout   = configuration.getLockTimeout();
    // Get include and exclude filters.
    switch (errorHandler.getConfigPhase())
@@ -593,7 +588,6 @@
    if (applyChanges && errorHandler.getIsAcceptable())
    {
      setLockTimeout(newLockTimeout);
      setIncludeFilters(newIncludeFilters);
      setExcludeFilters(newExcludeFilters);
@@ -710,15 +704,9 @@
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
   * @return String verbose string representation of the current cache
   *                maps in the following format: dn:id:backend
   *                one cache entry map representation per line
   *                or <CODE>null</CODE> if all maps are empty.
   * {@inheritDoc}
   */
  private String toVerboseString()
  public String toVerboseString()
  {
    StringBuilder sb = new StringBuilder();
opends/src/server/org/opends/server/types/LockManager.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.opends.server.types;
@@ -182,7 +183,7 @@
   * @return  The read lock that was acquired, or {@code null} if it
   *          was not possible to obtain a read lock for some reason.
   */
  public static Lock tryLockRead(DN entryDN)
  private static Lock tryLockRead(DN entryDN)
  {
    ReentrantReadWriteLock entryLock =
        new ReentrantReadWriteLock(fair);
@@ -297,7 +298,7 @@
   *          it was not possible to obtain a read lock for some
   *          reason.
   */
  public static Lock lockRead(DN entryDN, long timeout)
  private static Lock lockRead(DN entryDN, long timeout)
  {
    // First, try to get the lock without blocking.
    Lock readLock = tryLockRead(entryDN);
@@ -396,7 +397,7 @@
   *          if it was not possible to obtain a write lock for some
   *          reason.
   */
  public static Lock tryLockWrite(DN entryDN)
  private static Lock tryLockWrite(DN entryDN)
  {
    ReentrantReadWriteLock entryLock =
        new ReentrantReadWriteLock(fair);
@@ -508,7 +509,7 @@
   *          if it was not possible to obtain a read lock for some
   *          reason.
   */
  public static Lock lockWrite(DN entryDN, long timeout)
  private static Lock lockWrite(DN entryDN, long timeout)
  {
    // First, try to get the lock without blocking.
    Lock writeLock = tryLockWrite(entryDN);
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CommonEntryCacheTestCase.java
@@ -23,14 +23,13 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.opends.server.extensions;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
@@ -38,7 +37,6 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.LockType;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.util.ServerConstants;
@@ -48,8 +46,9 @@
/**
 * A common set of test cases for all entry cache implementations.
 * @param <C> The type of entry cache configuration.
 */
public abstract class CommonEntryCacheTestCase
public abstract class CommonEntryCacheTestCase<C extends EntryCacheCfg>
       extends ExtensionsTestCase
{
  /**
@@ -87,37 +86,14 @@
  /**
   * Cache implementation instance.
   */
  protected EntryCache cache;
  protected EntryCache<C> cache;
  /**
   * Entry cache configuration instance.
   */
  protected EntryCacheCfg configuration;
  /**
   * Reflection of the toVerboseString implementation method.
   */
  protected String toVerboseString()
            throws Exception
  {
    final Method[] cacheMethods =
        cache.getClass().getDeclaredMethods();
    for (int i = 0; i < cacheMethods.length; ++i) {
      if (cacheMethods[i].getName().equals("toVerboseString")) {
        cacheMethods[i].setAccessible(true);
        Object verboseString =
          cacheMethods[i].invoke(cache, (Object[]) null);
        return (String) verboseString;
      }
    }
    return null;
  }
  protected C configuration;
@@ -129,9 +105,9 @@
  public void testContainsEntry()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -139,14 +115,14 @@
    assertFalse(cache.containsEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.putEntry(testEntriesList.get(0), b, 1);
    assertTrue(cache.containsEntry(testEntriesList.get(0).getDN()),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -163,9 +139,9 @@
  public void testGetEntry1()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -173,14 +149,14 @@
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.putEntry(testEntriesList.get(0), b, 1);
    assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -194,30 +170,27 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testGetEntry2()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    assertNull(cache.getEntry(testEntriesList.get(0).getDN(), LockType.NONE,
      new ArrayList<Lock>()),
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.putEntry(testEntriesList.get(0), b, 1);
    assertNotNull(cache.getEntry(testEntriesList.get(0).getDN(), LockType.NONE,
      new ArrayList<Lock>()),
    assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -231,28 +204,27 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testGetEntry3()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    assertNull(cache.getEntry(b, -1, LockType.NONE, new ArrayList<Lock>()),
    assertNull(cache.getEntry(b, -1),
      "Not expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.putEntry(testEntriesList.get(0), b, 1);
    assertNotNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNotNull(cache.getEntry(b, 1),
      "Expected to find entry id " + Integer.toString(1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -268,9 +240,9 @@
  public void testGetEntryID()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -278,14 +250,14 @@
    assertEquals(cache.getEntryID(testEntriesList.get(0).getDN()), -1,
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.putEntry(testEntriesList.get(0), b, 1);
    assertEquals(cache.getEntryID(testEntriesList.get(0).getDN()), 1,
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -298,13 +270,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testPutEntry()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -314,12 +285,12 @@
    assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNotNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNotNull(cache.getEntry(b, 1),
      "Expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -332,13 +303,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testPutEntryIfAbsent()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -346,22 +316,22 @@
    assertTrue(cache.putEntryIfAbsent(testEntriesList.get(0), b, 1),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertFalse(cache.putEntryIfAbsent(testEntriesList.get(0), b, 1),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNotNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNotNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNotNull(cache.getEntry(b, 1),
      "Expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -374,13 +344,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testRemoveEntry()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -392,12 +361,12 @@
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNull(cache.getEntry(b, 1),
      "Not expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -410,13 +379,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testClear()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -428,12 +396,12 @@
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNull(cache.getEntry(b, 1),
      "Not expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -446,13 +414,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testClearBackend()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -463,20 +430,20 @@
    cache.putEntry(testEntriesList.get(1), c, 1);
    cache.clearBackend(b);
    assertNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNull(cache.getEntry(b, 1),
      "Not expected to find entry id " + Integer.toString(1) + " on backend " +
      b.getBackendID() + " in the cache.  Cache contents:" +
      ServerConstants.EOL + toVerboseString());
      ServerConstants.EOL + cache.toVerboseString());
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNotNull(cache.getEntry(c, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNotNull(cache.getEntry(c, 1),
      "Expected to find entry id " + Integer.toString(1) + " on backend " +
      c.getBackendID() + " in the cache.  Cache contents:" +
      ServerConstants.EOL + toVerboseString());
      ServerConstants.EOL + cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -489,13 +456,12 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testClearSubtree()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -512,17 +478,17 @@
    assertNull(cache.getEntry(testEntriesList.get(0).getDN()),
      "Not expected to find " + testEntriesList.get(0).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNull(cache.getEntry(b, 1, LockType.NONE, new ArrayList<Lock>()),
    assertNull(cache.getEntry(b, 1),
      "Not expected to find entry id " + Integer.toString(-1) +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    assertNotNull(cache.getEntry(testEntry.getDN()),
      "Expected to find " + testEntry.getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    // Clear the cache so that other tests can start from scratch.
    cache.clear();
@@ -538,9 +504,9 @@
  public void testHandleLowMemory()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    cache.handleLowMemory();
@@ -556,7 +522,6 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @SuppressWarnings("unchecked")
  public void testCacheConcurrency()
         throws Exception
  {
@@ -568,7 +533,7 @@
        cache.getEntry(testEntriesList.get(i).getDN());
        cache.removeEntry(testEntriesList.get(i).getDN());
        cache.putEntryIfAbsent(testEntriesList.get(i), b, i);
        cache.getEntry(b, i, LockType.NONE, new ArrayList<Lock>());
        cache.getEntry(b, i);
      }
    }
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS
 *      Portions copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -59,12 +59,12 @@
 */
@Test(groups = "entrycache", sequential=true)
public class DefaultEntryCacheTestCase
       extends CommonEntryCacheTestCase
       extends CommonEntryCacheTestCase<EntryCacheCfg>
{
  // Entry cache implementations participating in this test.
  private EntryCache softRefCache = null;
  private EntryCache fifoCache = null;
  private EntryCache fsCache = null;
  private SoftReferenceEntryCache softRefCache = null;
  private FIFOEntryCache fifoCache = null;
  private FileSystemEntryCache fsCache = null;
  // ... and their configuration entries.
  Entry cacheSoftReferenceConfigEntry = null;
@@ -113,7 +113,7 @@
      "ds-cfg-include-filter: uid=test1*",
      "ds-cfg-exclude-filter: uid=test0*");
    softRefCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheSoftReferenceConfigEntry));
      SoftReferenceEntryCacheCfgDefn.getInstance(), cacheSoftReferenceConfigEntry));
    cacheOrderMap.put(1, softRefCache);
    fifoCache = new FIFOEntryCache();
@@ -130,7 +130,7 @@
      "ds-cfg-include-filter: uid=test2*",
      "ds-cfg-exclude-filter: uid=test0*");
    fifoCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheFIFOConfigEntry));
      FIFOEntryCacheCfgDefn.getInstance(), cacheFIFOConfigEntry));
    cacheOrderMap.put(2, fifoCache);
    File cacheDirectory = TestCaseUtils.createTemporaryDirectory("opendj-test");
@@ -151,7 +151,7 @@
      "ds-cfg-cache-directory: " + cacheDirectory.getAbsolutePath());
    fsCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheFSConfigEntry));
      FileSystemEntryCacheCfgDefn.getInstance(), cacheFSConfigEntry));
    cacheOrderMap.put(3, fsCache);
    // Plug all cache implementations into default entry cache.
@@ -265,7 +265,7 @@
    }
    // Finilize all entry cache implementations.
    for (EntryCache entryCache : cacheOrderMap.values()) {
    for (EntryCache<?> entryCache : cacheOrderMap.values()) {
      entryCache.finalizeEntryCache();
    }
@@ -445,9 +445,9 @@
  public void testCacheLevels()
         throws Exception
  {
    assertNull(toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
      cache.toVerboseString());
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -466,19 +466,19 @@
        "Expected to find " +
        testSoftRefEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
      assertNotNull(super.cache.getEntry(
        testFIFOEntriesList.get(0).getDN()),
        "Expected to find " +
        testFIFOEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
      assertNotNull(super.cache.getEntry(
        testFSEntriesList.get(0).getDN()),
        "Expected to find " +
        testFSEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
    }
    // Ensure all test entries landed on their levels.
@@ -488,19 +488,19 @@
        "Expected to find " +
        testSoftRefEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
      assertNotNull(fifoCache.getEntry(
        testFIFOEntriesList.get(0).getDN()),
        "Expected to find " +
        testFIFOEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
      assertNotNull(fsCache.getEntry(
        testFSEntriesList.get(0).getDN()),
        "Expected to find " +
        testFSEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
        ServerConstants.EOL + cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
@@ -513,9 +513,9 @@
  public void cacheConcurrencySetup()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.opends.server.extensions;
@@ -33,6 +34,7 @@
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.testng.annotations.BeforeClass;
import org.opends.server.admin.std.meta.*;
import org.opends.server.admin.std.server.FIFOEntryCacheCfg;
import org.opends.server.api.Backend;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.DN;
@@ -51,7 +53,7 @@
 */
@Test(groups = "entrycache", sequential=true)
public class FIFOEntryCacheTestCase
       extends CommonEntryCacheTestCase
       extends CommonEntryCacheTestCase<FIFOEntryCacheCfg>
{
  /**
   * Initialize the entry cache test.
@@ -59,7 +61,6 @@
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  @SuppressWarnings("unchecked")
  public void entryCacheTestInit()
         throws Exception
  {
@@ -78,7 +79,7 @@
      "ds-cfg-enabled: true",
      "ds-cfg-max-entries: " + Integer.toString(super.MAXENTRIES));
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheConfigEntry);
      FIFOEntryCacheCfgDefn.getInstance(), cacheConfigEntry);
    // Force GC to make sure we have enough memory for
    // the cache capping constraints to work properly.
@@ -289,9 +290,9 @@
  public void testHandleLowMemory()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -308,7 +309,7 @@
        super.testEntriesList.get(i).getDN()), "Not expected to find " +
        super.testEntriesList.get(i).getDN().toString() + " in the " +
        "cache.  Cache contents:" + ServerConstants.EOL +
        super.toVerboseString());
        cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
@@ -321,9 +322,9 @@
  public void cacheConcurrencySetup()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
@@ -361,9 +362,9 @@
  public void testCacheRotation()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -377,7 +378,7 @@
        super.testEntriesList.get(i).getDN()), "Not expected to find " +
        super.testEntriesList.get(i).getDN().toString() + " in the " +
        "cache.  Cache contents:" + ServerConstants.EOL +
        super.toVerboseString());
        cache.toVerboseString());
    }
    // Make sure remaining NUMTESTENTRIES are still in the cache.
@@ -389,7 +390,7 @@
        super.testEntriesList.get(i).getDN()), "Expected to find " +
        super.testEntriesList.get(i).getDN().toString() + " in the " +
        "cache.  Cache contents:" + ServerConstants.EOL +
        super.toVerboseString());
        cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2007-2008 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS
 *      Portions copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -56,7 +56,7 @@
 */
@Test(groups = "entrycache", sequential=true)
public class FileSystemEntryCacheTestCase
       extends CommonEntryCacheTestCase
       extends CommonEntryCacheTestCase<FileSystemEntryCacheCfg>
{
  /**
   * Configuration entry for this cache.
@@ -71,7 +71,6 @@
  /**
   * Utility method to restore default cache configuration.
   */
  @SuppressWarnings("unchecked")
  private void restoreCacheDefaults()
          throws Exception
  {
@@ -80,16 +79,16 @@
    // Configure this cache back to defaults.
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheConfigEntry);
      FileSystemEntryCacheCfgDefn.getInstance(), cacheConfigEntry);
    // Initialize the cache.
    super.cache = new FileSystemEntryCache();
    super.cache.initializeEntryCache(configuration);
    // Make sure the cache is empty.
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
@@ -97,7 +96,6 @@
  /**
   * Utility method to configure the cache with LRU access order.
   */
  @SuppressWarnings("unchecked")
  private void setupLRUCache()
          throws Exception
  {
@@ -110,16 +108,16 @@
      Attributes.create("ds-cfg-cache-type", "LRU");
    newCacheConfigEntry.addAttribute(cacheConfigTypeAttr, null);
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), newCacheConfigEntry);
        FileSystemEntryCacheCfgDefn.getInstance(), newCacheConfigEntry);
    // Initialize the cache.
    super.cache = new FileSystemEntryCache();
    super.cache.initializeEntryCache(configuration);
    // Make sure the cache is empty.
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
@@ -127,7 +125,6 @@
  /**
   * Utility method to initialize persistent cache.
   */
  @SuppressWarnings("unchecked")
  private void persistentCacheSetup()
          throws Exception
  {
@@ -154,16 +151,16 @@
      Attributes.create("ds-cfg-max-entries", Integer.toString(super.MAXENTRIES));
    newCacheConfigEntry.removeAttribute(cacheConfigMaxAttr, null);
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), newCacheConfigEntry);
        FileSystemEntryCacheCfgDefn.getInstance(), newCacheConfigEntry);
    // Initialize the cache.
    super.cache = new FileSystemEntryCache();
    super.cache.initializeEntryCache(configuration);
    // Make sure the cache is empty.
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
@@ -190,7 +187,6 @@
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass
  @SuppressWarnings("unchecked")
  public void entryCacheTestInit()
         throws Exception
  {
@@ -212,7 +208,7 @@
      "ds-cfg-max-entries: " + Integer.toString(super.MAXENTRIES),
      "ds-cfg-cache-directory: " + cacheDirectory.getAbsolutePath());
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheConfigEntry);
        FileSystemEntryCacheCfgDefn.getInstance(), cacheConfigEntry);
    // Force GC to make sure we have enough memory for
    // the cache capping constraints to work properly.
@@ -270,8 +266,7 @@
    super.cache.finalizeEntryCache();
    // Remove default FS cache JE environment.
    FileSystemEntryCacheCfg config =
      (FileSystemEntryCacheCfg) super.configuration;
    FileSystemEntryCacheCfg config = super.configuration;
    TestCaseUtils.deleteDirectory(new File(config.getCacheDirectory()));
  }
@@ -437,9 +432,9 @@
  public void cacheConcurrencySetup()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }
@@ -518,9 +513,9 @@
  public void testCacheRotationFIFO()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
    // Put some test entries in the cache.
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
@@ -534,7 +529,7 @@
        super.testEntriesList.get(i).getDN()), "Not expected to find " +
        super.testEntriesList.get(i).getDN().toString() + " in the " +
        "cache.  Cache contents:" + ServerConstants.EOL +
        super.toVerboseString());
        cache.toVerboseString());
    }
    // Make sure remaining NUMTESTENTRIES are still in the cache.
@@ -546,7 +541,7 @@
        super.testEntriesList.get(i).getDN()), "Expected to find " +
        super.testEntriesList.get(i).getDN().toString() + " in the " +
        "cache.  Cache contents:" + ServerConstants.EOL +
        super.toVerboseString());
        cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
@@ -559,7 +554,6 @@
   * Tests LRU cache rotation on specific number of entries.
   */
  @Test(groups = "slow")
  @SuppressWarnings("unchecked")
  public void testCacheRotationLRU()
         throws Exception
  {
@@ -584,7 +578,7 @@
          "Expected to find " +
          super.testEntriesList.get(i).getDN().toString() + " in the " +
          "cache.  Cache contents:" + ServerConstants.EOL +
          super.toVerboseString());
          cache.toVerboseString());
    }
    // Plus the last cache entry added.
@@ -593,7 +587,7 @@
      "Expected to find " +
      super.testEntriesList.get(super.NUMTESTENTRIES - 1).getDN().toString() +
      " in the cache.  Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
    // And remaining NUMTESTENTRIES - 1 are now rotated.
    for(int i = (super.MAXENTRIES - 1);
@@ -604,7 +598,7 @@
          "Not expected to find " +
          super.testEntriesList.get(i).getDN().toString() + " in the " +
          "cache.  Cache contents:" + ServerConstants.EOL +
          super.toVerboseString());
          cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
@@ -620,7 +614,6 @@
   * Tests cache persistence with consistent backend.
   */
  @Test(groups = "slow")
  @SuppressWarnings("unchecked")
  public void testCachePersistence()
         throws Exception
  {
@@ -653,7 +646,7 @@
          "Expected to find " +
          super.testEntriesList.get(i).getDN().toString() + " in the " +
          "cache.  Cache contents:" + ServerConstants.EOL +
          super.toVerboseString());
          cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
@@ -673,7 +666,6 @@
   * Tests cache persistence with inconsistent backend.
   */
  @Test(groups = "slow")
  @SuppressWarnings("unchecked")
  public void testCachePersistenceInconsistent()
         throws Exception
  {
@@ -719,7 +711,7 @@
          "Not expected to find " +
          super.testEntriesList.get(i).getDN().toString() + " in the " +
          "cache.  Cache contents:" + ServerConstants.EOL +
          super.toVerboseString());
          cache.toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.opends.server.extensions;
@@ -33,6 +34,7 @@
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.testng.annotations.BeforeClass;
import org.opends.server.admin.std.meta.*;
import org.opends.server.admin.std.server.SoftReferenceEntryCacheCfg;
import org.opends.server.types.Entry;
import org.opends.server.util.ServerConstants;
import org.testng.annotations.AfterClass;
@@ -48,7 +50,7 @@
 */
@Test(groups = "entrycache", sequential=true)
public class SoftReferenceEntryCacheTestCase
       extends CommonEntryCacheTestCase
       extends CommonEntryCacheTestCase<SoftReferenceEntryCacheCfg>
{
  /**
   * Initialize the entry cache test.
@@ -56,7 +58,6 @@
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  @SuppressWarnings("unchecked")
  public void entryCacheTestInit()
         throws Exception
  {
@@ -75,7 +76,7 @@
      "org.opends.server.extensions.SoftReferenceEntryCache",
      "ds-cfg-enabled: true");
    super.configuration = AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheConfigEntry);
      SoftReferenceEntryCacheCfgDefn.getInstance(), cacheConfigEntry);
    // Force GC to make sure we have enough memory for
    // the cache capping constraints to work properly.
@@ -295,9 +296,9 @@
  public void cacheConcurrencySetup()
         throws Exception
  {
    assertNull(super.toVerboseString(),
    assertNull(cache.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
      cache.toVerboseString());
  }