| | |
| | | * |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS |
| | | * Portions Copyright 2011-2016 ForgeRock AS |
| | | * Portions copyright 2013 Manuel Gaupp |
| | | */ |
| | | package org.opends.server.backends.pluggable; |
| | |
| | | // Handle base-object search first. |
| | | if (searchScope == SearchScope.BASE_OBJECT) |
| | | { |
| | | final Entry baseEntry = fetchBaseEntry(txn, aBaseDN, searchScope); |
| | | if (!isManageDsaITOperation(searchOperation)) |
| | | { |
| | | dn2uri.checkTargetForReferral(baseEntry, searchOperation.getScope()); |
| | | } |
| | | |
| | | if (searchOperation.getFilter().matchesEntry(baseEntry)) |
| | | { |
| | | searchOperation.returnEntry(baseEntry, null); |
| | | } |
| | | |
| | | if (pageRequest != null) |
| | | { |
| | | // Indicate no more pages. |
| | | Control control = new PagedResultsControl(pageRequest.isCritical(), 0, null); |
| | | searchOperation.getResponseControls().add(control); |
| | | } |
| | | |
| | | searchBaseObject(txn, searchOperation, pageRequest); |
| | | return null; |
| | | } |
| | | |
| | |
| | | debugBuffer = new StringBuilder(); |
| | | } |
| | | |
| | | EntryIDSet entryIDSet = null; |
| | | EntryIDSet candidateEntryIDs = null; |
| | | boolean candidatesAreInScope = false; |
| | | if (sortRequest != null) |
| | | { |
| | |
| | | { |
| | | try |
| | | { |
| | | entryIDSet = vlvIndex.evaluate(txn, searchOperation, sortRequest, vlvRequest, debugBuffer); |
| | | if (entryIDSet != null) |
| | | candidateEntryIDs = vlvIndex.evaluate(txn, searchOperation, sortRequest, vlvRequest, debugBuffer); |
| | | if (candidateEntryIDs != null) |
| | | { |
| | | searchOperation.addResponseControl(newServerSideSortControl(SUCCESS)); |
| | | candidatesAreInScope = true; |
| | |
| | | // Combining server-side sort with paged result controls |
| | | // requires us to use an entryIDSet where the entryIDs are ordered |
| | | // so further paging can restart where it previously stopped |
| | | long[] entryIDReorderedSet; |
| | | if (entryIDSet == null) |
| | | long[] reorderedCandidateEntryIDs; |
| | | if (candidateEntryIDs == null) |
| | | { |
| | | if (processSearchWithVirtualAttributeRule(searchOperation, true)) |
| | | { |
| | |
| | | EntryContainer.this, txn, searchOperation, debugBuffer, rootContainer.getMonitorProvider()); |
| | | |
| | | // Evaluate the filter against the attribute indexes. |
| | | entryIDSet = indexFilter.evaluate(); |
| | | |
| | | if (!isBelowFilterThreshold(entryIDSet)) |
| | | candidateEntryIDs = indexFilter.evaluate(); |
| | | if (!isBelowFilterThreshold(candidateEntryIDs)) |
| | | { |
| | | final int lookThroughLimit = searchOperation.getClientConnection().getLookthroughLimit(); |
| | | final int indexLimit = |
| | | config.getIndexEntryLimit() == 0 ? CURSOR_ENTRY_LIMIT : config.getIndexEntryLimit(); |
| | | final int idSetLimit = lookThroughLimit > 0 ? Math.min(indexLimit, lookThroughLimit) : indexLimit; |
| | | |
| | | final int idSetLimit = getEntryIDSetLimit(searchOperation); |
| | | final EntryIDSet scopeSet = getIDSetFromScope(txn, aBaseDN, searchScope, idSetLimit); |
| | | entryIDSet.retainAll(scopeSet); |
| | | candidateEntryIDs.retainAll(scopeSet); |
| | | if (debugBuffer != null) |
| | | { |
| | | debugBuffer.append(" scope=").append(searchScope); |
| | |
| | | try |
| | | { |
| | | SortOrder sortOrder = sortRequest.getSortOrder(); |
| | | entryIDReorderedSet = sort(txn, entryIDSet, searchOperation, sortOrder, vlvRequest); |
| | | reorderedCandidateEntryIDs = sort(txn, candidateEntryIDs, searchOperation, sortOrder, vlvRequest); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | entryIDReorderedSet = entryIDSet.toLongArray(); |
| | | reorderedCandidateEntryIDs = candidateEntryIDs.toLongArray(); |
| | | serverSideSortControlError(searchOperation, sortRequest, de); |
| | | } |
| | | try |
| | |
| | | } |
| | | else |
| | | { |
| | | entryIDReorderedSet = entryIDSet.toLongArray(); |
| | | reorderedCandidateEntryIDs = candidateEntryIDs.toLongArray(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | entryIDReorderedSet = entryIDSet.toLongArray(); |
| | | reorderedCandidateEntryIDs = candidateEntryIDs.toLongArray(); |
| | | } |
| | | |
| | | // If requested, construct and return a fictitious entry containing |
| | |
| | | if (debugBuffer != null) |
| | | { |
| | | debugBuffer.append(" final="); |
| | | entryIDSet.toString(debugBuffer); |
| | | candidateEntryIDs.toString(debugBuffer); |
| | | |
| | | Entry debugEntry = buildDebugSearchIndexEntry(debugBuffer); |
| | | searchOperation.returnEntry(debugEntry, null); |
| | | return null; |
| | | } |
| | | |
| | | if (entryIDReorderedSet != null) |
| | | if (reorderedCandidateEntryIDs != null) |
| | | { |
| | | rootContainer.getMonitorProvider().incrementIndexedSearchCount(); |
| | | searchIndexed(txn, entryIDReorderedSet, candidatesAreInScope, searchOperation, pageRequest); |
| | | searchIndexed(txn, reorderedCandidateEntryIDs, candidatesAreInScope, searchOperation, pageRequest); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | if (sortRequest != null) |
| | | { |
| | | // FIXME -- Add support for sorting unindexed searches using indexes |
| | | // like DSEE currently does. |
| | | // FIXME OPENDJ-2628: Add support for sorting unindexed searches using indexes like DSEE currently does |
| | | searchOperation.addResponseControl(newServerSideSortControl(UNWILLING_TO_PERFORM)); |
| | | |
| | | if (sortRequest.isCritical()) |
| | | { |
| | | throw new DirectoryException( |
| | |
| | | return null; |
| | | } |
| | | |
| | | private int getEntryIDSetLimit(final SearchOperation searchOperation) |
| | | { |
| | | final int lookThroughLimit = searchOperation.getClientConnection().getLookthroughLimit(); |
| | | final int indexLimit = config.getIndexEntryLimit() == 0 ? CURSOR_ENTRY_LIMIT : config.getIndexEntryLimit(); |
| | | return lookThroughLimit > 0 ? Math.min(indexLimit, lookThroughLimit) : indexLimit; |
| | | } |
| | | |
| | | private void searchBaseObject(ReadableTransaction txn, SearchOperation searchOperation, |
| | | PagedResultsControl pageRequest) throws DirectoryException |
| | | { |
| | | final Entry baseEntry = fetchBaseEntry(txn, searchOperation.getBaseDN(), searchOperation.getScope()); |
| | | if (!isManageDsaITOperation(searchOperation)) |
| | | { |
| | | dn2uri.checkTargetForReferral(baseEntry, searchOperation.getScope()); |
| | | } |
| | | |
| | | if (searchOperation.getFilter().matchesEntry(baseEntry)) |
| | | { |
| | | searchOperation.returnEntry(baseEntry, null); |
| | | } |
| | | |
| | | if (pageRequest != null) |
| | | { |
| | | // Indicate no more pages. |
| | | Control control = new PagedResultsControl(pageRequest.isCritical(), 0, null); |
| | | searchOperation.getResponseControls().add(control); |
| | | } |
| | | } |
| | | |
| | | private void serverSideSortControlError(final SearchOperation searchOperation, |
| | | ServerSideSortRequestControl sortRequest, DirectoryException de) throws DirectoryException |
| | | { |