[netperf-dev] netperf4 commit notice r204 - branches/gobject_migration/src

raj at netperf.org raj at netperf.org
Tue Mar 6 18:13:06 PST 2007


Author: raj
Date: 2007-03-06 18:13:04 -0800 (Tue, 06 Mar 2007)
New Revision: 204

Modified:
   branches/gobject_migration/src/netperf-netserver.c
   branches/gobject_migration/src/netperf-netserver.h
Log:
still more halting steps towards GObjectification

Modified: branches/gobject_migration/src/netperf-netserver.c
===================================================================
--- branches/gobject_migration/src/netperf-netserver.c	2007-03-03 01:06:36 UTC (rev 203)
+++ branches/gobject_migration/src/netperf-netserver.c	2007-03-07 02:13:04 UTC (rev 204)
@@ -2,6 +2,82 @@
 #include <stdio.h>
 #include "netperf-netserver.h"
 
+/* perhaps one of these days, these should become properties of a
+   NetperfNetserver? */
+extern int debug;
+extern FILE *where;
+
+static int clear_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int clear_sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int close_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int closed_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int configured_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int dead_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int die_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int error_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int get_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int get_sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int idle_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int idled_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int initialized_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int interval_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int load_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int loaded_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int measure_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int measuring_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int netserver_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int np_idle_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int np_version_check(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int ns_version_check(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int snap_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int test_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int test_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int unexpected_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+static int unknown_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+
+const struct netperf_msgs   NP_Msgs[] = {
+  /* Message name, function,             StateBitMap */
+#ifdef OFF
+  { "cleared",         cleared_message,          0x00000000 },
+  { "configured",      configured_message,       0x00000000 },
+#endif
+  { "measuring",       measuring_message,        0x00000010 },
+  { "loaded",          loaded_message,           0x00000010 },
+  { "idled",           np_idle_message,          0x00000018 },
+  { "test_stats",      test_stats_message,       0x00000010 },
+  { "sys_stats",       sys_stats_message,        0x00000010 },
+  { "initialized",     initialized_message,      0x00000018 },
+  { "error",           error_message,            0x00000018 },
+  { "dead",            dead_message,             0x00000018 },
+  { "closed",          closed_message,           0x00000018 },
+  { "version",         np_version_check,         0x00000004 },
+  { NULL,              unknown_message,          0xFFFFFFFF }
+};
+
+const struct netperf_msgs   NS_Msgs[] = {
+  /* Message name,     function,                StateBitMap */
+#ifdef OFF
+  { "clear",           clear_message,            0x00000000 },
+  { "error",           error_message,            0x00000000 },
+  { "interval",        interval_message,         0x00000000 },
+  { "snap",            snap_message,             0x00000000 },
+#endif
+  { "measure",         measure_message,          0x00000010 },
+  { "load",            load_message,             0x00000010 },
+  { "idle",            idle_message,             0x00000010 },
+  { "get_stats",       get_stats_message,        0x00000010 },
+  { "get_sys_stats",   get_sys_stats_message,    0x00000010 },
+  { "clear_stats",     clear_stats_message,      0x00000010 },
+  { "clear_sys_stats", clear_sys_stats_message,  0x00000010 },
+  { "initialized",     initialized_message,      0x00000010 },
+  { "test",            test_message,             0x00000014 },
+  { "die",             die_message,              0x00000030 },
+  { "close",           close_message,            0x00000030 },
+  { "version",         ns_version_check,         0x00000001 },
+  { NULL,              unknown_message,          0xFFFFFFFF }
+};
+
 enum {
   NETSERVER_PROP_DUMMY_0,    /* GObject does not like a zero value for a property id */
   NETSERVER_PROP_ID,
@@ -160,6 +236,975 @@
 		 0);
 }
 
+/* a bunch of the message processing code, originally from netmsg.c */
+int
+process_message(NetperfNetserver *server, xmlDocPtr doc)
+{
+  int loc_debug = 0;
+  int rc = NPE_SUCCESS;
+  int cur_state = 0;
+  xmlChar *fromnid;
+  xmlNodePtr msg;
+  xmlNodePtr cur;
+  struct msgs *which_msg;
+
+  NETPERF_DEBUG_ENTRY(debug,where);
+
+  msg = xmlDocGetRootElement(doc);
+  if (msg == NULL) {
+    fprintf(stderr,"empty document\n");
+    fflush(stderr);
+    xmlFreeDoc(doc);
+    /* somehow I don't think that returning NPE_SUCCESS is the right
+       thing here? raj 2005-10-26 */
+    return(rc);
+  }
+  fromnid = xmlGetProp(msg,(const xmlChar *)"fromnid");
+
+  if (server != NULL)  cur_state = 1 << server->state;
+    
+  if (debug) {
+    fprintf(where,"process_message: received '%s' message from server %s\n",
+            msg->xmlChildrenNode->name, fromnid);
+    fprintf(where,"process_message: servers current state is %d\n", cur_state);
+    fflush(where);
+  }
+  for (cur = msg->xmlChildrenNode; cur != NULL; cur = cur->next) {
+    which_msg = np_msg_handler_base;
+    while (which_msg->msg_name != NULL) {
+      if (xmlStrcmp(cur->name,(xmlChar *)which_msg->msg_name)) {
+        which_msg++;
+        continue;
+      }
+      if (which_msg->valid_states & cur_state) {
+        rc = (which_msg->msg_func)(cur,doc,server);
+        if (rc != NPE_SUCCESS) {
+          fprintf(where,"process_message: received %d from %s\n",
+                  rc, which_msg->msg_name);
+          fflush(where);
+          server->state = NSRV_ERROR;
+          if (server->sock != -1) {
+            CLOSE_SOCKET(server->sock);
+            /* should we delete the server from the server_hash ? sgb */
+            break;
+          }
+        }
+      } else {
+        if (debug || loc_debug) {
+          fprintf(where,
+                  "process_message:state is %d got unexpected '%s' message.\n",
+                  cur_state,
+                  cur->name);
+          fflush(where);
+        }
+      }
+      which_msg++;
+    }
+  }
+  xmlFreeDoc(doc);
+  if (fromnid) free(fromnid);
+
+  NETPERF_DEBUG_EXIT(debug,where);
+
+  return(rc);
+}
+
+
+/*
+   netperf verify the version message from a netserver
+   Valid responses from netperf are a configuration message if versions
+   match or to close the connection if the version does not match.
+*/
+
+int
+np_version_check(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int rc;
+  if (!xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"vers"),NETPERF_VERSION) &&
+      !xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"updt"),NETPERF_UPDATE)  &&
+      !xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"fix"), NETPERF_FIX))     {
+    /* versions match */
+    if (debug) {
+      fprintf(where,"np_version_check: version check successful\n");
+      fflush(where);
+    } 
+    rc = NPE_SUCCESS;
+  } else {
+    /* versions don't match */
+    if (debug) {
+      fprintf(where,"np_version_check: version check failed\n");
+      fflush(where);
+    }
+    rc = NPE_BAD_VERSION;
+  }
+  return(rc);
+}
+
+
+/*
+   generate a version message and send it out the control
+   socket.  XML may be the wizziest thing since sliced bits, but it
+   sure does lead to some rather cumbersome coding... raj 2003-02-27
+*/
+int
+send_version_message(NetperfNetserver *server, const xmlChar *fromnid)
+{
+  int rc = NPE_SUCCESS;
+  xmlNodePtr message;
+
+
+  if ((message = xmlNewNode(NULL,(xmlChar *)"version")) != NULL) {
+    /* set the properties of the version message -
+       the version, update, and fix levels  sgb 2003-02-27 */
+    if ((xmlSetProp(message,(xmlChar *)"vers",NETPERF_VERSION) != NULL) &&
+        (xmlSetProp(message,(xmlChar *)"updt",NETPERF_UPDATE)  != NULL) &&
+        (xmlSetProp(message,(xmlChar *)"fix", NETPERF_FIX)     != NULL))  {
+      /* still smiling */
+      /* almost there... */
+      rc = write_to_control_connection(server->source,
+				       message,
+				       server->id,
+				       fromnid);
+      if (rc != NPE_SUCCESS) {
+        if (debug) {
+          fprintf(where,
+                  "send_version_message: write_to_control_connection failed\n");
+          fflush(where);
+        }
+      }
+    } else {
+      if (debug) {
+        fprintf(where,
+                "send_version_message: an xmlSetProp failed\n");
+        fflush(where);
+      }
+      rc = NPE_SEND_VERSION_XMLSETPROP_FAILED;
+    }
+    /* now that we are done with it, best to free the message node */
+    xmlFreeNode(message);
+  }
+  else {
+    if (debug) {
+      fprintf(where,
+              "send_version_message: xmlNewNode failed\n");
+      fflush(where);
+    }
+    rc = NPE_SEND_VERSION_XMLNEWNODE_FAILED;
+  }
+  if (debug) {
+    if (rc != NPE_SUCCESS) {
+      fprintf(where,"send_version_message: error status %d\n",rc);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+
+/*
+   netserver verify the version message from a netperf
+   Valid responses from a netserver in an error message if version
+   does not match or a version check response if it matches.
+*/
+
+int
+ns_version_check(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *netperf)
+{
+  int rc = NPE_SUCCESS;
+
+  if (!xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"vers"),NETPERF_VERSION) &&
+      !xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"updt"),NETPERF_UPDATE)  &&
+      !xmlStrcmp(xmlGetProp(msg,(const xmlChar *)"fix"), NETPERF_FIX))     {
+    /* versions match */
+    netperf->state      =  NSRV_VERS;
+    netperf->state_req  =  NSRV_WORK;
+    rc = send_version_message(netperf,netperf->my_nid);
+  } else {
+    /* versions don't match */
+    if (debug) {
+      fprintf(where,"ns_version_chk: version check failed\n");
+      fflush(where);
+    }
+    rc = NPE_BAD_VERSION;
+  }
+  return(rc);
+}
+
+
+int
+die_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"%s: tid = %s  prev_state_req = %d ",
+              __func__, testid, test->state_req);
+      fflush(where);
+    }
+    test->state_req = TEST_DEAD;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+
+int
+dead_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  xmlChar    *testid;
+  test_t     *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"%s: tid = %s  prev_state_req = %d ",
+              __func__, testid, test->state_req);
+      fflush(where);
+    }
+    test->state = TEST_DEAD;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(NPE_SUCCESS);
+}
+
+
+int
+error_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int loc_debug = 0;
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug || loc_debug) {
+      fprintf(where,"error_message: prev_state_req = %d ",test->state_req);
+      fflush(where);
+    }
+    test->err_rc  = atoi((char *)xmlGetProp(msg,(const xmlChar *)"err_rc"));
+    test->err_fn  = (char *)xmlGetProp(msg,(const xmlChar *)"err_fn");
+    test->err_str = (char *)xmlGetProp(msg,(const xmlChar *)"err_str");
+    test->err_no  = atoi((char *)xmlGetProp(msg,(const xmlChar *)"err_no"));
+    test->state   = TEST_ERROR;
+    if (debug || loc_debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fprintf(where,"\terr in test function %s  rc = %d\n",
+              test->err_fn,test->err_rc);
+      fprintf(where,"\terror message '%s' errno = %d\n",
+              test->err_str,test->err_no);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+
+int
+clear_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,
+            "clear_stats_message: test_state = %d calling %p\n",
+            test->state,
+            test->test_clear);
+      fflush(where);
+    }
+    rc = (test->test_clear)(test);
+    if (rc != NPE_SUCCESS) {
+      if (debug) {
+        fprintf(where,
+                "clear_stats_message: clear of statistics failed\n");
+        fflush(where);
+      }
+    }
+  }
+  return(rc);
+}
+
+
+int
+clear_sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,
+            "clear_sys_stats_message: test %p test_state = %d calling %p\n",
+            test,
+            test->state,
+            test->test_clear);
+      fflush(where);
+    }
+    rc = (test->test_clear)(test);
+    if (rc != NPE_SUCCESS) {
+      if (debug) {
+        fprintf(where,
+                "clear_sys_stats_message: clear of statistics failed\n");
+        fflush(where);
+      }
+    }
+  }
+  return(rc);
+}
+
+
+int
+get_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+  xmlNodePtr  stats;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"get_stats_message: test_state = %d\n",test->state);
+      fflush(where);
+    }
+    stats = (test->test_stats)(test);
+    rc = write_to_control_connection(server->source,
+				     stats,
+				     server->id,
+				     server->my_nid);
+    if (rc != NPE_SUCCESS) {
+      if (debug) {
+        fprintf(where,
+                "%s: write_to_control_connection failed\n",
+                __func__);
+        fflush(where);
+      }
+    }
+  }
+  return(rc);
+}
+
+
+int
+get_sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+  xmlNodePtr  sys_stats;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"%s: test_state = %d ",
+              __func__, test->state);
+      fflush(where);
+    }
+    sys_stats = (test->test_stats)(test);
+    rc = write_to_control_connection(server->source,
+				     sys_stats,
+				     server->id,
+				     server->my_nid);
+    if (rc != NPE_SUCCESS) {
+      if (debug) {
+        fprintf(where,
+                "%s: write_to_control_connection failed\n",
+                 __func__);
+        fflush(where);
+      }
+    }
+  }
+  return(rc);
+}
+
+
+int
+np_idle_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+  int        hash_value;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+
+  hash_value = TEST_HASH_VALUE(testid);
+
+  /* don't forget to add error checking one day */
+  if (debug) {
+    fprintf(where,"np_idle_message: waiting for mutex\n");
+    fflush(where);
+  }
+  NETPERF_MUTEX_LOCK(test_hash[hash_value].hash_lock);
+
+  test = test_hash[hash_value].test;
+  while (test != NULL) {
+    if (!xmlStrcmp(test->id,testid)) {
+      /* we have a match */
+      break;
+    }
+    test = test->next;
+  }
+
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"np_idle_message: prev_state = %d ",test->state);
+      fflush(where);
+    }
+    test->state = TEST_IDLE;
+    /* I'd have liked to have abstracted this with the NETPERF_mumble
+       macros, but the return values differ. raj 2006-03-02 */
+    g_cond_broadcast(test_hash[hash_value].condition);
+  }
+  if (debug) {
+    fprintf(where,"np_idle_message: unlocking mutex\n");
+    fflush(where);
+  }
+  NETPERF_MUTEX_UNLOCK(test_hash[hash_value].hash_lock);
+  return(rc);
+}
+
+int
+idle_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"idle_message: tid = %s  prev_state_req = %d ",
+              testid, test->state_req);
+      fflush(where);
+    }
+    test->state_req = TEST_IDLE;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+int
+idled_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"idled_message: tid = %s  prev_state_req = %d ",
+              testid, test->state_req);
+      fflush(where);
+    }
+    test->state = TEST_IDLE;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+int
+close_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  xmlChar    *flag;
+
+
+  /* what should we really do with this flag??  sgb 2005-12-5 */
+  flag = xmlGetProp(msg,(const xmlChar *)"flag");
+  if (debug) {
+    fprintf(where,"%s: flag = '%s'  state = %d req_state = %d\n",
+            __func__, flag, server->state, server->state_req);
+    fflush(where);
+  }
+  if (!xmlStrcmp(flag,(const xmlChar *)"LOOP")) {
+    server->state_req = NSRV_CLOSE;
+  }
+  else {
+    server->state_req = NSRV_EXIT;
+  }
+  return(NPE_SUCCESS);
+}
+
+int
+closed_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  xmlChar   *flag;
+
+
+  /* what should we really do with this flag??  sgb 2005-12-5 */
+  flag = xmlGetProp(msg,(const xmlChar *)"flag");
+  if (debug) {
+    fprintf(where,"%s: flag = '%s'  state = %d req_state = %d\n",
+            __func__, flag, server->state, server->state_req);
+    fflush(where);
+  }
+  if (!xmlStrcmp(flag,(const xmlChar *)"LOOPING")) {
+    server->state = NSRV_CLOSE;
+  }
+  else {
+    server->state = NSRV_EXIT;
+  }
+  return(NPE_SUCCESS);
+}
+
+int
+initialized_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  
+  int        rc = NPE_SUCCESS;
+  xmlNodePtr dependency_data;
+  xmlChar   *testid;
+  test_t    *test;
+  int        hash_value;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+
+  dependency_data = msg->xmlChildrenNode;
+  while (dependency_data != NULL) {
+    if (!xmlStrcmp(dependency_data->name,(const xmlChar *)"dependency_data")) {
+      break;
+    }
+  }
+  
+  hash_value = TEST_HASH_VALUE(testid);
+
+  /* don't forget to add error checking one day */
+  NETPERF_MUTEX_LOCK(test_hash[hash_value].hash_lock);
+
+  test = test_hash[hash_value].test;
+  while (test != NULL) {
+    if (!xmlStrcmp(test->id,testid)) {
+      /* we have a match */
+      break;
+    }
+    test = test->next;
+  }
+
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"initialized_message: prev_state = %d ",test->state);
+      fflush(where);
+    }
+    if (dependency_data != NULL) {
+      test->dependent_data = xmlCopyNode(dependency_data,1);
+      if (test->dependent_data != NULL) {
+        test->state = TEST_INIT;
+      } else {
+        test->state = TEST_ERROR;
+        /* add additional error information later */
+      }
+    } else {
+      test->state = TEST_INIT;
+    }
+
+    /* since the different cond broadcast calls return different
+       things, we cannot use the nice NETPERF_mumble abstractions. */
+
+    g_cond_broadcast(test_hash[hash_value].condition);
+
+
+    if (debug) {
+      fprintf(where," new_state = %d rc = %d\n",test->state,rc);
+      fflush(where);
+    }
+
+  }
+  NETPERF_MUTEX_UNLOCK(test_hash[hash_value].hash_lock);
+  return(rc);
+}
+
+
+int
+load_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"load_message: tid = %s  prev_state_req = %d ",
+              testid, test->state_req);
+      fflush(where);
+    }
+    test->state_req = TEST_LOADED;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+int
+loaded_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"loaded_message: prev_state = %d ",test->state);
+      fflush(where);
+    }
+    test->state = TEST_LOADED;
+    if (debug) {
+      fprintf(where," new_state = %d\n",test->state);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+
+int
+measure_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"measure_message: prev_state_req = %d ",test->state_req);
+      fflush(where);
+    }
+    test->state_req = TEST_MEASURE;
+    if (debug) {
+      fprintf(where," new_state_req = %d\n",test->state_req);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+int
+measuring_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  xmlChar   *testid;
+  test_t    *test;
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"measuring_message: prev_state = %d ",test->state);
+      fflush(where);
+    }
+    test->state = TEST_MEASURE;
+    if (debug) {
+      fprintf(where," new_state = %d\n",test->state);
+      fflush(where);
+    }
+  }
+  return(rc);
+}
+
+
+int
+test_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int        rc = NPE_SUCCESS;
+  int        rc2;
+  test_t    *new_test;
+  xmlNodePtr test_node;
+  xmlChar   *testid;
+  xmlChar   *loc_type = NULL;
+  xmlChar   *loc_value = NULL;
+  thread_launch_state_t *launch_state;
+
+  NETPERF_DEBUG_ENTRY(debug,where);
+
+  if (server->state != server->state_req) {
+    /* set netserver state to NSRV_WORK because receiving a test message
+       shows that netperf accepted our version message */
+    server->state = server->state_req;
+  }
+  test_node = msg;
+  while (test_node != NULL && rc == NPE_SUCCESS) {
+    if (xmlStrcmp(test_node->name,(const xmlChar *)"test")) {
+      if (debug) {
+        fprintf(where,"test_message: skipped a non-test node\n");
+        fflush(where);
+      }
+      test_node = test_node->next;
+      continue;
+    }
+    testid = xmlGetProp(test_node,(const xmlChar *)"tid");
+    new_test = (test_t *)malloc(sizeof(test_t));
+    if (new_test != NULL) { /* we have a new test_t structure */
+      memset(new_test,0,sizeof(test_t));
+      new_test->node      = test_node;
+      new_test->id        = testid;
+      new_test->server_id = server->id;
+      new_test->state     = TEST_PREINIT;
+      new_test->new_state = TEST_PREINIT;
+      new_test->state_req = TEST_IDLE;
+      new_test->debug     = debug;
+      new_test->where     = where;
+      rc = get_test_function(new_test,(const xmlChar *)"test_name");
+      if (rc == NPE_SUCCESS) {
+        rc = get_test_function(new_test,(const xmlChar *)"test_clear");
+      }
+      if (rc == NPE_SUCCESS) {
+        rc = get_test_function(new_test,(const xmlChar *)"test_stats");
+      }
+      if (rc == NPE_SUCCESS) {
+        rc = get_test_function(new_test,(const xmlChar *)"test_decode");
+      }
+
+    } else {
+      rc = NPE_MALLOC_FAILED2;
+    }
+    if (rc == NPE_SUCCESS) {
+      rc = add_test_to_hash(new_test);
+    }
+    if (rc == NPE_SUCCESS) {
+      if (debug) {
+        fprintf(where,
+                "test_message: launching test thread using func %p\n",
+                new_test->test_func);
+        fflush(where);
+      }
+      launch_state =
+	(thread_launch_state_t *)malloc(sizeof(thread_launch_state_t));
+      if (launch_state) {
+	launch_state->data_arg = new_test;
+	launch_state->start_routine = new_test->test_func;
+
+	/* before we launch the thread, we should bind ourselves to
+	   the cpu to which the thread will be bound (if at all) to
+	   make sure that stuff like stack allocation happens on the
+	   desired CPU. raj 2006-04-11 */
+
+	loc_type  = xmlGetProp(test_node,(const xmlChar *)"locality_type");
+	loc_value = xmlGetProp(test_node,(const xmlChar *)"locality_value");
+	if ((loc_type != NULL) && (loc_value != NULL)) {
+	  /* we use rc2 because we aren't going to fail the run if the
+	     affinity didn't work, but eventually we should emit some
+	     sort of warning */
+	  rc2 = set_own_locality((char *)loc_type,
+				 (char *)loc_value,
+				 debug,
+				 where);
+	}
+
+	rc = launch_thread(&new_test->thread_id,launch_pad,launch_state);
+	if (debug) {
+	  fprintf(where,
+		  "test_message: launched test thread\n");
+	  fflush(where);
+	}
+	/* having launched the test thread, we really aught to unbind
+	   ourselves from that CPU. at the moment, we do not do that */
+      }
+      else {
+	rc = NPE_MALLOC_FAILED2;
+      }
+    }
+
+    /* wait for test to initialize, then we will know that it's native
+       thread id has been set in the test_t */
+    if (rc == NPE_SUCCESS) {
+      while (new_test->new_state == TEST_PREINIT) {
+        if (debug) {
+          fprintf(where,
+                  "test_message: waiting on thread\n");
+          fflush(where);
+        }
+        g_usleep(1000000);
+      }  /* end wait */
+      if (debug) {
+        fprintf(where,
+                "test_message: test initialization finished on thread\n");
+        fflush(where);
+      }
+    }
+
+    /* now we can set test thread locality */
+    if (rc == NPE_SUCCESS) {
+      /* we will have already extracted loc_type and loc_value if they
+	 exist and there is no possibility of them having spontaneously
+	 appeared in the last N lines of code, so we don't need the
+	 xmlGetProp calls here :)  raj 2006-04-11 */
+      if ((loc_type != NULL) && (loc_value != NULL)) {
+	/* we use rc2 because we aren't going to fail the run if the
+	   affinity didn't work, but eventually we should emit some
+	   sort of warning */
+        rc2 = set_test_locality(new_test, (char *)loc_type, (char *)loc_value);
+	rc2 = clear_own_locality((char *)loc_type,debug,where);
+      }
+      /* however, at this point we need to be sure to free loc_type
+	 and/or loc_value. nulling may be a bit over the top, but
+	 might as well, this isn't supposed to be that performance
+	 critical */
+      if (NULL != loc_type)  {
+	free(loc_type);
+	loc_type = NULL;
+      }
+      if (NULL != loc_value) {
+	free(loc_value);
+	loc_value = NULL;
+      }
+    }
+
+    if (rc != NPE_SUCCESS) {
+      new_test->state  = TEST_ERROR;
+      new_test->err_rc = rc;
+      new_test->err_fn = (char *)__func__;
+      rc = NPE_TEST_INIT_FAILED;
+      break;
+    }
+    test_node = test_node->next;
+  }
+
+  NETPERF_DEBUG_EXIT(debug,where);
+
+  return(rc);
+}
+
+
+int
+sys_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          loc_debug = 0;
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+  xmlNodePtr  stats = NULL;
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (debug || loc_debug) {
+    fprintf(where,"sys_stats_message: test = %p\n",test);
+    fflush(where);
+  }
+  if (test != NULL) {
+    if (test->received_stats == NULL) {
+      test->received_stats = xmlNewNode(NULL,(xmlChar *)"received_stats");
+      if (debug || loc_debug) {
+        fprintf(where,"sys_stats_message: creating received_stats node %p\n",
+                test->received_stats);
+        fflush(where);
+      }
+    }
+    if (test->received_stats) {
+      stats = xmlCopyNode(msg,1);
+      xmlAddChild(test->received_stats, stats);
+      if (debug || loc_debug) {
+        fprintf(where,"sys_stats_message: stats to list %p\n",
+                test->received_stats->xmlChildrenNode);
+        fflush(where);
+      }
+    }
+    if (stats == NULL) {
+      test->state  = TEST_ERROR;
+      test->err_rc = NPE_SYS_STATS_DROPPED;
+      test->err_fn = (char *)__func__;
+    }
+  }
+  return(rc);
+}
+
+int
+test_stats_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int          rc = NPE_SUCCESS;
+  xmlChar     *testid;
+  test_t      *test;
+  xmlNodePtr  stats = NULL;
+
+
+  testid = xmlGetProp(msg,(const xmlChar *)"tid");
+  test   = find_test_in_hash(testid);
+  if (test != NULL) {
+    if (debug) {
+      fprintf(where,"test_stats_message: test_state = %d\n",test->state);
+      fflush(where);
+    }
+    if (test->received_stats == NULL) {
+      test->received_stats = xmlNewNode(NULL,(xmlChar *)"received_stats");
+    }
+    if (test->received_stats) {
+      stats = xmlCopyNode(msg,1);
+      xmlAddChild(test->received_stats, stats);
+    }
+    if (stats == NULL) {
+      test->state  = TEST_ERROR;
+      test->err_rc = NPE_TEST_STATS_DROPPED;
+      test->err_fn = (char *)__func__;
+    }
+  }
+  return(rc);
+}
+
+
+int
+unknown_message(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server)
+{
+  int rc = NPE_SUCCESS;
+
+
+  fprintf(where,"Server %s sent a %s message which is unknown by netperf4\n",
+          server->id, msg->name);
+  fflush(where);
+  return(rc);
+}
+
 /* signal handler for new message */
 static void netperf_netserver_new_message(NetperfNetserver *netserver, gpointer message)
 {

Modified: branches/gobject_migration/src/netperf-netserver.h
===================================================================
--- branches/gobject_migration/src/netperf-netserver.h	2007-03-03 01:06:36 UTC (rev 203)
+++ branches/gobject_migration/src/netperf-netserver.h	2007-03-07 02:13:04 UTC (rev 204)
@@ -3,6 +3,10 @@
 
 #include <glib-object.h>
 
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
 /* declarations to provide us with a Netserver object to be used by
    netperf4's GObject conversion */
 
@@ -17,10 +21,23 @@
   NETSERVER_EXIT
 } netserver_state_t;
 
