63 static int evel_measurement_interval;
69 static pthread_mutex_t evel_measurement_interval_mutex;
75 static bool evel_provide_throttling_state;
80 static char * evel_command_type_value;
85 static char * evel_measurement_interval_value;
90 static char * evel_throttle_spec_domain_value;
111 static const char *
const evel_jcs_strings[
EVEL_JCS_MAX] = {
113 "EVEL_JCS_COMMAND_LIST",
114 "EVEL_JCS_COMMAND_LIST_ENTRY",
117 "EVEL_JCS_FIELD_NAMES",
118 "EVEL_JCS_PAIRS_LIST",
119 "EVEL_JCS_PAIRS_LIST_ENTRY",
120 "EVEL_JCS_NV_PAIR_NAMES" 126 #define JSON_TOKEN_TYPES (JSMN_PRIMITIVE + 1) 142 "measurementsForVfScaling",
156 static struct hsearch_data * evel_throttle_hash_create(
DLIST * hash_keys);
162 const int num_required,
166 static char * evel_stack_strdup(
const MEMORY_CHUNK *
const chunk,
175 static void evel_debug_token(
const MEMORY_CHUNK *
const chunk,
177 static void evel_command_list_response(
MEMORY_CHUNK *
const post);
178 static int evel_json_encode_throttle(
char *
const json,
const int max_size);
179 static int evel_json_encode_throttle_spec(
char *
const json,
182 static int evel_json_encode_nv_pairs(
char *
const json,
185 static void evel_close_command();
186 static void evel_open_command();
187 static void evel_set_throttling_spec();
188 static void evel_set_measurement_interval();
189 static void evel_open_throttle_spec();
190 static void evel_close_throttle_spec();
192 static void evel_open_nv_pairs_list_entry();
193 static void evel_close_nv_pairs_list_entry();
194 static void evel_store_nv_pair_field_name(
char *
const value);
195 static void evel_store_nv_pair_name(
char *
const item);
196 static void evel_store_suppressed_field_name(
char *
const item);
215 pthread_mutex_lock(&evel_measurement_interval_mutex);
216 result = evel_measurement_interval;
217 pthread_mutex_unlock(&evel_measurement_interval_mutex);
240 result = evel_throttle_spec[domain];
255 const char *
const field_name)
257 bool suppress =
false;
264 assert(field_name != NULL);
273 hash_query.key = (
char *
const) field_name;
274 suppress = (hsearch_r(hash_query,
294 const char *
const field_name,
295 const char *
const name)
299 bool suppress =
false;
306 assert(field_name != NULL);
307 assert(name != NULL);
316 hash_query.key = (
char *
const) field_name;
317 hit = (hsearch_r(hash_query,
323 nv_pairs = hash_result->data;
335 hash_query.key = (
char *
const) name;
336 suppress = (hsearch_r(hash_query,
361 evel_throttle_spec[ii] = NULL;
364 pthread_rc = pthread_mutex_init(&evel_measurement_interval_mutex, NULL);
365 assert(pthread_rc == 0);
367 evel_measurement_interval = EVEL_MEASUREMENT_INTERVAL_UKNOWN;
386 if (evel_throttle_spec[ii] != NULL)
388 evel_throttle_free(evel_throttle_spec[ii]);
389 evel_throttle_spec[ii] = NULL;
393 pthread_rc = pthread_mutex_destroy(&evel_measurement_interval_mutex);
394 assert(pthread_rc == 0);
418 assert(throttle_spec != NULL);
430 if (nv_pairs_count > 0)
450 while (dlist_item != NULL)
458 assert(nv_pairs != NULL);
460 hash_add.data = nv_pairs;
481 struct hsearch_data * evel_throttle_hash_create(
DLIST * hash_keys)
484 struct hsearch_data * hash_table;
492 assert(hash_keys != NULL);
500 EVEL_DEBUG(
"Populating table for %d keys", key_count);
502 hash_table = calloc(1,
sizeof(
struct hsearch_data));
503 assert(hash_table != NULL);
508 if (hcreate_r(key_count * 2, hash_table) != 0)
512 while (dlist_item != NULL)
514 assert(dlist_item->
item != NULL);
520 hash_add.key = dlist_item->
item;
521 hash_add.data = dlist_item->
item;
522 hsearch_r(hash_add, ENTER, &add_result, hash_table);
558 assert(throttle_spec != NULL);
578 while (field_name != NULL)
585 while (nv_pairs != NULL)
587 evel_throttle_free_nv_pair(nv_pairs);
603 char * suppressed_name;
610 assert(nv_pairs != NULL);
625 while (suppressed_name != NULL)
627 free(suppressed_name);
650 const int num_tokens,
665 assert(chunk != NULL);
666 assert(json_tokens != NULL);
672 evel_init_json_stack(json_stack, chunk);
677 evel_provide_throttling_state =
false;
678 evel_command_type_value = NULL;
679 evel_measurement_interval_value = NULL;
680 evel_throttle_spec_domain_value = NULL;
682 evel_temp_throttle = NULL;
690 while (json_ok && (token_index < num_tokens))
692 const jsmntok_t *
const token = &json_tokens[token_index];
696 evel_debug_token(chunk, token);
702 entry = &json_stack->
entry[json_stack->
level];
714 EVEL_ERROR(
"Unexpected JSON state %d at token %d (%d)",
728 EVEL_ERROR(
"Unexpected JSON state %d at token %d (%d)",
737 evel_stack_store_key(json_stack, token);
741 evel_stack_store_value(json_stack, token);
745 evel_stack_store_item(json_stack, token);
749 EVEL_ERROR(
"Unexpected JSON state %d at token %d (%d)",
758 evel_stack_store_value(json_stack, token);
762 evel_stack_store_item(json_stack, token);
766 EVEL_ERROR(
"Unexpected JSON state %d at token %d (%d)",
774 EVEL_ERROR(
"Unexpected JSON format at token %d (%d)",
775 token_index, token->
type);
783 evel_stack_pop(json_stack);
792 evel_stack_cleanup(json_stack);
799 evel_command_list_response(post);
805 assert(evel_command_type_value == NULL);
806 assert(evel_measurement_interval_value == NULL);
807 assert(evel_throttle_spec_domain_value == NULL);
809 assert(evel_temp_throttle == NULL);
825 char * evel_stack_strdup(
const MEMORY_CHUNK *
const chunk,
839 assert(result != NULL);
860 json_stack->
level = 0;
861 entry = json_stack->
entry;
866 json_stack->
chunk = chunk;
880 const int num_required,
892 assert(json_stack != NULL);
893 assert(json_stack->
level >= 0);
902 EVEL_ERROR(
"JSON Nesting is too deep - stop processing");
910 entry = &json_stack->
entry[json_stack->
level];
923 if (strcmp(key,
"commandList") == 0)
930 if (strcmp(key,
"command") == 0)
938 if (strcmp(key,
"eventDomainThrottleSpecification") == 0)
940 evel_open_throttle_spec();
946 if (strcmp(key,
"suppressedFieldNames") == 0)
950 else if (strcmp(key,
"suppressedNvPairsList") == 0)
957 if (strcmp(key,
"suppressedNvPairNames") == 0)
967 EVEL_ERROR(
"Unexpected JSON key %s in state %d",
981 const int COMMAND_LIST_LEVEL = 2;
982 const int NV_PAIRS_LIST_LEVEL = 6;
985 (json_stack->
level == NV_PAIRS_LIST_LEVEL))
990 evel_open_nv_pairs_list_entry();
995 (json_stack->
level == COMMAND_LIST_LEVEL))
1007 json_stack->
level++;
1010 entry = &json_stack->
entry[json_stack->
level];
1039 assert(json_stack != NULL);
1040 assert(json_stack->
level >= 0);
1043 entry = &json_stack->
entry[json_stack->
level];
1059 evel_close_command();
1064 evel_close_throttle_spec();
1077 evel_close_nv_pairs_list_entry();
1102 json_stack->
level--;
1140 assert(json_stack != NULL);
1141 assert(json_stack->
level >= 0);
1144 entry = &json_stack->
entry[json_stack->
level];
1145 while ((json_stack->
level > 0))
1160 json_stack->
level--;
1168 if (evel_command_type_value != NULL)
1170 free(evel_command_type_value);
1171 evel_command_type_value = NULL;
1173 if (evel_measurement_interval_value != NULL)
1175 free(evel_measurement_interval_value);
1176 evel_measurement_interval_value = NULL;
1178 if (evel_throttle_spec_domain_value != NULL)
1180 free(evel_throttle_spec_domain_value);
1181 evel_throttle_spec_domain_value = NULL;
1184 if (evel_temp_throttle != NULL)
1186 evel_throttle_free(evel_temp_throttle);
1187 evel_temp_throttle = NULL;
1211 assert(json_stack != NULL);
1212 assert(json_stack->
level >= 0);
1218 entry = &json_stack->
entry[json_stack->
level];
1223 entry->
json_key = evel_stack_strdup(json_stack->
chunk, token);
1252 assert(json_stack != NULL);
1253 assert(json_stack->
level >= 0);
1260 entry = &json_stack->
entry[json_stack->
level];
1261 value = evel_stack_strdup(json_stack->
chunk, token);
1268 if (strcmp(entry->
json_key,
"commandType") == 0)
1270 evel_command_type_value = value;
1273 else if (strcmp(entry->
json_key,
"measurementInterval") == 0)
1275 evel_measurement_interval_value = value;
1281 if (strcmp(entry->
json_key,
"eventDomain") == 0)
1283 evel_throttle_spec_domain_value = value;
1289 if (strcmp(entry->
json_key,
"nvPairFieldName") == 0)
1291 evel_store_nv_pair_field_name(value);
1339 assert(json_stack != NULL);
1340 assert(json_stack->
level >= 0);
1347 entry = &json_stack->
entry[json_stack->
level];
1348 item = evel_stack_strdup(json_stack->
chunk, token);
1355 evel_store_nv_pair_name(item);
1360 evel_store_suppressed_field_name(item);
1407 evel_jcs_strings[new_state]);
1408 evel_json_command_state = new_state;
1419 void evel_debug_token(
const MEMORY_CHUNK *
const chunk,
1429 assert(token->
type > 0);
1437 EVEL_DEBUG(
"JSON token type: %s", evel_json_token_strings[token->
type]);
1449 void evel_command_list_response(
MEMORY_CHUNK *
const post)
1458 assert(post != NULL);
1459 assert(post->
memory == NULL);
1461 if (evel_provide_throttling_state)
1469 assert(json_post != NULL);
1471 post->
memory = json_post;
1473 evel_provide_throttling_state =
false;
1486 int evel_json_encode_throttle(
char *
const json,
const int max_size)
1498 assert(json != NULL);
1499 assert(max_size > 0);
1507 if (evel_throttle_spec[domain] != NULL)
1517 offset += snprintf(json + offset, max_size - offset,
1518 "{\"eventThrottlingState\": {");
1519 offset += snprintf(json + offset, max_size - offset,
1520 "\"eventThrottlingMode\": \"%s\"",
1521 throttled ?
"throttled" :
"normal");
1524 offset += snprintf(json + offset, max_size - offset,
1525 ", \"eventDomainThrottleSpecificationList\": [");
1527 domain_added =
false;
1530 if (evel_throttle_spec[domain] != NULL)
1534 offset += snprintf(json + offset, max_size - offset,
", ");
1537 offset += evel_json_encode_throttle_spec(json + offset,
1540 domain_added =
true;
1544 offset += snprintf(json + offset, max_size - offset,
"]");
1547 offset += snprintf(json + offset, max_size - offset,
"}}");
1561 int evel_json_encode_throttle_spec(
char *
const json,
1575 assert(evel_throttle_spec[domain] != NULL);
1577 throttle_spec = evel_throttle_spec[domain];
1583 offset += snprintf(json + offset, max_size - offset,
1585 offset += snprintf(json + offset, max_size - offset,
1586 "\"eventDomain\": \"%s\"",
1587 evel_domain_strings[domain]);
1593 if (dlist_item != NULL)
1595 offset += snprintf(json + offset, max_size - offset,
1596 ", \"suppressedFieldNames\": [");
1597 while (dlist_item != NULL)
1599 char * suppressed_field = dlist_item->
item;
1600 assert(suppressed_field != NULL);
1602 offset += snprintf(json + offset, max_size - offset,
1603 "\"%s\"", suppressed_field);
1605 if (dlist_item != NULL)
1607 offset += snprintf(json + offset, max_size - offset,
", ");
1611 offset += snprintf(json + offset, max_size - offset,
"]");
1618 if (dlist_item != NULL)
1620 offset += snprintf(json + offset, max_size - offset,
1621 ", \"suppressedNvPairsList\": [");
1622 while (dlist_item != NULL)
1624 offset += evel_json_encode_nv_pairs(json + offset,
1628 if (dlist_item != NULL)
1630 offset += snprintf(json + offset, max_size - offset,
", ");
1634 offset += snprintf(json + offset, max_size - offset,
"]");
1637 offset += snprintf(json + offset, max_size - offset,
"}");
1651 int evel_json_encode_nv_pairs(
char *
const json,
1662 assert(nv_pairs != NULL);
1670 offset += snprintf(json + offset, max_size - offset,
"{");
1671 offset += snprintf(json + offset, max_size - offset,
1672 "\"nvPairFieldName\": \"%s\"",
1675 offset += snprintf(json + offset, max_size - offset,
1676 ", \"suppressedNvPairNames\": [");
1677 while (dlist_item != NULL)
1679 name = dlist_item->
item;
1680 assert(name != NULL);
1681 offset += snprintf(json + offset, max_size - offset,
"\"%s\"", name);
1683 if (dlist_item != NULL)
1685 offset += snprintf(json + offset, max_size - offset,
", ");
1688 offset += snprintf(json + offset, max_size - offset,
"]");
1689 offset += snprintf(json + offset, max_size - offset,
"}");
1699 void evel_open_command()
1706 assert(evel_command_type_value == NULL);
1707 assert(evel_measurement_interval_value == NULL);
1715 void evel_close_command()
1729 if (evel_command_type_value != NULL)
1731 EVEL_DEBUG(
"Closing command %s", evel_command_type_value);
1733 if (strcmp(evel_command_type_value,
"provideThrottlingState") == 0)
1735 evel_provide_throttling_state =
true;
1737 else if (strcmp(evel_command_type_value,
"throttlingSpecification") == 0)
1739 evel_set_throttling_spec();
1741 else if (strcmp(evel_command_type_value,
"measurementIntervalChange") == 0)
1743 evel_set_measurement_interval();
1747 EVEL_ERROR(
"Ignoring unknown commandType: %s\n",
1748 evel_command_type_value);
1754 free(evel_command_type_value);
1755 evel_command_type_value = NULL;
1763 if (evel_temp_throttle != NULL)
1765 evel_throttle_free(evel_temp_throttle);
1766 evel_temp_throttle = NULL;
1778 if (evel_measurement_interval_value != NULL)
1780 free(evel_measurement_interval_value);
1781 evel_measurement_interval_value = NULL;
1790 void evel_set_throttling_spec()
1794 if ((evel_throttle_spec_domain >= 0) &&
1797 EVEL_DEBUG(
"Updating throttle spec for domain: %s",
1798 evel_domain_strings[evel_throttle_spec_domain]);
1804 if (evel_throttle_spec[evel_throttle_spec_domain] != NULL)
1806 evel_throttle_free(evel_throttle_spec[evel_throttle_spec_domain]);
1812 if (evel_temp_throttle != NULL)
1814 evel_throttle_finalize(evel_temp_throttle);
1822 evel_throttle_spec[evel_throttle_spec_domain] = evel_temp_throttle;
1823 evel_temp_throttle = NULL;
1832 void evel_set_measurement_interval()
1836 if (evel_measurement_interval_value != NULL)
1838 const long int value = strtol(evel_measurement_interval_value, NULL, 10);
1840 if ((value >= 0) && (value <= INT_MAX))
1845 EVEL_DEBUG(
"Updating measurement interval to %d\n", value);
1847 pthread_mutex_lock(&evel_measurement_interval_mutex);
1848 evel_measurement_interval = value;
1849 pthread_mutex_unlock(&evel_measurement_interval_mutex);
1853 EVEL_ERROR(
"Ignoring invalid measurement interval: %s",
1854 evel_measurement_interval_value);
1864 void evel_open_throttle_spec()
1871 assert(evel_throttle_spec_domain_value == NULL);
1873 assert(evel_temp_throttle == NULL);
1880 assert(evel_temp_throttle != NULL);
1892 void evel_close_throttle_spec()
1899 if (evel_throttle_spec_domain_value != NULL)
1901 evel_throttle_spec_domain =
1902 evel_decode_domain(evel_throttle_spec_domain_value);
1903 free(evel_throttle_spec_domain_value);
1904 evel_throttle_spec_domain_value = NULL;
1911 if (evel_temp_throttle != NULL)
1916 free(evel_temp_throttle);
1917 evel_temp_throttle = NULL;
1940 assert(domain_value != NULL);
1945 assert(evel_domain_strings[ii] != NULL);
1946 if (strcmp(evel_domain_strings[ii], domain_value) == 0)
1960 void evel_open_nv_pairs_list_entry()
1969 assert(evel_temp_throttle != NULL);
1976 assert(nv_pairs != NULL);
1988 void evel_close_nv_pairs_list_entry()
1998 nv_pairs = evel_get_last_nv_pairs();
2009 assert(popped == nv_pairs);
2010 evel_throttle_free_nv_pair(popped);
2021 void evel_store_nv_pair_field_name(
char *
const value)
2030 nv_pairs = evel_get_last_nv_pairs();
2045 void evel_store_nv_pair_name(
char *
const item)
2054 nv_pairs = evel_get_last_nv_pairs();
2069 void evel_store_suppressed_field_name(
char *
const item)
2076 assert(evel_temp_throttle != NULL);
2101 assert(evel_temp_throttle != NULL);
2107 assert(dlist_item != NULL);
2108 nv_pairs = dlist_item->
item;
2109 assert(nv_pairs != NULL);
DLIST suppressed_field_names
EVEL_EVENT_DOMAINS
Event domains for the various events we support.
EVEL_JSON_STATE
The nature of the next token that we are iterating through.
#define EVEL_DEBUG(FMT,...)
void evel_throttle_terminate()
Clean up event throttling.
EVEL_JSON_STATE json_state
Suppressed NV pairs list entry.
void evel_throttle_initialize()
Initialize event throttling to the default state.
DLIST_ITEM * dlist_get_first(DLIST *list)
An entry in the JSON stack.
void dlist_initialize(DLIST *list)
List initialization.
A chunk of memory used in the cURL functions.
bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC *throttle_spec, const char *const field_name)
Determine whether a field_name should be suppressed.
int dlist_count(DLIST *list)
DLIST suppressed_nv_pairs_list
char * nv_pair_field_name
EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain)
Return the EVEL_THROTTLE_SPEC for a given domain.
EVEL_JSON_STACK_ENTRY entry[EVEL_JSON_STACK_DEPTH]
Event Throttling Specification for a domain which is in a throttled state.
EVEL_JSON_COMMAND_STATE evel_json_command_state
#define EVEL_JSON_STACK_DEPTH
#define EVEL_ERROR(FMT,...)
DLIST suppressed_nv_pair_names
DLIST_ITEM * dlist_get_last(DLIST *list)
EVEL_JSON_COMMAND_STATE
States which we move through during JSON processing, tracking our way through the supported JSON stru...
void * dlist_pop_last(DLIST *list)
void dlist_push_last(DLIST *list, void *item)
A Heartbeat event (event header only).
int evel_get_measurement_interval()
Return the current measurement interval provided by the Event Listener.
struct hsearch_data * hash_nv_pairs_list
DLIST_ITEM * dlist_get_next(DLIST_ITEM *item)
bool evel_handle_command_list(const MEMORY_CHUNK *const chunk, const jsmntok_t *const json_tokens, const int num_tokens, MEMORY_CHUNK *const post)
Handle a JSON response from the listener, as a list of tokens from JSMN.
struct hsearch_data * hash_field_names
EVEL throttle definitions.
Double-linked list structure.
const MEMORY_CHUNK * chunk
#define EVEL_MAX_JSON_BODY
bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC *throttle_spec, const char *const field_name, const char *const name)
Determine whether a name-value pair should be allowed (not suppressed).
#define EVEL_MAX_RESPONSE_TOKENS
Maximum number of tokens that we allow for in a JSON response.
struct hsearch_data * hash_nv_pair_names
int dlist_is_empty(DLIST *list)