STATUS curlApiCallbacksShutdownActiveRequests()

in src/source/CurlApiCallbacks.c [386:473]


STATUS curlApiCallbacksShutdownActiveRequests(PCurlApiCallbacks pCurlApiCallbacks, STREAM_HANDLE streamHandle, UINT64 timeout, BOOL fromCurlThread,
                                              BOOL killThread)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    PCallbacksProvider pCallbacksProvider = NULL;
    BOOL requestsLocked = FALSE, hashTableEmpty = FALSE;
    PCurlRequest pCurlRequest;
    HashEntry hashEntry[STREAM_MAPPING_HASH_TABLE_BUCKET_LENGTH * STREAM_MAPPING_HASH_TABLE_BUCKET_COUNT];
    UINT32 hashEntryCount = ARRAY_SIZE(hashEntry), i;

    CHK(pCurlApiCallbacks != NULL && pCurlApiCallbacks->pCallbacksProvider != NULL, STATUS_INVALID_ARG);
    pCallbacksProvider = pCurlApiCallbacks->pCallbacksProvider;

    // Lock for exclusive operation
    pCallbacksProvider->clientCallbacks.lockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
    requestsLocked = TRUE;

    CHK_STATUS(hashTableIsEmpty(pCurlApiCallbacks->pActiveRequests, &hashTableEmpty));
    if (hashTableEmpty) {
        DLOGD("pActiveRequests hashtable is empty");

        // Early bailout
        CHK(FALSE, retStatus);
    }

    if (IS_VALID_STREAM_HANDLE(streamHandle)) {
        hashEntry[0].key = streamHandle;
        retStatus = hashTableGet(pCurlApiCallbacks->pActiveRequests, (UINT64) hashEntry[0].key, &hashEntry[0].value);
        CHK(retStatus == STATUS_HASH_KEY_NOT_PRESENT || retStatus == STATUS_SUCCESS, retStatus);
        if (retStatus == STATUS_HASH_KEY_NOT_PRESENT) {
            CHK(FALSE, STATUS_SUCCESS);
        }
        hashEntryCount = 1;
    } else {
        // is stream handle is invalid stream handle then delete all active requests.
        CHK_STATUS(hashTableGetAllEntries(pCurlApiCallbacks->pActiveRequests, hashEntry, &hashEntryCount));
    }

    for (i = 0; i < hashEntryCount; ++i) {
        // We have the request
        pCurlRequest = (PCurlRequest) hashEntry[i].value;

        // if killThread is true and we have attempted to terminate curl and curl thread is still blocked inside
        // curl call, then kill the thread.
        if (killThread && ATOMIC_LOAD_BOOL(&pCurlRequest->requestInfo.terminating)) {
            if (ATOMIC_LOAD_BOOL(&pCurlRequest->blockedInCurl)) {
                THREAD_CANCEL(pCurlRequest->threadId);
            }

        } else if (!fromCurlThread) {
            // Set the terminating status on the request
            ATOMIC_STORE_BOOL(&pCurlRequest->requestInfo.terminating, TRUE);

            if (ATOMIC_LOAD_BOOL(&pCurlRequest->blockedInCurl)) {
                // Terminate the curl request in flight
                terminateCurlSession(pCurlRequest->pCurlResponse, timeout);
            }
        }

        // if fromCurlThread is true then nothing needs to be done since this function is called right before the
        // curl thread terminates.
        if (fromCurlThread || (killThread && ATOMIC_LOAD_BOOL(&pCurlRequest->requestInfo.terminating))) {
            // if curlApiCallbacksShutdownActiveRequests is being called by curl thread, then free all resources
            // and the curl thread will then exit. Otherwise also free when we explicitly kill the thread.
            CHK_STATUS(hashTableRemove(pCurlApiCallbacks->pActiveRequests, (UINT64) streamHandle));

            // Free the request object
            CHK_STATUS(freeCurlRequest(&pCurlRequest));
        }
    }

    // No longer need to hold the lock to the requests
    pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
    requestsLocked = FALSE;

CleanUp:

    CHK_LOG_ERR(retStatus);

    // Unlock only if previously locked
    if (requestsLocked) {
        pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->activeRequestsLock);
    }

    LEAVES();
    return retStatus;
}