Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Document the token ring example
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 26 Apr 2006 16:37:55 +0000 (16:37 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 26 Apr 2006 16:37:55 +0000 (16:37 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2190 48e7efb5-ca39-0410-a469-dd3cf9ba447f

doc/module-gras.doc
examples/gras/tokenS/tokenS.c
examples/gras/tokenS/tokenS_deployment.xml

index f2451f0..5c3d672 100644 (file)
@@ -51,6 +51,7 @@
     
        - \ref GRAS_ex_ping
        - \ref GRAS_ex_mmrpc
+       - \ref GRAS_ex_token
        - \ref GRAS_ex_timer
 
     @{ */
 
        - \ref GRAS_ex_ping
        - \ref GRAS_ex_mmrpc
+       - \ref GRAS_ex_token
        - \ref GRAS_ex_timer
 
     \htmlonly <!-- 
       DOXYGEN_NAVBAR_CHILD "Ping-Pong"=GRAS_ex_ping.html
       DOXYGEN_NAVBAR_CHILD "RPC"=GRAS_ex_mmrpc.html
+      DOXYGEN_NAVBAR_CHILD "Token Ring"=GRAS_ex_token.html
       DOXYGEN_NAVBAR_CHILD "Timers"=GRAS_ex_timer.html
     --> \endhtmlonly
 
     [Back to \ref GRAS_ex_ping_toc]
  */
 
+---------------------------------------------------------------------
+--------------------- Simple Token Ring -----------------------------
+---------------------------------------------------------------------
+
+/** \page GRAS_ex_token Token Ring example
+
+   This example implements the token ring algorithm. It involves several
+   nodes arranged in a ring (each of them have a left and a right neighbour)
+   and exchanging a "token". This algorithm is one of the solution to ensure
+   the mutual exclusion between distributed processes. There is only one
+   token at any time, so the process in its possession is ensured to be the
+   only one having it. So, if there is an action you want all processes to
+   do alternativly, but you cannot afford to have two processes doing it at
+   the same time, let the process having the token doing it.
+   
+   Actually, there is a lot of different token ring algorithms in the
+   litterature, so this example implements one of them: the simplest one.
+   The ring is static (no new node can join it, and you'll get trouble if
+   one node dies or leaves), and nothing is done for the case in which the
+   token is lost. 
+
+   - \ref GRAS_ex_stoken_deploy
+   - \ref GRAS_ex_stoken_global
+   - \ref GRAS_ex_stoken_callback
+   - \ref GRAS_ex_stoken_main
+
+   \section GRAS_ex_stoken_deploy 1) Deployment file
+
+   Here is the deployment file:
+   \include examples/gras/tokenS/tokenS_deployment.xml
+   
+   The neighbour of each node is given at startup as command line argument.
+   Moreover, one of the nodes is instructed by a specific argument (the one
+   on Tremblay here) to create the token at the begining of the algorithm.
+   
+   \section GRAS_ex_stoken_global 2) Global definition
+   
+   The token is incarned by a specific message, which circulates from node
+   to node (the payload is an integer incremented at each hop). So, the most
+   important part of the code is the message callback, which forwards the
+   message to the next node. That is why we have to store all variable in a
+   global, as explained in the \ref GRAS_globals section. 
+
+   \dontinclude examples/gras/tokenS/tokenS.c
+   \skip typedef
+   \until }
+   
+   \section GRAS_ex_stoken_callback 3) The callback
+   
+   Even if this is the core of this algorithm, this function is quite
+   straightforward.
+   
+   \skip node_cb_stoken_handler
+   \until end_of_node_cb_stoken_handler
+
+   \section GRAS_ex_stoken_main 4) The main function
+   
+   This function is splited in two parts: The first one performs all the
+   needed initialisations (points 1-7) while the end (point 8. below) calls 
+   gras_msg_handle() as long as the planned amount of ring loops are not
+   performed.
+   
+   \skip node
+   \until end_of_node
+
+*/
+
 ---------------------------------------------------------------------
 -------------------------- MM RPC -----------------------------------
 ---------------------------------------------------------------------
index aafde91..de1399d 100644 (file)
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(Token,"Messages specific to this example");
 
-/* register messages which may be sent */
-static void register_messages(void) {
-  gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
-}
-
 /* Function prototypes */
 int node (int argc,char *argv[]);
 
@@ -32,9 +27,9 @@ int node (int argc,char *argv[]);
 /* Global private data */
 typedef struct {
   gras_socket_t sock; /* server socket on which I hear */
-  int remaining_loop; /* loop to do until done */
-  int create;        /* I have to create the token */
-  gras_socket_t tosuccessor; /* how to connect to next peer on ring */
+  int remaining_loop; /* number of loops to do until done */
+  int create;        /* whether I have to create the token */
+  gras_socket_t tosuccessor; /* how to connect to the successor on ring */
 } node_data_t;
 
 
@@ -52,7 +47,7 @@ static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
   node_data_t *globals=(node_data_t*)gras_userdata_get();
  
   /* 3. Log which predecessor connected */
-  int supersteps = 1;
+  int supersteps = 1; /* only log every superstep loop */
   if (NBLOOPS >= 1000) {
     supersteps = 100;
   } else if (NBLOOPS >= 100) {
@@ -67,23 +62,20 @@ static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
          msg, gras_socket_peer_name(expeditor),globals->remaining_loop);
   }
   
+  /* 4. If the right shouldn't be stopped yet */
   if (globals->remaining_loop > 0) {
-     
     msg += 1;
      
-    /* 5. I forward it to my successor */
-    DEBUG3("Send token(%d) to %s:%d",
-          msg, 
+    DEBUG3("Send token(%d) to %s:%d", msg, 
           gras_socket_peer_name(globals->tosuccessor),
           gras_socket_peer_port(globals->tosuccessor));
      
-     
-    /* 6. Send it as payload of a stoken message to the successor */
+    /* 5. Send the token as payload of a stoken message to the successor */
     TRY {
       gras_msg_send(globals->tosuccessor, 
                    gras_msgtype_by_name("stoken"), &msg);
      
-    /* 7. Deal with errors */
+    /* 6. Deal with errors */
     } CATCH(e) {
       gras_socket_close(globals->sock);
       RETHROW0("Unable to forward token: %s");
@@ -95,19 +87,18 @@ static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
      reused by our predecessor.
      Closing this side would thus create troubles */
   
-  /* 8. Decrease the remaining_loop integer. */
+  /* 7. Decrease the remaining_loop integer. */
   globals->remaining_loop -= 1;
    
-  /* 9. Repport the hop number to the user at the end */
+  /* 8. Repport the hop number to the user at the end */
   if (globals->remaining_loop == -1 && globals->create) {
     INFO1("Shut down the token-ring. There was %d hops.",msg);
   }
 
-  /* 10. Tell GRAS that we consummed this message */
+  /* 9. Tell GRAS that we consummed this message */
   return 1;
 } /* end_of_node_cb_stoken_handler */
 
-
 int node (int argc,char *argv[]) {
   node_data_t *globals;
   
@@ -151,15 +142,11 @@ int node (int argc,char *argv[]) {
 
   globals->tosuccessor = gras_socket_client(host,peerport);
   
-  /* 6. Register the known messages. This function is called twice here,
-        but it's because this file also acts as regression test.
-        No need to do so yourself of course. */
-  register_messages();
-  register_messages(); /* just to make sure it works ;) */
+  /* 6. Register the known messages.  */
+  gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
    
   /* 7. Register my callback */
-  gras_cb_register(gras_msgtype_by_name("stoken"),&node_cb_stoken_handler);
-  
+  gras_cb_register(gras_msgtype_by_name("stoken"),&node_cb_stoken_handler);  
 
   /* 8. One node has to create the token at startup. 
         It's specified by a command line argument */
index f144324..01f9538 100644 (file)
@@ -1,36 +1,30 @@
-<?xml version='1.0'?>
-<!DOCTYPE platform_description SYSTEM "surfxml.dtd">
+<?xml version='1.0'?><!DOCTYPE platform_description SYSTEM "surfxml.dtd">
 <platform_description>
 
  <process host="Tremblay" function="node">
-    <argument value="4000"/>     <!-- port on which I am listening -->
-    <argument value="Fafard"/>   <!-- peer (successor) host -->
-    <argument value="4000"/>     <!-- port on which peer is listening -->
-    <argument value="--create-token"/>   <!-- I'm first client, ie I have to create the token -->
+  <argument value="4000"/>                           <!-- port on which I am listening -->
+  <argument value="Fafard"/><argument value="4000"/> <!-- peer (successor) host name and port-->
+  <argument value="--create-token"/>                 <!-- I'm first client, ie I have to create the token -->
  </process>
  
  <process host="Fafard" function="node">
-    <argument value="4000"/>      <!-- port on which I am listening -->
-    <argument value="Jupiter"/>   <!-- peer (successor) host -->
-    <argument value="4000"/>      <!-- port on which peer is listening -->
+  <argument value="4000"/>                           <!-- port on which I am listening -->
+  <argument value="Jupiter"/><argument value="4000"/><!-- peer (successor) host name and port-->
  </process>
  
  <process host="Jupiter" function="node">
-    <argument value="4000"/>      <!-- port on which I am listening -->
-    <argument value="Ginette"/>   <!-- peer (successor) host -->
-    <argument value="4000"/>      <!-- port on which peer is listening -->
+  <argument value="4000"/>                            <!-- port on which I am listening -->
+  <argument value="Ginette"/><argument value="4000"/> <!-- peer (successor) host name and port-->
  </process>
  
  <process host="Ginette" function="node">
-    <argument value="4000"/>      <!-- port on which I am listening -->
-    <argument value="Bourassa"/>  <!-- peer (successor) host -->
-    <argument value="4000"/>      <!-- port on which peer is listening -->
+  <argument value="4000"/>                            <!-- port on which I am listening -->
+  <argument value="Bourassa"/><argument value="4000"/><!-- peer (successor) host name and port-->
  </process>
  
  <process host="Bourassa" function="node">
-    <argument value="4000"/>      <!-- port on which I am listening -->
-    <argument value="Tremblay"/>  <!-- peer (successor) host -->
-    <argument value="4000"/>      <!-- port on which peer is listening -->
+  <argument value="4000"/>                            <!-- port on which I am listening -->
+  <argument value="Tremblay"/><argument value="4000"/><!-- peer (successor) host name and port-->
  </process>
  
 </platform_description>