/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.api;
import java.util.List;
import java.util.HashSet;
import java.util.concurrent.locks.Lock;
import org.opends.server.core.DirectoryServer;
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;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.loggers.debug.DebugLogger.*;
/**
* This class defines the set of methods that must be implemented by a
* Directory Server entry cache. Note that components accessing the
* entry cache must not depend on any particular behavior. For
* example, if a call is made to putEntry to store an
* entry in the cache, there is no guarantee that immediately calling
* getEntry will be able to retrieve it. There are
* several potential reasons for this, including:
*
putEntry and getEntry
* calls.putEntry and getEntry calls.true if the entry cache currently contains
* the entry with the specified DN, or false
* if not.
*/
public abstract boolean containsEntry(DN entryDN);
/**
* 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)
*
* @param entryDN The DN of the entry to retrieve.
*
* @return The requested entry if it is present in the cache, or
* null if it is not present.
*/
public abstract Entry getEntry(DN entryDN);
/**
* 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
* 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 NONE).
*
* @return The requested entry if it is present in the cache, or
* null if it is not present.
*/
public Entry getEntry(DN entryDN,
LockType lockType,
ListNONE).
* @param lockList The list to which the obtained lock will be
* added (note that no lock will be added if the
* lock type was NONE).
*
* @return The requested entry if it is present in the cache, or
* null if it is not present.
*/
public Entry getEntry(Backend backend, long entryID,
LockType lockType,
Listnull if it is not present in the cache.
*/
protected abstract DN getEntryDN(Backend backend, long entryID);
/**
* Stores the provided entry in the cache. Note that the mechanism
* that it uses to achieve this is implementation-dependent, and it
* is acceptable for the entry to not actually be stored in any
* cache.
*
* @param entry The entry to store in the cache.
* @param backend The backend with which the entry is associated.
* @param entryID The entry ID within the provided backend that
* uniquely identifies the specified entry.
*/
public abstract void putEntry(Entry entry, Backend backend,
long entryID);
/**
* Stores the provided entry in the cache only if it does not
* conflict with an entry that already exists. Note that the
* mechanism that it uses to achieve this is
* implementation-dependent, and it is acceptable for the entry to
* not actually be stored in any cache. However, this method must
* not overwrite an existing version of the entry.
*
* @param entry The entry to store in the cache.
* @param backend The backend with which the entry is associated.
* @param entryID The entry ID within the provided backend that
* uniquely identifies the specified entry.
*
* @return false if an existing entry or some other
* problem prevented the method from completing
* successfully, or true if there was no
* conflict and the entry was either stored or the cache
* determined that this entry should never be cached for
* some reason.
*/
public abstract boolean putEntryIfAbsent(Entry entry,
Backend backend,
long entryID);
/**
* Removes the specified entry from the cache.
*
* @param entryDN The DN of the entry to remove from the cache.
*/
public abstract void removeEntry(DN entryDN);
/**
* Removes all entries from the cache. The cache should still be
* available for future use.
*/
public abstract void clear();
/**
* Removes all entries from the cache that are associated with the
* provided backend.
*
* @param backend The backend for which to flush the associated
* entries.
*/
public abstract void clearBackend(Backend backend);
/**
* Removes all entries from the cache that are below the provided
* DN.
*
* @param baseDN The base DN below which all entries should be
* flushed.
*/
public abstract void clearSubtree(DN baseDN);
/**
* Attempts to react to a scenario in which it is determined that
* the system is running low on available memory. In this case, the
* entry cache should attempt to free some memory if possible to try
* to avoid out of memory errors.
*/
public abstract void handleLowMemory();
/**
* Indicates whether the current set of exclude and include filters
* allow caching of the specified entry.
* @param entry The entry to evaluate against exclude and include
* filter sets.
* @return true if current set of filters allow caching
* the entry and false otherwise.
*/
protected boolean filtersAllowCaching(Entry entry)
{
// If there is a set of exclude filters, then make sure that the
// provided entry doesn't match any of them.
if (! excludeFilters.isEmpty())
{
for (SearchFilter f : excludeFilters)
{
try
{
if (f.matchesEntry(entry))
{
return false;
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
// This shouldn't happen, but if it does then we can't be
// sure whether the entry should be excluded, so we will
// by default.
return false;
}
}
}
// If there is a set of include filters, then make sure that the
// provided entry matches at least one of them.
if (! includeFilters.isEmpty())
{
boolean matchFound = false;
for (SearchFilter f : includeFilters)
{
try
{
if (f.matchesEntry(entry))
{
matchFound = true;
break;
}
}
catch (Exception e)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
// This shouldn't happen, but if it does, then
// just ignore it.
}
}
if (! matchFound)
{
return false;
}
}
return true;
}
/**
* {@inheritDoc}
*/
public void performBackendInitializationProcessing(Backend backend)
{
// Do nothing.
}
/**
* {@inheritDoc}
*/
public void performBackendFinalizationProcessing(Backend backend)
{
// Do not clear any backends if the server is shutting down.
if ( !(DirectoryServer.getInstance().isShuttingDown()) ) {
clearBackend(backend);
}
}
}