Logo AND Algorithmique Numérique Distribuée

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