Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Greately simplify surf_fopen() at the price of one malloc each time we call it instea...
[simgrid.git] / src / surf / trace_mgr.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2004 Arnaud Legrand. 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 "xbt/sysdep.h"
9 #include "xbt/log.h"
10 #include "xbt/str.h"
11 #include "xbt/dict.h"
12 #include "trace_mgr_private.h"
13 #include "surf_private.h"
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_trace, surf,"Surf trace management");
16
17 static xbt_dict_t trace_list = NULL;
18 static void _tmgr_trace_free(void *trace)
19 {
20   tmgr_trace_free(trace);
21 }
22
23 tmgr_history_t tmgr_history_new(void)
24 {
25   tmgr_history_t h;
26
27   h = xbt_new0(s_tmgr_history_t, 1);
28
29   h->heap = xbt_heap_new(8, xbt_free_f);        /* Why 8 ? Well, why not... */
30
31   return h;
32 }
33
34 void tmgr_history_free(tmgr_history_t h)
35 {
36   xbt_heap_free(h->heap);
37   free(h);
38 }
39
40 tmgr_trace_t tmgr_trace_new_from_string(const char *id, const char *input,
41                                         double periodicity)
42 {
43   tmgr_trace_t trace = NULL;
44   int linecount = 0;
45   s_tmgr_event_t event;
46   tmgr_event_t last_event = NULL;
47   xbt_dynar_t list;
48   unsigned int cpt;
49   char *val;
50
51   if (trace_list) {
52     trace = xbt_dict_get_or_null(trace_list, id);
53     if (trace)
54       return trace;
55   }
56
57   if (periodicity <= 0) {
58     xbt_assert1(0, "Periodicity has to be positive. Your value %lg",
59                 periodicity);
60   }
61
62   trace = xbt_new0(s_tmgr_trace_t, 1);
63   trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
64
65   list = xbt_str_split(input, "\n\r");
66
67
68   xbt_dynar_foreach(list, cpt, val) {
69     linecount++;
70     xbt_str_trim(val, " \t\n\r\x0B");
71     if (strlen(val) > 0) {
72       if (sscanf(val, "%lg" " " "%lg" "\n", &event.delta, &event.value) != 2) {
73         xbt_assert2(0, "%s\n%d: Syntax error", input, linecount);
74       }
75       if (last_event) {
76         if ((last_event->delta = event.delta - last_event->delta) <= 0) {
77           xbt_assert2(0,
78                       "%s\n%d: Invalid trace value, events have to be sorted",
79                       input, linecount);
80         }
81       }
82       xbt_dynar_push(trace->event_list, &event);
83       last_event =
84         xbt_dynar_get_ptr(trace->event_list,
85                           xbt_dynar_length(trace->event_list) - 1);
86       if (periodicity > 0) {
87         if (last_event)
88           last_event->delta = periodicity;
89       }
90     }
91   }
92
93   if (!trace_list)
94     trace_list = xbt_dict_new();
95
96   xbt_dict_set(trace_list, id, (void *) trace, _tmgr_trace_free);
97
98   xbt_dynar_free(&list);
99   return trace;
100 }
101
102 tmgr_trace_t tmgr_trace_new(const char *filename)
103 {
104   tmgr_trace_t trace = NULL;
105   FILE *f = NULL;
106   int linecount = 0;
107   char line[256];
108   double periodicity = -1.0;    /* No periodicity by default */
109   s_tmgr_event_t event;
110   tmgr_event_t last_event = NULL;
111
112   if ((!filename) || (strcmp(filename, "") == 0))
113     return NULL;
114
115   if (trace_list) {
116     trace = xbt_dict_get_or_null(trace_list, filename);
117     if (trace) {
118       WARN1("Ignoring redefinition of trace %s",filename);
119       return trace;
120     }
121   }
122
123   f = surf_fopen(filename, "r");
124   xbt_assert1(f!=NULL, "Cannot open file '%s'", filename);
125
126   trace = xbt_new0(s_tmgr_trace_t, 1);
127   trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
128
129   while (fgets(line, 256, f)) {
130     linecount++;
131     if ((line[0] == '#') || (line[0] == '\n') || (line[0] == '%'))
132       continue;
133
134     if (sscanf(line, "PERIODICITY " "%lg" "\n", &(periodicity))
135         == 1) {
136       if (periodicity <= 0) {
137         xbt_assert2(0,
138                     "%s,%d: Syntax error. Periodicity has to be positive",
139                     filename, linecount);
140       }
141       continue;
142     }
143
144     if (sscanf(line, "%lg" " " "%lg" "\n", &event.delta, &event.value) != 2) {
145       xbt_assert2(0, "%s,%d: Syntax error", filename, linecount);
146     }
147
148     if (last_event) {
149       if ((last_event->delta = event.delta - last_event->delta) <= 0) {
150         xbt_assert2(0,
151                     "%s,%d: Invalid trace value, events have to be sorted",
152                     filename, linecount);
153       }
154     }
155     xbt_dynar_push(trace->event_list, &event);
156     last_event = xbt_dynar_get_ptr(trace->event_list,
157                                    xbt_dynar_length(trace->event_list) - 1);
158   }
159
160   if (periodicity > 0) {
161     if (last_event)
162       last_event->delta = periodicity;
163   }
164
165   if (!trace_list)
166     trace_list = xbt_dict_new();
167
168   xbt_dict_set(trace_list, filename, (void *) trace, _tmgr_trace_free);
169
170   fclose(f);
171
172   return trace;
173 }
174
175 tmgr_trace_t tmgr_empty_trace_new(void)
176 {
177   tmgr_trace_t trace = NULL;
178   /*double periodicity = -1.0;   No periodicity by default; unused variables
179      tmgr_event_t last_event = NULL; */
180   s_tmgr_event_t event;
181
182   trace = xbt_new0(s_tmgr_trace_t, 1);
183   trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
184
185   event.delta = 0.0;
186   event.value = 0.0;
187   xbt_dynar_push(trace->event_list, &event);
188
189   return trace;
190 }
191
192 void tmgr_trace_free(tmgr_trace_t trace)
193 {
194   if (!trace)
195     return;
196   xbt_dynar_free(&(trace->event_list));
197   free(trace);
198 }
199
200 tmgr_trace_event_t tmgr_history_add_trace(tmgr_history_t h,
201                                           tmgr_trace_t trace,
202                                           double start_time,
203                                           unsigned int offset, void *model)
204 {
205   tmgr_trace_event_t trace_event = NULL;
206
207   trace_event = xbt_new0(s_tmgr_trace_event_t, 1);
208   trace_event->trace = trace;
209   trace_event->idx = offset;
210   trace_event->model = model;
211
212   xbt_assert0((trace_event->idx < xbt_dynar_length(trace->event_list)),
213               "You're referring to an event that does not exist!");
214
215   xbt_heap_push(h->heap, trace_event, start_time);
216
217   return trace_event;
218 }
219
220 double tmgr_history_next_date(tmgr_history_t h)
221 {
222   if (xbt_heap_size(h->heap))
223     return (xbt_heap_maxkey(h->heap));
224   else
225     return -1.0;
226 }
227
228 tmgr_trace_event_t tmgr_history_get_next_event_leq(tmgr_history_t h,
229                                                    double date,
230                                                    double *value,
231                                                    void **model)
232 {
233   double event_date = tmgr_history_next_date(h);
234   tmgr_trace_event_t trace_event = NULL;
235   tmgr_event_t event = NULL;
236   tmgr_trace_t trace = NULL;
237
238   if (event_date > date)
239     return NULL;
240
241   if (!(trace_event = xbt_heap_pop(h->heap)))
242     return NULL;
243
244   trace = trace_event->trace;
245   event = xbt_dynar_get_ptr(trace->event_list, trace_event->idx);
246
247   *value = event->value;
248   *model = trace_event->model;
249
250   if (trace_event->idx < xbt_dynar_length(trace->event_list) - 1) {
251     xbt_heap_push(h->heap, trace_event, event_date + event->delta);
252     trace_event->idx++;
253   } else if (event->delta > 0) {        /* Last element, checking for periodicity */
254     xbt_heap_push(h->heap, trace_event, event_date + event->delta);
255     trace_event->idx = 0;
256   } else {                      /* We don't need this trace_event anymore */
257     free(trace_event);
258     return NULL;
259   }
260
261   return trace_event;
262 }
263
264 void tmgr_finalize(void)
265 {
266   xbt_dict_free(&trace_list);
267 }