Logo AND Algorithmique Numérique Distribuée

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