My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
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 */
25 #include "stats.h"
26 #include "logging.h"
27 
28 #include <stdlib.h>
29 
35 struct stat_msg_hdr {
37  int n_samples;
38 };
39 
40 int is_thread_stat(enum stat_id id) {
41  for (int i=0; i < N_REPORTED_THREAD_STAT_TYPES; i++) {
42  if (reported_thread_stat_types[i].id == id) {
43  return 1;
44  }
45  }
46  return 0;
47 }
48 
49 int is_msu_stat(enum stat_id id) {
50  for (int i=0; i < N_REPORTED_MSU_STAT_TYPES; i++) {
51  if (reported_msu_stat_types[i].id == id) {
52  return 1;
53  }
54  }
55  return 0;
56 }
57 
58 
59 
61 static int init_stat_sample(int max_stats, struct stat_sample *sample) {
62  sample->max_stats = max_stats;
63  sample->stats = calloc(max_stats, sizeof(*sample->stats));
64  if (sample->stats == NULL) {
65  log_error("Error allocating sample stats");
66  return -1;
67  }
68  return 0;
69 }
70 
71 void free_stat_samples(struct stat_sample *sample, int n_samples) {
72  if (sample != NULL) {
73  for (int i=0; i<n_samples; i++) {
74  free(sample[i].stats);
75  }
76  free(sample);
77  }
78 }
79 
80 struct stat_sample *init_stat_samples(int max_stats, int n_samples) {
81  struct stat_sample *sample = calloc(n_samples, sizeof(*sample));
82  if (sample == NULL) {
83  log_error("Could not allocate %d stat samples", n_samples);
84  return NULL;
85  }
86  for (int i=0; i<n_samples; i++) {
87  if (init_stat_sample(max_stats, &sample[i]) != 0) {
88  log_error("Error initializing stat sample %d", i);
89  free(sample);
90  return NULL;
91  }
92  }
93  return sample;
94 }
95 
96 size_t serialized_stat_sample_size(struct stat_sample *sample, int n_samples) {
97  size_t size = sizeof(sample->hdr) * n_samples;
98  for (int i=0; i<n_samples; i++) {
99  size += sizeof(*sample->stats) * sample[i].hdr.n_stats;
100  }
101  size += sizeof(struct stat_msg_hdr);
102  return size;
103 }
104 
107 static ssize_t serialize_stat_sample(struct stat_sample *sample, void *buffer, size_t buff_len) {
108  if (buff_len < sizeof(sample->hdr) + sizeof(*sample->stats) * sample->hdr.n_stats) {
109  log_error("Buffer isn't large enough to fit serialized stat sample");
110  return -1;
111  }
112 
113  char *curr_buff = buffer;
114  memcpy(curr_buff, &sample->hdr, sizeof(sample->hdr));
115  curr_buff += sizeof(sample->hdr);
116  size_t stat_size = sizeof(*sample->stats) * sample->hdr.n_stats;
117  memcpy(curr_buff, sample->stats, stat_size);
118 
119  return stat_size + sizeof(sample->hdr);
120 }
121 
122 ssize_t serialize_stat_samples(struct stat_sample *samples, int n_samples,
123  void *buffer, size_t buff_len) {
124  if (buff_len < serialized_stat_sample_size(samples, n_samples)) {
125  log_error("Buffer isn't large enough to fit serialized stat samples");
126  return -1;
127  }
128 
129  struct stat_msg_hdr hdr = { .n_samples = n_samples };
130  memcpy(buffer, &hdr, sizeof(hdr));
131  hdr.n_samples= n_samples;
132 
133  char *curr_buff = ((char*)buffer) + sizeof(hdr);
134  char *end_buff = curr_buff + buff_len;
135 
136  for (int i=0; i<n_samples; i++) {
137  size_t new_size = serialize_stat_sample(&samples[i], curr_buff, end_buff-curr_buff);
138  if (new_size < 0) {
139  log_error("Erorr serializing stat sample %d", i);
140  return -1;
141  }
142  curr_buff += new_size;
143  }
144 
145  log(LOG_STAT_SERIALIZATION, "Serialized %d samples into buffer of size %d",
146  n_samples, (int)(curr_buff - (char*)buffer));
147  return curr_buff - (char*)buffer;
148 }
149 
153 static ssize_t deserialize_stat_sample(void *buffer, size_t buff_len, struct stat_sample *sample) {
154  if (buff_len < sizeof(sample->hdr)) {
155  log_error("Buffer isn't large enough to fit header");
156  return -1;
157  }
158 
159  char *curr_buff = buffer;
160  memcpy(&sample->hdr, buffer, sizeof(sample->hdr));
161  curr_buff += sizeof(sample->hdr);
162 
163  size_t stat_size = sizeof(*sample->stats) * sample->hdr.n_stats;
164  if (sizeof(sample->hdr) + stat_size > buff_len) {
165  log_error("Buffer isn't large enough to fit statistics");
166  return -1;
167  }
168  if (sample->max_stats < sample->hdr.n_stats) {
169  log_error("Not enough statistics allocated to fit deserialized stats");
170  return -1;
171  }
172  memcpy(sample->stats, curr_buff, stat_size);
173  return sizeof(sample->hdr) + stat_size;
174 }
175 
176 int deserialize_stat_samples(void *buffer, size_t buff_len, struct stat_sample *samples,
177  int n_samples) {
178  struct stat_msg_hdr *hdr = buffer;
179  if (buff_len < sizeof(*hdr)) {
180  log_error("Buffer not large enough for stat message header");
181  return -1;
182  }
183  if (n_samples < hdr->n_samples) {
184  log_error("Number of allocated samples smaller than in serialized buffer");
185  return -1;
186  }
187 
188  char *curr_buff = ((char *)buffer) + sizeof(*hdr);
189  char *end_buff = curr_buff + buff_len;
190  for (int i=0; i < hdr->n_samples; i++) {
191  ssize_t consumed = deserialize_stat_sample(curr_buff, end_buff - curr_buff, &samples[i]);
192  if (consumed < 0) {
193  log_error("Error deserializing stat sample %d", i);
194  return -1;
195  }
196  curr_buff += consumed;
197  }
198 
199  log(LOG_STAT_SERIALIZATION, "Deserialized buffer of size %d into %d samples",
200  ((int)(curr_buff - (char*) buffer)), hdr->n_samples);
201 
202  if (curr_buff - (char*)buffer < buff_len) {
203  log_warn("Entire buffer not used when deserializing stats");
204  }
205  return hdr->n_samples;
206 }
int max_stats
The allocated size of the stat_sample::stats structure.
Definition: stats.h:56
size_t serialized_stat_sample_size(struct stat_sample *sample, int n_samples)
Determines the size needed to hold the serialized version of sample.
Definition: stats.c:96
struct timed_stat * stats
The statistics in question.
Definition: stats.h:58
ssize_t serialize_stat_samples(struct stat_sample *samples, int n_samples, void *buffer, size_t buff_len)
Serializes from the provided samples into the buffer
Definition: stats.c:122
A single stat sample for a single item.
Definition: stats.h:53
struct stat_sample * init_stat_samples(int max_stats, int n_samples)
Initilizes n sets of samples of statistics, each of which contains max_stats points.
Definition: stats.c:80
static struct stat_type_label reported_msu_stat_types[]
Definition: stats.h:111
int deserialize_stat_samples(void *buffer, size_t buff_len, struct stat_sample *samples, int n_samples)
Deserializes from the provided buffer into the samples structure.
Definition: stats.c:176
stat_id
The identifiers with which stats can be logged.
Definition: stat_ids.h:32
static ssize_t serialize_stat_sample(struct stat_sample *sample, void *buffer, size_t buff_len)
Serializes a single stat sample into a buffer of size buff_len.
Definition: stats.c:107
Logging of status messages to the terminal.
Functions for the sending and receiving of statistics between ctrl and runtime.
int n_stats
The size of the sample (number of stats, not number of items)
Definition: stats.h:49
static int init_stat_sample(int max_stats, struct stat_sample *sample)
Initializes a single stat sample with room to hold max_stats statistics.
Definition: stats.c:61
#define N_REPORTED_MSU_STAT_TYPES
Definition: stats.h:114
#define log_error(fmt,...)
Definition: logging.h:101
int n_samples
The number of items sampled (not the size of the sample)
Definition: stats.c:37
static ssize_t deserialize_stat_sample(void *buffer, size_t buff_len, struct stat_sample *sample)
Deserializes a single stat sample from a buffer.
Definition: stats.c:153
static struct stat_type_label reported_thread_stat_types[]
Definition: stats.h:117
#define log(level, fmt,...)
Log at a custom level.
Definition: logging.h:147
int is_msu_stat(enum stat_id id)
Definition: stats.c:49
#define N_REPORTED_THREAD_STAT_TYPES
Definition: stats.h:120
Header for a serialized stats message.
Definition: stats.c:35
struct stat_sample_hdr hdr
Definition: stats.h:54
#define log_warn(fmt,...)
Definition: logging.h:113
int is_thread_stat(enum stat_id id)
Definition: stats.c:40
void free_stat_samples(struct stat_sample *sample, int n_samples)
Frees a set of stat samples.
Definition: stats.c:71