Exemplo n.º 1
0
/* InternalSearch: Interface that can be used "internally" by the server code. One of the main differences between
 * this function and MLSearch is that this function does not send back an LDAP result to the client.
 *
 * Return: VmDir level error code.  Also, pOperation->ldapResult content is set.
 */
int
VmDirInternalSearch(
    PVDIR_OPERATION pOperation
    )
{
    int     retVal = LDAP_SUCCESS;
    DWORD   dwEntryCount = 0;
    BOOLEAN bHasTxn = FALSE;
    PSTR    pszLocalErrMsg = NULL;
    ENTRYID     eId = 0;
    ENTRYID*    pValidatedEntries = NULL;
    PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);
    PVDIR_OPERATION_ML_METRIC  pMLMetrics = NULL;

    assert(pOperation && pOperation->pBEIF);

    pMLMetrics = &pOperation->MLMetrics;
    VMDIR_COLLECT_TIME(pMLMetrics->iMLStartTime);

    // compute required access for this search
    ComputeRequiredAccess(&pOperation->request.searchReq);

    // Normalize (base) DN
    retVal = VmDirNormalizeDN( &(pOperation->reqDn), pOperation->pSchemaCtx );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DN normalization failed - (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(VmDirSchemaCtxGetErrorMsg(pOperation->pSchemaCtx)) );

    if (VmDirHandleSpecialSearch( pOperation, pResult )) // TODO, add &pszLocalErrMsg
    {
        retVal = pResult->errCode ? pResult->errCode : pResult->vmdirErrCode;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "Special search failed - (%u)", retVal);

        goto cleanup;  // done special search
    }

    if (pOperation->dbCopyCtrl) {
        retVal = VmDirExecDbCopyCtrl(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    if (pOperation->syncReqCtrl != NULL) // Replication
    {
        pOperation->opType = VDIR_OPERATION_TYPE_REPL;
    }

    if (pOperation->pReplAgrDisableCtrl)
    {
        retVal = VmDirExecReplAgrEnableDisableCtrl(BERVAL_NORM_VAL(pOperation->reqDn), FALSE);
        BAIL_ON_VMDIR_ERROR(retVal);
    }
    else if (pOperation->pReplAgrEnableCtrl)
    {
        retVal = VmDirExecReplAgrEnableDisableCtrl(BERVAL_NORM_VAL(pOperation->reqDn), TRUE);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    // If base is not ROOT, read lock the base object (DnToEntryId index entry) to make sure it exists, and it does
    // not get deleted during this search processing.
    if (pOperation->reqDn.lberbv.bv_len != 0)
    {
        VMDIR_COLLECT_TIME(pMLMetrics->iBETxnBeginStartTime);

        retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
        bHasTxn = TRUE;

        VMDIR_COLLECT_TIME(pMLMetrics->iBETxnBeginEndTime);

        // Lookup in the DN index.
        retVal = pOperation->pBEIF->pfnBEDNToEntryId( pOperation->pBECtx, &(pOperation->reqDn), &eId );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DNToEID (%u)(%s)",
                retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
    }

    // start txn if not has one already.
    if (! pOperation->pBECtx->pBEPrivate)
    {
        retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                                      retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
        bHasTxn = TRUE;
    }

    retVal = AppendDNFilter( pOperation );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "Appending DN filter failed.");

    /*
     * TODO cleanup During background thread implementation of page search
     */
    if (gVmdirGlobals.bPagedSearchReadAhead)
    {
        if (pOperation->showPagedResultsCtrl != NULL &&
            !IsNullOrEmptyString(pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie))
        {
            retVal = VmDirPagedSearchCacheRead(
                        pOperation->showPagedResultsCtrl->value.pagedResultCtrlVal.cookie,
                        &pValidatedEntries,
                        &dwEntryCount);
            BAIL_ON_VMDIR_ERROR(retVal);
        }
    }

    if (pOperation->showPagedResultsCtrl == NULL)
    {
        retVal = _VmDirInternalNormalSearch(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }
    else
    {
        retVal = _VmDirInternalPagedSearch(pOperation);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    /*
     * TODO cleanup During background thread implementation of page search
     */
    if (pValidatedEntries != NULL)
    {
        retVal = ProcessPreValidatedEntries(
                    pOperation,
                    dwEntryCount,
                    pValidatedEntries);
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    VMDIR_COLLECT_TIME(pMLMetrics->iBETxnCommitStartTime);

    retVal = pOperation->pBEIF->pfnBETxnCommit( pOperation->pBECtx);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn commit (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
    bHasTxn = FALSE;

    VMDIR_COLLECT_TIME(pMLMetrics->iBETxnCommitEndTime);

cleanup:

    // collect metrics
    VMDIR_COLLECT_TIME(pMLMetrics->iMLEndTime);
    VmDirInternalMetricsUpdate(pOperation);
    VmDirInternalMetricsLogInefficientOp(pOperation);

    VMDIR_SAFE_FREE_MEMORY(pValidatedEntries);
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg);
    return retVal;

error:

    if (bHasTxn)
    {
        pOperation->pBEIF->pfnBETxnAbort(pOperation->pBECtx);
    }

    VMDIR_SET_LDAP_RESULT_ERROR(&pOperation->ldapResult, retVal, pszLocalErrMsg);
    goto cleanup;
}
Exemplo n.º 2
0
int
VmDirInternalSearch(
    PVDIR_OPERATION pOperation
    )
{
    int        retVal = LDAP_SUCCESS;
    ENTRYID    eId = 0;
    int        deadLockRetries = 0;
    BOOLEAN    bHasTxn = FALSE;
    PSTR       pszLocalErrMsg = NULL;
    PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);

    assert(pOperation && pOperation->pBEIF);

    // Normalize (base) DN
    retVal = VmDirNormalizeDN( &(pOperation->reqDn), pOperation->pSchemaCtx );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DN normalization failed - (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(VmDirSchemaCtxGetErrorMsg(pOperation->pSchemaCtx)) );

    if (VmDirHandleSpecialSearch( pOperation, pResult )) // TODO, add &pszLocalErrMsg
    {
        retVal = pResult->errCode;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, pszLocalErrMsg, "Special search failed - (%u)", retVal);

        goto cleanup;  // done special search
    }

    if (pOperation->syncReqCtrl != NULL) // Replication
    {
        pOperation->lowestPendingUncommittedUsn =
                    pOperation->pBEIF->pfnBEGetLeastOutstandingUSN( pOperation->pBECtx, FALSE );

        VmDirLog( LDAP_DEBUG_REPL, "Replication request USN (%u)",  pOperation->lowestPendingUncommittedUsn );
    }

    // If base is not ROOT, read lock the base object (DnToEntryId index entry) to make sure it exists, and it does
    // not get deleted during this search processing.
    if (pOperation->reqDn.lberbv.bv_len != 0)
    {
        // ************************************************************************************
        // transaction retry loop begin.  make sure all function within are retry agnostic.
        // ************************************************************************************
txnretry:
        if (bHasTxn)
        {
            pOperation->pBEIF->pfnBETxnAbort( pOperation->pBECtx );
            bHasTxn = FALSE;
        }

        deadLockRetries++;
        if (deadLockRetries > MAX_DEADLOCK_RETRIES)
        {
            retVal = VMDIR_ERROR_LOCK_DEADLOCK;
            BAIL_ON_VMDIR_ERROR( retVal );
        }
        else
        {
            retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
            BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                                          retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
            bHasTxn = TRUE;

            // Lookup in the DN index.
            retVal = pOperation->pBEIF->pfnBEDNToEntryId( pOperation->pBECtx, &(pOperation->reqDn), &eId );
            if (retVal != 0)
            {
                switch (retVal)
                {
                    case VMDIR_ERROR_BACKEND_DEADLOCK:
                        goto txnretry; // Possible retry.

                    default:
                        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "DNToEID (%u)(%s)",
                                                      retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));
                }
            }
        }
        // ************************************************************************************
        // transaction retry loop end.
        // ************************************************************************************
    }

    // start txn if not has one already.
    if (! pOperation->pBECtx->pBEPrivate)
    {
        retVal = pOperation->pBEIF->pfnBETxnBegin( pOperation->pBECtx, VDIR_BACKEND_TXN_READ );
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn begin (%u)(%s)",
                                      retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));

        bHasTxn = TRUE;
    }

    retVal = AppendDNFilter( pOperation );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "Appending DN filter failed.");

    retVal = BuildCandidateList( pOperation, pOperation->request.searchReq.filter);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "BuildCandidateList failed.");

    if (pOperation->request.searchReq.filter->computeResult == FILTER_RES_TRUE)
    {
        retVal = VMDIR_ERROR_UNWILLING_TO_PERFORM;
        BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                                      "Full scan of Entry DB is required. Refine your search.");
    }

    retVal = ProcessCandidateList( pOperation );
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg,
                                   "ProcessCandidateList failed. (%u)(%s)",
                                   retVal,
                                   VDIR_SAFE_STRING( pOperation->ldapResult.pszErrMsg) );

    retVal = pOperation->pBEIF->pfnBETxnCommit( pOperation->pBECtx);
    BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, pszLocalErrMsg, "txn commit (%u)(%s)",
                                  retVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg));

    bHasTxn = FALSE;

cleanup:

    VMDIR_SAFE_FREE_MEMORY( pszLocalErrMsg );

    return retVal;

error:

    if (bHasTxn)
    {
        pOperation->pBEIF->pfnBETxnAbort( pOperation->pBECtx );
    }

    VMDIR_SET_LDAP_RESULT_ERROR( &(pOperation->ldapResult), retVal, pszLocalErrMsg);

    goto cleanup;
}