Example #1
0
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);
        }
    }
}
Example #2
0
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.");
        }
    }
}
Example #3
0
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;
}
Example #4
0
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;
}