00001
00012
00013
00014
00015 #include <stdlib.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <sys/types.h>
00019 #include <unistd.h>
00020
00021 #include "utility.h"
00022 #include "server.h"
00023 #include "comm_basics.h"
00024 #include "comm_encode.h"
00025 #include "comm_data.h"
00026 #include "comm_protocol.h"
00027 #include "mfork.h"
00028
00039 int
00040 gs_server_verify_connectivity(gs_server_t *server, int serversocket)
00041 {
00042 int sock_agent, tag;
00043 char *reqstr = NULL;
00044
00045 sock_agent = gs_connect_direct(server->agenthost, server->agentport);
00046
00047 if(sock_agent < 0) {
00048 ERRPRINTF("Unable to connect to agent.\n");
00049 return -1;
00050 }
00051
00052 if((gs_send_tag(sock_agent, GS_PROT_AVAILABILITY_REQ) < 0) ||
00053 (gs_send_string(sock_agent, VERSION) < 0)) {
00054 ERRPRINTF("failed to send tag\n");
00055 gs_close_socket(sock_agent);
00056 return -1;
00057 }
00058
00059 if(gs_recv_tag(sock_agent, &tag) < 0) {
00060 ERRPRINTF("Error communicating with agent.\n");
00061 gs_close_socket(sock_agent);
00062 return -1;
00063 }
00064
00065 if(tag != GS_PROT_OK) {
00066 if(tag == GS_PROT_VERSION_MISMATCH)
00067 ERRPRINTF("Error: Agent is an incompatible version\n");
00068 else
00069 ERRPRINTF("Error: Agent refused with code %d\n", tag);
00070 gs_close_socket(sock_agent);
00071 return -1;
00072 }
00073
00074 if(gs_encode_availability_request(&reqstr, server) < 0) {
00075 ERRPRINTF("Could not encode availability request.\n");
00076 return -1;
00077 }
00078
00079 if(gs_send_string(sock_agent, reqstr) < 0) {
00080 ERRPRINTF("failed to send string\n");
00081 if(reqstr) free(reqstr);
00082 gs_close_socket(sock_agent);
00083 return -1;
00084 }
00085
00086 gs_close_socket(sock_agent);
00087 free(reqstr);
00088
00089 printf("Performing connectivity test. If it hangs at this point\n");
00090 printf("and you are behind a NAT, check your GRIDSOLVE_PROXY\n");
00091 printf("environment variable. If you are behind a firewall,\n");
00092 printf("check your port settings.\n");
00093
00094 if((sock_agent = gs_accept_connection(serversocket)) == -1) {
00095 ERRPRINTF("Failed to accept connection on socket\n");
00096 return -1;
00097 }
00098
00099 printf("\n\nConnectivity test successful.\n");
00100
00101 if(gs_recv_tag(sock_agent, &tag) < 0) {
00102 ERRPRINTF("Failed to read tag.\n");
00103 return -1;
00104 }
00105
00106 gs_close_socket(sock_agent);
00107
00108 if(tag != GS_PROT_OK) {
00109 ERRPRINTF("Agent rejected this server (tag = %d).\n", tag);
00110 return -1;
00111 }
00112
00113 return 0;
00114 }
00115
00133 int
00134 gs_server_parse_cmd_line(int argc, char **argv, char *gridsolve_root,
00135 char **logfile, int *daemon, char **srv_cfg)
00136 {
00137 int c;
00138
00139 *logfile = NULL;
00140 *daemon = 1;
00141 *srv_cfg = NULL;
00142
00143
00144
00145
00146
00147
00148 #define GS_SERVER_USAGE_STR "Usage: GS_server [-l logfile] [-c] [-s server config]"
00149
00150 while((c = getopt(argc,argv,"cl:s:")) != EOF) {
00151 switch(c) {
00152 case 'l':
00153 *logfile = strdup(optarg);
00154 break;
00155 case 's':
00156 *srv_cfg = strdup(optarg);
00157 break;
00158 case 'c':
00159 *daemon = 0;
00160 break;
00161 case '?':
00162 return -1;
00163 break;
00164 default:
00165 ERRPRINTF("Bad arg: '%c'.\n",c);
00166 return -1;
00167 }
00168 }
00169
00170
00171 if(!*logfile) {
00172 *logfile = dstring_sprintf("%s/gs_server.log", gridsolve_root);
00173 if(!*logfile) {
00174 fprintf(stderr,"Error generating log file name.\n");
00175 exit(EXIT_FAILURE);
00176 }
00177 }
00178
00179
00180 if(!*srv_cfg) {
00181 *srv_cfg = dstring_sprintf("%s/server_config", gridsolve_root);
00182 if(!*srv_cfg) {
00183 fprintf(stderr,"Error generating server config file name.\n");
00184 exit(EXIT_FAILURE);
00185 }
00186 }
00187
00188 return 0;
00189 }
00190
00197 static void
00198 server_signal_handler(int sig)
00199 {
00200 ERRPRINTF("Server terminating on signal %d...\n", sig);
00201 unlink(GS_SERVER_JOB_COUNT_FILE);
00202 exit(0);
00203 }
00204
00218 int
00219 main(int argc, char** argv)
00220 {
00221 gs_server_t *gs_server = NULL;
00222 int serversocket = -1, daemon;
00223 void **wr_args;
00224 pid_t pid;
00225 char *logfile, *gridsolve_root, *srv_cfg;
00226
00227 if(gs_signal(SIGTERM, server_signal_handler) == SIG_ERR)
00228 ERRPRINTF("Warning: could not set up SIGTERM signal handler\n");
00229 if(gs_signal(SIGINT, server_signal_handler) == SIG_ERR)
00230 ERRPRINTF("Warning: could not set up SIGINT signal handler\n");
00231
00232
00233 if((gridsolve_root = getenv("GRIDSOLVE_ROOT")) == NULL)
00234 gridsolve_root = GRIDSOLVE_TOP_BUILD_DIR;
00235 if(!gridsolve_root) {
00236 ERRPRINTF("Warning: GRIDSOLVE_ROOT unknown, assuming cwd.\n");
00237 gridsolve_root = strdup(".");
00238 }
00239
00240
00241 if(gs_server_parse_cmd_line(argc, argv, gridsolve_root, &logfile,
00242 &daemon, &srv_cfg) < 0) {
00243 fprintf(stderr, "%s\n", GS_SERVER_USAGE_STR);
00244 exit(EXIT_FAILURE);
00245 }
00246
00247
00248 if(daemon && gs_daemon_init(gridsolve_root, logfile) < 0) {
00249 fprintf(stderr, "Failed to start server as a daemon.\n");
00250 exit(EXIT_FAILURE);
00251 }
00252
00253
00254 if ((gs_server = gs_server_init(srv_cfg)) == NULL) {
00255 fprintf(stderr, "Failed to initialize the server.\n");
00256 exit(EXIT_FAILURE);
00257 }
00258
00259 #ifdef GS_DEBUG
00260 gs_server_dump(gs_server);
00261 #endif
00262
00263
00264 serversocket = gs_establish_socket(&(gs_server->port), 0);
00265
00266 if(serversocket == -1) {
00267 ERRPRINTF("Could not bind to port %d\n", gs_server->port);
00268 exit(EXIT_FAILURE);
00269 }
00270
00271 DBGPRINTF("Bound to port %d\n\n", gs_server->port);
00272 proxy_print_local_info();
00273
00274 if(gs_listen_on_socket(serversocket) < 0) {
00275 ERRPRINTF("Failed to listen on server socket.\n");
00276 exit(EXIT_FAILURE);
00277 }
00278
00279 if(gs_server_verify_connectivity(gs_server, serversocket) < 0) {
00280 fprintf(stderr, "Connectivity test failed. If you are behind a NAT,\n");
00281 fprintf(stderr, "check your GRIDSOLVE_PROXY settings.\n");
00282 exit(EXIT_FAILURE);
00283 }
00284
00285
00286
00287
00288 if(gs_server_register(gs_server) < 0) {
00289 ERRPRINTF("Failed to register with the agent.\n");
00290 return -1;
00291 }
00292
00293
00294 if(gs_server_register_problems(gs_server) < 0) {
00295 ERRPRINTF("Failed to register my problems with the agent.\n");
00296 return -1;
00297 }
00298
00299 wr_args = (void **)malloc(sizeof(void *));
00300 if(!wr_args) {
00301 ERRPRINTF("Failed to allocate memory for child args\n");
00302 exit(EXIT_FAILURE);
00303 }
00304
00305 wr_args[0] = gs_server;
00306
00307
00308
00309
00310 pid = mfork(gs_workload_report, GS_UPDATE_FREQUENCY, wr_args,
00311 NULL, NULL, NULL, 30);
00312
00313 if (pid < 0) {
00314 ERRPRINTF("Failed to fork workload manager process.\n");
00315 exit(EXIT_FAILURE);
00316 }
00317
00318 #ifdef GS_SMART_GRIDSOLVE
00319 if(gs_server->smart) {
00320 pid = mfork(gs_server_ping, GS_SERVER_PING_FREQUENCY, wr_args,
00321 NULL, NULL, NULL, 30);
00322
00323 if (pid < 0) {
00324 ERRPRINTF("Failed to fork server ping process.\n");
00325 exit(EXIT_FAILURE);
00326 }
00327 }
00328 #endif
00329
00330
00331 if (gs_server_listen_and_process_messages(gs_server, serversocket) < 0)
00332 exit(EXIT_FAILURE);
00333 else
00334 exit(EXIT_SUCCESS);
00335 }