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>