From 97cd849362b45ecbcb20194b5771c5ce777de6bc Mon Sep 17 00:00:00 2001
From: Renato Westphal <renato@opensourcerouting.org>
Date: Tue, 21 Apr 2020 21:27:47 -0300
Subject: [PATCH] lib: create a wrapper function for all northbound callbacks

The intention here is to keep the code more organized. These wrappers
should be used by the northbound clients only, and never directly
by any YANG backend code.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
---
 lib/northbound.c        | 222 +++++++++++++++++++++++-----------------
 lib/northbound_grpc.cpp |   3 +-
 2 files changed, 131 insertions(+), 94 deletions(-)

diff --git a/lib/northbound.c b/lib/northbound.c
index 85e723d7cf..d10e4713f5 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -62,11 +62,10 @@ static struct {
  */
 static bool transaction_in_progress;
 
+static int nb_callback_pre_validate(const struct nb_node *nb_node,
+				    const struct lyd_node *dnode);
 static int nb_callback_configuration(const enum nb_event event,
 				     struct nb_config_change *change);
-static void nb_log_callback(const enum nb_event event,
-			    enum nb_operation operation, const char *xpath,
-			    const char *value);
 static struct nb_transaction *nb_transaction_new(struct nb_config *config,
 						 struct nb_config_cbs *changes,
 						 enum nb_client client,
@@ -609,18 +608,7 @@ static int nb_candidate_validate_code(struct nb_config *candidate,
 			if (!nb_node->cbs.pre_validate)
 				goto next;
 
-			if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config,
-					     DEBUG_MODE_ALL)) {
-				char xpath[XPATH_MAXLEN];
-
-				yang_dnode_get_path(child, xpath,
-						    sizeof(xpath));
-				nb_log_callback(NB_EV_VALIDATE,
-						NB_OP_PRE_VALIDATE, xpath,
-						NULL);
-			}
-
-			ret = (*nb_node->cbs.pre_validate)(child);
+			ret = nb_callback_pre_validate(nb_node, child);
 			if (ret != NB_OK)
 				return NB_ERR_VALIDATION;
 
@@ -791,14 +779,128 @@ int nb_running_lock_check(enum nb_client client, const void *user)
 	return ret;
 }
 
