1 /* Broken Peer-To-Peer CAN simulator */
3 /* Copyright (c) 2006, 2007. The SimGrid Team.
4 * All rights reserved. */
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. */
10 #include "xbt/sysdep.h"
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.
16 //XBT_LOG_NEW_DEFAULT_CATEGORY(can,"Messages specific to this example"); // include can_tests.c must be OFF.
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);
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;};);
25 typedef struct s_get_suc get_suc_t;
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 {
33 char north_host[1024];
35 char south_host[1024];
38 int east_port; char west_host[1024]; int west_port;};);
39 typedef struct s_rep_suc rep_suc_t;
41 int node(int argc, char **argv);
43 // registering messages types
44 static void register_messages()
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.
52 // a forwarding function for a "get_suc" message.
53 static void forward_get_suc(get_suc_t msg, char host[1024], int port)
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);
59 temp_sock = gras_socket_client(host, port);
61 RETHROW0("Unable to connect!: %s");
64 gras_msg_send(temp_sock, "can_get_suc", &msg);
66 RETHROW0("Unable to send!: %s");
68 XBT_INFO("Forwarding a get_successor message to %s for (%d;%d)", host,
70 gras_socket_close(temp_sock);
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)
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.
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;
113 globals->x1 = (incoming->xId + globals->xId) / 2;
114 strcpy(globals->west_host, incoming->host);
115 globals->west_port = incoming->port;
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;
131 globals->x2 = (incoming->xId + globals->xId) / 2;
132 strcpy(globals->east_host, incoming->host);
133 globals->east_port = incoming->port;
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;
151 globals->y1 = (incoming->yId + globals->yId) / 2;
152 strcpy(globals->south_host, incoming->host);
153 globals->south_port = incoming->port;
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;
169 globals->y2 = (incoming->yId + globals->yId) / 2;
170 strcpy(globals->north_host, incoming->host);
171 globals->north_port = incoming->port;
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);
180 temp_sock = gras_socket_client(incoming->host, incoming->port);
184 ("Unable to connect to the node wich has requested for an area!: %s");
187 gras_msg_send(temp_sock, "can_rep_suc", &outgoing);
188 XBT_INFO("Environment informations sent!");
191 RETHROW2("%s:Timeout sending environment informations to %s: %s",
192 globals->host, gras_socket_peer_name(expeditor));
194 gras_socket_close(temp_sock);
195 } else // we have a problem!
196 XBT_INFO("An error occurded!!!!!!!!!!!!!");
199 gras_socket_close(expeditor); // spare
201 gras_msg_handle(10000.0); // wait a bit in case of someone want to ask me for something.
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!");
215 int node(int argc, char **argv)
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;
221 rep_suc_t rep_suc_msg;
223 get_suc_t get_suc_msg; // building the "get_suc" message.
224 gras_socket_t temp_sock2 = NULL;
226 XBT_INFO("Starting");
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.
232 globals = gras_userdata_new(node_data_t);
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)
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.
248 } else { // asking for an area.
249 XBT_INFO("Contacting %s so as to request for an area", argv[4]);
252 temp_sock = gras_socket_client(argv[4], atoi(argv[5]));
255 RETHROW0("Unable to connect known host to request for an area!: %s");
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;
264 gras_msg_send(temp_sock, "can_get_suc", &get_suc_msg);
267 gras_socket_close(temp_sock);
268 RETHROW0("Unable to contact known host to get an area!: %s");
270 gras_socket_close(temp_sock);
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);
279 RETHROW1("%s: Error waiting for an area:%s", globals->host);
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;
296 gras_socket_close(temp_sock); // spare
298 XBT_INFO("Node %s:%d inserted", globals->host, globals->port);
300 // associating messages to handlers.
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.
306 gras_msg_handle(10000.0); // waiting.. in case of someone has something to say.
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!");
314 gras_socket_close(globals->sock); // spare.
315 free(globals); // spare.