static void ASYNC_RETRY_WRAPPER_RETRY_FUNC()

in inc/c_util/async_retry_wrapper.h [383:455]


    static void ASYNC_RETRY_WRAPPER_RETRY_FUNC(async_function_name)(void* context) \
    { \
        if (context == NULL) \
        { \
            LogCriticalAndTerminate("NULL context for " MU_TOSTRING(async_function_name) " do retry function"); \
        } \
        else \
        { \
            ASYNC_RETRY_WRAPPER_CONTEXT(async_function_name)* retry_context = context; \
            return_type temp_async_function_result; \
            bool timed_out = false; \
            do \
            { \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_023: [ {async_function_name}_do_retry shall call the function async_function_name, passing the in_args that have been copied to the retry context with the exception of ARG_CB(...) and ARG_CONTEXT(...) which are instead passed as the generated callback handler and the allocated context. ]*/ \
                temp_async_function_result = async_function_name(retry_context->handle ASYNC_RETRY_WRAPPER_ARGS_IN_CALL(in_args), ASYNC_RETRY_WRAPPER_CALLBACK(async_function_name), retry_context); \
                if (ASYNC_RETRY_WRAPPER_RETRY_CONDITIONS_PROXY(retry_sync_enums)) \
                { \
                    if (retry_context->timeout_ms < UINT32_MAX) \
                    { \
                        /*Codes_SRS_ASYNC_RETRY_WRAPPER_02_001: [ Before each retry of the function, if timeout_ms milliseconds have elapsed since the initial call to ASYNC_RETRY_WRAPPER(async_function_name) then {async_function_name}_async_retry_wrapper_with_timeout shall call shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), the error_value from all of the ARG(type, name, error_value)'s in out_args. and the timeout_error_value for the ENUM(...) argument. ]*/ \
                        double elapsed_time_ms = timer_global_get_elapsed_ms() - retry_context->start_time; \
                        LogInfo("elapsed_time_ms=%lf + retry_context->backoff=%" PRIu32 " > retry_context->timeout_ms=%" PRIu32 "", \
                            elapsed_time_ms, retry_context->backoff, retry_context->timeout_ms); \
                        if (elapsed_time_ms + retry_context->backoff > retry_context->timeout_ms) \
                        { \
                            timed_out = true; \
                            LogError("Retries for " MU_TOSTRING(async_function_name) " timed out after %lf ms (including %" PRIu32 " ms of backoff) (timeout time was %" PRIu32 " ms)", \
                                elapsed_time_ms, retry_context->backoff, retry_context->timeout_ms); \
                            break; \
                        } \
                    } \
                    /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_045: [ Before each retry of the function, {async_function_name}_do_retry shall yield execution by a call to ThreadAPI_Sleep. ]*/ \
                    ThreadAPI_Sleep(retry_context->backoff); \
                    retry_context->backoff *= 2; \
                    if (retry_context->backoff > ASYNC_RETRY_WRAPPER_MAX_BACKOFF_MS) \
                    { \
                        retry_context->backoff = ASYNC_RETRY_WRAPPER_MAX_BACKOFF_MS; \
                    } \
                } \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_040: [ While async_function_name returns one of the values from RETRY_ON_SYNC(...), it shall be called again in a loop. ]*/ \
            } while (ASYNC_RETRY_WRAPPER_RETRY_CONDITIONS_PROXY(retry_sync_enums)); \
            if (timed_out) \
            { \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_041: [ If async_function_name returns a value other than expected_return then: ]*/ \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_025: [ {async_function_name}_do_retry shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), and the error_value from all of the ARG(type, name, error_value)'s in out_args. ]*/ \
                retry_context->user_captured_callback(retry_context->user_captured_callback_context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_FOR_CALL_WITH_TIMEOUT_PROXY(out_args)); \
                ASYNC_RETRY_WRAPPER_FREE_FIELDS_PROXY(in_args); \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_11_001: [ on_{async_function_name}_complete shall assign the threadpool to NULL. ]*/ \
                THANDLE_ASSIGN(THREADPOOL)(&retry_context->threadpool, NULL); \
                /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_028: [ {async_function_name}_do_retry shall free the allocated context. ]*/ \
                free(retry_context); \
            } \
            else \
            { \
                if (temp_async_function_result != expected_return) \
                { \
                    /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_041: [ If async_function_name returns a value other than expected_return then: ]*/ \
                    LogError(MU_TOSTRING(async_function_name) " failed during retry"); \
                    /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_025: [ {async_function_name}_do_retry shall call the user callback specified in ARG_CB(...), passing the context from ARG_CONTEXT(...), and the error_value from all of the ARG(type, name, error_value)'s in out_args. ]*/ \
                    retry_context->user_captured_callback(retry_context->user_captured_callback_context ASYNC_RETRY_WRAPPER_CALLBACK_ARGS_FOR_CALL_WITH_ERROR_PROXY(out_args)); \
                    ASYNC_RETRY_WRAPPER_FREE_FIELDS_PROXY(in_args); \
                    /*Codes_SRS_ASYNC_RETRY_WRAPPER_11_001: [ on_{async_function_name}_complete shall assign the threadpool to NULL. ]*/ \
                    THANDLE_ASSIGN(THREADPOOL)(&retry_context->threadpool, NULL); \
                    /*Codes_SRS_ASYNC_RETRY_WRAPPER_42_028: [ {async_function_name}_do_retry shall free the allocated context. ]*/ \
                    free(retry_context); \
                } \
                else \
                { \
                    /* Retry attempted, callback will be called */ \
                } \
            } \
        } \
    }