2 This file is part of GNUnet.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file sensor/gnunet-service-sensor_analysis.c
23 * @brief sensor service analysis functionality
24 * @author Omar Tarabai
27 #include "gnunet_util_lib.h"
29 #include "gnunet_peerstore_service.h"
30 #include "gnunet_sensor_model_plugin.h"
32 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-analysis",__VA_ARGS__)
35 * Carries information about the analysis model
36 * corresponding to one sensor
44 struct SensorModel *prev;
49 struct SensorModel *next;
52 * Pointer to sensor info structure
54 struct GNUNET_SENSOR_SensorInfo *sensor;
57 * Watcher of sensor values
59 struct GNUNET_PEERSTORE_WatchContext *wc;
62 * State of sensor. #GNUNET_YES if anomalous, #GNUNET_NO otherwise.
67 * Number of anomalous readings (positive) received in a row.
72 * Number of non-anomalous (negative) readings received in a row.
77 * Closure for model plugin.
78 * Usually, the instance of the model created for this sensor.
87 static const struct GNUNET_CONFIGURATION_Handle *cfg;
90 * Hashmap of loaded sensors
92 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
97 static char *model_lib_name;
102 static struct GNUNET_SENSOR_ModelFunctions *model_api;
105 * Handle to peerstore service
107 static struct GNUNET_PEERSTORE_Handle *peerstore;
110 * Head of DLL of created models
112 static struct SensorModel *models_head;
115 * Tail of DLL of created models
117 static struct SensorModel *models_tail;
122 static struct GNUNET_PeerIdentity peerid;
125 * How many subsequent values required to flip anomaly label.
126 * E.g. After 3 subsequent anomaly reports, status change to anomalous.
128 static unsigned long long confirmation_count;
131 * Destroy a created model
134 destroy_sensor_model (struct SensorModel *sensor_model)
136 GNUNET_assert (NULL != sensor_model);
137 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying sensor model for `%s'.\n",
138 sensor_model->sensor->name);
139 if (NULL != sensor_model->wc)
141 GNUNET_PEERSTORE_watch_cancel (sensor_model->wc);
142 sensor_model->wc = NULL;
144 if (NULL != sensor_model->cls)
146 model_api->destroy_model (sensor_model->cls);
147 sensor_model->cls = NULL;
149 GNUNET_free (sensor_model);
155 * Stop the sensor analysis module
158 SENSOR_analysis_stop ()
160 struct SensorModel *sm;
162 LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping sensor analysis module.\n");
163 while (NULL != models_head)
166 GNUNET_CONTAINER_DLL_remove (models_head, models_tail, sm);
167 destroy_sensor_model (sm);
169 if (NULL != peerstore)
171 GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES);
174 if (NULL != model_api)
176 GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model_api));
177 GNUNET_free (model_lib_name);
178 model_lib_name = NULL;
184 * Sensor value watch callback
186 * @param cls Sensor model struct
187 * @param record Received record from peerstore, should contain new sensor value
188 * @param emsg Error message from peerstore if any, NULL if no errors
189 * @return #GNUNET_YES
192 sensor_watcher (void *cls, struct GNUNET_PEERSTORE_Record *record, char *emsg)
194 struct SensorModel *model = cls;
198 LOG (GNUNET_ERROR_TYPE_DEBUG,
199 "Received a sensor value, will feed to sensor model.\n");
200 if (sizeof (double) != record->value_size)
202 LOG (GNUNET_ERROR_TYPE_ERROR, _("Received an invalid sensor value."));
205 val = (double *) (record->value);
206 anomalous = model_api->feed_model (model->cls, *val);
207 if (GNUNET_YES == anomalous)
209 model->positive_count++;
210 model->negative_count = 0;
211 if (GNUNET_NO == model->anomalous &&
212 model->positive_count >= confirmation_count)
214 model->anomalous = GNUNET_YES;
215 LOG (GNUNET_ERROR_TYPE_WARNING,
216 "Anomaly state started for sensor `%s', value: %f.\n",
217 model->sensor->name, val);
218 SENSOR_reporting_anomaly_update (model->sensor, model->anomalous);
223 model->negative_count++;
224 model->positive_count = 0;
225 if (GNUNET_YES == model->anomalous &&
226 model->negative_count >= confirmation_count)
228 model->anomalous = GNUNET_NO;
229 LOG (GNUNET_ERROR_TYPE_INFO,
230 "Anomaly state stopped for sensor `%s', value: %f.\n",
231 model->sensor->name, val);
232 SENSOR_reporting_anomaly_update (model->sensor, model->anomalous);
240 * Iterator for defined sensors
241 * Creates sensor model for numeric sensors
245 * @param value a 'struct GNUNET_SENSOR_SensorInfo *' with sensor information
246 * @return #GNUNET_YES to continue iterations
249 init_sensor_model (void *cls, const struct GNUNET_HashCode *key, void *value)
251 struct GNUNET_SENSOR_SensorInfo *sensor = value;
252 struct SensorModel *sensor_model;
254 if (0 != strcmp ("numeric", sensor->expected_datatype))
256 sensor_model = GNUNET_new (struct SensorModel);
257 sensor_model->sensor = sensor;
259 GNUNET_PEERSTORE_watch (peerstore, "sensor", &peerid, sensor->name,
260 &sensor_watcher, sensor_model);
261 sensor_model->anomalous = GNUNET_NO;
262 sensor_model->positive_count = 0;
263 sensor_model->negative_count = 0;
264 sensor_model->cls = model_api->create_model (model_api->cls);
265 GNUNET_CONTAINER_DLL_insert (models_head, models_tail, sensor_model);
266 LOG (GNUNET_ERROR_TYPE_DEBUG, "Created sensor model for `%s'.\n",
273 * Start the sensor analysis module
275 * @param c our service configuration
276 * @param sensors multihashmap of loaded sensors
277 * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
280 SENSOR_analysis_start (const struct GNUNET_CONFIGURATION_Handle *c,
281 struct GNUNET_CONTAINER_MultiHashMap *s)
285 GNUNET_assert (NULL != s);
289 GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-analysis", "MODEL",
292 LOG (GNUNET_ERROR_TYPE_ERROR,
293 _("Analysis model not defined in configuration.\n"));
294 return GNUNET_SYSERR;
296 GNUNET_asprintf (&model_lib_name, "libgnunet_plugin_sensor_model_%s",
298 model_api = GNUNET_PLUGIN_load (model_lib_name, (void *) cfg);
299 GNUNET_free (model_name);
300 if (NULL == model_api)
302 LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not load analysis model `%s'.\n"),
304 return GNUNET_SYSERR;
306 peerstore = GNUNET_PEERSTORE_connect (cfg);
307 if (NULL == peerstore)
309 LOG (GNUNET_ERROR_TYPE_ERROR,
310 _("Could not connect to peerstore service.\n"));
311 SENSOR_analysis_stop ();
312 return GNUNET_SYSERR;
315 GNUNET_CONFIGURATION_get_value_number (cfg, "sensor-analysis",
316 "CONFIRMATION_COUNT",
317 &confirmation_count))
318 confirmation_count = 1;
319 GNUNET_CRYPTO_get_peer_identity (cfg, &peerid);
320 GNUNET_CONTAINER_multihashmap_iterate (sensors, &init_sensor_model, NULL);
324 /* end of gnunet-service-sensor_analysis.c */