source: azure_iot_hub/trunk/azure_iohub/iothub_client/src/iothub_client_retry_control.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 24.5 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include "internal/iothub_client_retry_control.h"
5
6#include <math.h>
7
8#include "azure_c_shared_utility/gballoc.h"
9#include "azure_c_shared_utility/agenttime.h"
10#include "azure_c_shared_utility/optimize_size.h"
11#include "azure_c_shared_utility/xlogging.h"
12
13#define RESULT_OK 0
14#define INDEFINITE_TIME ((time_t)-1)
15
16typedef struct RETRY_CONTROL_INSTANCE_TAG
17{
18 IOTHUB_CLIENT_RETRY_POLICY policy;
19 unsigned int max_retry_time_in_secs;
20
21 unsigned int initial_wait_time_in_secs;
22 unsigned int max_jitter_percent;
23
24 unsigned int retry_count;
25 time_t first_retry_time;
26 time_t last_retry_time;
27 unsigned int current_wait_time_in_secs;
28} RETRY_CONTROL_INSTANCE;
29
30typedef int (*RETRY_ACTION_EVALUATION_FUNCTION)(RETRY_CONTROL_INSTANCE* retry_state, RETRY_ACTION* retry_action);
31
32
33// ========== Helper Functions ========== //
34
35// ---------- Set/Retrieve Options Helpers ----------//
36
37static void* retry_control_clone_option(const char* name, const void* value)
38{
39 void* result;
40
41 if ((name == NULL) || (value == NULL))
42 {
43 LogError("Failed to clone option (either name (%p) or value (%p) are NULL)", name, value);
44 result = NULL;
45 }
46 else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
47 strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
48 {
49 unsigned int* cloned_value;
50
51 if ((cloned_value = (unsigned int*)malloc(sizeof(unsigned int))) == NULL)
52 {
53 LogError("Failed to clone option '%p' (malloc failed)", name);
54 result = NULL;
55 }
56 else
57 {
58 *cloned_value = *(unsigned int*)value;
59
60 result = (void*)cloned_value;
61 }
62 }
63 else
64 {
65 LogError("Failed to clone option (option with name '%s' is not suppported)", name);
66 result = NULL;
67 }
68
69 return result;
70}
71
72static void retry_control_destroy_option(const char* name, const void* value)
73{
74 if ((name == NULL) || (value == NULL))
75 {
76 LogError("Failed to destroy option (either name (%p) or value (%p) are NULL)", name, value);
77 }
78 else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
79 strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
80 {
81 free((void*)value);
82 }
83 else
84 {
85 LogError("Failed to destroy option (option with name '%s' is not suppported)", name);
86 }
87}
88
89// ========== _should_retry() Auxiliary Functions ========== //
90
91static int evaluate_retry_action(RETRY_CONTROL_INSTANCE* retry_control, RETRY_ACTION* retry_action)
92{
93 int result;
94
95 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_019: [If `retry_control->retry_count` is 0, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
96 if (retry_control->retry_count == 0)
97 {
98 *retry_action = RETRY_ACTION_RETRY_NOW;
99 result = RESULT_OK;
100 }
101 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_020: [If `retry_control->last_retry_time` is INDEFINITE_TIME and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, the evaluation function shall return non-zero]
102 else if (retry_control->last_retry_time == INDEFINITE_TIME &&
103 retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
104 {
105 LogError("Failed to evaluate retry action (last_retry_time is INDEFINITE_TIME)");
106 result = MU_FAILURE;
107 }
108 else
109 {
110 time_t current_time;
111
112 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_021: [`current_time` shall be set using get_time()]
113 if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
114 {
115 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_022: [If get_time() fails, the evaluation function shall return non-zero]
116 LogError("Failed to evaluate retry action (get_time() failed)");
117 result = MU_FAILURE;
118 }
119 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_023: [If `retry_control->max_retry_time_in_secs` is not 0 and (`current_time` - `retry_control->first_retry_time`) is greater than or equal to `retry_control->max_retry_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_STOP_RETRYING]
120 else if (retry_control->max_retry_time_in_secs > 0 &&
121 get_difftime(current_time, retry_control->first_retry_time) >= retry_control->max_retry_time_in_secs)
122 {
123 *retry_action = RETRY_ACTION_STOP_RETRYING;
124
125 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
126 result = RESULT_OK;
127 }
128 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_028: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_IMMEDIATE, retry_action shall be set to RETRY_ACTION_RETRY_NOW]
129 else if (retry_control->policy == IOTHUB_CLIENT_RETRY_IMMEDIATE)
130 {
131 *retry_action = RETRY_ACTION_RETRY_NOW;
132
133 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
134 result = RESULT_OK;
135 }
136 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_024: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is less than `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_LATER]
137 else if (get_difftime(current_time, retry_control->last_retry_time) < retry_control->current_wait_time_in_secs)
138 {
139 *retry_action = RETRY_ACTION_RETRY_LATER;
140
141 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
142 result = RESULT_OK;
143 }
144 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_025: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is greater or equal to `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
145 else
146 {
147 *retry_action = RETRY_ACTION_RETRY_NOW;
148
149 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
150 result = RESULT_OK;
151 }
152 }
153
154 return result;
155}
156
157static unsigned int calculate_next_wait_time(RETRY_CONTROL_INSTANCE* retry_control)
158{
159 unsigned int result;
160
161 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_029: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_INTERVAL, `calculate_next_wait_time` shall return `retry_control->initial_wait_time_in_secs`]
162 if (retry_control->policy == IOTHUB_CLIENT_RETRY_INTERVAL)
163 {
164 result = retry_control->initial_wait_time_in_secs;
165 }
166 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_030: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (`retry_control->retry_count`))]
167 else if (retry_control->policy == IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF)
168 {
169 result = retry_control->initial_wait_time_in_secs * (retry_control->retry_count);
170 }
171 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_031: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF, `calculate_next_wait_time` shall return (pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`)]
172 else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF)
173 {
174 result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs);
175 }
176 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_032: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `calculate_next_wait_time` shall return ((pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`) * (1 + (`retry_control->max_jitter_percent` / 100) * (rand() / RAND_MAX)))]
177 else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
178 {
179 double jitter_percent = (retry_control->max_jitter_percent / 100.0) * (rand() / ((double)RAND_MAX));
180
181 result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs * (1 + jitter_percent));
182 }
183 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_033: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_RANDOM, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (rand() / RAND_MAX))]
184 else if (retry_control->policy == IOTHUB_CLIENT_RETRY_RANDOM)
185 {
186 double random_percent = ((double)rand() / (double)RAND_MAX);
187 result = (unsigned int)(retry_control->initial_wait_time_in_secs * random_percent);
188 }
189 else
190 {
191 LogError("Failed to calculate the next wait time (policy %d is not expected)", retry_control->policy);
192
193 result = 0;
194 }
195
196 return result;
197}
198
199
200// ========== Public API ========== //
201
202int is_timeout_reached(time_t start_time, unsigned int timeout_in_secs, bool* is_timed_out)
203{
204 int result;
205
206 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_057: [If `start_time` is INDEFINITE_TIME, `is_timeout_reached` shall fail and return non-zero]
207 if (start_time == INDEFINITE_TIME)
208 {
209 LogError("Failed to verify timeout (start_time is INDEFINITE)");
210 result = MU_FAILURE;
211 }
212 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_058: [If `is_timed_out` is NULL, `is_timeout_reached` shall fail and return non-zero]
213 else if (is_timed_out == NULL)
214 {
215 LogError("Failed to verify timeout (is_timed_out is NULL)");
216 result = MU_FAILURE;
217 }
218 else
219 {
220 time_t current_time;
221
222 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_059: [`is_timeout_reached` shall obtain the `current_time` using get_time()]
223 if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
224 {
225 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_060: [If get_time() fails, `is_timeout_reached` shall fail and return non-zero]
226 LogError("Failed to verify timeout (get_time failed)");
227 result = MU_FAILURE;
228 }
229 else
230 {
231 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_061: [If (`current_time` - `start_time`) is greater or equal to `timeout_in_secs`, `is_timed_out` shall be set to true]
232 if (get_difftime(current_time, start_time) >= timeout_in_secs)
233 {
234 *is_timed_out = true;
235 }
236 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_062: [If (`current_time` - `start_time`) is less than `timeout_in_secs`, `is_timed_out` shall be set to false]
237 else
238 {
239 *is_timed_out = false;
240 }
241
242 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_063: [If no errors occur, `is_timeout_reached` shall return 0]
243 result = RESULT_OK;
244 }
245 }
246
247 return result;
248}
249
250void retry_control_reset(RETRY_CONTROL_HANDLE retry_control_handle)
251{
252 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_034: [If `retry_control_handle` is NULL, `retry_control_reset` shall return]
253 if (retry_control_handle == NULL)
254 {
255 LogError("Failed to reset the retry control (retry_state_handle is NULL)");
256 }
257 else
258 {
259 RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
260
261 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_035: [`retry_control` shall have fields `retry_count` and `current_wait_time_in_secs` set to 0 (zero), `first_retry_time` and `last_retry_time` set to INDEFINITE_TIME]
262 retry_control->retry_count = 0;
263 retry_control->current_wait_time_in_secs = 0;
264 retry_control->first_retry_time = INDEFINITE_TIME;
265 retry_control->last_retry_time = INDEFINITE_TIME;
266 }
267}
268
269RETRY_CONTROL_HANDLE retry_control_create(IOTHUB_CLIENT_RETRY_POLICY policy, unsigned int max_retry_time_in_secs)
270{
271 RETRY_CONTROL_INSTANCE* retry_control;
272
273 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_002: [`retry_control_create` shall allocate memory for the retry control instance structure (a.k.a. `retry_control`)]
274 if ((retry_control = (RETRY_CONTROL_INSTANCE*)malloc(sizeof(RETRY_CONTROL_INSTANCE))) == NULL)
275 {
276 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_003: [If malloc fails, `retry_control_create` shall fail and return NULL]
277 LogError("Failed creating the retry control (malloc failed)");
278 }
279 else
280 {
281 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_004: [The parameters passed to `retry_control_create` shall be saved into `retry_control`]
282 memset(retry_control, 0, sizeof(RETRY_CONTROL_INSTANCE));
283 retry_control->policy = policy;
284 retry_control->max_retry_time_in_secs = max_retry_time_in_secs;
285
286 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_005: [If `policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF or IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `retry_control->initial_wait_time_in_secs` shall be set to 1]
287 if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF ||
288 retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
289 {
290 retry_control->initial_wait_time_in_secs = 1;
291 }
292 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_006: [Otherwise `retry_control->initial_wait_time_in_secs` shall be set to 5]
293 else
294 {
295 retry_control->initial_wait_time_in_secs = 5;
296 }
297
298 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_007: [`retry_control->max_jitter_percent` shall be set to 5]
299 retry_control->max_jitter_percent = 5;
300
301 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_008: [The remaining fields in `retry_control` shall be initialized according to retry_control_reset()]
302 retry_control_reset(retry_control);
303 }
304
305 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_009: [If no errors occur, `retry_control_create` shall return a handle to `retry_control`]
306 return (RETRY_CONTROL_HANDLE)retry_control;
307}
308
309void retry_control_destroy(RETRY_CONTROL_HANDLE retry_control_handle)
310{
311 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_055: [If `retry_control_handle` is NULL, `retry_control_destroy` shall return]
312 if (retry_control_handle == NULL)
313 {
314 LogError("Failed to destroy the retry control (retry_control_handle is NULL)");
315 }
316 else
317 {
318 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_056: [`retry_control_destroy` shall destroy `retry_control_handle` using free()]
319 free(retry_control_handle);
320 }
321}
322
323int retry_control_should_retry(RETRY_CONTROL_HANDLE retry_control_handle, RETRY_ACTION* retry_action)
324{
325 int result;
326
327 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_010: [If `retry_control_handle` or `retry_action` are NULL, `retry_control_should_retry` shall fail and return non-zero]
328 if ((retry_control_handle == NULL) || (retry_action == NULL))
329 {
330 LogError("Failed to evaluate if retry should be attempted (either retry_control_handle (%p) or retry_action (%p) are NULL)", retry_control_handle, retry_action);
331 result = MU_FAILURE;
332 }
333 else
334 {
335 RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
336
337 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_027: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_NONE, retry_action shall be set to RETRY_ACTION_STOP_RETRYING and return immediatelly with result 0]
338 if (retry_control->policy == IOTHUB_CLIENT_RETRY_NONE)
339 {
340 *retry_action = RETRY_ACTION_STOP_RETRYING;
341 result = RESULT_OK;
342 }
343 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_011: [If `retry_control->first_retry_time` is INDEFINITE_TIME, it shall be set using get_time()]
344 else if (retry_control->first_retry_time == INDEFINITE_TIME && (retry_control->first_retry_time = get_time(NULL)) == INDEFINITE_TIME)
345 {
346 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_012: [If get_time() fails, `retry_control_should_retry` shall fail and return non-zero]
347 LogError("Failed to evaluate if retry should be attempted (get_time() failed)");
348 result = MU_FAILURE;
349 }
350 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_013: [evaluate_retry_action() shall be invoked]
351 else if (evaluate_retry_action(retry_control, retry_action) != RESULT_OK)
352 {
353 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_014: [If evaluate_retry_action() fails, `retry_control_should_retry` shall fail and return non-zero]
354 LogError("Failed to evaluate if retry should be attempted (evaluate_retry_action() failed)");
355 result = MU_FAILURE;
356 }
357 else
358 {
359 if (*retry_action == RETRY_ACTION_RETRY_NOW)
360 {
361 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_015: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW, `retry_control->retry_count` shall be incremented by 1]
362 retry_control->retry_count++;
363
364 if (retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
365 {
366 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_016: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->last_retry_time` shall be set using get_time()]
367 retry_control->last_retry_time = get_time(NULL);
368
369 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_017: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->current_wait_time_in_secs` shall be set using calculate_next_wait_time()]
370 retry_control->current_wait_time_in_secs = calculate_next_wait_time(retry_control);
371 }
372 }
373
374 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_018: [If no errors occur, `retry_control_should_retry` shall return 0]
375 result = RESULT_OK;
376 }
377 }
378
379 return result;
380}
381
382int retry_control_set_option(RETRY_CONTROL_HANDLE retry_control_handle, const char* name, const void* value)
383{
384 int result;
385
386 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_036: [If `retry_control_handle`, `name` or `value` are NULL, `retry_control_set_option` shall fail and return non-zero]
387 if (retry_control_handle == NULL || name == NULL || value == NULL)
388 {
389 LogError("Failed to set option (either retry_state_handle (%p), name (%p) or value (%p) are NULL)", retry_control_handle, name, value);
390 result = MU_FAILURE;
391 }
392 else
393 {
394 RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
395
396 if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0)
397 {
398 unsigned int cast_value = *((unsigned int*)value);
399
400 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_037: [If `name` is "initial_wait_time_in_secs" and `value` is less than 1, `retry_control_set_option` shall fail and return non-zero]
401 if (cast_value < 1)
402 {
403 LogError("Failed to set option '%s' (value must be equal or greater to 1)", name);
404 result = MU_FAILURE;
405 }
406 else
407 {
408 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_038: [If `name` is "initial_wait_time_in_secs", `value` shall be saved on `retry_control->initial_wait_time_in_secs`]
409 retry_control->initial_wait_time_in_secs = cast_value;
410
411 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
412 result = RESULT_OK;
413 }
414 }
415 else if (strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
416 {
417 unsigned int cast_value = *((unsigned int*)value);
418
419 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_039: [If `name` is "max_jitter_percent" and `value` is less than 0 or greater than 100, `retry_control_set_option` shall fail and return non-zero]
420 if (cast_value > 100) // it's unsigned int, it doesn't need to be checked for less than zero.
421 {
422 LogError("Failed to set option '%s' (value must be in the range 0 to 100)", name);
423 result = MU_FAILURE;
424 }
425 else
426 {
427 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_040: [If `name` is "max_jitter_percent", value shall be saved on `retry_control->max_jitter_percent`]
428 retry_control->max_jitter_percent = cast_value;
429
430 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
431 result = RESULT_OK;
432 }
433 }
434 else if (strcmp(RETRY_CONTROL_OPTION_SAVED_OPTIONS, name) == 0)
435 {
436 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_041: [If `name` is "retry_control_options", value shall be fed to `retry_control` using OptionHandler_FeedOptions]
437 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, retry_control_handle) != OPTIONHANDLER_OK)
438 {
439 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_042: [If OptionHandler_FeedOptions fails, `retry_control_set_option` shall fail and return non-zero]
440 LogError("messenger_set_option failed (OptionHandler_FeedOptions failed)");
441 result = MU_FAILURE;
442 }
443 else
444 {
445 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, `retry_control_set_option` shall return 0]
446 result = RESULT_OK;
447 }
448 }
449 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_043: [If `name` is not a supported option, `retry_control_set_option` shall fail and return non-zero]
450 else
451 {
452 LogError("messenger_set_option failed (option with name '%s' is not suppported)", name);
453 result = MU_FAILURE;
454 }
455 }
456
457 return result;
458}
459
460OPTIONHANDLER_HANDLE retry_control_retrieve_options(RETRY_CONTROL_HANDLE retry_control_handle)
461{
462 OPTIONHANDLER_HANDLE result;
463
464 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_045: [If `retry_control_handle`, `retry_control_retrieve_options` shall fail and return NULL]
465 if (retry_control_handle == NULL)
466 {
467 LogError("Failed to retrieve options (retry_state_handle is NULL)");
468 result = NULL;
469 }
470 else
471 {
472 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_046: [An instance of OPTIONHANDLER_HANDLE (a.k.a. `options`) shall be created using OptionHandler_Create]
473 OPTIONHANDLER_HANDLE options = OptionHandler_Create(retry_control_clone_option, retry_control_destroy_option, (pfSetOption)retry_control_set_option);
474
475 if (options == NULL)
476 {
477 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_047: [If OptionHandler_Create fails, `retry_control_retrieve_options` shall fail and return NULL]
478 LogError("Failed to retrieve options (OptionHandler_Create failed)");
479 result = NULL;
480 }
481 else
482 {
483 RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
484
485 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_050: [`retry_control->initial_wait_time_in_secs` shall be added to `options` using OptionHandler_Add]
486 if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, (void*)&retry_control->initial_wait_time_in_secs) != OPTIONHANDLER_OK)
487 {
488 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
489 LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
490 result = NULL;
491 }
492 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_051: [`retry_control->max_jitter_percent` shall be added to `options` using OptionHandler_Add]
493 else if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, (void*)&retry_control->max_jitter_percent) != OPTIONHANDLER_OK)
494 {
495 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
496 LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
497 result = NULL;
498 }
499 else
500 {
501 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_054: [If no errors occur, `retry_control_retrieve_options` shall return the OPTIONHANDLER_HANDLE instance]
502 result = options;
503 }
504
505 if (result == NULL)
506 {
507 // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_053: [If any failures occur, `retry_control_retrieve_options` shall release any memory it has allocated]
508 OptionHandler_Destroy(options);
509 }
510 }
511 }
512
513 return result;
514}
Note: See TracBrowser for help on using the repository browser.