X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/c27b3454cc178bce7be2c8dd41232a7a6057a63d..dc1d1c52813ce1141673c90a54d7bfa62eade695:/server/mr_main.c diff --git a/server/mr_main.c b/server/mr_main.c index e95fff0a..704a57a7 100644 --- a/server/mr_main.c +++ b/server/mr_main.c @@ -4,51 +4,29 @@ * $Header$ * * Copyright (C) 1987 by the Massachusetts Institute of Technology + * For copying and distribution information, please see the file + * . * - * - * SMS server process. + * MOIRA server process. * * Most of this is stolen from ../gdb/tsr.c * * You are in a maze of twisty little finite automata, all different. * Let the reader beware. * - * $Log$ - * Revision 1.9 1987-06-21 16:39:54 wesommer - * Performance work, rearrangement of include files. - * - * Revision 1.8 87/06/09 18:44:45 wesommer - * modified error handling. - * - * Revision 1.7 87/06/08 02:44:44 wesommer - * Minor lint fix. - * - * Revision 1.6 87/06/03 17:41:00 wesommer - * Added startup support. - * - * Revision 1.5 87/06/03 16:07:17 wesommer - * Fixes for lint. - * - * Revision 1.4 87/06/02 20:05:11 wesommer - * Bug fixes on memory allocation. - * - * Revision 1.3 87/06/01 04:34:27 wesommer - * Changed returned error code. - * - * Revision 1.2 87/06/01 03:34:53 wesommer - * Added shutdown, logging. - * - * Revision 1.1 87/05/31 22:06:56 wesommer - * Initial revision - * */ -static char *rcsid_sms_main_c = "$Header$"; +static char *rcsid_mr_main_c = "$Header$"; +#include #include +#include #include #include -#include "sms_server.h" +#include +#include +#include "mr_server.h" +#include extern CONNECTION newconn, listencon; @@ -66,20 +44,26 @@ extern char *whoami; extern char buf1[BUFSIZ]; extern char *takedown; extern int errno; +extern FILE *journal; - -extern char *malloc(); extern char *inet_ntoa(); -extern void sms_com_err(); +extern void mr_com_err(); extern void do_client(); extern int sigshut(); void clist_append(); void oplist_append(); -extern u_short ntohs(); +void reapchild(), godormant(), gowakeup(); + +extern time_t now; + +#ifdef _DEBUG_MALLOC_INC +static char *dbg_malloc(); +static int dbg_free(); +#endif /* - * Main SMS server loop. + * Main MOIRA server loop. * * Initialize the world, then start accepting connections and * making progress on current connections. @@ -91,20 +75,48 @@ main(argc, argv) int argc; char **argv; { - int status; + int status, i; + time_t tardy; + char *port; + extern char *database; + struct stat stbuf; whoami = argv[0]; /* * Error handler init. */ - init_sms_err_tbl(); - init_krb_err_tbl(); - set_com_err_hook(sms_com_err); - - if (argc != 1) { - com_err(whoami, 0, "Usage: smsd"); + initialize_sms_error_table(); + initialize_krb_error_table(); + initialize_gdss_error_table(); + set_com_err_hook(mr_com_err); + setlinebuf(stderr); + + database = "moira"; + port = index(MOIRA_SERVER, ':') + 1; + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-db") && i+1 < argc) { + database = argv[i+1]; + i++; + } else if (!strcmp(argv[i], "-p") && i+1 < argc) { + port = argv[i+1]; + i++; + } else { + com_err(whoami, 0, "Usage: moirad [-db database][-p port]"); exit(1); - } + } + } + + /* Profiling implies that getting rid of one level of call + * indirection here wins us maybe 1% on the VAX. + */ +#ifdef _DEBUG_MALLOC_INC + gdb_amv = dbg_malloc; + gdb_fmv = dbg_free; +#else + gdb_amv = malloc; + gdb_fmv = (int (*)()) free; +#endif /* * GDB initialization. @@ -115,47 +127,57 @@ main(argc, argv) } gdb_debug(0); /* this can be patched, if necessary, to enable */ /* GDB level debugging .. */ + krb_realm = malloc(REALM_SZ); + krb_get_lrealm(krb_realm, 1); /* - * Database initialization. + * Database initialization. Only init if database should be open. */ - if ((status = sms_open_database()) != 0) { - com_err(whoami, status, "when trying to open database."); + if (stat(MOIRA_MOTD_FILE, &stbuf) != 0) { + if ((status = mr_open_database()) != 0) { + com_err(whoami, status, " when trying to open database."); exit(1); + } + sanity_check_database(); + } else { + dormant = ASLEEP; + com_err(whoami, 0, "sleeping, not opening database"); } + sanity_check_queries(); + /* * Set up client array handler. */ nclients = 0; clients = (client **) malloc(0); - /* - * Signal handlers - * There should probably be a few more of these. - */ + mr_setup_signals(); - if ((((int)signal (SIGTERM, sigshut)) < 0) || - (((int)signal (SIGHUP, sigshut)) < 0)) { - com_err(whoami, errno, "Unable to establish signal handler."); - exit(1); + journal = fopen(JOURNAL, "a"); + if (journal == NULL) { + com_err(whoami, errno, " while opening journal file"); + exit(1); } - + /* * Establish template connection. */ - if ((status = do_listen()) != 0) { + if ((status = do_listen(port)) != 0) { com_err(whoami, status, - "while trying to create listening connection"); + " while trying to create listening connection"); exit(1); } op_list = create_list_of_operations(1, listenop); - (void) sprintf(buf1, "started (pid %d)", getpid()); - com_err(whoami, 0, buf1); - com_err(whoami, 0, rcsid_sms_main_c); + com_err(whoami, 0, "started (pid %d)", getpid()); + com_err(whoami, 0, rcsid_mr_main_c); + if (dormant != ASLEEP) + send_zgram("MOIRA", "server started"); + else + send_zgram("MOIRA", "server started, but database closed"); /* * Run until shut down. @@ -168,52 +190,105 @@ main(argc, argv) #ifdef notdef com_err(whoami, 0, "tick"); #endif notdef + if (dormant == SLEEPY) { + mr_close_database(); + com_err(whoami, 0, "database closed"); + mr_setup_signals(); + send_zgram("MOIRA", "database closed"); + dormant = ASLEEP; + } else if (dormant == GROGGY) { + mr_open_database(); + com_err(whoami, 0, "database open"); + mr_setup_signals(); + send_zgram("MOIRA", "database open again"); + dormant = AWAKE; + } + errno = 0; status = op_select_any(op_list, 0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL); if (status == -1) { - com_err(whoami, errno, "error from op_select"); + if (errno != EINTR) + com_err(whoami, errno, " error from op_select"); + if (!inc_running || now - inc_started > INC_TIMEOUT) + next_incremental(); continue; } else if (status != -2) { - com_err(whoami, 0, "wrong return from op_select_any"); + com_err(whoami, 0, " wrong return from op_select_any"); continue; } if (takedown) break; + time(&now); + if (!inc_running || now - inc_started > INC_TIMEOUT) + next_incremental(); #ifdef notdef fprintf(stderr, " tick\n"); #endif notdef /* - * Handle any existing connections. - */ - for (i=0; ipending_op)) { - cur_client = clients[i]; - do_client(cur_client); - cur_client = NULL; - if (takedown) break; - } - } - /* - * Handle any new connections. + * Handle any new connections; this comes first so + * errno isn't tromped on. */ if (OP_DONE(listenop)) { if (OP_STATUS(listenop) == OP_CANCELLED) { - com_err(whoami, errno, "Error on listen"); - exit(1); - + if (errno == EWOULDBLOCK) { + do_reset_listen(); + } else { + static int count = 0; + com_err(whoami, errno, + " error (%d) on listen", count); + if (count++ > 10) + exit(1); + } } else if ((status = new_connection()) != 0) { com_err(whoami, errno, - "Error on listening operation."); + " Error on listening operation."); /* * Sleep here to prevent hosing? */ } + /* if the new connection is our only connection, + * and the server is supposed to be down, then go + * down now. + */ + if ((dormant == AWAKE) && (nclients == 1) && + (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) { + com_err(whoami, 0, "motd file exists, slumbertime"); + dormant = SLEEPY; + } + /* on new connection, if we are no longer supposed + * to be down, then wake up. + */ + if ((dormant == ASLEEP) && + (stat(MOIRA_MOTD_FILE, &stbuf) == -1) && + (errno == ENOENT)) { + com_err(whoami, 0, "motd file no longer exists, waking up"); + dormant = GROGGY; + } + + } + /* + * Handle any existing connections. + */ + tardy = now - 30*60; + + for (i=0; ipending_op)) { + cur_client->last_time_used = now; + do_client(cur_client); + } else if (clients[i]->last_time_used < tardy) { + com_err(whoami, 0, "Shutting down connection due to inactivity"); + shutdown(cur_client->con->in.fd, 0); + } + cur_client = NULL; + if (takedown) break; } } - com_err(whoami, 0, takedown); - sms_close_database(); + com_err(whoami, 0, "%s", takedown); + mr_close_database(); + send_zgram("MOIRA", takedown); return 0; } @@ -222,11 +297,10 @@ main(argc, argv) */ int -do_listen() +do_listen(port) +char *port; { - char *service = index(SMS_GDB_SERV, ':') + 1; - - listencon = create_listening_connection(service); + listencon = create_listening_connection(port); if (listencon == NULL) return errno; @@ -240,6 +314,15 @@ do_listen() return 0; } + +do_reset_listen() +{ + client_addrlen = sizeof(client_addr); + start_accepting_client(listencon, listenop, &newconn, + (char *)&client_addr, + &client_addrlen, &client_tuple); +} + /* * This routine is called when a new connection comes in. * @@ -259,21 +342,23 @@ new_connection() } if (newconn == NULL) { - return SMS_NOT_CONNECTED; + return MR_NOT_CONNECTED; } /* * Set up the new connection and reply to the client */ cp = (client *)malloc(sizeof *cp); - cp->state = CL_STARTING; + bzero(cp, sizeof(*cp)); cp->action = CL_ACCEPT; cp->con = newconn; cp->id = counter++; cp->args = NULL; - cp->clname = NULL; - cp->reply.sms_argv = NULL; - + cp->clname[0] = NULL; + cp->reply.mr_argv = NULL; + cp->first = NULL; + cp->last = NULL; + cp->last_time_used = now; newconn = NULL; cp->pending_op = create_operation(); @@ -298,13 +383,11 @@ new_connection() * Log new connection. */ - (void) sprintf(buf1, - "New connection from %s port %d (now %d client%s)", - inet_ntoa(cp->haddr.sin_addr), - (int)ntohs(cp->haddr.sin_port), - nclients, - nclients!=1?"s":""); - com_err(whoami, 0, buf1); + com_err(whoami, 0, "New connection from %s port %d (now %d client%s)", + inet_ntoa(cp->haddr.sin_addr), + (int)ntohs(cp->haddr.sin_port), + nclients, + nclients!=1?"s":""); /* * Get ready to accept the next connection. @@ -413,3 +496,83 @@ oplist_delete(oplp, op) } abort(); } + + +void reapchild() +{ + union wait status; + int pid; + + while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) { + if (pid == inc_pid) + inc_running = 0; + if (!takedown && (status.w_termsig != 0 || status.w_retcode != 0)) + com_err(whoami, 0, "%d: child exits with signal %d status %d", + pid, status.w_termsig, status.w_retcode); + } +} + + +void godormant() +{ + switch (dormant) { + case AWAKE: + case GROGGY: + com_err(whoami, 0, "requested to go dormant"); + break; + case ASLEEP: + com_err(whoami, 0, "already asleep"); + break; + case SLEEPY: + break; + } + dormant = SLEEPY; +} + + +void gowakeup() +{ + switch (dormant) { + case ASLEEP: + case SLEEPY: + com_err(whoami, 0, "Good morning"); + break; + case AWAKE: + com_err(whoami, 0, "already awake"); + break; + case GROGGY: + break; + } + dormant = GROGGY; +} + + +mr_setup_signals() +{ + /* There should probably be a few more of these. */ + + if ((((int)signal (SIGTERM, sigshut)) < 0) || + (((int)signal (SIGCHLD, reapchild)) < 0) || + (((int)signal (SIGUSR1, godormant)) < 0) || + (((int)signal (SIGUSR2, gowakeup)) < 0) || + (((int)signal (SIGHUP, sigshut)) < 0)) { + com_err(whoami, errno, " Unable to establish signal handlers."); + exit(1); + } +} + +#ifdef _DEBUG_MALLOC_INC +static char *dbg_malloc(size) + SIZETYPE size; +{ + return( debug_malloc("somewhere in the gdb code",1,size) ); +} + +static int dbg_free(cptr) + DATATYPE *cptr; +{ + debug_free((char *)NULL, 0, cptr); + return 0; /* GDB is being stupid */ +} +#endif +