home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / ircd4652.zip / ircd-df-4.6.5-os2 / src / userload.c < prev    next >
C/C++ Source or Header  |  1997-12-28  |  12KB  |  367 lines

  1. /****************************************************************************
  2.  *  Userload module by Michael L. VanLoon (mlv) <michaelv@iastate.edu>
  3.  *  Written 2/93.  Originally grafted into irc2.7.2g 4/93.
  4.  *
  5.  *   IRC - Internet Relay Chat, ircd/userload.c
  6.  *   Copyright (C) 1990 University of Oulu, Computing Center
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify
  9.  *   it under the terms of the GNU General Public License as published by
  10.  *   the Free Software Foundation; either version 1, or (at your option)
  11.  *   any later version.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful,
  14.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *   GNU General Public License for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with this program; if not, write to the Free Software
  20.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  ****************************************************************************/
  22.  
  23. #include "struct.h"
  24. #include "common.h"
  25. #include "sys.h"
  26. #include "userload.h"
  27. #include <stdio.h>
  28. #ifndef _WIN32
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <sys/errno.h>
  32. #else
  33. #include <io.h>
  34. #endif
  35. #include <string.h>
  36. #include <signal.h>
  37. #ifndef _WIN32
  38. #include <sys/resource.h>
  39. #endif
  40. #include "h.h"
  41.  
  42.  
  43. struct current_load_struct current_load_data;
  44. struct load_entry *load_list_head = NULL, *load_list_tail = NULL,
  45.                   *load_free_head = NULL, *load_free_tail = NULL;
  46.  
  47. #ifdef DEBUGMODE
  48. clock_t    clock_last = 0;
  49. #endif
  50.  
  51. void update_load()
  52. {
  53.   static struct timeval now, last;
  54.   register struct load_entry *cur_load_entry;
  55.  
  56.   /* This seems to get polluted on startup by an exit_client()
  57.    * before any connections have been recorded.
  58.    */
  59.   if (current_load_data.local_count > MAXCONNECTIONS ||
  60.       current_load_data.client_count > MAXCONNECTIONS ||
  61.       current_load_data.conn_count > MAXCONNECTIONS)
  62.     bzero(¤t_load_data, sizeof(struct current_load_struct));
  63.   
  64.   memcpy(&last, &now, sizeof(struct timeval));
  65. #ifndef _WIN32
  66.   if (gettimeofday(&now, NULL) != 0)
  67.     return;  /* error getting time of day--can't calculate time diff */
  68. #else
  69.   /* Well, since the windows libs don't have gettimeofday() we have
  70.    * to improvise a bit, hopefully this will achieve close to the
  71.    * same result.  -Cabal95
  72.    */
  73.   now.tv_sec = time(NULL);
  74. #endif
  75.  
  76.   if (load_free_tail == NULL) {
  77.     if ((cur_load_entry =
  78.      (struct load_entry *) MyMalloc(sizeof(struct load_entry))) == NULL)
  79.       return;
  80.     /* printf("malloc pointer: %x\n", cur_load_entry); */
  81.   } else {
  82.     cur_load_entry = load_free_tail;
  83.     load_free_tail = cur_load_entry->prev;
  84.     if (load_free_tail == NULL)
  85.       load_free_head = NULL;
  86.     /* printf("free pointer: %x\n", cur_load_entry); */
  87.   }
  88.   if (load_list_tail != NULL) {
  89. #ifndef _WIN32
  90.     cur_load_entry->time_incr = ((now.tv_sec * 1000 + now.tv_usec / 1000 + 5)
  91.        - (last.tv_sec * 1000 + last.tv_usec / 1000)) / 10;
  92. #else
  93.     /* Don't even use *.tv_usec since its an unknown value.  -Cabal95 */
  94.     cur_load_entry->time_incr = ((now.tv_sec * 1000 + 5)
  95.        - last.tv_sec * 1000) / 10;
  96. #endif
  97.     cur_load_entry->local_count = current_load_data.local_count;
  98.     cur_load_entry->client_count = current_load_data.client_count;
  99.     cur_load_entry->conn_count = current_load_data.conn_count;
  100. #ifdef DEBUGMODE
  101.     cur_load_entry->cpu_usage = (clock()-clock_last);
  102.     clock_last = clock();
  103. #endif
  104.   } else {
  105.     load_list_head = cur_load_entry;
  106.     bzero(cur_load_entry, sizeof(struct load_entry));
  107.     cur_load_entry->time_incr = 1;
  108.   }
  109.   cur_load_entry->prev = load_list_tail;
  110.   load_list_tail = cur_load_entry;
  111. }
  112.  
  113.  
  114. void calc_load(sptr, parv)
  115. aClient *sptr;
  116. char    *parv;  /* we only get passed the original parv[0] */
  117. {
  118.   register struct load_entry *cur_load_entry;
  119.   struct load_entry *last;
  120. #ifdef DEBUGMODE
  121.   u_long secs = 0, adj_secs, total[4], adj[4];/*[local,client,conn,cpu]*/
  122.   int i;
  123.   u_int times[5][4]; /* [min,hour,day,Yest,YYest][local,client,conn,cpu] */
  124.   char what[4][HOSTLEN + 1];
  125.  
  126.   bzero(total, 4 * sizeof(u_long));
  127. #else
  128.   u_long secs = 0, adj_secs, total[3], adj[3];/*[local,client,conn]*/
  129.   int i, times[5][3]; /* [min,hour,day,Yest,YYest][local,client,conn] */
  130.   char what[3][HOSTLEN + 1];
  131.  
  132.   bzero(total, 3 * sizeof(u_long));
  133. #endif
  134.  
  135.   current_load_data.entries = 0;
  136.  
  137.   update_load();  /* we want stats accurate as of *now* */
  138.  
  139.   for (cur_load_entry = load_list_tail; (secs < 6000) &&
  140.        (cur_load_entry != NULL); cur_load_entry = cur_load_entry->prev) {
  141.     u_long time_incr = cur_load_entry->time_incr;
  142.     total[0] += time_incr * cur_load_entry->local_count;
  143.     total[1] += time_incr * cur_load_entry->client_count;
  144.     total[2] += time_incr * cur_load_entry->conn_count;
  145. #ifdef DEBUGMODE
  146.     total[3] += cur_load_entry->cpu_usage;
  147. #endif
  148.     last = cur_load_entry;
  149.     secs += cur_load_entry->time_incr;
  150.     current_load_data.entries++;
  151.   }
  152.   if ((secs > 6000) && (last != NULL)) {
  153.     adj_secs = secs - 6000;
  154.     adj[0] = adj_secs * last->local_count;
  155.     adj[1] = adj_secs * last->client_count;
  156.     adj[2] = adj_secs * last->conn_count;
  157. #ifdef DEBUGMODE
  158.     times[0][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
  159.   } else {
  160.     adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
  161.     times[0][3] = total[3];
  162.   }
  163. #else
  164.   } else
  165.     adj_secs = adj[0] = adj[1] = adj[2] = 0;
  166. #endif
  167.   for (i = 0; i < 3; i++) {
  168.     times[0][i] = ((total[i] - adj[i]) * 1000 / (secs - adj_secs) + 5) / 10;
  169.   }
  170.  
  171.   secs = (secs + 5) / 10;
  172.   for (i = 0; i < 3; i++)
  173.     total[i] = (total[i] + 5) / 10;
  174.  
  175.   for ( ; (secs < 36000) && (cur_load_entry != NULL); secs +=
  176.        (cur_load_entry->time_incr + 5) / 10, cur_load_entry =
  177.        cur_load_entry->prev, current_load_data.entries++) {
  178.     u_long time_incr = (cur_load_entry->time_incr + 5) / 10;
  179.     total[0] += time_incr * cur_load_entry->local_count;
  180.     total[1] += time_incr * cur_load_entry->client_count;
  181.     total[2] += time_incr * cur_load_entry->conn_count;
  182. #ifdef DEBUGMODE
  183.     total[3] += cur_load_entry->cpu_usage;
  184. #endif
  185.     last = cur_load_entry;
  186.   }
  187.   if ((secs > 36000) && (last != NULL)) {
  188.     adj_secs = secs - 36000;
  189.     adj[0] = adj_secs * last->local_count;
  190.     adj[1] = adj_secs * last->client_count;
  191.     adj[2] = adj_secs * last->conn_count;
  192. #ifdef DEBUGMODE
  193.     times[1][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
  194.   } else {
  195.     adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
  196.     times[1][3] = total[3];
  197.   }
  198. #else
  199.   } else
  200.     adj_secs = adj[0] = adj[1] = adj[2] = 0;
  201. #endif
  202.   for (i = 0; i < 3; i++) {
  203.     times[1][i] = ((total[i] - adj[i]) * 100 / (secs - adj_secs) + 5) / 10;
  204.   }
  205.  
  206.   secs = (secs + 5) / 10;
  207.   for (i = 0; i < 3; i++)
  208.     total[i] = (total[i] + 5) / 10;
  209.  
  210.   for ( ; (secs < 86400) && (cur_load_entry != NULL); secs +=
  211.        (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
  212.        cur_load_entry->prev, current_load_data.entries++) {
  213.     u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
  214.     total[0] += time_incr * cur_load_entry->local_count;
  215.     total[1] += time_incr * cur_load_entry->client_count;
  216.     total[2] += time_incr * cur_load_entry->conn_count;
  217. #ifdef DEBUGMODE
  218.     total[3] += cur_load_entry->cpu_usage;
  219. #endif
  220.     last = cur_load_entry;
  221.   }
  222.   if ((secs > 86400) && (last != NULL)) {
  223.     adj_secs = secs - 86400;
  224.     adj[0] = adj_secs * last->local_count;
  225.     adj[1] = adj_secs * last->client_count;
  226.     adj[2] = adj_secs * last->conn_count;
  227. #ifdef DEBUGMODE
  228.     times[2][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
  229.   } else {
  230.     adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
  231.     times[2][3] = total[3];
  232.   }
  233. #else
  234.   } else
  235.     adj_secs = adj[0] = adj[1] = adj[2] = 0;
  236. #endif
  237.   for (i = 0; i < 3; i++) {
  238.     times[2][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
  239.   }
  240.  
  241. #ifdef DEBUGMODE
  242.   bzero(total, 4 * sizeof(u_long));
  243. #else
  244.   bzero(total, 3 * sizeof(u_long));
  245. #endif
  246.  
  247.   for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
  248.        (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
  249.        cur_load_entry->prev, current_load_data.entries++) {
  250.     u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
  251.     total[0] += time_incr * cur_load_entry->local_count;
  252.     total[1] += time_incr * cur_load_entry->client_count;
  253.     total[2] += time_incr * cur_load_entry->conn_count;
  254. #ifdef DEBUGMODE
  255.     total[3] += cur_load_entry->cpu_usage;
  256. #endif
  257.     last = cur_load_entry;
  258.   }
  259.   if ((secs > 86400) && (last != NULL)) {
  260.     adj_secs = secs - 86400;
  261.     adj[0] = adj_secs * last->local_count;
  262.     adj[1] = adj_secs * last->client_count;
  263.     adj[2] = adj_secs * last->conn_count;
  264. #ifdef DEBUGMODE
  265.     times[3][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
  266.   } else {
  267.     adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
  268.     times[3][3] = total[3];
  269.   }
  270. #else
  271.   } else
  272.     adj_secs = adj[0] = adj[1] = adj[2] = 0;
  273. #endif
  274.   for (i = 0; i < 3; i++) {
  275.     times[3][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
  276.   }
  277.  
  278. #ifdef DEBUGMODE
  279.   bzero(total, 4 * sizeof(u_long));
  280. #else
  281.   bzero(total, 3 * sizeof(u_long));
  282. #endif
  283.  
  284.   for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
  285.        (cur_load_entry->time_incr + 50) / 100, cur_load_entry =
  286.        cur_load_entry->prev, current_load_data.entries++) {
  287.     u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
  288.     total[0] += time_incr * cur_load_entry->local_count;
  289.     total[1] += time_incr * cur_load_entry->client_count;
  290.     total[2] += time_incr * cur_load_entry->conn_count;
  291. #ifdef DEBUGMODE
  292.     total[3] += cur_load_entry->cpu_usage;
  293. #endif
  294.     last = cur_load_entry;
  295.   }
  296.   if ((secs > 86400) && (last != NULL)) {
  297.     adj_secs = secs - 86400;
  298.     adj[0] = adj_secs * last->local_count;
  299.     adj[1] = adj_secs * last->client_count;
  300.     adj[2] = adj_secs * last->conn_count;
  301. #ifdef DEBUGMODE
  302.     times[4][3] = total[3]-(last->cpu_usage*(double)adj_secs/last->time_incr);
  303.   } else {
  304.     adj_secs = adj[0] = adj[1] = adj[2] = adj[3] = 0;
  305.     times[4][3] = total[3];
  306.   }
  307. #else
  308.   } else
  309.     adj_secs = adj[0] = adj[1] = adj[2] = 0;
  310. #endif
  311.   for (i = 0; i < 3; i++) {
  312.     times[4][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
  313.   }
  314.  
  315.   if ((cur_load_entry != NULL) && (cur_load_entry->prev != NULL) &&
  316.       (secs > 86400)) {  /* have nodes to free -- more than 3 days old */
  317.     struct load_entry *cur_free_entry = load_free_head;
  318.  
  319.     load_free_head = load_list_head;
  320.     load_list_head = cur_load_entry;
  321.     if (cur_free_entry != NULL)
  322.       cur_free_entry->prev = cur_load_entry->prev;
  323.     else
  324.       load_free_tail = cur_load_entry->prev;
  325.  
  326.     /* printf("freeing: %x  (head: %x,  tail: %x)\n", cur_load_entry->prev,
  327.        load_free_head, load_free_tail); */
  328.  
  329.     cur_load_entry->prev = NULL;
  330.   }
  331.  
  332.   strcpy(what[0], DOMAINNAME);
  333.   strcat(what[0], " clients");
  334.   strcpy(what[1], "total clients");
  335.   strcpy(what[2], "total connections");
  336. #ifdef DEBUGMODE
  337.   strcpy(what[3], "CPU usage");
  338. #endif
  339.   sendto_one(sptr,
  340.     ":%s NOTICE %s :Minute   Hour  Day  Yest.  YYest.  Userload for:",
  341.     me.name, parv);
  342.   for (i = 0; i < 3; i++)
  343.     sendto_one(sptr,
  344.       ":%s NOTICE %s :%3d.%02d  %3d.%01d  %3d   %3d     %3d   %s",
  345.       me.name, parv, times[0][i] / 100, times[0][i] % 100, times[1][i] / 10,
  346.       times[1][i] % 10, times[2][i], times[3][i], times[4][i], what[i]);
  347.  
  348. #ifdef DEBUGMODE
  349.     sendto_one(sptr,
  350.       ":%s NOTICE %s :%6.2f%% %5.1f%% %3d%%  %3d%%    %3d%%  %s",
  351.       me.name, parv,
  352.       (double)((double)times[0][3]/(0.6*CLOCKS_PER_SEC)),
  353.       (double)((double)times[1][3]/(36*CLOCKS_PER_SEC)),
  354.       (int)((double)times[2][3]/(864*CLOCKS_PER_SEC)),
  355.       (int)((double)times[3][3]/(864*CLOCKS_PER_SEC)),
  356.       (int)((double)times[4][3]/(864*CLOCKS_PER_SEC)),
  357.       what[3]);
  358. #endif
  359. }
  360.  
  361.  
  362. void initload()
  363. {
  364.   bzero(¤t_load_data, sizeof(struct current_load_struct));
  365.   update_load();  /* Initialize the load list */
  366. }
  367.