Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
First pass of cleanup so that it compiles with paranoid compiler flags
[simgrid.git] / examples / gras / p2p / can / can.c
1 /*////////////////////////////////////////////////////*/
2 // Peer-To-Peer CAN simulator 050406 by Dytto ESIAL //
3 //////////////////////////////////////////////////////
4
5
6 #include "xbt/sysdep.h"
7 #include "gras.h"
8
9 #include "can_tests.c"                                                
10 //#include "types.h" // header alone containing the typedef struct of a node // include can_tests.c must be OFF.
11
12 //XBT_LOG_NEW_DEFAULT_CATEGORY(can,"Messages specific to this example"); // include can_tests.c must be OFF.
13
14 //extern char *_gras_this_type_symbol_does_not_exist__s_nuke;
15 int node_nuke_handler(gras_msg_cb_ctx_t ctx,void *payload_data);
16
17 // struct of a "get_successor" message, when a node look after the area in which he want to be.
18 GRAS_DEFINE_TYPE(s_get_suc,
19         struct s_get_suc{
20                 int xId;
21                 int yId;
22                 char host[1024];
23                 int port;       
24         };
25 );
26 typedef struct s_get_suc get_suc_t;
27
28 // struct of a "response_successor" message, hen a node receive the information of his new area.
29 GRAS_DEFINE_TYPE(s_rep_suc,
30         struct s_rep_suc{
31                 int x1; // Xmin
32                 int x2; // Xmax
33                 int y1; // Ymin
34                 int y2; // Ymax
35
36                 char north_host[1024];
37                 int north_port;
38                 char south_host[1024];
39                 int south_port;
40                 char east_host[1024];
41                 int east_port;
42                 char west_host[1024];
43                 int west_port;
44         };
45 );
46 typedef struct s_rep_suc rep_suc_t;
47
48 int node(int argc,char **argv);
49
50 // registering messages types
51 static void register_messages(){
52         gras_msgtype_declare("can_get_suc",gras_datadesc_by_symbol(s_get_suc));
53         gras_msgtype_declare("can_rep_suc",gras_datadesc_by_symbol(s_rep_suc));
54         gras_msgtype_declare("can_nuke",gras_datadesc_by_symbol(s_nuke));// can_test.c message // include can_tests.c must be ON.
55 }
56
57
58 // a forwarding function for a "get_suc" message.
59 static void forward_get_suc(get_suc_t msg, char host[1024], int port){
60         gras_socket_t temp_sock=NULL;
61         xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
62         //INFO2("Transmiting message to %s:%d",host,port);      
63         TRY{
64                 temp_sock=gras_socket_client(host,port);
65         }CATCH(e){
66                 RETHROW0("Unable to connect!: %s");
67         }
68         TRY{
69                 gras_msg_send(temp_sock,gras_msgtype_by_name("can_get_suc"),&msg);
70         }CATCH(e){
71                 RETHROW0("Unable to send!: %s");
72         }
73         INFO3("Forwarding a get_successor message to %s for (%d;%d)",host,msg.xId,msg.yId);
74         gras_socket_close(temp_sock);
75 }
76
77 // the handling function of a "get_suc" message (what do a node when he receive a "get_suc" message.
78 static int node_get_suc_handler(gras_msg_cb_ctx_t ctx,void *payload_data){
79         gras_socket_t expeditor=gras_msg_cb_ctx_from(ctx);
80         get_suc_t *incoming=(get_suc_t*)payload_data;
81         xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
82         node_data_t *globals=(node_data_t*)gras_userdata_get();
83
84         INFO3("Received a get_successor message from %s for (%d;%d)",gras_socket_peer_name(expeditor),incoming->xId,incoming->yId);
85         //INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
86         if(incoming->xId<globals->x1) // test if the message must be forwarded to a neighbour.
87                 forward_get_suc(*incoming, globals->west_host, globals->west_port);
88         else if(incoming->xId>globals->x2)
89                 forward_get_suc(*incoming, globals->east_host, globals->east_port);
90         else if(incoming->yId<globals->y1)
91                 forward_get_suc(*incoming, globals->south_host, globals->south_port);
92         else if(incoming->yId>globals->y2)
93                 forward_get_suc(*incoming, globals->north_host, globals->north_port);
94         else{ // if the message must not be forwarded, then the area is splitted in half and one half is assignated to the new node.
95                 rep_suc_t outgoing;
96                 int validate=0;
97                 INFO4("Spliting my area between me (%d;%d) and the inserting node (%d;%d)!",
98                       globals->xId,globals->yId,incoming->xId,incoming->yId);
99                 if((globals->x2-globals->x1)>(globals->y2-globals->y1)){ // the height of the area is smaller than its width.
100                   if(incoming->xId<globals->xId){ // the new node is west from the actual node.
101                         outgoing.x1=globals->x1;
102                         outgoing.x2=(incoming->xId+globals->xId)/2;
103                         outgoing.y1=globals->y1;
104                         outgoing.y2=globals->y2;
105                         strcpy(outgoing.north_host,globals->north_host);
106                         outgoing.north_port=globals->north_port;
107                         strcpy(outgoing.south_host,globals->south_host);
108                         outgoing.south_port=globals->south_port;
109                         strcpy(outgoing.east_host,globals->host);
110                         outgoing.east_port=globals->port;
111                         strcpy(outgoing.west_host,globals->west_host);
112                         outgoing.west_port=globals->west_port;
113
114                         globals->x1=(incoming->xId+globals->xId)/2;
115                         strcpy(globals->west_host,incoming->host);
116                         globals->west_port=incoming->port;
117                         validate=1;
118                   }
119                   else if(incoming->xId>globals->xId){ // the new node is east from the actual node.
120                         outgoing.x1=(incoming->xId+globals->xId)/2;
121                         outgoing.x2=globals->x2;
122                         outgoing.y1=globals->y1;
123                         outgoing.y2=globals->y2;
124                         strcpy(outgoing.north_host,globals->north_host);
125                         outgoing.north_port=globals->north_port;
126                         strcpy(outgoing.south_host,globals->south_host);
127                         outgoing.south_port=globals->south_port;
128                         strcpy(outgoing.east_host,globals->east_host);
129                         outgoing.east_port=globals->east_port;
130                         strcpy(outgoing.west_host,globals->host);
131                         outgoing.west_port=globals->port;
132
133                         globals->x2=(incoming->xId+globals->xId)/2;
134                         strcpy(globals->east_host,incoming->host);
135                         globals->east_port=incoming->port;
136                         validate=1;                     
137                   }
138                 }
139                 else{
140                    if(incoming->yId<globals->yId){ // the new node is south from the actual node.
141                         outgoing.y1=globals->y1;
142                         outgoing.y2=(incoming->yId+globals->yId)/2;
143                         outgoing.y1=globals->y1;
144                         outgoing.x2=globals->x2;
145                         strcpy(outgoing.east_host,globals->east_host);
146                         outgoing.east_port=globals->east_port;
147                         strcpy(outgoing.west_host,globals->west_host);
148                         outgoing.west_port=globals->west_port;
149                         strcpy(outgoing.north_host,globals->host);
150                         outgoing.north_port=globals->port;
151                         strcpy(outgoing.south_host,globals->south_host);
152                         outgoing.south_port=globals->south_port;
153
154                         globals->y1=(incoming->yId+globals->yId)/2;
155                         strcpy(globals->south_host,incoming->host);
156                         globals->south_port=incoming->port;
157                         validate=1;                     
158                    }
159                    else if(incoming->yId>globals->yId){ // the new node is north from the actual node.
160                         outgoing.y1=(incoming->yId+globals->yId)/2;
161                         outgoing.y2=globals->y2;
162                         outgoing.x1=globals->x1;
163                         outgoing.x2=globals->x2;
164                         strcpy(outgoing.east_host,globals->east_host);
165                         outgoing.east_port=globals->east_port;
166                         strcpy(outgoing.west_host,globals->west_host);
167                         outgoing.west_port=globals->west_port;
168                         strcpy(outgoing.north_host,globals->north_host);
169                         outgoing.north_port=globals->north_port;
170                         strcpy(outgoing.south_host,globals->host);
171                         outgoing.south_port=globals->port;
172
173                         globals->y2=(incoming->yId+globals->yId)/2;
174                         strcpy(globals->north_host,incoming->host);
175                         globals->north_port=incoming->port;
176                         validate=1;                     
177                    }
178                 }
179                 if(validate==1){ // the area for the new node has been defined, then send theses informations to the new node.
180                         INFO2("Sending environment informations to node %s:%d",incoming->host,incoming->port);
181                         gras_socket_t temp_sock=NULL;   
182                         TRY{
183                                 temp_sock=gras_socket_client(incoming->host,incoming->port);
184                         }CATCH(e){
185                                 RETHROW0("Unable to connect to the node wich has requested for an area!: %s");
186                         }
187                         TRY{
188                                 gras_msg_send(temp_sock,gras_msgtype_by_name("can_rep_suc"),&outgoing);
189                                 INFO0("Environment informations sent!");
190                         }CATCH(e){
191                                 RETHROW2("%s:Timeout sending environment informations to %s: %s",globals->host,gras_socket_peer_name(expeditor));
192                         }
193                         gras_socket_close(temp_sock);
194                 }
195                 else // we have a problem!
196                         INFO0("An error occurded!!!!!!!!!!!!!");
197
198         }
199         gras_socket_close(expeditor); // spare
200         TRY{
201           gras_msg_handle(10000.0); // wait a bit in case of someone want to ask me for something.
202         }CATCH(e){
203         INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
204           //INFO0("Closing node, all has been done!");
205         }
206    return 1;
207 }
208
209
210
211
212
213 int node(int argc,char **argv){
214         node_data_t *globals=NULL;
215         xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
216
217         INFO0("Starting");
218
219         /* 1. Init the GRAS infrastructure and declare my globals */
220         gras_init(&argc,argv);
221         gras_os_sleep((15-gras_os_getpid())*20); // wait a bit.
222         
223         globals=gras_userdata_new(node_data_t);
224
225         globals->xId=atoi(argv[1]); // x coordinate of the node.
226         globals->yId=atoi(argv[2]); // y coordinate of the node.
227         globals->port=atoi(argv[3]); // node port
228         globals->sock=gras_socket_server(globals->port); // node socket.
229         snprintf(globals->host,1024,gras_os_myname()); // node name.
230         globals->version=0; // node version (used for fun)
231
232         /* 2. Inserting the Node */
233         INFO2("Inserting node %s:%d",globals->host,globals->port);
234         if(argc==4){ // the node is a server, then he has the whole area.
235                 globals->x1=0;
236                 globals->x2=1000;
237                 globals->y1=0;
238                 globals->y2=1000;
239         }else{ // asking for an area.
240                 INFO1("Contacting %s so as to request for an area",argv[4]);
241                 gras_socket_t temp_sock=NULL;
242                 TRY{
243                         temp_sock=gras_socket_client(argv[4],atoi(argv[5]));
244                 }CATCH(e){
245                         RETHROW0("Unable to connect known host to request for an area!: %s");
246                 }
247
248                 get_suc_t get_suc_msg; // building the "get_suc" message.
249                 get_suc_msg.xId=globals->xId;
250                 get_suc_msg.yId=globals->yId;
251                 strcpy(get_suc_msg.host,globals->host);
252                 get_suc_msg.port=globals->port;
253                 TRY{ // asking.
254                         gras_msg_send(temp_sock,gras_msgtype_by_name("can_get_suc"),&get_suc_msg);
255                 }CATCH(e){
256                         gras_socket_close(temp_sock);
257                         RETHROW0("Unable to contact known host to get an area!: %s");
258                 }
259                 gras_socket_close(temp_sock);
260
261                 rep_suc_t rep_suc_msg;
262                 gras_socket_t temp_sock2=NULL;
263                 TRY{ // waiting for a reply.
264                         INFO0("Waiting for reply!");
265                         gras_msg_wait(6000,gras_msgtype_by_name("can_rep_suc"),&temp_sock2,&rep_suc_msg);
266                 }CATCH(e){
267                         RETHROW1("%s: Error waiting for an area:%s",globals->host);
268                 }
269
270                 // retreiving the data of the response.
271                 globals->x1=rep_suc_msg.x1;
272                 globals->x2=rep_suc_msg.x2;
273                 globals->y1=rep_suc_msg.y1;
274                 globals->y2=rep_suc_msg.y2;
275                 strcpy(globals->north_host,rep_suc_msg.north_host);
276                 globals->north_port=rep_suc_msg.north_port;
277                 strcpy(globals->south_host,rep_suc_msg.south_host);
278                 globals->south_port=rep_suc_msg.south_port;
279                 strcpy(globals->east_host,rep_suc_msg.east_host);
280                 globals->east_port=rep_suc_msg.east_port;
281                 strcpy(globals->west_host,rep_suc_msg.west_host);
282                 globals->west_port=rep_suc_msg.west_port;
283
284                 gras_socket_close(temp_sock); // spare
285         }
286         INFO2("Node %s:%d inserted",globals->host,globals->port);
287
288         // associating messages to handlers.
289         register_messages();
290         gras_cb_register(gras_msgtype_by_name("can_get_suc"),&node_get_suc_handler);
291         gras_cb_register(gras_msgtype_by_name("can_nuke"),&node_nuke_handler);// can_test.c handler // include can_tests.c must be ON.
292         
293         TRY{
294           gras_msg_handle(10000.0); // waiting.. in case of someone has something to say.
295         }CATCH(e){
296                 INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
297           //INFO0("Closing node, all has been done!");
298         }
299
300         gras_socket_close(globals->sock); // spare.
301         free(globals); // spare.
302         //gras_exit();
303         return(0);
304 }
305
306 // END