Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
processes are now started in file order
[simgrid.git] / examples / gras / tokenS / tokenS.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(Token,"Messages specific to this example");
18
19 /* register messages which may be sent */
20 static void register_messages(void) {
21   gras_msgtype_declare("stoken", gras_datadesc_by_name("int"));
22 }
23
24 /* Function prototypes */
25 int node (int argc,char *argv[]);
26
27
28 /* **********************************************************************
29  * Node code
30  * **********************************************************************/
31
32 /* Global private data */
33 typedef struct {
34   gras_socket_t sock; /* server socket on which I hear */
35   int remaining_loop; /* loop to do until done */
36   int create;         /* I have to create the token */
37   gras_socket_t tosuccessor; /* how to connect to next peer on ring */
38 } node_data_t;
39
40
41 /* Callback function */
42 static int node_cb_stoken_handler(gras_msg_cb_ctx_t ctx, void *payload) {
43   
44   xbt_ex_t e;
45   
46   /* 1. Get the payload into the msg variable, and retrieve my caller */
47   int msg=*(int*)payload;
48   gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
49
50
51   /* 2. Retrieve the node's state (globals) */
52   node_data_t *globals=(node_data_t*)gras_userdata_get();
53  
54   /* 3. Log which predecessor connected */
55   int supersteps = 1;
56   if (NBLOOPS >= 1000) {
57     supersteps = 100;
58   } else if (NBLOOPS >= 100) {
59     supersteps = 10;
60   } else if (NBLOOPS <=10) {
61     supersteps = 1;
62   }
63   if (globals->create && (! (globals->remaining_loop % supersteps))) {
64     INFO1("Begin a new loop. Still to do: %d", globals->remaining_loop);
65   } else if (! (globals->remaining_loop % supersteps)) {
66     VERB3("Got token(%d) from %s remaining_loop=%d", 
67           msg, gras_socket_peer_name(expeditor),globals->remaining_loop);
68   }
69   
70   if (globals->remaining_loop > 0) {
71      
72     msg += 1;
73      
74     /* 5. I forward it to my successor */
75     DEBUG3("Send token(%d) to %s:%d",
76            msg, 
77            gras_socket_peer_name(globals->tosuccessor),
78            gras_socket_peer_port(globals->tosuccessor));
79      
80      
81     /* 6. Send it as payload of a stoken message to the successor */
82     TRY {
83       gras_msg_send(globals->tosuccessor, 
84                     gras_msgtype_by_name("stoken"), &msg);
85      
86     /* 7. Deal with errors */
87     } CATCH(e) {
88       gras_socket_close(globals->sock);
89       RETHROW0("Unable to forward token: %s");
90     }
91   
92   }
93               
94   /* DO NOT CLOSE THE expeditor SOCKET since the client socket is
95      reused by our predecessor.
96      Closing this side would thus create troubles */
97   
98   /* 8. Decrease the remaining_loop integer. */
99   globals->remaining_loop -= 1;
100    
101   /* 9. Repport the hop number to the user at the end */
102   if (globals->remaining_loop == -1 && globals->create) {
103     INFO1("Shut down the token-ring. There was %d hops.",msg);
104   }
105
106   /* 10. Tell GRAS that we consummed this message */
107   return 1;
108 } /* end_of_node_cb_stoken_handler */
109
110
111 int node (int argc,char *argv[]) {
112   node_data_t *globals;
113   
114   const char *host;
115   int   myport;
116   int   peerport;
117     
118   xbt_ex_t e;
119   
120   /* 1. Init the GRAS infrastructure and declare my globals */
121   gras_init(&argc,argv);
122   globals=gras_userdata_new(node_data_t);
123   
124   
125   /* 2. Get the successor's address. The command line overrides
126         defaults when specified */
127   host = "127.0.0.1";
128   myport = 4000;
129   peerport = 4000;
130   if (argc >= 4) {
131     myport=atoi(argv[1]);
132     host=argv[2];
133     peerport=atoi(argv[3]);
134   }
135
136   /* 3. Save successor's address in global var */
137   globals->remaining_loop=NBLOOPS;
138   globals->create = 0;
139   globals->tosuccessor = NULL;
140
141   if (!gras_os_getpid() % 100)
142   INFO4("Launch node %d (successor on %s:%d; listening on %d)",
143         gras_os_getpid(), host,peerport, myport);
144
145   /* 4. Create my master socket for listening */
146   globals->sock = gras_socket_server(myport);
147   gras_os_sleep(1.0); /* Make sure all server sockets are created */
148
149   /* 5. Create socket to the successor on the ring */
150   DEBUG2("Connect to my successor on %s:%d",host,peerport);
151
152   globals->tosuccessor = gras_socket_client(host,peerport);
153   
154   /* 6. Register the known messages. This function is called twice here,
155         but it's because this file also acts as regression test.
156         No need to do so yourself of course. */
157   register_messages();
158   register_messages(); /* just to make sure it works ;) */
159    
160   /* 7. Register my callback */
161   gras_cb_register(gras_msgtype_by_name("stoken"),&node_cb_stoken_handler);
162   
163
164   /* 8. One node has to create the token at startup. 
165         It's specified by a command line argument */
166   if (argc >= 5 && !strncmp("--create-token", argv[4],strlen(argv[4])))
167     globals->create=1;
168
169   if (globals->create) {
170     int token = 0;
171             
172     globals->remaining_loop = NBLOOPS - 1;
173       
174     INFO3("Create the token (with value %d) and send it to %s:%d",
175           token, host, peerport);
176
177     TRY {         
178       gras_msg_send(globals->tosuccessor,
179                   gras_msgtype_by_name("stoken"), &token);
180     } CATCH(e) {
181       RETHROW0("Unable to send the freshly created token: %s");
182     }
183   } 
184   
185   /* 8. Wait up to 10 seconds for an incomming message to handle */
186   while (globals->remaining_loop > (globals->create ? -1 : 0)) {
187     gras_msg_handle(10.0);
188   
189     DEBUG1("looping (remaining_loop=%d)", globals->remaining_loop);
190   }
191
192   gras_os_sleep(1.0); /* FIXME: if the sender quited, receive fail */
193
194   /* 9. Free the allocated resources, and shut GRAS down */ 
195   gras_socket_close(globals->sock);
196   gras_socket_close(globals->tosuccessor);
197   free(globals);
198   gras_exit();
199   
200   return 0;
201 } /* end_of_node */