Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Only output the elapsed time at verbose level, so that we don't see it during make...
[simgrid.git] / examples / gras / mutual_exclusion / simple_token / simple_token.c
1 /* $Id$ */
2
3 /* stoken - simple/static token ring                                        */
4
5 /* Copyright (c) 2005 Alexandre Colucci.                                    */
6 /* Copyright (c) 2005 Martin Quinson.                                       */
7 /* All rights reserved.                                                     */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11  
12 #include "gras.h"
13  
14 #define NBLOOPS 3
15 /*#define NBLOOPS 30000*/
16
17 XBT_LOG_NEW_DEFAULT_CATEGORY(SimpleToken,"Messages specific to this example");
18
19 /* Function prototypes */
20 int node (int argc,char *argv[]);
21
22
23 /* **********************************************************************
24  * Node code
25  * **********************************************************************/
26
27 /* Global private data */
28 typedef struct {
29   gras_socket_t sock; /* server socket on which I hear */
30   int remaining_loop; /* number of loops to do until done */
31   int create;         /* whether I have to create the token */
32   gras_socket_t tosuccessor; /* how to connect to the successor on ring */
33   double start_time; /* to measure the elapsed time. Only used by the 
34                          node that creates the token */
35 } node_data_t;
36
37
38 /* Callback function */
39 static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
40   
41   xbt_ex_t e;
42   
43   /* 1. Get the payload into the msg variable, and retrieve my caller */
44   int msg=*(int*)payload;
45   gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
46
47
48   /* 2. Retrieve the node's state (globals) */
49   node_data_t *globals=(node_data_t*)gras_userdata_get();
50  
51   /* 3. Log which predecessor connected */
52   int supersteps = 1; /* only log every superstep loop */
53   if (NBLOOPS >= 1000) {
54     supersteps = 100;
55   } else if (NBLOOPS >= 100) {
56     supersteps = 10;
57   } else if (NBLOOPS <=10) {
58     supersteps = 1;
59   }
60   if (globals->create && (! (globals->remaining_loop % supersteps))) {
61     INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
62   } else if (! (globals->remaining_loop % supersteps)) {
63     VERB3("Got token(%d) from %s remaining_loop=%d", 
64           msg, gras_socket_peer_name(expeditor),globals->remaining_loop);
65   }
66   
67   /* 4. If the right shouldn't be stopped yet */
68   if (globals->remaining_loop > 0) {
69     msg += 1;
70      
71     DEBUG3("Send token(%d) to %s:%d", msg, 
72            gras_socket_peer_name(globals->tosuccessor),
73            gras_socket_peer_port(globals->tosuccessor));
74      
75     /* 5. Send the token as payload of a stoken message to the successor */
76     TRY {
77       gras_msg_send(globals->tosuccessor, "stoken", &msg);
78      
79     /* 6. Deal with errors */
80     } CATCH(e) {
81       gras_socket_close(globals->sock);
82       RETHROW0("Unable to forward token: %s");
83     }
84   
85   }
86               
87   /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
88      reused by our predecessor.
89      Closing this side would thus create troubles */
90   
91   /* 7. Decrease the remaining_loop integer. */
92   globals->remaining_loop -= 1;
93    
94   /* 8. Repport the hop number to the user at the end */
95   if (globals->remaining_loop == -1 && globals->create) {
96     double elapsed = gras_os_time() - globals->start_time; 
97     INFO1("Shut down the token-ring. There was %d hops.",msg);
98     VERB1("Elapsed time: %g", elapsed);
99   }
100
101   /* 9. Tell GRAS that we consummed this message */
102   return 0;
103 } /* end_of_node_cb_stoken_handler */
104
105 int node (int argc,char *argv[]) {
106   node_data_t *globals;
107   
108   const char *host;
109   int   myport;
110   int   peerport;
111     
112   xbt_ex_t e;
113   
114   /* 1. Init the GRAS infrastructure and declare my globals */
115   gras_init(&argc,argv);
116   globals=gras_userdata_new(node_data_t);
117   
118   
119   /* 2. Get the successor's address. The command line overrides
120         defaults when specified */
121   host = "127.0.0.1";
122   myport = 4000;
123   peerport = 4000;
124   if (argc >= 4) {
125     myport=atoi(argv[1]);
126     host=argv[2];
127     peerport=atoi(argv[3]);
128   }
129
130   /* 3. Save successor's address in global var */
131   globals->remaining_loop=NBLOOPS;
132   globals->create = 0;
133   globals->tosuccessor = NULL;
134
135   if (!gras_os_getpid() % 100)
136   INFO4("Launch node %d (successor on %s:%d; listening on %d)",
137         gras_os_getpid(), host,peerport, myport);
138
139   /* 4. Register the known messages.  */
140   gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
141    
142   /* 5. Create my master socket for listening */
143   globals->sock = gras_socket_server(myport);
144   gras_os_sleep(1.0); /* Make sure all server sockets are created */
145    
146   /* 6. Create socket to the successor on the ring */
147   DEBUG2("Connect to my successor on %s:%d",host,peerport);
148
149   globals->tosuccessor = gras_socket_client(host,peerport);
150   
151   /* 7. Register my callback */
152   gras_cb_register("stoken",&node_cb_stoken_handler);  
153
154   /* 8. One node has to create the token at startup. 
155         It's specified by a command line argument */
156   if (argc >= 5 && !strncmp("--create-token", argv[4],strlen("--create-token")))
157     globals->create=1;
158
159   if (globals->create) {
160     int token = 0;
161
162     globals->start_time = gras_os_time();
163
164     globals->remaining_loop = NBLOOPS - 1;
165       
166     INFO3("Create the token (with value %d) and send it to %s:%d",
167           token, host, peerport);
168
169     TRY {         
170       gras_msg_send(globals->tosuccessor, "stoken", &token);
171     } CATCH(e) {
172       RETHROW0("Unable to send the freshly created token: %s");
173     }
174   } 
175   
176   /* 8. Wait up to 10 seconds for an incomming message to handle */
177   while (globals->remaining_loop > (globals->create ? -1 : 0)) {
178     gras_msg_handle(10.0);
179   
180     DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
181   }
182
183   gras_os_sleep(1.0); /* FIXME: if the sender quited, receive fail */
184
185   /* 9. Free the allocated resources, and shut GRAS down */ 
186   gras_socket_close(globals->sock);
187   gras_socket_close(globals->tosuccessor);
188   free(globals);
189   gras_exit();
190   
191   return 0;
192 } /* end_of_node */