api: refactor api data storage

single struct to hold all api handler, flags, etc.
Provide functions to toggle flags instead of writing directly to
internal data.

Type: refactor
Change-Id: I4730d7290e57489de8eda34a72211527e015b721
Signed-off-by: Damjan Marion <damarion@cisco.com>
diff --git a/src/vlibmemory/memclnt_api.c b/src/vlibmemory/memclnt_api.c
index 289a4c5..9e2971a 100644
--- a/src/vlibmemory/memclnt_api.c
+++ b/src/vlibmemory/memclnt_api.c
@@ -193,8 +193,8 @@
   foreach_vlib_api_msg;
 #undef _
 
-  am->is_mp_safe[VL_API_CONTROL_PING] = 1;
-  am->is_mp_safe[VL_API_CONTROL_PING_REPLY] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_CONTROL_PING, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_CONTROL_PING_REPLY, 1);
 
   return 0;
 }
@@ -727,10 +727,10 @@
   foreach_plugin_trace_msg;
 #undef _
 
-  am->api_trace_cfg[VL_API_TRACE_PLUGIN_MSG_IDS].replay_enable = 0;
+  vl_api_allow_msg_replay (am, VL_API_TRACE_PLUGIN_MSG_IDS, 0);
 
   /* No reason to halt the parade to create a trace record... */
-  am->is_mp_safe[VL_API_TRACE_PLUGIN_MSG_IDS] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_TRACE_PLUGIN_MSG_IDS, 1);
   rpc_call_main_thread_cb_fn = vl_api_rpc_call_main_thread;
   return 0;
 }
diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c
index ecdcc72..80d8628 100644
--- a/src/vlibmemory/memory_api.c
+++ b/src/vlibmemory/memory_api.c
@@ -532,9 +532,9 @@
    * special-case freeing of memclnt_delete messages, so we can
    * simply munmap pairwise / private API segments...
    */
-  am->message_bounce[VL_API_MEMCLNT_DELETE] = 1;
-  am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE_REPLY] = 1;
-  am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE] = 1;
+  am->msg_data[VL_API_MEMCLNT_DELETE].bounce = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_MEMCLNT_KEEPALIVE_REPLY, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_MEMCLNT_KEEPALIVE, 1);
 
   vlib_set_queue_signal_callback (vm, memclnt_queue_callback);
 
@@ -768,6 +768,7 @@
 				 vlib_node_runtime_t *node, u8 is_private)
 {
   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
   u8 *(*handler) (void *, void *, void *);
   u8 *(*print_fp) (void *, void *);
   svm_region_t *old_vlib_rp;
@@ -785,23 +786,23 @@
 	u32 c;
       } * ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
-	ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
+      if (m && m->name)
+	ed->c = elog_string (am->elog_main, (char *) m->name);
       else
 	ed->c = elog_string (am->elog_main, "BOGUS");
     }
 
