#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#include "utility.h"#include "server.h"#include "comm_basics.h"#include "comm_encode.h"#include "comm_data.h"#include "comm_protocol.h"#include "mfork.h"
Go to the source code of this file.
Defines | |
| #define | GS_SERVER_USAGE_STR "Usage: GS_server [-l logfile] [-c] [-s server config]" |
Functions | |
| int | gs_server_verify_connectivity (gs_server_t *server, int serversocket) |
| int | gs_server_parse_cmd_line (int argc, char **argv, char *gridsolve_root, char **logfile, int *daemon, char **srv_cfg) |
| static void | server_signal_handler (int sig) |
| int | main (int argc, char **argv) |
This file contains a main() driver for the server, parsing the command line arguments and starting up the deamons. This main routine was seperated from the rest of the server code, so that the rest of the server code can be compiled as a library and used by other parts of GridSolve (e.g. the comm routines can manipulate the server data structures using the server library).
Definition in file server_main.c.
| #define GS_SERVER_USAGE_STR "Usage: GS_server [-l logfile] [-c] [-s server config]" |
| int gs_server_parse_cmd_line | ( | int | argc, | |
| char ** | argv, | |||
| char * | gridsolve_root, | |||
| char ** | logfile, | |||
| int * | daemon, | |||
| char ** | srv_cfg | |||
| ) |
Parse the command line for flags passed to the server. Currently the syntax is: GS_server -c [-l logfile] [-s config]
| argc | -- arg count | |
| argv | -- array of arguments | |
| gridsolve_root | -- root of the GridSolve installation | |
| logfile | -- if a -l arg is seen this is set to the name of the log file upon return, otherwise it is set to NULL. The user need not allocate any memory. | |
| daemon | -- set TRUE upon return if this should be run as a daemon process, FALSE otherwise. |
Definition at line 134 of file server_main.c.
{
int c;
*logfile = NULL;
*daemon = 1;
*srv_cfg = NULL;
/* when making changes to the command line args, update
* GS_SERVER_USAGE_STR so the usage information is printed
* correctly upon error.
*/
#define GS_SERVER_USAGE_STR "Usage: GS_server [-l logfile] [-c] [-s server config]"
while((c = getopt(argc,argv,"cl:s:")) != EOF) {
switch(c) {
case 'l':
*logfile = strdup(optarg);
break;
case 's':
*srv_cfg = strdup(optarg);
break;
case 'c':
*daemon = 0;
break;
case '?':
return -1;
break;
default:
ERRPRINTF("Bad arg: '%c'.\n",c);
return -1;
}
}
/* Setup default log file name if necessary */
if(!*logfile) {
*logfile = dstring_sprintf("%s/gs_server.log", gridsolve_root);
if(!*logfile) {
fprintf(stderr,"Error generating log file name.\n");
exit(EXIT_FAILURE);
}
}
/* Setup default server config file name if necessary */
if(!*srv_cfg) {
*srv_cfg = dstring_sprintf("%s/server_config", gridsolve_root);
if(!*srv_cfg) {
fprintf(stderr,"Error generating server config file name.\n");
exit(EXIT_FAILURE);
}
}
return 0;
}


| int gs_server_verify_connectivity | ( | gs_server_t * | server, | |
| int | serversocket | |||
| ) |
Checks whether this server can be contacted by the agent as a simple test of network connectivity. this is mainly used for rejecting servers that should be proxied, but aren't.
| server | -- the server struct for this server |
Definition at line 40 of file server_main.c.
{
int sock_agent, tag;
char *reqstr = NULL;
sock_agent = gs_connect_direct(server->agenthost, server->agentport);
if(sock_agent < 0) {
ERRPRINTF("Unable to connect to agent.\n");
return -1;
}
if((gs_send_tag(sock_agent, GS_PROT_AVAILABILITY_REQ) < 0) ||
(gs_send_string(sock_agent, VERSION) < 0)) {
ERRPRINTF("failed to send tag\n");
gs_close_socket(sock_agent);
return -1;
}
if(gs_recv_tag(sock_agent, &tag) < 0) {
ERRPRINTF("Error communicating with agent.\n");
gs_close_socket(sock_agent);
return -1;
}
if(tag != GS_PROT_OK) {
if(tag == GS_PROT_VERSION_MISMATCH)
ERRPRINTF("Error: Agent is an incompatible version\n");
else
ERRPRINTF("Error: Agent refused with code %d\n", tag);
gs_close_socket(sock_agent);
return -1;
}
if(gs_encode_availability_request(&reqstr, server) < 0) {
ERRPRINTF("Could not encode availability request.\n");
return -1;
}
if(gs_send_string(sock_agent, reqstr) < 0) {
ERRPRINTF("failed to send string\n");
if(reqstr) free(reqstr);
gs_close_socket(sock_agent);
return -1;
}
gs_close_socket(sock_agent);
free(reqstr);
printf("Performing connectivity test. If it hangs at this point\n");
printf("and you are behind a NAT, check your GRIDSOLVE_PROXY\n");
printf("environment variable. If you are behind a firewall,\n");
printf("check your port settings.\n");
if((sock_agent = gs_accept_connection(serversocket)) == -1) {
ERRPRINTF("Failed to accept connection on socket\n");
return -1;
}
printf("\n\nConnectivity test successful.\n");
if(gs_recv_tag(sock_agent, &tag) < 0) {
ERRPRINTF("Failed to read tag.\n");
return -1;
}
gs_close_socket(sock_agent);
if(tag != GS_PROT_OK) {
ERRPRINTF("Agent rejected this server (tag = %d).\n", tag);
return -1;
}
return 0;
}


