DWORD VmDirIndexLibInit( PVMDIR_MUTEX pModMutex ) { static VDIR_DEFAULT_INDEX_CFG defIdx[] = VDIR_INDEX_INITIALIZER; DWORD dwError = 0; DWORD i = 0; PSTR pszLastOffset = NULL; ENTRYID maxEId = 0; VDIR_BACKEND_CTX beCtx = {0}; BOOLEAN bHasTxn = FALSE; PVDIR_INDEX_CFG pIndexCfg = NULL; PVDIR_SCHEMA_CTX pSchemaCtx = NULL; PVDIR_SCHEMA_AT_DESC pATDesc = NULL; if (!pModMutex) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } // pModMutex refers to gVdirSchemaGlobals.cacheModMutex, // so do not free it during shutdown gVdirIndexGlobals.mutex = pModMutex; dwError = VmDirAllocateCondition(&gVdirIndexGlobals.cond); BAIL_ON_VMDIR_ERROR(dwError); dwError = LwRtlCreateHashMap( &gVdirIndexGlobals.pIndexCfgMap, LwRtlHashDigestPstrCaseless, LwRtlHashEqualPstrCaseless, NULL); BAIL_ON_VMDIR_ERROR(dwError); beCtx.pBE = VmDirBackendSelect(NULL); dwError = beCtx.pBE->pfnBETxnBegin(&beCtx, VDIR_BACKEND_TXN_WRITE); BAIL_ON_VMDIR_ERROR(dwError); bHasTxn = TRUE; // get fields to continue indexing from where it left last time dwError = beCtx.pBE->pfnBEUniqKeyGetValue( &beCtx, INDEX_LAST_OFFSET_KEY, &pszLastOffset); if (dwError) { dwError = beCtx.pBE->pfnBEMaxEntryId(&maxEId); BAIL_ON_VMDIR_ERROR(dwError); if (maxEId == ENTRY_ID_SEQ_INITIAL_VALUE) { gVdirIndexGlobals.bFirstboot = TRUE; } else { gVdirIndexGlobals.bLegacyDB = TRUE; } // set index_last_offset = -1 to indicate indexing has started gVdirIndexGlobals.offset = -1; dwError = beCtx.pBE->pfnBEUniqKeySetValue( &beCtx, INDEX_LAST_OFFSET_KEY, "-1"); BAIL_ON_VMDIR_ERROR(dwError); } else { dwError = VmDirStringToINT64(pszLastOffset, NULL, &gVdirIndexGlobals.offset); BAIL_ON_VMDIR_ERROR(dwError); } dwError = beCtx.pBE->pfnBETxnCommit(&beCtx); BAIL_ON_VMDIR_ERROR(dwError); bHasTxn = FALSE; dwError = VmDirSchemaCtxAcquire(&pSchemaCtx); BAIL_ON_VMDIR_ERROR(dwError); // open default indices for (i = 0; defIdx[i].pszAttrName; i++) { dwError = VmDirDefaultIndexCfgInit(&defIdx[i], &pIndexCfg); BAIL_ON_VMDIR_ERROR(dwError); // update attribute types in schema cache with their index info dwError = VmDirSchemaAttrNameToDescriptor( pSchemaCtx, pIndexCfg->pszAttrName, &pATDesc); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirIndexCfgGetAllScopesInStrArray( pIndexCfg, &pATDesc->ppszUniqueScopes); BAIL_ON_VMDIR_ERROR(dwError); pATDesc->dwSearchFlags |= 1; // for free later pATDesc->pLdapAt->ppszUniqueScopes = pATDesc->ppszUniqueScopes; pATDesc->pLdapAt->dwSearchFlags = pATDesc->dwSearchFlags; dwError = VmDirIndexOpen(pIndexCfg); BAIL_ON_VMDIR_ERROR(dwError); pIndexCfg = NULL; } // VMIT support dwError = VmDirIndexLibInitVMIT(); BAIL_ON_VMDIR_ERROR(dwError); dwError = InitializeIndexingThread(); BAIL_ON_VMDIR_ERROR(dwError); cleanup: if (bHasTxn) { beCtx.pBE->pfnBETxnAbort(&beCtx); } VmDirBackendCtxContentFree(&beCtx); VmDirSchemaCtxRelease(pSchemaCtx); VMDIR_SAFE_FREE_MEMORY(pszLastOffset); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError); VmDirFreeIndexCfg(pIndexCfg); goto cleanup; }
/* * merge current and patch schema * 1. if new schema defined in patch, copy them over to current schema * 2. if both current and patch schema have schema definition, use value from patch schema * * The output is merged into pCurrentEntry. */ static DWORD VmDirSchemaPatchMerge( PVDIR_ENTRY pCurrentEntry, PVDIR_ENTRY pPatchEntry ) { DWORD dwError = 0; PVDIR_SCHEMA_INSTANCE pPatchSchema = NULL; PVDIR_ATTRIBUTE pAttr = NULL; USHORT usCnt = 0; dwError = _VmDirSchemaEntryToInstance( pPatchEntry, &pPatchSchema); BAIL_ON_VMDIR_ERROR(dwError); pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_ATTRIBUTE_TYPES, pCurrentEntry ); assert( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; usCnt < pPatchSchema->ats.usNumATs; usCnt++) { PVDIR_SCHEMA_AT_DESC pATDesc = NULL; dwError = VmDirSchemaAttrNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->ats.pATSortName[ usCnt ].pszName, &pATDesc); if ( dwError == ERROR_NO_SUCH_ATTRIBUTE ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_ATTRIBUTE_TYPES, pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->ats.pATSortName[ usCnt ].pszName, pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_OBJECT_CLASSES, pCurrentEntry ); assert( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; usCnt < pPatchSchema->ocs.usNumOCs; usCnt++) { PVDIR_SCHEMA_OC_DESC pOCDesc = NULL; dwError = VmDirSchemaOCNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->ocs.pOCSortName[ usCnt ].pszName, &pOCDesc); if ( dwError == ERROR_NO_SUCH_OBJECTCLASS ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_OBJECT_CLASSES, pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->ocs.pOCSortName[ usCnt ].pszName, pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_DIT_CONTENTRULES, pCurrentEntry ); assert ( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; pAttr && usCnt < pPatchSchema->contentRules.usNumContents; usCnt++) { PVDIR_SCHEMA_CR_DESC pCRDesc = NULL; dwError = VmDirSchemaCRNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszName, &pCRDesc); if ( dwError == ERROR_NO_SUCH_DITCONTENTRULES ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_DIT_CONTENTRULES, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszName, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } cleanup: if ( pPatchSchema ) { VdirSchemaInstanceFree(pPatchSchema); } return dwError; error: goto cleanup; }