-  if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
+  if (m && m->handler)
     {
-      handler = (void *) am->msg_handlers[id];
+      handler = (void *) m->handler;
 
       if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
 	vl_msg_api_trace (am, am->rx_trace, the_msg);
 
       if (PREDICT_FALSE (am->msg_print_flag))
 	{
-	  fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
-	  print_fp = (void *) am->msg_print_handlers[id];
+	  fformat (stdout, "[%d]: %s\n", id, m->name);
+	  print_fp = (void *) am->msg_data[id].print_handler;
 	  if (print_fp == 0)
 	    {
 	      fformat (stdout, "  [no registered print fn for msg %d]\n", id);
@@ -811,11 +812,11 @@
 	      (*print_fp) (the_msg, vm);
 	    }
 	}
-      is_mp_safe = am->is_mp_safe[id];
+      is_mp_safe = am->msg_data[id].is_mp_safe;
 
       if (!is_mp_safe)
 	{
-	  vl_msg_api_barrier_trace_context (am->msg_names[id]);
+	  vl_msg_api_barrier_trace_context (am->msg_data[id].name);
 	  vl_msg_api_barrier_sync ();
 	}
       if (is_private)
@@ -829,10 +830,10 @@
       if (PREDICT_FALSE (vl_mem_api_fuzz_hook != 0))
 	(*vl_mem_api_fuzz_hook) (id, the_msg);
 
-      if (am->is_autoendian[id])
+      if (m->is_autoendian)
 	{
 	  void (*endian_fp) (void *);
-	  endian_fp = am->msg_endian_handlers[id];
+	  endian_fp = am->msg_data[id].endian_handler;
 	  (*endian_fp) (the_msg);
 	}
       if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
@@ -859,7 +860,7 @@
    * Special-case, so we can e.g. bounce messages off the vnet
    * main thread without copying them...
    */
-  if (id >= vec_len (am->message_bounce) || !(am->message_bounce[id]))
+  if (!m || !m->bounce)
     {
       if (is_private)
 	{
@@ -892,8 +893,8 @@
 	u32 c;
       } * ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
-	ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
+      if (m && m->name)
+	ed->c = elog_string (am->elog_main, (char *) m->name);
       else
 	ed->c = elog_string (am->elog_main, "BOGUS");
       ed->barrier = is_mp_safe;
diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c
index 585fca6..330390e 100644
--- a/src/vlibmemory/memory_client.c
+++ b/src/vlibmemory/memory_client.c
@@ -377,7 +377,7 @@
     vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0,  \
     vl_api_##n##_t_print_json, vl_api_##n##_t_tojson,                         \
     vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);                       \
-  am->api_trace_cfg[VL_API_##N].replay_enable = 0;
+  am->msg_data[VL_API_##N].replay_allowed = 0;
   foreach_api_msg;
 #undef _
 }
@@ -562,6 +562,8 @@
   vl_api_get_first_msg_id_t *mp;
   api_main_t *am = vlibapi_get_main ();
   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
+  vl_api_msg_data_t *m =
+    vl_api_get_msg_data (am, VL_API_GET_FIRST_MSG_ID_REPLY);
   f64 timeout;
   void *old_handler;
   clib_time_t clib_time;
@@ -574,12 +576,11 @@
   clib_time_init (&clib_time);
 
   /* Push this plugin's first_msg_id_reply handler */
-  old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY];
-  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *)
-    vl_api_get_first_msg_id_reply_t_handler;
-  if (!am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY])
+  old_handler = m->handler;
+  m->handler = (void *) vl_api_get_first_msg_id_reply_t_handler;
+  if (!m->calc_size_func)
     {
-      am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY] =
+      m->calc_size_func =
 	(uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size;
     }
 
@@ -608,7 +609,7 @@
 
     sock_err:
       /* Restore old handler */
-      am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
+      m->handler = old_handler;
 
       return -1;
     }
@@ -633,7 +634,7 @@
 	    }
 	}
       /* Restore old handler */
-      am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
+      m->handler = old_handler;
 
       return rv;
     }
@@ -641,7 +642,7 @@
 result:
 
   /* Restore the old handler */
-  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
+  m->handler = old_handler;
 
   if (rv == (u16) ~ 0)
     clib_warning ("plugin '%s' not registered", plugin_name);
diff --git a/src/vlibmemory/memory_shared.c b/src/vlibmemory/memory_shared.c
index b70f45f..77a610b 100644
--- a/src/vlibmemory/memory_shared.c
+++ b/src/vlibmemory/memory_shared.c
@@ -117,14 +117,16 @@
 		  if (CLIB_DEBUG > 0)
 		    {
 		      u16 *msg_idp, msg_id;
+		      vl_api_msg_data_t *m;
 		      clib_warning
 			("garbage collect pool %d ring %d index %d", pool, i,
 			 q->head);
 		      msg_idp = (u16 *) (rv->data);
 		      msg_id = clib_net_to_host_u16 (*msg_idp);
-		      if (msg_id < vec_len (vlibapi_get_main ()->msg_names))
+		      m = vl_api_get_msg_data (am, msg_id);
+		      if (m)
 			clib_warning ("msg id %d name %s", (u32) msg_id,
-				      vlibapi_get_main ()->msg_names[msg_id]);
+				      m->name);
 		    }
 		  shmem_hdr->garbage_collects++;
 		  goto collected;
@@ -731,10 +733,7 @@
 
   is_client ? svm_region_exit_client () : svm_region_exit ();
 
