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; }
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; }
/* * 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; }