Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Make rngStream management functions in platform more visible
[simgrid.git] / src / surf / trace_mgr.c
1 /* Copyright (c) 2004, 2005, 2007, 2009, 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 "xbt/sysdep.h"
8 #include "xbt/log.h"
9 #include "xbt/str.h"
10 #include "xbt/dict.h"
11 #include "trace_mgr_private.h"
12 #include "surf_private.h"
13 #include "xbt/RngStream.h"
14 #include <math.h>
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_trace, surf, "Surf trace management");
17
18 static xbt_dict_t trace_list = NULL;
19
20 XBT_INLINE tmgr_history_t tmgr_history_new(void)
21 {
22   tmgr_history_t h;
23
24   h = xbt_new0(s_tmgr_history_t, 1);
25
26   h->heap = xbt_heap_new(8, xbt_free_f);        /* Why 8 ? Well, why not... */
27
28   return h;
29 }
30
31 XBT_INLINE void tmgr_history_free(tmgr_history_t h)
32 {
33   xbt_heap_free(h->heap);
34   free(h);
35 }
36
37 tmgr_trace_t tmgr_trace_new_from_generator(const char *id,
38                                           probabilist_event_generator_t generator1,
39                                           probabilist_event_generator_t generator2)
40 {
41   tmgr_trace_t trace = NULL;
42   RngStream rng_stream = NULL;
43   
44   rng_stream = sg_platf_rng_stream_get(id);
45   
46   trace = xbt_new0(s_tmgr_trace_t, 1);
47   trace->type = e_trace_probabilist;
48   
49   trace->s_probabilist.event_generator[0] = generator1;
50   trace->s_probabilist.event_generator[0]->rng_stream = rng_stream;
51   tmgr_event_generator_next_value(trace->s_probabilist.event_generator[0]);
52   
53   //FIXME : may also be a parameter
54   trace->s_probabilist.next_event = 0;
55   
56   if(generator2 == NULL) {
57     trace->s_probabilist.event_generator[1] = generator1;
58   } else {
59     trace->s_probabilist.event_generator[1] = generator2;
60     trace->s_probabilist.event_generator[1]->rng_stream = rng_stream;
61     tmgr_event_generator_next_value(trace->s_probabilist.event_generator[1]);
62   }
63   
64   return trace;
65 }
66
67 probabilist_event_generator_t tmgr_event_generator_new_uniform(double alpha,
68                                                                double beta)
69 {  
70   probabilist_event_generator_t event_generator = NULL;
71   
72   event_generator = xbt_new0(s_probabilist_event_generator_t, 1);
73   event_generator->type = e_generator_uniform;
74   event_generator->s_uniform_parameters.alpha = alpha;
75   event_generator->s_uniform_parameters.beta = beta;
76
77   tmgr_event_generator_next_value(event_generator);
78   
79   return event_generator;
80 }
81
82 probabilist_event_generator_t tmgr_event_generator_new_exponential(double lambda)
83 {  
84   probabilist_event_generator_t event_generator = NULL;
85   
86   event_generator = xbt_new0(s_probabilist_event_generator_t, 1);
87   event_generator->type = e_generator_exponential;
88   event_generator->s_exponential_parameters.lambda = lambda;
89
90   return event_generator;
91 }
92
93 probabilist_event_generator_t tmgr_event_generator_new_weibull(double lambda,
94                                                                double k)
95 {  
96   probabilist_event_generator_t event_generator = NULL;
97   
98   event_generator = xbt_new0(s_probabilist_event_generator_t, 1);
99   event_generator->type = e_generator_weibull;
100   event_generator->s_weibull_parameters.lambda = lambda;
101   event_generator->s_weibull_parameters.k = k;
102
103   tmgr_event_generator_next_value(event_generator);
104   
105   return event_generator;
106 }
107
108 double tmgr_event_generator_next_value(probabilist_event_generator_t generator)
109 {
110   
111   switch(generator->type) {
112     case e_generator_uniform:
113       generator->next_value = (RngStream_RandU01(generator->rng_stream)
114                   * (generator->s_uniform_parameters.beta - generator->s_uniform_parameters.alpha))
115                   + generator->s_uniform_parameters.alpha;
116       break;
117     case e_generator_exponential:
118       generator->next_value = -log(RngStream_RandU01(generator->rng_stream))
119                               / generator->s_exponential_parameters.lambda;
120       break;
121     case e_generator_weibull:
122       generator->next_value = - generator->s_weibull_parameters.lambda
123                               * pow( log(RngStream_RandU01(generator->rng_stream)),
124                                     1.0 / generator->s_weibull_parameters.k );
125   }
126   
127   return generator->next_value;
128 }
129
130 tmgr_trace_t tmgr_trace_new_from_string(const char *id, const char *input,
131                                         double periodicity)
132 {
133   tmgr_trace_t trace = NULL;
134   int linecount = 0;
135   s_tmgr_event_t event;
136   tmgr_event_t last_event = NULL;
137   xbt_dynar_t list;
138   unsigned int cpt;
139   char *val;
140
141   if (trace_list) {
142     trace = xbt_dict_get_or_null(trace_list, id);
143     if (trace) {
144       XBT_WARN("Ignoring redefinition of trace %s", id);
145       return trace;
146     }
147   }
148
149   xbt_assert(periodicity >= 0,
150               "Invalid periodicity %lg (must be positive)", periodicity);
151
152   trace = xbt_new0(s_tmgr_trace_t, 1);
153   trace->type = e_trace_list;
154   trace->s_list.event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
155
156   list = xbt_str_split(input, "\n\r");
157
158   xbt_dynar_foreach(list, cpt, val) {
159     linecount++;
160     xbt_str_trim(val, " \t\n\r\x0B");
161     if (val[0] == '#' || val[0] == '\0' || val[0] == '%')
162       continue;
163
164     if (sscanf(val, "PERIODICITY " "%lg" "\n", &periodicity) == 1)
165       continue;
166
167     if (sscanf(val, "%lg" " " "%lg" "\n", &event.delta, &event.value) != 2)
168       xbt_die("%s:%d: Syntax error in trace\n%s", id, linecount, input);
169
170     if (last_event) {
171       if (last_event->delta > event.delta) {
172         xbt_die("%s:%d: Invalid trace: Events must be sorted, "
173                 "but time %lg > time %lg.\n%s",
174                 id, linecount, last_event->delta, event.delta, input);
175       }
176       last_event->delta = event.delta - last_event->delta;
177     }
178     xbt_dynar_push(trace->s_list.event_list, &event);
179     last_event =
180         xbt_dynar_get_ptr(trace->s_list.event_list,
181                           xbt_dynar_length(trace->s_list.event_list) - 1);
182   }
183   if (last_event)
184     last_event->delta = periodicity;
185
186   if (!trace_list)
187     trace_list = xbt_dict_new_homogeneous((void (*)(void *)) tmgr_trace_free);
188
189   xbt_dict_set(trace_list, id, (void *) trace, NULL);
190
191   xbt_dynar_free(&list);
192   return trace;
193 }
194
195 tmgr_trace_t tmgr_trace_new_from_file(const char *filename)
196 {
197   char *tstr = NULL;
198   FILE *f = NULL;
199   tmgr_trace_t trace = NULL;
200
201   if ((!filename) || (strcmp(filename, "") == 0))
202     return NULL;
203
204   if (trace_list) {
205     trace = xbt_dict_get_or_null(trace_list, filename);
206     if (trace) {
207       XBT_WARN("Ignoring redefinition of trace %s", filename);
208       return trace;
209     }
210   }
211
212   f = surf_fopen(filename, "r");
213   xbt_assert(f != NULL, "Cannot open file '%s' (path=%s)", filename,
214               xbt_str_join(surf_path, ":"));
215
216   tstr = xbt_str_from_file(f);
217   fclose(f);
218   trace = tmgr_trace_new_from_string(filename, tstr, 0.);
219   xbt_free(tstr);
220
221   return trace;
222 }
223
224 tmgr_trace_t tmgr_empty_trace_new(void)
225 {
226   tmgr_trace_t trace = NULL;
227   s_tmgr_event_t event;
228
229   trace = xbt_new0(s_tmgr_trace_t, 1);
230   trace->type = e_trace_list;
231   trace->s_list.event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
232
233   event.delta = 0.0;
234   event.value = 0.0;
235   xbt_dynar_push(trace->s_list.event_list, &event);
236
237   return trace;
238 }
239
240 XBT_INLINE void tmgr_trace_free(tmgr_trace_t trace)
241 {
242   if (!trace)
243     return;
244   
245   switch(trace->type) {
246     case e_trace_list:
247       xbt_dynar_free(&(trace->s_list.event_list));
248       break;
249     case e_trace_probabilist:
250       THROW_UNIMPLEMENTED;
251       break;
252   }
253   free(trace);
254 }
255
256 tmgr_trace_event_t tmgr_history_add_trace(tmgr_history_t h,
257                                           tmgr_trace_t trace,
258                                           double start_time,
259                                           unsigned int offset, void *model)
260 {
261   tmgr_trace_event_t trace_event = NULL;
262
263   trace_event = xbt_new0(s_tmgr_trace_event_t, 1);
264   trace_event->trace = trace;
265   trace_event->idx = offset;
266   trace_event->model = model;
267
268   if(trace->type == e_trace_list) {
269     xbt_assert((trace_event->idx < xbt_dynar_length(trace->s_list.event_list)),
270               "You're referring to an event that does not exist!");
271   }
272   
273   xbt_heap_push(h->heap, trace_event, start_time);
274
275   return trace_event;
276 }
277
278 XBT_INLINE double tmgr_history_next_date(tmgr_history_t h)
279 {
280   if (xbt_heap_size(h->heap))
281     return (xbt_heap_maxkey(h->heap));
282   else
283     return -1.0;
284 }
285
286 tmgr_trace_event_t tmgr_history_get_next_event_leq(tmgr_history_t h,
287                                                    double date,
288                                                    double *value,
289                                                    void **model)
290 {
291   double event_date = tmgr_history_next_date(h);
292   tmgr_trace_event_t trace_event = NULL;
293   tmgr_event_t event = NULL;
294   tmgr_trace_t trace = NULL;
295   double event_delta;
296
297   if (event_date > date)
298     return NULL;
299
300   if (!(trace_event = xbt_heap_pop(h->heap)))
301     return NULL;
302
303   trace = trace_event->trace;
304   *model = trace_event->model;
305   
306   switch(trace->type) {
307     case e_trace_list:
308         
309       event = xbt_dynar_get_ptr(trace->s_list.event_list, trace_event->idx);
310
311       *value = event->value;
312
313       if (trace_event->idx < xbt_dynar_length(trace->s_list.event_list) - 1) {
314         xbt_heap_push(h->heap, trace_event, event_date + event->delta);
315         trace_event->idx++;
316       } else if (event->delta > 0) {        /* Last element, checking for periodicity */
317         xbt_heap_push(h->heap, trace_event, event_date + event->delta);
318         trace_event->idx = 0;
319       } else {                      /* We don't need this trace_event anymore */
320         trace_event->free_me = 1;
321       }
322       break;
323       
324     case e_trace_probabilist:
325       
326       //FIXME : Simplist and not tested
327       //Would only work for failure events for now
328       *value = (double) trace->s_probabilist.next_event;
329       if(trace->s_probabilist.next_event == 0) {
330         event_delta = tmgr_event_generator_next_value(trace->s_probabilist.event_generator[0]);
331         trace->s_probabilist.next_event = 0;
332       } else {
333         event_delta = tmgr_event_generator_next_value(trace->s_probabilist.event_generator[1]);
334         trace->s_probabilist.next_event = 1;
335       }
336       xbt_heap_push(h->heap, trace_event, event_date + event_delta);
337       
338       break;
339   }
340
341   return trace_event;
342 }
343
344 XBT_INLINE void tmgr_finalize(void)
345 {
346   xbt_dict_free(&trace_list);
347 }
348
349 int tmgr_trace_event_free(tmgr_trace_event_t trace_event)
350 {
351   if (trace_event->free_me) {
352     xbt_free(trace_event);
353     return 1;
354   }
355   return 0;
356 }