-static void nb_log_callback(const enum nb_event event,
-			    enum nb_operation operation, const char *xpath,
-			    const char *value)
+static void nb_log_config_callback(const enum nb_event event,
+				   enum nb_operation operation,
+				   const struct lyd_node *dnode)
 {
+	const char *value;
+	char xpath[XPATH_MAXLEN];
+
+	if (!DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL))
+		return;
+
+	yang_dnode_get_path(dnode, xpath, sizeof(xpath));
+	if (yang_snode_is_typeless_data(dnode->schema))
+		value = "(none)";
+	else
+		value = yang_dnode_get_string(dnode, NULL);
+
 	zlog_debug(
 		"northbound callback: event [%s] op [%s] xpath [%s] value [%s]",
 		nb_event_name(event), nb_operation_name(operation), xpath,
-		value ? value : "(NULL)");
+		value);
+}
+
+static int nb_callback_create(const struct nb_node *nb_node,
+			      enum nb_event event, const struct lyd_node *dnode,
+			      union nb_resource *resource)
+{
+	nb_log_config_callback(event, NB_OP_CREATE, dnode);
+
+	return nb_node->cbs.create(event, dnode, resource);
+}
+
+static int nb_callback_modify(const struct nb_node *nb_node,
+			      enum nb_event event, const struct lyd_node *dnode,
+			      union nb_resource *resource)
+{
+	nb_log_config_callback(event, NB_OP_MODIFY, dnode);
+
+	return nb_node->cbs.modify(event, dnode, resource);
+}
+
+static int nb_callback_destroy(const struct nb_node *nb_node,
+			       enum nb_event event,
+			       const struct lyd_node *dnode)
+{
+	nb_log_config_callback(event, NB_OP_DESTROY, dnode);
+
+	return nb_node->cbs.destroy(event, dnode);
+}
+
+static int nb_callback_move(const struct nb_node *nb_node, enum nb_event event,
+			    const struct lyd_node *dnode)
+{
+	nb_log_config_callback(event, NB_OP_MOVE, dnode);
+
+	return nb_node->cbs.move(event, dnode);
+}
+
+static int nb_callback_pre_validate(const struct nb_node *nb_node,
+				    const struct lyd_node *dnode)
+{
+	nb_log_config_callback(NB_EV_VALIDATE, NB_OP_PRE_VALIDATE, dnode);
+
+	return nb_node->cbs.pre_validate(dnode);
+}
+
+static void nb_callback_apply_finish(const struct nb_node *nb_node,
+				     const struct lyd_node *dnode)
+{
+	nb_log_config_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, dnode);
+
+	nb_node->cbs.apply_finish(dnode);
+}
+
+struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
+				       const char *xpath,
+				       const void *list_entry)
+{
+	DEBUGD(&nb_dbg_cbs_state,
+	       "northbound callback (get_elem): xpath [%s] list_entry [%p]",
+	       xpath, list_entry);
+
+	return nb_node->cbs.get_elem(xpath, list_entry);
+}
+
+const void *nb_callback_get_next(const struct nb_node *nb_node,
+				 const void *parent_list_entry,
+				 const void *list_entry)
+{
+	DEBUGD(&nb_dbg_cbs_state,
+	       "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]",
+	       nb_node->xpath, parent_list_entry, list_entry);
+
+	return nb_node->cbs.get_next(parent_list_entry, list_entry);
+}
+
+int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry,
+			 struct yang_list_keys *keys)
+{
+	DEBUGD(&nb_dbg_cbs_state,
+	       "northbound callback (get_keys): node [%s] list_entry [%p]",
+	       nb_node->xpath, list_entry);
+
+	return nb_node->cbs.get_keys(list_entry, keys);
+}
+
+const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
+				     const void *parent_list_entry,
+				     const struct yang_list_keys *keys)
+{
+	DEBUGD(&nb_dbg_cbs_state,
+	       "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]",
+	       nb_node->xpath, parent_list_entry);
+
+	return nb_node->cbs.lookup_entry(parent_list_entry, keys);
+}
+
+int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
+		    const struct list *input, struct list *output)
+{
+	DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
+
+	return nb_node->cbs.rpc(xpath, input, output);
 }
 
 /*
@@ -815,15 +917,6 @@ static int nb_callback_configuration(const enum nb_event event,
 	union nb_resource *resource;
 	int ret = NB_ERR;
 
-	if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) {
-		const char *value = "(none)";
-
-		if (dnode && !yang_snode_is_typeless_data(dnode->schema))
-			value = yang_dnode_get_string(dnode, NULL);
-
-		yang_dnode_get_path(dnode, xpath, sizeof(xpath));
-		nb_log_callback(event, operation, xpath, value);
-	}
 
 	if (event == NB_EV_VALIDATE)
 		resource = NULL;
@@ -832,16 +925,16 @@ static int nb_callback_configuration(const enum nb_event event,
 
 	switch (operation) {
 	case NB_OP_CREATE:
-		ret = (*nb_node->cbs.create)(event, dnode, resource);
+		ret = nb_callback_create(nb_node, event, dnode, resource);
 		break;
 	case NB_OP_MODIFY:
-		ret = (*nb_node->cbs.modify)(event, dnode, resource);
+		ret = nb_callback_modify(nb_node, event, dnode, resource);
 		break;
 	case NB_OP_DESTROY:
-		ret = (*nb_node->cbs.destroy)(event, dnode);
+		ret = nb_callback_destroy(nb_node, event, dnode);
 		break;
 	case NB_OP_MOVE:
-		ret = (*nb_node->cbs.move)(event, dnode);
+		ret = nb_callback_move(nb_node, event, dnode);
 		break;
 	default:
 		yang_dnode_get_path(dnode, xpath, sizeof(xpath));
@@ -890,57 +983,6 @@ static int nb_callback_configuration(const enum nb_event event,
 	return ret;
 }
 
-struct yang_data *nb_callback_get_elem(const struct nb_node *nb_node,
-				       const char *xpath,
-				       const void *list_entry)
-{
-	DEBUGD(&nb_dbg_cbs_state,
-	       "northbound callback (get_elem): xpath [%s] list_entry [%p]",
-	       xpath, list_entry);
-
-	return nb_node->cbs.get_elem(xpath, list_entry);
-}
-
-const void *nb_callback_get_next(const struct nb_node *nb_node,
-				 const void *parent_list_entry,
-				 const void *list_entry)
-{
-	DEBUGD(&nb_dbg_cbs_state,
-	       "northbound callback (get_next): node [%s] parent_list_entry [%p] list_entry [%p]",
-	       nb_node->xpath, parent_list_entry, list_entry);
-
-	return nb_node->cbs.get_next(parent_list_entry, list_entry);
-}
-
-int nb_callback_get_keys(const struct nb_node *nb_node, const void *list_entry,
-			 struct yang_list_keys *keys)
-{
-	DEBUGD(&nb_dbg_cbs_state,
-	       "northbound callback (get_keys): node [%s] list_entry [%p]",
-	       nb_node->xpath, list_entry);
-
-	return nb_node->cbs.get_keys(list_entry, keys);
-}
-
-const void *nb_callback_lookup_entry(const struct nb_node *nb_node,
-				     const void *parent_list_entry,
-				     const struct yang_list_keys *keys)
-{
-	DEBUGD(&nb_dbg_cbs_state,
-	       "northbound callback (lookup_entry): node [%s] parent_list_entry [%p]",
-	       nb_node->xpath, parent_list_entry);
-
-	return nb_node->cbs.lookup_entry(parent_list_entry, keys);
-}
-
-int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
-		    const struct list *input, struct list *output)
-{
-	DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
-
-	return nb_node->cbs.rpc(xpath, input, output);
-}
-
 static struct nb_transaction *
 nb_transaction_new(struct nb_config *config, struct nb_config_cbs *changes,
 		   enum nb_client client, const void *user, const char *comment)
@@ -1058,7 +1100,6 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
 {
 	struct nb_config_cbs cbs;
 	struct nb_config_cb *cb;
-	char xpath[XPATH_MAXLEN];
 
 	/* Initialize tree of 'apply_finish' callbacks. */
 	RB_INIT(nb_config_cbs, &cbs);
