DWORD InitializeIndexingThread( VOID ) { DWORD dwError = 0; dwError = VmDirSrvThrInit( &gVdirIndexGlobals.pThrInfo, gVdirIndexGlobals.mutex, gVdirIndexGlobals.cond, TRUE); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirCreateThread( &gVdirIndexGlobals.pThrInfo->tid, gVdirIndexGlobals.pThrInfo->bJoinThr, VmDirIndexingThreadFun, gVdirIndexGlobals.pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: goto cleanup; }
static DWORD VmDirPagedSearchCreateThread( PVDIR_PAGED_SEARCH_RECORD pSearchRecord ) { DWORD dwError = 0; PVDIR_THREAD_INFO pThrInfo = NULL; dwError = VmDirSrvThrInit(&pThrInfo, NULL, NULL, FALSE); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirCreateThread( &pThrInfo->tid, pThrInfo->bJoinThr, _VmDirPagedSearchWorkerThread, pSearchRecord); BAIL_ON_VMDIR_ERROR(dwError); pSearchRecord->pThreadInfo = pThrInfo; cleanup: return dwError; error: VmDirSrvThrFree(pThrInfo); goto cleanup; }
DWORD VmDirInitDCConnThread( PVMDIR_DC_CONNECTION pDCConn ) { DWORD dwError = 0; VMDIR_THREAD threadId = {0}; if (!pDCConn) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } dwError = VmDirCreateThread( &threadId, FALSE, // no thread join _VmDirDCConnThreadFun, pDCConn); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s failed, error %d", __FUNCTION__, dwError); goto cleanup; }
DWORD VmDirInitRidSynchThr( PVDIR_THREAD_INFO* ppThrInfo ) { DWORD dwError = 0; PVDIR_THREAD_INFO pThrInfo = NULL; dwError = VmDirAllocateMemory( sizeof(*pThrInfo), (PVOID)&pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrInit( pThrInfo, NULL, NULL, TRUE); // join by main thr dwError = VmDirCreateThread( &pThrInfo->tid, FALSE, _VmDirRidSyncThr, pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrAdd(pThrInfo); *ppThrInfo = pThrInfo; cleanup: return dwError; error: if (pThrInfo) { VmDirSrvThrFree(pThrInfo); } goto cleanup; }
DWORD InitializeDbChkpointThread( VOID) { DWORD dwError = 0; PVDIR_THREAD_INFO pThrInfo = NULL; dwError = VmDirAllocateMemory( sizeof(*pThrInfo), (PVOID)&pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrInit( pThrInfo, NULL, NULL, TRUE); // join by main thr dwError = VmDirCreateThread( &pThrInfo->tid, FALSE, VmDirBdbCheckpointThrFun, pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrAdd(pThrInfo); cleanup: return (int)dwError; //TODO, should not cast error: if (pThrInfo) { VmDirSrvThrFree(pThrInfo); } goto cleanup; }
DWORD InitializeIndexingThread( void) { DWORD dwError = 0; PVDIR_THREAD_INFO pThrInfo = NULL; dwError = VmDirAllocateMemory( sizeof(*pThrInfo), (PVOID)&pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrInit( pThrInfo, gVdirAttrIndexGlobals.mutex, // alternative mutex gVdirAttrIndexGlobals.condition, // alternative cond TRUE); // join by main thr dwError = VmDirCreateThread( &pThrInfo->tid, FALSE, vdirIndexingThrFun, pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrAdd(pThrInfo); cleanup: return dwError; error: if (pThrInfo) { VmDirSrvThrFree(pThrInfo); } goto cleanup; }
static DWORD vmdirConnAccept( Sockbuf_IO* pSockbuf_IO, DWORD dwPort, BOOLEAN bIsLdaps ) { ber_socket_t newsockfd = -1; int retVal = LDAP_SUCCESS; ber_socket_t ip4_fd = -1; ber_socket_t ip6_fd = -1; ber_socket_t max_fd = -1; VMDIR_THREAD threadId; BOOLEAN bInLock = FALSE; int iLocalLogMask = 0; PVDIR_CONNECTION_CTX pConnCtx = NULL; fd_set event_fd_set; fd_set poll_fd_set; struct timeval timeout = {0}; // Wait for ***1st*** replication cycle to be over. if (gVmdirServerGlobals.serverId == 0) // instance has not been initialized { VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Connection accept thread: Have NOT yet started listening on LDAP port (%u)," " waiting for the 1st replication cycle to be over.", dwPort); VMDIR_LOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); // wait till 1st replication cycle is over if (VmDirConditionWait( gVmdirGlobals.replCycleDoneCondition, gVmdirGlobals.replCycleDoneMutex ) != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "Connection accept thread: VmDirConditionWait failed." ); retVal = LDAP_OPERATIONS_ERROR; goto cleanup; } // also wake up the other (normal LDAP port/SSL LDAP port listner) LDAP connection accept thread, // waiting on 1st replication cycle to be over // BUGBUG Does not handle spurious wake up VmDirConditionSignal(gVmdirGlobals.replCycleDoneCondition); VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) // Asked to shutdown before we started accepting { goto cleanup; } VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Connection accept thread: listening on LDAP port (%u).", dwPort); } iLocalLogMask = VmDirLogGetMask(); ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &iLocalLogMask); SetupLdapPort(dwPort, &ip4_fd, &ip6_fd); if (ip4_fd < 0 && ip6_fd < 0) { VmDirSleep(1000); goto cleanup; } FD_ZERO(&event_fd_set); if (ip4_fd >= 0) { FD_SET (ip4_fd, &event_fd_set); if (ip4_fd > max_fd) { max_fd = ip4_fd; } } if (ip6_fd >= 0) { FD_SET (ip6_fd, &event_fd_set); if (ip6_fd > max_fd) { max_fd = ip6_fd; } } retVal = VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter); if (retVal != 0 ) { VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "%s: VmDirSyncCounterIncrement(gVmdirGlobals.pPortListenSyncCounter) returned error", __func__); BAIL_ON_VMDIR_ERROR(retVal); } while (TRUE) { if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) { goto cleanup; } poll_fd_set = event_fd_set; timeout.tv_sec = 3; timeout.tv_usec = 0; retVal = select ((int)max_fd+1, &poll_fd_set, NULL, NULL, &timeout); if (retVal < 0 ) { #ifdef _WIN32 errno = WSAGetLastError(); #endif VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: select() (port %d) call failed: %d.", __func__, dwPort, errno); VmDirSleep( 1000 ); continue; } else if (retVal == 0) { //VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() timeout (port %d)", __func__, dwPort); continue; } if (ip4_fd >= 0 && FD_ISSET(ip4_fd, &poll_fd_set)) { newsockfd = accept(ip4_fd, (struct sockaddr *) NULL, NULL); } else if (ip6_fd >= 0 && FD_ISSET(ip6_fd, &poll_fd_set)) { newsockfd = accept(ip6_fd, (struct sockaddr *) NULL, NULL); } else { VMDIR_LOG_INFO( LDAP_DEBUG_CONNS, "%s: select() returned with no data (port %d), return: %d", __func__, dwPort, retVal); continue; } if (newsockfd < 0) { #ifdef _WIN32 errno = WSAGetLastError(); #endif if (errno != EAGAIN && errno != EWOULDBLOCK ) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: accept() (port %d) failed with errno: %d.", __func__, dwPort, errno ); } continue; } if ( _VmDirFlowCtrlThrEnter() == TRUE ) { tcp_close(newsockfd); newsockfd = -1; VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "Maxmimum number of concurrent LDAP threads reached. Blocking new connection" ); continue; } retVal = VmDirAllocateMemory( sizeof(VDIR_CONNECTION_CTX), (PVOID*)&pConnCtx); BAIL_ON_VMDIR_ERROR(retVal); pConnCtx->sockFd = newsockfd; newsockfd = -1; pConnCtx->pSockbuf_IO = pSockbuf_IO; retVal = VmDirCreateThread(&threadId, TRUE, ProcessAConnection, (PVOID)pConnCtx); if (retVal != 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: VmDirCreateThread() (port) failed with errno: %d", __func__, dwPort, errno ); tcp_close(pConnCtx->sockFd); _VmDirFlowCtrlThrExit(); VMDIR_SAFE_FREE_MEMORY(pConnCtx); continue; } else { pConnCtx = NULL; //thread take ownership on pConnCtx VmDirFreeVmDirThread(&threadId); } } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVmdirGlobals.replCycleDoneMutex); if (ip4_fd >= 0) { tcp_close(ip4_fd); } if (ip6_fd >= 0) { tcp_close(ip6_fd); } if (newsockfd >= 0) { tcp_close(newsockfd); } #ifndef _WIN32 raise(SIGTERM); #endif VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "%s: Connection accept thread: stop (port %d)", __func__, dwPort); return retVal; error: goto cleanup; }
DWORD VmDirInitConnAcceptThread( void ) { DWORD dwError = 0; PDWORD pdwLdapPorts = NULL; DWORD dwLdapPorts = 0; PDWORD pdwLdapsPorts = NULL; DWORD dwLdapsPorts = 0; PVDIR_THREAD_INFO pThrInfo = NULL; PDWORD pdwPort = NULL; DWORD i = 0; BOOLEAN isIPV6AddressPresent = FALSE; BOOLEAN isIPV4AddressPresent = FALSE; dwError = VmDirWhichAddressPresent(&isIPV4AddressPresent, &isIPV6AddressPresent); BAIL_ON_VMDIR_ERROR(dwError); if (isIPV4AddressPresent) { gVmdirServerGlobals.isIPV4AddressPresent = TRUE; } if (isIPV6AddressPresent) { gVmdirServerGlobals.isIPV6AddressPresent = TRUE; } VmDirGetLdapListenPorts(&pdwLdapPorts, &dwLdapPorts); VmDirGetLdapsListenPorts(&pdwLdapsPorts, &dwLdapsPorts); for (i = 0; i < dwLdapPorts; i++) { dwError = VmDirAllocateMemory( sizeof(*pThrInfo), (PVOID*)&pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( sizeof(DWORD), (PVOID)&pdwPort); BAIL_ON_VMDIR_ERROR(dwError); *pdwPort = pdwLdapPorts[i]; VmDirSrvThrInit( pThrInfo, gVmdirGlobals.replCycleDoneMutex, // alternative mutex gVmdirGlobals.replCycleDoneCondition, // alternative cond FALSE); // join by main thr dwError = VmDirCreateThread( &pThrInfo->tid, FALSE, vmdirConnAcceptThrFunc, (PVOID)pdwPort); // New thread owns pdwPort BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrAdd(pThrInfo); pThrInfo = NULL; pdwPort = NULL; } for (i = 0; gVmdirOpensslGlobals.bSSLInitialized && i < dwLdapsPorts; i++) { dwError = VmDirAllocateMemory( sizeof(*pThrInfo), (PVOID*)&pThrInfo); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( sizeof(DWORD), (PVOID)&pdwPort); BAIL_ON_VMDIR_ERROR(dwError); *pdwPort = pdwLdapsPorts[i]; VmDirSrvThrInit( pThrInfo, gVmdirGlobals.replCycleDoneMutex, // alternative mutex gVmdirGlobals.replCycleDoneCondition, // alternative cond FALSE); // join by main thr dwError = VmDirCreateThread( &pThrInfo->tid, FALSE, vmdirSSLConnAcceptThrFunc, (PVOID)pdwPort); BAIL_ON_VMDIR_ERROR(dwError); VmDirSrvThrAdd(pThrInfo); pThrInfo = NULL; pdwPort = NULL; } cleanup: return dwError; error: if (pThrInfo) { VmDirSrvThrFree(pThrInfo); } VMDIR_SAFE_FREE_MEMORY(pdwPort); goto cleanup; }
/* * This thread waits on gVdirAttrIndexGlobals.condition and spawns worker thread * to perform indexing in the back ground. */ static DWORD vdirIndexingThrFun( PVOID pArg ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; PVDIR_CFG_ATTR_INDEX_DESC* ppIndexDesc = NULL; PVDIR_THREAD_INFO pThrInfo = (PVDIR_THREAD_INFO)pArg; while (1) { DWORD dwCnt = 0; DWORD dwSize = 0; VMDIR_THREAD tid = {0}; PVDIR_ATTR_INDEX_INSTANCE pCache = NULL; memset(&tid, 0, sizeof(tid)); // wait till new indices are created VMDIR_LOCK_MUTEX(bInLock, gVdirAttrIndexGlobals.mutex); dwError = VmDirConditionWait( pThrInfo->conditionUsed, pThrInfo->mutexUsed); BAIL_ON_VMDIR_ERROR(dwError); // get new cache we want to enable pCache = gVdirAttrIndexGlobals.pNewCache; VMDIR_UNLOCK_MUTEX(bInLock, gVdirAttrIndexGlobals.mutex); if (VmDirdState() == VMDIRD_STATE_SHUTDOWN) { break; } if (!pCache) { continue; } // get number of indices in building status for (dwCnt = 0, dwSize = 0; dwCnt < pCache->usNumIndex; dwCnt++) { if (pCache->pSortName[dwCnt].status == VDIR_CFG_ATTR_INDEX_BUILDING) { dwSize++; } } if (dwSize == 0) { continue; } dwError = VmDirAllocateMemory( sizeof(PVDIR_CFG_ATTR_INDEX_DESC) * (dwSize + 1), // +1 for NULL ending (PVOID)&ppIndexDesc); BAIL_ON_VMDIR_ERROR(dwError); // fill ppIndexDesc with building index // NOTE, ppIndexDesc does NOT own them; pCache does. for (dwCnt = 0, dwSize = 0; dwCnt < pCache->usNumIndex; dwCnt++) { if (pCache->pSortName[dwCnt].status == VDIR_CFG_ATTR_INDEX_BUILDING) { ppIndexDesc[dwSize] = &pCache->pSortName[dwCnt]; dwSize++; } } // TODO, detach thr now, need to join to safely finish bdb io... dwError = VmDirCreateThread( &tid, TRUE, vdirIndexingWorkerThrFun, (PVOID)ppIndexDesc); BAIL_ON_VMDIR_ERROR(dwError); // worker takes over ppIndexDesc. ppIndexDesc = NULL; VmDirFreeVmDirThread(&tid); } cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVdirAttrIndexGlobals.mutex); // TODO: should be dwError? return 0; error: VMDIR_SAFE_FREE_MEMORY(ppIndexDesc); //TODO, should we stop vmdird? VmDirLog( LDAP_DEBUG_ANY, "VmdirIndexingThr: error stop" ); goto cleanup; }