00001 #include <time.h>
00002 #include <cds/logger.h>
00003
00004 #include "rl_subscription.h"
00005 #include "rls_mod.h"
00006
00007 char *rls_table = "rls_subscription";
00008 char *vs_table = "rls_vs";
00009 char *vs_names_table = "rls_vs_names";
00010
00011
00012 void generate_db_id(db_id_t *id, void *data)
00013 {
00014 if (id) {
00015 snprintf(*id, sizeof(*id), "%px%xx%x",
00016 data, (int)time(NULL), rand());
00017
00018 }
00019 }
00020
00021 #define string_val(v,s) (v).type = DB_STR; \
00022 (v).val.str_val=s; \
00023 (v).nul=(s.len == 0);
00024
00025 #define int_val(v,i) (v).type = DB_INT; \
00026 (v).val.int_val=i;\
00027 (v).nul=0;
00028
00029 #define time_val(v,t) (v).type = DB_DATETIME; \
00030 (v).val.time_val=t;\
00031 (v).nul=0;
00032
00033 #define string_val_ex(v,str,l) (v).type = DB_STR; \
00034 (v).val.str_val.s=str; \
00035 (v).val.str_val.len=l; \
00036 (v).nul=0;
00037
00038 #define blob_val(v,str) (v).type = DB_BLOB; \
00039 (v).val.blob_val=str; \
00040 (v).nul=0;
00041
00042
00043
00044
00045 static int virtual_subscription_db_add(virtual_subscription_t *vs, rl_subscription_t *s)
00046 {
00047 db_key_t cols[20];
00048 db_val_t vals[20];
00049 int n = -1;
00050 int i, cnt;
00051 vs_display_name_t *dn;
00052
00053 DEBUG_LOG("storing into database\n");
00054
00055 if (rls_dbf.use_table(rls_db, vs_table) < 0) {
00056 LOG(L_ERR, "vsub_db_add: Error in use_table\n");
00057 return -1;
00058 }
00059
00060 cols[++n] = "uri";
00061 string_val(vals[n], vs->uri);
00062
00063 cols[++n] = "id";
00064 string_val_ex(vals[n], vs->dbid, strlen(vs->dbid));
00065
00066 cols[++n] = "rls_id";
00067 string_val_ex(vals[n], s->dbid, strlen(s->dbid));
00068
00069
00070 if (rls_dbf.insert(rls_db, cols, vals, n + 1) < 0) {
00071 LOG(L_ERR, "vsub_db_add: Error while inserting virtual subscription\n");
00072 return -1;
00073 }
00074
00075
00076 cnt = vector_size(&vs->display_names);
00077 for (i = 0; i < cnt; i++) {
00078 if (rls_dbf.use_table(rls_db, vs_names_table) < 0) {
00079 LOG(L_ERR, "vsub_db_add (names): Error in use_table\n");
00080 return -1;
00081 }
00082 dn = vector_get_ptr(&vs->display_names, i);
00083 if (!dn) continue;
00084
00085 n = -1;
00086
00087 cols[++n] = "id";
00088 string_val_ex(vals[n], vs->dbid, strlen(vs->dbid));
00089
00090 cols[++n] = "name";
00091 string_val(vals[n], dn->name);
00092
00093 cols[++n] = "lang";
00094 string_val(vals[n], dn->lang);
00095
00096 if (rls_dbf.insert(rls_db, cols, vals, n + 1) < 0) {
00097 LOG(L_ERR, "vsub_db_add: Error while inserting name\n");
00098 return -1;
00099 }
00100 }
00101
00102 return 0;
00103 }
00104
00105 static int vs_db_add(rl_subscription_t *s)
00106 {
00107 int i, cnt;
00108 int res = 0;
00109 virtual_subscription_t *vs;
00110
00111 cnt = ptr_vector_size(&s->vs);
00112 for (i = 0; i < cnt; i++) {
00113 vs = ptr_vector_get(&s->vs, i);
00114 if (!vs) continue;
00115
00116 res = virtual_subscription_db_add(vs, s);
00117 if (res != 0) break;
00118 }
00119 return res;
00120 }
00121
00122 static int vs_db_update(rl_subscription_t *s)
00123 {
00124
00125
00126
00127
00128
00129 return 0;
00130 }
00131
00132 static int vs_db_remove(rl_subscription_t *s)
00133 {
00134 db_key_t keys[] = { "id" };
00135 db_op_t ops[] = { OP_EQ };
00136 db_val_t k_vals[1];
00137 int i, cnt;
00138 int res = 0;
00139 virtual_subscription_t *vs;
00140
00141 cnt = ptr_vector_size(&s->vs);
00142 for (i = 0; i < cnt; i++) {
00143 vs = ptr_vector_get(&s->vs, i);
00144 if (!vs) continue;
00145
00146 string_val_ex(k_vals[0], vs->dbid, strlen(vs->dbid));
00147
00148
00149 if (rls_dbf.use_table(rls_db, vs_table) < 0) {
00150 LOG(L_ERR, "db_remove_presence_tuple: Error in use_table\n");
00151 res = -1;
00152 }
00153 if (rls_dbf.delete(rls_db, keys, ops, k_vals, 1) < 0) {
00154 LOG(L_ERR, "db_remove_presence_tuple: Can't delete record\n");
00155 res = -1;
00156 }
00157
00158
00159 if (rls_dbf.use_table(rls_db, vs_names_table) < 0) {
00160 LOG(L_ERR, "db_remove_presence_tuple: Error in use_table\n");
00161 res = -1;
00162 }
00163 if (rls_dbf.delete(rls_db, keys, ops, k_vals, 1) < 0) {
00164 LOG(L_ERR, "db_remove_presence_tuple: Can't delete record\n");
00165 res = -1;
00166 }
00167 }
00168
00169 return res;
00170 }
00171
00172
00173
00174 int rls_db_add(rl_subscription_t *s)
00175 {
00176 db_key_t cols[20];
00177 db_val_t vals[20];
00178 str_t dialog = STR_NULL;
00179 str_t str_xcap_params = STR_NULL;
00180 int n = -1;
00181 int res = 0;
00182 time_t t;
00183
00184 if (!use_db) return 0;
00185
00186
00187 if (s->type != rls_external_subscription) return 0;
00188
00189 DEBUG_LOG("storing into database\n");
00190
00191 if (rls_dbf.use_table(rls_db, rls_table) < 0) {
00192 LOG(L_ERR, "rls_db_add: Error in use_table\n");
00193 return -1;
00194 }
00195
00196 cols[++n] = "doc_version";
00197 int_val(vals[n], s->doc_version);
00198
00199 cols[++n] = "status";
00200 int_val(vals[n], s->u.external.status);
00201
00202 t = time(NULL);
00203 t += rls_subscription_expires_in(s);
00204 cols[++n] = "expires";
00205 time_val(vals[n], t);
00206
00207 if (dlg_func.dlg2str(s->u.external.dialog, &dialog) != 0) {
00208 LOG(L_ERR, "Error while serializing dialog\n");
00209 return -1;
00210 }
00211 cols[++n] = "dialog";
00212 blob_val(vals[n], dialog);
00213
00214 cols[++n] = "contact";
00215 string_val(vals[n], s->u.external.contact);
00216
00217 cols[++n] = "uri";
00218 string_val(vals[n], s->u.external.record_id);
00219
00220 cols[++n] = "package";
00221 string_val(vals[n], s->u.external.package);
00222
00223 cols[++n] = "w_uri";
00224 string_val(vals[n], s->u.external.subscriber);
00225
00226 if (xcap_params2str(&str_xcap_params, &s->xcap_params) != 0) {
00227 LOG(L_ERR, "Error while serializing xcap params\n");
00228 str_free_content(&dialog);
00229 return -1;
00230 }
00231 cols[++n] = "xcap_params";
00232 blob_val(vals[n], str_xcap_params);
00233
00234 cols[++n] = "id";
00235 string_val_ex(vals[n], s->dbid, strlen(s->dbid));
00236
00237
00238 if (rls_dbf.insert(rls_db, cols, vals, n + 1) < 0) {
00239 LOG(L_ERR, "rls_db_add: Error while inserting subscription\n");
00240 res = -1;
00241 }
00242
00243 str_free_content(&dialog);
00244 str_free_content(&str_xcap_params);
00245
00246 if (res == 0) res = vs_db_add(s);
00247
00248 return res;
00249 }
00250
00251 int rls_db_remove(rl_subscription_t *s)
00252 {
00253 db_key_t keys[] = { "id" };
00254 db_op_t ops[] = { OP_EQ };
00255 db_val_t k_vals[] = {
00256 { DB_STR, 0,
00257 { .str_val = { s: s->dbid, len: strlen(s->dbid) }
00258 }
00259 }
00260 };
00261
00262 if (!use_db) return 0;
00263
00264
00265 if (s->type != rls_external_subscription) return 0;
00266
00267 if (rls_dbf.use_table(rls_db, rls_table) < 0) {
00268 LOG(L_ERR, "db_remove_presence_tuple: Error in use_table\n");
00269 return -1;
00270 }
00271
00272 if (rls_dbf.delete(rls_db, keys, ops, k_vals, 1) < 0) {
00273 LOG(L_ERR, "db_remove_presence_tuple: Can't delete record\n");
00274 return -1;
00275 }
00276
00277 return vs_db_remove(s);
00278 }
00279
00280 int rls_db_update(rl_subscription_t *s)
00281 {
00282 db_key_t cols[20];
00283 db_val_t vals[20];
00284 str_t dialog = STR_NULL;
00285 str_t str_xcap_params = STR_NULL;
00286 int n = -1;
00287 int res = 0;
00288 time_t t;
00289 db_key_t keys[] = { "id" };
00290 db_op_t ops[] = { OP_EQ };
00291 db_val_t k_vals[] = {
00292 { DB_STR, 0,
00293 { .str_val = { s: s->dbid, len: strlen(s->dbid) }
00294 }
00295 }
00296 };
00297
00298 if (!use_db) return 0;
00299
00300
00301 if (s->type != rls_external_subscription) return 0;
00302
00303 if (rls_dbf.use_table(rls_db, rls_table) < 0) {
00304 LOG(L_ERR, "rls_db_add: Error in use_table\n");
00305 return -1;
00306 }
00307
00308 cols[++n] = "doc_version";
00309 int_val(vals[n], s->doc_version);
00310
00311 cols[++n] = "status";
00312 int_val(vals[n], s->u.external.status);
00313
00314 t = time(NULL);
00315 t += rls_subscription_expires_in(s);
00316 cols[++n] = "expires";
00317 time_val(vals[n], t);
00318
00319 if (dlg_func.dlg2str(s->u.external.dialog, &dialog) != 0) {
00320 LOG(L_ERR, "Error while serializing dialog\n");
00321 return -1;
00322 }
00323 cols[++n] = "dialog";
00324 blob_val(vals[n], dialog);
00325
00326 cols[++n] = "contact";
00327 string_val(vals[n], s->u.external.contact);
00328
00329 cols[++n] = "uri";
00330 string_val(vals[n], s->u.external.record_id);
00331
00332 cols[++n] = "package";
00333 string_val(vals[n], s->u.external.package);
00334
00335 cols[++n] = "w_uri";
00336 string_val(vals[n], s->u.external.subscriber);
00337
00338 if (xcap_params2str(&str_xcap_params, &s->xcap_params) != 0) {
00339 LOG(L_ERR, "Error while serializing xcap params\n");
00340 str_free_content(&dialog);
00341 return -1;
00342 }
00343 cols[++n] = "xcap_params";
00344 blob_val(vals[n], str_xcap_params);
00345
00346 if (rls_dbf.update(rls_db, keys, ops, k_vals,
00347 cols, vals, 1, n + 1) < 0) {
00348 LOG(L_ERR, "rls_db_add: Error while inserting subscription\n");
00349 res = -1;
00350 }
00351
00352 str_free_content(&dialog);
00353 str_free_content(&str_xcap_params);
00354
00355 return vs_db_update(s);
00356 }
00357
00358
00359
00360 #define get_str_val(rvi,dst) do{if(!rvi.nul){dst.s=(char*)rvi.val.string_val;dst.len=strlen(dst.s);}}while(0)
00361 #define get_blob_val(rvi,dst) do{if(!rvi.nul){dst=rvi.val.blob_val;}else dst.len=0;}while(0)
00362 #define get_time_val(rvi,dst) do{if(!rvi.nul){dst=rvi.val.time_val;}}while(0)
00363 #define get_int_val(rvi,dst) do{if(!rvi.nul){dst=rvi.val.int_val;}else dst=0;}while(0)
00364
00365 static dlg_t *dlg2str(str_t *s)
00366 {
00367 dlg_t *dlg = (dlg_t*)mem_alloc(sizeof(*dlg));
00368 if (!dlg) LOG(L_ERR, "Can't allocate dialog\n");
00369 else {
00370 if (dlg_func.str2dlg(s, dlg) != 0) {
00371 LOG(L_ERR, "Error while deserializing dialog\n");
00372 mem_free(dlg);
00373 dlg = NULL;
00374 }
00375 }
00376 return dlg;
00377 }
00378
00379 int db_load_vs_names(db_con_t *rls_db, virtual_subscription_t *vs)
00380 {
00381 int i, r = 0;
00382 db_res_t *res = NULL;
00383 db_key_t result_cols[] = {
00384 "name", "lang"
00385 };
00386 db_key_t keys[] = { "id" };
00387 db_op_t ops[] = { OP_EQ };
00388 db_val_t k_vals[] = {
00389 { DB_STR, 0,
00390 { .str_val = { s: vs->dbid, len: strlen(vs->dbid) } }
00391 }
00392 };
00393
00394 if (rls_dbf.use_table(rls_db, vs_names_table) < 0) {
00395 LOG(L_ERR, "vs_load_vs_names: Error in use_table\n");
00396 return -1;
00397 }
00398
00399 if (rls_dbf.query (rls_db, keys,ops, k_vals,
00400 result_cols, 1, sizeof(result_cols) / sizeof(db_key_t),
00401 0, &res) < 0) {
00402 LOG(L_ERR, "db_load_vs_names: Error while querying vs names\n");
00403 r = -1;
00404 res = NULL;
00405 }
00406 if (res) {
00407 for (i = 0; i < res->n; i++) {
00408 db_row_t *row = &res->rows[i];
00409 db_val_t *row_vals = ROW_VALUES(row);
00410 str name = STR_NULL;
00411 str lang = STR_NULL;
00412
00413 get_str_val(row_vals[0], name);
00414 get_str_val(row_vals[1], lang);
00415
00416 DEBUG_LOG(" adding name %.*s\n", FMT_STR(name));
00417 vs_add_display_name(vs, name.s, lang.s);
00418 }
00419
00420 rls_dbf.free_result(rls_db, res);
00421 }
00422
00423 return r;
00424 }
00425
00426 int db_load_vs(db_con_t *rls_db, rl_subscription_t *s)
00427 {
00428 int i, r = 0;
00429 db_res_t *res = NULL;
00430 virtual_subscription_t *vs;
00431 db_key_t result_cols[] = {
00432 "id", "uri"
00433 };
00434 db_key_t keys[] = { "rls_id" };
00435 db_op_t ops[] = { OP_EQ };
00436 db_val_t k_vals[] = {
00437 { DB_STR, 0,
00438 { .str_val = { s: s->dbid, len: strlen(s->dbid) } }
00439 }
00440 };
00441
00442 if (rls_dbf.use_table(rls_db, vs_table) < 0) {
00443 LOG(L_ERR, "vs_load_vs: Error in use_table\n");
00444 return -1;
00445 }
00446
00447 if (rls_dbf.query (rls_db, keys,ops, k_vals,
00448 result_cols, 1, sizeof(result_cols) / sizeof(db_key_t),
00449 0, &res) < 0) {
00450 LOG(L_ERR, "db_load_vs: Error while querying presentity\n");
00451 r = -1;
00452 res = NULL;
00453 }
00454 if (res) {
00455 for (i = 0; i < res->n; i++) {
00456 db_row_t *row = &res->rows[i];
00457 db_val_t *row_vals = ROW_VALUES(row);
00458 str id = STR_NULL;
00459 str uri = STR_NULL;
00460
00461 get_str_val(row_vals[0], id);
00462 get_str_val(row_vals[1], uri);
00463
00464 r = vs_create(&uri, &vs, NULL, s, max_list_nesting_level) | r;
00465 if ((r != 0) || (!vs)) { r = -1; break; }
00466
00467 strcpy(vs->dbid, id.s);
00468 DEBUG_LOG(" created VS to %.*s\n", FMT_STR(uri));
00469
00470 ptr_vector_add(&s->vs, vs);
00471
00472 db_load_vs_names(rls_db, vs);
00473 }
00474
00475 rls_dbf.free_result(rls_db, res);
00476 }
00477
00478 return r;
00479 }
00480
00481 int db_load_rls()
00482 {
00483
00484
00485 db_con_t* rls_db = NULL;
00486 int i, r = 0;
00487 rl_subscription_t *s;
00488 db_res_t *res = NULL;
00489 db_key_t result_cols[] = {
00490 "id", "doc_version", "dialog",
00491 "expires", "status", "contact",
00492 "uri", "package", "w_uri",
00493 "xcap_params"
00494 };
00495
00496 if (!use_db) return 0;
00497
00498 DEBUG_LOG("loading rls from db\n");
00499
00500
00501 if (rls_dbf.init) rls_db = rls_dbf.init(db_url);
00502 if (!rls_db) {
00503 LOG(L_ERR, "db_load_rls: Error while connecting database\n");
00504 return -1;
00505 }
00506
00507 if (rls_dbf.use_table(rls_db, rls_table) < 0) {
00508 LOG(L_ERR, "rls_load_rls: Error in use_table\n");
00509 return -1;
00510 }
00511
00512 if (rls_dbf.query (rls_db, NULL, NULL, NULL,
00513 result_cols, 0, sizeof(result_cols) / sizeof(db_key_t),
00514 0, &res) < 0) {
00515 LOG(L_ERR, "db_load_rls: Error while querying presentity\n");
00516 r = -1;
00517 res = NULL;
00518 }
00519 if (res) {
00520 for (i = 0; i < res->n; i++) {
00521 db_row_t *row = &res->rows[i];
00522 db_val_t *row_vals = ROW_VALUES(row);
00523 str id = STR_NULL;
00524 str contact = STR_NULL;
00525 str dialog = STR_NULL;
00526 str xcap_params = STR_NULL;
00527 str uri = STR_NULL;
00528 str package = STR_NULL;
00529 str w_uri = STR_NULL;
00530 subscription_status_t status;
00531 time_t expires = 0;
00532 int expires_after;
00533 dlg_t *dlg = NULL;
00534
00535 s = rls_alloc_subscription(rls_external_subscription);
00536 if (!s) { r = -1; break; }
00537
00538 get_str_val(row_vals[0], id);
00539 strcpy(s->dbid, id.s);
00540 get_int_val(row_vals[1], s->doc_version);
00541 get_blob_val(row_vals[2], dialog);
00542 get_time_val(row_vals[3], expires);
00543 get_int_val(row_vals[4], status);
00544 get_str_val(row_vals[5], contact);
00545 get_str_val(row_vals[6], uri);
00546 get_str_val(row_vals[7], package);
00547 get_str_val(row_vals[8], w_uri);
00548 get_blob_val(row_vals[9], xcap_params);
00549 if (expires != 0) expires_after = expires - time(NULL);
00550 else expires_after = 0;
00551 dlg = dlg2str(&dialog);
00552 sm_init_subscription_nolock_ex(rls_manager, &s->u.external,
00553 dlg,
00554 status,
00555 &contact,
00556 &uri,
00557 &package,
00558 &w_uri,
00559 expires_after,
00560 s);
00561 DEBUG_LOG(" created RLS to %.*s from %.*s\n",
00562 FMT_STR(uri), FMT_STR(w_uri));
00563
00564 if (str2xcap_params(&s->xcap_params, &xcap_params) < 0) {
00565 ERR("can't set xcap params\n");
00566 rls_free(s);
00567 s = 0;
00568 r = -1;
00569 break;
00570 }
00571
00572
00573 db_load_vs(rls_db, s);
00574 }
00575
00576 rls_dbf.free_result(rls_db, res);
00577 }
00578
00579
00580 if (rls_dbf.close) rls_dbf.close(rls_db);
00581
00582 DEBUG_LOG("rls loaded\n");
00583
00584 return r;
00585 }
00586