File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / tests / heavy-wq.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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: #include "tests.h"
   40: 
   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>