]> git.proxmox.com Git - mirror_frr.git/blob - tests/lib/test_heavy_thread.c
Merge commit '3d22338f04d9554fa' into evpn-prep
[mirror_frr.git] / tests / lib / test_heavy_thread.c
1 /*
2 * $Id: heavy-thread.c,v 1.2 2005/04/25 16:42:24 paul Exp $
3 *
4 * This file is part of Quagga.
5 *
6 * Quagga is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * Quagga is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /* This programme shows the effects of 'heavy' long-running functions
22 * on the cooperative threading model, as demonstrated by heavy.c, and how
23 * they can be mitigated using a background thread.
24 *
25 * Run it with a config file containing 'password whatever', telnet to it
26 * (it defaults to port 4000) and enter the 'clear foo string' command.
27 * then type whatever and observe that, unlike heavy.c, the vty interface
28 * remains responsive.
29 */
30 #include <zebra.h>
31 #include <math.h>
32
33 #include "thread.h"
34 #include "vty.h"
35 #include "command.h"
36 #include "memory.h"
37 #include "log.h"
38
39 #include "tests.h"
40
41 extern struct thread_master *master;
42
43 enum
44 {
45 ITERS_FIRST = 0,
46 ITERS_ERR = 100,
47 ITERS_LATER = 400,
48 ITERS_PRINT = 10,
49 ITERS_MAX = 1000,
50 };
51
52 struct work_state {
53 struct vty *vty;
54 char *str;
55 int i;
56 };
57
58 static void
59 slow_func (struct vty *vty, const char *str, const int i)
60 {
61 double x = 1;
62 int j;
63
64 for (j = 0; j < 300; j++)
65 x += sin(x)*j;
66
67 if ((i % ITERS_LATER) == 0)
68 printf ("%s: %d, temporary error, save this somehow and do it later..\n",
69 __func__, i);
70
71 if ((i % ITERS_ERR) == 0)
72 printf ("%s: hard error\n", __func__);
73
74 if ((i % ITERS_PRINT) == 0)
75 printf ("%s did %d, x = %g\n", str, i, x);
76 }
77
78 static int
79 clear_something (struct thread *thread)
80 {
81 struct work_state *ws = THREAD_ARG(thread);
82
83 /* this could be like iterating through 150k of route_table
84 * or worse, iterating through a list of peers, to bgp_stop them with
85 * each having 150k route tables to process...
86 */
87 while (ws->i < ITERS_MAX)
88 {
89 slow_func(ws->vty, ws->str, ws->i);
90 ws->i++;
91 if (thread_should_yield(thread))
92 {
93 thread_add_timer_msec (master, clear_something, ws, 0, NULL);
94 return 0;
95 }
96 }
97
98 /* All done! */
99 XFREE (MTYPE_TMP, ws->str);
100 XFREE (MTYPE_TMP, ws);
101 return 0;
102 }
103
104 DEFUN (clear_foo,
105 clear_foo_cmd,
106 "clear foo LINE...",
107 "clear command\n"
108 "arbitrary string\n")
109 {
110 char *str;
111 struct work_state *ws;
112
113 if (!argc)
114 {
115 vty_outln (vty, "%% string argument required");
116 return CMD_WARNING;
117 }
118
119 str = argv_concat (argv, argc, 0);
120
121 if ((ws = XMALLOC(MTYPE_TMP, sizeof(*ws))) == NULL)
122 {
123 zlog_err ("%s: unable to allocate work_state", __func__);
124 return CMD_WARNING;
125 }
126
127 if (!(ws->str = XSTRDUP (MTYPE_TMP, str)))
128 {
129 zlog_err ("%s: unable to xstrdup", __func__);
130 XFREE (MTYPE_TMP, ws);
131 return CMD_WARNING;
132 }
133
134 ws->vty = vty;
135 ws->i = ITERS_FIRST;
136
137 thread_add_timer_msec (master, clear_something, ws, 0, NULL);
138
139 return CMD_SUCCESS;
140 }
141
142 void
143 test_init()
144 {
145 install_element (VIEW_NODE, &clear_foo_cmd);
146 }