home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / condor40.zip / CONDOR / src / condor_collect / collector.c next >
C/C++ Source or Header  |  1989-09-14  |  10KB  |  476 lines

  1. /* 
  2. ** Copyright 1986, 1987, 1988, 1989 University of Wisconsin
  3. ** 
  4. ** Permission to use, copy, modify, and distribute this software and its
  5. ** documentation for any purpose and without fee is hereby granted,
  6. ** provided that the above copyright notice appear in all copies and that
  7. ** both that copyright notice and this permission notice appear in
  8. ** supporting documentation, and that the name of the University of
  9. ** Wisconsin not be used in advertising or publicity pertaining to
  10. ** distribution of the software without specific, written prior
  11. ** permission.  The University of Wisconsin makes no representations about
  12. ** the suitability of this software for any purpose.  It is provided "as
  13. ** is" without express or implied warranty.
  14. ** 
  15. ** THE UNIVERSITY OF WISCONSIN DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. ** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. ** FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN  BE LIABLE FOR
  18. ** ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  21. ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. ** 
  23. ** Authors:  Allan Bricker and Michael J. Litzkow,
  24. **              University of Wisconsin, Computer Sciences Dept.
  25. ** 
  26. */ 
  27.  
  28.  
  29. #include <stdio.h>
  30. #include <netdb.h>
  31. #include <errno.h>
  32. #include <pwd.h>
  33. #include <signal.h>
  34. #include <ctype.h>
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <sys/param.h>
  38. #include <sys/file.h>
  39. #include <sys/time.h>
  40. #include <sys/resource.h>
  41. #include <sys/wait.h>
  42. #include <netinet/in.h>
  43. #include <rpc/types.h>
  44. #include <rpc/xdr.h>
  45.  
  46. #include "condor_types.h"
  47. #include "debug.h"
  48. #include "trace.h"
  49. #include "except.h"
  50. #include "sched.h"
  51. #include "expr.h"
  52. #include "manager.h"
  53. #include "clib.h"
  54.  
  55. static char *_FileName_ = __FILE__;        /* Used by EXCEPT (see except.h)     */
  56.  
  57.  
  58. CONTEXT        *create_context();
  59. MACH_REC    *create_mach_rec();
  60. char        *param();
  61.  
  62. extern MACH_REC    *MachineList;
  63. extern int    errno;
  64.  
  65. char    *Log;
  66. char    *CollectorLog;
  67. int        MaxCollectorLog;
  68. int        ClientTimeout;
  69. int        MachineUpdateInterval;
  70. int        Foreground;
  71. int        Termlog;
  72.  
  73. int        ClientSock = -1;
  74.  
  75. int        ConnectionSock;
  76. int        UdpSock;
  77.  
  78. extern int    Terse;
  79. extern struct sockaddr_in    From;
  80. extern int        Len;
  81.  
  82. char *MyName;
  83.  
  84.  
  85. usage( name )
  86. char    *name;
  87. {
  88.     dprintf( D_ALWAYS, "Usage: %s [-f] [-t]\n", name );
  89.     exit( 1 );
  90. }
  91.  
  92.  
  93. main( argc, argv)
  94. int        argc;
  95. char    *argv[];
  96. {
  97.     int        count;
  98.     fd_set    readfds;
  99.     char    **ptr;
  100.     int        alarm_handler(), sigpipe_handler();
  101.     int        sigint_handler(), sighup_handler();
  102.  
  103.         /* Read the configuration file */
  104.     MyName = *argv;
  105.  
  106.     config( MyName, (CONTEXT *)0 );
  107.  
  108.     init_params();
  109.     Terse = 1;
  110.  
  111.     if( argc > 3 ) {
  112.         usage( argv[0] );
  113.     }
  114.     for( ptr=argv+1; *ptr; ptr++ ) {
  115.         if( ptr[0][0] != '-' ) {
  116.             usage( argv[0] );
  117.         }
  118.         switch( ptr[0][1] ) {
  119.             case 'f':
  120.                 Foreground++;
  121.                 break;
  122.             case 't':
  123.                 Termlog++;
  124.                 break;
  125.             default:
  126.                 usage( argv[0] );
  127.         }
  128.     }
  129.  
  130.         /* This is so if we dump core it'll go in the log directory */
  131.     if( chdir(Log) < 0 ) {
  132.         EXCEPT( "chdir to log directory <%s>", Log );
  133.     }
  134.  
  135.         /* Arrange to run in background */
  136.     if( !Foreground ) {
  137.         if( fork() )
  138.             exit( 0 );
  139.     }
  140.  
  141.         /* Set up logging */
  142.     dprintf_config( "COLLECTOR", 2 );
  143.  
  144.     dprintf( D_ALWAYS, "*************************************************\n" );
  145.     dprintf( D_ALWAYS, "***       CONDOR_COLLECTOR STARTING UP        ***\n" );
  146.     dprintf( D_ALWAYS, "*************************************************\n" );
  147.     dprintf( D_ALWAYS, "\n" );
  148.  
  149.     if( signal(SIGINT,sigint_handler) < 0 ) {
  150.         EXCEPT( "signal(SIGINT,0x%x)", sigint_handler );
  151.     }
  152.     if( signal(SIGHUP,sighup_handler) < 0 ) {
  153.         EXCEPT( "signal(SIGHUP,0x%x)", sighup_handler );
  154.     }
  155.  
  156.     ConnectionSock = init_tcp_sock( "condor_collector", COLLECTOR_PORT );
  157.     UdpSock = init_udp_sock( "condor_collector", COLLECTOR_UDP_PORT );
  158.  
  159.     if( signal(SIGPIPE,sigpipe_handler) < 0 ) {
  160.         EXCEPT( "signal(SIGPIPE,0x%x)", sigpipe_handler );
  161.     }
  162.  
  163.     if( signal(SIGALRM,alarm_handler) < 0 ) {
  164.         EXCEPT( "signal(SIGALRM,0x%x)", alarm_handler );
  165.     }
  166.  
  167.  
  168.     MachineList = create_mach_rec( (struct sockaddr_in    *)0 );
  169.     FD_ZERO( &readfds );
  170.  
  171.     for(;;) {
  172.  
  173.         FD_SET( ConnectionSock, &readfds );
  174.         FD_SET( UdpSock, &readfds );
  175.  
  176.         /*
  177.         ** dprintf( D_ALWAYS, "Selecting\n" );
  178.         */
  179.  
  180.         if( (count = select(FD_SETSIZE, (int *)&readfds, (int *)0, (int *)0,
  181.                                                 (struct timeval *)0 )) <= 0 ) {
  182.             EXCEPT( "select() returns %d", count );
  183.         }
  184.             
  185.  
  186.         /*
  187.         ** dprintf( D_ALWAYS, "Select returned %d\n", count );
  188.         */
  189.  
  190.         if( FD_ISSET(UdpSock,&readfds) ) {
  191.             accept_datagram();
  192.         }
  193.         if( FD_ISSET(ConnectionSock,&readfds) ) {
  194.                 accept_tcp_connection();
  195.         }
  196.     }
  197. }
  198.  
  199. accept_datagram()
  200. {
  201.     XDR        xdr, *xdrs, *xdr_Udp_Init();
  202.     int        cmd;
  203.  
  204.  
  205.     xdrs = xdr_Udp_Init( &UdpSock, &xdr );
  206.  
  207.         /* Read the request */
  208.     xdrs->x_op = XDR_DECODE;
  209.     if( !xdr_int(xdrs,&cmd) ) {
  210.         dprintf( D_ALWAYS, "Can't receive command from client\n" );
  211.         return;
  212.     }
  213.  
  214.     switch( cmd ) {
  215.         case STARTD_INFO:
  216.             machine_info( xdrs, &From, STARTD_INFO );
  217.             break;
  218.         case SCHEDD_INFO:
  219.             machine_info( xdrs, &From, SCHEDD_INFO );
  220.             break;
  221.         case NEGOTIATOR_INFO:
  222.             dprintf( D_ALWAYS, "Getting Negotiator info\n" );
  223.             negotiator_info( xdrs );
  224.             break;
  225.         default:
  226.             dprintf( D_ALWAYS, "Got UNKNOWN command (%d) -- IGNORED\n", cmd );
  227.             break;
  228.     }
  229.  
  230.     xdr_destroy( xdrs );
  231. }
  232.  
  233. accept_tcp_connection()
  234. {
  235.     struct sockaddr_in    from;
  236.     int        len;
  237.     XDR        xdr, *xdrs, *xdr_Init();
  238.  
  239.     len = sizeof from;
  240.     bzero( (char *)&from, sizeof from );
  241.     ClientSock = accept( ConnectionSock, (struct sockaddr *)&from, &len );
  242.  
  243.     if( ClientSock < 0 && errno != EINTR ) {
  244.         EXCEPT( "accept" );
  245.     }
  246.  
  247.     xdrs = xdr_Init( &ClientSock, &xdr );
  248.  
  249.     (void)alarm( (unsigned)ClientTimeout );    /* don't hang here forever */
  250.     do_command( xdrs, &from );
  251.     (void)alarm( 0 );                /* cancel alarm */
  252.  
  253.     xdr_destroy( xdrs );
  254.     (void)close( ClientSock );
  255.     ClientSock = -1;
  256. }
  257.  
  258. init_udp_sock( service, port )
  259. char    *service;
  260. int        port;
  261. {
  262.     struct sockaddr_in    sin;
  263.     struct servent *servp;
  264.     int        sock;
  265.  
  266.     bzero( (char *)&sin, sizeof sin );
  267.     servp = getservbyname(service, "tcp");
  268.     if( servp ) {
  269.         sin.sin_port = htons( (u_short)servp->s_port );
  270.     } else {
  271.         sin.sin_port = htons( (u_short)port );
  272.     }
  273.  
  274.     if( (sock=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
  275.         EXCEPT( "socket" );
  276.     }
  277.  
  278.     if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
  279.         if( errno == EADDRINUSE ) {
  280.             EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
  281.         } else {
  282.             EXCEPT( "bind" );
  283.         }
  284.     }
  285.  
  286.     return sock;
  287. }
  288.  
  289. #ifdef vax
  290. struct linger linger = { 0, 0 };    /* Don't linger */
  291. #endif vax
  292.  
  293. init_tcp_sock( service, port )
  294. char    *service;
  295. int        port;
  296. {
  297.     struct sockaddr_in    sin;
  298.     struct servent *servp;
  299.     int        on = 1;
  300.     int        sock;
  301.  
  302.     bzero( (char *)&sin, sizeof sin );
  303.     servp = getservbyname(service, "tcp");
  304.     if( servp ) {
  305.         sin.sin_port = htons( (u_short)servp->s_port );
  306.     } else {
  307.         sin.sin_port = htons( (u_short)port );
  308.     }
  309.  
  310.     if( (sock=socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
  311.         EXCEPT( "socket" );
  312.     }
  313.  
  314.     if( setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(caddr_t *)&on,sizeof(on))
  315.                                                                         < 0) {
  316.         EXCEPT( "setsockopt" );
  317.     }
  318.  
  319. #ifdef vax
  320.     if( setsockopt(sock,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger))
  321.                                                                         < 0 ) {
  322.         EXCEPT( "setsockopt" );
  323.     }
  324. #endif vax
  325.  
  326.     if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
  327.         if( errno == EADDRINUSE ) {
  328.             EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
  329.         } else {
  330.             EXCEPT( "bind" );
  331.         }
  332.     }
  333.  
  334.     if( listen(sock,5) < 0 ) {
  335.         EXCEPT( "listen" );
  336.     }
  337.  
  338.     return sock;
  339. }
  340.  
  341.  
  342. /*
  343. ** Somebody has connected to our socket with a request.  Read the request
  344. ** and handle it.
  345. */
  346. do_command( xdrs, from )
  347. XDR        *xdrs;
  348. struct sockaddr_in    *from;
  349. {
  350.     int        cmd;
  351.  
  352.         /* Read the request */
  353.     xdrs->x_op = XDR_DECODE;
  354.     if( !xdr_int(xdrs,&cmd) ) {
  355.         dprintf( D_ALWAYS, "Can't receive command from client\n" );
  356.         return;
  357.     }
  358.  
  359.     switch( cmd ) {
  360.         case STARTD_INFO:    /* Receive new status from a startd */
  361.             machine_info( xdrs, from, STARTD_INFO );
  362.             break;
  363.         case SCHEDD_INFO:    /* Receive new status from a schedd */
  364.             machine_info( xdrs, from, SCHEDD_INFO );
  365.             break;
  366.         case NEGOTIATOR_INFO:    /* Receive new status info from negotiator */
  367.             negotiator_info( xdrs );
  368.             break;
  369.         case GIVE_STATUS_LINES:    /* Give info for the condor_status command */
  370.             dprintf( D_ALWAYS, "Got GIVE_STATUS_LINES request\n" );
  371.             give_status_lines( xdrs );
  372.             break;
  373.         case GIVE_STATUS:    /* Give info to the negotiator */
  374.             dprintf( D_ALWAYS, "Got GIVE_STATUS request\n" );
  375.             give_status( xdrs );
  376.             break;
  377.         case RESCHEDULE:    /* Please do your scheduling early (now) */
  378.             dprintf( D_ALWAYS, "Got RESCHEDULE request -- ignoring\n" );
  379.             break;
  380.         case PING:            /* Accept and break a connection */
  381.             dprintf( D_ALWAYS, "Got PING request\n" );
  382.             break;
  383.         default:
  384.             dprintf( D_ALWAYS, "Got UNKNOWN command (%d) -- IGNORED\n", cmd );
  385.             break;
  386.     }
  387. }
  388.  
  389. SetSyscalls(){}
  390.  
  391. init_params()
  392. {
  393.     char    *tmp;
  394.  
  395.     if( param("COLLECTOR_DEBUG") == NULL ) {
  396.         EXCEPT( "COLLECTOR_DEBUG not specified in config file\n" );
  397.     }
  398.     Foreground = boolean( "COLLECTOR_DEBUG", "Foreground" );
  399.  
  400.     Log = param( "LOG" );
  401.     if( Log == NULL )  {
  402.         EXCEPT( "No log directory specified in config file\n" );
  403.     }
  404.  
  405.     CollectorLog = param( "COLLECTOR_LOG" );
  406.     if( CollectorLog == NULL ) {
  407.         EXCEPT( "No log file specified in config file\n" );
  408.     }
  409.  
  410.     tmp = param( "MAX_COLLECTOR_LOG" );
  411.     if( tmp == NULL ) {
  412.         MaxCollectorLog = 0;
  413.     } else {
  414.         MaxCollectorLog = 64000;
  415.     }
  416.  
  417.     tmp = param( "CLIENT_TIMEOUT" );
  418.     if( tmp == NULL ) {
  419.         ClientTimeout = 30;
  420.     } else {
  421.         ClientTimeout = atoi( tmp );
  422.     }
  423.  
  424.     tmp = param( "MACHINE_UPDATE_INTERVAL" );
  425.     if( tmp == NULL ) {
  426.         MachineUpdateInterval = 300;
  427.     } else {
  428.         MachineUpdateInterval = atoi( tmp );
  429.     }
  430.  
  431. }
  432.  
  433. /*
  434. ** The other end of our connection to the client has gone away.  Close our
  435. ** end.  Then the read()/write() will fail, and whichever client routine
  436. ** is involved will clean up.
  437. */
  438. sigpipe_handler()
  439. {
  440.     if( ClientSock < 0 ) {
  441.         EXCEPT( "Got SIGPIPE, but no ClientSock" );
  442.     }
  443.  
  444.     (void)close( ClientSock );
  445.     ClientSock = -1;
  446. }
  447.  
  448. alarm_handler()
  449. {
  450.     if( ClientSock < 0 ) {
  451.         EXCEPT( "Got SIGALRM, but no ClientSock" );
  452.     }
  453.  
  454.     dprintf( D_ALWAYS,
  455.         "Client not responding after %d seconds -- breaking connection\n",
  456.         ClientTimeout
  457.     );
  458.  
  459.     (void)close( ClientSock );
  460.     ClientSock = -1;
  461. }
  462.  
  463. sigint_handler()
  464. {
  465.     dprintf( D_ALWAYS, "Killed by SIGINT\n" );
  466.     exit( 0 );
  467. }
  468.  
  469. sighup_handler()
  470. {
  471.     dprintf( D_ALWAYS, "Re reading config file\n" );
  472.  
  473.     config( MyName, (CONTEXT *)0 );
  474.     init_params();
  475. }
  476.