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,
30 typedef struct s_get_suc get_suc_t;
32 // struct of a "response_successor" message, hen a node receive the information of his new area.
33 GRAS_DEFINE_TYPE(s_rep_suc,
40 char north_host[1024];
42 char south_host[1024];
50 typedef struct s_rep_suc rep_suc_t;
52 int node(int argc,char **argv);
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.
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);
68 temp_sock=gras_socket_client(host,port);
70 RETHROW0("Unable to connect!: %s");
73 gras_msg_send(temp_sock,"can_get_suc",&msg);
75 RETHROW0("Unable to send!: %s");
77 INFO3("Forwarding a get_successor message to %s for (%d;%d)",host,msg.xId,msg.yId);
78 gras_socket_close(temp_sock);
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.
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;
118 globals->x1=(incoming->xId+globals->xId)/2;
119 strcpy(globals->west_host,incoming->host);
120 globals->west_port=incoming->port;
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;
137 globals->x2=(incoming->xId+globals->xId)/2;
138 strcpy(globals->east_host,incoming->host);
139 globals->east_port=incoming->port;
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;
158 globals->y1=(incoming->yId+globals->yId)/2;
159 strcpy(globals->south_host,incoming->host);
160 globals->south_port=incoming->port;
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;
177 globals->y2=(incoming->yId+globals->yId)/2;
178 strcpy(globals->north_host,incoming->host);
179 globals->north_port=incoming->port;
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);
187 temp_sock=gras_socket_client(incoming->host,incoming->port);
189 RETHROW0("Unable to connect to the node wich has requested for an area!: %s");
192 gras_msg_send(temp_sock,"can_rep_suc",&outgoing);
193 INFO0("Environment informations sent!");
195 RETHROW2("%s:Timeout sending environment informations to %s: %s",globals->host,gras_socket_peer_name(expeditor));
197 gras_socket_close(temp_sock);
199 else // we have a problem!
200 INFO0("An error occurded!!!!!!!!!!!!!");
203 gras_socket_close(expeditor); // spare
205 gras_msg_handle(10000.0); // wait a bit in case of someone want to ask me for something.
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!");
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;
222 rep_suc_t rep_suc_msg;
224 get_suc_t get_suc_msg; // building the "get_suc" message.
225 gras_socket_t temp_sock2=NULL;
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.
233 globals=gras_userdata_new(node_data_t);
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)
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.
249 }else{ // asking for an area.
250 INFO1("Contacting %s so as to request for an area",argv[4]);
253 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);
266 gras_socket_close(temp_sock);
267 RETHROW0("Unable to contact known host to get an area!: %s");
269 gras_socket_close(temp_sock);
273 TRY{ // waiting for a reply.
274 INFO0("Waiting for reply!");
275 gras_msg_wait(6000,"can_rep_suc",&temp_sock2,&rep_suc_msg);
277 RETHROW1("%s: Error waiting for an area:%s",globals->host);
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;
294 gras_socket_close(temp_sock); // spare
296 INFO2("Node %s:%d inserted",globals->host,globals->port);
298 // associating messages to handlers.
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.
304 gras_msg_handle(10000.0); // waiting.. in case of someone has something to say.
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!");
310 gras_socket_close(globals->sock); // spare.
311 free(globals); // spare.