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)
205 /***************************************************************************/
206 /* Check preconditions. */
207 /***************************************************************************/
208 assert(other != NULL);
209 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
210 assert(jsonobj != NULL);
212 EVEL_DEBUG("Adding jsonObject");
214 dlist_push_last(&other->jsonobjects, jsonobj);
219 /**************************************************************************//**
220 * Add a field name/value pair to the Other.
222 * The name and value are null delimited ASCII strings. The library takes
223 * a copy so the caller does not have to preserve values after the function
226 * @param other Pointer to the Other.
227 * @param name ASCIIZ string with the field's name. The caller does not
228 * need to preserve the value once the function returns.
229 * @param value ASCIIZ string with the field's value. The caller does not
230 * need to preserve the value once the function returns.
231 *****************************************************************************/
232 void evel_other_field_add(EVENT_OTHER * other, char * name, char * value)
234 OTHER_FIELD * other_field = NULL;
237 /***************************************************************************/
238 /* Check preconditions. */
239 /***************************************************************************/
240 assert(other != NULL);
241 assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
242 assert(name != NULL);
243 assert(value != NULL);
245 EVEL_DEBUG("Adding name=%s value=%s", name, value);
246 other_field = malloc(sizeof(OTHER_FIELD));
247 assert(other_field != NULL);
248 memset(other_field, 0, sizeof(OTHER_FIELD));
249 other_field->name = strdup(name);
250 other_field->value = strdup(value);
251 assert(other_field->name != NULL);
252 assert(other_field->value != NULL);
254 dlist_push_last(&other->namedvalues, other_field);
259 /**************************************************************************//**
260 * Encode the Other in JSON according to AT&T's schema for the event type.
262 * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into.
263 * @param event Pointer to the ::EVENT_HEADER to encode.
264 *****************************************************************************/
265 void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf,
268 OTHER_FIELD * other_field = NULL;
269 EVEL_JSON_OBJECT * jsonobjp = NULL;
270 DLIST_ITEM * other_field_item = NULL;
271 EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL;
272 DLIST_ITEM * jsobj_field_item = NULL;
273 EVEL_INTERNAL_KEY * keyinst = NULL;
274 DLIST_ITEM * keyinst_field_item = NULL;
275 HASHTABLE_T *ht = NULL;
277 bool itm_added = false;
278 DLIST *itm_list = NULL;
279 ENTRY_T *entry = NULL;
283 /***************************************************************************/
284 /* Check preconditions. */
285 /***************************************************************************/
286 assert(event != NULL);
287 assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
289 evel_json_encode_header(jbuf, &event->header);
290 evel_json_open_named_object(jbuf, "otherFields");
292 // iterate through hashtable and print DLIST for each entry
294 evel_json_checkpoint(jbuf);
295 ht = event->namedarrays;
301 evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays");
302 for( idx = 0; idx < ht->size; idx++ ) {
303 if( ht->table[idx] != NULL)
305 entry = ht->table[idx];
306 EVEL_DEBUG("Encoding other %s %p",(char *) (entry->key), entry->value);
308 evel_json_open_object(jbuf);
309 evel_enc_kv_string(jbuf, "name", entry->key);
311 itm_list = (DLIST*)(entry->value);
312 evel_json_open_opt_named_list(jbuf, "arrayOfFields");
314 other_field_item = dlist_get_first(itm_list);
315 while (other_field_item != NULL)
317 other_field = (OTHER_FIELD *) other_field_item->item;
318 EVEL_DEBUG("Encoding other %s %s",(char *)other_field->name,(char*)other_field->value);
319 if(other_field != NULL){
320 evel_json_open_object(jbuf);
321 evel_enc_kv_string(jbuf, "name", other_field->name);
322 evel_enc_kv_string(jbuf, "value", other_field->value);
323 evel_json_close_object(jbuf);
324 other_field_item = dlist_get_next(other_field_item);
327 evel_json_close_list(jbuf);
328 evel_json_close_object(jbuf);
332 evel_json_close_list(jbuf);
335 evel_json_rewind(jbuf);
339 evel_json_checkpoint(jbuf);
340 if(evel_json_open_opt_named_list(jbuf, "jsonObjects"))
342 bool item_added = false;
343 other_field_item = dlist_get_first(&event->jsonobjects);
344 while (other_field_item != NULL)
346 jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item;
347 if(jsonobjp != NULL);
349 evel_json_open_object(jbuf);
351 if( evel_json_open_opt_named_list(jbuf, "objectInstances"))
353 bool item_added2 = false;
354 jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances);
355 while (jsobj_field_item != NULL)
357 jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item;
358 if( jsonobjinst != NULL )
360 evel_json_open_object(jbuf);
361 evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring);
362 evel_enc_kv_opt_ull(jbuf, "objectInstanceEpochMicrosec", &jsonobjinst->objinst_epoch_microsec);
363 //evel_json_checkpoint(jbuf);
364 if (evel_json_open_opt_named_list(jbuf, "objectKeys"))
366 bool item_added3 = false;
368 keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys);
369 while (keyinst_field_item != NULL)
371 keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item;
374 evel_json_open_object(jbuf);
375 evel_enc_kv_string(jbuf, "keyName", keyinst->keyname);
376 evel_enc_kv_opt_int(jbuf, "keyOrder", &keyinst->keyorder);
377 evel_enc_kv_opt_string(jbuf, "keyValue", &keyinst->keyvalue);
378 evel_json_close_object(jbuf);
381 keyinst_field_item = dlist_get_next(keyinst_field_item);
383 evel_json_close_list(jbuf);
385 /*************************************************************************/
386 /* If we've not written anything, rewind to before we opened the list. */
387 /*************************************************************************/
390 // evel_json_rewind(jbuf);
393 evel_json_close_object(jbuf);
396 jsobj_field_item = dlist_get_next(jsobj_field_item);
398 evel_json_close_list(jbuf);
401 evel_json_rewind(jbuf);
405 evel_enc_kv_string(jbuf, "objectName", jsonobjp->object_name);
406 evel_enc_kv_opt_string(jbuf, "objectSchema", &jsonobjp->objectschema);
407 evel_enc_kv_opt_string(jbuf, "objectSchemaUrl", &jsonobjp->objectschemaurl);
408 evel_enc_kv_opt_string(jbuf, "nfSubscribedObjectName", &jsonobjp->nfsubscribedobjname);
409 evel_enc_kv_opt_string(jbuf, "nfSubscriptionId", &jsonobjp->nfsubscriptionid);
410 evel_json_close_object(jbuf);
413 other_field_item = dlist_get_next(other_field_item);
415 evel_json_close_list(jbuf);
419 evel_json_rewind(jbuf);
424 evel_json_checkpoint(jbuf);
425 if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
427 bool item_added = false;
429 other_field_item = dlist_get_first(&event->namedvalues);
430 while (other_field_item != NULL)
432 other_field = (OTHER_FIELD *) other_field_item->item;
433 if(other_field != NULL)
435 evel_json_open_object(jbuf);
436 evel_enc_kv_string(jbuf, "name", other_field->name);
437 evel_enc_kv_string(jbuf, "value", other_field->value);
438 evel_json_close_object(jbuf);
441 other_field_item = dlist_get_next(other_field_item);
443 evel_json_close_list(jbuf);
445 /*************************************************************************/
446 /* If we've not written anything, rewind to before we opened the list. */
447 /*************************************************************************/
450 evel_json_rewind(jbuf);
455 evel_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version);
457 evel_json_close_object(jbuf);
462 /**************************************************************************//**
465 * Free off the Other supplied. Will free all the contained allocated memory.
467 * @note It does not free the Other itself, since that may be part of a
469 *****************************************************************************/
470 void evel_free_other(EVENT_OTHER * event)
472 OTHER_FIELD * other_field = NULL;
473 EVEL_JSON_OBJECT * jsonobjp = NULL;
474 DLIST_ITEM * other_field_item = NULL;
478 /***************************************************************************/
479 /* Check preconditions. As an internal API we don't allow freeing NULL */
480 /* events as we do on the public API. */
481 /***************************************************************************/
482 assert(event != NULL);
483 assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
485 /***************************************************************************/
486 /* Free all internal strings then the header itself. */
487 /***************************************************************************/
488 other_field = dlist_pop_last(&event->namedvalues);
489 while (other_field != NULL)
491 EVEL_DEBUG("Freeing Other Field (%s, %s)",
494 free(other_field->name);
495 free(other_field->value);
497 other_field = dlist_pop_last(&event->namedvalues);
500 jsonobjp = dlist_pop_last(&event->jsonobjects);
501 while (jsonobjp != NULL)
503 evel_free_jsonobject( jsonobjp );
505 jsonobjp = dlist_pop_last(&event->jsonobjects);
508 evel_free_header(&event->header);