My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
controller_stats.c
Go to the documentation of this file.
1 /*
2 START OF LICENSE STUB
3  DeDOS: Declarative Dispersion-Oriented Software
4  Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 END OF LICENSE STUB
19 */
20 #include "controller_stats.h"
21 #include "timeseries.h"
22 #include "stats.h"
23 #include "logging.h"
24 #include "controller_mysql.h"
25 #include "controller_dfg.h"
26 #include "stat_msg_handler.h"
27 
28 #include <stdbool.h>
29 
30 struct stat_type {
31  enum stat_id id;
32  char *name;
34  int num_items;
35  struct stat_item *items;
36 };
37 
38 static struct stat_type stat_types[] = {
40 };
41 
42 #define N_STAT_TYPES sizeof(stat_types) / sizeof(*stat_types)
43 static bool stats_initialized = false;
44 
45 #define CHECK_INIT \
46  if (!stats_initialized) { \
47  log_warn("Statistics not initialized"); \
48  return -1; \
49  }
50 
51 
52 static struct stat_type *get_stat_type(enum stat_id id) {
53  for (int i=0; i < N_STAT_TYPES; i++) {
54  if (stat_types[i].id == id) {
55  return &stat_types[i];
56  }
57  }
58  return NULL;
59 }
60 
61 static struct timed_rrdb *get_stat(enum stat_id id, unsigned int item_id) {
62  if (!stats_initialized) {
63  log_error("Stats not initialized");
64  return NULL;
65  }
66  if (item_id >= MAX_STAT_ID) {
67  log_error("Item ID %u too high!", id);
68  return NULL;
69  }
70  struct stat_type *type = get_stat_type(id);
71  if (type == NULL) {
72  log_error("Type %d not initialized", id);
73  return NULL;
74  }
75  if (type->id_indices[item_id] == -1) {
76  //log_error("ID %u for types %d not initialized", item_id, id);
77  return NULL;
78  }
79  if (type->items == NULL) {
80  return NULL;
81  }
82  return &type->items[type->id_indices[item_id]].stats;
83 }
84 
86  unsigned int runtime_id, unsigned int thread_id) {
87  if (!stats_initialized) {
88  return NULL;
89  }
90  int item_id = runtime_id * MAX_THREADS + thread_id ;
91  return get_stat(id, item_id);
92 }
93 
94 
95 struct timed_rrdb *get_msu_stat(enum stat_id id, unsigned int msu_id) {
96  if (!stats_initialized) {
97  return NULL;
98  }
99  return get_stat(id, msu_id);
100 }
101 
102 static int unregister_stat(enum stat_id stat_id, unsigned int item_id) {
103  if (!stats_initialized) {
104  log_error("Stats not initialized");
105  return -1;
106  }
107  struct stat_type *type = get_stat_type(stat_id);
108  if (type->id_indices[item_id] == -1) {
109  log_warn("Item ID %u not assigned", item_id);
110  return -1;
111  }
112  type->id_indices[item_id] = -1;
113  return 0;
114 }
115 
116 int unregister_msu_stats(unsigned int msu_id) {
117  CHECK_INIT;
118  for (int i=0; i < N_REPORTED_MSU_STAT_TYPES; i++) {
120  }
121  return 0;
122 }
123 
124 int unregister_thread_stats(unsigned int thread_id, unsigned int runtime_id) {
125  CHECK_INIT;
126  for (int i=0; i < N_REPORTED_THREAD_STAT_TYPES; i++) {
127  unregister_stat(reported_thread_stat_types[i].id, runtime_id * MAX_THREADS + thread_id);
128  }
129  return 0;
130 }
131 
132 int register_stat(enum stat_id stat_id, unsigned int item_id) {
133  CHECK_INIT;
134  if (item_id >= MAX_STAT_ID) {
135  log_error("Item ID %u too high!", item_id);
136  return -1;
137  }
138  if (!stats_initialized) {
139  log_error("Stats not initialized");
140  return -1;
141  }
142  struct stat_type *type = get_stat_type(stat_id);
143  if (type->id_indices[item_id] != -1) {
144  log_warn("Item ID %u already assigned index %d",
145  item_id, type->id_indices[item_id]);
146  return 1;
147  }
148  log(LOG_STATS, "Allocating new msu stat item: %u", item_id);
149  int index = type->num_items;
150  type->id_indices[item_id] = index;
151  type->num_items++;
152  struct stat_item *new_item = realloc(type->items, sizeof(*type->items) * type->num_items);
153  if (new_item != NULL) {
154  type->items = new_item;
155  } else {
156  log_error("Error reallocating stat item");
157  return -1;
158  }
159 
160  struct stat_item *item = &type->items[index];
161  item->id = item_id;
162  for (int i=0; i < RRDB_ENTRIES; i++) {
163  item->stats.time[i].tv_sec = -1;
164  }
165  memset(&item->stats, 0, sizeof(item->stats));
166 
167  return 0;
168 }
169 
170 int register_msu_stats(unsigned int msu_id, int msu_type_id, int thread_id, int runtime_id) {
171  CHECK_INIT;
172  db_register_msu_stats(msu_id, msu_type_id, thread_id, runtime_id);
173  for (int i=0; i < N_REPORTED_MSU_STAT_TYPES; i++) {
174  if (register_stat(reported_msu_stat_types[i].id, msu_id)) {
175  log_warn("Couldn't register msu %u", msu_id);
176  }
177  }
178  return 0;
179 }
180 
181 int register_thread_stats(unsigned int thread_id, unsigned int runtime_id) {
182  CHECK_INIT;
183  for (int i=0; i < N_REPORTED_THREAD_STAT_TYPES; i++) {
184  if (register_stat(reported_thread_stat_types[i].id, runtime_id * MAX_THREADS + thread_id)) {
185  log_warn("Couldn't register thread %u", thread_id);
186  }
187  }
188  db_register_thread_stats(thread_id, runtime_id);
189  return 0;
190 }
191 
193  if (stats_initialized) {
194  log_error("Statistics already initialized");
195  return -1;
196  }
197 
198  for (int i=0; i < N_REPORTED_STAT_TYPES; i++) {
199  for (int j=0; j<MAX_STAT_ID; j++) {
200  stat_types[i].id_indices[j] = -1;
201  }
202  stat_types[i].items = NULL;
203  }
204  stats_initialized = true;
205 
206  struct dedos_dfg *dfg = get_dfg();
207 
208  if (dfg == NULL) {
209  log_error("DFG must be initialized before initializing statistics");
210  return -1;
211  }
212  for (int i=0; i < dfg->n_runtimes; i++) {
213  struct dfg_runtime *rt = dfg->runtimes[i];
214  for (int j=0; j < rt->n_pinned_threads + rt->n_unpinned_threads; j++) {
215  register_thread_stats(rt->threads[j]->id, rt->id);
216  }
217  // Also register output thread
219  }
220  for (int i=0; i < dfg->n_msus; i++) {
221  register_msu_stats(dfg->msus[i]->id,
222  dfg->msus[i]->type->id,
223  dfg->msus[i]->scheduling.thread->id,
224  dfg->msus[i]->scheduling.runtime->id);
225  }
227  return 0;
228 }
229 
230 
231 void show_stats(struct dfg_msu *msu){
232  if (!stats_initialized) {
233  return;
234  }
235  int stat_id = msu->id;
236  for (int i=0; i < N_REPORTED_MSU_STAT_TYPES; i++) {
237  struct timed_rrdb *ts = get_msu_stat(reported_msu_stat_types[i].id, stat_id);
238  printf("******* Statistic: %s\n", reported_msu_stat_types[i].name);
239  print_timeseries(ts);
240  }
241 }
static bool stats_initialized
int unregister_msu_stats(unsigned int msu_id)
int n_msus
The number of MSUs in dedos_dfg::msus.
Definition: dfg.h:255
#define MAX_STAT_ID
Round-robin database (circular buffer) for storing timeseries data.
Definition: timeseries.h:36
int unregister_thread_stats(unsigned int thread_id, unsigned int runtime_id)
struct dfg_scheduling scheduling
Information about where an MSU is scheduled.
Definition: dfg.h:225
#define MAX_THREADS
The maximum number of threads that may be present on a runtime.
Definition: dfg.h:47
static struct stat_type stat_types[]
static struct stat_type_label reported_msu_stat_types[]
Definition: stats.h:111
stat_id
The identifiers with which stats can be logged.
Definition: stat_ids.h:32
int init_stats_msg_handler()
struct stat_item * items
The items of this type being logged.
Definition: rt_stats.c:72
static int unregister_stat(enum stat_id stat_id, unsigned int item_id)
int id
Unique identifier for the runtime.
Definition: dfg.h:74
static struct stat_type * get_stat_type(enum stat_id id)
unsigned int id
A unique identifier for the item being logged.
Definition: rt_stats.c:52
Logging of status messages to the terminal.
#define N_STAT_TYPES
struct timed_rrdb * get_msu_stat(enum stat_id id, unsigned int msu_id)
Functions for the sending and receiving of statistics between ctrl and runtime.
struct dfg_msu_type * type
The type of the MSU and meta-routing information.
Definition: dfg.h:221
#define REPORTED_STAT_TYPES
Definition: stats.h:96
Representation of a runtime in the DFG.
Definition: dfg.h:73
The structure holding all items of a type of stats.
Definition: rt_stats.c:62
struct timespec time
Definition: stats.h:38
The internal statistics structure where stats are aggregated One per statistic-item.
Definition: rt_stats.c:50
const char * name
Definition: http_parser.c:485
struct dfg_runtime * runtime
The runtime on which an MSU is running.
Definition: dfg.h:117
int register_msu_stats(unsigned int msu_id, int msu_type_id, int thread_id, int runtime_id)
int n_runtimes
The number of elements in dedos_dfg::runtimes.
Definition: dfg.h:260
#define N_REPORTED_MSU_STAT_TYPES
Definition: stats.h:114
#define log_error(fmt,...)
Definition: logging.h:101
int id
A unique identifier for the MSU.
Definition: dfg.h:217
int n_unpinned_threads
Number of the above-threads which are unpinned.
Definition: dfg.h:81
#define RRDB_ENTRIES
timeseries.h
Definition: timeseries.h:32
struct dfg_thread * thread
The thread on which an MSU is running.
Definition: dfg.h:118
#define N_REPORTED_STAT_TYPES
Number of reported stat types.
Definition: stats.h:109
int id
Unique identifier for the thread.
Definition: dfg.h:105
Representation of a single MSU in the dfg.
Definition: dfg.h:216
static struct stat_type_label reported_thread_stat_types[]
Definition: stats.h:117
int register_stat(enum stat_id stat_id, unsigned int item_id)
int n_pinned_threads
Number of the above-threads which are pinned.
Definition: dfg.h:80
int id
A unique identifier for the MSU type.
Definition: dfg.h:177
enum stat_id id
Stat ID as defined in stats.h.
Definition: rt_stats.c:63
static struct timed_rrdb * get_stat(enum stat_id id, unsigned int item_id)
int num_items
Number of items currently registered for logging.
Definition: rt_stats.c:69
Top-level structure holding the data-flow graph.
Definition: dfg.h:239
static struct dedos_dfg * dfg
Static local copy of the DFG, so each call doesn't have to pass a copy.
Definition: dfg.c:32
void print_timeseries(struct timed_rrdb *timeseries)
Prints the beginning and end of a timeseries.
Definition: timeseries.c:82
struct timed_stat * stats
Timestamp and data for each gathered statistic.
Definition: rt_stats.c:55
int register_thread_stats(unsigned int thread_id, unsigned int runtime_id)
int db_register_thread_stats(int thread_id, int runtime_id)
struct dfg_runtime * runtimes[16]
The runtimes present in the application.
Definition: dfg.h:258
struct dfg_thread * threads[32]
Threads located on the runtime.
Definition: dfg.h:79
int db_register_msu_stats(int msu_id, int msu_type_id, int thread_id, int runtime_id)
static int runtime_id(int runtime_fd)
#define log(level, fmt,...)
Log at a custom level.
Definition: logging.h:147
struct dedos_dfg * get_dfg()
Definition: runtime_dfg.c:115
int id_indices[MAX_STAT_ITEM_ID]
Index at which the IDs are stored.
Definition: rt_stats.c:68
#define N_REPORTED_THREAD_STAT_TYPES
Definition: stats.h:120
struct timed_rrdb * get_thread_stat(enum stat_id id, unsigned int runtime_id, unsigned int thread_id)
#define log_warn(fmt,...)
Definition: logging.h:113
#define CHECK_INIT
void show_stats(struct dfg_msu *msu)
struct dfg_msu * msus[512]
The MSUs present in the application.
Definition: dfg.h:253
int init_statistics()
Initializes the entire stats module.