#include "gnunet_util_lib.h"
#include "sensor.h"
#include "gnunet_peerstore_service.h"
+#include "gnunet_sensor_model_plugin.h"
#define LOG(kind,...) GNUNET_log_from (kind, "sensor-analysis",__VA_ARGS__)
struct SensorModel
{
+ /*
+ * DLL
+ */
+ struct SensorModel *prev;
+
+ /*
+ * DLL
+ */
+ struct SensorModel *next;
+
/*
* Pointer to sensor info structure
*/
*/
struct GNUNET_PEERSTORE_WatchContext *wc;
+ /*
+ * Closure for model plugin
+ */
+ void *cls;
+
};
/**
/*
* Model handle
*/
-static struct GNUNET_SENSOR_ModelFunctions *model;
-
-/**
- * Hashmap of loaded sensor definitions
- */
-static struct GNUNET_CONTAINER_MultiHashMap *sensors;
+static struct GNUNET_SENSOR_ModelFunctions *model_api;
/*
* Handle to peerstore service
static struct GNUNET_PEERSTORE_Handle *peerstore;
/*
- * Datatypes supported by the analysis component
+ * Head of DLL of created models
*/
-static const char *analysis_datatypes[] = { "uint64", "double", NULL };
+static struct SensorModel *models_head;
/*
- * MultiHashmap of all sensor models
+ * Tail of DLL of created models
+ */
+static struct SensorModel *models_tail;
+
+/**
+ * My peer id
*/
-static struct GNUNET_CONTAINER_MultiHashMap *sensor_models;
+struct GNUNET_PeerIdentity peerid;
+
+/*
+ * Destroy a created model
+ */
+static void
+destroy_sensor_model (struct SensorModel *sensor_model)
+{
+ GNUNET_assert (NULL != sensor_model);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Destroying sensor model for `%s'.\n",
+ sensor_model->sensor->name);
+ if (NULL != sensor_model->wc)
+ {
+ GNUNET_PEERSTORE_watch_cancel(sensor_model->wc);
+ sensor_model->wc = NULL;
+ }
+ if (NULL != sensor_model->cls)
+ {
+ model_api->destroy_model (sensor_model->cls);
+ sensor_model->cls = NULL;
+ }
+ GNUNET_free(sensor_model);
+ sensor_model = NULL;
+}
/*
- * TODO: document
+ * Stop the sensor analysis module
*/
void SENSOR_analysis_stop()
{
- if (NULL != model)
+ struct SensorModel *sm;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping sensor analysis module.\n");
+ while (NULL != models_head)
{
- GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model));
- GNUNET_free (model_lib_name);
- model_lib_name = NULL;
+ sm = models_head;
+ GNUNET_CONTAINER_DLL_remove(models_head, models_tail, sm);
+ destroy_sensor_model(sm);
}
if (NULL != peerstore)
{
GNUNET_PEERSTORE_disconnect(peerstore);
peerstore = NULL;
}
- if (NULL != sensor_models)
+ if (NULL != model_api)
{
- /* TODO: iterate over sensor models and destroy */
- GNUNET_CONTAINER_multihashmap_destroy(sensor_models);
- sensor_models = NULL;
+ GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model_api));
+ GNUNET_free (model_lib_name);
+ model_lib_name = NULL;
}
}
/*
- * TODO: document
+ * Sensor value watch callback
*/
static int
sensor_watcher (void *cls,
struct GNUNET_PEERSTORE_Record *record,
char *emsg)
{
+ struct SensorModel *sensor_model = cls;
+ double *val;
+ int anomalous;
+
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received a sensor value, will feed to sensor model.\n");
+ if (sizeof(double) != record->value_size)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Received an invalid sensor value."));
+ return GNUNET_YES;
+ }
+ val = (double *)(record->value);
+ anomalous = model_api->feed_model (sensor_model->cls, *val);
+ if (GNUNET_YES == anomalous)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Anomaly detected in sensor `%s', value: %f.\n",
+ sensor_model->sensor->name, *val);
+ }
+ else
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Value non-anomalous.\n");
return GNUNET_YES;
}
/*
- * TODO: document
+ * Iterator for defined sensors
+ * Creates sensor model for numeric sensors
+ *
+ * @param cls unused
+ * @param key unused
+ * @param value a 'struct SensorInfo *' with sensor information
+ * @return #GNUNET_YES to continue iterations
*/
static int
init_sensor_model (void *cls,
{
struct SensorInfo *sensor = value;
struct SensorModel *sensor_model;
- int is_numeric;
- int i;
- is_numeric = GNUNET_NO;
- for (i = 0; NULL != analysis_datatypes[i]; i++)
- {
- if (0 == strcasecmp (analysis_datatypes[i], sensor->expected_datatype))
- {
- is_numeric = GNUNET_YES;
- break;
- }
- }
- if (GNUNET_NO == is_numeric)
+ if (0 != strcmp("numeric", sensor->expected_datatype))
return GNUNET_YES;
sensor_model = GNUNET_new(struct SensorModel);
+ sensor_model->sensor = sensor;
sensor_model->wc = GNUNET_PEERSTORE_watch(peerstore,
- "sensor", NULL, sensor->name,
+ "sensor", &peerid, sensor->name,
&sensor_watcher, sensor_model);
- GNUNET_CONTAINER_multihashmap_put(sensor_models, key,
- sensor_model, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ sensor_model->cls = model_api->create_model(model_api->cls);
+ GNUNET_CONTAINER_DLL_insert(models_head, models_tail, sensor_model);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Created sensor model for `%s'.\n", sensor->name);
return GNUNET_YES;
}
/*
- * TODO: document
+ * Start the sensor analysis module
*
+ * @param c our service configuration
+ * @param sensors multihashmap of loaded sensors
* @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
*/
int
SENSOR_analysis_start(const struct GNUNET_CONFIGURATION_Handle *c,
- struct GNUNET_CONTAINER_MultiHashMap *sensors_mhm)
+ struct GNUNET_CONTAINER_MultiHashMap *sensors)
{
char *model_name;
+ GNUNET_assert(NULL != sensors);
cfg = c;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-analysis", "MODEL",
return GNUNET_SYSERR;
}
GNUNET_asprintf (&model_lib_name, "libgnunet_plugin_sensor_model_%s", model_name);
- model = GNUNET_PLUGIN_load(model_lib_name, (void *) cfg);
+ model_api = GNUNET_PLUGIN_load(model_lib_name, (void *) cfg);
GNUNET_free(model_name);
- if(NULL == model)
+ if(NULL == model_api)
{
LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not load analysis model `%s'.\n"), model_lib_name);
return GNUNET_SYSERR;
}
- sensors = sensors_mhm;
- if (NULL == sensors)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Tried to start analysis before loading sensors.\n"));
- SENSOR_analysis_stop();
- return GNUNET_SYSERR;
- }
peerstore = GNUNET_PEERSTORE_connect(cfg);
if (NULL == peerstore)
{
SENSOR_analysis_stop();
return GNUNET_SYSERR;
}
- sensor_models = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
+ GNUNET_CRYPTO_get_peer_identity(cfg, &peerid);
GNUNET_CONTAINER_multihashmap_iterate(sensors, &init_sensor_model, NULL);
return GNUNET_OK;