| | |
| | | * its own entry container. The entry container is the object that implements |
| | | * the guts of the backend API methods for LDAP operations. |
| | | */ |
| | | public class EntryContainer |
| | | public final class EntryContainer |
| | | implements SuffixContainer, ConfigurationChangeListener<PluggableBackendCfg> |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | |
| | | */ |
| | | EntryID getHighestEntryID(ReadableTransaction txn) throws StorageRuntimeException |
| | | { |
| | | Cursor<ByteString, ByteString> cursor = txn.openCursor(id2entry.getName()); |
| | | try |
| | | try (Cursor<ByteString, ByteString> cursor = txn.openCursor(id2entry.getName())) |
| | | { |
| | | // Position a cursor on the last data item, and the key should give the highest ID. |
| | | if (cursor.positionToLastKey()) |
| | |
| | | } |
| | | return new EntryID(0); |
| | | } |
| | | finally |
| | | { |
| | | cursor.close(); |
| | | } |
| | | } |
| | | |
| | | boolean hasSubordinates(final DN dn) |
| | |
| | | int lookthroughCount = 0; |
| | | int lookthroughLimit = searchOperation.getClientConnection().getLookthroughLimit(); |
| | | |
| | | try |
| | | { |
| | | final Cursor<ByteString, ByteString> cursor = txn.openCursor(dn2id.getName()); |
| | | try |
| | | try (final Cursor<ByteString, ByteString> cursor = txn.openCursor(dn2id.getName())) |
| | | { |
| | | // Initialize the cursor very close to the starting value. |
| | | boolean success = cursor.positionToKeyOrNext(begin); |
| | |
| | | success = cursor.next(); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | cursor.close(); |
| | | } |
| | | } |
| | | catch (StorageRuntimeException e) |
| | | { |
| | | logger.traceException(e); |
| | |
| | | * |
| | | * @return <CODE>true</CODE> if the specified entry exists, |
| | | * or <CODE>false</CODE> if it does not. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while trying to make the |
| | | * determination. |
| | | */ |
| | | private boolean entryExists(ReadableTransaction txn, final DN entryDN) throws DirectoryException |
| | | private boolean entryExists(ReadableTransaction txn, final DN entryDN) |
| | | { |
| | | // Try the entry cache first. |
| | | EntryCache<?> entryCache = DirectoryServer.getEntryCache(); |
| | | if (entryCache != null && entryCache.containsEntry(entryDN)) |
| | | { |
| | | return true; |
| | | } |
| | | return dn2id.get(txn, entryDN) != null; |
| | | return (entryCache != null && entryCache.containsEntry(entryDN)) |
| | | || dn2id.get(txn, entryDN) != null; |
| | | } |
| | | |
| | | |
| | |
| | | @Override |
| | | public Entry run(ReadableTransaction txn) throws Exception |
| | | { |
| | | return getEntry0(txn, entryDN); |
| | | Entry entry = getEntry0(txn, entryDN); |
| | | if (entry == null) |
| | | { |
| | | // The entryDN does not exist. Check for referral entries above the target entry. |
| | | dn2uri.targetEntryReferrals(txn, entryDN, null); |
| | | } |
| | | return entry; |
| | | } |
| | | }); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | try |
| | | { |
| | | final EntryID entryID = dn2id.get(txn, entryDN); |
| | | if (entryID == null) |
| | | { |
| | | // The entryDN does not exist. Check for referral entries above the target entry. |
| | | dn2uri.targetEntryReferrals(txn, entryDN, null); |
| | | return null; |
| | | } |
| | | |
| | |
| | | } |
| | | return entry; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // it is not very clean to specify twice the same exception but it saves me some code for now |
| | | throwAllowedExceptionTypes(e, DirectoryException.class, DirectoryException.class); |
| | | return null; // unreachable |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * The simplest case of replacing an entry in which the entry DN has |
| | |
| | | /** |
| | | * Get a count of the number of entries stored in this entry container including the baseDN |
| | | * |
| | | * @param txn |
| | | * a non null transaction |
| | | * @return The number of entries stored in this entry container including the baseDN. |
| | | * @throws StorageRuntimeException |
| | | * If an error occurs in the storage. |
| | |
| | | /** |
| | | * Finds an existing entry whose DN is the closest ancestor of a given baseDN. |
| | | * |
| | | * @param baseDN the DN for which we are searching a matched DN. |
| | | * @param targetDN the DN for which we are searching a matched DN. |
| | | * @return the DN of the closest ancestor of the baseDN. |
| | | * @throws DirectoryException If an error prevented the check of an |
| | | * existing entry from being performed. |
| | | */ |
| | | private DN getMatchedDN(ReadableTransaction txn, DN baseDN) throws DirectoryException |
| | | private DN getMatchedDN(ReadableTransaction txn, DN targetDN) throws DirectoryException |
| | | { |
| | | DN parentDN = baseDN.getParentDNInSuffix(); |
| | | while (parentDN != null && parentDN.isDescendantOf(getBaseDN())) |
| | | DN parentDN = targetDN.getParentDNInSuffix(); |
| | | while (parentDN != null && parentDN.isDescendantOf(baseDN)) |
| | | { |
| | | if (entryExists(txn, parentDN)) |
| | | { |
| | |
| | | |
| | | /** |
| | | * Fetch the base Entry of the EntryContainer. |
| | | * @param baseDN the DN for the base entry |
| | | * @param searchBaseDN the DN for the base entry |
| | | * @param searchScope the scope under which this is fetched. |
| | | * Scope is used for referral processing. |
| | | * @return the Entry matching the baseDN. |
| | | * @throws DirectoryException if the baseDN doesn't exist. |
| | | */ |
| | | private Entry fetchBaseEntry(ReadableTransaction txn, DN baseDN, SearchScope searchScope) |
| | | private Entry fetchBaseEntry(ReadableTransaction txn, DN searchBaseDN, SearchScope searchScope) |
| | | throws DirectoryException |
| | | { |
| | | Entry baseEntry = null; |
| | | try |
| | | { |
| | | baseEntry = getEntry0(txn, baseDN); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | logger.traceException(e); |
| | | } |
| | | |
| | | // The base entry must exist for a successful result. |
| | | Entry baseEntry = getEntry0(txn, searchBaseDN); |
| | | if (baseEntry == null) |
| | | { |
| | | // Check for referral entries above the base entry. |
| | | dn2uri.targetEntryReferrals(txn, baseDN, searchScope); |
| | | |
| | | dn2uri.targetEntryReferrals(txn, searchBaseDN, searchScope); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, |
| | | ERR_SEARCH_NO_SUCH_OBJECT.get(baseDN), getMatchedDN(txn, baseDN), null); |
| | | ERR_SEARCH_NO_SUCH_OBJECT.get(searchBaseDN), getMatchedDN(txn, searchBaseDN), null); |
| | | } |
| | | |
| | | return baseEntry; |
| | | } |
| | | |
| | |
| | | return sortByGreaterThanOrEqualAssertion(searchOperation, vlvRequest, sortOrder, sortMap); |
| | | } |
| | | |
| | | private static final long[] toArray(Collection<EntryID> entryIDs) |
| | | private static long[] toArray(Collection<EntryID> entryIDs) |
| | | { |
| | | final long[] array = new long[entryIDs.size()]; |
| | | int i = 0; |
| | |
| | | return array; |
| | | } |
| | | |
| | | private static final EntryIDSet sortByGreaterThanOrEqualAssertion(SearchOperation searchOperation, |
| | | private static EntryIDSet sortByGreaterThanOrEqualAssertion(SearchOperation searchOperation, |
| | | VLVRequestControl vlvRequest, SortOrder sortOrder, final TreeMap<ByteString, EntryID> sortMap) |
| | | throws DirectoryException |
| | | { |
| | |
| | | return result; |
| | | } |
| | | |
| | | private static final EntryIDSet sortByOffset(SearchOperation searchOperation, VLVRequestControl vlvRequest, |
| | | private static EntryIDSet sortByOffset(SearchOperation searchOperation, VLVRequestControl vlvRequest, |
| | | TreeMap<ByteString, EntryID> sortMap) throws DirectoryException |
| | | { |
| | | int targetOffset = vlvRequest.getOffset(); |