Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
0b9cd01d73a6734081be0acd280d3358fc383169
[simgrid.git] / src / surf / trace_mgr.cpp
1 /* Copyright (c) 2004-2005, 2007, 2009-2014. 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 "src/surf/trace_mgr.hpp"
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 simgrid::trace_mgr::trace::trace()
21 {
22 }
23
24 simgrid::trace_mgr::trace::~trace()
25 {
26   xbt_dynar_free(&event_list);
27 }
28 simgrid::trace_mgr::future_evt_set::future_evt_set()
29 {
30 }
31
32 simgrid::trace_mgr::future_evt_set::~future_evt_set()
33 {
34   xbt_heap_free(p_heap);
35 }
36
37 tmgr_trace_t tmgr_trace_new_from_string(const char *id, const char *input, double periodicity)
38 {
39   tmgr_trace_t trace = NULL;
40   int linecount = 0;
41   s_tmgr_event_t event;
42   tmgr_event_t last_event = NULL;
43   xbt_dynar_t list;
44   unsigned int cpt;
45   char *val;
46
47   if (trace_list) {
48     trace = (tmgr_trace_t)xbt_dict_get_or_null(trace_list, id);
49     if (trace) {
50       XBT_WARN("Ignoring redefinition of trace %s", id);
51       return trace;
52     }
53   }
54
55   xbt_assert(periodicity >= 0,
56               "Invalid periodicity %g (must be positive)", periodicity);
57
58   trace = new simgrid::trace_mgr::trace();
59   trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
60
61   list = xbt_str_split(input, "\n\r");
62
63   xbt_dynar_foreach(list, cpt, val) {
64     linecount++;
65     xbt_str_trim(val, " \t\n\r\x0B");
66     if (val[0] == '#' || val[0] == '\0' || val[0] == '%')
67       continue;
68
69     if (sscanf(val, "PERIODICITY " "%lg" "\n", &periodicity) == 1)
70       continue;
71
72     if (sscanf(val, "%lg" " " "%lg" "\n", &event.delta, &event.value) != 2)
73       xbt_die("%s:%d: Syntax error in trace\n%s", id, linecount, input);
74
75     if (last_event) {
76       if (last_event->delta > event.delta) {
77         xbt_die("%s:%d: Invalid trace: Events must be sorted, "
78                 "but time %g > time %g.\n%s",
79                 id, linecount, last_event->delta, event.delta, input);
80       }
81       last_event->delta = event.delta - last_event->delta;
82     } else {
83       if(event.delta > 0.0){
84         s_tmgr_event_t first_event;
85         first_event.delta=event.delta;
86         first_event.value=-1.0;
87         xbt_dynar_push(trace->event_list, &first_event);
88       }
89     }
90     xbt_dynar_push(trace->event_list, &event);
91     last_event = (tmgr_event_t)xbt_dynar_get_ptr(trace->event_list, xbt_dynar_length(trace->event_list) - 1);
92   }
93   if (last_event)
94     last_event->delta = periodicity;
95
96   if (!trace_list)
97     trace_list = xbt_dict_new_homogeneous((void (*)(void *)) tmgr_trace_free);
98
99   xbt_dict_set(trace_list, id, (void *) trace, NULL);
100
101   xbt_dynar_free(&list);
102   return trace;
103 }
104
105 tmgr_trace_t tmgr_trace_new_from_file(const char *filename)
106 {
107   tmgr_trace_t trace = NULL;
108
109   if ((!filename) || (strcmp(filename, "") == 0))
110     return NULL;
111
112   if (trace_list) {
113     trace = (tmgr_trace_t)xbt_dict_get_or_null(trace_list, filename);
114     if (trace) {
115       XBT_WARN("Ignoring redefinition of trace %s", filename);
116       return trace;
117     }
118   }
119
120   FILE *f = surf_fopen(filename, "r");
121   xbt_assert(f != NULL,
122       "Cannot open file '%s' (path=%s)", filename, xbt_str_join(surf_path, ":"));
123
124   char *tstr = xbt_str_from_file(f);
125   fclose(f);
126   trace = tmgr_trace_new_from_string(filename, tstr, 0.);
127   xbt_free(tstr);
128
129   return trace;
130 }
131
132 tmgr_trace_t tmgr_empty_trace_new(void)
133 {
134   tmgr_trace_t trace = NULL;
135   s_tmgr_event_t event;
136
137   trace = new simgrid::trace_mgr::trace();
138   trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
139
140   event.delta = 0.0;
141   event.value = 0.0;
142   xbt_dynar_push(trace->event_list, &event);
143
144   return trace;
145 }
146
147 void tmgr_trace_free(tmgr_trace_t trace)
148 {
149   delete trace;
150 }
151
152 /** @brief Registers a new trace into the future event set, and get an iterator over the integrated trace  */
153 tmgr_trace_iterator_t simgrid::trace_mgr::future_evt_set::add_trace(tmgr_trace_t trace, double start_time, surf::Resource *resource)
154 {
155   tmgr_trace_iterator_t trace_iterator = NULL;
156
157   trace_iterator = xbt_new0(s_tmgr_trace_event_t, 1);
158   trace_iterator->trace = trace;
159   trace_iterator->idx = 0;
160   trace_iterator->resource = resource;
161
162   xbt_assert((trace_iterator->idx < xbt_dynar_length(trace->event_list)), "Your trace should have at least one event!");
163
164   xbt_heap_push(p_heap, trace_iterator, start_time);
165
166   return trace_iterator;
167 }
168
169 /** @brief returns the date of the next occurring event (pure function) */
170 double simgrid::trace_mgr::future_evt_set::next_date() const
171 {
172   if (xbt_heap_size(p_heap))
173     return (xbt_heap_maxkey(p_heap));
174   else
175     return -1.0;
176 }
177
178 /** @brief Retrieves the next occurring event, or NULL if none happens before #date */
179 tmgr_trace_iterator_t simgrid::trace_mgr::future_evt_set::pop_leq(
180     double date, double *value, simgrid::surf::Resource **resource)
181 {
182   double event_date = next_date();
183   if (event_date > date)
184     return NULL;
185
186   tmgr_trace_iterator_t trace_iterator = (tmgr_trace_iterator_t)xbt_heap_pop(p_heap);
187   if (trace_iterator == NULL)
188     return NULL;
189
190   tmgr_trace_t trace = trace_iterator->trace;
191   *resource = trace_iterator->resource;
192
193   tmgr_event_t event = (tmgr_event_t)xbt_dynar_get_ptr(trace->event_list, trace_iterator->idx);
194
195   *value = event->value;
196
197   if (trace_iterator->idx < xbt_dynar_length(trace->event_list) - 1) {
198     xbt_heap_push(p_heap, trace_iterator, event_date + event->delta);
199     trace_iterator->idx++;
200   } else if (event->delta > 0) {        /* Last element, checking for periodicity */
201     xbt_heap_push(p_heap, trace_iterator, event_date + event->delta);
202     trace_iterator->idx = 1; /* not 0 as the first event is a placeholder to handle when events really start */
203   } else {                      /* We don't need this trace_event anymore */
204     trace_iterator->free_me = 1;
205   }
206
207   return trace_iterator;
208 }
209
210 void tmgr_finalize(void)
211 {
212   xbt_dict_free(&trace_list);
213 }
214
215 void tmgr_trace_event_unref(tmgr_trace_iterator_t *trace_event)
216 {
217   if ((*trace_event)->free_me) {
218     xbt_free(*trace_event);
219     *trace_event = nullptr;
220   }
221 }