1 /*************************************************************************//**
3 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
5 * Unless otherwise specified, all software contained herein is
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 ****************************************************************************/
19 /**************************************************************************//**
21 * Implementation of EVEL functions relating to Other domain.
23 *****************************************************************************/
30 #include "evel_internal.h"
32 /**************************************************************************//**
33 * Create a new Other event.
35 * @note The mandatory fields on the Other must be supplied to this factory
36 * function and are immutable once set. Optional fields have explicit
37 * setter functions, but again values may only be set once so that the
38 * Other has immutable properties.
39 * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is
40 * not used (i.e. posted) it must be released using ::evel_free_other.
41 * @retval NULL Failed to create the event.
42 *****************************************************************************/
43 EVENT_OTHER * evel_new_other(const char* ev_name, const char *ev_id)
45 EVENT_OTHER * other = NULL;
48 /***************************************************************************/
49 /* Check preconditions. */
50 /***************************************************************************/
52 /***************************************************************************/
53 /* Allocate the Other. */
54 /***************************************************************************/
55 other = malloc(sizeof(EVENT_OTHER));
58 log_error_state("Out of memory");
61 memset(other, 0, sizeof(EVENT_OTHER));
62 EVEL_DEBUG("New Other is at %lp", other);
64 /***************************************************************************/
65 /* Initialize the header & the Other fields. Optional string values are */
66 /* uninitialized (NULL). */
67 /***************************************************************************/
68 evel_init_header_nameid(&other->header,ev_name,ev_id);
69 other->header.event_domain = EVEL_DOMAIN_OTHER;
70 other->major_version = EVEL_OTHER_EVENT_MAJOR_VERSION;
71 other->minor_version = EVEL_OTHER_EVENT_MINOR_VERSION;
73 other->namedarrays = NULL;
74 dlist_initialize(&other->jsonobjects);
75 dlist_initialize(&other->namedvalues);
82 /**************************************************************************//**
83 * Set the Event Type property of the Other.
85 * @note The property is treated as immutable: it is only valid to call
86 * the setter once. However, we don't assert if the caller tries to
87 * overwrite, just ignoring the update instead.
89 * @param other Pointer to the Other.
90 * @param type The Event Type to be set. ASCIIZ string. The caller
91 * does not need to preserve the value once the function
93 *****************************************************************************/
94 void evel_other_type_set(EVENT_OTHER * other,
95 const char * const type)
99 /***************************************************************************/
100 /* Check preconditions and call evel_header_type_set. */
101 /***************************************************************************/
102 assert(other != NULL);
103 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
104 evel_header_type_set(&other->header, type);
109 /**************************************************************************//**
110 * Set size of Named arrays hash table
112 * The max size of hash table is passed
114 * @param other Pointer to the Other.
115 * @param size size of hashtable
116 *****************************************************************************/
117 void evel_other_field_set_namedarraysize(EVENT_OTHER * other, const int size)
121 /***************************************************************************/
122 /* Check preconditions. */
123 /***************************************************************************/
124 assert(other != NULL);
125 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
126 assert(other->namedarrays == NULL);
129 EVEL_DEBUG("Adding Named array");
131 other->namedarrays = ht_create(size);
137 /**************************************************************************//**
138 * Add a json object to jsonObject list.
140 * The name and value are null delimited ASCII strings. The library takes
141 * a copy so the caller does not have to preserve values after the function
144 * @param other Pointer to the Other.
145 * @param size size of hashtable
146 *****************************************************************************/
147 void evel_other_field_add_namedarray(EVENT_OTHER * other, const char *hashname, char * name, char *value)
149 OTHER_FIELD * other_field = NULL;
153 /***************************************************************************/
154 /* Check preconditions. */
155 /***************************************************************************/
156 assert(other != NULL);
157 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
158 assert(other->namedarrays != NULL);
160 EVEL_DEBUG("Adding values to Named array");
162 EVEL_DEBUG("Adding name=%s value=%s", name, value);
163 other_field = malloc(sizeof(OTHER_FIELD));
164 assert(other_field != NULL);
165 memset(other_field, 0, sizeof(OTHER_FIELD));
166 other_field->name = strdup(name);
167 other_field->value = strdup(value);
168 assert(other_field->name != NULL);
169 assert(other_field->value != NULL);
172 list = (DLIST *)ht_get(other->namedarrays, hashname);
175 DLIST * nlist = malloc(sizeof(DLIST));
176 dlist_initialize(nlist);
177 dlist_push_last(nlist, other_field);
178 ht_set(other->namedarrays, hashname,(void*)nlist);
179 EVEL_DEBUG("Created to new namedarray table %p",nlist);
183 dlist_push_last(list, other_field);
184 EVEL_DEBUG("Adding to existing table %p",list);
191 /**************************************************************************//**
192 * Add a json object to jsonObject list.
194 * The name and value are null delimited ASCII strings. The library takes
195 * a copy so the caller does not have to preserve values after the function
198 * @param other Pointer to the Other.
199 * @param jsonobj Pointer to json object
200 *****************************************************************************/
201 void evel_other_field_add_jsonobj(EVENT_OTHER * other, EVEL_JSON_OBJECT *jsonobj)
203 OTHER_FIELD * other_field = NULL;
206 /***************************************************************************/
207 /* Check preconditions. */
208 /***************************************************************************/
209 assert(other != NULL);
210 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
211 assert(jsonobj != NULL);
213 EVEL_DEBUG("Adding jsonObject");
215 dlist_push_last(&other->jsonobjects, jsonobj);
220 /**************************************************************************//**
221 * Add a field name/value pair to the Other.
223 * The name and value are null delimited ASCII strings. The library takes
224 * a copy so the caller does not have to preserve values after the function
227 * @param other Pointer to the Other.
228 * @param name ASCIIZ string with the field's name. The caller does not
229 * need to preserve the value once the function returns.
230 * @param value ASCIIZ string with the field's value. The caller does not
231 * need to preserve the value once the function returns.
232 *****************************************************************************/
233 void evel_other_field_add(EVENT_OTHER * other, char * name, char * value)
235 OTHER_FIELD * other_field = NULL;
238 /***************************************************************************/
239 /* Check preconditions. */
240 /***************************************************************************/
241 assert(other != NULL);
242 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
243 assert(name != NULL);
244 assert(value != NULL);
246 EVEL_DEBUG("Adding name=%s value=%s", name, value);
247 other_field = malloc(sizeof(OTHER_FIELD));
248 assert(other_field != NULL);
249 memset(other_field, 0, sizeof(OTHER_FIELD));
250 other_field->name = strdup(name);
251 other_field->value = strdup(value);
252 assert(other_field->name != NULL);
253 assert(other_field->value != NULL);
255 dlist_push_last(&other->namedvalues, other_field);
260 /**************************************************************************//**
261 * Encode the Other in JSON according to AT&T's schema for the event type.
263 * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
264 * @param event Pointer to the ::EVENT_HEADER to encode.
265 *****************************************************************************/
266 void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf,
269 OTHER_FIELD * other_field = NULL;
270 EVEL_JSON_OBJECT * jsonobjp = NULL;
271 DLIST_ITEM * other_field_item = NULL;
272 EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL;
273 DLIST_ITEM * jsobj_field_item = NULL;
274 EVEL_INTERNAL_KEY * keyinst = NULL;
275 DLIST_ITEM * keyinst_field_item = NULL;
276 HASHTABLE_T *ht = NULL;
278 bool itm_added = false;
279 DLIST *itm_list = NULL;
280 ENTRY_T *entry = NULL;
284 /***************************************************************************/
285 /* Check preconditions. */
286 /***************************************************************************/
287 assert(event != NULL);
288 assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
290 evel_json_encode_header(jbuf, &event->header);
291 evel_json_open_named_object(jbuf, "otherFields");
293 // iterate through hashtable and print DLIST for each entry
295 evel_json_checkpoint(jbuf);
296 ht = event->namedarrays;
302 evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays");
303 for( idx = 0; idx < ht->size; idx++ ) {
304 if( ht->table[idx] != NULL)
306 entry = ht->table[idx];
307 EVEL_DEBUG("Encoding other %s %p",(char *) (entry->key), entry->value);
309 evel_json_open_object(jbuf);
310 evel_enc_kv_string(jbuf, "name", entry->key);
312 itm_list = (DLIST*)(entry->value);
313 evel_json_open_opt_named_list(jbuf, "arrayOfFields");
315 other_field_item = dlist_get_first(itm_list);
316 while (other_field_item != NULL)
318 other_field = (OTHER_FIELD *) other_field_item->item;
319 EVEL_DEBUG("Encoding other %s %s",(char *)other_field->name,(char*)other_field->value);
320 if(other_field != NULL){
321 evel_json_open_object(jbuf);
322 evel_enc_kv_string(jbuf, "name", other_field->name);
323 evel_enc_kv_string(jbuf, "value", other_field->value);
324 evel_json_close_object(jbuf);
325 other_field_item = dlist_get_next(other_field_item);
328 evel_json_close_list(jbuf);
329 evel_json_close_object(jbuf);
333 evel_json_close_list(jbuf);
336 evel_json_rewind(jbuf);
340 evel_json_checkpoint(jbuf);
341 if(evel_json_open_opt_named_list(jbuf, "jsonObjects"))
343 bool item_added = false;
344 other_field_item = dlist_get_first(&event->jsonobjects);
345 while (other_field_item != NULL)
347 jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item;
348 if(jsonobjp != NULL);
350 evel_json_open_object(jbuf);
352 if( evel_json_open_opt_named_list(jbuf, "objectInstances"))
354 bool item_added2 = false;
355 jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances);
356 while (jsobj_field_item != NULL)
358 jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item;
359 if( jsonobjinst != NULL )
361 evel_json_open_object(jbuf);
362 evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
363 evel_enc_kv_ull(jbuf, "objectInstanceEpochMicrosec", jsonobjinst->objinst_epoch_microsec);
364 //evel_json_checkpoint(jbuf);
365 if (evel_json_open_opt_named_list(jbuf, "objectKeys"))
367 bool item_added3 = false;
369 keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys);
370 while (keyinst_field_item != NULL)
372 keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item;
375 evel_json_open_object(jbuf);
376 evel_enc_kv_string(jbuf, "keyName", keyinst->keyname);
377 evel_enc_kv_opt_int(jbuf, "keyOrder", &keyinst->keyorder);
378 evel_enc_kv_opt_string(jbuf, "keyValue", &keyinst->keyvalue);
379 evel_json_close_object(jbuf);
382 keyinst_field_item = dlist_get_next(keyinst_field_item);
384 evel_json_close_list(jbuf);
386 /*************************************************************************/
387 /* If we've not written anything, rewind to before we opened the list. */
388 /*************************************************************************/
391 // evel_json_rewind(jbuf);
394 evel_json_close_object(jbuf);
397 jsobj_field_item = dlist_get_next(jsobj_field_item);
399 evel_json_close_list(jbuf);
402 evel_json_rewind(jbuf);
406 evel_enc_kv_string(jbuf, "objectName", jsonobjp->object_name);
407 evel_enc_kv_opt_string(jbuf, "objectSchema", &jsonobjp->objectschema);
408 evel_enc_kv_opt_string(jbuf, "objectSchemaUrl", &jsonobjp->objectschemaurl);
409 evel_enc_kv_opt_string(jbuf, "nfSubscribedObjectName", &jsonobjp->nfsubscribedobjname);
410 evel_enc_kv_opt_string(jbuf, "nfSubscriptionId", &jsonobjp->nfsubscriptionid);
411 evel_json_close_object(jbuf);
414 other_field_item = dlist_get_next(other_field_item);
416 evel_json_close_list(jbuf);
420 evel_json_rewind(jbuf);
425 evel_json_checkpoint(jbuf);
426 if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
428 bool item_added = false;
430 other_field_item = dlist_get_first(&event->namedvalues);
431 while (other_field_item != NULL)
433 other_field = (OTHER_FIELD *) other_field_item->item;
434 if(other_field != NULL)
436 evel_json_open_object(jbuf);
437 evel_enc_kv_string(jbuf, "name", other_field->name);
438 evel_enc_kv_string(jbuf, "value", other_field->value);
439 evel_json_close_object(jbuf);
442 other_field_item = dlist_get_next(other_field_item);
444 evel_json_close_list(jbuf);
446 /*************************************************************************/
447 /* If we've not written anything, rewind to before we opened the list. */
448 /*************************************************************************/
451 evel_json_rewind(jbuf);
456 evel_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version);
458 evel_json_close_object(jbuf);
463 /**************************************************************************//**
466 * Free off the Other supplied. Will free all the contained allocated memory.
468 * @note It does not free the Other itself, since that may be part of a
470 *****************************************************************************/
471 void evel_free_other(EVENT_OTHER * event)
473 OTHER_FIELD * other_field = NULL;
477 /***************************************************************************/
478 /* Check preconditions. As an internal API we don't allow freeing NULL */
479 /* events as we do on the public API. */
480 /***************************************************************************/
481 assert(event != NULL);
482 assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
484 /***************************************************************************/
485 /* Free all internal strings then the header itself. */
486 /***************************************************************************/
487 other_field = dlist_pop_last(&event->namedvalues);
488 while (other_field != NULL)
490 EVEL_DEBUG("Freeing Other Field (%s, %s)",
493 free(other_field->name);
494 free(other_field->value);
496 other_field = dlist_pop_last(&event->namedvalues);
498 evel_free_header(&event->header);