Add License to VES library
[demo.git] / vnfs / VES / code / evel_library / evel_state_change.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to the State Change.
4  *
5  * License
6  * -------
7  *
8  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *        http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *****************************************************************************/
21
22 #include <string.h>
23 #include <assert.h>
24 #include <stdlib.h>
25
26 #include "evel_throttle.h"
27
28 /**************************************************************************//**
29  * Create a new State Change event.
30  *
31  * @note    The mandatory fields on the State Change must be supplied to this
32  *          factory function and are immutable once set.  Optional fields have
33  *          explicit setter functions, but again values may only be set once
34  *          so that the State Change has immutable properties.
35  *
36  * @param new_state     The new state of the reporting entity.
37  * @param old_state     The old state of the reporting entity.
38  * @param interface     The card or port name of the reporting entity.
39  *
40  * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE.  If the
41  *          event is not used it must be released using
42  *          ::evel_free_state_change
43  * @retval  NULL  Failed to create the event.
44  *****************************************************************************/
45 EVENT_STATE_CHANGE * evel_new_state_change(const EVEL_ENTITY_STATE new_state,
46                                            const EVEL_ENTITY_STATE old_state,
47                                            const char * const interface)
48 {
49   EVENT_STATE_CHANGE * state_change = NULL;
50   EVEL_ENTER();
51
52   /***************************************************************************/
53   /* Check preconditions.                                                    */
54   /***************************************************************************/
55   assert(new_state < EVEL_MAX_ENTITY_STATES);
56   assert(old_state < EVEL_MAX_ENTITY_STATES);
57   assert(interface != NULL);
58
59   /***************************************************************************/
60   /* Allocate the State Change.                                              */
61   /***************************************************************************/
62   state_change = malloc(sizeof(EVENT_STATE_CHANGE));
63   if (state_change == NULL)
64   {
65     log_error_state("Out of memory");
66     goto exit_label;
67   }
68   memset(state_change, 0, sizeof(EVENT_STATE_CHANGE));
69   EVEL_DEBUG("New State Change is at %lp", state_change);
70
71   /***************************************************************************/
72   /* Initialize the header & the State Change fields.  Optional string       */
73   /* values are uninitialized (NULL).                                        */
74   /***************************************************************************/
75   evel_init_header(&state_change->header);
76   state_change->header.event_domain = EVEL_DOMAIN_STATE_CHANGE;
77   state_change->major_version = EVEL_STATE_CHANGE_MAJOR_VERSION;
78   state_change->minor_version = EVEL_STATE_CHANGE_MINOR_VERSION;
79   state_change->new_state = new_state;
80   state_change->old_state = old_state;
81   state_change->state_interface = strdup(interface);
82   dlist_initialize(&state_change->additional_fields);
83
84 exit_label:
85   EVEL_EXIT();
86   return state_change;
87 }
88
89 /**************************************************************************//**
90  * Free a State Change.
91  *
92  * Free off the State Change supplied.  Will free all the contained allocated
93  * memory.
94  *
95  * @note It does not free the State Change itself, since that may be part of a
96  * larger structure.
97  *****************************************************************************/
98 void evel_free_state_change(EVENT_STATE_CHANGE * const state_change)
99 {
100   STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
101
102   EVEL_ENTER();
103
104   /***************************************************************************/
105   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
106   /* events as we do on the public API.                                      */
107   /***************************************************************************/
108   assert(state_change != NULL);
109   assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
110
111   /***************************************************************************/
112   /* Free all internal strings then the header itself.                       */
113   /***************************************************************************/
114   addl_field = dlist_pop_last(&state_change->additional_fields);
115   while (addl_field != NULL)
116   {
117     EVEL_DEBUG("Freeing Additional Field (%s, %s)",
118                addl_field->name,
119                addl_field->value);
120     free(addl_field->name);
121     free(addl_field->value);
122     free(addl_field);
123     addl_field = dlist_pop_last(&state_change->additional_fields);
124   }
125   free(state_change->state_interface);
126   evel_free_header(&state_change->header);
127
128   EVEL_EXIT();
129 }
130
131 /**************************************************************************//**
132  * Set the Event Type property of the State Change.
133  *
134  * @note  The property is treated as immutable: it is only valid to call
135  *        the setter once.  However, we don't assert if the caller tries to
136  *        overwrite, just ignoring the update instead.
137  *
138  * @param state_change  Pointer to the ::EVENT_STATE_CHANGE.
139  * @param type          The Event Type to be set. ASCIIZ string. The caller
140  *                      does not need to preserve the value once the function
141  *                      returns.
142  *****************************************************************************/
143 void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change,
144                                 const char * const type)
145 {
146   EVEL_ENTER();
147
148   /***************************************************************************/
149   /* Check preconditions and call evel_header_type_set.                      */
150   /***************************************************************************/
151   assert(state_change != NULL);
152   assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
153   evel_header_type_set(&state_change->header, type);
154
155   EVEL_EXIT();
156 }
157
158 /**************************************************************************//**
159  * Add an additional field name/value pair to the State Change.
160  *
161  * The name and value are null delimited ASCII strings.  The library takes
162  * a copy so the caller does not have to preserve values after the function
163  * returns.
164  *
165  * @param state_change  Pointer to the ::EVENT_STATE_CHANGE.
166  * @param name          ASCIIZ string with the attribute's name.  The caller
167  *                      does not need to preserve the value once the function
168  *                      returns.
169  * @param value         ASCIIZ string with the attribute's value.  The caller
170  *                      does not need to preserve the value once the function
171  *                      returns.
172  *****************************************************************************/
173 void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change,
174                                       const char * const name,
175                                       const char * const value)
176 {
177   STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
178   EVEL_ENTER();
179
180   /***************************************************************************/
181   /* Check preconditions.                                                    */
182   /***************************************************************************/
183   assert(state_change != NULL);
184   assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
185   assert(name != NULL);
186   assert(value != NULL);
187
188   EVEL_DEBUG("Adding name=%s value=%s", name, value);
189   addl_field = malloc(sizeof(STATE_CHANGE_ADDL_FIELD));
190   assert(addl_field != NULL);
191   memset(addl_field, 0, sizeof(STATE_CHANGE_ADDL_FIELD));
192   addl_field->name = strdup(name);
193   addl_field->value = strdup(value);
194   assert(addl_field->name != NULL);
195   assert(addl_field->value != NULL);
196
197   dlist_push_last(&state_change->additional_fields, addl_field);
198
199   EVEL_EXIT();
200 }
201
202 /**************************************************************************//**
203  * Encode the state change as a JSON state change.
204  *
205  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
206  * @param state_change  Pointer to the ::EVENT_STATE_CHANGE to encode.
207  *****************************************************************************/
208 void evel_json_encode_state_change(EVEL_JSON_BUFFER * jbuf,
209                                    EVENT_STATE_CHANGE * state_change)
210 {
211   STATE_CHANGE_ADDL_FIELD * addl_field = NULL;
212   DLIST_ITEM * addl_field_item = NULL;
213   char * new_state;
214   char * old_state;
215
216   EVEL_ENTER();
217
218   /***************************************************************************/
219   /* Check preconditions.                                                    */
220   /***************************************************************************/
221   assert(state_change != NULL);
222   assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE);
223
224   new_state = evel_entity_state(state_change->new_state);
225   old_state = evel_entity_state(state_change->old_state);
226
227   evel_json_encode_header(jbuf, &state_change->header);
228   evel_json_open_named_object(jbuf, "stateChangeFields");
229
230   /***************************************************************************/
231   /* Mandatory fields.                                                       */
232   /***************************************************************************/
233   evel_enc_kv_string(jbuf, "newState", new_state);
234   evel_enc_kv_string(jbuf, "oldState", old_state);
235   evel_enc_kv_string(jbuf, "stateInterface", state_change->state_interface);
236
237   /***************************************************************************/
238   /* Optional fields.                                                        */
239   /***************************************************************************/
240   evel_json_checkpoint(jbuf);
241   if (evel_json_open_opt_named_list(jbuf, "additionalFields"))
242   {
243     bool item_added = false;
244
245     addl_field_item = dlist_get_first(&state_change->additional_fields);
246     while (addl_field_item != NULL)
247     {
248       addl_field = (STATE_CHANGE_ADDL_FIELD *) addl_field_item->item;
249       assert(addl_field != NULL);
250
251       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
252                                           "additionalFields",
253                                           addl_field->name))
254       {
255         evel_json_open_object(jbuf);
256         evel_enc_kv_string(jbuf, "name", addl_field->name);
257         evel_enc_kv_string(jbuf, "value", addl_field->value);
258         evel_json_close_object(jbuf);
259         item_added = true;
260       }
261       addl_field_item = dlist_get_next(addl_field_item);
262     }
263     evel_json_close_list(jbuf);
264
265     /*************************************************************************/
266     /* If we've not written anything, rewind to before we opened the list.   */
267     /*************************************************************************/
268     if (!item_added)
269     {
270       evel_json_rewind(jbuf);
271     }
272   }
273
274   evel_enc_version(jbuf,
275                    "stateChangeFieldsVersion",
276                    state_change->major_version,
277                    state_change->minor_version);
278
279   evel_json_close_object(jbuf);
280
281   EVEL_EXIT();
282 }