Example #1
0
static
PVDIR_PAGED_SEARCH_RECORD
VmDirPagedSearchCacheFind(
    PCSTR pszCookie
    )
{
    DWORD dwError = 0;
    PLW_HASHTABLE_NODE pNode = NULL;
    PVDIR_PAGED_SEARCH_RECORD pSearchRecord = NULL;
    BOOLEAN bInLock = FALSE;

    if (IsNullOrEmptyString(pszCookie))
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    VMDIR_LOCK_MUTEX(bInLock, gPagedSearchCache.mutex);
    dwError = LwRtlHashTableFindKey(
                    gPagedSearchCache.pHashTbl,
                    &pNode,
                    (PVOID)pszCookie);
    dwError = LwNtStatusToWin32Error(dwError);
    BAIL_ON_VMDIR_ERROR(dwError);

    pSearchRecord = LW_STRUCT_FROM_FIELD(pNode, VDIR_PAGED_SEARCH_RECORD, Node);
    _RefPagedSearchRecord(pSearchRecord);

cleanup:
    VMDIR_UNLOCK_MUTEX(bInLock, gPagedSearchCache.mutex);
    return pSearchRecord;
error:
    goto cleanup;
}
Example #2
0
static
int
IsAttrInReplScope(
    VDIR_OPERATION *    op,
    char *              attrType,
    char *              attrMetaData,
    BOOLEAN *           inScope,
    PSTR*               ppszErrorMsg
    )
{
    int                     retVal = LDAP_SUCCESS;
    PLW_HASHTABLE_NODE      pNode = NULL;
    char                    origInvocationId[VMDIR_GUID_STR_LEN];
    USN                     origUsn = VmDirStringToLA( VmDirStringRChrA( attrMetaData, ':' ) + 1, NULL, 10 );
    int                     rc = 0;
    PSTR                    pszLocalErrorMsg = NULL;

    *inScope = FALSE;

    // attrMetaData format is: <local USN>:<version no>:<originating server ID>:<originating time>:<originating USN>
    VmDirStringNCpyA( origInvocationId, VMDIR_GUID_STR_LEN,
                      VmDirStringChrA( VmDirStringChrA( attrMetaData, ':' ) + 1, ':') + 1, VMDIR_GUID_STR_LEN - 1);
    origInvocationId[VMDIR_GUID_STR_LEN - 1] = '\0';

    // Skip the attribute:
    //    - if the originating server for the current state is same as the requesting server or if it is one of those
    //      attributes that have "local" scope only. E.g. sending ATTR_LAST_LOCAL_USN_PROCESSED and
    //      ATTR_UP_TO_DATE_VECTOR, causes continuous back-forth replication of Replication Agreements and Server
    //      entries between various servers.

    assert( op->syncReqCtrl != NULL );

    if ((attrType != NULL && (VmDirStringCompareA( attrType, ATTR_LAST_LOCAL_USN_PROCESSED, FALSE) == 0 ||
                              VmDirStringCompareA( attrType, ATTR_UP_TO_DATE_VECTOR, FALSE) == 0 ||
                              VmDirStringCompareA( attrType, VDIR_ATTRIBUTE_SEQUENCE_RID, FALSE) == 0)))

    {
        // Reset metaData value so that we don't send local only attribute back.
        attrMetaData[0] = '\0';
        *inScope = FALSE;
        goto cleanup;
    }
    else if ( attrType != NULL && (VmDirStringCompareA( attrType, ATTR_USN_CHANGED, FALSE) == 0))
    {
        ; // always send uSNChanged. (PR 1573117)
    }
    else if (VmDirStringCompareA( origInvocationId,
                  op->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,TRUE ) == 0)
    {
        // Change is originated from the requesting server.
        // Reset metaData value so that we don't send metaData as well as this attribute back.
        attrMetaData[0] = '\0';
        *inScope = FALSE;
        goto cleanup;
    }
    else
    {
        rc = LwRtlHashTableFindKey( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, origInvocationId );
        rc = LwNtStatusToWin32Error(rc);
        if (rc != 0 && rc != ERROR_NOT_FOUND)
        {
            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "IsAttrInReplScope: LwRtlHashTableFindKey failed for origInvocationId: %s",
                      origInvocationId );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "LwRtlHashTableFindKey failed.");
        }

        if (pNode == NULL) // Attribute is to be sent in the result entry.
        {
            UptoDateVectorEntry * utdVectorEntry = NULL;
            VDIR_BERVALUE         bvServerId = VDIR_BERVALUE_INIT;

            if (VmDirAllocateMemory( sizeof( UptoDateVectorEntry ), (PVOID *)&utdVectorEntry) != 0)
            {
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "IsAttrInReplScope: BervalContentDup failed.");
            }
            bvServerId.lberbv.bv_val = origInvocationId;
            bvServerId.lberbv.bv_len = VmDirStringLenA( origInvocationId );
            if (VmDirBervalContentDup( &bvServerId, &utdVectorEntry->invocationId ) != 0)
            {
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "IsAttrInReplScope: BervalContentDup failed.");
            }
            utdVectorEntry->currMaxOrigUsnProcessed = origUsn;
            LwRtlHashTableResizeAndInsert( op->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector,
                                           &utdVectorEntry->Node, &pNode);
            assert( pNode == NULL );    // assert the key of added node is unique
        }
        else
        {
            UptoDateVectorEntry *   utdVectorEntry = NULL;
            utdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);

            if (origUsn > utdVectorEntry->reqLastOrigUsnProcessed )
            { // Attribute is to be sent in the result entry.
                // Update if origUsn of this attribute is > the current highest
                if (origUsn > utdVectorEntry->currMaxOrigUsnProcessed )
                {
                    utdVectorEntry->currMaxOrigUsnProcessed = origUsn;
                }
            }
            else
            {
                VMDIR_LOG_VERBOSE( LDAP_DEBUG_REPL_ATTR,
                          "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = FALSE",
                          attrType, attrMetaData );

                // Reset metaData value so that we don't send metaData for this attribute back.
                attrMetaData[0] = '\0';
                *inScope = FALSE;
                goto cleanup;
            }
        }
    }

    VMDIR_LOG_INFO( LDAP_DEBUG_REPL_ATTR, "IsAttrInReplScope: Attribute: %s, metaData: %s, replication scope = TRUE",
              attrType, attrMetaData );
    *inScope = TRUE;

