blob: 4b0fc73258e47e68ab7f9b47092a8d5519f644f3 [file] [log] [blame]
paul43313d02005-04-19 21:28:36 +00001/*
paulf4d062f2005-04-21 16:58:44 +00002 * $Id: heavy.c,v 1.2 2005/04/21 16:58:44 paul Exp $
paul43313d02005-04-19 21:28:36 +00003 *
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
17 * along with Quagga; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22/* This programme shows the effects of 'heavy' long-running functions
23 * on the cooperative threading model.
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 the vty interface is unresponsive
28 * for quite a period of time, due to the clear_something command
29 * taking a very long time to complete.
30 */
31#include <zebra.h>
32
33#include <lib/version.h>
34#include "getopt.h"
35#include "thread.h"
36#include "vty.h"
37#include "command.h"
38#include "memory.h"
paulf4d062f2005-04-21 16:58:44 +000039#include <math.h>
paul43313d02005-04-19 21:28:36 +000040
41struct thread_master *master;
42
43struct option longopts[] =
44{
45 { "daemon", no_argument, NULL, 'd'},
46 { "config_file", required_argument, NULL, 'f'},
47 { "help", no_argument, NULL, 'h'},
48 { "vty_addr", required_argument, NULL, 'A'},
49 { "vty_port", required_argument, NULL, 'P'},
50 { "version", no_argument, NULL, 'v'},
51 { 0 }
52};
53
54enum
55{
56 ITERS_FIRST = 0,
paulf4d062f2005-04-21 16:58:44 +000057 ITERS_ERR = 100,
58 ITERS_LATER = 400,
paul43313d02005-04-19 21:28:36 +000059 ITERS_PRINT = 10,
60 ITERS_MAX = 1000,
61};
62
63static void
paulf4d062f2005-04-21 16:58:44 +000064slow_func (struct vty *vty, const char *str, const int i)
paul43313d02005-04-19 21:28:36 +000065{
paulf4d062f2005-04-21 16:58:44 +000066 double x = 1;
67 int j;
68
69 for (j = 0; j < 300000; j++)
70 x += sin(x)*j;
71
72 if ((i % ITERS_LATER) == 0)
73 printf ("%s: %d, temporary error, save this somehow and do it later..\n",
74 __func__, i);
75
76 if ((i % ITERS_ERR) == 0)
77 printf ("%s: hard error\n", __func__);
78
paul43313d02005-04-19 21:28:36 +000079 if ((i % ITERS_PRINT) == 0)
paulf4d062f2005-04-21 16:58:44 +000080 printf ("%s did %d, x = %g%s", str, i, x, VTY_NEWLINE);
paul43313d02005-04-19 21:28:36 +000081}
82
83static void
paulf4d062f2005-04-21 16:58:44 +000084clear_something (struct vty *vty, const char *str)
paul43313d02005-04-19 21:28:36 +000085{
86 int i;
87
88 /* this could be like iterating through 150k of route_table
paulf4d062f2005-04-21 16:58:44 +000089 * or worse, iterating through a list of peers, to bgp_stop them with
90 * each having 150k route tables to process...
paul43313d02005-04-19 21:28:36 +000091 */
92 for (i = ITERS_FIRST; i < ITERS_MAX; i++)
93 slow_func (vty, str, i);
paulf4d062f2005-04-21 16:58:44 +000094}
95
96DEFUN (daemon_exit,
97 daemon_exit_cmd,
98 "daemon-exit",
99 "Make the daemon exit\n")
100{
101 exit(0);
paul43313d02005-04-19 21:28:36 +0000102}
103
104DEFUN (clear_foo,
105 clear_foo_cmd,
106 "clear foo .LINE",
107 "clear command\n"
108 "arbitrary string\n")
109{
110 char *str;
111 if (!argc)
112 {
113 vty_out (vty, "%% string argument required%s", VTY_NEWLINE);
114 return CMD_WARNING;
115 }
116
117 str = argv_concat (argv, argc, 0);
118
119 clear_something (vty, str);
paulf4d062f2005-04-21 16:58:44 +0000120 XFREE (MTYPE_TMP, str);
paul43313d02005-04-19 21:28:36 +0000121 return CMD_SUCCESS;
122}
123
paulf4d062f2005-04-21 16:58:44 +0000124static int timer_count;
125int
126heavy_timer (struct thread *thread)
127{
128 int *count = THREAD_ARG(thread);
129
130 printf ("run %d of timer\n", (*count)++);
131 thread_add_timer (master, heavy_timer, count, 5);
132 return 0;
133}
134
135static void
136heavy_timer_init()
137{
138 thread_add_timer (master, heavy_timer, &timer_count, 5);
139}
140
paul43313d02005-04-19 21:28:36 +0000141static void
142slow_vty_init()
143{
paulf4d062f2005-04-21 16:58:44 +0000144 install_element (VIEW_NODE, &clear_foo_cmd);
145 install_element (VIEW_NODE, &daemon_exit_cmd);
paul43313d02005-04-19 21:28:36 +0000146}
147
148/* Help information display. */
149static void
150usage (char *progname, int status)
151{
152 if (status != 0)
153 fprintf (stderr, "Try `%s --help' for more information.\n", progname);
154 else
155 {
156 printf ("Usage : %s [OPTION...]\n\
157Daemon which does 'slow' things.\n\n\
158-d, --daemon Runs in daemon mode\n\
159-f, --config_file Set configuration file name\n\
160-A, --vty_addr Set vty's bind address\n\
161-P, --vty_port Set vty's port number\n\
162-v, --version Print program version\n\
163-h, --help Display this help and exit\n\
164\n\
165Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
166 }
167 exit (status);
168}
169
170
171/* main routine. */
172int
173main (int argc, char **argv)
174{
175 char *p;
176 char *vty_addr = NULL;
177 int vty_port = 4000;
178 int daemon_mode = 0;
179 char *progname;
180 struct thread thread;
181 char *config_file = NULL;
182
183 /* Set umask before anything for security */
184 umask (0027);
185
186 /* get program name */
187 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
188
189 /* master init. */
190 master = thread_master_create ();
191
192 while (1)
193 {
194 int opt;
195
196 opt = getopt_long (argc, argv, "dhf:A:P:v", longopts, 0);
197
198 if (opt == EOF)
199 break;
200
201 switch (opt)
202 {
203 case 0:
204 break;
205 case 'f':
206 config_file = optarg;
207 break;
208 case 'd':
209 daemon_mode = 1;
210 break;
211 case 'A':
212 vty_addr = optarg;
213 break;
214 case 'P':
215 /* Deal with atoi() returning 0 on failure */
216 if (strcmp(optarg, "0") == 0)
217 {
218 vty_port = 0;
219 break;
220 }
221 vty_port = atoi (optarg);
222 vty_port = (vty_port ? vty_port : 4000);
223 break;
224 case 'v':
225 print_version (progname);
226 exit (0);
227 break;
228 case 'h':
229 usage (progname, 0);
230 break;
231 default:
232 usage (progname, 1);
233 break;
234 }
235 }
236
237 /* Library inits. */
238 cmd_init (1);
239 vty_init (master);
240 memory_init ();
241
242 /* OSPF vty inits. */
243 slow_vty_init ();
244
245 sort_node ();
246
247 /* Change to the daemon program. */
248 if (daemon_mode)
249 daemon (0, 0);
250
251 /* Create VTY socket */
252 vty_serv_sock (vty_addr, vty_port, "/tmp/.heavy.sock");
253
254 /* Configuration file read*/
255 if (!config_file)
256 usage (progname, 1);
257 vty_read_config (config_file, NULL);
258
paulf4d062f2005-04-21 16:58:44 +0000259 heavy_timer_init();
260
paul43313d02005-04-19 21:28:36 +0000261 /* Fetch next active thread. */
262 while (thread_fetch (master, &thread))
263 thread_call (&thread);
264
265 /* Not reached. */
266 exit (0);
267}
268