void VmDnsUnlockWrite( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); if (!pWriteLockCount) { VMDNS_LOG_ERROR("Out of memory, can't decrement lock count."); } else { if (*pWriteLockCount ==1) { pthread_rwlock_unlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[UNLOCK WRITE] result write count is %u.\n", *pWriteLockCount); } if (*pWriteLockCount > 0) { (*pWriteLockCount)--; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[--WRITE %u]\n", *pWriteLockCount); } else { VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "Unexpected unlock write, write count is %u.\n", *pWriteLockCount); } } }
void VmDnsUnlockRead( PVMDNS_RWLOCK pLock ) { int* pWriteLockCount = VmDnsGetLockKey(&pLock->writeKey); int* pReadLockCount = VmDnsGetLockKey(&pLock->readKey); if (!pWriteLockCount || !pReadLockCount) { VMDNS_LOG_ERROR("Out of memory, can't decrement lock count."); } else { if (*pWriteLockCount > 0) { VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "Read unlock while already holding write lock."); } else { if (*pReadLockCount ==1) { pthread_rwlock_unlock(&pLock->rwLock); VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[UNLOCK READ]"); } } if (*pReadLockCount > 0) { (*pReadLockCount)--; VmDnsLog(VMDNS_LOG_LEVEL_DEBUG, "[--READ %u]\n", *pReadLockCount); } else { VmDnsLog(VMDNS_LOG_LEVEL_ERROR, "Unexpected read unlock."); } } }
static DWORD VmDnsCacheRefreshThread( PVOID pArgs ) { DWORD dwError = 0; DWORD newUSN = 0; PVMDNS_CACHE_CONTEXT pCacheContext = (PVMDNS_CACHE_CONTEXT)pArgs; pCacheContext->bRunning = TRUE; pCacheContext->dwLastUSN = 0; dwError = VmDnsStoreGetReplicationStatus(&(pCacheContext->dwLastUSN)); while (!pCacheContext->bShutdown) { if (VMDNS_READY != VmDnsSrvGetState()) { dwError = VmDnsCacheLoadInitialData(pCacheContext); if (dwError) { VMDNS_LOG_DEBUG("DnsCacheRefreshThread loading initial data failed with %u...Retrying", dwError); goto wait; } else { VMDNS_LOG_INFO("DnsCacheRefreshThread loaded initial data, setting VMDNS state to READY."); VmDnsSrvSetState(VMDNS_READY); } } newUSN = 0; VmDnsStoreGetReplicationStatus(&newUSN); if (pCacheContext->dwLastUSN != 0) { // Refresh LRU, Cache etc. dwError = VmDnsCacheSyncZones( pCacheContext->dwLastUSN, pCacheContext ); if (dwError) { VMDNS_LOG_ERROR("DnsCacheRefreshThread zone synchronization failed with %u.", dwError); } } else { VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to get replication status %u.", dwError); } if (newUSN != 0) { pCacheContext->dwLastUSN = newUSN; dwError = VmDnsCachePurgeLRU(pCacheContext); if (dwError) { VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to purge LRU cache with %u.", dwError); } } wait: if (!pCacheContext->bShutdown) { dwError = VmDnsConditionTimedWait( pCacheContext->pRefreshEvent, pCacheContext->pThreadLock, 5 * 1000 ); if (dwError != ETIMEDOUT && dwError != WSAETIMEDOUT && dwError != ERROR_SUCCESS) { VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to wait with %u. Thread DIEING.", dwError); BAIL_ON_VMDNS_ERROR(dwError); } } } cleanup: pCacheContext->bRunning = FALSE; return dwError; error: goto cleanup; }
DWORD VmDnsSockPosixWaitForEvent( PVM_SOCK_EVENT_QUEUE pQueue, int iTimeoutMS, PVM_SOCKET* ppSocket, PVM_SOCK_EVENT_TYPE pEventType, PVM_SOCK_IO_BUFFER* ppIoBuffer ) { DWORD dwError = 0; BOOLEAN bLocked = FALSE; VM_SOCK_EVENT_TYPE eventType = VM_SOCK_EVENT_TYPE_UNKNOWN; PVM_SOCKET pSocket = NULL; PVM_SOCK_IO_BUFFER pIoBuffer = NULL; PVM_SOCK_IO_CONTEXT pIoContext = NULL; uint64_t uiTriggerCount = 0; if (!pQueue || !ppSocket || !pEventType) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_POSIX_SOCK_ERROR(dwError); } dwError = VmDnsLockMutex(pQueue->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); bLocked = TRUE; if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } if ((pQueue->state == VM_SOCK_POSIX_EVENT_STATE_PROCESS) && (pQueue->iReady >= pQueue->nReady)) { pQueue->state = VM_SOCK_POSIX_EVENT_STATE_WAIT; } if (pQueue->state == VM_SOCK_POSIX_EVENT_STATE_WAIT) { pQueue->iReady = 0; pQueue->nReady = -1; while (pQueue->nReady < 0) { pQueue->nReady = epoll_wait( pQueue->epollFd, pQueue->pEventArray, pQueue->dwSize, iTimeoutMS); if ((pQueue->nReady < 0) && (errno != EINTR)) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } } pQueue->state = VM_SOCK_POSIX_EVENT_STATE_PROCESS; } if (pQueue->state == VM_SOCK_POSIX_EVENT_STATE_PROCESS) { if (pQueue->iReady < pQueue->nReady) { struct epoll_event* pEvent = &pQueue->pEventArray[pQueue->iReady]; PVM_SOCKET pEventSocket = (PVM_SOCKET)pEvent->data.ptr; if (!pEventSocket) { dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (pEvent->events & (EPOLLERR | EPOLLHUP)) { eventType = VM_SOCK_EVENT_TYPE_CONNECTION_CLOSED; pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); dwError = VmDnsSockPosixEventQueueDelete_inlock( pQueue, pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); } else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER) { switch (pEventSocket->protocol) { case VM_SOCK_PROTOCOL_TCP: dwError = VmDnsSockPosixAcceptConnection( pEventSocket, &pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); dwError = VmDnsSockPosixSetNonBlocking(pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); eventType = VM_SOCK_EVENT_TYPE_TCP_NEW_CONNECTION; break; case VM_SOCK_PROTOCOL_UDP: pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE; break; default: dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); break; } } else if (pEventSocket->type == VM_SOCK_TYPE_SERVER) { switch (pEventSocket->protocol) { case VM_SOCK_PROTOCOL_TCP: if (!pEventSocket->pData) { eventType = VM_SOCK_EVENT_TYPE_TCP_REQUEST_SIZE_READ; } pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); break; default: dwError = ERROR_INVALID_STATE; BAIL_ON_POSIX_SOCK_ERROR(dwError); break; } } else if (pEventSocket->type == VM_SOCK_TYPE_SIGNAL) { if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); } } else if (pEventSocket->type == VM_SOCK_TYPE_TIMER) { if (pQueue->bShutdown) { dwError = ERROR_SHUTDOWN_IN_PROGRESS; BAIL_ON_POSIX_SOCK_ERROR(dwError); } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); if (read(pSocket->fd, &uiTriggerCount, sizeof(uiTriggerCount)) < 0) { VMDNS_LOG_ERROR("%s: read() on timer fd failed (%d)", __FUNCTION__, errno); } eventType = VM_SOCK_EVENT_TYPE_TIMER_EXPIRATION; } } else { pSocket = VmDnsSockPosixAcquireSocket(pEventSocket); } } pQueue->iReady++; } dwError = VmDnsSockPosixSetData(pSocket, NULL, (PVOID *)&pIoBuffer); BAIL_ON_POSIX_SOCK_ERROR(dwError); if (pIoBuffer && eventType == VM_SOCK_EVENT_TYPE_UNKNOWN) { pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); eventType = pIoContext->eventType; } *ppSocket = pSocket; *ppIoBuffer = pIoBuffer; *pEventType = eventType; cleanup: if (bLocked) { VmDnsUnlockMutex(pQueue->pMutex); } return dwError; error: if (ppSocket) { *ppSocket = NULL; } if (ppIoBuffer) { *ppIoBuffer = NULL; } if (pEventType) { *pEventType = VM_SOCK_EVENT_TYPE_UNKNOWN; } if (pSocket) { VmDnsSockPosixReleaseSocket(pSocket); } goto cleanup; }