Microsoft Azure IoTHub client AMQP transport
Dependents: sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more
This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks
message_queue.c@57:56ac1346c70d, 2018-10-04 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Thu Oct 04 09:14:47 2018 -0700
- Revision:
- 57:56ac1346c70d
- Parent:
- 56:8704100b3b54
1.2.10
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AzureIoTClient | 39:e98d5df6dc74 | 1 | // Copyright (c) Microsoft. All rights reserved. |
AzureIoTClient | 39:e98d5df6dc74 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
AzureIoTClient | 39:e98d5df6dc74 | 3 | |
AzureIoTClient | 39:e98d5df6dc74 | 4 | #include <stdlib.h> |
AzureIoTClient | 39:e98d5df6dc74 | 5 | #include <stdbool.h> |
AzureIoTClient | 39:e98d5df6dc74 | 6 | #include "azure_c_shared_utility/optimize_size.h" |
AzureIoTClient | 39:e98d5df6dc74 | 7 | #include "azure_c_shared_utility/crt_abstractions.h" |
AzureIoTClient | 39:e98d5df6dc74 | 8 | #include "azure_c_shared_utility/gballoc.h" |
AzureIoTClient | 56:8704100b3b54 | 9 | #include "azure_c_shared_utility/agenttime.h" |
AzureIoTClient | 39:e98d5df6dc74 | 10 | #include "azure_c_shared_utility/xlogging.h" |
AzureIoTClient | 39:e98d5df6dc74 | 11 | #include "azure_c_shared_utility/singlylinkedlist.h" |
AzureIoTClient | 39:e98d5df6dc74 | 12 | |
AzureIoTClient | 39:e98d5df6dc74 | 13 | typedef struct MESSAGE_QUEUE_TAG MESSAGE_QUEUE; |
AzureIoTClient | 39:e98d5df6dc74 | 14 | |
AzureIoTClient | 53:e21e1e88460f | 15 | #include "internal/message_queue.h" |
AzureIoTClient | 39:e98d5df6dc74 | 16 | |
AzureIoTClient | 39:e98d5df6dc74 | 17 | #define RESULT_OK 0 |
AzureIoTClient | 39:e98d5df6dc74 | 18 | #define INDEFINITE_TIME ((time_t)(-1)) |
AzureIoTClient | 39:e98d5df6dc74 | 19 | |
AzureIoTClient | 39:e98d5df6dc74 | 20 | static const char* SAVED_OPTION_MAX_RETRY_COUNT = "SAVED_OPTION_MAX_RETRY_COUNT"; |
AzureIoTClient | 39:e98d5df6dc74 | 21 | static const char* SAVED_OPTION_MAX_ENQUEUE_TIME_SECS = "SAVED_OPTION_MAX_ENQUEUE_TIME_SECS"; |
AzureIoTClient | 39:e98d5df6dc74 | 22 | static const char* SAVED_OPTION_MAX_PROCESSING_TIME_SECS = "SAVED_OPTION_MAX_PROCESSING_TIME_SECS"; |
AzureIoTClient | 39:e98d5df6dc74 | 23 | |
AzureIoTClient | 39:e98d5df6dc74 | 24 | |
AzureIoTClient | 39:e98d5df6dc74 | 25 | struct MESSAGE_QUEUE_TAG |
AzureIoTClient | 39:e98d5df6dc74 | 26 | { |
AzureIoTClient | 39:e98d5df6dc74 | 27 | size_t max_message_enqueued_time_secs; |
AzureIoTClient | 39:e98d5df6dc74 | 28 | size_t max_message_processing_time_secs; |
AzureIoTClient | 39:e98d5df6dc74 | 29 | size_t max_retry_count; |
AzureIoTClient | 39:e98d5df6dc74 | 30 | |
AzureIoTClient | 39:e98d5df6dc74 | 31 | PROCESS_MESSAGE_CALLBACK on_process_message_callback; |
AzureIoTClient | 39:e98d5df6dc74 | 32 | void* on_process_message_context; |
AzureIoTClient | 39:e98d5df6dc74 | 33 | |
AzureIoTClient | 39:e98d5df6dc74 | 34 | SINGLYLINKEDLIST_HANDLE pending; |
AzureIoTClient | 39:e98d5df6dc74 | 35 | SINGLYLINKEDLIST_HANDLE in_progress; |
AzureIoTClient | 39:e98d5df6dc74 | 36 | }; |
AzureIoTClient | 39:e98d5df6dc74 | 37 | |
AzureIoTClient | 39:e98d5df6dc74 | 38 | typedef struct MESSAGE_QUEUE_ITEM_TAG |
AzureIoTClient | 39:e98d5df6dc74 | 39 | { |
AzureIoTClient | 39:e98d5df6dc74 | 40 | MQ_MESSAGE_HANDLE message; |
AzureIoTClient | 39:e98d5df6dc74 | 41 | MESSAGE_PROCESSING_COMPLETED_CALLBACK on_message_processing_completed_callback; |
AzureIoTClient | 39:e98d5df6dc74 | 42 | void* user_context; |
AzureIoTClient | 39:e98d5df6dc74 | 43 | time_t enqueue_time; |
AzureIoTClient | 39:e98d5df6dc74 | 44 | time_t processing_start_time; |
AzureIoTClient | 39:e98d5df6dc74 | 45 | size_t number_of_attempts; |
AzureIoTClient | 39:e98d5df6dc74 | 46 | } MESSAGE_QUEUE_ITEM; |
AzureIoTClient | 39:e98d5df6dc74 | 47 | |
AzureIoTClient | 39:e98d5df6dc74 | 48 | |
AzureIoTClient | 39:e98d5df6dc74 | 49 | |
AzureIoTClient | 39:e98d5df6dc74 | 50 | // ---------- Helper Functions ---------- // |
AzureIoTClient | 39:e98d5df6dc74 | 51 | |
AzureIoTClient | 39:e98d5df6dc74 | 52 | static bool find_item_by_message_ptr(LIST_ITEM_HANDLE list_item, const void* match_context) |
AzureIoTClient | 39:e98d5df6dc74 | 53 | { |
AzureIoTClient | 39:e98d5df6dc74 | 54 | MESSAGE_QUEUE_ITEM* current_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 55 | MQ_MESSAGE_HANDLE* target_item = (MQ_MESSAGE_HANDLE*)match_context; |
AzureIoTClient | 39:e98d5df6dc74 | 56 | |
AzureIoTClient | 39:e98d5df6dc74 | 57 | return (current_item->message == target_item); |
AzureIoTClient | 39:e98d5df6dc74 | 58 | } |
AzureIoTClient | 39:e98d5df6dc74 | 59 | |
AzureIoTClient | 39:e98d5df6dc74 | 60 | static void fire_message_callback(MESSAGE_QUEUE_ITEM* mq_item, MESSAGE_QUEUE_RESULT result, void* reason) |
AzureIoTClient | 39:e98d5df6dc74 | 61 | { |
AzureIoTClient | 39:e98d5df6dc74 | 62 | if (mq_item->on_message_processing_completed_callback != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 63 | { |
AzureIoTClient | 39:e98d5df6dc74 | 64 | if (result == MESSAGE_QUEUE_RETRYABLE_ERROR) |
AzureIoTClient | 39:e98d5df6dc74 | 65 | { |
AzureIoTClient | 39:e98d5df6dc74 | 66 | result = MESSAGE_QUEUE_ERROR; |
AzureIoTClient | 39:e98d5df6dc74 | 67 | } |
AzureIoTClient | 39:e98d5df6dc74 | 68 | |
AzureIoTClient | 39:e98d5df6dc74 | 69 | mq_item->on_message_processing_completed_callback(mq_item->message, result, reason, mq_item->user_context); |
AzureIoTClient | 39:e98d5df6dc74 | 70 | } |
AzureIoTClient | 39:e98d5df6dc74 | 71 | } |
AzureIoTClient | 39:e98d5df6dc74 | 72 | |
AzureIoTClient | 39:e98d5df6dc74 | 73 | static bool should_retry_sending(MESSAGE_QUEUE_HANDLE message_queue, MESSAGE_QUEUE_ITEM* mq_item, MESSAGE_QUEUE_RESULT result) |
AzureIoTClient | 39:e98d5df6dc74 | 74 | { |
AzureIoTClient | 39:e98d5df6dc74 | 75 | return (result == MESSAGE_QUEUE_RETRYABLE_ERROR && mq_item->number_of_attempts <= message_queue->max_retry_count); |
AzureIoTClient | 39:e98d5df6dc74 | 76 | } |
AzureIoTClient | 39:e98d5df6dc74 | 77 | |
AzureIoTClient | 39:e98d5df6dc74 | 78 | static int retry_sending_message(MESSAGE_QUEUE_HANDLE message_queue, LIST_ITEM_HANDLE list_item) |
AzureIoTClient | 39:e98d5df6dc74 | 79 | { |
AzureIoTClient | 39:e98d5df6dc74 | 80 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 81 | MESSAGE_QUEUE_ITEM* mq_item; |
AzureIoTClient | 56:8704100b3b54 | 82 | |
AzureIoTClient | 39:e98d5df6dc74 | 83 | mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 84 | |
AzureIoTClient | 39:e98d5df6dc74 | 85 | if (singlylinkedlist_remove(message_queue->in_progress, list_item)) |
AzureIoTClient | 39:e98d5df6dc74 | 86 | { |
AzureIoTClient | 39:e98d5df6dc74 | 87 | LogError("Failed removing message from in-progress list"); |
AzureIoTClient | 39:e98d5df6dc74 | 88 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 89 | } |
AzureIoTClient | 39:e98d5df6dc74 | 90 | else if (singlylinkedlist_add(message_queue->pending, (const void*)mq_item) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 91 | { |
AzureIoTClient | 39:e98d5df6dc74 | 92 | LogError("Failed moving message back to pending list"); |
AzureIoTClient | 39:e98d5df6dc74 | 93 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 94 | } |
AzureIoTClient | 39:e98d5df6dc74 | 95 | else |
AzureIoTClient | 39:e98d5df6dc74 | 96 | { |
AzureIoTClient | 39:e98d5df6dc74 | 97 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 98 | } |
AzureIoTClient | 39:e98d5df6dc74 | 99 | |
AzureIoTClient | 39:e98d5df6dc74 | 100 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 101 | } |
AzureIoTClient | 39:e98d5df6dc74 | 102 | |
AzureIoTClient | 39:e98d5df6dc74 | 103 | static void dequeue_message_and_fire_callback(SINGLYLINKEDLIST_HANDLE list, LIST_ITEM_HANDLE list_item, MESSAGE_QUEUE_RESULT result, void* reason) |
AzureIoTClient | 39:e98d5df6dc74 | 104 | { |
AzureIoTClient | 39:e98d5df6dc74 | 105 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 106 | |
AzureIoTClient | 39:e98d5df6dc74 | 107 | // Codes_SRS_MESSAGE_QUEUE_09_045: [If `message` is present in `message_queue->in_progress`, it shall be removed] |
AzureIoTClient | 39:e98d5df6dc74 | 108 | if (singlylinkedlist_remove(list, list_item)) |
AzureIoTClient | 39:e98d5df6dc74 | 109 | { |
AzureIoTClient | 39:e98d5df6dc74 | 110 | LogError("failed removing message from list (%p)", list); |
AzureIoTClient | 39:e98d5df6dc74 | 111 | } |
AzureIoTClient | 56:8704100b3b54 | 112 | |
AzureIoTClient | 39:e98d5df6dc74 | 113 | // Codes_SRS_MESSAGE_QUEUE_09_049: [Otherwise `mq_item->on_message_processing_completed_callback` shall be invoked passing `mq_item->message`, `result`, `reason` and `mq_item->user_context`] |
AzureIoTClient | 39:e98d5df6dc74 | 114 | fire_message_callback(mq_item, result, reason); |
AzureIoTClient | 39:e98d5df6dc74 | 115 | |
AzureIoTClient | 39:e98d5df6dc74 | 116 | // Codes_SRS_MESSAGE_QUEUE_09_050: [The `mq_item` related to `message` shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 117 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 118 | } |
AzureIoTClient | 39:e98d5df6dc74 | 119 | |
AzureIoTClient | 39:e98d5df6dc74 | 120 | static void on_process_message_completed_callback(MESSAGE_QUEUE_HANDLE message_queue, MQ_MESSAGE_HANDLE message, MESSAGE_QUEUE_RESULT result, USER_DEFINED_REASON reason) |
AzureIoTClient | 39:e98d5df6dc74 | 121 | { |
AzureIoTClient | 39:e98d5df6dc74 | 122 | // Codes_SRS_MESSAGE_QUEUE_09_069: [If `message` or `message_queue` are NULL, on_message_processing_completed_callback shall return immediately] |
AzureIoTClient | 39:e98d5df6dc74 | 123 | if (message == NULL || message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 124 | { |
AzureIoTClient | 39:e98d5df6dc74 | 125 | LogError("on_process_message_completed_callback invoked with NULL arguments (message=%p, message_queue=%p)", message, message_queue); |
AzureIoTClient | 39:e98d5df6dc74 | 126 | } |
AzureIoTClient | 39:e98d5df6dc74 | 127 | else |
AzureIoTClient | 39:e98d5df6dc74 | 128 | { |
AzureIoTClient | 39:e98d5df6dc74 | 129 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 56:8704100b3b54 | 130 | |
AzureIoTClient | 39:e98d5df6dc74 | 131 | if ((list_item = singlylinkedlist_find(message_queue->in_progress, find_item_by_message_ptr, message)) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 132 | { |
AzureIoTClient | 39:e98d5df6dc74 | 133 | // Codes_SRS_MESSAGE_QUEUE_09_044: [If `message` is not present in `message_queue->in_progress`, it shall be ignored] |
AzureIoTClient | 39:e98d5df6dc74 | 134 | LogError("on_process_message_completed_callback invoked for a message not in the in-progress list (%p)", message); |
AzureIoTClient | 39:e98d5df6dc74 | 135 | } |
AzureIoTClient | 39:e98d5df6dc74 | 136 | else |
AzureIoTClient | 39:e98d5df6dc74 | 137 | { |
AzureIoTClient | 39:e98d5df6dc74 | 138 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 56:8704100b3b54 | 139 | |
AzureIoTClient | 39:e98d5df6dc74 | 140 | // Codes_SRS_MESSAGE_QUEUE_09_047: [If `result` is MESSAGE_QUEUE_RETRYABLE_ERROR and `mq_item->number_of_attempts` is less than or equal `message_queue->max_retry_count`, the `message` shall be moved to `message_queue->pending` to be re-sent] |
AzureIoTClient | 39:e98d5df6dc74 | 141 | // Codes_SRS_MESSAGE_QUEUE_09_048: [If `result` is MESSAGE_QUEUE_RETRYABLE_ERROR and `mq_item->number_of_attempts` is greater than `message_queue->max_retry_count`, result shall be changed to MESSAGE_QUEUE_ERROR] |
AzureIoTClient | 39:e98d5df6dc74 | 142 | if (!should_retry_sending(message_queue, mq_item, result) || retry_sending_message(message_queue, list_item) != RESULT_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 143 | { |
AzureIoTClient | 39:e98d5df6dc74 | 144 | dequeue_message_and_fire_callback(message_queue->in_progress, list_item, result, reason); |
AzureIoTClient | 39:e98d5df6dc74 | 145 | } |
AzureIoTClient | 39:e98d5df6dc74 | 146 | } |
AzureIoTClient | 39:e98d5df6dc74 | 147 | } |
AzureIoTClient | 39:e98d5df6dc74 | 148 | } |
AzureIoTClient | 39:e98d5df6dc74 | 149 | |
AzureIoTClient | 39:e98d5df6dc74 | 150 | static void process_timeouts(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 151 | { |
AzureIoTClient | 39:e98d5df6dc74 | 152 | time_t current_time; |
AzureIoTClient | 39:e98d5df6dc74 | 153 | |
AzureIoTClient | 39:e98d5df6dc74 | 154 | if ((current_time = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 39:e98d5df6dc74 | 155 | { |
AzureIoTClient | 39:e98d5df6dc74 | 156 | LogError("failed processing timeouts (get_time failed)"); |
AzureIoTClient | 39:e98d5df6dc74 | 157 | } |
AzureIoTClient | 39:e98d5df6dc74 | 158 | else |
AzureIoTClient | 39:e98d5df6dc74 | 159 | { |
AzureIoTClient | 39:e98d5df6dc74 | 160 | // Codes_SRS_MESSAGE_QUEUE_09_035: [If `message_queue->max_message_enqueued_time_secs` is greater than zero, `message_queue->in_progress` and `message_queue->pending` items shall be checked for timeout] |
AzureIoTClient | 39:e98d5df6dc74 | 161 | if (message_queue->max_message_enqueued_time_secs > 0) |
AzureIoTClient | 39:e98d5df6dc74 | 162 | { |
AzureIoTClient | 39:e98d5df6dc74 | 163 | LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(message_queue->pending); |
AzureIoTClient | 39:e98d5df6dc74 | 164 | |
AzureIoTClient | 39:e98d5df6dc74 | 165 | while (list_item != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 166 | { |
AzureIoTClient | 39:e98d5df6dc74 | 167 | LIST_ITEM_HANDLE current_list_item = list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 168 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 169 | |
AzureIoTClient | 39:e98d5df6dc74 | 170 | list_item = singlylinkedlist_get_next_item(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 171 | |
AzureIoTClient | 39:e98d5df6dc74 | 172 | if (mq_item == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 173 | { |
AzureIoTClient | 39:e98d5df6dc74 | 174 | LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)"); |
AzureIoTClient | 39:e98d5df6dc74 | 175 | } |
AzureIoTClient | 39:e98d5df6dc74 | 176 | else if (get_difftime(current_time, mq_item->enqueue_time) >= message_queue->max_message_enqueued_time_secs) |
AzureIoTClient | 39:e98d5df6dc74 | 177 | { |
AzureIoTClient | 39:e98d5df6dc74 | 178 | // Codes_SRS_MESSAGE_QUEUE_09_036: [If any items are in `message_queue` lists for `message_queue->max_message_enqueued_time_secs` or more, they shall be removed and `message_queue->on_message_processing_completed_callback` invoked with MESSAGE_QUEUE_TIMEOUT] |
AzureIoTClient | 39:e98d5df6dc74 | 179 | dequeue_message_and_fire_callback(message_queue->pending, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 180 | } |
AzureIoTClient | 39:e98d5df6dc74 | 181 | else |
AzureIoTClient | 39:e98d5df6dc74 | 182 | { |
AzureIoTClient | 39:e98d5df6dc74 | 183 | // The pending list order is already based on enqueue time, so if one message is not expired, later ones won't be either. |
AzureIoTClient | 39:e98d5df6dc74 | 184 | break; |
AzureIoTClient | 39:e98d5df6dc74 | 185 | } |
AzureIoTClient | 39:e98d5df6dc74 | 186 | } |
AzureIoTClient | 39:e98d5df6dc74 | 187 | |
AzureIoTClient | 39:e98d5df6dc74 | 188 | list_item = singlylinkedlist_get_head_item(message_queue->in_progress); |
AzureIoTClient | 39:e98d5df6dc74 | 189 | |
AzureIoTClient | 39:e98d5df6dc74 | 190 | while (list_item != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 191 | { |
AzureIoTClient | 39:e98d5df6dc74 | 192 | LIST_ITEM_HANDLE current_list_item = list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 193 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 194 | |
AzureIoTClient | 39:e98d5df6dc74 | 195 | list_item = singlylinkedlist_get_next_item(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 196 | |
AzureIoTClient | 39:e98d5df6dc74 | 197 | if (mq_item == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 198 | { |
AzureIoTClient | 39:e98d5df6dc74 | 199 | LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)"); |
AzureIoTClient | 39:e98d5df6dc74 | 200 | } |
AzureIoTClient | 39:e98d5df6dc74 | 201 | else if (get_difftime(current_time, mq_item->enqueue_time) >= message_queue->max_message_enqueued_time_secs) |
AzureIoTClient | 39:e98d5df6dc74 | 202 | { |
AzureIoTClient | 39:e98d5df6dc74 | 203 | // Codes_SRS_MESSAGE_QUEUE_09_038: [If any items are in `message_queue->in_progress` for `message_queue->max_message_processing_time_secs` or more, they shall be removed and `message_queue->on_message_processing_completed_callback` invoked with MESSAGE_QUEUE_TIMEOUT] |
AzureIoTClient | 39:e98d5df6dc74 | 204 | dequeue_message_and_fire_callback(message_queue->in_progress, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 205 | } |
AzureIoTClient | 39:e98d5df6dc74 | 206 | } |
AzureIoTClient | 39:e98d5df6dc74 | 207 | } |
AzureIoTClient | 39:e98d5df6dc74 | 208 | |
AzureIoTClient | 39:e98d5df6dc74 | 209 | // Codes_SRS_MESSAGE_QUEUE_09_037: [If `message_queue->max_message_processing_time_secs` is greater than zero, `message_queue->in_progress` items shall be checked for timeout] |
AzureIoTClient | 39:e98d5df6dc74 | 210 | if (message_queue->max_message_processing_time_secs > 0) |
AzureIoTClient | 39:e98d5df6dc74 | 211 | { |
AzureIoTClient | 39:e98d5df6dc74 | 212 | LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(message_queue->in_progress); |
AzureIoTClient | 39:e98d5df6dc74 | 213 | |
AzureIoTClient | 39:e98d5df6dc74 | 214 | while (list_item != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 215 | { |
AzureIoTClient | 39:e98d5df6dc74 | 216 | LIST_ITEM_HANDLE current_list_item = list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 217 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 218 | |
AzureIoTClient | 39:e98d5df6dc74 | 219 | list_item = singlylinkedlist_get_next_item(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 220 | |
AzureIoTClient | 39:e98d5df6dc74 | 221 | if (mq_item == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 222 | { |
AzureIoTClient | 39:e98d5df6dc74 | 223 | LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)"); |
AzureIoTClient | 39:e98d5df6dc74 | 224 | } |
AzureIoTClient | 39:e98d5df6dc74 | 225 | else if (get_difftime(current_time, mq_item->processing_start_time) >= message_queue->max_message_processing_time_secs) |
AzureIoTClient | 39:e98d5df6dc74 | 226 | { |
AzureIoTClient | 39:e98d5df6dc74 | 227 | dequeue_message_and_fire_callback(message_queue->in_progress, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 228 | } |
AzureIoTClient | 39:e98d5df6dc74 | 229 | else |
AzureIoTClient | 39:e98d5df6dc74 | 230 | { |
AzureIoTClient | 39:e98d5df6dc74 | 231 | // The in-progress list order is already based on start-processing time, so if one message is not expired, later ones won't be either. |
AzureIoTClient | 39:e98d5df6dc74 | 232 | break; |
AzureIoTClient | 39:e98d5df6dc74 | 233 | } |
AzureIoTClient | 39:e98d5df6dc74 | 234 | } |
AzureIoTClient | 39:e98d5df6dc74 | 235 | } |
AzureIoTClient | 39:e98d5df6dc74 | 236 | } |
AzureIoTClient | 39:e98d5df6dc74 | 237 | } |
AzureIoTClient | 39:e98d5df6dc74 | 238 | |
AzureIoTClient | 39:e98d5df6dc74 | 239 | static void process_pending_messages(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 240 | { |
AzureIoTClient | 39:e98d5df6dc74 | 241 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 242 | |
AzureIoTClient | 39:e98d5df6dc74 | 243 | while ((list_item = singlylinkedlist_get_head_item(message_queue->pending)) != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 244 | { |
AzureIoTClient | 39:e98d5df6dc74 | 245 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 246 | |
AzureIoTClient | 39:e98d5df6dc74 | 247 | if (mq_item == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 248 | { |
AzureIoTClient | 39:e98d5df6dc74 | 249 | LogError("internal error, failed to retrieve list node value"); |
AzureIoTClient | 39:e98d5df6dc74 | 250 | break; |
AzureIoTClient | 39:e98d5df6dc74 | 251 | } |
AzureIoTClient | 39:e98d5df6dc74 | 252 | else if (singlylinkedlist_remove(message_queue->pending, list_item) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 253 | { |
AzureIoTClient | 39:e98d5df6dc74 | 254 | LogError("failed moving message out of pending list (%p)", mq_item->message); |
AzureIoTClient | 39:e98d5df6dc74 | 255 | |
AzureIoTClient | 39:e98d5df6dc74 | 256 | // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed] |
AzureIoTClient | 39:e98d5df6dc74 | 257 | if (mq_item->on_message_processing_completed_callback != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 258 | { |
AzureIoTClient | 39:e98d5df6dc74 | 259 | mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context); |
AzureIoTClient | 39:e98d5df6dc74 | 260 | } |
AzureIoTClient | 39:e98d5df6dc74 | 261 | |
AzureIoTClient | 39:e98d5df6dc74 | 262 | // Not freeing since this would cause a memory A/V on the next call. |
AzureIoTClient | 39:e98d5df6dc74 | 263 | |
AzureIoTClient | 39:e98d5df6dc74 | 264 | break; // Trying to avoid an infinite loop |
AzureIoTClient | 39:e98d5df6dc74 | 265 | } |
AzureIoTClient | 39:e98d5df6dc74 | 266 | // Codes_SRS_MESSAGE_QUEUE_09_040: [`mq_item->processing_start_time` shall be set using get_time()] |
AzureIoTClient | 39:e98d5df6dc74 | 267 | else if ((mq_item->processing_start_time = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 39:e98d5df6dc74 | 268 | { |
AzureIoTClient | 39:e98d5df6dc74 | 269 | // Codes_SRS_MESSAGE_QUEUE_09_041: [If get_time() fails, `mq_item` shall be removed from `message_queue->in_progress`] |
AzureIoTClient | 39:e98d5df6dc74 | 270 | LogError("failed setting message processing_start_time (%p)", mq_item->message); |
AzureIoTClient | 39:e98d5df6dc74 | 271 | |
AzureIoTClient | 39:e98d5df6dc74 | 272 | // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed] |
AzureIoTClient | 39:e98d5df6dc74 | 273 | if (mq_item->on_message_processing_completed_callback != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 274 | { |
AzureIoTClient | 39:e98d5df6dc74 | 275 | mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context); |
AzureIoTClient | 39:e98d5df6dc74 | 276 | } |
AzureIoTClient | 39:e98d5df6dc74 | 277 | |
AzureIoTClient | 39:e98d5df6dc74 | 278 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 279 | } |
AzureIoTClient | 39:e98d5df6dc74 | 280 | // Codes_SRS_MESSAGE_QUEUE_09_039: [Each `mq_item` in `message_queue->pending` shall be moved to `message_queue->in_progress`] |
AzureIoTClient | 39:e98d5df6dc74 | 281 | else if (singlylinkedlist_add(message_queue->in_progress, (const void*)mq_item) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 282 | { |
AzureIoTClient | 39:e98d5df6dc74 | 283 | LogError("failed moving message to in-progress list (%p)", mq_item->message); |
AzureIoTClient | 39:e98d5df6dc74 | 284 | |
AzureIoTClient | 39:e98d5df6dc74 | 285 | // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed] |
AzureIoTClient | 39:e98d5df6dc74 | 286 | if (mq_item->on_message_processing_completed_callback != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 287 | { |
AzureIoTClient | 39:e98d5df6dc74 | 288 | mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context); |
AzureIoTClient | 39:e98d5df6dc74 | 289 | } |
AzureIoTClient | 39:e98d5df6dc74 | 290 | |
AzureIoTClient | 39:e98d5df6dc74 | 291 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 292 | } |
AzureIoTClient | 39:e98d5df6dc74 | 293 | else |
AzureIoTClient | 39:e98d5df6dc74 | 294 | { |
AzureIoTClient | 39:e98d5df6dc74 | 295 | mq_item->number_of_attempts++; |
AzureIoTClient | 39:e98d5df6dc74 | 296 | |
AzureIoTClient | 39:e98d5df6dc74 | 297 | // Codes_SRS_MESSAGE_QUEUE_09_043: [If no failures occur, `message_queue->on_process_message_callback` shall be invoked passing `mq_item->message` and `on_process_message_completed_callback`] |
AzureIoTClient | 39:e98d5df6dc74 | 298 | message_queue->on_process_message_callback(message_queue, mq_item->message, on_process_message_completed_callback, mq_item->user_context); |
AzureIoTClient | 39:e98d5df6dc74 | 299 | } |
AzureIoTClient | 39:e98d5df6dc74 | 300 | } |
AzureIoTClient | 39:e98d5df6dc74 | 301 | } |
AzureIoTClient | 39:e98d5df6dc74 | 302 | |
AzureIoTClient | 39:e98d5df6dc74 | 303 | static void* cloneOption(const char* name, const void* value) |
AzureIoTClient | 39:e98d5df6dc74 | 304 | { |
AzureIoTClient | 39:e98d5df6dc74 | 305 | void* result; |
AzureIoTClient | 39:e98d5df6dc74 | 306 | |
AzureIoTClient | 39:e98d5df6dc74 | 307 | if (name == NULL || value == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 308 | { |
AzureIoTClient | 39:e98d5df6dc74 | 309 | LogError("invalid argument (name=%p, value=%p)", name, value); |
AzureIoTClient | 39:e98d5df6dc74 | 310 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 311 | } |
AzureIoTClient | 56:8704100b3b54 | 312 | else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0 || |
AzureIoTClient | 56:8704100b3b54 | 313 | strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0 || |
AzureIoTClient | 39:e98d5df6dc74 | 314 | strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0) |
AzureIoTClient | 39:e98d5df6dc74 | 315 | { |
AzureIoTClient | 39:e98d5df6dc74 | 316 | if ((result = malloc(sizeof(size_t))) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 317 | { |
AzureIoTClient | 39:e98d5df6dc74 | 318 | LogError("failed cloning option %s (malloc failed)", name); |
AzureIoTClient | 39:e98d5df6dc74 | 319 | } |
AzureIoTClient | 39:e98d5df6dc74 | 320 | else |
AzureIoTClient | 39:e98d5df6dc74 | 321 | { |
AzureIoTClient | 39:e98d5df6dc74 | 322 | memcpy(result, value, sizeof(size_t)); |
AzureIoTClient | 39:e98d5df6dc74 | 323 | } |
AzureIoTClient | 39:e98d5df6dc74 | 324 | } |
AzureIoTClient | 39:e98d5df6dc74 | 325 | else |
AzureIoTClient | 39:e98d5df6dc74 | 326 | { |
AzureIoTClient | 39:e98d5df6dc74 | 327 | LogError("option %s is invalid", name); |
AzureIoTClient | 39:e98d5df6dc74 | 328 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 329 | } |
AzureIoTClient | 39:e98d5df6dc74 | 330 | |
AzureIoTClient | 39:e98d5df6dc74 | 331 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 332 | } |
AzureIoTClient | 39:e98d5df6dc74 | 333 | |
AzureIoTClient | 39:e98d5df6dc74 | 334 | static void destroyOption(const char* name, const void* value) |
AzureIoTClient | 39:e98d5df6dc74 | 335 | { |
AzureIoTClient | 39:e98d5df6dc74 | 336 | if (name == NULL || value == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 337 | { |
AzureIoTClient | 39:e98d5df6dc74 | 338 | LogError("invalid argument (name=%p, value=%p)", name, value); |
AzureIoTClient | 39:e98d5df6dc74 | 339 | } |
AzureIoTClient | 56:8704100b3b54 | 340 | else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0 || |
AzureIoTClient | 56:8704100b3b54 | 341 | strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0 || |
AzureIoTClient | 39:e98d5df6dc74 | 342 | strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0) |
AzureIoTClient | 39:e98d5df6dc74 | 343 | { |
AzureIoTClient | 39:e98d5df6dc74 | 344 | free((void*)value); |
AzureIoTClient | 39:e98d5df6dc74 | 345 | } |
AzureIoTClient | 39:e98d5df6dc74 | 346 | else |
AzureIoTClient | 39:e98d5df6dc74 | 347 | { |
AzureIoTClient | 39:e98d5df6dc74 | 348 | LogError("option %s is invalid", name); |
AzureIoTClient | 39:e98d5df6dc74 | 349 | } |
AzureIoTClient | 39:e98d5df6dc74 | 350 | } |
AzureIoTClient | 39:e98d5df6dc74 | 351 | |
AzureIoTClient | 39:e98d5df6dc74 | 352 | |
AzureIoTClient | 39:e98d5df6dc74 | 353 | |
AzureIoTClient | 39:e98d5df6dc74 | 354 | // ---------- Public APIs ---------- // |
AzureIoTClient | 39:e98d5df6dc74 | 355 | |
AzureIoTClient | 39:e98d5df6dc74 | 356 | void message_queue_remove_all(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 357 | { |
AzureIoTClient | 39:e98d5df6dc74 | 358 | // Codes_SRS_MESSAGE_QUEUE_09_026: [If `message_queue` is NULL, message_queue_retrieve_options shall return] |
AzureIoTClient | 39:e98d5df6dc74 | 359 | if (message_queue != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 360 | { |
AzureIoTClient | 39:e98d5df6dc74 | 361 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 362 | |
AzureIoTClient | 56:8704100b3b54 | 363 | // Codes_SRS_MESSAGE_QUEUE_09_027: [Each `mq_item` in `message_queue->pending` and `message_queue->in_progress` lists shall be removed] |
AzureIoTClient | 39:e98d5df6dc74 | 364 | while ((list_item = singlylinkedlist_get_head_item(message_queue->in_progress)) != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 365 | { |
AzureIoTClient | 39:e98d5df6dc74 | 366 | // Codes_SRS_MESSAGE_QUEUE_09_028: [`message_queue->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_CANCELLED for each `mq_item` removed] |
AzureIoTClient | 56:8704100b3b54 | 367 | // Codes_SRS_MESSAGE_QUEUE_09_029: [Each `mq_item` shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 368 | dequeue_message_and_fire_callback(message_queue->in_progress, list_item, MESSAGE_QUEUE_CANCELLED, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 369 | } |
AzureIoTClient | 39:e98d5df6dc74 | 370 | |
AzureIoTClient | 39:e98d5df6dc74 | 371 | while ((list_item = singlylinkedlist_get_head_item(message_queue->pending)) != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 372 | { |
AzureIoTClient | 39:e98d5df6dc74 | 373 | // Codes_SRS_MESSAGE_QUEUE_09_028: [`message_queue->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_CANCELLED for each `mq_item` removed] |
AzureIoTClient | 56:8704100b3b54 | 374 | // Codes_SRS_MESSAGE_QUEUE_09_029: [Each `mq_item` shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 375 | dequeue_message_and_fire_callback(message_queue->pending, list_item, MESSAGE_QUEUE_CANCELLED, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 376 | } |
AzureIoTClient | 39:e98d5df6dc74 | 377 | } |
AzureIoTClient | 39:e98d5df6dc74 | 378 | } |
AzureIoTClient | 39:e98d5df6dc74 | 379 | |
AzureIoTClient | 39:e98d5df6dc74 | 380 | static int move_messages_between_lists(SINGLYLINKEDLIST_HANDLE from_list, SINGLYLINKEDLIST_HANDLE to_list) |
AzureIoTClient | 39:e98d5df6dc74 | 381 | { |
AzureIoTClient | 39:e98d5df6dc74 | 382 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 383 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 384 | |
AzureIoTClient | 39:e98d5df6dc74 | 385 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 386 | |
AzureIoTClient | 39:e98d5df6dc74 | 387 | while ((list_item = singlylinkedlist_get_head_item(from_list)) != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 388 | { |
AzureIoTClient | 39:e98d5df6dc74 | 389 | if (singlylinkedlist_remove(from_list, list_item) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 390 | { |
AzureIoTClient | 39:e98d5df6dc74 | 391 | LogError("failed removing message from list"); |
AzureIoTClient | 39:e98d5df6dc74 | 392 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 393 | } |
AzureIoTClient | 39:e98d5df6dc74 | 394 | else |
AzureIoTClient | 39:e98d5df6dc74 | 395 | { |
AzureIoTClient | 39:e98d5df6dc74 | 396 | MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 39:e98d5df6dc74 | 397 | |
AzureIoTClient | 39:e98d5df6dc74 | 398 | if (singlylinkedlist_add(to_list, (const void*)mq_item) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 399 | { |
AzureIoTClient | 39:e98d5df6dc74 | 400 | LogError("failed moving message to list"); |
AzureIoTClient | 39:e98d5df6dc74 | 401 | |
AzureIoTClient | 39:e98d5df6dc74 | 402 | fire_message_callback(mq_item, MESSAGE_QUEUE_CANCELLED, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 403 | |
AzureIoTClient | 39:e98d5df6dc74 | 404 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 405 | |
AzureIoTClient | 39:e98d5df6dc74 | 406 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 407 | |
AzureIoTClient | 39:e98d5df6dc74 | 408 | break; |
AzureIoTClient | 39:e98d5df6dc74 | 409 | } |
AzureIoTClient | 39:e98d5df6dc74 | 410 | else |
AzureIoTClient | 39:e98d5df6dc74 | 411 | { |
AzureIoTClient | 39:e98d5df6dc74 | 412 | mq_item->number_of_attempts = 0; |
AzureIoTClient | 39:e98d5df6dc74 | 413 | mq_item->processing_start_time = INDEFINITE_TIME; |
AzureIoTClient | 39:e98d5df6dc74 | 414 | } |
AzureIoTClient | 39:e98d5df6dc74 | 415 | } |
AzureIoTClient | 39:e98d5df6dc74 | 416 | } |
AzureIoTClient | 39:e98d5df6dc74 | 417 | |
AzureIoTClient | 39:e98d5df6dc74 | 418 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 419 | } |
AzureIoTClient | 39:e98d5df6dc74 | 420 | |
AzureIoTClient | 39:e98d5df6dc74 | 421 | int message_queue_move_all_back_to_pending(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 422 | { |
AzureIoTClient | 39:e98d5df6dc74 | 423 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 424 | |
AzureIoTClient | 39:e98d5df6dc74 | 425 | if (message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 426 | { |
AzureIoTClient | 39:e98d5df6dc74 | 427 | LogError("invalid argument (message_queue is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 428 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 429 | } |
AzureIoTClient | 39:e98d5df6dc74 | 430 | else |
AzureIoTClient | 39:e98d5df6dc74 | 431 | { |
AzureIoTClient | 39:e98d5df6dc74 | 432 | SINGLYLINKEDLIST_HANDLE temp_list; |
AzureIoTClient | 39:e98d5df6dc74 | 433 | |
AzureIoTClient | 39:e98d5df6dc74 | 434 | if ((temp_list = singlylinkedlist_create()) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 435 | { |
AzureIoTClient | 39:e98d5df6dc74 | 436 | LogError("failed creating temporary list"); |
AzureIoTClient | 39:e98d5df6dc74 | 437 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 438 | } |
AzureIoTClient | 39:e98d5df6dc74 | 439 | else |
AzureIoTClient | 39:e98d5df6dc74 | 440 | { |
AzureIoTClient | 39:e98d5df6dc74 | 441 | if (move_messages_between_lists(message_queue->in_progress, temp_list) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 442 | { |
AzureIoTClient | 39:e98d5df6dc74 | 443 | LogError("failed moving in-progress message to temporary list"); |
AzureIoTClient | 39:e98d5df6dc74 | 444 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 445 | } |
AzureIoTClient | 39:e98d5df6dc74 | 446 | else if (move_messages_between_lists(message_queue->pending, temp_list) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 447 | { |
AzureIoTClient | 39:e98d5df6dc74 | 448 | LogError("failed moving pending message to temporary list"); |
AzureIoTClient | 39:e98d5df6dc74 | 449 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 450 | } |
AzureIoTClient | 39:e98d5df6dc74 | 451 | else if (move_messages_between_lists(temp_list, message_queue->pending) != 0) |
AzureIoTClient | 39:e98d5df6dc74 | 452 | { |
AzureIoTClient | 39:e98d5df6dc74 | 453 | LogError("failed moving pending message to temporary list"); |
AzureIoTClient | 39:e98d5df6dc74 | 454 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 455 | } |
AzureIoTClient | 39:e98d5df6dc74 | 456 | else |
AzureIoTClient | 39:e98d5df6dc74 | 457 | { |
AzureIoTClient | 39:e98d5df6dc74 | 458 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 459 | } |
AzureIoTClient | 39:e98d5df6dc74 | 460 | |
AzureIoTClient | 39:e98d5df6dc74 | 461 | if (result != RESULT_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 462 | { |
AzureIoTClient | 39:e98d5df6dc74 | 463 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 464 | |
AzureIoTClient | 39:e98d5df6dc74 | 465 | while ((list_item = singlylinkedlist_get_head_item(temp_list)) != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 466 | { |
AzureIoTClient | 39:e98d5df6dc74 | 467 | dequeue_message_and_fire_callback(temp_list, list_item, MESSAGE_QUEUE_CANCELLED, NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 468 | } |
AzureIoTClient | 39:e98d5df6dc74 | 469 | } |
AzureIoTClient | 39:e98d5df6dc74 | 470 | |
AzureIoTClient | 56:8704100b3b54 | 471 | singlylinkedlist_destroy(temp_list); |
AzureIoTClient | 39:e98d5df6dc74 | 472 | } |
AzureIoTClient | 39:e98d5df6dc74 | 473 | } |
AzureIoTClient | 39:e98d5df6dc74 | 474 | |
AzureIoTClient | 39:e98d5df6dc74 | 475 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 476 | } |
AzureIoTClient | 39:e98d5df6dc74 | 477 | |
AzureIoTClient | 39:e98d5df6dc74 | 478 | void message_queue_destroy(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 479 | { |
AzureIoTClient | 39:e98d5df6dc74 | 480 | // Codes_SRS_MESSAGE_QUEUE_09_013: [If `message_queue` is NULL, message_queue_destroy shall return immediately] |
AzureIoTClient | 39:e98d5df6dc74 | 481 | if (message_queue != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 482 | { |
AzureIoTClient | 39:e98d5df6dc74 | 483 | // Codes_SRS_MESSAGE_QUEUE_09_014: [message_queue_destroy shall invoke message_queue_remove_all] |
AzureIoTClient | 39:e98d5df6dc74 | 484 | message_queue_remove_all(message_queue); |
AzureIoTClient | 39:e98d5df6dc74 | 485 | |
AzureIoTClient | 39:e98d5df6dc74 | 486 | // Codes_SRS_MESSAGE_QUEUE_09_015: [message_queue_destroy shall free all memory allocated and pointed by `message_queue`] |
AzureIoTClient | 39:e98d5df6dc74 | 487 | if (message_queue->pending != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 488 | { |
AzureIoTClient | 39:e98d5df6dc74 | 489 | singlylinkedlist_destroy(message_queue->pending); |
AzureIoTClient | 39:e98d5df6dc74 | 490 | } |
AzureIoTClient | 39:e98d5df6dc74 | 491 | |
AzureIoTClient | 39:e98d5df6dc74 | 492 | if (message_queue->in_progress != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 493 | { |
AzureIoTClient | 39:e98d5df6dc74 | 494 | singlylinkedlist_destroy(message_queue->in_progress); |
AzureIoTClient | 39:e98d5df6dc74 | 495 | } |
AzureIoTClient | 56:8704100b3b54 | 496 | |
AzureIoTClient | 39:e98d5df6dc74 | 497 | free(message_queue); |
AzureIoTClient | 39:e98d5df6dc74 | 498 | } |
AzureIoTClient | 39:e98d5df6dc74 | 499 | } |
AzureIoTClient | 39:e98d5df6dc74 | 500 | |
AzureIoTClient | 39:e98d5df6dc74 | 501 | MESSAGE_QUEUE_HANDLE message_queue_create(MESSAGE_QUEUE_CONFIG* config) |
AzureIoTClient | 39:e98d5df6dc74 | 502 | { |
AzureIoTClient | 39:e98d5df6dc74 | 503 | MESSAGE_QUEUE* result; |
AzureIoTClient | 39:e98d5df6dc74 | 504 | |
AzureIoTClient | 39:e98d5df6dc74 | 505 | // Codes_SRS_MESSAGE_QUEUE_09_001: [If `config` is NULL, message_queue_create shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 506 | if (config == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 507 | { |
AzureIoTClient | 39:e98d5df6dc74 | 508 | LogError("invalid configuration (NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 509 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 510 | } |
AzureIoTClient | 39:e98d5df6dc74 | 511 | // Codes_SRS_MESSAGE_QUEUE_09_002: [If `config->on_process_message_callback` is NULL, message_queue_create shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 512 | else if (config->on_process_message_callback == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 513 | { |
AzureIoTClient | 39:e98d5df6dc74 | 514 | LogError("invalid configuration (on_process_message_callback is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 515 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 516 | } |
AzureIoTClient | 39:e98d5df6dc74 | 517 | // Codes_SRS_MESSAGE_QUEUE_09_004: [Memory shall be allocated for the MESSAGE_QUEUE data structure (aka `message_queue`)] |
AzureIoTClient | 39:e98d5df6dc74 | 518 | else if ((result = (MESSAGE_QUEUE*)malloc(sizeof(MESSAGE_QUEUE))) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 519 | { |
AzureIoTClient | 39:e98d5df6dc74 | 520 | // Codes_SRS_MESSAGE_QUEUE_09_005: [If `instance` cannot be allocated, message_queue_create shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 521 | LogError("failed allocating MESSAGE_QUEUE"); |
AzureIoTClient | 39:e98d5df6dc74 | 522 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 523 | } |
AzureIoTClient | 39:e98d5df6dc74 | 524 | else |
AzureIoTClient | 39:e98d5df6dc74 | 525 | { |
AzureIoTClient | 39:e98d5df6dc74 | 526 | memset(result, 0, sizeof(MESSAGE_QUEUE)); |
AzureIoTClient | 39:e98d5df6dc74 | 527 | |
AzureIoTClient | 39:e98d5df6dc74 | 528 | // Codes_SRS_MESSAGE_QUEUE_09_006: [`message_queue->pending` shall be set using singlylinkedlist_create()] |
AzureIoTClient | 39:e98d5df6dc74 | 529 | if ((result->pending = singlylinkedlist_create()) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 530 | { |
AzureIoTClient | 39:e98d5df6dc74 | 531 | // Codes_SRS_MESSAGE_QUEUE_09_007: [If singlylinkedlist_create fails, message_queue_create shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 532 | LogError("failed allocating MESSAGE_QUEUE pending list"); |
AzureIoTClient | 39:e98d5df6dc74 | 533 | // Codes_SRS_MESSAGE_QUEUE_09_011: [If any failures occur, message_queue_create shall release all memory it has allocated] |
AzureIoTClient | 39:e98d5df6dc74 | 534 | message_queue_destroy(result); |
AzureIoTClient | 39:e98d5df6dc74 | 535 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 536 | } |
AzureIoTClient | 39:e98d5df6dc74 | 537 | // Codes_SRS_MESSAGE_QUEUE_09_008: [`message_queue->in_progress` shall be set using singlylinkedlist_create()] |
AzureIoTClient | 39:e98d5df6dc74 | 538 | else if ((result->in_progress = singlylinkedlist_create()) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 539 | { |
AzureIoTClient | 39:e98d5df6dc74 | 540 | // Codes_SRS_MESSAGE_QUEUE_09_009: [If singlylinkedlist_create fails, message_queue_create shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 541 | LogError("failed allocating MESSAGE_QUEUE in-progress list"); |
AzureIoTClient | 39:e98d5df6dc74 | 542 | // Codes_SRS_MESSAGE_QUEUE_09_011: [If any failures occur, message_queue_create shall release all memory it has allocated] |
AzureIoTClient | 39:e98d5df6dc74 | 543 | message_queue_destroy(result); |
AzureIoTClient | 39:e98d5df6dc74 | 544 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 545 | } |
AzureIoTClient | 39:e98d5df6dc74 | 546 | else |
AzureIoTClient | 39:e98d5df6dc74 | 547 | { |
AzureIoTClient | 39:e98d5df6dc74 | 548 | // Codes_SRS_MESSAGE_QUEUE_09_010: [All arguments in `config` shall be saved into `message_queue`] |
AzureIoTClient | 39:e98d5df6dc74 | 549 | // Codes_SRS_MESSAGE_QUEUE_09_012: [If no failures occur, message_queue_create shall return the `message_queue` pointer] |
AzureIoTClient | 39:e98d5df6dc74 | 550 | |
AzureIoTClient | 39:e98d5df6dc74 | 551 | result->max_message_enqueued_time_secs = config->max_message_enqueued_time_secs; |
AzureIoTClient | 39:e98d5df6dc74 | 552 | result->max_message_processing_time_secs = config->max_message_processing_time_secs; |
AzureIoTClient | 39:e98d5df6dc74 | 553 | result->max_retry_count = config->max_retry_count; |
AzureIoTClient | 39:e98d5df6dc74 | 554 | result->on_process_message_callback = config->on_process_message_callback; |
AzureIoTClient | 39:e98d5df6dc74 | 555 | } |
AzureIoTClient | 39:e98d5df6dc74 | 556 | } |
AzureIoTClient | 39:e98d5df6dc74 | 557 | |
AzureIoTClient | 39:e98d5df6dc74 | 558 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 559 | } |
AzureIoTClient | 39:e98d5df6dc74 | 560 | |
AzureIoTClient | 39:e98d5df6dc74 | 561 | int message_queue_add(MESSAGE_QUEUE_HANDLE message_queue, MQ_MESSAGE_HANDLE message, MESSAGE_PROCESSING_COMPLETED_CALLBACK on_message_processing_completed_callback, void* user_context) |
AzureIoTClient | 39:e98d5df6dc74 | 562 | { |
AzureIoTClient | 39:e98d5df6dc74 | 563 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 564 | |
AzureIoTClient | 39:e98d5df6dc74 | 565 | // Codes_SRS_MESSAGE_QUEUE_09_016: [If `message_queue` or `message` are NULL, message_queue_add shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 566 | if (message_queue == NULL || message == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 567 | { |
AzureIoTClient | 39:e98d5df6dc74 | 568 | LogError("invalid argument (message_queue=%p, message=%p)", message_queue, message); |
AzureIoTClient | 39:e98d5df6dc74 | 569 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 570 | } |
AzureIoTClient | 39:e98d5df6dc74 | 571 | else |
AzureIoTClient | 39:e98d5df6dc74 | 572 | { |
AzureIoTClient | 39:e98d5df6dc74 | 573 | MESSAGE_QUEUE_ITEM* mq_item; |
AzureIoTClient | 39:e98d5df6dc74 | 574 | |
AzureIoTClient | 39:e98d5df6dc74 | 575 | // Codes_SRS_MESSAGE_QUEUE_09_017: [message_queue_add shall allocate a structure (aka `mq_item`) to save the `message`] |
AzureIoTClient | 39:e98d5df6dc74 | 576 | if ((mq_item = (MESSAGE_QUEUE_ITEM*)malloc(sizeof(MESSAGE_QUEUE_ITEM))) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 577 | { |
AzureIoTClient | 39:e98d5df6dc74 | 578 | // Codes_SRS_MESSAGE_QUEUE_09_018: [If `mq_item` cannot be allocated, message_queue_add shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 579 | LogError("failed creating container for message"); |
AzureIoTClient | 39:e98d5df6dc74 | 580 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 581 | } |
AzureIoTClient | 39:e98d5df6dc74 | 582 | else |
AzureIoTClient | 39:e98d5df6dc74 | 583 | { |
AzureIoTClient | 39:e98d5df6dc74 | 584 | memset(mq_item, 0, sizeof(MESSAGE_QUEUE_ITEM)); |
AzureIoTClient | 39:e98d5df6dc74 | 585 | |
AzureIoTClient | 39:e98d5df6dc74 | 586 | // Codes_SRS_MESSAGE_QUEUE_09_019: [`mq_item->enqueue_time` shall be set using get_time()] |
AzureIoTClient | 39:e98d5df6dc74 | 587 | if ((mq_item->enqueue_time = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 39:e98d5df6dc74 | 588 | { |
AzureIoTClient | 39:e98d5df6dc74 | 589 | // Codes_SRS_MESSAGE_QUEUE_09_020: [If get_time fails, message_queue_add shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 590 | LogError("failed setting message enqueue time"); |
AzureIoTClient | 39:e98d5df6dc74 | 591 | // Codes_SRS_MESSAGE_QUEUE_09_024: [If any failures occur, message_queue_add shall release all memory it has allocated] |
AzureIoTClient | 39:e98d5df6dc74 | 592 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 593 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 594 | } |
AzureIoTClient | 39:e98d5df6dc74 | 595 | // Codes_SRS_MESSAGE_QUEUE_09_021: [`mq_item` shall be added to `message_queue->pending` list] |
AzureIoTClient | 39:e98d5df6dc74 | 596 | else if (singlylinkedlist_add(message_queue->pending, (const void*)mq_item) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 597 | { |
AzureIoTClient | 39:e98d5df6dc74 | 598 | // Codes_SRS_MESSAGE_QUEUE_09_022: [`mq_item` fails to be added to `message_queue->pending`, message_queue_add shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 599 | LogError("failed enqueing message"); |
AzureIoTClient | 39:e98d5df6dc74 | 600 | // Codes_SRS_MESSAGE_QUEUE_09_024: [If any failures occur, message_queue_add shall release all memory it has allocated] |
AzureIoTClient | 39:e98d5df6dc74 | 601 | free(mq_item); |
AzureIoTClient | 39:e98d5df6dc74 | 602 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 603 | } |
AzureIoTClient | 39:e98d5df6dc74 | 604 | else |
AzureIoTClient | 39:e98d5df6dc74 | 605 | { |
AzureIoTClient | 39:e98d5df6dc74 | 606 | // Codes_SRS_MESSAGE_QUEUE_09_023: [`message` shall be saved into `mq_item->message`] |
AzureIoTClient | 39:e98d5df6dc74 | 607 | mq_item->message = message; |
AzureIoTClient | 39:e98d5df6dc74 | 608 | mq_item->on_message_processing_completed_callback = on_message_processing_completed_callback; |
AzureIoTClient | 39:e98d5df6dc74 | 609 | mq_item->user_context = user_context; |
AzureIoTClient | 39:e98d5df6dc74 | 610 | mq_item->processing_start_time = INDEFINITE_TIME; |
AzureIoTClient | 39:e98d5df6dc74 | 611 | // Codes_SRS_MESSAGE_QUEUE_09_025: [If no failures occur, message_queue_add shall return 0] |
AzureIoTClient | 39:e98d5df6dc74 | 612 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 613 | } |
AzureIoTClient | 39:e98d5df6dc74 | 614 | } |
AzureIoTClient | 39:e98d5df6dc74 | 615 | } |
AzureIoTClient | 39:e98d5df6dc74 | 616 | |
AzureIoTClient | 39:e98d5df6dc74 | 617 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 618 | } |
AzureIoTClient | 39:e98d5df6dc74 | 619 | |
AzureIoTClient | 39:e98d5df6dc74 | 620 | int message_queue_is_empty(MESSAGE_QUEUE_HANDLE message_queue, bool* is_empty) |
AzureIoTClient | 39:e98d5df6dc74 | 621 | { |
AzureIoTClient | 39:e98d5df6dc74 | 622 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 623 | |
AzureIoTClient | 39:e98d5df6dc74 | 624 | // Codes_SRS_MESSAGE_QUEUE_09_030: [If `message_queue` or `is_empty` are NULL, message_queue_is_empty shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 625 | if (message_queue == NULL || is_empty == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 626 | { |
AzureIoTClient | 39:e98d5df6dc74 | 627 | LogError("invalid argument (message_queue=%p, is_empty=%p)", message_queue, is_empty); |
AzureIoTClient | 39:e98d5df6dc74 | 628 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 629 | } |
AzureIoTClient | 39:e98d5df6dc74 | 630 | else |
AzureIoTClient | 39:e98d5df6dc74 | 631 | { |
AzureIoTClient | 39:e98d5df6dc74 | 632 | // Codes_SRS_MESSAGE_QUEUE_09_031: [If `message_queue->pending` and `message_queue->in_progress` are empty, `is_empty` shall be set to true] |
AzureIoTClient | 39:e98d5df6dc74 | 633 | // Codes_SRS_MESSAGE_QUEUE_09_032: [Otherwise `is_empty` shall be set to false] |
AzureIoTClient | 39:e98d5df6dc74 | 634 | *is_empty = (singlylinkedlist_get_head_item(message_queue->pending) == NULL && singlylinkedlist_get_head_item(message_queue->in_progress) == NULL); |
AzureIoTClient | 39:e98d5df6dc74 | 635 | // Codes_SRS_MESSAGE_QUEUE_09_033: [If no failures occur, message_queue_is_empty shall return 0] |
AzureIoTClient | 39:e98d5df6dc74 | 636 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 637 | } |
AzureIoTClient | 39:e98d5df6dc74 | 638 | |
AzureIoTClient | 39:e98d5df6dc74 | 639 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 640 | } |
AzureIoTClient | 39:e98d5df6dc74 | 641 | |
AzureIoTClient | 39:e98d5df6dc74 | 642 | void message_queue_do_work(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 643 | { |
AzureIoTClient | 39:e98d5df6dc74 | 644 | // Codes_SRS_MESSAGE_QUEUE_09_034: [If `message_queue` is NULL, message_queue_do_work shall return immediately] |
AzureIoTClient | 39:e98d5df6dc74 | 645 | if (message_queue != NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 646 | { |
AzureIoTClient | 39:e98d5df6dc74 | 647 | process_timeouts(message_queue); |
AzureIoTClient | 39:e98d5df6dc74 | 648 | process_pending_messages(message_queue); |
AzureIoTClient | 39:e98d5df6dc74 | 649 | } |
AzureIoTClient | 39:e98d5df6dc74 | 650 | } |
AzureIoTClient | 39:e98d5df6dc74 | 651 | |
AzureIoTClient | 39:e98d5df6dc74 | 652 | int message_queue_set_max_message_enqueued_time_secs(MESSAGE_QUEUE_HANDLE message_queue, size_t seconds) |
AzureIoTClient | 39:e98d5df6dc74 | 653 | { |
AzureIoTClient | 39:e98d5df6dc74 | 654 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 655 | |
AzureIoTClient | 39:e98d5df6dc74 | 656 | // Codes_SRS_MESSAGE_QUEUE_09_051: [If `message_queue` is NULL, message_queue_set_max_message_enqueued_time_secs shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 657 | if (message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 658 | { |
AzureIoTClient | 39:e98d5df6dc74 | 659 | LogError("invalid argument (message_queue is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 660 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 661 | } |
AzureIoTClient | 39:e98d5df6dc74 | 662 | else |
AzureIoTClient | 39:e98d5df6dc74 | 663 | { |
AzureIoTClient | 39:e98d5df6dc74 | 664 | // Codes_SRS_MESSAGE_QUEUE_09_053: [`seconds` shall be saved into `message_queue->max_message_enqueued_time_secs`] |
AzureIoTClient | 39:e98d5df6dc74 | 665 | message_queue->max_message_enqueued_time_secs = seconds; |
AzureIoTClient | 39:e98d5df6dc74 | 666 | // Codes_SRS_MESSAGE_QUEUE_09_054: [If no failures occur, message_queue_set_max_message_enqueued_time_secs shall return 0] |
AzureIoTClient | 39:e98d5df6dc74 | 667 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 668 | } |
AzureIoTClient | 39:e98d5df6dc74 | 669 | |
AzureIoTClient | 39:e98d5df6dc74 | 670 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 671 | } |
AzureIoTClient | 39:e98d5df6dc74 | 672 | |
AzureIoTClient | 39:e98d5df6dc74 | 673 | int message_queue_set_max_message_processing_time_secs(MESSAGE_QUEUE_HANDLE message_queue, size_t seconds) |
AzureIoTClient | 39:e98d5df6dc74 | 674 | { |
AzureIoTClient | 39:e98d5df6dc74 | 675 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 676 | |
AzureIoTClient | 39:e98d5df6dc74 | 677 | // Codes_SRS_MESSAGE_QUEUE_09_055: [If `message_queue` is NULL, message_queue_set_max_message_processing_time_secs shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 678 | if (message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 679 | { |
AzureIoTClient | 39:e98d5df6dc74 | 680 | LogError("invalid argument (message_queue is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 681 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 682 | } |
AzureIoTClient | 39:e98d5df6dc74 | 683 | else |
AzureIoTClient | 39:e98d5df6dc74 | 684 | { |
AzureIoTClient | 39:e98d5df6dc74 | 685 | // Codes_SRS_MESSAGE_QUEUE_09_057: [`seconds` shall be saved into `message_queue->max_message_processing_time_secs`] |
AzureIoTClient | 39:e98d5df6dc74 | 686 | message_queue->max_message_processing_time_secs = seconds; |
AzureIoTClient | 39:e98d5df6dc74 | 687 | // Codes_SRS_MESSAGE_QUEUE_09_058: [If no failures occur, message_queue_set_max_message_processing_time_secs shall return 0] |
AzureIoTClient | 39:e98d5df6dc74 | 688 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 689 | } |
AzureIoTClient | 39:e98d5df6dc74 | 690 | |
AzureIoTClient | 39:e98d5df6dc74 | 691 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 692 | } |
AzureIoTClient | 39:e98d5df6dc74 | 693 | |
AzureIoTClient | 39:e98d5df6dc74 | 694 | int message_queue_set_max_retry_count(MESSAGE_QUEUE_HANDLE message_queue, size_t max_retry_count) |
AzureIoTClient | 39:e98d5df6dc74 | 695 | { |
AzureIoTClient | 39:e98d5df6dc74 | 696 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 697 | |
AzureIoTClient | 39:e98d5df6dc74 | 698 | // Codes_SRS_MESSAGE_QUEUE_09_059: [If `message_queue` is NULL, message_queue_set_max_retry_count shall fail and return non-zero] |
AzureIoTClient | 39:e98d5df6dc74 | 699 | if (message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 700 | { |
AzureIoTClient | 39:e98d5df6dc74 | 701 | LogError("invalid argument (message_queue is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 702 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 703 | } |
AzureIoTClient | 39:e98d5df6dc74 | 704 | else |
AzureIoTClient | 39:e98d5df6dc74 | 705 | { |
AzureIoTClient | 39:e98d5df6dc74 | 706 | // Codes_SRS_MESSAGE_QUEUE_09_061: [If no failures occur, message_queue_set_max_retry_count shall return 0] |
AzureIoTClient | 39:e98d5df6dc74 | 707 | message_queue->max_retry_count = max_retry_count; |
AzureIoTClient | 39:e98d5df6dc74 | 708 | // Codes_SRS_MESSAGE_QUEUE_09_060: [`max_retry_count` shall be saved into `message_queue->max_retry_count`] |
AzureIoTClient | 39:e98d5df6dc74 | 709 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 710 | } |
AzureIoTClient | 39:e98d5df6dc74 | 711 | |
AzureIoTClient | 39:e98d5df6dc74 | 712 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 713 | } |
AzureIoTClient | 39:e98d5df6dc74 | 714 | |
AzureIoTClient | 39:e98d5df6dc74 | 715 | static int setOption(void* handle, const char* name, const void* value) |
AzureIoTClient | 39:e98d5df6dc74 | 716 | { |
AzureIoTClient | 39:e98d5df6dc74 | 717 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 718 | |
AzureIoTClient | 39:e98d5df6dc74 | 719 | if (handle == NULL || name == NULL || value == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 720 | { |
AzureIoTClient | 39:e98d5df6dc74 | 721 | LogError("invalid argument (handle=%p, name=%p, value=%p)", handle, name, value); |
AzureIoTClient | 39:e98d5df6dc74 | 722 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 723 | } |
AzureIoTClient | 39:e98d5df6dc74 | 724 | else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0) |
AzureIoTClient | 39:e98d5df6dc74 | 725 | { |
AzureIoTClient | 39:e98d5df6dc74 | 726 | if (message_queue_set_max_message_enqueued_time_secs((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 727 | { |
AzureIoTClient | 39:e98d5df6dc74 | 728 | LogError("failed setting option %s", name); |
AzureIoTClient | 39:e98d5df6dc74 | 729 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 730 | } |
AzureIoTClient | 39:e98d5df6dc74 | 731 | else |
AzureIoTClient | 39:e98d5df6dc74 | 732 | { |
AzureIoTClient | 39:e98d5df6dc74 | 733 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 734 | } |
AzureIoTClient | 39:e98d5df6dc74 | 735 | } |
AzureIoTClient | 39:e98d5df6dc74 | 736 | else if (strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0) |
AzureIoTClient | 39:e98d5df6dc74 | 737 | { |
AzureIoTClient | 39:e98d5df6dc74 | 738 | if (message_queue_set_max_message_processing_time_secs((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 739 | { |
AzureIoTClient | 39:e98d5df6dc74 | 740 | LogError("failed setting option %s", name); |
AzureIoTClient | 39:e98d5df6dc74 | 741 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 742 | } |
AzureIoTClient | 39:e98d5df6dc74 | 743 | else |
AzureIoTClient | 39:e98d5df6dc74 | 744 | { |
AzureIoTClient | 39:e98d5df6dc74 | 745 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 746 | } |
AzureIoTClient | 39:e98d5df6dc74 | 747 | } |
AzureIoTClient | 39:e98d5df6dc74 | 748 | else if (strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0) |
AzureIoTClient | 39:e98d5df6dc74 | 749 | { |
AzureIoTClient | 39:e98d5df6dc74 | 750 | if (message_queue_set_max_retry_count((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 751 | { |
AzureIoTClient | 39:e98d5df6dc74 | 752 | LogError("failed setting option %s", name); |
AzureIoTClient | 39:e98d5df6dc74 | 753 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 754 | } |
AzureIoTClient | 39:e98d5df6dc74 | 755 | else |
AzureIoTClient | 39:e98d5df6dc74 | 756 | { |
AzureIoTClient | 39:e98d5df6dc74 | 757 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 758 | } |
AzureIoTClient | 39:e98d5df6dc74 | 759 | } |
AzureIoTClient | 39:e98d5df6dc74 | 760 | else |
AzureIoTClient | 39:e98d5df6dc74 | 761 | { |
AzureIoTClient | 39:e98d5df6dc74 | 762 | LogError("option %s is invalid", name); |
AzureIoTClient | 39:e98d5df6dc74 | 763 | result = __FAILURE__; |
AzureIoTClient | 39:e98d5df6dc74 | 764 | } |
AzureIoTClient | 39:e98d5df6dc74 | 765 | |
AzureIoTClient | 39:e98d5df6dc74 | 766 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 767 | } |
AzureIoTClient | 39:e98d5df6dc74 | 768 | |
AzureIoTClient | 39:e98d5df6dc74 | 769 | OPTIONHANDLER_HANDLE message_queue_retrieve_options(MESSAGE_QUEUE_HANDLE message_queue) |
AzureIoTClient | 39:e98d5df6dc74 | 770 | { |
AzureIoTClient | 39:e98d5df6dc74 | 771 | OPTIONHANDLER_HANDLE result; |
AzureIoTClient | 39:e98d5df6dc74 | 772 | |
AzureIoTClient | 39:e98d5df6dc74 | 773 | // Codes_SRS_MESSAGE_QUEUE_09_062: [If `message_queue` is NULL, message_queue_retrieve_options shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 774 | if (message_queue == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 775 | { |
AzureIoTClient | 39:e98d5df6dc74 | 776 | LogError("invalid argument (message_queue is NULL)"); |
AzureIoTClient | 39:e98d5df6dc74 | 777 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 778 | } |
AzureIoTClient | 39:e98d5df6dc74 | 779 | // Codes_SRS_MESSAGE_QUEUE_09_063: [An OPTIONHANDLER_HANDLE instance shall be created using OptionHandler_Create] |
AzureIoTClient | 39:e98d5df6dc74 | 780 | else if ((result = OptionHandler_Create(cloneOption, destroyOption, setOption)) == NULL) |
AzureIoTClient | 39:e98d5df6dc74 | 781 | { |
AzureIoTClient | 39:e98d5df6dc74 | 782 | // Codes_SRS_MESSAGE_QUEUE_09_064: [If an OPTIONHANDLER_HANDLE instance fails to be created, message_queue_retrieve_options shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 783 | LogError("failed creating OPTIONHANDLER_HANDLE"); |
AzureIoTClient | 39:e98d5df6dc74 | 784 | } |
AzureIoTClient | 39:e98d5df6dc74 | 785 | // Codes_SRS_MESSAGE_QUEUE_09_065: [Each option of `instance` shall be added to the OPTIONHANDLER_HANDLE instance using OptionHandler_AddOption] |
AzureIoTClient | 39:e98d5df6dc74 | 786 | else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, &message_queue->max_message_enqueued_time_secs) != OPTIONHANDLER_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 787 | { |
AzureIoTClient | 39:e98d5df6dc74 | 788 | LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_ENQUEUE_TIME_SECS); |
AzureIoTClient | 39:e98d5df6dc74 | 789 | // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 790 | OptionHandler_Destroy(result); |
AzureIoTClient | 39:e98d5df6dc74 | 791 | // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 792 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 793 | } |
AzureIoTClient | 39:e98d5df6dc74 | 794 | else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_PROCESSING_TIME_SECS, &message_queue->max_message_processing_time_secs) != OPTIONHANDLER_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 795 | { |
AzureIoTClient | 39:e98d5df6dc74 | 796 | LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_PROCESSING_TIME_SECS); |
AzureIoTClient | 39:e98d5df6dc74 | 797 | // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 798 | OptionHandler_Destroy(result); |
AzureIoTClient | 39:e98d5df6dc74 | 799 | // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 800 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 801 | } |
AzureIoTClient | 39:e98d5df6dc74 | 802 | else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_RETRY_COUNT, &message_queue->max_retry_count) != OPTIONHANDLER_OK) |
AzureIoTClient | 39:e98d5df6dc74 | 803 | { |
AzureIoTClient | 39:e98d5df6dc74 | 804 | LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_PROCESSING_TIME_SECS); |
AzureIoTClient | 39:e98d5df6dc74 | 805 | // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed] |
AzureIoTClient | 39:e98d5df6dc74 | 806 | OptionHandler_Destroy(result); |
AzureIoTClient | 39:e98d5df6dc74 | 807 | // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL] |
AzureIoTClient | 39:e98d5df6dc74 | 808 | result = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 809 | } |
AzureIoTClient | 39:e98d5df6dc74 | 810 | |
AzureIoTClient | 39:e98d5df6dc74 | 811 | // Codes_SRS_MESSAGE_QUEUE_09_068: [If no failures occur, message_queue_retrieve_options shall return the OPTIONHANDLER_HANDLE instance] |
AzureIoTClient | 39:e98d5df6dc74 | 812 | return result; |
AzureIoTClient | 56:8704100b3b54 | 813 | } |