Logo AND Algorithmique Numérique Distribuée

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