+/* state machine data structure for process message */
+
+typedef struct _NetperfNetserver NetperfNetserver;
+typedef struct _NetperfNetserverClass NetperfNetserverClass;
+
+typedef int (*netperf_msg_func_t)(xmlNodePtr msg, xmlDocPtr doc, NetperfNetserver *server);
+
+struct netperf_msgs {
+  char *msg_name;
+  netperf_msg_func_t msg_func;
+  unsigned int valid_states;
+};
+
 /* first the instance structure. this will look remarkably like the
    old netserver_t structure. */
 
-typedef struct _NetperfNetserver {
+struct _NetperfNetserver {
   /* the parent object - in this case a GObject object */
   GObject parent_instance;
 
@@ -51,14 +68,24 @@
   char        *err_fn;   /* name of the routine which placed this
 			    server into the NETSERVER_ERROR state*/
 
+  struct netperf_msgs *message_state_table; /* a pointer to the table
+					      of the various messages,
+					      the routine to call and
+					      the states in which
+					      that message is
+					      valid. there will be one
+					      main one for a netperf
+					      and one for a netserver
+					      */
+
   /* do we need to have references to the test instances associated
      with this netserver instance? */
-} NetperfNetserver;
+};
 
 /* second, the class structure, which is where we will put any method
    functions we wish to have and any signals we wish to define */
 
-typedef struct _NetperfNetserverClass {
+struct _NetperfNetserverClass {
   /* the parent class, matching what we do with the instance */
   GObjectClass parent_class;
 
@@ -67,7 +94,7 @@
   void (*control_closed)(NetperfNetserver *netserver);
 
   /* methods */
-} NetperfNetserverClass;
+};
 
 
 GType netperf_netserver_get_type (void);



More information about the netperf-dev mailing list