Adding version control in the protocol. It can't check with older versions.
--- a/client.c Sun Feb 15 17:33:57 2009 +0100
+++ b/client.c Sun Feb 15 19:04:15 2009 +0100
@@ -182,6 +182,30 @@
m.type = LIST;
send_msg(server_socket, &m);
+ send_msg(server_socket, &m);
+}
+
+/* Exits if wrong */
+void c_check_version()
+{
+ struct msg m;
+ int res;
+
+ m.type = GET_VERSION;
+ send_msg(server_socket, &m);
+
+ res = recv_msg(server_socket, &m);
+ if(res == -1 || res == 0)
+ error("Error checking version");
+
+ if (m.type != VERSION || m.u.version != PROTOCOL_VERSION)
+ {
+ printf("Wrong server version. Received %i, expecting %i\n",
+ m.u.version, PROTOCOL_VERSION);
+
+ error("Wrong server version. Received %i, expecting %i",
+ m.u.version, PROTOCOL_VERSION);
+ }
}
void c_show_info()
--- a/main.c Sun Feb 15 17:33:57 2009 +0100
+++ b/main.c Sun Feb 15 19:04:15 2009 +0100
@@ -386,7 +386,10 @@
ignore_sigpipe();
if (command_line.need_server)
+ {
ensure_server_up();
+ c_check_version();
+ }
switch(command_line.request)
{
--- a/main.h Sun Feb 15 17:33:57 2009 +0100
+++ b/main.h Sun Feb 15 19:04:15 2009 +0100
@@ -1,6 +1,7 @@
enum
{
- CMD_LEN=500
+ CMD_LEN=500,
+ PROTOCOL_VERSION=623
};
enum msg_types
@@ -31,7 +32,9 @@
INFO_DATA,
SET_MAX_SLOTS,
GET_MAX_SLOTS,
- GET_MAX_SLOTS_OK
+ GET_MAX_SLOTS_OK,
+ GET_VERSION,
+ VERSION
};
enum Request
@@ -135,6 +138,7 @@
} swap;
int last_errorlevel;
int max_slots;
+ int version;
} u;
};
@@ -193,6 +197,7 @@
char *build_command_string();
void c_send_max_slots(int max_slots);
void c_get_max_slots();
+void c_check_version();
/* jobs.c */
void s_list(int s);
--- a/server.c Sun Feb 15 17:33:57 2009 +0100
+++ b/server.c Sun Feb 15 19:04:15 2009 +0100
@@ -32,7 +32,8 @@
enum Break
{
BREAK,
- NOBREAK
+ NOBREAK,
+ CLOSE
};
/* Prototypes */
@@ -42,6 +43,7 @@
static void end_server(int ls);
static void s_newjob_ok(int index);
static void s_runjob(int jobid, int index);
+static void clean_after_client_disappeared(int socket, int index);
struct Client_conn
{
@@ -56,6 +58,16 @@
static char *path;
static int max_descriptors;
+static void s_send_version(int s)
+{
+ struct msg m;
+
+ m.type = VERSION;
+ m.u.version = PROTOCOL_VERSION;
+
+ send_msg(s, &m);
+}
+
static void sigterm_handler(int n)
{
const char *dumpfilename;
@@ -222,7 +234,14 @@
enum Break b;
b = client_read(i);
/* Check if we should break */
- if (b == BREAK)
+ if (b == CLOSE)
+ {
+ warning("Closing");
+ /* On unknown message, we close the client,
+ or it may hang waiting for an answer */
+ clean_after_client_disappeared(client_cs[i].socket, i);
+ }
+ else if (b == BREAK)
keep_loop = 0;
}
/* This will return firstjob->jobid or -1 */
@@ -324,126 +343,113 @@
}
/* Process message */
- if (m.type == KILL_SERVER)
- return BREAK; /* break in the parent*/
-
- if (m.type == NEWJOB)
- {
- client_cs[index].jobid = s_newjob(s, &m);
- client_cs[index].hasjob = 1;
- s_newjob_ok(index);
- }
-
- if (m.type == RUNJOB_OK)
+ switch(m.type)
{
- char *buffer = 0;
- if (m.u.output.store_output)
- {
- /* Receive the output filename */
- buffer = (char *) malloc(m.u.output.ofilename_size);
- res = recv_bytes(s, buffer,
- m.u.output.ofilename_size);
- if (res != m.u.output.ofilename_size)
- error("Reading the ofilename");
- }
- s_process_runjob_ok(client_cs[index].jobid, buffer,
- m.u.output.pid);
- }
-
- if (m.type == LIST)
- {
- s_list(s);
- /* We must actively close, meaning End of Lines */
- close(s);
- remove_connection(index);
- }
-
- if (m.type == INFO)
- {
- s_job_info(s, m.u.jobid);
- close(s);
- remove_connection(index);
- }
+ case KILL_SERVER:
+ return BREAK; /* break in the parent*/
+ break;
+ case NEWJOB:
+ client_cs[index].jobid = s_newjob(s, &m);
+ client_cs[index].hasjob = 1;
+ s_newjob_ok(index);
+ break;
+ case RUNJOB_OK:
+ {
+ char *buffer = 0;
+ if (m.u.output.store_output)
+ {
+ /* Receive the output filename */
+ buffer = (char *) malloc(m.u.output.ofilename_size);
+ res = recv_bytes(s, buffer,
+ m.u.output.ofilename_size);
+ if (res != m.u.output.ofilename_size)
+ error("Reading the ofilename");
+ }
+ s_process_runjob_ok(client_cs[index].jobid, buffer,
+ m.u.output.pid);
+ }
+ break;
+ case LIST:
+ s_list(s);
+ /* We must actively close, meaning End of Lines */
+ close(s);
+ remove_connection(index);
+ break;
+ case INFO:
+ s_job_info(s, m.u.jobid);
+ close(s);
+ remove_connection(index);
+ break;
+ case ENDJOB:
+ job_finished(&m.u.result, client_cs[index].jobid);
+ /* For the dependencies */
+ check_notify_list(client_cs[index].jobid);
+ /* We don't want this connection to do anything
+ * more related to the jobid, secially on remove_connection
+ * when we receive the EOC. */
+ client_cs[index].hasjob = 0;
+ break;
+ case CLEAR_FINISHED:
+ s_clear_finished();
+ break;
+ case ASK_OUTPUT:
+ s_send_output(s, m.u.jobid);
+ break;
+ case REMOVEJOB:
+ {
+ int went_ok;
+ went_ok = s_remove_job(s, m.u.jobid);
+ if (went_ok)
+ {
+ int i;
+ for(i = 0; i < nconnections; ++i)
+ {
+ if (client_cs[i].hasjob && client_cs[i].jobid == m.u.jobid)
+ {
+ close(client_cs[i].socket);
- if (m.type == ENDJOB)
- {
- job_finished(&m.u.result, client_cs[index].jobid);
- /* For the dependencies */
- check_notify_list(client_cs[index].jobid);
- /* We don't want this connection to do anything
- * more related to the jobid, secially on remove_connection
- * when we receive the EOC. */
- client_cs[index].hasjob = 0;
- }
-
- if (m.type == CLEAR_FINISHED)
- {
- s_clear_finished();
- }
+ /* So remove_connection doesn't call s_removejob again */
+ client_cs[i].hasjob = 0;
- if (m.type == ASK_OUTPUT)
- {
- s_send_output(s, m.u.jobid);
- }
-
- if (m.type == REMOVEJOB)
- {
- int went_ok;
- went_ok = s_remove_job(s, m.u.jobid);
- if (went_ok)
- {
- int i;
- for(i = 0; i < nconnections; ++i)
- {
- if (client_cs[i].hasjob && client_cs[i].jobid == m.u.jobid)
- {
- close(client_cs[i].socket);
-
- /* So remove_connection doesn't call s_removejob again */
- client_cs[i].hasjob = 0;
-
- /* We don't try to remove any notification related to
- * 'i', because it will be for sure a ts client for a job */
- remove_connection(i);
+ /* We don't try to remove any notification related to
+ * 'i', because it will be for sure a ts client for a job */
+ remove_connection(i);
+ }
+ }
}
}
- }
- }
-
- if (m.type == WAITJOB)
- {
- s_wait_job(s, m.u.jobid);
- }
-
- if (m.type == WAIT_RUNNING_JOB)
- {
- s_wait_running_job(s, m.u.jobid);
- }
-
- if (m.type == URGENT)
- {
- s_move_urgent(s, m.u.jobid);
- }
-
- if (m.type == SET_MAX_SLOTS)
- {
- s_set_max_slots(m.u.max_slots);
- }
-
- if (m.type == GET_MAX_SLOTS)
- {
- s_get_max_slots(s);
- }
-
- if (m.type == SWAP_JOBS)
- {
- s_swap_jobs(s, m.u.swap.jobid1,
- m.u.swap.jobid2);
- }
-
- if (m.type == GET_STATE)
- {
- s_send_state(s, m.u.jobid);
+ break;
+ case WAITJOB:
+ s_wait_job(s, m.u.jobid);
+ break;
+ case WAIT_RUNNING_JOB:
+ s_wait_running_job(s, m.u.jobid);
+ break;
+ case URGENT:
+ s_move_urgent(s, m.u.jobid);
+ break;
+ case SET_MAX_SLOTS:
+ s_set_max_slots(m.u.max_slots);
+ break;
+ case GET_MAX_SLOTS:
+ s_get_max_slots(s);
+ break;
+ case SWAP_JOBS:
+ s_swap_jobs(s, m.u.swap.jobid1,
+ m.u.swap.jobid2);
+ break;
+ case GET_STATE:
+ s_send_state(s, m.u.jobid);
+ break;
+ case GET_VERSION:
+ s_send_version(s);
+ break;
+ default:
+ /* Command not supported */
+ /* On unknown message, we close the client,
+ or it may hang waiting for an answer */
+ warning("Unknown message: %i", m.type);
+ return CLOSE;
}
return NOBREAK; /* normal */