cleanup:

    if (ppszErrorMsg)
    {
        *ppszErrorMsg = pszLocalErrorMsg;
    }
    else
    {
        VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    }

    return( retVal );

error:

    goto cleanup;
}
Example #3
0
/*
 * Test whether the origUsn is in scope so that attribute, attr-meta-data or
 * attr-value-meta-data be sent back to the replicaiton consumer based on whether
 * the origUsn for that invocationId has been processed already by the consumer
 * TODO: Needed Refractoring
 */
DWORD
VmDirIsUsnInScope(
    PVDIR_OPERATION     pOperation,
    PCSTR               pAttrName,
    PCSTR               pszOrigInvocationId,
    USN                 origUsn,
    USN                 localUSN,
    USN                 priorSentUSNCreated,
    PBOOLEAN            pbIsUsnInScope
    )
{
    DWORD                   dwError = 0;
    PLW_HASHTABLE_NODE      pNode = NULL;
    PSTR                    pszLocalErrorMsg = NULL;
    UptoDateVectorEntry     *pUtdVectorEntry = NULL;
    UptoDateVectorEntry     *pNewUtdVectorEntry = NULL;
    int                     retVal = 0;

    if (!pOperation ||
        !pszOrigInvocationId ||
        !pbIsUsnInScope ||
        !pOperation->syncReqCtrl ||
        !pOperation->syncDoneCtrl)
    {
        BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER);
    }

    *pbIsUsnInScope = FALSE;

    //Originating server for the current state is same as the requesting server
    if (VmDirStringCompareA(
                pszOrigInvocationId,
                pOperation->syncReqCtrl->value.syncReqCtrlVal.reqInvocationId.lberbv.bv_val,
                TRUE) == 0)
    {
        *pbIsUsnInScope = FALSE;
        goto cleanup;
    }

    retVal = LwRtlHashTableFindKey(
            pOperation->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector, &pNode, pszOrigInvocationId);

    retVal = LwNtStatusToWin32Error(retVal);

    if (retVal != 0 && retVal != ERROR_NOT_FOUND)
    {
        VMDIR_LOG_VERBOSE(
                VMDIR_LOG_MASK_ALL,
                "%s: LwRtlHashTableFindKey failed for origInvocationId: %s",
                __FUNCTION__,
                pszOrigInvocationId);
        dwError = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, (pszLocalErrorMsg), "LwRtlHashTableFindKey failed.");
    }

    if (pNode == NULL)
    {
        VDIR_BERVALUE    bvServerId = VDIR_BERVALUE_INIT;

        dwError = VmDirAllocateMemory(sizeof(UptoDateVectorEntry), (PVOID *)&pNewUtdVectorEntry);
        BAIL_ON_VMDIR_ERROR(dwError);

        bvServerId.lberbv.bv_val = (PSTR)pszOrigInvocationId;
        bvServerId.lberbv.bv_len = VmDirStringLenA(pszOrigInvocationId);

        dwError = VmDirBervalContentDup(&bvServerId, &pNewUtdVectorEntry->invocationId);
        BAIL_ON_VMDIR_ERROR(dwError);

        pNewUtdVectorEntry->currMaxOrigUsnProcessed = origUsn;

        LwRtlHashTableResizeAndInsert(
                pOperation->syncDoneCtrl->value.syncDoneCtrlVal.htUtdVector,
                &pNewUtdVectorEntry->Node,
                &pNode);

        // assert the key of added node is unique
        assert(pNode == NULL);

        pNewUtdVectorEntry = NULL;
        *pbIsUsnInScope = TRUE;

        goto cleanup;
    }

    pUtdVectorEntry = (UptoDateVectorEntry *)LW_STRUCT_FROM_FIELD(pNode, UptoDateVectorEntry, Node);

    if (origUsn > pUtdVectorEntry->reqLastOrigUsnProcessed )
    {
        // attribute or the valueMetaData item in scope if origUsn valueMetaData is > the current highest
        if (origUsn > pUtdVectorEntry->currMaxOrigUsnProcessed )
        {
            pUtdVectorEntry->currMaxOrigUsnProcessed = origUsn;
        }

        // Note, this handles ADD->MODIFY case but not multiple MODIFYs scenario.
        // However, it is fine as consumer should be able to handle redundant feed from supplier.
        // The key point here is to NOT send ATTR_USN_CREATED, so we can derive correct sync_state in WriteSyncStateControl.
        if (localUSN > priorSentUSNCreated)
        {
            *pbIsUsnInScope = TRUE;

            if (priorSentUSNCreated > 0)
            {
                VMDIR_LOG_INFO(
                        LDAP_DEBUG_REPL,
                        "%s new usn %llu after prior usncreated %llu attr %s",
                        __FUNCTION__,
                        origUsn,
                        priorSentUSNCreated,
                        VDIR_SAFE_STRING(pAttrName));
            }
        }
        else
        {
            VMDIR_LOG_INFO(
                    LDAP_DEBUG_REPL,
                    "%s (add->modify) race condition avoided. skip prior usncreated %llu attr %s",
                    __FUNCTION__,
                    priorSentUSNCreated,
                    VDIR_SAFE_STRING(pAttrName));
        }

        goto cleanup;
    }

    VMDIR_LOG_INFO(
            LDAP_DEBUG_REPL,
            "%s: (not in scope) attr name: %s orig invo: %s utdUsn: %"PRId64" usn: %"PRId64,
            __FUNCTION__,
            VDIR_SAFE_STRING(pAttrName),
            VDIR_SAFE_STRING(pszOrigInvocationId),
            pUtdVectorEntry->reqLastOrigUsnProcessed,
            origUsn);

cleanup:
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    return dwError;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError);
    if (pNewUtdVectorEntry)
    {
        VmDirFreeBervalContent(&pNewUtdVectorEntry->invocationId);
    }
    VMDIR_SAFE_FREE_MEMORY(pNewUtdVectorEntry);
    goto cleanup;
}