Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9ee7c9ca5dc8a2b2c1549bd9639155e3b9cd4a10
[simgrid.git] / src / surf / network_gtnets.c
1 /*     $Id$     */
2
3 /* Copyright (c) 2005 Henri Casanova. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "network_gtnets_private.h"
9 #include "gtnets/gtnets_interface.h"
10 #include "xbt/str.h"
11
12
13 static   double time_to_next_flow_completion=-1;
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets, surf,
16                                 "Logging specific to the SURF network module");
17
18 /** QUESTIONS for GTNetS integration
19  **   1. Check that we did the right thing with name_service and get_resource_name
20  **   2. Right now there is no "kill flow" in our GTNetS implementation. Do we
21  **      need to do something about this?
22  **   3. We ignore the fact there is some max_duration on flows (see #2 above)
23  **   4. share_resources() returns a duration, not a date, right?
24  **   5. We don't suppoer "rates"
25  **   6. We don't update "remaining" for ongoing flows. Is it bad?
26  **/
27
28 static int src_id = -1;
29 static int dst_id = -1;
30
31 /* Free memory for a network link */
32 static void link_free(void *nw_link)
33 {
34   free(((network_link_GTNETS_t) nw_link)->name);
35   xbt_dict_free(&(((network_link_GTNETS_t)nw_link)->properties));
36   free(nw_link);
37 }
38
39 /* Instantiate a new network link */
40 /* name: some name for the link, from the XML */
41 /* bw: The bandwidth value            */
42 /* lat: The latency value             */
43 static void link_new(char *name, double bw, double lat, xbt_dict_t props)
44 {
45   static int link_count = -1;
46   network_link_GTNETS_t gtnets_link;
47
48   /* If link already exists, nothing to do (FIXME: check that multiple definition match?) */
49   if (xbt_dict_get_or_null(link_set, name)) {
50     return;
51   }
52
53   /* KF: Increment the link counter for GTNetS */
54   link_count++;
55
56 /*
57   nw_link->model = (surf_model_t) surf_network_model;
58   nw_link->name = name;
59   nw_link->bw_current = bw_initial;
60   if (bw_trace)
61     nw_link->bw_event =
62         tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
63   nw_link->lat_current = lat_initial;
64   if (lat_trace)
65     nw_link->lat_event =
66         tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
67   nw_link->state_current = state_initial;
68   if (state_trace)
69     nw_link->state_event =
70         tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
71 */
72
73   /* KF: Add the link to the GTNetS simulation */
74   if (gtnets_add_link(link_count, bw, lat)) {
75     xbt_assert0(0, "Cannot create GTNetS link");
76   }
77
78   /* KF: Insert entry in the dictionary */
79   gtnets_link = xbt_new0(s_network_link_GTNETS_t, 1);
80   gtnets_link->name = name;
81   gtnets_link->bw_current = bw;
82   gtnets_link->lat_current = lat;
83   gtnets_link->id = link_count;
84   /* Add the properties */
85   gtnets_link->properties = props;
86
87   xbt_dict_set(link_set, name, gtnets_link, link_free);
88
89   return;
90 }
91
92 /* free the network card */
93 static void network_card_free(void *nw_card)
94 {
95   free(((network_card_GTNETS_t) nw_card)->name);
96   free(nw_card);
97 }
98
99 /* Instantiate a new network card: MODIFYED BY KF */
100 static int network_card_new(const char *name)
101 {
102   static int card_count = -1;
103
104   XBT_IN1("(%s)",name);
105   /* KF: Check that we haven't seen the network card before */
106   network_card_GTNETS_t card =
107       xbt_dict_get_or_null(network_card_set, name);
108
109   if (!card) {
110     /* KF: Increment the card counter for GTNetS */
111     card_count++;
112
113     /* KF: just use the dictionary to map link names to link indices */
114     card = xbt_new0(s_network_card_GTNETS_t, 1);
115     card->name = xbt_strdup(name);
116     card->id = card_count;
117     xbt_dict_set(network_card_set, name, card, network_card_free);
118   }
119   
120   LOG1(xbt_log_priority_trace, "   return %d",card->id);
121   XBT_OUT;
122   /* KF: just return the GTNetS ID as the SURF ID */
123   return card->id;
124 }
125
126 /* Instantiate a new route: MODIFY BY KF */
127 static void route_new(int src_id, int dst_id, network_link_GTNETS_t *links, int nb_link)
128 {
129   int i;
130   int *gtnets_links;
131   XBT_IN4("(src_id=%d, dst_id=%d, links=%p, nb_link=%d)",
132           src_id,dst_id,links,nb_link);
133
134   /* KF: Build the list of gtnets link IDs */
135   gtnets_links = (int *) calloc(nb_link, sizeof(int));
136   for (i = 0; i < nb_link; i++) {
137     gtnets_links[i] = links[i]->id;
138   }
139
140   /* KF: Create the GTNets route */
141   if (gtnets_add_route(src_id, dst_id, gtnets_links, nb_link)) {
142     xbt_assert0(0, "Cannot create GTNetS route");
143   }
144   XBT_OUT;
145 }
146
147 /* Instantiate a new route: MODIFY BY KF */
148 static void route_onehop_new(int src_id, int dst_id, network_link_GTNETS_t *links, int nb_link)
149 {
150   int linkid;
151
152   if (nb_link != 1) {
153     xbt_assert0(0, "In onehop_new, nb_link should be 1");
154   }
155
156   /* KF: Build the linbst of gtnets link IDs */
157   linkid = links[0]->id;
158
159   /* KF: Create the GTNets route */
160   if (gtnets_add_onehop_route(src_id, dst_id, linkid)) {
161     xbt_assert0(0, "Cannot create GTNetS route");
162   }
163 }
164
165
166
167 /* Parse the XML for a network link */
168 static void parse_link_init(void)
169 {
170   char *name;
171   double bw;
172   double lat;
173   e_surf_link_state_t state;
174
175   name = xbt_strdup(A_surfxml_link_id);
176   surf_parse_get_double(&bw, A_surfxml_link_bandwidth);
177   surf_parse_get_double(&lat, A_surfxml_link_latency);
178   state = SURF_LINK_ON;
179
180   tmgr_trace_t bw_trace;
181   tmgr_trace_t state_trace;
182   tmgr_trace_t lat_trace;
183   
184   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
185   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
186   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
187
188   if (bw_trace)
189     INFO0("The GTNetS network model doesn't support bandwidth state traces");
190   if (lat_trace)
191     INFO0("The GTNetS network model doesn't support latency state traces");
192   if (state_trace)
193     INFO0("The GTNetS network model doesn't support link state traces");
194
195   current_property_set = xbt_dict_new();
196   link_new(name, bw, lat, current_property_set);
197 }
198
199 /* Parses a route from the XML: UNMODIFIED BY HC */
200 static void parse_route_set_endpoints(void)
201 {
202   src_id = network_card_new(A_surfxml_route_src);
203   dst_id = network_card_new(A_surfxml_route_dst);
204   route_action = A_surfxml_route_action;
205 }
206
207 /* KF*/
208 static void parse_route_set_routers(void)
209 {
210   int id = network_card_new(A_surfxml_router_id);
211
212   /* KF: Create the GTNets router */
213   if (gtnets_add_router(id)) {
214     xbt_assert0(0, "Cannot add GTNetS router");
215   }
216 }
217
218 /* Create the route (more than one hops): MODIFIED BY KF */
219 static void parse_route_set_route(void)
220 {
221   char *name;
222   if (src_id != -1 && dst_id != -1) {
223     name = bprintf("%x#%x",src_id, dst_id);
224     manage_route(route_table, name, route_action, 0);
225     free(name);    
226   }
227 }
228
229 static void add_route()
230 {
231   xbt_ex_t e;
232   unsigned int cpt = 0;    
233   int link_list_capacity = 0;
234   int nb_link = 0;
235   xbt_dict_cursor_t cursor = NULL;
236   char *key,*data, *end;
237   const char *sep = "#";
238   xbt_dynar_t links, keys;
239   static network_link_GTNETS_t *link_list = NULL;
240
241
242   XBT_IN;
243   xbt_dict_foreach(route_table, cursor, key, data) {
244     char *link = NULL;
245     nb_link = 0;
246     links = (xbt_dynar_t)data;
247     keys = xbt_str_split_str(key, sep);
248
249     link_list_capacity = xbt_dynar_length(links);
250     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
251
252     src_id = strtol(xbt_dynar_get_as(keys, 0, char*), &end, 16);
253     dst_id = strtol(xbt_dynar_get_as(keys, 1, char*), &end, 16);
254     xbt_dynar_free(&keys);
255
256     xbt_dynar_foreach (links, cpt, link) {
257       TRY {
258         link_list[nb_link++] = xbt_dict_get(link_set, link);
259       }
260       CATCH(e) {
261         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
262       }     
263     }
264     if (nb_link == 1)
265       route_onehop_new(src_id, dst_id, link_list, nb_link);
266    }
267
268   xbt_dict_foreach(route_table, cursor, key, data) {
269     char *link = NULL;
270     nb_link = 0;
271     links = (xbt_dynar_t)data;
272     keys = xbt_str_split_str(key, sep);
273
274     link_list_capacity = xbt_dynar_length(links);
275     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
276
277     src_id = strtol(xbt_dynar_get_as(keys, 0, char*), &end, 16);
278     dst_id = strtol(xbt_dynar_get_as(keys, 1, char*), &end, 16);
279     xbt_dynar_free(&keys);
280
281     xbt_dynar_foreach (links, cpt, link) {
282       TRY {
283         link_list[nb_link++] = xbt_dict_get(link_set, link);
284       }
285       CATCH(e) {
286         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
287       }     
288     }
289     if (nb_link > 1)
290       route_new(src_id, dst_id, link_list, nb_link);
291    }
292
293   xbt_dict_free(&route_table);
294   XBT_OUT;
295 }
296
297 /* Main XML parsing */
298 static void define_callbacks(const char *file)
299 {
300   surfxml_add_callback(STag_surfxml_router_cb_list,   &parse_route_set_routers);
301   surfxml_add_callback(STag_surfxml_link_cb_list,     &parse_link_init);
302   surfxml_add_callback(STag_surfxml_route_cb_list,    &parse_route_set_endpoints);
303   surfxml_add_callback(ETag_surfxml_route_cb_list,      &parse_route_set_route);
304   surfxml_add_callback(ETag_surfxml_platform_cb_list,   &add_route);
305 }
306
307 static void *name_service(const char *name)
308 {
309   return xbt_dict_get_or_null(network_card_set, name);
310 }
311
312 static const char *get_resource_name(void *resource_id)
313 {
314   return ((network_card_GTNETS_t) resource_id)->name;
315 }
316
317 static xbt_dict_t get_properties(void *link)
318 {
319   return ((network_card_GTNETS_t) link)->properties;
320 }
321
322
323 /* We do not care about this: only used for traces */
324 static int resource_used(void *resource_id)
325 {
326   return 0;                     /* We don't care */
327 }
328
329 static int action_free(surf_action_t action)
330 {
331   action->refcount--;
332   if (!action->refcount) {
333     xbt_swag_remove(action, action->state_set);
334     /* KF: No explicit freeing needed for GTNeTS here */
335     free(action);
336     return 1;
337   }
338   return 0;
339 }
340
341 static void action_use(surf_action_t action)
342 {
343   action->refcount++;
344 }
345
346 static void action_cancel(surf_action_t action)
347 {
348   xbt_assert0(0, "Cannot cancel GTNetS flow");
349   return;
350 }
351
352 static void action_recycle(surf_action_t action)
353 {
354   xbt_assert0(0, "Cannot recycle GTNetS flow");
355   return;
356 }
357
358 static void action_change_state(surf_action_t action,
359                                 e_surf_action_state_t state)
360 {
361 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
362 /*     if(((surf_action_network_GTNETS_t)action)->variable) { */
363 /*       lmm_variable_disable(maxmin_system, ((surf_action_network_GTNETS_t)action)->variable); */
364 /*       ((surf_action_network_GTNETS_t)action)->variable = NULL; */
365 /*     } */
366
367   surf_action_change_state(action, state);
368   return;
369 }
370
371
372 /* share_resources() */
373 static double share_resources(double now)
374 {
375   xbt_swag_t running_actions = surf_network_model->common_public->states.running_action_set;
376
377   //get the first relevant value from the running_actions list
378   if (!xbt_swag_size(running_actions))
379     return -1.0;
380
381   xbt_assert0(time_to_next_flow_completion, "Time to next flow completion not initialized!\n");
382   
383   time_to_next_flow_completion = gtnets_get_time_to_next_flow_completion();
384
385   return time_to_next_flow_completion;
386 }
387
388 /* delta: by how many time units the simulation must advance */
389 /* In this function: change the state of actions that terminate */
390 /* The delta may not come from the network, and thus may be different (smaller) 
391    than the one returned by the function above */
392 /* If the delta is a network-caused min, then do not emulate any timer in the
393    network simulation, otherwise fake a timer somehow to advance the simulation of min seconds */
394
395 static void update_actions_state(double now, double delta)
396 {
397   surf_action_network_GTNETS_t action = NULL;
398   //  surf_action_network_GTNETS_t next_action = NULL;
399   xbt_swag_t running_actions =
400       surf_network_model->common_public->states.running_action_set;
401
402   /* If there are no renning flows, just return */
403   if (time_to_next_flow_completion < 0.0) {
404     return;
405   }
406
407   /*KF: if delta == time_to_next_flow_completion, too. */
408   if (time_to_next_flow_completion <= delta) {  /* run until the first flow completes */
409     void **metadata;
410     int i, num_flows;
411
412     num_flows = 0;
413
414     if (gtnets_run_until_next_flow_completion(&metadata, &num_flows)) {
415       xbt_assert0(0,
416                   "Cannot run GTNetS simulation until next flow completion");
417     }
418     if (num_flows < 1) {
419       xbt_assert0(0,
420                   "GTNetS simulation couldn't find a flow that would complete");
421     }
422
423     xbt_swag_foreach(action, running_actions) {
424       DEBUG2("Action (%p) remains old value: %f", action, action->generic_action.remains);
425       double remain = gtnets_get_flow_rx(action);
426       DEBUG1("Remain value returned by GTNetS : %f", remain);
427       //need to trust this remain value
428       if(remain == 0){
429         action->generic_action.remains=0;
430       }else {
431         action->generic_action.remains=action->generic_action.cost-remain;
432       }
433       DEBUG2("Action (%p) remains new value: %f", action, action->generic_action.remains);
434     }
435
436     for (i = 0; i < num_flows; i++) {
437       action =  (surf_action_network_GTNETS_t) (metadata[i]);
438       
439       action->generic_action.finish = now + time_to_next_flow_completion;
440       action_change_state((surf_action_t) action, SURF_ACTION_DONE);
441       DEBUG1("----> Action (%p) just terminated",action);
442     }
443
444
445   } else {                      /* run for a given number of seconds */
446     if (gtnets_run(delta)) {
447       xbt_assert0(0, "Cannot run GTNetS simulation");
448     }
449   }
450
451   return;
452 }
453
454 /* UNUSED HERE: no traces */
455 static void update_resource_state(void *id,
456                                   tmgr_trace_event_t event_type,
457                                   double value, double date)
458 {
459   xbt_assert0(0, "Cannot update model state for GTNetS simulation");
460   return;
461 }
462
463 /* KF: Rate not supported */
464 static surf_action_t communicate(void *src, void *dst, double size,
465                                  double rate)
466 {
467   surf_action_network_GTNETS_t action = NULL;
468   network_card_GTNETS_t card_src = src;
469   network_card_GTNETS_t card_dst = dst;
470 /*
471   int route_size = ROUTE_SIZE(card_src->id, card_dst->id);
472   network_link_GTNETS_t *route = ROUTE(card_src->id, card_dst->id);
473 */
474
475 /*
476   xbt_assert2(route_size,"You're trying to send data from %s to %s but there is no connexion between these two cards.", card_src->name, card_dst->name);
477 */
478
479   action = xbt_new0(s_surf_action_network_GTNETS_t, 1);
480
481   action->generic_action.refcount = 1;
482   action->generic_action.cost = size;
483   action->generic_action.remains = size;
484   /* Max durations are not supported */
485   action->generic_action.max_duration = NO_MAX_DURATION;
486   action->generic_action.start = surf_get_clock();
487   action->generic_action.finish = -1.0;
488   action->generic_action.model_type =
489       (surf_model_t) surf_network_model;
490
491   action->generic_action.state_set =
492       surf_network_model->common_public->states.running_action_set;
493
494   xbt_swag_insert(action, action->generic_action.state_set);
495
496   /* KF: Add a flow to the GTNets Simulation, associated to this action */
497   if (gtnets_create_flow(card_src->id, card_dst->id, size, (void *) action)
498       < 0) {
499     xbt_assert2(0, "Not route between host %s and host %s", card_src->name,
500                 card_dst->name);
501   }
502
503   return (surf_action_t) action;
504 }
505
506 /* Suspend a flow() */
507 static void action_suspend(surf_action_t action)
508 {
509   xbt_assert0(0,
510               "action_suspend() not supported for the GTNets network model");
511 }
512
513 /* Resume a flow() */
514 static void action_resume(surf_action_t action)
515 {
516   xbt_assert0(0,
517               "action_resume() not supported for the GTNets network model");
518 }
519
520 /* Test whether a flow is suspended */
521 static int action_is_suspended(surf_action_t action)
522 {
523   return 0;
524 }
525
526 static void finalize(void)
527 {
528 #if 0
529   int i, j;
530 #endif
531   xbt_dict_free(&network_card_set);
532   xbt_dict_free(&link_set);
533   xbt_swag_free(surf_network_model->common_public->states.
534                 ready_action_set);
535   xbt_swag_free(surf_network_model->common_public->states.
536                 running_action_set);
537   xbt_swag_free(surf_network_model->common_public->states.
538                 failed_action_set);
539   xbt_swag_free(surf_network_model->common_public->states.
540                 done_action_set);
541   free(surf_network_model->common_public);
542   free(surf_network_model->common_private);
543   free(surf_network_model->extension_public);
544
545   free(surf_network_model);
546   surf_network_model = NULL;
547
548   gtnets_finalize();
549 }
550
551 static void surf_network_model_init_internal(void)
552 {
553   s_surf_action_t action;
554
555   surf_network_model = xbt_new0(s_surf_network_model_t, 1);
556
557   surf_network_model->common_private =
558       xbt_new0(s_surf_model_private_t, 1);
559   surf_network_model->common_public =
560       xbt_new0(s_surf_model_public_t, 1);
561   surf_network_model->extension_public =
562       xbt_new0(s_surf_network_model_extension_public_t, 1);
563
564   surf_network_model->common_public->states.ready_action_set =
565       xbt_swag_new(xbt_swag_offset(action, state_hookup));
566   surf_network_model->common_public->states.running_action_set =
567       xbt_swag_new(xbt_swag_offset(action, state_hookup));
568   surf_network_model->common_public->states.failed_action_set =
569       xbt_swag_new(xbt_swag_offset(action, state_hookup));
570   surf_network_model->common_public->states.done_action_set =
571       xbt_swag_new(xbt_swag_offset(action, state_hookup));
572
573   surf_network_model->common_public->name_service = name_service;
574   surf_network_model->common_public->get_resource_name =
575       get_resource_name;
576   surf_network_model->common_public->action_get_state =
577       surf_action_get_state;
578   surf_network_model->common_public->action_use = action_use;
579   surf_network_model->common_public->action_free = action_free;
580   surf_network_model->common_public->action_cancel = action_cancel;
581   surf_network_model->common_public->action_recycle = action_recycle;
582   surf_network_model->common_public->action_change_state =
583       action_change_state;
584   surf_network_model->common_public->action_set_data =
585       surf_action_set_data;
586   surf_network_model->common_public->name = "network";
587
588   surf_network_model->common_private->resource_used = resource_used;
589   surf_network_model->common_private->share_resources = share_resources;
590   surf_network_model->common_private->update_actions_state =
591       update_actions_state;
592   surf_network_model->common_private->update_resource_state = update_resource_state;
593   surf_network_model->common_private->finalize = finalize;
594
595   surf_network_model->common_public->suspend = action_suspend;
596   surf_network_model->common_public->resume = action_resume;
597   surf_network_model->common_public->is_suspended = action_is_suspended;
598
599   surf_network_model->extension_public->communicate = communicate;
600
601   /*for the props of the link*/
602   surf_network_model->common_public->get_properties =  get_properties;
603
604   link_set = xbt_dict_new();
605   network_card_set = xbt_dict_new();
606
607   /* KF: Added the initialization for GTNetS interface */
608   if (gtnets_initialize()) {
609     xbt_assert0(0, "impossible to initialize GTNetS interface");
610   }
611 }
612
613 #ifdef HAVE_GTNETS
614 void surf_network_model_init_GTNETS(const char *filename)
615 {
616   if (surf_network_model)
617     return;
618   surf_network_model_init_internal();
619   define_callbacks(filename);
620   xbt_dynar_push(model_list, &surf_network_model);
621
622   update_model_description(surf_network_model_description,
623                            "GTNets",
624                            (surf_model_t) surf_network_model);
625 }
626 #endif