Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Surf: factorize resource sets into common_public
[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 = surf_model_resource_by_name(surf_network_model, name);
107
108   if (!card) {
109     /* KF: Increment the card counter for GTNetS */
110     card_count++;
111
112     /* KF: just use the dictionary to map link names to link indices */
113     card = xbt_new0(s_network_card_GTNETS_t, 1);
114     card->name = xbt_strdup(name);
115     card->id = card_count;
116     xbt_dict_set(surf_model_resource_set(surf_network_model), name, card, network_card_free);
117   }
118
119   LOG1(xbt_log_priority_trace, "   return %d", card->id);
120   XBT_OUT;
121   /* KF: just return the GTNetS ID as the SURF ID */
122   return card->id;
123 }
124
125 /* Instantiate a new route: MODIFY BY KF */
126 static void route_new(int src_id, int dst_id, network_link_GTNETS_t * links,
127                       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,
149                              network_link_GTNETS_t * links, int nb_link)
150 {
151   int linkid;
152
153   if (nb_link != 1) {
154     xbt_assert0(0, "In onehop_new, nb_link should be 1");
155   }
156
157   /* KF: Build the linbst of gtnets link IDs */
158   linkid = links[0]->id;
159
160   /* KF: Create the GTNets route */
161   if (gtnets_add_onehop_route(src_id, dst_id, linkid)) {
162     xbt_assert0(0, "Cannot create GTNetS route");
163   }
164 }
165
166
167
168 /* Parse the XML for a network link */
169 static void parse_link_init(void)
170 {
171   char *name;
172   double bw;
173   double lat;
174   e_surf_link_state_t state;
175
176   name = xbt_strdup(A_surfxml_link_id);
177   surf_parse_get_double(&bw, A_surfxml_link_bandwidth);
178   surf_parse_get_double(&lat, A_surfxml_link_latency);
179   state = SURF_LINK_ON;
180
181   tmgr_trace_t bw_trace;
182   tmgr_trace_t state_trace;
183   tmgr_trace_t lat_trace;
184
185   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
186   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
187   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
188
189   if (bw_trace)
190     INFO0("The GTNetS network model doesn't support bandwidth state traces");
191   if (lat_trace)
192     INFO0("The GTNetS network model doesn't support latency state traces");
193   if (state_trace)
194     INFO0("The GTNetS network model doesn't support link state traces");
195
196   current_property_set = xbt_dict_new();
197   link_new(name, bw, lat, current_property_set);
198 }
199
200 /* Parses a route from the XML: UNMODIFIED BY HC */
201 static void parse_route_set_endpoints(void)
202 {
203   src_id = network_card_new(A_surfxml_route_src);
204   dst_id = network_card_new(A_surfxml_route_dst);
205   route_action = A_surfxml_route_action;
206 }
207
208 /* KF*/
209 static void parse_route_set_routers(void)
210 {
211   int id = network_card_new(A_surfxml_router_id);
212
213   /* KF: Create the GTNets router */
214   if (gtnets_add_router(id)) {
215     xbt_assert0(0, "Cannot add GTNetS router");
216   }
217 }
218
219 /* Create the route (more than one hops): MODIFIED BY KF */
220 static void parse_route_set_route(void)
221 {
222   char *name;
223   if (src_id != -1 && dst_id != -1) {
224     name = bprintf("%x#%x", src_id, dst_id);
225     manage_route(route_table, name, route_action, 0);
226     free(name);
227   }
228 }
229
230 static void add_route()
231 {
232   xbt_ex_t e;
233   unsigned int cpt = 0;
234   int link_list_capacity = 0;
235   int nb_link = 0;
236   xbt_dict_cursor_t cursor = NULL;
237   char *key, *data, *end;
238   const char *sep = "#";
239   xbt_dynar_t links, keys;
240   static network_link_GTNETS_t *link_list = NULL;
241
242
243   XBT_IN;
244   xbt_dict_foreach(route_table, cursor, key, data) {
245     char *link = NULL;
246     nb_link = 0;
247     links = (xbt_dynar_t) data;
248     keys = xbt_str_split_str(key, sep);
249
250     link_list_capacity = xbt_dynar_length(links);
251     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
252
253     src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 16);
254     dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 16);
255     xbt_dynar_free(&keys);
256
257     xbt_dynar_foreach(links, cpt, link) {
258       TRY {
259         link_list[nb_link++] = xbt_dict_get(link_set, link);
260       }
261       CATCH(e) {
262         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
263       }
264     }
265     if (nb_link == 1)
266       route_onehop_new(src_id, dst_id, link_list, nb_link);
267   }
268
269   xbt_dict_foreach(route_table, cursor, key, data) {
270     char *link = NULL;
271     nb_link = 0;
272     links = (xbt_dynar_t) data;
273     keys = xbt_str_split_str(key, sep);
274
275     link_list_capacity = xbt_dynar_length(links);
276     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
277
278     src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 16);
279     dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 16);
280     xbt_dynar_free(&keys);
281
282     xbt_dynar_foreach(links, cpt, link) {
283       TRY {
284         link_list[nb_link++] = xbt_dict_get(link_set, link);
285       }
286       CATCH(e) {
287         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
288       }
289     }
290     if (nb_link >= 1)
291       route_new(src_id, dst_id, link_list, nb_link);
292   }
293
294   xbt_dict_free(&route_table);
295   gtnets_print_topology();
296   XBT_OUT;
297 }
298
299 /* Main XML parsing */
300 static void define_callbacks(const char *file)
301 {
302   surfxml_add_callback(STag_surfxml_router_cb_list, &parse_route_set_routers);
303   surfxml_add_callback(STag_surfxml_link_cb_list, &parse_link_init);
304   surfxml_add_callback(STag_surfxml_route_cb_list,
305                        &parse_route_set_endpoints);
306   surfxml_add_callback(ETag_surfxml_route_cb_list, &parse_route_set_route);
307   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_route);
308 }
309
310 static const char *get_resource_name(void *resource_id)
311 {
312   return ((network_card_GTNETS_t) resource_id)->name;
313 }
314
315 static xbt_dict_t get_properties(void *link)
316 {
317   return ((network_card_GTNETS_t) link)->properties;
318 }
319
320
321 /* We do not care about this: only used for traces */
322 static int resource_used(void *resource_id)
323 {
324   return 0;                     /* We don't care */
325 }
326
327 static int action_free(surf_action_t action)
328 {
329   action->refcount--;
330   if (!action->refcount) {
331     xbt_swag_remove(action, action->state_set);
332     /* KF: No explicit freeing needed for GTNeTS here */
333     free(action);
334     return 1;
335   }
336   return 0;
337 }
338
339 static void action_use(surf_action_t action)
340 {
341   action->refcount++;
342 }
343
344 static void action_cancel(surf_action_t action)
345 {
346   xbt_assert0(0, "Cannot cancel GTNetS flow");
347   return;
348 }
349
350 static void action_recycle(surf_action_t action)
351 {
352   xbt_assert0(0, "Cannot recycle GTNetS flow");
353   return;
354 }
355
356 static void action_change_state(surf_action_t action,
357                                 e_surf_action_state_t state)
358 {
359 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
360 /*     if(((surf_action_network_GTNETS_t)action)->variable) { */
361 /*       lmm_variable_disable(maxmin_system, ((surf_action_network_GTNETS_t)action)->variable); */
362 /*       ((surf_action_network_GTNETS_t)action)->variable = NULL; */
363 /*     } */
364
365   surf_action_change_state(action, state);
366   return;
367 }
368
369
370 /* share_resources() */
371 static double share_resources(double now)
372 {
373   xbt_swag_t running_actions =
374     surf_network_model->common_public.states.running_action_set;
375
376   //get the first relevant value from the running_actions list
377   if (!xbt_swag_size(running_actions))
378     return -1.0;
379
380   xbt_assert0(time_to_next_flow_completion,
381               "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,
425              action->generic_action.remains);
426       double remain = gtnets_get_flow_rx(action);
427       DEBUG1("Remain value returned by GTNetS : %f", remain);
428       //need to trust this remain value
429       if (remain == 0) {
430         action->generic_action.remains = 0;
431       } else {
432         action->generic_action.remains = action->generic_action.cost - remain;
433       }
434       DEBUG2("Action (%p) remains new value: %f", action,
435              action->generic_action.remains);
436     }
437
438     for (i = 0; i < num_flows; i++) {
439       action = (surf_action_network_GTNETS_t) (metadata[i]);
440
441       action->generic_action.finish = now + time_to_next_flow_completion;
442       action_change_state((surf_action_t) action, SURF_ACTION_DONE);
443       DEBUG1("----> Action (%p) just terminated", action);
444     }
445
446
447   } else {                      /* run for a given number of seconds */
448     if (gtnets_run(delta)) {
449       xbt_assert0(0, "Cannot run GTNetS simulation");
450     }
451   }
452
453   return;
454 }
455
456 /* UNUSED HERE: no traces */
457 static void update_resource_state(void *id,
458                                   tmgr_trace_event_t event_type,
459                                   double value, double date)
460 {
461   xbt_assert0(0, "Cannot update model state for GTNetS simulation");
462   return;
463 }
464
465 /* KF: Rate not supported */
466 static surf_action_t communicate(void *src, void *dst, double size,
467                                  double rate)
468 {
469   surf_action_network_GTNETS_t action = NULL;
470   network_card_GTNETS_t card_src = src;
471   network_card_GTNETS_t card_dst = dst;
472 /*
473   int route_size = ROUTE_SIZE(card_src->id, card_dst->id);
474   network_link_GTNETS_t *route = ROUTE(card_src->id, card_dst->id);
475 */
476
477 /*
478   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);
479 */
480
481   action = xbt_new0(s_surf_action_network_GTNETS_t, 1);
482
483   action->generic_action.refcount = 1;
484   action->generic_action.cost = size;
485   action->generic_action.remains = size;
486   /* Max durations are not supported */
487   action->generic_action.max_duration = NO_MAX_DURATION;
488   action->generic_action.start = surf_get_clock();
489   action->generic_action.finish = -1.0;
490   action->generic_action.model_type = (surf_model_t) surf_network_model;
491
492   action->generic_action.state_set =
493     surf_network_model->common_public.states.running_action_set;
494
495   xbt_swag_insert(action, action->generic_action.state_set);
496
497   /* KF: Add a flow to the GTNets Simulation, associated to this action */
498   if (gtnets_create_flow(card_src->id, card_dst->id, size, (void *) action)
499       < 0) {
500     xbt_assert2(0, "Not route between host %s and host %s", card_src->name,
501                 card_dst->name);
502   }
503
504   return (surf_action_t) action;
505 }
506
507 /* Suspend a flow() */
508 static void action_suspend(surf_action_t action)
509 {
510   xbt_assert0(0,
511               "action_suspend() not supported for the GTNets network model");
512 }
513
514 /* Resume a flow() */
515 static void action_resume(surf_action_t action)
516 {
517   xbt_assert0(0,
518               "action_resume() not supported for the GTNets network model");
519 }
520
521 /* Test whether a flow is suspended */
522 static int action_is_suspended(surf_action_t action)
523 {
524   return 0;
525 }
526
527 static void finalize(void)
528 {
529   xbt_dict_free(&link_set);
530
531   surf_model_exit((surf_model_t)surf_network_model);
532
533   free(surf_network_model->extension_public);
534
535   free(surf_network_model);
536   surf_network_model = NULL;
537
538   gtnets_finalize();
539 }
540
541 static void surf_network_model_init_internal(void)
542 {
543   s_surf_action_t action;
544
545   surf_network_model = xbt_new0(s_surf_network_model_t, 1);
546
547   surf_model_init((surf_model_t)surf_network_model);
548
549   surf_network_model->extension_public =
550     xbt_new0(s_surf_network_model_extension_public_t, 1);
551
552   surf_network_model->common_public.name_service = name_service;
553   surf_network_model->common_public.get_resource_name = get_resource_name;
554   surf_network_model->common_public.action_get_state = surf_action_get_state;
555   surf_network_model->common_public.action_use = action_use;
556   surf_network_model->common_public.action_free = action_free;
557   surf_network_model->common_public.action_cancel = action_cancel;
558   surf_network_model->common_public.action_recycle = action_recycle;
559   surf_network_model->common_public.action_change_state =
560     action_change_state;
561   surf_network_model->common_public.action_set_data = surf_action_set_data;
562   surf_network_model->common_public.name = "network";
563
564   surf_network_model->common_private->resource_used = resource_used;
565   surf_network_model->common_private->share_resources = share_resources;
566   surf_network_model->common_private->update_actions_state =
567     update_actions_state;
568   surf_network_model->common_private->update_resource_state =
569     update_resource_state;
570   surf_network_model->common_private->finalize = finalize;
571
572   surf_network_model->common_public.suspend = action_suspend;
573   surf_network_model->common_public.resume = action_resume;
574   surf_network_model->common_public.is_suspended = action_is_suspended;
575
576   surf_network_model->extension_public->communicate = communicate;
577
578   /*for the props of the link */
579   surf_network_model->common_public.get_properties = get_properties;
580
581   link_set = xbt_dict_new();
582
583   /* KF: Added the initialization for GTNetS interface */
584   if (gtnets_initialize()) {
585     xbt_assert0(0, "impossible to initialize GTNetS interface");
586   }
587 }
588
589 #ifdef HAVE_GTNETS
590 void surf_network_model_init_GTNETS(const char *filename)
591 {
592   if (surf_network_model)
593     return;
594   surf_network_model_init_internal();
595   define_callbacks(filename);
596   xbt_dynar_push(model_list, &surf_network_model);
597
598   update_model_description(surf_network_model_description,
599                            "GTNets", (surf_model_t) surf_network_model);
600 }
601 #endif