Logo AND Algorithmique Numérique Distribuée

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