Logo AND Algorithmique Numérique Distribuée

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