1 /* Copyright (c) 2004-2005, 2007, 2009-2014. The SimGrid Team.
2 * All rights reserved. */
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. */
7 #include "xbt/sysdep.h"
11 #include "src/surf/trace_mgr.hpp"
12 #include "surf_private.h"
13 #include "xbt/RngStream.h"
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_trace, surf, "Surf trace management");
18 static xbt_dict_t trace_list = NULL;
20 simgrid::trace_mgr::trace::trace()
24 simgrid::trace_mgr::trace::~trace()
26 xbt_dynar_free(&event_list);
28 simgrid::trace_mgr::future_evt_set::future_evt_set()
32 simgrid::trace_mgr::future_evt_set::~future_evt_set()
34 xbt_heap_free(p_heap);
37 tmgr_trace_t tmgr_trace_new_from_string(const char *id, const char *input, double periodicity)
39 tmgr_trace_t trace = NULL;
42 tmgr_event_t last_event = NULL;
48 trace = (tmgr_trace_t)xbt_dict_get_or_null(trace_list, id);
50 XBT_WARN("Ignoring redefinition of trace %s", id);
55 xbt_assert(periodicity >= 0,
56 "Invalid periodicity %g (must be positive)", periodicity);
58 trace = new simgrid::trace_mgr::trace();
59 trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
61 list = xbt_str_split(input, "\n\r");
63 xbt_dynar_foreach(list, cpt, val) {
65 xbt_str_trim(val, " \t\n\r\x0B");
66 if (val[0] == '#' || val[0] == '\0' || val[0] == '%')
69 if (sscanf(val, "PERIODICITY " "%lg" "\n", &periodicity) == 1)
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);
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);
81 last_event->delta = event.delta - last_event->delta;
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);
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);
94 last_event->delta = periodicity;
97 trace_list = xbt_dict_new_homogeneous((void (*)(void *)) tmgr_trace_free);
99 xbt_dict_set(trace_list, id, (void *) trace, NULL);
101 xbt_dynar_free(&list);
105 tmgr_trace_t tmgr_trace_new_from_file(const char *filename)
107 tmgr_trace_t trace = NULL;
109 if ((!filename) || (strcmp(filename, "") == 0))
113 trace = (tmgr_trace_t)xbt_dict_get_or_null(trace_list, filename);
115 XBT_WARN("Ignoring redefinition of trace %s", filename);
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, ":"));
124 char *tstr = xbt_str_from_file(f);
126 trace = tmgr_trace_new_from_string(filename, tstr, 0.);
132 tmgr_trace_t tmgr_empty_trace_new(void)
134 tmgr_trace_t trace = NULL;
135 s_tmgr_event_t event;
137 trace = new simgrid::trace_mgr::trace();
138 trace->event_list = xbt_dynar_new(sizeof(s_tmgr_event_t), NULL);
142 xbt_dynar_push(trace->event_list, &event);
147 void tmgr_trace_free(tmgr_trace_t trace)
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)
155 tmgr_trace_iterator_t trace_iterator = NULL;
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;
162 xbt_assert((trace_iterator->idx < xbt_dynar_length(trace->event_list)), "Your trace should have at least one event!");
164 xbt_heap_push(p_heap, trace_iterator, start_time);
166 return trace_iterator;
169 /** @brief returns the date of the next occurring event (pure function) */
170 double simgrid::trace_mgr::future_evt_set::next_date() const
172 if (xbt_heap_size(p_heap))
173 return (xbt_heap_maxkey(p_heap));
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)
182 double event_date = next_date();
183 if (event_date > date)
186 tmgr_trace_iterator_t trace_iterator = (tmgr_trace_iterator_t)xbt_heap_pop(p_heap);
187 if (trace_iterator == NULL)
190 tmgr_trace_t trace = trace_iterator->trace;
191 *resource = trace_iterator->resource;
193 tmgr_event_t event = (tmgr_event_t)xbt_dynar_get_ptr(trace->event_list, trace_iterator->idx);
195 *value = event->value;
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;
207 return trace_iterator;
210 void tmgr_finalize(void)
212 xbt_dict_free(&trace_list);
215 void tmgr_trace_event_unref(tmgr_trace_iterator_t *trace_event)
217 if ((*trace_event)->free_me) {
218 xbt_free(*trace_event);
219 *trace_event = nullptr;