-  /* $$$ more careful cleanup, valgrind run... */
-  vec_free (am->msg_handlers);
-  vec_free (am->msg_endian_handlers);
-  vec_free (am->msg_print_handlers);
+  vec_free (am->msg_data);
 }
 
 void
diff --git a/src/vlibmemory/socket_api.c b/src/vlibmemory/socket_api.c
index 3df182b..e451d62 100644
--- a/src/vlibmemory/socket_api.c
+++ b/src/vlibmemory/socket_api.c
@@ -132,7 +132,7 @@
   cf = vl_api_registration_file (rp);
   ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
 
-  if (msg_id >= vec_len (am->api_trace_cfg))
+  if (msg_id >= vec_len (am->msg_data))
     {
       clib_warning ("id out of range: %d", msg_id);
       vl_msg_api_free ((void *) elem);
@@ -802,7 +802,7 @@
     vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t,  \
     vl_api_##n##_t_print_json, vl_api_##n##_t_tojson,                         \
     vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);                       \
-  am->api_trace_cfg[VL_API_##N].replay_enable = 0;
+  am->msg_data[VL_API_##N].replay_allowed = 0;
   foreach_vlib_api_msg;
 #undef _
 
diff --git a/src/vlibmemory/vlib_api.c b/src/vlibmemory/vlib_api.c
index b598f0b..3d4f882 100644
--- a/src/vlibmemory/vlib_api.c
+++ b/src/vlibmemory/vlib_api.c
@@ -340,7 +340,7 @@
    */
   msg_id_base = setup_message_id_table ();
 
-  am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_GET_NODE_GRAPH, 1);
   return 0;
 }
 
diff --git a/src/vlibmemory/vlib_api_cli.c b/src/vlibmemory/vlib_api_cli.c
index 39e2250..084080f 100644
--- a/src/vlibmemory/vlib_api_cli.c
+++ b/src/vlibmemory/vlib_api_cli.c
@@ -242,20 +242,19 @@
     vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce",
 		     "MP-safe");
 
-  for (i = 1; i < vec_len (am->msg_names); i++)
+  for (i = 1; i < vec_len (am->msg_data); i++)
     {
+      vl_api_msg_data_t *m = vl_api_get_msg_data (am, i);
       if (verbose == 0)
 	{
 	  vlib_cli_output (vm, "%-4d %s", i,
-			   am->msg_names[i] ? am->msg_names[i] :
-			   "  [no handler]");
+			   m->name ? m->name : "  [no handler]");
 	}
       else
 	{
 	  vlib_cli_output (vm, "%-4d %-40s %6d %7d", i,
-			   am->msg_names[i] ? am->msg_names[i] :
-			   "  [no handler]", am->message_bounce[i],
-			   am->is_mp_safe[i]);
+			   m->name ? m->name : "  [no handler]", m->bounce,
+			   m->is_mp_safe);
 	}
     }
 
@@ -510,7 +509,7 @@
       assert_size (file_size_left, clib_max (size, sizeof (u16)));
       msg_id = ntohs (*((u16 *) msg));
       if (msg_id >= vec_len (msgid_vec) ||
-	  msgid_vec[msg_id] >= vec_len (am->api_trace_cfg))
+	  msgid_vec[msg_id] >= vec_len (am->msg_data))
 	vlib_cli_output (vm, "warning: unknown msg id %d for msg number %d\n",
 			 msg_id, i);
 
