DefaultIndex.java revision 36e213444660f0a74ed415adeab490a5f3d50a6f
/*
* 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 legal-notices/CDDLv1_0.txt
* 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 legal-notices/CDDLv1_0.txt.
* 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
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2012-2015 ForgeRock AS
*/
/**
* Represents an index implemented by a tree in which each key maps to a set of entry IDs. The key
* is a byte array, and is constructed from some normalized form of an attribute value (or fragment
* of a value) appearing in the entry.
*/
{
/** The limit on the number of entry IDs that may be indexed by one key. */
private final EntryContainer entryContainer;
private int indexEntryLimit;
private EntryIDSetCodec codec;
/**
* A flag to indicate if this index should be trusted to be consistent with the entries tree.
* If not trusted, we assume that existing entryIDSets for a key is still accurate. However, keys
* that do not exist are undefined instead of an empty entryIDSet. The following rules will be
* observed when the index is not trusted: - no entryIDs will be added to a non-existing key. -
* undefined entryIdSet will be returned whenever a key is not found.
*/
private volatile boolean trusted;
/**
* Create a new index object.
*
* @param name
* The name of the index tree within the entryContainer.
* @param state
* The state tree to persist index state info.
* @param indexEntryLimit
* The configured limit on the number of entry IDs that may be indexed by one key.
* @param entryContainer
* The entryContainer holding this index.
* @throws StorageRuntimeException
* If an error occurs in the storage.
*/
throws StorageRuntimeException
{
super(name);
this.indexEntryLimit = indexEntryLimit;
this.entryContainer = entryContainer;
}
{
{
// If there are no entries in the entry container then there
// is no reason why this index can't be upgraded to trusted.
setTrusted(txn, true);
}
}
{
{
{
}
}
}
{
{
{
}
});
}
{
}
{
}
public final void update(final WriteableTransaction txn, final ByteString key, final EntryIDSet deletedIDs,
{
/*
* Check the special condition where both deletedIDs and addedIDs are null. This is used when
* deleting entries must be completely removed.
*/
{
{
}
return;
}
// Handle cases where nothing is changed early to avoid DB access.
{
return;
}
/*
* Avoid taking a write lock on a record which has hit all IDs because it is likely to be a
* point of contention.
*/
{
return;
}
// The record is going to be changed in some way.
{
{
{
/*
* If there are no more IDs then return null indicating that the record should be removed.
* If index is not trusted then this will cause all subsequent reads for this key to
* return undefined set.
*/
}
else if (trusted)
{
if (deletedIDs != null)
{
}
if (isNotEmpty(addedIDs))
{
}
}
return null; // no change.
}
});
}
{
}
{
}
private EntryIDSet computeEntryIDSet(ByteString key, ByteString value, EntryIDSet deletedIDs, EntryIDSet addedIDs)
{
{
{
{
if (logger.isTraceEnabled())
{
logger.trace("Index entry exceeded in index %s. " + "Limit: %d. ID list size: %d.\nKey:%s", getName(),
}
return entryIDSet;
}
}
}
if (deletedIDs != null)
{
}
return entryIDSet;
}
{
if (logger.isTraceEnabled())
{
logger.trace("The expected key does not exist in the index %s.\nKey:%s", getName(), key.toHexPlusAsciiString(4));
}
setTrusted(txn, false);
}
{
try
{
{
}
}
catch (StorageRuntimeException e)
{
logger.traceException(e);
return newUndefinedSet();
}
}
public final boolean setIndexEntryLimit(int indexEntryLimit)
{
this.indexEntryLimit = indexEntryLimit;
return rebuildRequired;
}
public final int getIndexEntryLimit()
{
return indexEntryLimit;
}
public final synchronized void setTrusted(WriteableTransaction txn, boolean trusted) throws StorageRuntimeException
{
if (trusted)
{
}
else
{
}
}
public final boolean isTrusted()
{
return trusted;
}
}