home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / lb / rsdclnt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  5.5 KB  |  203 lines

  1. /*
  2.  * Copyright (c) 1989,1990,1991 University of Rochester
  3.  * Department of Electrical Engineering
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that the above copyright notice and this paragraph are
  8.  * duplicated in all such forms and that any documentation,
  9.  * advertising materials, and other materials related to such
  10.  * distribution and use acknowledge that the software was developed
  11.  * at the University of Rochester.
  12.  *
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * rsdclnt.c  for the 'lb' load balancer 
  20.  *   -Deke Kassabian, University of Rochester EE Department
  21.  *   ( deke@ee.rochester.edu )  (716) 275-3106
  22.  *
  23.  * $Revision: 1.2 $
  24.  * $Author: deke $
  25.  * $Date: 91/03/03 17:52:36 $
  26.  * $Log:    rsdclnt.c,v $
  27.  * Revision 1.2  91/03/03  17:52:36  deke
  28.  * changed stats to lstats to avoid name clash: required by change in rstat.h
  29.  *
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <rpc/rpc.h>
  34. #include <rpcsvc/rstat.h>
  35. #include "config.h"
  36.  
  37. main(argc, argv, envp)
  38. int argc;
  39. char *argv[];
  40. char *envp[];
  41. {
  42.  
  43. struct statstime lstats;
  44. FILE *fd,*fopen();
  45. char *fgets();
  46. int getstats();
  47.  
  48. int start,             /* where in the argv the command begins */
  49.     ppgrp,            /* parent process group            */
  50.     command,            /* whether there is a command         */
  51.     verbose_mode,         /* all possible output            */
  52.     quiet_mode;            /* no output                */
  53.  
  54. char *path=RSH;
  55.  
  56. char *dir,*pname;
  57. char *cmd_exec[MAXSHBUF],    /* command to execute (local)        */
  58.      *rcmd_exec[MAXSHBUF],    /* command to execute (remote)        */
  59.      dbuf[MAXSHBUF],        /* working directory placeholder    */
  60.      host[MAXHOST],        /* hostname placeholder            */
  61.      best_host[MAXHOST],    /* hostname placeholder            */
  62.      fentry[MAXLINE];        /* file buffer */
  63.  
  64. float my_sfactor,
  65.       best_sfactor,
  66.       factor, limit,        /* file variables            */
  67.       load;
  68.  
  69.     pname = *argv;            /* Name of this program  */
  70.     verbose_mode=0,quiet_mode=0;    /* Default is neither    */
  71.     best_sfactor=MAXFLOAT;         /* Practically infinity! */
  72.      command=1;            /* There is a command     */
  73.  
  74.  /* Check arguments. 
  75.   *
  76.   * if argc=1 then verbose=Y and command=NULL
  77.   * if argc>=2 check for flags:
  78.   *    -v=verbose (full output),  -q=quiet (don't output machine selection)
  79.   *    with no flags, only machine selection will be output
  80.   *    The above flags are mutually exclusive.  v overrides q
  81.   *
  82.   *    Additional arguments are taken to be a command.  No sanity checking
  83.   *    will be done.  When a machine is selected, the command will be sent
  84.   *    to that machine as a shell command.
  85.   *
  86.   */
  87.  
  88.  if (argc == 1) {
  89.     command=0;            /* no command to execute */
  90.     verbose_mode=1;            /* verbose mode         */
  91.  }
  92.  else {
  93.      start=1;
  94.      if(!strcmp(argv[1],"-q")){
  95.       quiet_mode=1;            /* quiet mode - no output */
  96.       start=2;
  97.       if(argc == 2) exit(0);        /* No command, no output! */
  98.      } 
  99.      if(!strcmp(argv[1],"-v")){
  100.       verbose_mode=1;            /* verbose mode         */
  101.       start=2;
  102.       if(argc == 2) command=0;        /* No command - verbose   */
  103.      } 
  104.  }
  105.  if(command){
  106.     for( ; start<argc ; start++){
  107.         strcat(cmd_exec," "); strcat(cmd_exec,argv[start]);
  108.     }
  109.  }
  110.  
  111.  
  112.  if((fd=fopen(CONFIGFILE,"r"))==0){
  113.      fprintf(stderr,"Error opening configuration file\n");
  114.      exit(1);
  115.  }
  116.  
  117.     while((fgets(fentry,MAXLINE,fd))!=NULL){
  118.        sscanf(fentry,"%s %f %f",host,&factor,&limit);
  119.        if(fentry[0]=='#') continue;     /*ignore comments*/
  120.         
  121.        if(verbose_mode)
  122.           printf("\nHOST=%s\tFACTOR=%.2f\tLIMIT=%.2f\n",host,factor,limit);
  123.        
  124.        if(getstats(host,&lstats) !=0){
  125.         load=MAXFLOAT;            /* skip this one */
  126.        } 
  127.        else {
  128.         load=loadavg(&lstats,0);    
  129.        }
  130.  
  131.        if( load > limit){
  132.           if(verbose_mode) printf("Host %s is over defined limit\n",host);
  133.           continue;
  134.           }
  135.  
  136.        my_sfactor=100*(load/factor);
  137.  
  138.        if(verbose_mode)
  139.         printf("Load avg=%.3f\tSelection factor=%.3f\n",
  140.             load,my_sfactor);
  141.  
  142.        if(best_sfactor>my_sfactor){
  143.         best_sfactor=my_sfactor;
  144.         strcpy(best_host,host);
  145.        }
  146.     } /*endwhile */
  147.  
  148.     if(verbose_mode)
  149.        printf("Selected host: <%s> factor=<%.3f>\n",best_host,best_sfactor);
  150.  
  151.     if(command){
  152.         sprintf(rcmd_exec,"(cd %s;%s)",getwd(dbuf),cmd_exec);
  153.         if(!quiet_mode){ /* print if not quiet_mode */
  154.            printf("\nrsh %s %s &\n",best_host,rcmd_exec); 
  155.         }
  156.         ppgrp = getpgrp(getppid());
  157.         if (fork())
  158.         exit(0);
  159.         if(setpgrp(getpid(), ppgrp)) 
  160.         perror("stepgrp");
  161.         execle(path,path,best_host,rcmd_exec,(char *)0,envp); exit(0);
  162.         perror("");
  163.     }
  164. exit(0);
  165. }
  166.  
  167. getstats(hostname,lstats)
  168. char *hostname;
  169. struct statstime *lstats;
  170. {
  171. int c;
  172.     c=rstat(hostname,lstats);    /* rstat seems to return:        */
  173.                 /*    0  on success            */
  174.                 /*    13 on hostname lookup fail  */
  175.                 /*    14 on connection timeout    */
  176.                 /*    15 on "rstat not supported" */
  177.     /*  I chose to generate my own error messages.  perror() didn't */
  178.     /*    give error messages I liked.  Switch back to perror if you  */
  179.     /*    care to.                            */
  180.  
  181.     switch(c){
  182.     case 0:
  183.         break;
  184.     case 13:
  185.         fprintf(stderr,"rstat error (%d): ",c);
  186.         fprintf(stderr,"host %s is unknown.\n",hostname);
  187.         break;
  188.     case 14:
  189.         fprintf(stderr,"rstat error (%d): ",c);
  190.         fprintf(stderr,"host %s is down or unreachable.\n",hostname);
  191.         break;
  192.     case 15:
  193.         fprintf(stderr,"rstat error (%d): ",c);
  194.         fprintf(stderr,"host %s does not support protocol.\n",hostname);
  195.         break;
  196.     default:
  197.         fprintf(stderr,"rstat error (%d): ",c);
  198.             fprintf(stderr,"unknown error\n");
  199.         break;
  200.     }
  201.     return(c);
  202. }
  203.