Initial VES for DANOS vRouter
[demo.git] / vnfs / VESreporting_vFW5.0_DANOS / evel / evel-library / code / evel_library / evel_other.c
1 /*************************************************************************//**
2  *
3  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
4  *
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
10  *
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.
16  *
17  ****************************************************************************/
18
19 /**************************************************************************//**
20  * @file
21  * Implementation of EVEL functions relating to Other domain.
22  *
23  *****************************************************************************/
24
25 #include <string.h>
26 #include <assert.h>
27 #include <stdlib.h>
28
29 #include "evel.h"
30 #include "evel_internal.h"
31
32 /**************************************************************************//**
33  * Create a new Other event.
34  *
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)
44 {
45   EVENT_OTHER * other = NULL;
46   EVEL_ENTER();
47
48   /***************************************************************************/
49   /* Check preconditions.                                                    */
50   /***************************************************************************/
51
52   /***************************************************************************/
53   /* Allocate the Other.                                                     */
54   /***************************************************************************/
55   other = malloc(sizeof(EVENT_OTHER));
56   if (other == NULL)
57   {
58     log_error_state("Out of memory");
59     goto exit_label;
60   }
61   memset(other, 0, sizeof(EVENT_OTHER));
62   EVEL_DEBUG("New Other is at %lp", other);
63
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;
72
73   other->namedarrays = NULL;
74   dlist_initialize(&other->jsonobjects);
75   dlist_initialize(&other->namedvalues);
76
77 exit_label:
78   EVEL_EXIT();
79   return other;
80 }
81
82 /**************************************************************************//**
83  * Set the Event Type property of the Other.
84  *
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.
88  *
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
92  *                    returns.
93  *****************************************************************************/
94 void evel_other_type_set(EVENT_OTHER * other,
95                          const char * const type)
96 {
97   EVEL_ENTER();
98
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);
105
106   EVEL_EXIT();
107 }
108
109 /**************************************************************************//**
110  * Set size of Named arrays hash table
111  *
112  * The max size of hash table is passed
113  *
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)
118 {
119   EVEL_ENTER();
120
121   /***************************************************************************/
122   /* Check preconditions.                                                    */
123   /***************************************************************************/
124   assert(other != NULL);
125   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
126   assert(other->namedarrays == NULL);
127   assert(size > 0);
128
129   EVEL_DEBUG("Adding Named array");
130
131   other->namedarrays =  ht_create(size);
132
133   EVEL_EXIT();
134 }
135
136
137 /**************************************************************************//**
138  * Add a json object to jsonObject list.
139  *
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
142  * returns.
143  *
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)
148 {
149   OTHER_FIELD * other_field = NULL;
150   DLIST *list = NULL;
151   EVEL_ENTER();
152
153   /***************************************************************************/
154   /* Check preconditions.                                                    */
155   /***************************************************************************/
156   assert(other != NULL);
157   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
158   assert(other->namedarrays != NULL);
159
160   EVEL_DEBUG("Adding values to Named array");
161       
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);
170
171
172   list = (DLIST *)ht_get(other->namedarrays, hashname);
173   if( list == NULL )
174   {
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);
180   }
181   else
182   {
183      dlist_push_last(list, other_field);
184      EVEL_DEBUG("Adding to existing table %p",list);
185   }
186
187   EVEL_EXIT();
188 }
189
190
191 /**************************************************************************//**
192  * Add a json object to jsonObject list.
193  *
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
196  * returns.
197  *
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)
202 {
203   EVEL_ENTER();
204
205   /***************************************************************************/
206   /* Check preconditions.                                                    */
207   /***************************************************************************/
208   assert(other != NULL);
209   assert(other->header.event_domain == EVEL_DOMAIN_OTHER);
210   assert(jsonobj != NULL);
211
212   EVEL_DEBUG("Adding jsonObject");
213
214   dlist_push_last(&other->jsonobjects, jsonobj);
215
216   EVEL_EXIT();
217 }
218
219 /**************************************************************************//**
220  * Add a field name/value pair to the Other.
221  *
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
224  * returns.
225  *
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)
233 {
234   OTHER_FIELD * other_field = NULL;
235   EVEL_ENTER();
236
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);
244
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);
253
254   dlist_push_last(&other->namedvalues, other_field);
255
256   EVEL_EXIT();
257 }
258
259 /**************************************************************************//**
260  * Encode the Other in JSON according to AT&T's schema for the event type.
261  *
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,
266                             EVENT_OTHER * event)
267 {
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;
276   int idx;
277   bool itm_added = false;
278   DLIST *itm_list = NULL;
279   ENTRY_T *entry = NULL;
280
281   EVEL_ENTER();
282
283   /***************************************************************************/
284   /* Check preconditions.                                                    */
285   /***************************************************************************/
286   assert(event != NULL);
287   assert(event->header.event_domain == EVEL_DOMAIN_OTHER);
288
289   evel_json_encode_header(jbuf, &event->header);
290   evel_json_open_named_object(jbuf, "otherFields");
291
292 // iterate through hashtable and print DLIST for each entry
293
294    evel_json_checkpoint(jbuf);
295    ht = event->namedarrays;
296    if( ht != NULL )
297    {
298      if( ht->size > 0)
299      {
300
301         evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays");
302         for( idx = 0; idx < ht->size; idx++ ) {
303              if( ht->table[idx] != NULL)
304              {
305                 entry =  ht->table[idx]; 
306                 EVEL_DEBUG("Encoding other %s %p",(char *) (entry->key), entry->value);
307
308                 evel_json_open_object(jbuf);
309                 evel_enc_kv_string(jbuf, "name", entry->key);
310
311                 itm_list = (DLIST*)(entry->value);
312                 evel_json_open_opt_named_list(jbuf, "arrayOfFields");
313
314     other_field_item = dlist_get_first(itm_list);
315     while (other_field_item != NULL)
316     {
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);
325      }
326     }
327                  evel_json_close_list(jbuf);
328                  evel_json_close_object(jbuf);
329
330              }
331         }
332         evel_json_close_list(jbuf);
333
334      } else {
335        evel_json_rewind(jbuf);
336      }
337    }
338
339   evel_json_checkpoint(jbuf);
340   if(evel_json_open_opt_named_list(jbuf, "jsonObjects"))
341   {
342   bool item_added = false;
343   other_field_item = dlist_get_first(&event->jsonobjects);
344   while (other_field_item != NULL)
345   {
346     jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item;
347     if(jsonobjp != NULL);
348     {
349      evel_json_open_object(jbuf);
350
351        if( evel_json_open_opt_named_list(jbuf, "objectInstances"))
352        {
353         bool item_added2 = false;
354         jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances);
355         while (jsobj_field_item != NULL)
356         {
357            jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item;
358            if( jsonobjinst != NULL )
359            {
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"))
365   {
366     bool item_added3 = false;
367
368     keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys);
369     while (keyinst_field_item != NULL)
370     {
371       keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item;
372       if(keyinst != NULL)
373       {
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);
379         item_added3 = false;
380       }
381       keyinst_field_item = dlist_get_next(keyinst_field_item);
382     }
383     evel_json_close_list(jbuf);
384
385     /*************************************************************************/
386     /* If we've not written anything, rewind to before we opened the list.   */
387     /*************************************************************************/
388     //if (!item_added3)
389     //{
390     //  evel_json_rewind(jbuf);
391     //}
392   }
393                evel_json_close_object(jbuf);
394             }
395             item_added2 = true;
396             jsobj_field_item = dlist_get_next(jsobj_field_item);
397         }
398         evel_json_close_list(jbuf);
399         if( !item_added2 )
400         {
401           evel_json_rewind(jbuf);
402         }
403        }
404
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);
411     item_added = true;
412   }
413   other_field_item = dlist_get_next(other_field_item);
414   }
415   evel_json_close_list(jbuf);
416
417   if (!item_added)
418   {
419      evel_json_rewind(jbuf);
420   }
421
422   }
423
424   evel_json_checkpoint(jbuf);
425   if( evel_json_open_opt_named_list(jbuf, "nameValuePairs"))
426   {
427      bool item_added = false;
428
429   other_field_item = dlist_get_first(&event->namedvalues);
430   while (other_field_item != NULL)
431   {
432     other_field = (OTHER_FIELD *) other_field_item->item;
433     if(other_field != NULL)
434     {
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);
439       item_added = true;
440     }
441     other_field_item = dlist_get_next(other_field_item);
442   }
443   evel_json_close_list(jbuf);
444
445     /*************************************************************************/
446     /* If we've not written anything, rewind to before we opened the list.   */
447     /*************************************************************************/
448     if (!item_added)
449     {
450       evel_json_rewind(jbuf);
451     }
452
453   }
454
455   evel_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version);
456
457   evel_json_close_object(jbuf);
458
459   EVEL_EXIT();
460 }
461
462 /**************************************************************************//**
463  * Free an Other.
464  *
465  * Free off the Other supplied.  Will free all the contained allocated memory.
466  *
467  * @note It does not free the Other itself, since that may be part of a
468  * larger structure.
469  *****************************************************************************/
470 void evel_free_other(EVENT_OTHER * event)
471 {
472   OTHER_FIELD * other_field = NULL;
473   EVEL_JSON_OBJECT * jsonobjp = NULL;
474   DLIST_ITEM * other_field_item = NULL;
475
476   EVEL_ENTER();
477
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);
484
485   /***************************************************************************/
486   /* Free all internal strings then the header itself.                       */
487   /***************************************************************************/
488   other_field = dlist_pop_last(&event->namedvalues);
489   while (other_field != NULL)
490   {
491     EVEL_DEBUG("Freeing Other Field (%s, %s)",
492                other_field->name,
493                other_field->value);
494     free(other_field->name);
495     free(other_field->value);
496     free(other_field);
497     other_field = dlist_pop_last(&event->namedvalues);
498   }
499
500   jsonobjp = dlist_pop_last(&event->jsonobjects);
501   while (jsonobjp != NULL)
502   {
503     evel_free_jsonobject( jsonobjp );
504
505     jsonobjp = dlist_pop_last(&event->jsonobjects);
506   }
507
508   evel_free_header(&event->header);
509
510   EVEL_EXIT();
511 }