File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / tests / heavy-wq.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

    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: 
   39: extern struct thread_master *master;
   40: static struct work_queue *heavy_wq;
   41: 
   42: struct heavy_wq_node
   43: {
   44:   char *str;
   45:   int i;
   46: };
   47: 
   48: enum
   49: {
   50:   ITERS_FIRST = 0,
   51:   ITERS_ERR = 100,
   52:   ITERS_LATER = 400,
   53:   ITERS_PRINT = 10,
   54:   ITERS_MAX = 1000,
   55: };
   56: 
   57: static void
   58: heavy_wq_add (struct vty *vty, const char *str, int i)
   59: {
   60:   struct heavy_wq_node *hn;
   61: 
   62:   if ((hn = XCALLOC (MTYPE_PREFIX_LIST, sizeof(struct heavy_wq_node))) == NULL)
   63:     {
   64:       zlog_err ("%s: unable to allocate hn", __func__);
   65:       return;
   66:     }
   67:   
   68:   hn->i = i;
   69:   if (!(hn->str = XSTRDUP (MTYPE_PREFIX_LIST_STR, str)))
   70:     {
   71:       zlog_err ("%s: unable to xstrdup", __func__);
   72:       XFREE (MTYPE_PREFIX_LIST, hn);
   73:       return;
   74:     }
   75:   
   76:   work_queue_add (heavy_wq, hn);
   77:   
   78:   return;
   79: }
   80: 
   81: static void
   82: slow_func_err (struct work_queue *wq, struct work_queue_item *item)
   83: {
   84:   printf ("%s: running error function\n", __func__);
   85: }
   86: 
   87: static void
   88: slow_func_del (struct work_queue *wq, void *data)
   89: {
   90:   struct heavy_wq_node *hn = data;
   91:   assert (hn && hn->str);
   92:   printf ("%s: %s\n", __func__, hn->str);
   93:   XFREE (MTYPE_PREFIX_LIST_STR, hn->str);
   94:   hn->str = NULL;  
   95:   XFREE(MTYPE_PREFIX_LIST, hn);
   96: }
   97: 
   98: static wq_item_status
   99: slow_func (struct work_queue *wq, void *data)
  100: {
  101:   struct heavy_wq_node *hn = data;
  102:   double x = 1;
  103:   int j;
  104:   
  105:   assert (hn && hn->str);
  106:   
  107:   for (j = 0; j < 300; j++)
  108:     x += sin(x)*j;
  109:   
  110:   if ((hn->i % ITERS_LATER) == 0)
  111:     return WQ_RETRY_LATER;
  112:   
  113:   if ((hn->i % ITERS_ERR) == 0)
  114:     return WQ_RETRY_NOW;
  115:   
  116:   if ((hn->i % ITERS_PRINT) == 0)
  117:     printf ("%s did %d, x = %g\n", hn->str, hn->i, x);
  118: 
  119:   return WQ_SUCCESS;
  120: }
  121: 
  122: static void
  123: clear_something (struct vty *vty, const char *str)
  124: {
  125:   int i;
  126:   
  127:   /* this could be like iterating through 150k of route_table 
  128:    * or worse, iterating through a list of peers, to bgp_stop them with
  129:    * each having 150k route tables to process...
  130:    */
  131:   for (i = ITERS_FIRST; i < ITERS_MAX; i++)
  132:     heavy_wq_add (vty, str, i);
  133: }
  134: 
  135: DEFUN (clear_foo,
  136:        clear_foo_cmd,
  137:        "clear foo .LINE",
  138:        "clear command\n"
  139:        "arbitrary string\n")
  140: {
  141:   char *str;
  142:   if (!argc)
  143:     {
  144:       vty_out (vty, "%% string argument required%s", VTY_NEWLINE);
  145:       return CMD_WARNING;
  146:     }
  147:   
  148:   str = argv_concat (argv, argc, 0);
  149:   
  150:   clear_something (vty, str);
  151:   XFREE (MTYPE_TMP, str);
  152:   return CMD_SUCCESS;
  153: }
  154: 
  155: static int
  156: heavy_wq_init ()
  157: {
  158:   if (! (heavy_wq = work_queue_new (master, "heavy_work_queue")))
  159:     {
  160:       zlog_err ("%s: could not get new work queue!", __func__);
  161:       return -1;
  162:     }
  163:   
  164:   heavy_wq->spec.workfunc = &slow_func;
  165:   heavy_wq->spec.errorfunc = &slow_func_err;
  166:   heavy_wq->spec.del_item_data = &slow_func_del;
  167:   heavy_wq->spec.max_retries = 3;
  168:   heavy_wq->spec.hold = 1000;
  169:   
  170:   return 0;
  171: }
  172: 
  173: void
  174: test_init()
  175: {
  176:   install_element (VIEW_NODE, &clear_foo_cmd);
  177:   heavy_wq_init();
  178: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>