/* * Free a heap Attribute * (ATTENTION: if the pAttr is within a pEntry, only when pEntry is constructed as * ENTRY_STORAGE_FORMAT_NORMAL allocation type, its attribute can be freed using this function; * otherwise, an entry's attribute free is taken care of by 'pEntry->bvs' */ VOID VmDirFreeAttribute( PVDIR_ATTRIBUTE pAttr ) { if (!pAttr) { return; } // pAttr->type is always store in place and has NO bvnorm_val. no need to free here. if (!dequeIsEmpty(&pAttr->valueMetaDataToAdd)) { VmDirFreeAttrValueMetaDataDequeueContent(&pAttr->valueMetaDataToAdd); } if (!dequeIsEmpty(&pAttr->valueMetaDataToDelete)) { VmDirFreeAttrValueMetaDataDequeueContent(&pAttr->valueMetaDataToDelete); } VmDirFreeMetaData(pAttr->pMetaData); VmDirFreeBervalContent(&pAttr->type); VmDirFreeBervalArrayContent(pAttr->vals, pAttr->numVals); VMDIR_SAFE_FREE_MEMORY(pAttr->vals); VMDIR_SAFE_FREE_MEMORY(pAttr); }
/** * Removes and frees all links in the deque, except the sentinel. * @param deque */ void dequeClear(Deque* deque) { while (!dequeIsEmpty(deque)) { dequePopFront(deque); } }
VOID testEmpty( PVMDIR_TEST_STATE pState, PDEQUE pDeque ) { DWORD dwError = 0; PDEQUEUE_TEST_ELEMENT pElement = NULL; BOOLEAN fEmpty = FALSE; //Test case: pop from empty queue fEmpty = dequeIsEmpty(pDeque); TestAssertEquals(fEmpty, TRUE); dwError = dequePopLeft(pDeque, (PVOID*)&pElement); TestAssertEquals(dwError, ERROR_NO_MORE_ITEMS); }
/** * Determines if there is a path from the source to the destination using an * iterative breadth-first search starting at the source. * * Remember to call clearVisited() before starting the search. * * @param graph * @param source * @param destination * @return 1 if there is a path, 0 otherwise. */ int bfsIterative(Graph* graph, Vertex* source, Vertex* destination) { clearVisited(graph); int i; int found = 0; // queue Deque *collection = malloc(sizeof(Deque)); Vertex *current; // initialize queue and add source collection = dequeNew(); dequePushBack(collection, source); // search until destination is found or we run out of edges while (!(found == 1) && !dequeIsEmpty(collection)) { // current vertex is the one first added to collection current = dequeFront(collection); dequePopFront(collection); current->isVisited = 1; // if the current node is the destination, we're done if (current == destination) found = 1; // otherwise add its neighbors to the queue else { for (i = 0; i < current->numNeighbors; ++i) if (!(current->neighbors[i]->isVisited)) dequePushBack(collection, current->neighbors[i]); } } // clean things up clearVisited(graph); dequeClear(collection); free(collection); // return if path was found return found; }
/* * Determine whether the supplier's attr-value-meta-data wins by checking it against local * attr-meta-data and local attr-value-meta-data. * It first compares the <version><invocation-id> of that in local attr-meta-data which was * applied either in the previous transaction or the previous modification in the current * transactions. Then if the <version><invocation-id> matches, it looks up the local server * to see if the same attr-value-meta-data exist: if supplier's attr-value-meta-data has a * newer timestamp then it wins and inScope set to TRUE. */ DWORD VmDirReplResolveValueMetaDataConflicts( PVDIR_OPERATION pModOp, PVDIR_ATTRIBUTE pAttr, PVMDIR_VALUE_ATTRIBUTE_METADATA pSupplierValueMetaData, ENTRYID entryId, PBOOLEAN pInScope ) { DWORD dwError = 0; VDIR_BERVALUE bervSupplierValueMetaData = VDIR_BERVALUE_INIT; VDIR_BERVALUE bervConsumerValueMetaData = VDIR_BERVALUE_INIT; DEQUE valueMetaDataQueue = {0}; PVMDIR_VALUE_ATTRIBUTE_METADATA pConsumerValueMetaData = NULL; if (!pModOp || !pAttr || !pSupplierValueMetaData || !pInScope) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } *pInScope = TRUE; dwError = pModOp->pBEIF->pfnBEGetAttrMetaData(pModOp->pBECtx, pAttr, entryId); BAIL_ON_VMDIR_ERROR(dwError); //Consumer <version><originating-server-id> in metaValueData //not match supplier's <version<<originating-server-id> in metaData //this value-meta-data out of scope if (pSupplierValueMetaData->version != pAttr->pMetaData->version || VmDirStringCompareA( pSupplierValueMetaData->pszOrigInvoId, pAttr->pMetaData->pszOrigInvoId, TRUE) != 0) { *pInScope = FALSE; goto cleanup; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //Ignore error, used only for logging VmDirValueMetaDataSerialize(pSupplierValueMetaData, &bervSupplierValueMetaData); VmDirValueMetaDataSerialize(pConsumerValueMetaData, &bervConsumerValueMetaData); } dwError = pModOp->pBEIF->pfnBEGetAttrValueMetaData( pModOp->pBECtx, entryId, pAttr->pATDesc->usAttrID, &valueMetaDataQueue); BAIL_ON_VMDIR_ERROR(dwError); while(!dequeIsEmpty(&valueMetaDataQueue)) { VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); dequePopLeft(&valueMetaDataQueue, (PVOID*)&pConsumerValueMetaData); if (pConsumerValueMetaData->dwValSize != pSupplierValueMetaData->dwValSize || VmDirCompareMemory( pConsumerValueMetaData->pszValue, pSupplierValueMetaData->pszValue, pConsumerValueMetaData->dwValSize) != 0) { continue; } if (VmDirStringCompareA( pConsumerValueMetaData->pszValChgOrigTime, pSupplierValueMetaData->pszValChgOrigTime, TRUE) > 0) { *pInScope = FALSE; VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta lose: %s consumer: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val), VDIR_SAFE_STRING(bervConsumerValueMetaData.lberbv_val)); } } if (*pInScope) { VMDIR_LOG_DEBUG( LDAP_DEBUG_REPL, "%s: supplier attr-value-meta won: %s", __FUNCTION__, VDIR_SAFE_STRING(bervSupplierValueMetaData.lberbv_val)); } cleanup: VmDirFreeBervalContent(&bervSupplierValueMetaData); VmDirFreeBervalContent(&bervConsumerValueMetaData); VMDIR_SAFE_FREE_VALUE_METADATA(pConsumerValueMetaData); VmDirFreeAttrValueMetaDataDequeueContent(&valueMetaDataQueue); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
DWORD VmDirIsAttrValueInScope( PVDIR_OPERATION pOperation, PDEQUE pAllValueMetaDataQueue, PDEQUE pValueMetaDataToSendQueue ) { DWORD dwError = 0; VDIR_BERVALUE bervValueMetaData = VDIR_BERVALUE_INIT; PVMDIR_VALUE_ATTRIBUTE_METADATA pValueMetaData = NULL; if (!pOperation || !pAllValueMetaDataQueue || !pValueMetaDataToSendQueue) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } while (!dequeIsEmpty(pAllValueMetaDataQueue)) { BOOLEAN bUsnInScope = FALSE; VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); dequePopLeft(pAllValueMetaDataQueue, (PVOID*)&pValueMetaData); dwError = VmDirIsUsnInScope( pOperation, NULL, pValueMetaData->pszValChgOrigInvoId, pValueMetaData->valChgOrigUsn, pValueMetaData->localUsn, 0, &bUsnInScope); BAIL_ON_VMDIR_ERROR(dwError); if (!bUsnInScope) { continue; } if (VmDirLogGetMask() & LDAP_DEBUG_REPL) { //ignore error VmDirValueMetaDataSerialize(pValueMetaData, &bervValueMetaData); VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "%s: valueMetaData: %s, usnInScope true", __FUNCTION__, VDIR_SAFE_STRING(bervValueMetaData.lberbv_val)); VmDirFreeBervalContent(&bervValueMetaData); } dwError = dequePush(pValueMetaDataToSendQueue, pValueMetaData); BAIL_ON_VMDIR_ERROR(dwError); pValueMetaData = NULL; } cleanup: VMDIR_SAFE_FREE_VALUE_METADATA(pValueMetaData); return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", dwError); goto cleanup; }
/* This function re-instantiates the current vmdir instance with a * foreign (MDB) database file. It is triggered by running vdcadmintool * with option 8. Before this action, a foreign database files must be copied * onto diretory mdb_home_dir/partner/ which may include mdb WAL files under * xlogs/. See PR 1995325 for the functional spec and use cases. */ DWORD VmDirSrvServerReset( PDWORD pServerResetState ) { int i = 0; DWORD dwError = 0; VDIR_ENTRY_ARRAY entryArray = {0}; const char *dbHomeDir = VMDIR_DB_DIR; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; BOOLEAN bWriteInvocationId = FALSE; PSTR pszConfigurationContainerDn = NULL; PSTR pszDomainControllerContainerDn = NULL; PSTR pszManagedServiceAccountContainerDn = NULL; DEQUE computers = {0}; PSTR pszComputer = NULL; PVDIR_ATTRIBUTE pAttrUPN = NULL; BOOLEAN bMdbWalEnable = FALSE; VmDirGetMdbWalEnable(&bMdbWalEnable); //swap current vmdir database file with the foriegn one under partner/ dwError = _VmDirSwapDB(dbHomeDir, bMdbWalEnable); BAIL_ON_VMDIR_ERROR(dwError); //Delete Computers (domain controller accounts) under Domain Controller container dwError = VmDirAllocateStringPrintf(&pszDomainControllerContainerDn, "ou=%s,%s", VMDIR_DOMAIN_CONTROLLERS_RDN_VAL, gVmdirServerGlobals.systemDomainDN.lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSimpleEqualFilterInternalSearch(pszDomainControllerContainerDn, LDAP_SCOPE_ONE, ATTR_OBJECT_CLASS, OC_COMPUTER, &entryArray); BAIL_ON_VMDIR_ERROR(dwError); if(entryArray.iSize > 0) { for (i = 0; i < entryArray.iSize; i++) { pAttrUPN = VmDirFindAttrByName(&entryArray.pEntry[i], ATTR_KRB_UPN); if (pAttrUPN) { PSTR pPc = NULL; dwError = VmDirAllocateStringA(pAttrUPN->vals[0].lberbv_val, &pPc); dequePush(&computers, pPc); } dwError = VmDirDeleteEntry(&entryArray.pEntry[i]); BAIL_ON_VMDIR_ERROR(dwError); } } VmDirFreeEntryArrayContent(&entryArray); /* Delete all entries in the subtree under Configuration container * (e.g. under cn=Configuration,dc=vmware,dc=com). * This will remove the old replication topology */ dwError = VmDirAllocateStringPrintf(&pszConfigurationContainerDn, "cn=%s,%s", VMDIR_CONFIGURATION_CONTAINER_NAME, gVmdirServerGlobals.systemDomainDN.lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSimpleEqualFilterInternalSearch(pszConfigurationContainerDn, LDAP_SCOPE_SUBTREE, ATTR_OBJECT_CLASS, OC_DIR_SERVER, &entryArray); BAIL_ON_VMDIR_ERROR(dwError); if (entryArray.iSize > 0) { for (i = 0; i < entryArray.iSize; i++) { /* Delete all replication agreement entries for a server and * the server it self under the configuration/site container */ dwError = VmDirInternalDeleteTree(entryArray.pEntry[i].dn.lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); } } VmDirFreeEntryArrayContent(&entryArray); //Delete ManagedServiceAccount entries that are associated with any of the domain controllers dwError = VmDirAllocateStringPrintf(&pszManagedServiceAccountContainerDn, "cn=%s,%s", VMDIR_MSAS_RDN_VAL, gVmdirServerGlobals.systemDomainDN.lberbv_val); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSimpleEqualFilterInternalSearch(pszManagedServiceAccountContainerDn, LDAP_SCOPE_ONE, ATTR_OBJECT_CLASS, OC_MANAGED_SERVICE_ACCOUNT, &entryArray); BAIL_ON_VMDIR_ERROR(dwError); if (entryArray.iSize > 0) { for (i = 0; i < entryArray.iSize; i++) { PDEQUE_NODE p = NULL; pAttrUPN = VmDirFindAttrByName(&entryArray.pEntry[i], ATTR_KRB_UPN); for(p = computers.pHead; p != NULL; p = p->pNext) { if (VmDirStringCaseStrA(pAttrUPN->vals[0].lberbv_val, p->pElement) != NULL) { dwError = VmDirDeleteEntry(&entryArray.pEntry[i]); BAIL_ON_VMDIR_ERROR(dwError); break; } } } } dwError = VmDirSchemaCtxAcquire(&pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSrvCreateServerObj(pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); //Create server and replication entries for the current instance // on top of the (cleaned up) foreign database. dwError = VmDirSrvCreateReplAgrsContainer(pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); dwError = _VmDirPatchDSERoot(pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); VmDirSchemaCtxRelease(pSchemaCtx); pSchemaCtx = NULL; dwError = LoadServerGlobals(&bWriteInvocationId); BAIL_ON_VMDIR_ERROR(dwError); cleanup: if (pSchemaCtx) { VmDirSchemaCtxRelease(pSchemaCtx); } VmDirFreeEntryArrayContent(&entryArray); VMDIR_SAFE_FREE_MEMORY(pszConfigurationContainerDn); VMDIR_SAFE_FREE_MEMORY(pszDomainControllerContainerDn); while(!dequeIsEmpty(&computers)) { dequePopLeft(&computers, (PVOID*)&pszComputer); VMDIR_SAFE_FREE_MEMORY(pszComputer); } return dwError; error: goto cleanup; }