40611ef044957066bced134276f6b4cf1593e030
[rahunas] / src / rh-task-dbset.c
1 /**
2  * RahuNAS task dbset implementation 
3  * Author: Suriya  Soutmun <darksolar@gmail.com>
4  * Date:   2008-09-11
5  */
6
7 #include <stdlib.h>
8 #include <syslog.h>
9 #include <time.h>
10 #include <string.h>
11 #include <libgda/libgda.h>
12 #include "rahunasd.h"
13 #include "rh-task.h"
14 #include "rh-ipset.h"
15 #include "rh-utils.h"
16
17 struct dbset_row {
18   gchar *session_id;
19   gchar *vserver_id;
20   gchar *username;
21   gchar *ip;
22   gchar *mac;
23   time_t session_start;
24   time_t session_timeout;
25   unsigned short bandwidth_slot_id; 
26   long bandwidth_max_down;
27   long bandwidth_max_up;
28 };
29
30 gboolean get_errors (GdaConnection * connection)
31 {
32   GList *list;
33   GList *node;
34   GdaConnectionEvent *error;
35
36   list = (GList *) gda_connection_get_events(connection);
37
38   for (node = g_list_first(list); node != NULL; node = g_list_next(node)) {
39     error = (GdaConnectionEvent *) node->data;
40     logmsg(RH_LOG_NORMAL, "DB Error no: %d", 
41              gda_connection_event_get_code(error));
42     logmsg(RH_LOG_NORMAL, "DB Desc: %s", 
43              gda_connection_event_get_description(error));
44     logmsg(RH_LOG_NORMAL, "DB Source: %s", 
45              gda_connection_event_get_source(error));
46     logmsg(RH_LOG_NORMAL, "DB SQL State: %s", 
47              gda_connection_event_get_sqlstate(error));
48   }
49 }
50
51 gboolean *parse_dm_to_struct(GList **data_list, GdaDataModel *dm) {
52   gint  row_id;
53   gint  column_id;
54   GValue *value;
55   gchar  *str;
56   gchar  *title;
57   GdaNumeric *num;
58   struct dbset_row *row;
59   struct tm tm;
60   time_t time;
61
62   char tmp[80];
63
64   for (row_id = 0; row_id < gda_data_model_get_n_rows(dm); row_id++) {
65     row = (struct dbset_row *)g_malloc(sizeof(struct dbset_row));
66     if (row == NULL) {
67       /* Do implement the row list cleanup */
68     }
69
70     *data_list = g_list_append(*data_list, row); 
71
72     for (column_id = 0; column_id < gda_data_model_get_n_columns(dm); 
73            column_id++) {
74
75       title = gda_data_model_get_column_title(dm, column_id);
76       value = gda_data_model_get_value_at (dm, column_id, row_id, NULL);
77       str = gda_value_stringify(value);
78                
79       if (strncmp("session_id", title, 10) == 0) {
80         row->session_id = g_strdup(str);
81       } else if (strncmp("vserver_id", title, 10) == 0) {
82         row->vserver_id = g_strdup(str);
83       } else if (strncmp("username", title, 8) == 0) {
84         row->username = g_strdup(str);
85       } else if (strncmp("ip", title, 2) == 0) {
86         row->ip = g_strdup(str);
87       } else if (strncmp("mac", title, 3) == 0) {
88         row->mac = g_strdup(str);
89       } else if (strncmp("session_start", title, 13) == 0) {
90         strptime(str, "%s", &tm);
91         time = mktime(&tm);
92         memcpy(&row->session_start, &time, sizeof(time_t));
93       } else if (strncmp("session_timeout", title, 15) == 0) {
94         strptime(str, "%s", &tm);
95         time = mktime(&tm);
96         memcpy(&row->session_timeout, &time, sizeof(time_t));
97       } else if (strncmp("bandwidth_slot_id", title, 17) == 0) {
98         row->bandwidth_slot_id = atoi(str);
99       } else if (strncmp("bandwidth_max_down", title, 18) == 0) {
100         row->bandwidth_max_down = atol(str);
101       } else if (strncmp("bandwidth_max_up", title, 18) == 0) {
102         row->bandwidth_max_up = atol(str);
103       }
104     }
105   }
106   
107   return TRUE;
108 }
109
110 GList *execute_sql_command(GdaConnection *connection, const gchar *buffer)
111 {
112   GdaSqlParser *parser = NULL;
113   GdaStatement *stmt   = NULL;
114   GdaSet       *params = NULL;
115   GList *data_list = NULL;
116   GList *list;
117   GList *node;
118   GdaDataModel *dm;
119   gboolean errors = FALSE;
120
121   parser = g_object_get_data (G_OBJECT (connection), "parser");
122
123   stmt = gda_sql_parser_parse_string (parser, buffer, NULL, NULL);
124   gda_statement_get_parameters (stmt, &params, NULL);
125
126   dm = gda_connection_statement_execute_select (connection, stmt, params, NULL);
127   if (dm) {
128     parse_dm_to_struct (&data_list, dm);
129     g_object_unref (dm);
130   }
131
132   if (params)
133     g_object_unref (params);
134
135   if (stmt)
136     g_object_unref (stmt);
137   
138   return errors == TRUE ? NULL : data_list;
139 }
140
141 void execute_sql(GdaConnection *connection, const gchar *buffer)
142 {
143   GdaSqlParser *parser = NULL;
144   GdaStatement *stmt   = NULL;
145   GdaSet       *params = NULL;
146   gint         res     = 0;
147
148   parser = g_object_get_data (G_OBJECT (connection), "parser");
149
150   stmt = gda_sql_parser_parse_string (parser, buffer, NULL, NULL);
151   gda_statement_get_parameters (stmt, &params, NULL);
152
153   res = gda_connection_statement_execute_non_select (connection, stmt, params,
154                                                      NULL, NULL);
155   if (params)
156     g_object_unref (params);
157
158   if (stmt)
159     g_object_unref (stmt);
160 }
161
162 void list_datasource (void)
163 {
164   GList *ds_list;
165   GList *node;
166   GdaDsnInfo *info;
167
168   info = gda_config_get_dsn_info (PROGRAM);
169
170   logmsg(RH_LOG_NORMAL, "Datasource: NAME: %s PROVIDER: %s",
171          info->name, info->provider);
172   logmsg(RH_LOG_NORMAL, "  CNC: %s", info->cnc_string);
173   logmsg(RH_LOG_NORMAL, "  DESC: %s", info->description);
174 }
175
176 void free_data_list(GList *data_list)
177 {
178   GList *node;
179   struct dbset_row *row;
180
181   for (node = g_list_first(data_list); node != NULL; 
182          node = g_list_next (node)) {
183     row = (struct dbset_row *) node->data;
184     g_free(row->session_id);
185     g_free(row->vserver_id);
186     g_free(row->username);
187     g_free(row->ip);
188     g_free(row->mac);
189   }
190   
191   g_list_free (data_list);  
192 }
193
194 gboolean restore_set(GList **data_list, struct vserver *vs)
195 {
196   GList *node = NULL;
197   struct dbset_row *row = NULL;
198   uint32_t id;
199   GList *member_node = NULL;
200   struct rahunas_member *member = NULL;
201   struct task_req req;
202   unsigned char ethernet[ETH_ALEN] = {0,0,0,0,0,0};
203   unsigned char max_try = 3;
204  
205   node = g_list_first(*data_list);
206
207   if (node == NULL)
208     return TRUE;
209
210   DP("Get data from DB if exist");
211
212   for (node; node != NULL; node = g_list_next(node)) {
213     row = (struct dbset_row *) node->data;
214
215     if (atoi(row->vserver_id) != vs->vserver_config->vserver_id)
216       continue;
217
218     id = iptoid(vs->v_map, row->ip);
219
220     if (id < 0)
221       continue;
222
223     req.id = id;
224     req.vserver_id = atoi(row->vserver_id);
225     req.username = row->username;
226     req.session_id = row->session_id;
227     parse_mac(row->mac, &ethernet);
228     memcpy(req.mac_address, &ethernet, ETH_ALEN);
229
230     req.session_start = row->session_start;
231     req.session_timeout = row->session_timeout;
232
233     req.bandwidth_slot_id = row->bandwidth_slot_id;
234     req.bandwidth_max_down = row->bandwidth_max_down; 
235     req.bandwidth_max_up = row->bandwidth_max_up;
236
237     rh_task_startsess(vs, &req);
238   }
239   return TRUE;
240 }
241
242
243 GdaConnection *openconn (GdaConnectionOptions options)
244 {
245   GdaConnection *connection = NULL;
246   GdaSqlParser  *parser = NULL;
247   connection = gda_connection_open_from_dsn (PROGRAM, NULL, options, NULL);
248
249   parser = gda_connection_create_parser (connection);
250   if (!parser) {
251     parser = gda_sql_parser_new ();
252   }
253
254   g_object_set_data_full (G_OBJECT (connection), "parser", parser, g_object_unref);
255
256   return connection;
257 }
258
259 /* Start service task */
260 static int startservice ()
261 {
262   GError *error = NULL;
263   GdaDsnInfo dsn_info = {
264     .name        = PROGRAM,
265     .provider    = "SQLite",
266     .cnc_string  = "DB_DIR=" RAHUNAS_DB_DIR ";DB_NAME=" DB_NAME,
267     .description = "RahuNAS DB Set",
268   };
269
270   logmsg(RH_LOG_NORMAL, "Task DBSET start..");
271    
272   gda_init();
273     
274   if (!gda_config_define_dsn (&dsn_info, &error)) {
275     logmsg (RH_LOG_ERROR, "Could not define DSN");
276     g_error_free (error);
277   }
278
279   list_datasource();
280
281   return 0;
282 }
283
284 /* Stop service task */
285 static int stopservice  ()
286 {
287   gda_config_remove_dsn (PROGRAM, NULL);
288   return 0;
289 }
290
291 /* Initialize */
292 static void init (struct vserver *vs)
293 {
294   GdaConnection *connection;
295   GList *data_list;
296   GList *node;
297   struct dbset_row *row;
298   char select_cmd[256];
299
300   if (vs->vserver_config->init_flag == VS_RELOAD)
301     return;
302
303   logmsg(RH_LOG_NORMAL, "[%s] Task DBSET initialize..",
304          vs->vserver_config->vserver_name);  
305
306   connection = openconn (GDA_CONNECTION_OPTIONS_READ_ONLY);
307
308   snprintf(select_cmd, sizeof (select_cmd), 
309            "SELECT * FROM dbset WHERE vserver_id='%d'",
310            vs->vserver_config->vserver_id);
311
312   DP("SQL: %s", select_cmd);
313
314   data_list = execute_sql_command(connection, select_cmd); 
315
316   restore_set(&data_list, vs);
317
318   free_data_list(data_list);
319
320   if (connection)
321     g_object_unref(G_OBJECT(connection));
322 }
323
324 /* Cleanup */
325 static void cleanup (struct vserver *vs)
326 {
327   /* Do nothing */
328 }
329
330 /* Start session task */
331 static int startsess (struct vserver *vs, struct task_req *req)
332 {
333   GdaConnection *connection;
334   gint res;
335   char startsess_cmd[256];
336   char time_str[32];
337   char time_str2[32];
338   GList *member_node = NULL;
339   struct rahunas_member *member = NULL;
340
341   connection = openconn (GDA_CONNECTION_OPTIONS_NONE);
342
343   strftime(&time_str, sizeof time_str, "%s", localtime(&req->session_start));
344   strftime(&time_str2, sizeof time_str2, "%s", 
345     localtime(&req->session_timeout));
346
347   member_node = member_get_node_by_id(vs, req->id);
348   if (member_node == NULL)
349     return (-1);
350
351   member = (struct rahunas_member *) member_node->data;
352
353   snprintf(startsess_cmd, sizeof (startsess_cmd), "INSERT INTO dbset"
354          "(session_id,vserver_id,username,ip,mac,session_start,"
355          "session_timeout,bandwidth_slot_id,bandwidth_max_down,"
356          "bandwidth_max_up) "
357          "VALUES('%s','%d','%s','%s','%s',%s,%s,%u,%lu,%lu)",
358          req->session_id, 
359          vs->vserver_config->vserver_id, 
360          req->username, 
361          idtoip(vs->v_map, req->id), 
362          mac_tostring(req->mac_address), 
363          time_str, 
364          time_str2,
365          member->bandwidth_slot_id, 
366          req->bandwidth_max_down,
367          req->bandwidth_max_up);
368
369   DP("SQL: %s", startsess_cmd);
370
371   execute_sql(connection, startsess_cmd);
372
373   if (connection)
374     g_object_unref(G_OBJECT(connection));
375
376   return 0;
377 }
378
379 /* Stop session task */
380 static int stopsess (struct vserver *vs, struct task_req *req)
381 {
382   GdaConnection *connection;
383   gint res;
384   char stopsess_cmd[256];
385   GList *member_node = NULL;
386   struct rahunas_member *member = NULL;
387
388   member_node = member_get_node_by_id(vs, req->id);
389   if (member_node == NULL)
390     return (-1);
391
392   member = (struct rahunas_member *) member_node->data;
393
394   connection = openconn (GDA_CONNECTION_OPTIONS_NONE);
395
396   DP("Username  : %s", member->username);
397   DP("SessionID : %s", member->session_id);
398
399   snprintf(stopsess_cmd, sizeof (stopsess_cmd), "DELETE FROM dbset WHERE "
400          "session_id='%s' AND username='%s' AND vserver_id='%d'",
401          member->session_id, 
402          member->username,
403          vs->vserver_config->vserver_id);
404
405   DP("SQL: %s", stopsess_cmd);
406
407   execute_sql(connection, stopsess_cmd);
408
409   if (connection)
410     g_object_unref(G_OBJECT(connection));
411
412   return 0;
413 }
414
415 /* Commit start session task */
416 static int commitstartsess (struct vserver *vs, struct task_req *req)
417 {
418   /* Do nothing or need to implement */
419 }
420
421 /* Commit stop session task */
422 static int commitstopsess  (struct vserver *vs, struct task_req *req)
423 {
424   /* Do nothing or need to implement */
425 }
426
427 /* Rollback start session task */
428 static int rollbackstartsess (struct vserver *vs, struct task_req *req)
429 {
430   /* Do nothing or need to implement */
431 }
432
433 /* Rollback stop session task */
434 static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
435 {
436   /* Do nothing or need to implement */
437 }
438
439 static struct task task_dbset = {
440   .taskname = "DBSET",
441   .taskprio = 10,
442   .init = &init,
443   .cleanup = &cleanup,
444   .startservice = &startservice,
445   .stopservice = &stopservice,
446   .startsess = &startsess,
447   .stopsess = &stopsess,
448   .commitstartsess = &commitstartsess,
449   .commitstopsess = &commitstopsess,
450   .rollbackstartsess = &rollbackstartsess,
451   .rollbackstopsess = &rollbackstopsess,
452 };
453
454 void rh_task_dbset_reg(struct main_server *ms) {
455   task_register(ms, &task_dbset);
456 }