| int main | ( | int | argc, | |
| char ** | argv | |||
| ) |
Main routine for the server. Checks to see if the appropriate environment variables are set, handle the log file, initialize server structures, make this server process into a daemon, bind server to port, fork the workload reporter, and then call routine to handle incoming messages.
| argc | -- arg count | |
| argv | -- array of arguments |
Definition at line 219 of file server_main.c.
{
gs_server_t *gs_server = NULL;
int serversocket = -1, daemon;
void **wr_args;
pid_t pid;
char *logfile, *gridsolve_root, *srv_cfg;
if(gs_signal(SIGTERM, server_signal_handler) == SIG_ERR)
ERRPRINTF("Warning: could not set up SIGTERM signal handler\n");
if(gs_signal(SIGINT, server_signal_handler) == SIG_ERR)
ERRPRINTF("Warning: could not set up SIGINT signal handler\n");
/* Check environment */
if((gridsolve_root = getenv("GRIDSOLVE_ROOT")) == NULL)
gridsolve_root = GRIDSOLVE_TOP_BUILD_DIR;
if(!gridsolve_root) {
ERRPRINTF("Warning: GRIDSOLVE_ROOT unknown, assuming cwd.\n");
gridsolve_root = strdup(".");
}
/* Parse command line args */
if(gs_server_parse_cmd_line(argc, argv, gridsolve_root, &logfile,
&daemon, &srv_cfg) < 0) {
fprintf(stderr, "%s\n", GS_SERVER_USAGE_STR);
exit(EXIT_FAILURE);
}
/* Make current process into a daemon */
if(daemon && gs_daemon_init(gridsolve_root, logfile) < 0) {
fprintf(stderr, "Failed to start server as a daemon.\n");
exit(EXIT_FAILURE);
}
/* Call the server initialization code */
if ((gs_server = gs_server_init(srv_cfg)) == NULL) {
fprintf(stderr, "Failed to initialize the server.\n");
exit(EXIT_FAILURE);
}
#ifdef GS_DEBUG
gs_server_dump(gs_server);
#endif
/* Bind server to a port. gs_server->port should be set in gs_server_init */
serversocket = gs_establish_socket(&(gs_server->port), 0);
if(serversocket == -1) {
ERRPRINTF("Could not bind to port %d\n", gs_server->port);
exit(EXIT_FAILURE);
}
DBGPRINTF("Bound to port %d\n\n", gs_server->port);
proxy_print_local_info();
if(gs_listen_on_socket(serversocket) < 0) {
ERRPRINTF("Failed to listen on server socket.\n");
exit(EXIT_FAILURE);
}
if(gs_server_verify_connectivity(gs_server, serversocket) < 0) {
fprintf(stderr, "Connectivity test failed. If you are behind a NAT,\n");
fprintf(stderr, "check your GRIDSOLVE_PROXY settings.\n");
exit(EXIT_FAILURE);
}
/* Register the server with the agent. Cannot do this earlier, because
* the listening port is not known until now
*/
if(gs_server_register(gs_server) < 0) {
ERRPRINTF("Failed to register with the agent.\n");
return -1;
}
/* Register the problems with the agent */
if(gs_server_register_problems(gs_server) < 0) {
ERRPRINTF("Failed to register my problems with the agent.\n");
return -1;
}
wr_args = (void **)malloc(sizeof(void *));
if(!wr_args) {
ERRPRINTF("Failed to allocate memory for child args\n");
exit(EXIT_FAILURE);
}
wr_args[0] = gs_server;
/* Monitored fork. Forks a child processes to repeatedly run the
* routine gs_workload_report.
*/
pid = mfork(gs_workload_report, GS_UPDATE_FREQUENCY, wr_args,
NULL, NULL, NULL, 30);
if (pid < 0) {
ERRPRINTF("Failed to fork workload manager process.\n");
exit(EXIT_FAILURE);
}
#ifdef GS_SMART_GRIDSOLVE
if(gs_server->smart) {
pid = mfork(gs_server_ping, GS_SERVER_PING_FREQUENCY, wr_args,
NULL, NULL, NULL, 30);
if (pid < 0) {
ERRPRINTF("Failed to fork server ping process.\n");
exit(EXIT_FAILURE);
}
}
#endif
/* Run the actual routine which listens for and handles messages */
if (gs_server_listen_and_process_messages(gs_server, serversocket) < 0)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
}

| static void server_signal_handler | ( | int | sig | ) | [static] |
Signal handler for SIGTERM. Exit with normal status.
| sig | -- the signal that was caught |
Definition at line 198 of file server_main.c.
{
ERRPRINTF("Server terminating on signal %d...\n", sig);
unlink(GS_SERVER_JOB_COUNT_FILE);
exit(0);
}


1.6.3-20100507