@@ -522,7 +521,7 @@
 
   for (; i <= last_index; i++)
     {
-      trace_cfg_t *cfgp;
+      vl_api_msg_data_t *m;
       u16 msg_id;
       int size;
 
@@ -537,7 +536,7 @@
       msg_id = ntohs (*((u16 *) msg));
 
       if (msg_id >= vec_len (msgid_vec) ||
-	  msgid_vec[msg_id] >= vec_len (am->api_trace_cfg))
+	  msgid_vec[msg_id] >= vec_len (am->msg_data))
 	{
 	  vlib_cli_output (
 	    vm, "warning: unknown msg id %d for msg number %d, skipping\n",
@@ -547,7 +546,7 @@
 	}
 
       msg_id = msgid_vec[msg_id];
-      cfgp = am->api_trace_cfg + msg_id;
+      m = vl_api_get_msg_data (am, msg_id);
 
       /* Copy the buffer (from the read-only mmap'ed file) */
       vec_validate (tmpbuf, size - 1 + sizeof (uword));
@@ -561,9 +560,7 @@
       if (((which == DUMP || which == DUMP_JSON) &&
 	   clib_arch_is_little_endian))
 	{
-	  void (*endian_fp) (void *);
-	  if (msg_id >= vec_len (am->msg_endian_handlers)
-	      || (am->msg_endian_handlers[msg_id] == 0))
+	  if (m && m->endian_handler == 0)
 	    {
 	      vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id);
 	      munmap (hp, file_size);
@@ -571,8 +568,7 @@
 	      am->replay_in_progress = 0;
 	      return;
 	    }
-	  endian_fp = am->msg_endian_handlers[msg_id];
-	  (*endian_fp) (tmpbuf + sizeof (uword));
+	  m->endian_handler (tmpbuf + sizeof (uword));
 	}
 
       /* msg_id always in network byte order */
@@ -585,13 +581,9 @@
       switch (which)
 	{
 	case DUMP_JSON:
-	  if (msg_id < vec_len (am->msg_print_json_handlers) &&
-	      am->msg_print_json_handlers[msg_id])
+	  if (m && m->print_json_handler)
 	    {
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_json_handlers[msg_id];
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_json_handler (tmpbuf + sizeof (uword), vm);
 	    }
 	  else
 	    {
@@ -602,13 +594,9 @@
 	  break;
 
 	case DUMP:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id])
+	  if (m && m->print_handler)
 	    {
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_handlers[msg_id];
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_handler (tmpbuf + sizeof (uword), vm);
 	    }
 	  else
 	    {
@@ -619,25 +607,20 @@
 	  break;
 
 	case INITIALIZERS:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id])
+	  if (m && m->print_handler)
 	    {
 	      u8 *s;
 	      int j;
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_handlers[msg_id];
 
 	      vlib_cli_output (vm, "/*");
 
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_handler (tmpbuf + sizeof (uword), vm);
 	      vlib_cli_output (vm, "*/\n");
 
-	      s = format (0, "static u8 * vl_api_%s_%d[%d] = {",
-			  am->msg_names[msg_id], i,
-			  am->api_trace_cfg[msg_id].size);
+	      s = format (0, "static u8 * vl_api_%s_%d[%d] = {", m->name, i,
+			  m->trace_size);
 
-	      for (j = 0; j < am->api_trace_cfg[msg_id].size; j++)
+	      for (j = 0; j < m->trace_size; j++)
 		{
 		  if ((j & 7) == 0)
 		    s = format (s, "\n    ");
@@ -650,22 +633,17 @@
 	  break;
 
 	case REPLAY:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id] && cfgp->replay_enable)
+	  if (m && m->print_handler && m->replay_allowed)
 	    {
-	      void (*handler) (void *, vlib_main_t *);
-
-	      handler = (void *) am->msg_handlers[msg_id];
-
-	      if (!am->is_mp_safe[msg_id])
+	      if (!m->is_mp_safe)
 		vl_msg_api_barrier_sync ();
-	      (*handler) (tmpbuf + sizeof (uword), vm);
-	      if (!am->is_mp_safe[msg_id])
+	      m->handler (tmpbuf + sizeof (uword));
+	      if (!m->is_mp_safe)
 		vl_msg_api_barrier_release ();
 	    }
 	  else
 	    {
-	      if (cfgp->replay_enable)
+	      if (m->replay_allowed)
 		vlib_cli_output (vm, "Skipping msg id %d: no handler\n",
 				 msg_id);
 	      break;
@@ -708,11 +686,17 @@
   vl_msg_print_args *a = ctx;
   api_main_t *am = vlibapi_get_main ();
   u16 msg_id = ntohs (*((u16 *) msg));
-  void (*print_fp) (void *, void *);
-  void (**handlers) (void *, void *);
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id);
+  void (*handler) (void *, void *) = 0;
   u8 is_json = a->is_json;
   u8 *tmpbuf = 0;
 
