/* * When LdapSchema is created from file or subschema subentry, it contains * data which is no longer needed. Only relevant data should remain in order * to keep LdapSchema instance always consistent. */ DWORD VmDirLdapSchemaRemoveNoopData( PVDIR_LDAP_SCHEMA pSchema ) { DWORD dwError = 0; LW_HASHMAP_ITER atIter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_ITER crIter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; if (!pSchema) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } while (LwRtlHashMapIterate(pSchema->attributeTypes, &atIter, &pair)) { PVDIR_LDAP_ATTRIBUTE_TYPE pAt = (PVDIR_LDAP_ATTRIBUTE_TYPE)pair.pValue; VMDIR_SAFE_FREE_MEMORY(pAt->pSource->at_equality_oid); VMDIR_SAFE_FREE_MEMORY(pAt->pSource->at_ordering_oid); VMDIR_SAFE_FREE_MEMORY(pAt->pSource->at_substr_oid); VMDIR_SAFE_FREE_MEMORY(pAt->pSource->at_sup_oid); pAt->pSource->at_syntax_len = 0; } while (LwRtlHashMapIterate(pSchema->contentRules, &crIter, &pair)) { PVDIR_LDAP_CONTENT_RULE pCr = (PVDIR_LDAP_CONTENT_RULE)pair.pValue; VMDIR_SAFE_FREE_MEMORY(pCr->pSource->cr_desc); } error: return dwError; }
DWORD VmDirLdapSchemaResolveAndVerifyAll( PVDIR_LDAP_SCHEMA pSchema ) { DWORD dwError = 0; LW_HASHMAP_ITER atIter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_ITER ocIter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_ITER crIter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; if (!pSchema) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } while (LwRtlHashMapIterate(pSchema->attributeTypes, &atIter, &pair)) { PVDIR_LDAP_ATTRIBUTE_TYPE pAt = (PVDIR_LDAP_ATTRIBUTE_TYPE)pair.pValue; dwError = VmDirLdapAtResolveSup(pSchema, pAt); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirLdapAtVerify(pAt); BAIL_ON_VMDIR_ERROR(dwError); } while (LwRtlHashMapIterate(pSchema->objectClasses, &ocIter, &pair)) { PVDIR_LDAP_OBJECT_CLASS pOc = (PVDIR_LDAP_OBJECT_CLASS)pair.pValue; dwError = VmDirLdapOcResolveSup(pSchema, pOc); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirLdapOcVerify(pSchema, pOc); BAIL_ON_VMDIR_ERROR(dwError); } while (LwRtlHashMapIterate(pSchema->contentRules, &crIter, &pair)) { PVDIR_LDAP_CONTENT_RULE pCr = (PVDIR_LDAP_CONTENT_RULE)pair.pValue; dwError = VmDirLdapCrResolveOid(pSchema, pCr); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirLdapCrVerify(pSchema, pCr); BAIL_ON_VMDIR_ERROR(dwError); } error: return dwError; }
DWORD VmDirIndexUpdateCommit( PVDIR_INDEX_UPD pIndexUpd ) { DWORD dwError = 0; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; PSTR pszStatus = NULL; if (!pIndexUpd) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } while (LwRtlHashMapIterate(pIndexUpd->pUpdIndexCfgMap, &iter, &pair)) { PVDIR_INDEX_CFG pIndexCfg = (PVDIR_INDEX_CFG)pair.pValue; dwError = VmDirIndexCfgRecordProgress(pIndexUpd->pBECtx, pIndexCfg); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszStatus); dwError = VmDirIndexCfgStatusStringfy(pIndexCfg, &pszStatus); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, pszStatus ); } if (pIndexUpd->bHasBETxn) { PVDIR_BACKEND_INTERFACE pBE = pIndexUpd->pBECtx->pBE; dwError = pBE->pfnBETxnCommit(pIndexUpd->pBECtx); BAIL_ON_VMDIR_ERROR(dwError); pIndexUpd->bHasBETxn = FALSE; } VmDirIndexUpdFree(gVdirIndexGlobals.pIndexUpd); gVdirIndexGlobals.pIndexUpd = pIndexUpd; VmDirConditionSignal(gVdirIndexGlobals.cond); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s succeeded", __FUNCTION__ ); cleanup: VMDIR_SAFE_FREE_MEMORY(pszStatus); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); goto cleanup; }
static DWORD _convertHashMapToSuperlogTable( PLW_HASHMAP pHashMap, PVMDIR_SUPERLOG_TABLE_COLUMN_SET pCols, PVMDIR_SUPERLOG_TABLE *ppTable ) { DWORD dwError = 0; DWORD dwCount = 0; PVMDIR_SUPERLOG_TABLE pTable = NULL; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; unsigned int i = 0; unsigned int j; PVMDIR_SUPERLOG_TABLE_ROW pSrcRow = NULL; PVMDIR_SUPERLOG_TABLE_ROW pDstRow = NULL; dwCount = LwRtlHashMapGetCount(pHashMap); dwError = _allocateSuperlogTable(dwCount, pCols, &pTable); BAIL_ON_VMDIR_ERROR(dwError); while (LwRtlHashMapIterate(pHashMap, &iter, &pair)) { pSrcRow = pair.pValue; pDstRow = (PVMDIR_SUPERLOG_TABLE_ROW)&pTable->rows[i++]; pDstRow->count = pSrcRow->count; pDstRow->totalTime = pSrcRow->totalTime; for (j = 0; j < VMDIR_SUPERLOG_TABLE_COL_NUM; j++) { if (pSrcRow->colVals[j]) { dwError = VmDirAllocateStringA(pSrcRow->colVals[j], &pDstRow->colVals[j]); BAIL_ON_VMDIR_ERROR(dwError); } } dwError = VmDirAllocateStringPrintf( &pDstRow->colVals[AVG_TIME], "%lu", pDstRow->totalTime / pDstRow->count ); BAIL_ON_VMDIR_ERROR(dwError); } *ppTable = pTable; cleanup: return dwError; error: VmDirFreeSuperLogTable(pTable); goto cleanup; }
int VmDirReplResolveConflicts( PVDIR_OPERATION pOperation, PVDIR_ENTRY pEntry, PLW_HASHMAP pMetaDataMap ) { int retVal = LDAP_SUCCESS; int dbRetVal = 0; PSTR pszAttrType = NULL; DWORD dwConflictCnt = 0; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; PVDIR_ATTRIBUTE pConsumerAttr = NULL; PVMDIR_ATTRIBUTE_METADATA pSupplierMetaData = NULL; PVMDIR_REPLICATION_METRICS pReplMetrics = NULL; if (!pOperation || !pEntry || !pMetaDataMap) { BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER); } while (LwRtlHashMapIterate(pMetaDataMap, &iter, &pair)) { pszAttrType = (PSTR) pair.pKey; pSupplierMetaData = (PVMDIR_ATTRIBUTE_METADATA) pair.pValue; if (VmDirStringCompareA(pszAttrType, ATTR_OBJECT_GUID, FALSE) == 0) { continue; } VmDirFreeAttribute(pConsumerAttr); pConsumerAttr = NULL; retVal = VmDirAttributeAllocate(pszAttrType, 0, pOperation->pSchemaCtx, &pConsumerAttr); BAIL_ON_LDAP_ERROR( retVal, LDAP_OPERATIONS_ERROR, (pOperation->ldapResult.pszErrMsg), "VmDirAttributeAllocate failed", VDIR_SAFE_STRING(pOperation->pBEErrorMsg)); dbRetVal = pOperation->pBEIF->pfnBEGetAttrMetaData( pOperation->pBECtx, pConsumerAttr, pEntry->eId); if (dbRetVal) { switch (dbRetVal) { case ERROR_BACKEND_ATTR_META_DATA_NOTFOUND: //When a new attribute is being added // => Supplier attribute meta data WINS against consumer attribute meta data break; default: BAIL_ON_LDAP_ERROR( retVal, LDAP_OPERATIONS_ERROR, (pOperation->ldapResult.pszErrMsg), "pfnBEGetAttrMetaData failed - (%d)(%s)", dbRetVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg)); } } else { BOOLEAN bSupplierWon = FALSE; BOOLEAN bIsSameAttrValue = FALSE; PSZ_METADATA_BUF pszSupplierMetaData = {'\0'}; PSZ_METADATA_BUF pszConsumerMetaData = {'\0'}; bSupplierWon = _VmDirReplAttrConflictCheck( pSupplierMetaData, pConsumerAttr->pMetaData); bIsSameAttrValue = _VmDirIsBenignReplConflict( pEntry, pConsumerAttr); //Ignore error - used only for logging VmDirMetaDataSerialize(pSupplierMetaData, &pszSupplierMetaData[0]); VmDirMetaDataSerialize(pConsumerAttr->pMetaData, &pszConsumerMetaData[0]); if (bSupplierWon == FALSE) { if (VmDirStringCompareA(pszAttrType, ATTR_USN_CHANGED, FALSE) == 0) { // Need to keep usnChanged to advance localUSN for this replication change. retVal = VmDirMetaDataCopyContent(pConsumerAttr->pMetaData, pSupplierMetaData); BAIL_ON_VMDIR_ERROR(retVal); } else { VMDIR_FREE_REPL_ATTR_IN_CONFLICT(pSupplierMetaData); } dwConflictCnt++; if (!bIsSameAttrValue) { VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: supplier version loses." " pszAttrType: %s supplier attr meta: %s, consumer attr meta: %s ", __FUNCTION__, pEntry->dn.lberbv.bv_val, pszAttrType, pszSupplierMetaData, pszConsumerMetaData); } } else { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "%s: supplier version wins." " pszAttrType: %s supplier attr meta: %s, consumer attr meta: %s ", __FUNCTION__, pEntry->dn.lberbv.bv_val, pszAttrType, pszSupplierMetaData, pszConsumerMetaData); } } } if (dwConflictCnt > 0) { if (VmDirReplMetricsCacheFind(pOperation->pszPartner, &pReplMetrics) == 0) { VmMetricsCounterAdd(pReplMetrics->pCountConflictResolved, dwConflictCnt); } } cleanup: VmDirFreeAttribute(pConsumerAttr); return retVal; ldaperror: error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", retVal); goto cleanup; }
DWORD VmDirDDVectorParseString( PSTR pszDeadlockDetectionVectorStr, PBOOLEAN pbCompleteReplCycle ) { PSTR pszLocalVectorStr = NULL; PDWORD pdwValue = NULL; DWORD dwError = 0; DWORD dwMinConsecutiveEmptyPage = INT_MAX; BOOLEAN bInLock = FALSE; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; VMDIR_LOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); if (pszDeadlockDetectionVectorStr && pbCompleteReplCycle) { dwError = VmDirAllocateStringA(pszDeadlockDetectionVectorStr+VmDirStringLenA("vector:"), &pszLocalVectorStr); BAIL_ON_VMDIR_ERROR(dwError); // cache the counter value if (LwRtlHashMapFindKey( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, (PVOID*)&pdwValue, gVmdirServerGlobals.bvServerObjName.lberbv_val) == 0) { dwMinConsecutiveEmptyPage = *pdwValue; dwMinConsecutiveEmptyPage++; VMDIR_LOG_INFO(LDAP_DEBUG_REPL, "consecutive empty pages received: %d", dwMinConsecutiveEmptyPage); } // clear and reconstruct the vector LwRtlHashMapClear( gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, VmDirSimpleHashMapPairFree, NULL); dwError = VmDirStrtoVector( pszLocalVectorStr, _VmDirDeadlockDetectionVectorStrToPair, gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap); BAIL_ON_VMDIR_ERROR(dwError); // update the cached counter value dwError = _VmDirDDVectorUpdateDefaultsInLock(dwMinConsecutiveEmptyPage); BAIL_ON_VMDIR_ERROR(dwError); // check for replication cycle completion while (LwRtlHashMapIterate(gVmdirServerGlobals.pReplDeadlockDetectionVector->pEmptyPageSentMap, &iter, &pair)) { dwMinConsecutiveEmptyPage = VMDIR_MIN(dwMinConsecutiveEmptyPage, *(PDWORD)pair.pValue); } *pbCompleteReplCycle = (dwMinConsecutiveEmptyPage >= gVmdirGlobals.dwEmptyPageCnt); if (*pbCompleteReplCycle) { VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s: Break Empty Pages Received, vec: %s", __FUNCTION__, pszDeadlockDetectionVectorStr); } } else // if vector not present - non empty page - clear the vector contents { _VmDirDDVectorUpdateInLock(0); } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVmdirServerGlobals.pReplDeadlockDetectionVector->pMutex); VMDIR_SAFE_FREE_MEMORY(pszLocalVectorStr); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
DWORD VmDirUTDVectorUpdateNew( PVMDIR_UTDVECTOR_CACHE pNewUTDVectorCache ) { USN origUsnInDB = 0; USN newOrigUsn = 0; DWORD dwError = 0; PSTR pszInvocationId = NULL; PSTR pszKey = NULL; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; if (!pNewUTDVectorCache) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } while (LwRtlHashMapIterate(pNewUTDVectorCache->pUtdVectorMap, &iter, &pair)) { origUsnInDB = 0; pszInvocationId = (PSTR) pair.pKey; newOrigUsn = (USN) pair.pValue; dwError = VmDirUTDVectorGlobalCacheLookup(pszInvocationId, &origUsnInDB); if (dwError == LW_STATUS_NOT_FOUND) { dwError = 0; } BAIL_ON_VMDIR_ERROR(dwError); if (origUsnInDB > newOrigUsn) { dwError = VmDirAllocateStringA(pszInvocationId, &pszKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlHashMapInsert( pNewUTDVectorCache->pUtdVectorMap, pszKey, (PVOID)origUsnInDB, &pair); BAIL_ON_VMDIR_ERROR(dwError); pszKey = NULL; VmDirSimpleHashMapPairFreeKeyOnly(&pair, NULL); VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: smaller origUsn InvoId: %s origUsnInDB: %"PRId64 "newOrigUsn: %" PRId64, __FUNCTION__, VDIR_SAFE_STRING(pszInvocationId), origUsnInDB, newOrigUsn); } } cleanup: return dwError; error: VMDIR_SAFE_FREE_MEMORY(pszKey); VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
static DWORD _BuildAllValStrs( PVDIR_INDEX_CFG pIndexCfg, PSTR* ppszStatusVal, PSTR* ppszInitOffsetVal, PSTR* ppszScopesVal, PSTR* ppszNewScopesVal, PSTR* ppszDelScopesVal ) { DWORD dwError = 0; PSTR pszStatusVal = NULL; PSTR pszInitOffsetVal = NULL; PSTR pszScopesVal = NULL; PSTR pszNewScopesVal = NULL; PSTR pszDelScopesVal = NULL; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; PVDIR_LINKED_LIST_NODE pNode = NULL; if (!pIndexCfg || !ppszStatusVal || !ppszInitOffsetVal || !ppszScopesVal || !ppszNewScopesVal || !ppszDelScopesVal) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAllocateStringPrintf( &pszStatusVal, "%d", pIndexCfg->status); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringPrintf( &pszInitOffsetVal, "%u", pIndexCfg->initOffset); BAIL_ON_VMDIR_ERROR(dwError); while (LwRtlHashMapIterate(pIndexCfg->pUniqScopes, &iter, &pair)) { PSTR pszScope = (PSTR)pair.pKey; PSTR pszTmp = pszScopesVal; dwError = VmDirAllocateStringPrintf( &pszScopesVal, "%s%s%s", pszTmp ? pszTmp : "", pszTmp ? INDEX_SEP : "", pszScope); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszTmp); } pNode = pIndexCfg->pNewUniqScopes->pHead; while (pNode) { PSTR pszScope = (PSTR)pNode->pElement; PSTR pszTmp = pszNewScopesVal; dwError = VmDirAllocateStringPrintf( &pszNewScopesVal, "%s%s%s", pszTmp ? pszTmp : "", pszTmp ? INDEX_SEP : "", pszScope); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszTmp); pNode = pNode->pPrev; } pNode = pIndexCfg->pDelUniqScopes->pHead; while (pNode) { PSTR pszScope = (PSTR)pNode->pElement; PSTR pszTmp = pszDelScopesVal; dwError = VmDirAllocateStringPrintf( &pszDelScopesVal, "%s%s%s", pszTmp ? pszTmp : "", pszTmp ? INDEX_SEP : "", pszScope); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_SAFE_FREE_MEMORY(pszTmp); pNode = pNode->pPrev; } *ppszStatusVal = pszStatusVal; *ppszInitOffsetVal = pszInitOffsetVal; *ppszScopesVal = pszScopesVal; *ppszNewScopesVal = pszNewScopesVal; *ppszDelScopesVal = pszDelScopesVal; cleanup: return dwError; error: VMDIR_SAFE_FREE_MEMORY(pszStatusVal); VMDIR_SAFE_FREE_MEMORY(pszInitOffsetVal); VMDIR_SAFE_FREE_MEMORY(pszScopesVal); VMDIR_SAFE_FREE_MEMORY(pszNewScopesVal); VMDIR_SAFE_FREE_MEMORY(pszDelScopesVal); goto cleanup; }
DWORD VmDirSchemaAttrIdMapUpdateDB( PVDIR_SCHEMA_ATTR_ID_MAP pAttrIdMap ) { DWORD dwError = 0; DWORD dwNumNewIds = 0; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; PSTR pszMapStr = NULL; PVMDIR_STRING_LIST pMapStrList = NULL; VDIR_BACKEND_CTX beCtx = {0}; BOOLEAN bHasTxn = FALSE; if (!pAttrIdMap) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwNumNewIds = LwRtlHashMapGetCount(pAttrIdMap->pNewIds); if (dwNumNewIds == 0) { // No new Id goto cleanup; } dwError = VmDirStringListInitialize(&pMapStrList, dwNumNewIds); BAIL_ON_VMDIR_ERROR(dwError); while (LwRtlHashMapIterate(pAttrIdMap->pNewIds, &iter, &pair)) { dwError = VmDirAllocateStringPrintf(&pszMapStr, "%d%s%s", (USHORT)(uintptr_t)pair.pValue, SCHEMA_ATTR_ID_MAP_SEP, (PSTR)pair.pKey); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirStringListAdd(pMapStrList, pszMapStr); BAIL_ON_VMDIR_ERROR(dwError); } beCtx.pBE = VmDirBackendSelect(PERSISTED_DSE_ROOT_DN); dwError = beCtx.pBE->pfnBETxnBegin(&beCtx, VDIR_BACKEND_TXN_WRITE, &bHasTxn); BAIL_ON_VMDIR_ERROR( dwError ); dwError = beCtx.pBE->pfnBEDupKeySetValues(&beCtx, ATTR_ID_MAP_KEY, pMapStrList); BAIL_ON_VMDIR_ERROR(dwError); if (bHasTxn) { dwError = beCtx.pBE->pfnBETxnCommit(&beCtx); bHasTxn = FALSE; BAIL_ON_VMDIR_ERROR(dwError); } LwRtlHashMapResetIter(&iter); while (LwRtlHashMapIterate(pAttrIdMap->pNewIds, &iter, &pair)) { dwError = LwRtlHashMapInsert(pAttrIdMap->pStoredIds, pair.pKey, pair.pValue, NULL); BAIL_ON_VMDIR_ERROR(dwError); } LwRtlHashMapClear(pAttrIdMap->pNewIds, VmDirNoopHashMapPairFree, NULL); cleanup: VmDirBackendCtxContentFree(&beCtx); VmDirStringListFree(pMapStrList); return dwError; error: if (bHasTxn) { beCtx.pBE->pfnBETxnAbort(&beCtx); } VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError ); goto cleanup; }