STATUS getStreamingEndpointCachingCurl()

in src/source/CurlApiCallbacks.c [1556:1639]


STATUS getStreamingEndpointCachingCurl(UINT64 customData, PCHAR streamName, PCHAR apiName, PServiceCallContext pServiceCallContext)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    PCurlApiCallbacks pCurlApiCallbacks = (PCurlApiCallbacks) customData;
    PCallbacksProvider pCallbacksProvider = NULL;
    UINT64 curTime, value;
    STREAM_HANDLE streamHandle;
    PEndpointTracker pEndpointTracker = NULL;
    BOOL endpointsLocked = FALSE, emulateApiCall = TRUE;

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

    streamHandle = (STREAM_HANDLE) pServiceCallContext->customData;

    // We check whether we have already made the call by checking
    // for the presence of the endpoint in the cache.
    switch (pCurlApiCallbacks->cacheType) {
        case API_CALL_CACHE_TYPE_NONE:
            emulateApiCall = FALSE;
            break;

        case API_CALL_CACHE_TYPE_ENDPOINT_ONLY:
            // Explicit fall-through

        case API_CALL_CACHE_TYPE_ALL:
            pCallbacksProvider->clientCallbacks.lockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->cachedEndpointsLock);
            endpointsLocked = TRUE;

            // Attempt to retrieve the cached value
            retStatus = hashTableGet(pCurlApiCallbacks->pCachedEndpoints, (UINT64) streamHandle, &value);

            CHK(retStatus == STATUS_HASH_KEY_NOT_PRESENT || retStatus == STATUS_SUCCESS, retStatus);

            if (retStatus == STATUS_HASH_KEY_NOT_PRESENT) {
                emulateApiCall = FALSE;

                // Reset the status if not found
                retStatus = STATUS_SUCCESS;
            } else {
                pEndpointTracker = (PEndpointTracker) value;
                curTime = pCallbacksProvider->clientCallbacks.getCurrentTimeFn(pCallbacksProvider->clientCallbacks.customData);

                if (pEndpointTracker == NULL || pEndpointTracker->streamingEndpoint[0] == '\0' ||
                    pEndpointTracker->endpointLastUpdateTime + pCurlApiCallbacks->cacheUpdatePeriod <= curTime) {
                    emulateApiCall = FALSE;
                }
            }

            break;
    }

    // Force the get endpoint call if we have no up-to-date info
    if (!emulateApiCall) {
        // No longer need to hold the endpoint lock
        if (endpointsLocked) {
            pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->cachedEndpointsLock);
            endpointsLocked = FALSE;
        }

        CHK_STATUS(getStreamingEndpointCurl(customData, streamName, apiName, pServiceCallContext));

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

    DLOGV("Caching GetStreamingEndpoint API call");

    // At this stage we should be holding the lock
    CHECK(endpointsLocked);
    retStatus = getStreamingEndpointResultEvent(streamHandle, SERVICE_CALL_RESULT_OK, pEndpointTracker->streamingEndpoint);

    notifyCallResult(pCallbacksProvider, retStatus, streamHandle);

CleanUp:

    if (endpointsLocked) {
        pCallbacksProvider->clientCallbacks.unlockMutexFn(pCallbacksProvider->clientCallbacks.customData, pCurlApiCallbacks->cachedEndpointsLock);
    }

    LEAVES();
    return retStatus;
}