Sensor gaussian model skeleton
[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  * My peer id
89  */
90 struct GNUNET_PeerIdentity peerid;
91
92 /*
93  * TODO: document
94  */
95 static int
96 destroy_sensor_model (void *cls,
97     const struct GNUNET_HashCode *key,
98     void *value)
99 {
100   struct SensorModel *sensor_model = value;
101
102   if (NULL == sensor_model)
103     return GNUNET_YES;
104   LOG (GNUNET_ERROR_TYPE_DEBUG,
105         "Destroying sensor model for `%s'.\n",
106         sensor_model->sensor->name);
107   if (NULL != sensor_model->wc)
108   {
109     GNUNET_PEERSTORE_watch_cancel(sensor_model->wc);
110     sensor_model->wc = NULL;
111   }
112   return GNUNET_YES;
113 }
114
115 /*
116  * Stop the sensor analysis module
117  */
118 void SENSOR_analysis_stop()
119 {
120
121   LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping sensor analysis module.\n");
122   if (NULL != model)
123   {
124     GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model));
125     GNUNET_free (model_lib_name);
126     model_lib_name = NULL;
127   }
128   if (NULL != sensor_models)
129   {
130     GNUNET_CONTAINER_multihashmap_iterate(sensor_models, &destroy_sensor_model, NULL);
131     GNUNET_CONTAINER_multihashmap_destroy(sensor_models);
132     sensor_models = NULL;
133   }
134   if (NULL != peerstore)
135   {
136     GNUNET_PEERSTORE_disconnect(peerstore);
137     peerstore = NULL;
138   }
139 }
140
141 /*
142  * TODO: document
143  */
144 static int
145 sensor_watcher (void *cls,
146     struct GNUNET_PEERSTORE_Record *record,
147     char *emsg)
148 {
149   LOG (GNUNET_ERROR_TYPE_DEBUG,
150       "Received a sensor value, will feed to sensor model.\n");
151   return GNUNET_YES;
152 }
153
154 /*
155  * TODO: document
156  */
157 static int
158 init_sensor_model (void *cls,
159     const struct GNUNET_HashCode *key,
160     void *value)
161 {
162   struct SensorInfo *sensor = value;
163   struct SensorModel *sensor_model;
164   int is_numeric;
165   int i;
166
167   is_numeric = GNUNET_NO;
168   for (i = 0; NULL != analysis_datatypes[i]; i++)
169   {
170     if (0 == strcmp (analysis_datatypes[i], sensor->expected_datatype))
171     {
172       is_numeric = GNUNET_YES;
173       break;
174     }
175   }
176   if (GNUNET_NO == is_numeric)
177     return GNUNET_YES;
178   sensor_model = GNUNET_new(struct SensorModel);
179   sensor_model->sensor = sensor;
180   sensor_model->wc = GNUNET_PEERSTORE_watch(peerstore,
181           "sensor", &peerid, sensor->name,
182           &sensor_watcher, sensor_model);
183   GNUNET_CONTAINER_multihashmap_put(sensor_models, key,
184       sensor_model, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
185   LOG (GNUNET_ERROR_TYPE_DEBUG,
186       "Created sensor model for `%s'.\n", sensor->name);
187   return GNUNET_YES;
188 }
189
190 /*
191  * Start the sensor analysis module
192  *
193  * @param c our service configuration
194  * @param sensors_mhm multihashmap of loaded sensors
195  * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
196  */
197 int
198 SENSOR_analysis_start(const struct GNUNET_CONFIGURATION_Handle *c,
199     struct GNUNET_CONTAINER_MultiHashMap *sensors_mhm)
200 {
201   char *model_name;
202
203   cfg = c;
204   if (GNUNET_OK !=
205       GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-analysis", "MODEL",
206                                                  &model_name))
207   {
208     LOG (GNUNET_ERROR_TYPE_ERROR, _("Analysis model not defined in configuration.\n"));
209     return GNUNET_SYSERR;
210   }
211   GNUNET_asprintf (&model_lib_name, "libgnunet_plugin_sensor_model_%s", model_name);
212   model = GNUNET_PLUGIN_load(model_lib_name, (void *) cfg);
213   GNUNET_free(model_name);
214   if(NULL == model)
215   {
216     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not load analysis model `%s'.\n"), model_lib_name);
217     return GNUNET_SYSERR;
218   }
219   sensors = sensors_mhm;
220   if (NULL == sensors)
221   {
222     LOG (GNUNET_ERROR_TYPE_ERROR, _("Tried to start analysis before loading sensors.\n"));
223     SENSOR_analysis_stop();
224     return GNUNET_SYSERR;
225   }
226   peerstore = GNUNET_PEERSTORE_connect(cfg);
227   if (NULL == peerstore)
228   {
229     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to peerstore service.\n"));
230     SENSOR_analysis_stop();
231     return GNUNET_SYSERR;
232   }
233   GNUNET_CRYPTO_get_peer_identity(cfg, &peerid);
234   sensor_models = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
235   GNUNET_CONTAINER_multihashmap_iterate(sensors, &init_sensor_model, NULL);
236
237   return GNUNET_OK;
238 }
239
240 /* end of gnunet-service-sensor-analysis.c */