1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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) ;
} ;
}
|