summaryrefslogtreecommitdiff
path: root/lib/northbound_cli.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2019-04-03 16:31:18 -0300
committerRenato Westphal <renato@opensourcerouting.org>2019-04-26 18:04:22 -0300
commit83981138fe8c1e0a40b8dede74eca65449dda5de (patch)
treecd22f38c39e38eb1fb9f0dd7354fe19480523fba /lib/northbound_cli.c
parent364ad673c885d741d575e97dbae70bf6d7c8f36e (diff)
lib: introduce a read-write lock for northbound configurations
The upcoming gRPC-based northbound plugin will run on a separate pthread, and it will need to have access to the running configuration global variable. Introduce a rw-lock to control concurrent access to the running configuration. Add the lock inside the "nb_config" structure so that it can be used to protect candidate configurations as well (this might be necessary depending on the threading scheme of future northbound plugins). Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'lib/northbound_cli.c')
-rw-r--r--lib/northbound_cli.c139
1 files changed, 87 insertions, 52 deletions
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index cd79c0608e..ae1b0578a0 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -193,8 +193,13 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
"Please check the logs for more details.\n");
/* Regenerate candidate for consistency. */
- nb_config_replace(vty->candidate_config, running_config,
- true);
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ nb_config_replace(vty->candidate_config,
+ running_config, true);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
+
return CMD_WARNING_CONFIG_FAILED;
}
}
@@ -302,7 +307,12 @@ static int nb_cli_commit(struct vty *vty, bool force,
/* "confirm" parameter. */
if (confirmed_timeout) {
- vty->confirmed_commit_rollback = nb_config_dup(running_config);
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ vty->confirmed_commit_rollback =
+ nb_config_dup(running_config);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
vty->t_confirmed_commit_timeout = NULL;
thread_add_timer(master, nb_cli_confirmed_commit_timeout, vty,
@@ -316,8 +326,13 @@ static int nb_cli_commit(struct vty *vty, bool force,
/* Map northbound return code to CLI return code. */
switch (ret) {
case NB_OK:
- nb_config_replace(vty->candidate_config_base, running_config,
- true);
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ nb_config_replace(vty->candidate_config_base,
+ running_config, true);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
+
vty_out(vty,
"%% Configuration committed successfully (Transaction ID #%u).\n\n",
transaction_id);
@@ -682,7 +697,12 @@ DEFPY (config_update,
return CMD_WARNING;
}
- nb_config_replace(vty->candidate_config_base, running_config, true);
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ nb_config_replace(vty->candidate_config_base, running_config,
+ true);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
vty_out(vty, "%% Candidate configuration updated successfully.\n\n");
@@ -782,8 +802,12 @@ DEFPY (show_config_running,
}
}
- nb_cli_show_config(vty, running_config, format, translator,
- !!with_defaults);
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ nb_cli_show_config(vty, running_config, format, translator,
+ !!with_defaults);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
return CMD_SUCCESS;
}
@@ -897,57 +921,68 @@ DEFPY (show_config_compare,
struct nb_config *config2, *config_transaction2 = NULL;
int ret = CMD_WARNING;
- if (c1_candidate)
- config1 = vty->candidate_config;
- else if (c1_running)
- config1 = running_config;
- else {
- config_transaction1 = nb_db_transaction_load(c1_tid);
- if (!config_transaction1) {
- vty_out(vty, "%% Transaction %u does not exist\n\n",
- (unsigned int)c1_tid);
- goto exit;
+ /*
+ * For simplicity, lock the running configuration regardless if it's
+ * going to be used or not.
+ */
+ pthread_rwlock_rdlock(&running_config->lock);
+ {
+ if (c1_candidate)
+ config1 = vty->candidate_config;
+ else if (c1_running)
+ config1 = running_config;
+ else {
+ config_transaction1 = nb_db_transaction_load(c1_tid);
+ if (!config_transaction1) {
+ vty_out(vty,
+ "%% Transaction %u does not exist\n\n",
+ (unsigned int)c1_tid);
+ goto exit;
+ }
+ config1 = config_transaction1;
}
- config1 = config_transaction1;
- }
- if (c2_candidate)
- config2 = vty->candidate_config;
- else if (c2_running)
- config2 = running_config;
- else {
- config_transaction2 = nb_db_transaction_load(c2_tid);
- if (!config_transaction2) {
- vty_out(vty, "%% Transaction %u does not exist\n\n",
- (unsigned int)c2_tid);
- goto exit;
+ if (c2_candidate)
+ config2 = vty->candidate_config;
+ else if (c2_running)
+ config2 = running_config;
+ else {
+ config_transaction2 = nb_db_transaction_load(c2_tid);
+ if (!config_transaction2) {
+ vty_out(vty,
+ "%% Transaction %u does not exist\n\n",
+ (unsigned int)c2_tid);
+ goto exit;
+ }
+ config2 = config_transaction2;
}
- config2 = config_transaction2;
- }
- if (json)
- format = NB_CFG_FMT_JSON;
- else if (xml)
- format = NB_CFG_FMT_XML;
- else
- format = NB_CFG_FMT_CMDS;
+ if (json)
+ format = NB_CFG_FMT_JSON;
+ else if (xml)
+ format = NB_CFG_FMT_XML;
+ else
+ format = NB_CFG_FMT_CMDS;
- if (translator_family) {
- translator = yang_translator_find(translator_family);
- if (!translator) {
- vty_out(vty, "%% Module translator \"%s\" not found\n",
- translator_family);
- goto exit;
+ if (translator_family) {
+ translator = yang_translator_find(translator_family);
+ if (!translator) {
+ vty_out(vty,
+ "%% Module translator \"%s\" not found\n",
+ translator_family);
+ goto exit;
+ }
}
- }
- ret = nb_cli_show_config_compare(vty, config1, config2, format,
- translator);
-exit:
- if (config_transaction1)
- nb_config_free(config_transaction1);
- if (config_transaction2)
- nb_config_free(config_transaction2);
+ ret = nb_cli_show_config_compare(vty, config1, config2, format,
+ translator);
+ exit:
+ if (config_transaction1)
+ nb_config_free(config_transaction1);
+ if (config_transaction2)
+ nb_config_free(config_transaction2);
+ }
+ pthread_rwlock_unlock(&running_config->lock);
return ret;
}