]> git.proxmox.com Git - mirror_frr.git/blame - tests/lib/test_heavy_wq.c
*: ditch vty_outln(), part 1 of 2
[mirror_frr.git] / tests / lib / test_heavy_wq.c
CommitLineData
9f3f7a11 1/*
9f3f7a11 2 * This file is part of Quagga.
3 *
4 * Quagga is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2, or (at your option) any
7 * later version.
8 *
9 * Quagga is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
896014f4
DL
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9f3f7a11 17 */
18
19/* This programme shows the effects of 'heavy' long-running functions
20 * on the cooperative threading model.
21 *
22 * Run it with a config file containing 'password whatever', telnet to it
23 * (it defaults to port 4000) and enter the 'clear foo string' command.
24 * then type whatever and observe that the vty interface is unresponsive
25 * for quite a period of time, due to the clear_something command
26 * taking a very long time to complete.
27 */
28#include <zebra.h>
29
30#include "thread.h"
31#include "vty.h"
32#include "command.h"
33#include "memory.h"
34#include "log.h"
35#include "workqueue.h"
36#include <math.h>
37
9fc3f9b3
DL
38#include "tests.h"
39
4a1ab8e4
DL
40DEFINE_MGROUP(TEST_HEAVYWQ, "heavy-wq test")
41DEFINE_MTYPE_STATIC(TEST_HEAVYWQ, WQ_NODE, "heavy_wq_node")
42DEFINE_MTYPE_STATIC(TEST_HEAVYWQ, WQ_NODE_STR, "heavy_wq_node->str")
43
9f3f7a11 44extern struct thread_master *master;
45static struct work_queue *heavy_wq;
46
47struct heavy_wq_node
48{
49 char *str;
50 int i;
51};
52
53enum
54{
55 ITERS_FIRST = 0,
56 ITERS_ERR = 100,
57 ITERS_LATER = 400,
58 ITERS_PRINT = 10,
59 ITERS_MAX = 1000,
60};
61
62static void
63heavy_wq_add (struct vty *vty, const char *str, int i)
64{
65 struct heavy_wq_node *hn;
66
4a1ab8e4 67 if ((hn = XCALLOC (MTYPE_WQ_NODE, sizeof(struct heavy_wq_node))) == NULL)
9f3f7a11 68 {
69 zlog_err ("%s: unable to allocate hn", __func__);
70 return;
71 }
72
73 hn->i = i;
4a1ab8e4 74 if (!(hn->str = XSTRDUP (MTYPE_WQ_NODE_STR, str)))
9f3f7a11 75 {
76 zlog_err ("%s: unable to xstrdup", __func__);
4a1ab8e4 77 XFREE (MTYPE_WQ_NODE, hn);
9f3f7a11 78 return;
79 }
80
81 work_queue_add (heavy_wq, hn);
82
83 return;
84}
85
86static void
87slow_func_err (struct work_queue *wq, struct work_queue_item *item)
88{
89 printf ("%s: running error function\n", __func__);
90}
91
92static void
3414bf25 93slow_func_del (struct work_queue *wq, void *data)
9f3f7a11 94{
6379b961 95 struct heavy_wq_node *hn = data;
9f3f7a11 96 assert (hn && hn->str);
3414bf25 97 printf ("%s: %s\n", __func__, hn->str);
4a1ab8e4 98 XFREE (MTYPE_WQ_NODE_STR, hn->str);
9f3f7a11 99 hn->str = NULL;
4a1ab8e4 100 XFREE(MTYPE_WQ_NODE, hn);
9f3f7a11 101}
102
103static wq_item_status
3414bf25 104slow_func (struct work_queue *wq, void *data)
9f3f7a11 105{
6379b961 106 struct heavy_wq_node *hn = data;
9f3f7a11 107 double x = 1;
108 int j;
109
110 assert (hn && hn->str);
111
112 for (j = 0; j < 300; j++)
113 x += sin(x)*j;
114
115 if ((hn->i % ITERS_LATER) == 0)
116 return WQ_RETRY_LATER;
117
118 if ((hn->i % ITERS_ERR) == 0)
119 return WQ_RETRY_NOW;
120
121 if ((hn->i % ITERS_PRINT) == 0)
122 printf ("%s did %d, x = %g\n", hn->str, hn->i, x);
123
124 return WQ_SUCCESS;
125}
126
127static void
128clear_something (struct vty *vty, const char *str)
129{
130 int i;
131
132 /* this could be like iterating through 150k of route_table
133 * or worse, iterating through a list of peers, to bgp_stop them with
134 * each having 150k route tables to process...
135 */
136 for (i = ITERS_FIRST; i < ITERS_MAX; i++)
137 heavy_wq_add (vty, str, i);
138}
139
140DEFUN (clear_foo,
141 clear_foo_cmd,
e961923c 142 "clear foo LINE...",
9f3f7a11 143 "clear command\n"
144 "arbitrary string\n")
145{
146 char *str;
147 if (!argc)
148 {
5c7571d4 149 vty_out (vty, "%% string argument required\n");
9f3f7a11 150 return CMD_WARNING;
151 }
152
153 str = argv_concat (argv, argc, 0);
154
155 clear_something (vty, str);
156 XFREE (MTYPE_TMP, str);
157 return CMD_SUCCESS;
158}
159
160static int
161heavy_wq_init ()
162{
163 if (! (heavy_wq = work_queue_new (master, "heavy_work_queue")))
164 {
165 zlog_err ("%s: could not get new work queue!", __func__);
166 return -1;
167 }
168
169 heavy_wq->spec.workfunc = &slow_func;
170 heavy_wq->spec.errorfunc = &slow_func_err;
171 heavy_wq->spec.del_item_data = &slow_func_del;
172 heavy_wq->spec.max_retries = 3;
9f3f7a11 173 heavy_wq->spec.hold = 1000;
174
175 return 0;
176}
177
178void
179test_init()
180{
181 install_element (VIEW_NODE, &clear_foo_cmd);
182 heavy_wq_init();
183}