Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bug fixes: correct use of xbt dictionaries and arrays
[simgrid.git] / src / instr / surf_instr.c
1 /* Copyright (c) 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5   * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "instr/private.h"
8
9 #ifdef HAVE_TRACING
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(tracing_surf,tracing,"Tracing Surf");
12
13 #define VARIABLE_SEPARATOR '#'
14
15 static xbt_dict_t hosts_id;
16 static xbt_dict_t created_links;
17 static xbt_dict_t link_bandwidth;
18 static xbt_dict_t link_latency;
19 static xbt_dict_t host_containers;
20
21 static xbt_dict_t last_platform_variables; /* to control the amount of add/sub variables events:
22    dict with key {RESOURCE_NAME}#Time or {RESOURCE_NAME}#Value of dict with variables types == string */
23
24 static xbt_dict_t platform_variables; /* host or link name -> array of categories */
25
26 static xbt_dict_t resource_variables; /* (host|link)#variable -> value */
27
28 /* to trace gtnets */
29 static xbt_dict_t gtnets_src; /* %p (action) -> %s */
30 static xbt_dict_t gtnets_dst; /* %p (action) -> %s */
31
32 void __TRACE_surf_init (void)
33 {
34   hosts_id = xbt_dict_new();
35   created_links = xbt_dict_new();
36   link_bandwidth = xbt_dict_new();
37   link_latency = xbt_dict_new();
38   platform_variables = xbt_dict_new();
39   host_containers = xbt_dict_new();
40   last_platform_variables =  xbt_dict_new();
41   resource_variables = xbt_dict_new ();
42   gtnets_src = xbt_dict_new ();
43   gtnets_dst = xbt_dict_new ();
44 }
45
46 static char *strsplit (char *input, int field, char del) //caller should free the returned string
47 {
48   int length = strlen(input), i;
49   int s = 0, e = length+1;
50   int current_field = 0;
51   for (i = 0; i < length; i++){
52      if (input[i] == del){
53        if (current_field == field){
54          e = i-1;
55          break;
56        }else{
57          s = i+1;
58          current_field++;
59        }
60      }
61   }
62   //copy string from s to e (with length equal to e-s) and return
63   char *ret = malloc ((e-s+2)*sizeof(char));
64   strncpy (ret, input+s, e-s+1);
65   ret[e-s+1] = '\0';
66   return ret;
67 }
68
69 void __TRACE_surf_finalize (void)
70 {
71   if (!IS_TRACING_PLATFORM) return;
72   if (!xbt_dict_length(last_platform_variables)){
73     return;
74   }else{
75     xbt_dict_cursor_t cursor = NULL;
76     unsigned int cursor_ar = 0;
77     char *key, *value, *res;
78     char *resource;
79
80     /* get all resources from last_platform_variables */
81     xbt_dynar_t resources = xbt_dynar_new(sizeof(char*), xbt_free);
82     xbt_dict_foreach(last_platform_variables, cursor, key, value) {
83       res = strsplit (key, 0, VARIABLE_SEPARATOR);
84       char *aux = strsplit (key, 1, VARIABLE_SEPARATOR);
85       if (strcmp (aux, "Time") == 0){ //only need to add one of three
86         char *var_cpy = xbt_strdup (res);
87         xbt_dynar_push (resources, &var_cpy);
88       }
89       free (aux);
90       free (res);
91     }
92
93     /* iterate through resources array */
94     xbt_dynar_foreach (resources, cursor_ar, resource) {
95       char timekey[100], valuekey[100], variablekey[100];
96       snprintf (timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
97       snprintf (valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
98       snprintf (variablekey, 100, "%s%cVariable", resource, VARIABLE_SEPARATOR);
99
100       char *time = xbt_dict_get_or_null (last_platform_variables, timekey);
101       if (!time) continue;
102       char *value = xbt_dict_get (last_platform_variables, valuekey);
103       char *variable = xbt_dict_get (last_platform_variables, variablekey);
104       pajeSubVariable (atof(time), variable, resource, value);
105
106       xbt_dict_remove (last_platform_variables, timekey);
107       xbt_dict_remove (last_platform_variables, valuekey);
108       xbt_dict_remove (last_platform_variables, variablekey);
109     }
110   }
111 }
112
113 void __TRACE_surf_check_variable_set_to_zero (double now, const char *variable, const char *resource)
114 {
115   /* check if we have to set it to 0 */
116   if (!xbt_dict_get_or_null (platform_variables, resource)){
117     xbt_dynar_t array = xbt_dynar_new(sizeof(char*), xbt_free);
118     char *var_cpy = xbt_strdup(variable);
119     xbt_dynar_push (array, &var_cpy);
120     if (IS_TRACING_PLATFORM) pajeSetVariable (now, variable, resource, "0");
121     xbt_dict_set (platform_variables, resource, array, xbt_dynar_free_voidp);
122   }else{
123     xbt_dynar_t array = xbt_dict_get (platform_variables, resource);
124     unsigned int i;
125     char* cat;
126     int flag = 0;
127     xbt_dynar_foreach (array, i, cat) {
128       if (strcmp(variable, cat)==0){
129         flag = 1;
130       }
131     }
132     if (flag==0){
133       char *var_cpy = xbt_strdup(variable);
134       xbt_dynar_push (array, &var_cpy);
135       if (IS_TRACING_PLATFORM) pajeSetVariable (now, variable, resource, "0");
136     }
137   }
138   /* end of check */
139 }
140
141 void __TRACE_surf_update_action_state_resource (double now, double delta, const char *variable, const char *resource, double value)
142 {
143   if (!IS_TRACING_PLATFORM) return;
144
145   char valuestr[100];
146   snprintf (valuestr, 100, "%f", value);
147
148   /*
149   //fprintf (stderr, "resource = %s variable = %s (%f -> %f) value = %s\n", resource, variable, now, now+delta, valuestr);
150   if (1){
151     __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
152     if (IS_TRACING_PLATFORM) pajeAddVariable (now, variable, resource, valuestr);
153     if (IS_TRACING_PLATFORM) pajeSubVariable (now+delta, variable, resource, valuestr);
154     return;
155   }
156   */
157
158   /*
159    * The following code replaces the code above with the objective
160    * to decrease the size of file because of unnecessary add/sub on
161    * variables. It should be re-checked before put in production.
162    */
163
164   char nowstr[100], nowdeltastr[100];
165   snprintf (nowstr, 100, "%.15f", now);
166   snprintf (nowdeltastr, 100, "%.15f", now+delta);
167
168   char timekey[100], valuekey[100], variablekey[100];
169   snprintf (timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
170   snprintf (valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
171   snprintf (variablekey, 100, "%s%cVariable", resource, VARIABLE_SEPARATOR);
172
173   char *lastvariable = xbt_dict_get_or_null (last_platform_variables, variablekey);
174   if (lastvariable == NULL){
175     __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
176     pajeAddVariable (now, variable, resource, valuestr);
177     char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
178     char *valuestr_cpy = xbt_strdup (valuestr);
179     char *variable_cpy = xbt_strdup (variable);
180     xbt_dict_set (last_platform_variables, timekey, nowdeltastr_cpy, xbt_free);
181     xbt_dict_set (last_platform_variables, valuekey, valuestr_cpy, xbt_free);
182     xbt_dict_set (last_platform_variables, variablekey, variable_cpy, xbt_free);
183   }else{
184     char *lasttime = xbt_dict_get_or_null (last_platform_variables, timekey);
185     char *lastvalue = xbt_dict_get_or_null (last_platform_variables, valuekey);
186
187     /* check if it is the same variable */
188     if (strcmp(lastvariable, variable) == 0){ /* same variable */
189       /* check if lasttime equals now */
190       if (atof(lasttime) == now){ /* lastime == now */
191         /* check if lastvalue equals valuestr */
192         if (atof(lastvalue) == value){ /* lastvalue == value (good, just advance time) */
193           char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
194           xbt_dict_set (last_platform_variables, timekey, nowdeltastr_cpy, xbt_free);
195         }else{ /* value has changed */
196           /* value has changed, subtract previous value, add new one */
197           pajeSubVariable (atof(lasttime), variable, resource, lastvalue);
198           pajeAddVariable (atof(nowstr), variable, resource, valuestr);
199           char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
200           char *valuestr_cpy = xbt_strdup (valuestr);
201           xbt_dict_set (last_platform_variables, timekey, nowdeltastr_cpy, xbt_free);
202           xbt_dict_set (last_platform_variables, valuekey, valuestr_cpy, xbt_free);
203         }
204       }else{ /* lasttime != now */
205         /* the last time is different from new starting time, subtract to lasttime and add from nowstr */
206         pajeSubVariable (atof(lasttime), variable, resource, lastvalue);
207         pajeAddVariable (atof(nowstr), variable, resource, valuestr);
208         char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
209         char *valuestr_cpy = xbt_strdup (valuestr);
210         xbt_dict_set (last_platform_variables, timekey, nowdeltastr_cpy, xbt_free);
211         xbt_dict_set (last_platform_variables, valuekey, valuestr_cpy, xbt_free);
212       }
213     }else{ /* variable has changed */
214       pajeSubVariable (atof(lasttime), lastvariable, resource, lastvalue);
215       __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
216       pajeAddVariable (now, variable, resource, valuestr);
217       char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
218       char *valuestr_cpy = xbt_strdup (valuestr);
219       char *variable_cpy = xbt_strdup (variable);
220       xbt_dict_set (last_platform_variables, timekey, nowdeltastr_cpy, xbt_free);
221       xbt_dict_set (last_platform_variables, valuekey, valuestr_cpy, xbt_free);
222       xbt_dict_set (last_platform_variables, variablekey, variable_cpy, xbt_free);
223     }
224   }
225   return;
226 }
227
228 void __TRACE_surf_set_resource_variable (double date, const char *variable, const char *resource, double value)
229 {
230   if (!IS_TRACING) return;
231   char aux[100], key[100];
232   snprintf (aux, 100, "%f", value);
233   snprintf (key, 100, "%s%c%s", resource, VARIABLE_SEPARATOR, variable);
234
235   char *last_value = xbt_dict_get_or_null(resource_variables, key);
236   if (last_value){
237     if (atof(last_value) == value){
238       return;
239     }
240   }
241   if (IS_TRACING_PLATFORM) pajeSetVariable (date, variable, resource, aux);
242   xbt_dict_set (resource_variables, xbt_strdup(key), xbt_strdup(aux), xbt_free);
243 }
244
245 void TRACE_surf_link_set_utilization (const char *name, smx_action_t smx_action, double value, double now, double delta)
246 {
247   if (!IS_TRACING || !IS_TRACED(smx_action)) return;
248
249   if (strcmp (name, "__loopback__")==0 ||
250       strcmp (name, "loopback")==0){ //ignore loopback updates
251     return;
252   }
253
254   if (value == 0) return;
255
256   if (!xbt_dict_get_or_null (created_links, name)){
257     TRACE_surf_link_missing ();
258     return;
259   }
260
261   char type[100];
262   snprintf (type, 100, "b%s", smx_action->category);
263   __TRACE_surf_update_action_state_resource (now, delta, type, name, value);
264   return;
265 }
266
267 void TRACE_surf_host_set_utilization (const char *name, smx_action_t smx_action, double value, double now, double delta)
268 {
269   if (!IS_TRACING || !IS_TRACED(smx_action)) return;
270
271   if (value==0){
272     return;
273   }
274
275   char type[100];
276   snprintf (type, 100, "p%s", smx_action->category);
277   __TRACE_surf_update_action_state_resource (now, delta, type, name, value);
278   return;
279 }
280
281 void TRACE_surf_link_declaration (char *name, double bw, double lat)
282 {
283   if (!IS_TRACING) return;
284   //if (IS_TRACING_PLATFORM) pajeCreateContainerWithBandwidthLatency (SIMIX_get_clock(), name, "LINK", "platform", name, bw, lat);
285   //save bw and lat information for this link
286   double *bw_ptr, *lat_ptr;
287   bw_ptr = xbt_new (double, 1);
288   lat_ptr = xbt_new (double, 1);
289   *bw_ptr = bw;
290   *lat_ptr = lat;
291   xbt_dict_set (link_bandwidth, name, bw_ptr, xbt_free);
292   xbt_dict_set (link_latency, name, lat_ptr, xbt_free);
293 }
294
295 void TRACE_surf_host_declaration (char *name, double power)
296 {
297   if (!IS_TRACING) return;
298   pajeCreateContainer (SIMIX_get_clock(), name, "HOST", "platform", name);
299   xbt_dict_set (host_containers, name, xbt_strdup("1"), xbt_free);
300   if (IS_TRACING_PLATFORM){
301     __TRACE_surf_set_resource_variable (SIMIX_get_clock(), "power", name, power);
302   }
303 }
304
305 void TRACE_surf_link_save_endpoints (char *link_name, int src, int dst)
306 {
307   if (!IS_TRACING) return;
308   char srcidstr[100], dstidstr[100];
309   snprintf (srcidstr, 100, "%d", src);
310   snprintf (dstidstr, 100, "%d", dst);
311   char *srcname = xbt_dict_get (hosts_id, srcidstr);
312   char *dstname = xbt_dict_get (hosts_id, dstidstr);
313
314   char key[100];
315   snprintf (key, 100, "l%d-%d", src, dst);
316
317   if (strcmp (link_name, "__loopback__")==0 ||
318       strcmp (link_name, "loopback")==0){ //ignore loopback updates
319     return;
320   }
321
322   if (!xbt_dict_get_or_null (created_links, link_name)){
323     //if (IS_TRACING_PLATFORM) pajeStartLink (SIMIX_get_clock(), "edge", "platform", "route", srcname, key);
324     //if (IS_TRACING_PLATFORM) pajeEndLink (SIMIX_get_clock()+0.1, "edge", "platform", "route", dstname, key);
325     double *bw = xbt_dict_get (link_bandwidth, link_name);
326     double *lat = xbt_dict_get (link_latency, link_name);
327     pajeCreateContainerWithBandwidthLatencySrcDst (SIMIX_get_clock(), link_name, "LINK", "platform", link_name, *bw, *lat, srcname, dstname);
328     if (IS_TRACING_PLATFORM) __TRACE_surf_set_resource_variable (SIMIX_get_clock(), "bandwidth", link_name, *bw);
329     if (IS_TRACING_PLATFORM) __TRACE_surf_set_resource_variable (SIMIX_get_clock(), "latency", link_name, *lat);
330     xbt_dict_set (created_links, link_name, xbt_strdup ("1"), xbt_free);
331   }
332 }
333
334 void TRACE_surf_host_set_power (double date, char *resource, double power)
335 {
336   __TRACE_surf_set_resource_variable (date, "power", resource, power);
337 }
338
339 void TRACE_surf_link_set_bandwidth (double date, char *resource, double bandwidth)
340 {
341   __TRACE_surf_set_resource_variable (date, "bandwidth", resource, bandwidth);
342 }
343
344 void TRACE_surf_link_set_latency (double date, char *resource, double latency)
345 {
346   __TRACE_surf_set_resource_variable (date, "latency", resource, latency);
347 }
348
349 void TRACE_surf_host_define_id (const char *name, int host_id)
350 {
351   if (!IS_TRACING) return;
352   char strid[100];
353   snprintf (strid, 100, "%d", host_id);
354   xbt_dict_set (hosts_id, name, strdup(strid), free);
355   xbt_dict_set (hosts_id, strid, strdup(name), free);
356 }
357
358 /* to trace gtnets */
359 void TRACE_surf_gtnets_communicate (void *action, int src, int dst)
360 {
361   if (!IS_TRACING) return;
362   char key[100], aux[100];
363   snprintf (key, 100, "%p", action);
364
365   snprintf (aux, 100, "%d", src);
366   xbt_dict_set (gtnets_src, key, xbt_strdup(aux), xbt_free);
367   snprintf (aux, 100, "%d", dst);
368   xbt_dict_set (gtnets_dst, key, xbt_strdup(aux), xbt_free);
369 }
370
371 int TRACE_surf_gtnets_get_src (void *action)
372 {
373   if (!IS_TRACING) return -1;
374   char key[100];
375   snprintf (key, 100, "%p", action);
376
377   char *aux = xbt_dict_get_or_null (gtnets_src, key);
378   if (aux){
379         return atoi(aux);
380   }else{
381     return -1;
382   }
383 }
384
385 int TRACE_surf_gtnets_get_dst (void *action)
386 {
387   if (!IS_TRACING) return -1;
388   char key[100];
389   snprintf (key, 100, "%p", action);
390
391   char *aux = xbt_dict_get_or_null (gtnets_dst, key);
392   if (aux){
393         return atoi(aux);
394   }else{
395     return -1;
396   }
397 }
398
399 void TRACE_surf_gtnets_destroy (void *action)
400 {
401   if (!IS_TRACING) return;
402   char key[100];
403   snprintf (key, 100, "%p", action);
404   xbt_dict_remove (gtnets_src, key);
405   xbt_dict_remove (gtnets_dst, key);
406 }
407
408 void TRACE_surf_link_missing (void)
409 {
410   CRITICAL0("The trace cannot be done because "
411                  "the platform you are using contains "
412                  "routes with more than one link.");
413   THROW0(tracing_error, TRACE_ERROR_COMPLEX_ROUTES, "Tracing failed");
414 }
415
416 void TRACE_msg_clean (void)
417 {
418   __TRACE_surf_finalize();
419
420   xbt_dict_cursor_t cursor = NULL;
421   char *key, *value;
422
423   /* get all host from host_containers */
424   xbt_dict_foreach(host_containers, cursor, key, value) {
425     pajeDestroyContainer (MSG_get_clock(), "HOST", key);
426   }
427 }
428
429 void TRACE_surf_host_vivaldi_parse (char *host, double x, double y, double h)
430 {
431   if (!IS_TRACING || !IS_TRACING_PLATFORM) return;
432
433   char valuestr[100];
434   snprintf (valuestr, 100, "%g", x);
435   pajeSetVariable (0, "vivaldi_x", host, valuestr);
436   snprintf (valuestr, 100, "%g", y);
437   pajeSetVariable (0, "vivaldi_y", host, valuestr);
438   snprintf (valuestr, 100, "%g", h);
439   pajeSetVariable (0, "vivaldi_h", host, valuestr);
440 }
441
442 #endif