Annotation of embedaddon/quagga/tests/heavy-wq.c, revision 1.1.1.2
1.1 misho 1: /*
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: *
14: * You should have received a copy of the GNU General Public License
15: * along with Quagga; see the file COPYING. If not, write to the Free
16: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17: * 02111-1307, USA.
18: */
19:
20: /* This programme shows the effects of 'heavy' long-running functions
21: * on the cooperative threading model.
22: *
23: * Run it with a config file containing 'password whatever', telnet to it
24: * (it defaults to port 4000) and enter the 'clear foo string' command.
25: * then type whatever and observe that the vty interface is unresponsive
26: * for quite a period of time, due to the clear_something command
27: * taking a very long time to complete.
28: */
29: #include <zebra.h>
30:
31: #include "thread.h"
32: #include "vty.h"
33: #include "command.h"
34: #include "memory.h"
35: #include "log.h"
36: #include "workqueue.h"
37: #include <math.h>
38:
1.1.1.2 ! misho 39: #include "tests.h"
! 40:
1.1 misho 41: extern struct thread_master *master;
42: static struct work_queue *heavy_wq;
43:
44: struct heavy_wq_node
45: {
46: char *str;
47: int i;
48: };
49:
50: enum
51: {
52: ITERS_FIRST = 0,
53: ITERS_ERR = 100,
54: ITERS_LATER = 400,
55: ITERS_PRINT = 10,
56: ITERS_MAX = 1000,
57: };
58:
59: static void
60: heavy_wq_add (struct vty *vty, const char *str, int i)
61: {
62: struct heavy_wq_node *hn;
63:
64: if ((hn = XCALLOC (MTYPE_PREFIX_LIST, sizeof(struct heavy_wq_node))) == NULL)
65: {
66: zlog_err ("%s: unable to allocate hn", __func__);
67: return;
68: }
69:
70: hn->i = i;
71: if (!(hn->str = XSTRDUP (MTYPE_PREFIX_LIST_STR, str)))
72: {
73: zlog_err ("%s: unable to xstrdup", __func__);
74: XFREE (MTYPE_PREFIX_LIST, hn);
75: return;
76: }
77:
78: work_queue_add (heavy_wq, hn);
79:
80: return;
81: }
82:
83: static void
84: slow_func_err (struct work_queue *wq, struct work_queue_item *item)
85: {
86: printf ("%s: running error function\n", __func__);
87: }
88:
89: static void
90: slow_func_del (struct work_queue *wq, void *data)
91: {
92: struct heavy_wq_node *hn = data;
93: assert (hn && hn->str);
94: printf ("%s: %s\n", __func__, hn->str);
95: XFREE (MTYPE_PREFIX_LIST_STR, hn->str);
96: hn->str = NULL;
97: XFREE(MTYPE_PREFIX_LIST, hn);
98: }
99:
100: static wq_item_status
101: slow_func (struct work_queue *wq, void *data)
102: {
103: struct heavy_wq_node *hn = data;
104: double x = 1;
105: int j;
106:
107: assert (hn && hn->str);
108:
109: for (j = 0; j < 300; j++)
110: x += sin(x)*j;
111:
112: if ((hn->i % ITERS_LATER) == 0)
113: return WQ_RETRY_LATER;
114:
115: if ((hn->i % ITERS_ERR) == 0)
116: return WQ_RETRY_NOW;
117:
118: if ((hn->i % ITERS_PRINT) == 0)
119: printf ("%s did %d, x = %g\n", hn->str, hn->i, x);
120:
121: return WQ_SUCCESS;
122: }
123:
124: static void
125: clear_something (struct vty *vty, const char *str)
126: {
127: int i;
128:
129: /* this could be like iterating through 150k of route_table
130: * or worse, iterating through a list of peers, to bgp_stop them with
131: * each having 150k route tables to process...
132: */
133: for (i = ITERS_FIRST; i < ITERS_MAX; i++)
134: heavy_wq_add (vty, str, i);
135: }
136:
137: DEFUN (clear_foo,
138: clear_foo_cmd,
139: "clear foo .LINE",
140: "clear command\n"
141: "arbitrary string\n")
142: {
143: char *str;
144: if (!argc)
145: {
146: vty_out (vty, "%% string argument required%s", VTY_NEWLINE);
147: return CMD_WARNING;
148: }
149:
150: str = argv_concat (argv, argc, 0);
151:
152: clear_something (vty, str);
153: XFREE (MTYPE_TMP, str);
154: return CMD_SUCCESS;
155: }
156:
157: static int
158: heavy_wq_init ()
159: {
160: if (! (heavy_wq = work_queue_new (master, "heavy_work_queue")))
161: {
162: zlog_err ("%s: could not get new work queue!", __func__);
163: return -1;
164: }
165:
166: heavy_wq->spec.workfunc = &slow_func;
167: heavy_wq->spec.errorfunc = &slow_func_err;
168: heavy_wq->spec.del_item_data = &slow_func_del;
169: heavy_wq->spec.max_retries = 3;
170: heavy_wq->spec.hold = 1000;
171:
172: return 0;
173: }
174:
175: void
176: test_init()
177: {
178: install_element (VIEW_NODE, &clear_foo_cmd);
179: heavy_wq_init();
180: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>