@@ -1075,6 +1116,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
 		 * be called though).
 		 */
 		if (change->cb.operation == NB_OP_DESTROY) {
+			char xpath[XPATH_MAXLEN];
+
 			dnode = dnode->parent;
 			if (!dnode)
 				break;
@@ -1111,15 +1154,8 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction)
 	}
 
 	/* Call the 'apply_finish' callbacks, sorted by their priorities. */
-	RB_FOREACH (cb, nb_config_cbs, &cbs) {
-		if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) {
-			yang_dnode_get_path(cb->dnode, xpath, sizeof(xpath));
-			nb_log_callback(NB_EV_APPLY, NB_OP_APPLY_FINISH, xpath,
-					NULL);
-		}
-
-		(*cb->nb_node->cbs.apply_finish)(cb->dnode);
-	}
+	RB_FOREACH (cb, nb_config_cbs, &cbs)
+		nb_callback_apply_finish(cb->nb_node, cb->dnode);
 
 	/* Release memory. */
 	while (!RB_EMPTY(nb_config_cbs, &cbs)) {
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index b195f1aeca..66bf05c1ab 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -545,7 +545,8 @@ class NorthboundImpl final : public frr::Northbound::Service
 		}
 
 		// Execute callback registered for this XPath.
-		if (nb_node->cbs.rpc(xpath, input_list, output_list) != NB_OK) {
+		if (nb_callback_rpc(nb_node, xpath, input_list, output_list)
+		    != NB_OK) {
 			flog_warn(EC_LIB_NB_CB_RPC,
 				  "%s: rpc callback failed: %s", __func__,
 				  xpath);
