summaryrefslogtreecommitdiffstats
path: root/lib/command_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/command_queue.c')
-rw-r--r--lib/command_queue.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/lib/command_queue.c b/lib/command_queue.c
new file mode 100644
index 00000000..5f14abae
--- /dev/null
+++ b/lib/command_queue.c
@@ -0,0 +1,154 @@
+/* Command Message Queue
+ * Copyright (C) 2009 Chris Hall (GMCH), Highwayman
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#include "mqueue.h"
+#include "qpnexus.h"
+#include "memory.h"
+#include "command_queue.h"
+#include "command_execute.h"
+#include "vty.h"
+#include "uty.h"
+#include "vector.h"
+#include "qstring.h"
+
+/*------------------------------------------------------------------------------
+ * Form of message passed with command to be executed
+ */
+
+struct cq_command_args
+{
+ enum cmd_return_code ret ; /* return code from command */
+} ;
+MQB_ARGS_SIZE_OK(cq_command_args) ;
+
+/*------------------------------------------------------------------------------
+ * Prototypes
+ */
+static void cq_action(mqueue_block mqb, mqb_flag_t flag);
+static void cq_return(mqueue_block mqb, mqb_flag_t flag);
+
+/*------------------------------------------------------------------------------
+ * Enqueue vty and argv[] for execution in given nexus.
+ */
+void
+cq_enqueue(struct vty *vty, qpn_nexus dst)
+{
+ struct cq_command_args* args ;
+ mqueue_block mqb ;
+
+ assert(vty_cli_nexus) ; /* must be running qnexus-wise */
+
+ mqb = mqb_init_new(NULL, cq_action, vty) ;
+ args = mqb_get_args(mqb) ;
+
+ args->ret = CMD_QUEUED ;
+
+ mqueue_enqueue(dst->queue, mqb, 0) ;
+}
+
+/*------------------------------------------------------------------------------
+ * Dispatch a command from the message queue block
+ *
+ * When done (or revoked/deleted) return the message, so that the sender knows
+ * that the command has been dealt with (one way or another).
+ *
+ * Note that if the command is revoked the return is set to CMD_QUEUED.
+ */
+static void
+cq_action(mqueue_block mqb, mqb_flag_t flag)
+{
+ struct vty *vty;
+ struct cq_command_args* args ;
+
+ assert(vty_cli_nexus) ; /* must be running qnexus-wise */
+
+ vty = mqb_get_arg0(mqb);
+ args = mqb_get_args(mqb) ;
+
+ if (flag == mqb_action)
+ {
+ args->ret = cmd_dispatch_call(vty) ;
+ assert(args->ret != CMD_QUEUED) ; /* avoid confusion ! */
+ }
+ else
+ args->ret = CMD_QUEUED ;
+
+ mqb_set_action(mqb, cq_return) ;
+ mqueue_enqueue(vty_cli_nexus->queue, mqb, 0) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Accept return from command which has completed.
+ *
+ * The command line processing for the vty may be stalled (with read mode
+ * disabled) waiting for the return from the command.
+ *
+ * Do not care whether the message is being revoked or not... the command
+ * has completed and that must be signalled to the CLI. Any pending output
+ * is released.
+ *
+ * The command itself may have been revoked before it was executed. That
+ * makes no difference either... the output buffers will simply be empty.
+ * However, the return code is CMD_QUEUED, to signal the fact that the command
+ * was never executed.
+ */
+static void
+cq_return(mqueue_block mqb, mqb_flag_t flag)
+{
+ struct vty *vty ;
+ struct cq_command_args* args ;
+
+ assert(vty_cli_nexus) ; /* must be running qnexus-wise */
+
+ vty = mqb_get_arg0(mqb) ;
+ args = mqb_get_args(mqb) ;
+
+ /* signal end of command */
+ cmd_post_command(vty, args->ret) ;
+ vty_queued_result(vty, args->ret) ;
+
+//if (qpthreads_enabled)
+// qpt_thread_signal(vty_cli_nexus->thread_id, SIGMQUEUE);
+
+ mqb_free(mqb);
+}
+
+/*------------------------------------------------------------------------------
+ * Revoke any messages related to the given VTY -- if running qnexus-wise.
+ *
+ * Revokes in vty_cmd_nexus -- so before command is started
+ * and in vty_cli_nexus -- so after command has completed
+ *
+ * Can do nothing about any command actually being executed in the
+ * vty_cmd_nexus.
+ */
+void
+cq_revoke(struct vty *vty)
+{
+ if (vty_cli_nexus)
+ {
+ mqueue_revoke(vty_cmd_nexus->queue, vty) ;
+ mqueue_revoke(vty_cli_nexus->queue, vty) ;
+ } ;
+}
+