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 >
Wrap
C/C++ Source or Header
|
1989-09-14
|
10KB
|
476 lines
/*
** Copyright 1986, 1987, 1988, 1989 University of Wisconsin
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the name of the University of
** Wisconsin not be used in advertising or publicity pertaining to
** distribution of the software without specific, written prior
** permission. The University of Wisconsin makes no representations about
** the suitability of this software for any purpose. It is provided "as
** is" without express or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN DISCLAIMS ALL WARRANTIES WITH REGARD TO
** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
** FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN BE LIABLE FOR
** ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**
** Authors: Allan Bricker and Michael J. Litzkow,
** University of Wisconsin, Computer Sciences Dept.
**
*/
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include "condor_types.h"
#include "debug.h"
#include "trace.h"
#include "except.h"
#include "sched.h"
#include "expr.h"
#include "manager.h"
#include "clib.h"
static char *_FileName_ = __FILE__; /* Used by EXCEPT (see except.h) */
CONTEXT *create_context();
MACH_REC *create_mach_rec();
char *param();
extern MACH_REC *MachineList;
extern int errno;
char *Log;
char *CollectorLog;
int MaxCollectorLog;
int ClientTimeout;
int MachineUpdateInterval;
int Foreground;
int Termlog;
int ClientSock = -1;
int ConnectionSock;
int UdpSock;
extern int Terse;
extern struct sockaddr_in From;
extern int Len;
char *MyName;
usage( name )
char *name;
{
dprintf( D_ALWAYS, "Usage: %s [-f] [-t]\n", name );
exit( 1 );
}
main( argc, argv)
int argc;
char *argv[];
{
int count;
fd_set readfds;
char **ptr;
int alarm_handler(), sigpipe_handler();
int sigint_handler(), sighup_handler();
/* Read the configuration file */
MyName = *argv;
config( MyName, (CONTEXT *)0 );
init_params();
Terse = 1;
if( argc > 3 ) {
usage( argv[0] );
}
for( ptr=argv+1; *ptr; ptr++ ) {
if( ptr[0][0] != '-' ) {
usage( argv[0] );
}
switch( ptr[0][1] ) {
case 'f':
Foreground++;
break;
case 't':
Termlog++;
break;
default:
usage( argv[0] );
}
}
/* This is so if we dump core it'll go in the log directory */
if( chdir(Log) < 0 ) {
EXCEPT( "chdir to log directory <%s>", Log );
}
/* Arrange to run in background */
if( !Foreground ) {
if( fork() )
exit( 0 );
}
/* Set up logging */
dprintf_config( "COLLECTOR", 2 );
dprintf( D_ALWAYS, "*************************************************\n" );
dprintf( D_ALWAYS, "*** CONDOR_COLLECTOR STARTING UP ***\n" );
dprintf( D_ALWAYS, "*************************************************\n" );
dprintf( D_ALWAYS, "\n" );
if( signal(SIGINT,sigint_handler) < 0 ) {
EXCEPT( "signal(SIGINT,0x%x)", sigint_handler );
}
if( signal(SIGHUP,sighup_handler) < 0 ) {
EXCEPT( "signal(SIGHUP,0x%x)", sighup_handler );
}
ConnectionSock = init_tcp_sock( "condor_collector", COLLECTOR_PORT );
UdpSock = init_udp_sock( "condor_collector", COLLECTOR_UDP_PORT );
if( signal(SIGPIPE,sigpipe_handler) < 0 ) {
EXCEPT( "signal(SIGPIPE,0x%x)", sigpipe_handler );
}
if( signal(SIGALRM,alarm_handler) < 0 ) {
EXCEPT( "signal(SIGALRM,0x%x)", alarm_handler );
}
MachineList = create_mach_rec( (struct sockaddr_in *)0 );
FD_ZERO( &readfds );
for(;;) {
FD_SET( ConnectionSock, &readfds );
FD_SET( UdpSock, &readfds );
/*
** dprintf( D_ALWAYS, "Selecting\n" );
*/
if( (count = select(FD_SETSIZE, (int *)&readfds, (int *)0, (int *)0,
(struct timeval *)0 )) <= 0 ) {
EXCEPT( "select() returns %d", count );
}
/*
** dprintf( D_ALWAYS, "Select returned %d\n", count );
*/
if( FD_ISSET(UdpSock,&readfds) ) {
accept_datagram();
}
if( FD_ISSET(ConnectionSock,&readfds) ) {
accept_tcp_connection();
}
}
}
accept_datagram()
{
XDR xdr, *xdrs, *xdr_Udp_Init();
int cmd;
xdrs = xdr_Udp_Init( &UdpSock, &xdr );
/* Read the request */
xdrs->x_op = XDR_DECODE;
if( !xdr_int(xdrs,&cmd) ) {
dprintf( D_ALWAYS, "Can't receive command from client\n" );
return;
}
switch( cmd ) {
case STARTD_INFO:
machine_info( xdrs, &From, STARTD_INFO );
break;
case SCHEDD_INFO:
machine_info( xdrs, &From, SCHEDD_INFO );
break;
case NEGOTIATOR_INFO:
dprintf( D_ALWAYS, "Getting Negotiator info\n" );
negotiator_info( xdrs );
break;
default:
dprintf( D_ALWAYS, "Got UNKNOWN command (%d) -- IGNORED\n", cmd );
break;
}
xdr_destroy( xdrs );
}
accept_tcp_connection()
{
struct sockaddr_in from;
int len;
XDR xdr, *xdrs, *xdr_Init();
len = sizeof from;
bzero( (char *)&from, sizeof from );
ClientSock = accept( ConnectionSock, (struct sockaddr *)&from, &len );
if( ClientSock < 0 && errno != EINTR ) {
EXCEPT( "accept" );
}
xdrs = xdr_Init( &ClientSock, &xdr );
(void)alarm( (unsigned)ClientTimeout ); /* don't hang here forever */
do_command( xdrs, &from );
(void)alarm( 0 ); /* cancel alarm */
xdr_destroy( xdrs );
(void)close( ClientSock );
ClientSock = -1;
}
init_udp_sock( service, port )
char *service;
int port;
{
struct sockaddr_in sin;
struct servent *servp;
int sock;
bzero( (char *)&sin, sizeof sin );
servp = getservbyname(service, "tcp");
if( servp ) {
sin.sin_port = htons( (u_short)servp->s_port );
} else {
sin.sin_port = htons( (u_short)port );
}
if( (sock=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
EXCEPT( "socket" );
}
if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
if( errno == EADDRINUSE ) {
EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
} else {
EXCEPT( "bind" );
}
}
return sock;
}
#ifdef vax
struct linger linger = { 0, 0 }; /* Don't linger */
#endif vax
init_tcp_sock( service, port )
char *service;
int port;
{
struct sockaddr_in sin;
struct servent *servp;
int on = 1;
int sock;
bzero( (char *)&sin, sizeof sin );
servp = getservbyname(service, "tcp");
if( servp ) {
sin.sin_port = htons( (u_short)servp->s_port );
} else {
sin.sin_port = htons( (u_short)port );
}
if( (sock=socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
EXCEPT( "socket" );
}
if( setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(caddr_t *)&on,sizeof(on))
< 0) {
EXCEPT( "setsockopt" );
}
#ifdef vax
if( setsockopt(sock,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger))
< 0 ) {
EXCEPT( "setsockopt" );
}
#endif vax
if( bind(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0 ) {
if( errno == EADDRINUSE ) {
EXCEPT( "CONDOR_COLLECTOR ALREADY RUNNING" );
} else {
EXCEPT( "bind" );
}
}
if( listen(sock,5) < 0 ) {
EXCEPT( "listen" );
}
return sock;
}
/*
** Somebody has connected to our socket with a request. Read the request
** and handle it.
*/
do_command( xdrs, from )
XDR *xdrs;
struct sockaddr_in *from;
{
int cmd;
/* Read the request */
xdrs->x_op = XDR_DECODE;
if( !xdr_int(xdrs,&cmd) ) {
dprintf( D_ALWAYS, "Can't receive command from client\n" );
return;
}
switch( cmd ) {
case STARTD_INFO: /* Receive new status from a startd */
machine_info( xdrs, from, STARTD_INFO );
break;
case SCHEDD_INFO: /* Receive new status from a schedd */
machine_info( xdrs, from, SCHEDD_INFO );
break;
case NEGOTIATOR_INFO: /* Receive new status info from negotiator */
negotiator_info( xdrs );
break;
case GIVE_STATUS_LINES: /* Give info for the condor_status command */
dprintf( D_ALWAYS, "Got GIVE_STATUS_LINES request\n" );
give_status_lines( xdrs );
break;
case GIVE_STATUS: /* Give info to the negotiator */
dprintf( D_ALWAYS, "Got GIVE_STATUS request\n" );
give_status( xdrs );
break;
case RESCHEDULE: /* Please do your scheduling early (now) */
dprintf( D_ALWAYS, "Got RESCHEDULE request -- ignoring\n" );
break;
case PING: /* Accept and break a connection */
dprintf( D_ALWAYS, "Got PING request\n" );
break;
default:
dprintf( D_ALWAYS, "Got UNKNOWN command (%d) -- IGNORED\n", cmd );
break;
}
}
SetSyscalls(){}
init_params()
{
char *tmp;
if( param("COLLECTOR_DEBUG") == NULL ) {
EXCEPT( "COLLECTOR_DEBUG not specified in config file\n" );
}
Foreground = boolean( "COLLECTOR_DEBUG", "Foreground" );
Log = param( "LOG" );
if( Log == NULL ) {
EXCEPT( "No log directory specified in config file\n" );
}
CollectorLog = param( "COLLECTOR_LOG" );
if( CollectorLog == NULL ) {
EXCEPT( "No log file specified in config file\n" );
}
tmp = param( "MAX_COLLECTOR_LOG" );
if( tmp == NULL ) {
MaxCollectorLog = 0;
} else {
MaxCollectorLog = 64000;
}
tmp = param( "CLIENT_TIMEOUT" );
if( tmp == NULL ) {
ClientTimeout = 30;
} else {
ClientTimeout = atoi( tmp );
}
tmp = param( "MACHINE_UPDATE_INTERVAL" );
if( tmp == NULL ) {
MachineUpdateInterval = 300;
} else {
MachineUpdateInterval = atoi( tmp );
}
}
/*
** The other end of our connection to the client has gone away. Close our
** end. Then the read()/write() will fail, and whichever client routine
** is involved will clean up.
*/
sigpipe_handler()
{
if( ClientSock < 0 ) {
EXCEPT( "Got SIGPIPE, but no ClientSock" );
}
(void)close( ClientSock );
ClientSock = -1;
}
alarm_handler()
{
if( ClientSock < 0 ) {
EXCEPT( "Got SIGALRM, but no ClientSock" );
}
dprintf( D_ALWAYS,
"Client not responding after %d seconds -- breaking connection\n",
ClientTimeout
);
(void)close( ClientSock );
ClientSock = -1;
}
sigint_handler()
{
dprintf( D_ALWAYS, "Killed by SIGINT\n" );
exit( 0 );
}
sighup_handler()
{
dprintf( D_ALWAYS, "Re reading config file\n" );
config( MyName, (CONTEXT *)0 );
init_params();
}