towards sensor analysis functionality
[oweals/gnunet.git] / src / sensor / gnunet-service-sensor-analysis.c
1 /*
2      This file is part of GNUnet.
3      (C)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file sensor/gnunet-service-sensor-analysis.c
23  * @brief sensor service analysis functionality
24  * @author Omar Tarabai
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "sensor.h"
29 #include "gnunet_peerstore_service.h"
30
31 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-analysis",__VA_ARGS__)
32
33 /*
34  * Carries information about the analysis model
35  * corresponding to one sensor
36  */
37 struct SensorModel
38 {
39
40   /*
41    * Pointer to sensor info structure
42    */
43   struct SensorInfo *sensor;
44
45   /*
46    * Watcher of sensor values
47    */
48   struct GNUNET_PEERSTORE_WatchContext *wc;
49
50 };
51
52 /**
53  * Our configuration.
54  */
55 static const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57 /*
58  * Model library name
59  */
60 static char *model_lib_name;
61
62 /*
63  * Model handle
64  */
65 static struct GNUNET_SENSOR_ModelFunctions *model;
66
67 /**
68  * Hashmap of loaded sensor definitions
69  */
70 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
71
72 /*
73  * Handle to peerstore service
74  */
75 static struct GNUNET_PEERSTORE_Handle *peerstore;
76
77 /*
78  * Datatypes supported by the analysis component
79  */
80 static const char *analysis_datatypes[] = { "uint64", "double", NULL };
81
82 /*
83  * MultiHashmap of all sensor models
84  */
85 static struct GNUNET_CONTAINER_MultiHashMap *sensor_models;
86
87 /*
88  * TODO: document
89  */
90 void SENSOR_analysis_stop()
91 {
92   if (NULL != model)
93   {
94     GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model));
95     GNUNET_free (model_lib_name);
96     model_lib_name = NULL;
97   }
98   if (NULL != peerstore)
99   {
100     GNUNET_PEERSTORE_disconnect(peerstore);
101     peerstore = NULL;
102   }
103   if (NULL != sensor_models)
104   {
105     /* TODO: iterate over sensor models and destroy */
106     GNUNET_CONTAINER_multihashmap_destroy(sensor_models);
107     sensor_models = NULL;
108   }
109 }
110
111 /*
112  * TODO: document
113  */
114 static int
115 sensor_watcher (void *cls,
116     struct GNUNET_PEERSTORE_Record *record,
117     char *emsg)
118 {
119   LOG (GNUNET_ERROR_TYPE_DEBUG,
120       "Received a sensor value, will feed to sensor model.\n");
121   return GNUNET_YES;
122 }
123
124 /*
125  * TODO: document
126  */
127 static int
128 init_sensor_model (void *cls,
129     const struct GNUNET_HashCode *key,
130     void *value)
131 {
132   struct SensorInfo *sensor = value;
133   struct SensorModel *sensor_model;
134   int is_numeric;
135   int i;
136
137   is_numeric = GNUNET_NO;
138   for (i = 0; NULL != analysis_datatypes[i]; i++)
139   {
140     if (0 == strcasecmp (analysis_datatypes[i], sensor->expected_datatype))
141     {
142       is_numeric = GNUNET_YES;
143       break;
144     }
145   }
146   if (GNUNET_NO == is_numeric)
147     return GNUNET_YES;
148   sensor_model = GNUNET_new(struct SensorModel);
149   sensor_model->wc = GNUNET_PEERSTORE_watch(peerstore,
150           "sensor", NULL, sensor->name,
151           &sensor_watcher, sensor_model);
152   GNUNET_CONTAINER_multihashmap_put(sensor_models, key,
153       sensor_model, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
154   return GNUNET_YES;
155 }
156
157 /*
158  * TODO: document
159  *
160  * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
161  */
162 int
163 SENSOR_analysis_start(const struct GNUNET_CONFIGURATION_Handle *c,
164     struct GNUNET_CONTAINER_MultiHashMap *sensors_mhm)
165 {
166   char *model_name;
167
168   cfg = c;
169   if (GNUNET_OK !=
170       GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-analysis", "MODEL",
171                                                  &model_name))
172   {
173     LOG (GNUNET_ERROR_TYPE_ERROR, _("Analysis model not defined in configuration.\n"));
174     return GNUNET_SYSERR;
175   }
176   GNUNET_asprintf (&model_lib_name, "libgnunet_plugin_sensor_model_%s", model_name);
177   model = GNUNET_PLUGIN_load(model_lib_name, (void *) cfg);
178   GNUNET_free(model_name);
179   if(NULL == model)
180   {
181     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not load analysis model `%s'.\n"), model_lib_name);
182     return GNUNET_SYSERR;
183   }
184   sensors = sensors_mhm;
185   if (NULL == sensors)
186   {
187     LOG (GNUNET_ERROR_TYPE_ERROR, _("Tried to start analysis before loading sensors.\n"));
188     SENSOR_analysis_stop();
189     return GNUNET_SYSERR;
190   }
191   peerstore = GNUNET_PEERSTORE_connect(cfg);
192   if (NULL == peerstore)
193   {
194     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to peerstore service.\n"));
195     SENSOR_analysis_stop();
196     return GNUNET_SYSERR;
197   }
198   sensor_models = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
199   GNUNET_CONTAINER_multihashmap_iterate(sensors, &init_sensor_model, NULL);
200
201   return GNUNET_OK;
202 }
203
204 /* end of gnunet-service-sensor-analysis.c */