Adding version control in the protocol. It can't check with older versions.
authorviric@mandarina
Sun, 15 Feb 2009 19:04:15 +0100
changeset 260 ecd09b351170
parent 259 ba3827aa8f25
child 261 dc8f1609bad8
Adding version control in the protocol. It can't check with older versions.
client.c
main.c
main.h
server.c
--- 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 */