DLL instead of multihashmap
[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    * DLL
42    */
43   struct SensorModel *prev;
44
45   /*
46    * DLL
47    */
48   struct SensorModel *next;
49
50   /*
51    * Pointer to sensor info structure
52    */
53   struct SensorInfo *sensor;
54
55   /*
56    * Watcher of sensor values
57    */
58   struct GNUNET_PEERSTORE_WatchContext *wc;
59
60 };
61
62 /**
63  * Our configuration.
64  */
65 static const struct GNUNET_CONFIGURATION_Handle *cfg;
66
67 /*
68  * Model library name
69  */
70 static char *model_lib_name;
71
72 /*
73  * Model handle
74  */
75 static struct GNUNET_SENSOR_ModelFunctions *model_api;
76
77 /*
78  * Handle to peerstore service
79  */
80 static struct GNUNET_PEERSTORE_Handle *peerstore;
81
82 /*
83  * Datatypes supported by the analysis component
84  */
85 static const char *analysis_datatypes[] = { "uint64", "double", NULL };
86
87 /*
88  * Head of DLL of created models
89  */
90 static struct SensorModel *models_head;
91
92 /*
93  * Tail of DLL of created models
94  */
95 static struct SensorModel *models_tail;
96
97 /**
98  * My peer id
99  */
100 struct GNUNET_PeerIdentity peerid;
101
102 /*
103  * Destroy a created model
104  */
105 static void
106 destroy_sensor_model (struct SensorModel *sensor_model)
107 {
108   GNUNET_assert (NULL != sensor_model);
109   LOG (GNUNET_ERROR_TYPE_DEBUG,
110         "Destroying sensor model for `%s'.\n",
111         sensor_model->sensor->name);
112   if (NULL != sensor_model->wc)
113   {
114     GNUNET_PEERSTORE_watch_cancel(sensor_model->wc);
115     sensor_model->wc = NULL;
116   }
117   sensor_model = NULL;
118 }
119
120 /*
121  * Stop the sensor analysis module
122  */
123 void SENSOR_analysis_stop()
124 {
125   struct SensorModel *sm;
126
127   LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping sensor analysis module.\n");
128   if (NULL != model_api)
129   {
130     GNUNET_break (NULL == GNUNET_PLUGIN_unload (model_lib_name, model_api));
131     GNUNET_free (model_lib_name);
132     model_lib_name = NULL;
133   }
134   while (NULL != models_head)
135   {
136     sm = models_head;
137     destroy_sensor_model(sm);
138     GNUNET_CONTAINER_DLL_remove(models_head, models_tail, sm);
139   }
140   if (NULL != peerstore)
141   {
142     GNUNET_PEERSTORE_disconnect(peerstore);
143     peerstore = NULL;
144   }
145 }
146
147 /*
148  * Sensor value watch callback
149  */
150 static int
151 sensor_watcher (void *cls,
152     struct GNUNET_PEERSTORE_Record *record,
153     char *emsg)
154 {
155   LOG (GNUNET_ERROR_TYPE_DEBUG,
156       "Received a sensor value, will feed to sensor model.\n");
157   return GNUNET_YES;
158 }
159
160 /*
161  * Iterator for defined sensors
162  * Creates sensor model for numeric sensors
163  *
164  * @param cls unused
165  * @param key unused
166  * @param value a 'struct SensorInfo *' with sensor information
167  * @return #GNUNET_YES to continue iterations
168  */
169 static int
170 init_sensor_model (void *cls,
171     const struct GNUNET_HashCode *key,
172     void *value)
173 {
174   struct SensorInfo *sensor = value;
175   struct SensorModel *sensor_model;
176   int is_numeric;
177   int i;
178
179   is_numeric = GNUNET_NO;
180   for (i = 0; NULL != analysis_datatypes[i]; i++)
181   {
182     if (0 == strcmp (analysis_datatypes[i], sensor->expected_datatype))
183     {
184       is_numeric = GNUNET_YES;
185       break;
186     }
187   }
188   if (GNUNET_NO == is_numeric)
189     return GNUNET_YES;
190   sensor_model = GNUNET_new(struct SensorModel);
191   sensor_model->sensor = sensor;
192   sensor_model->wc = GNUNET_PEERSTORE_watch(peerstore,
193           "sensor", &peerid, sensor->name,
194           &sensor_watcher, sensor_model);
195   GNUNET_CONTAINER_DLL_insert(models_head, models_tail, sensor_model);
196   LOG (GNUNET_ERROR_TYPE_DEBUG,
197       "Created sensor model for `%s'.\n", sensor->name);
198   return GNUNET_YES;
199 }
200
201 /*
202  * Start the sensor analysis module
203  *
204  * @param c our service configuration
205  * @param sensors multihashmap of loaded sensors
206  * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
207  */
208 int
209 SENSOR_analysis_start(const struct GNUNET_CONFIGURATION_Handle *c,
210     struct GNUNET_CONTAINER_MultiHashMap *sensors)
211 {
212   char *model_name;
213
214   GNUNET_assert(NULL != sensors);
215   cfg = c;
216   if (GNUNET_OK !=
217       GNUNET_CONFIGURATION_get_value_string (cfg, "sensor-analysis", "MODEL",
218                                                  &model_name))
219   {
220     LOG (GNUNET_ERROR_TYPE_ERROR, _("Analysis model not defined in configuration.\n"));
221     return GNUNET_SYSERR;
222   }
223   GNUNET_asprintf (&model_lib_name, "libgnunet_plugin_sensor_model_%s", model_name);
224   model_api = GNUNET_PLUGIN_load(model_lib_name, (void *) cfg);
225   GNUNET_free(model_name);
226   if(NULL == model_api)
227   {
228     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not load analysis model `%s'.\n"), model_lib_name);
229     return GNUNET_SYSERR;
230   }
231   peerstore = GNUNET_PEERSTORE_connect(cfg);
232   if (NULL == peerstore)
233   {
234     LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to peerstore service.\n"));
235     SENSOR_analysis_stop();
236     return GNUNET_SYSERR;
237   }
238   GNUNET_CRYPTO_get_peer_identity(cfg, &peerid);
239   GNUNET_CONTAINER_multihashmap_iterate(sensors, &init_sensor_model, NULL);
240
241   return GNUNET_OK;
242 }
243
244 /* end of gnunet-service-sensor-analysis.c */