+  if (!m)
+    {
+      vlib_cli_output (a->vm, "Unknown msg id %d\n", msg_id);
+      return 0;
+    }
+
   if (clib_arch_is_little_endian)
     {
       u32 msg_length = vec_len (msg);
@@ -720,25 +704,15 @@
       clib_memcpy_fast (tmpbuf, msg, msg_length);
       msg = tmpbuf;
 
-      void (*endian_fp) (void *);
-      endian_fp = am->msg_endian_handlers[msg_id];
-      (*endian_fp) (tmpbuf);
+      m->endian_handler (tmpbuf);
     }
 
-  if (is_json)
-    handlers = am->msg_print_json_handlers;
-  else
-    handlers = am->msg_print_handlers;
+  handler = is_json ? m->print_json_handler : m->print_handler;
 
-  if (msg_id < vec_len (handlers) && handlers[msg_id])
-    {
-      print_fp = (void *) handlers[msg_id];
-      (*print_fp) (msg, a->vm);
-    }
+  if (handler)
+    handler (msg, a->vm);
   else
-    {
-      vlib_cli_output (a->vm, "Skipping msg id %d: no print fcn\n", msg_id);
-    }
+    vlib_cli_output (a->vm, "Skipping msg id %d: no print fcn\n", msg_id);
 
   vec_free (tmpbuf);
   return 0;
@@ -825,9 +799,8 @@
 {
   api_main_t *am = vlibapi_get_main ();
   u16 msg_id;
-  void *(*fromjson) (cJSON *, int *);
   int len = 0, rv = -1;
-  trace_cfg_t *cfgp;
+  vl_api_msg_data_t *m;
   u8 *msg = 0;
 
   cJSON *msg_id_obj = cJSON_GetObjectItem (o, "_msgname");
@@ -849,6 +822,7 @@
 
   u8 *name_crc = format (0, "%s_%s%c", name, crc, 0);
   msg_id = vl_msg_find_id_by_name_and_crc (vm, am, (char *) name_crc);
+  m = vl_api_get_msg_data (am, msg_id);
   if (msg_id == (u16) ~0)
     {
       msg_id = vl_msg_find_id_by_name (vm, am, name);
@@ -862,28 +836,19 @@
     }
   vec_free (name_crc);
 
-  cfgp = am->api_trace_cfg + msg_id;
-  if (!am->api_trace_cfg)
+  if (m->replay_allowed)
     {
-      vlib_cli_output (vm, "msg id %d no trace config\n", msg_id);
-      return rv;
-    }
-
-  if (cfgp->replay_enable)
-    {
-
       if (proc_warning)
 	vlib_cli_output (vm, "warning: msg %d has different signature\n");
 
-      fromjson = am->msg_fromjson_handlers[msg_id];
-      if (!fromjson)
+      if (!m->fromjson_handler)
 	{
 	  vlib_cli_output (vm, "missing fromjson convert function! id %d\n",
 			   msg_id);
 	  return rv;
 	}
 
-      msg = (u8 *) fromjson (o, &len);
+      msg = (u8 *) m->fromjson_handler (o, &len);
       if (!msg)
 	{
 	  vlib_cli_output (vm, "failed to convert JSON (msg id %d)!\n",
@@ -892,24 +857,18 @@
 	}
 
       if (clib_arch_is_little_endian)
-	{
-	  void (*endian_fp) (void *);
-	  endian_fp = am->msg_endian_handlers[msg_id];
-	  (*endian_fp) (msg);
-	}
+	m->endian_handler (msg);
 
-      void (*handler) (void *, vlib_main_t *);
-      handler = (void *) am->msg_handlers[msg_id];
-      if (!handler)
+      if (!m->handler)
 	{
 	  vlib_cli_output (vm, "no handler for msg id %d!\n", msg_id);
 	  goto end;
 	}
 
-      if (!am->is_mp_safe[msg_id])
+      if (!m->is_mp_safe)
 	vl_msg_api_barrier_sync ();
-      (*handler) (msg, vm);
-      if (!am->is_mp_safe[msg_id])
+      m->handler (msg);
+      if (!m->is_mp_safe)
 	vl_msg_api_barrier_release ();
     }