Coverage Report

Created: 2025-07-09 06:29

/src/opensips/cachedb/cachedb.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2011-2019 OpenSIPS Solutions
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * opensips is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 */
20
21
#include "cachedb.h"
22
#include "cachedb_cap.h"
23
#include "../dprint.h"
24
#include "../sr_module.h"
25
#include "../mem/mem.h"
26
#include "../mem/meminfo.h"
27
#include "../str.h"
28
#include "../ut.h"
29
30
#include <string.h>
31
#include <stdlib.h>
32
33
stat_var *cdb_total_queries;
34
stat_var *cdb_slow_queries;
35
36
struct cachedb_engine_t
37
{
38
  cachedb_engine cde;
39
  struct cachedb_engine_t* next;
40
};
41
42
int init_cdb_support(void)
43
0
{
44
0
  if (register_stat("cdb", "cdb_total_queries", &cdb_total_queries, 0) ||
45
0
      register_stat("cdb", "cdb_slow_queries", &cdb_slow_queries, 0)) {
46
0
    LM_ERR("failed to register CacheDB stats\n");
47
0
    return -1;
48
0
  }
49
50
0
  return 0;
51
0
}
52
53
int cachedb_store_url(struct cachedb_url **list,char *val)
54
0
{
55
0
  struct cachedb_url *new,*it;
56
0
  int len;
57
58
0
  len = strlen(val);
59
0
  new = pkg_malloc(sizeof(struct cachedb_url) + len);
60
0
  if (new == NULL) {
61
0
    LM_ERR("no more pkg\n");
62
0
    return -1;
63
0
  }
64
65
0
  memset(new,0,sizeof(struct cachedb_url) + len);
66
0
  new->url.len = len;
67
0
  new->url.s = (char *)(new + 1);
68
0
  memcpy(new->url.s,val,len);
69
70
0
  if (*list == NULL)
71
0
    *list = new;
72
0
  else {
73
0
    for (it=*list;it->next;it=it->next);
74
0
    it->next = new;
75
0
  }
76
77
0
  return 0;
78
0
}
79
80
void cachedb_free_url(struct cachedb_url *list)
81
0
{
82
0
  struct cachedb_url *it=list,*aux;
83
84
0
  while (it){
85
0
    aux = it->next;
86
0
    pkg_free(it);
87
0
    it=aux;
88
0
  }
89
0
}
90
91
static struct cachedb_engine_t* cachedb_list = NULL;
92
93
cachedb_engine* lookup_cachedb(str *name)
94
0
{
95
0
  struct cachedb_engine_t* cde_node;
96
97
0
  cde_node = cachedb_list;
98
99
0
  while(cde_node)
100
0
  {
101
0
    if (name->len == cde_node->cde.name.len &&
102
0
        strncmp(name->s, cde_node->cde.name.s, name->len) == 0)
103
0
      return &cde_node->cde;
104
105
0
    cde_node = cde_node->next;
106
0
  }
107
108
0
  return 0;
109
0
}
110
111
int cachedb_bind_mod(str *url,cachedb_funcs *funcs)
112
0
{
113
0
  char *mod_name,*grp_name;
114
0
  int len;
115
0
  str cachedb_name;
116
0
  cachedb_engine *cde;
117
118
119
0
  if (url == NULL || url->s == NULL || funcs == NULL) {
120
0
    LM_ERR("NULL parameter provided\n");
121
0
    return -1;
122
0
  }
123
124
0
  memset(funcs,0,sizeof(cachedb_funcs));
125
126
0
  mod_name = memchr(url->s,':',url->len);
127
0
  if (mod_name == NULL) {
128
0
    LM_ERR("cannot extract cachedb type\n");
129
0
    return -1;
130
0
  }
131
132
0
  len = mod_name - url->s;
133
0
  cachedb_name.len = len;
134
0
  cachedb_name.s = url->s;
135
136
  /* no point in giving here the grp_name, but for the sake of uniform
137
   * cachedb_urls in modules and for script, take in into account
138
   * the presence of grp here too, and skip it */
139
0
  grp_name=memchr(cachedb_name.s,':',cachedb_name.len);
140
0
  if (grp_name)
141
0
    cachedb_name.len = grp_name - cachedb_name.s;
142
143
0
  cde = lookup_cachedb(&cachedb_name);
144
0
  if (cde == NULL) {
145
0
    LM_ERR("failed to bind to [%.*s] module. Is it loaded ?\n",
146
0
        cachedb_name.len,cachedb_name.s);
147
0
    return -1;
148
0
  }
149
150
0
  LM_DBG("Binded to mod %.*s\n",cachedb_name.len,cachedb_name.s);
151
0
  *funcs = cde->cdb_func;
152
0
  return 0;
153
0
}
154
155
int register_cachedb(cachedb_engine* cde_entry)
156
0
{
157
0
  struct cachedb_engine_t* cde_node;
158
159
0
  if(cde_entry == NULL)
160
0
  {
161
0
    LM_ERR("null argument\n");
162
0
    return -1;
163
0
  }
164
165
0
  if (lookup_cachedb( &cde_entry->name))
166
0
  {
167
0
    LM_ERR("cachedb system <%.*s> already registered\n",
168
0
        cde_entry->name.len, cde_entry->name.s);
169
0
    return -1;
170
0
  }
171
172
0
  cde_node = (struct cachedb_engine_t*)pkg_malloc(
173
0
    sizeof(struct cachedb_engine_t) + cde_entry->name.len);
174
0
  if (cde_node== NULL)
175
0
  {
176
0
    LM_ERR("no more pkg memory\n");
177
0
    return -1;
178
0
  }
179
180
0
  cde_node->cde.name.s = (char*)cde_node + sizeof(struct cachedb_engine_t);
181
0
  memcpy(cde_node->cde.name.s, cde_entry->name.s, cde_entry->name.len);
182
0
  cde_node->cde.name.len = cde_entry->name.len;
183
184
0
  cde_node->cde.cdb_func = cde_entry->cdb_func;
185
186
0
  if (check_cachedb_api(&cde_node->cde) < 0) {
187
0
    LM_ERR("failed to meet api needs\n");
188
0
    pkg_free(cde_node);
189
0
    return -1;
190
0
  }
191
192
0
  cde_node->cde.default_connection = NULL;
193
0
  cde_node->cde.connections = NULL;
194
195
0
  cde_node->next = cachedb_list;
196
0
  cachedb_list = cde_node;
197
198
0
  LM_DBG("registered cachedb system [%.*s]\n", cde_node->cde.name.len,
199
0
      cde_node->cde.name.s);
200
201
0
  return 0;
202
0
}
203
204
int cachedb_insert_connection(cachedb_engine *cde,cachedb_con *conn)
205
0
{
206
0
  cachedb_con_list *new,*it;
207
0
  str grp;
208
209
0
  grp.s = ((cachedb_pool_con *)conn->data)->id->group_name;
210
0
  if (grp.s)
211
0
    grp.len = strlen(grp.s);
212
213
0
  if (grp.s == NULL || grp.len == 0) {
214
0
    LM_DBG("inserting default script connection\n");
215
0
    cde->default_connection = conn;
216
0
    return 0;
217
0
  }
218
219
0
  LM_DBG("inserting grp connection [%.*s]\n",grp.len,grp.s);
220
221
0
  new = pkg_malloc(sizeof(cachedb_con_list));
222
0
  if (new == NULL) {
223
0
    LM_ERR("no more pkg\n");
224
0
    return -1;
225
0
  }
226
227
0
  memset(new,0,sizeof(cachedb_con_list));
228
0
  new->connection = conn;
229
0
  new->grp = grp;
230
231
0
  if (cde->connections == NULL) {
232
0
    cde->connections = new;
233
0
  } else {
234
0
    for (it=cde->connections;it->next;it=it->next);
235
0
    it->next = new;
236
0
  }
237
238
0
  return 0;
239
0
}
240
241
int cachedb_put_connection(str *cachedb_name,cachedb_con *con)
242
0
{
243
0
  cachedb_engine *cde;
244
245
0
  cde = lookup_cachedb(cachedb_name);
246
0
  if(cde == NULL)
247
0
  {
248
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
249
0
        " this name registered\n",
250
0
        cachedb_name->len,cachedb_name->s);
251
0
    return -1;
252
0
  }
253
254
0
  LM_DBG("in cachedb_put_connection %p\n",con);
255
0
  if (cachedb_insert_connection(cde,con) < 0) {
256
0
    LM_ERR("failed to insert new connection\n");
257
0
    return -1;
258
0
  }
259
260
0
  return 0;
261
0
}
262
263
cachedb_con *cachedb_get_connection(cachedb_engine *cde,str *group_name)
264
0
{
265
0
  cachedb_con_list *ret;
266
267
0
  if (cde == NULL) {
268
0
    LM_ERR("no such cachedb engine\n");
269
0
    return 0;
270
0
  }
271
272
0
  if (group_name == NULL || group_name->s == NULL || group_name->len == 0)
273
0
    return cde->default_connection;
274
0
  else {
275
0
    for (ret=cde->connections;ret;ret=ret->next) {
276
0
      if (ret->grp.len == group_name->len &&
277
0
        memcmp(ret->grp.s,group_name->s,group_name->len) == 0)
278
0
        return ret->connection;
279
0
    }
280
0
    return NULL;
281
0
  }
282
0
}
283
284
void cachedb_end_connections(str *cachedb_name)
285
0
{
286
0
  cachedb_engine *cde;
287
0
  cachedb_con_list *it;
288
289
0
  cde = lookup_cachedb(cachedb_name);
290
0
  if(cde == NULL) {
291
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
292
0
        " this name registered\n",
293
0
        cachedb_name->len,cachedb_name->s);
294
0
    return;
295
0
  }
296
297
0
  if (cde->default_connection)
298
0
    cde->cdb_func.destroy(cde->default_connection);
299
300
0
  for (it=cde->connections;it;it=it->next)
301
0
    cde->cdb_func.destroy(it->connection);
302
0
}
303
304
305
int cachedb_remove(str* cachedb_name, str* attr)
306
0
{
307
0
  cachedb_engine* cde;
308
0
  str cde_engine,grp_name;
309
0
  char *p;
310
0
  cachedb_con *con;
311
0
  int ret;
312
313
0
  if(cachedb_name == NULL || attr == NULL)
314
0
  {
315
0
    LM_ERR("null arguments\n");
316
0
    return -1;
317
0
  }
318
319
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
320
0
  if (p == NULL) {
321
0
    cde_engine = *cachedb_name;
322
0
    grp_name.s = NULL;
323
0
    grp_name.len = 0;
324
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
325
0
  } else {
326
0
    cde_engine.s = cachedb_name->s;
327
0
    cde_engine.len = p - cde_engine.s;
328
0
    grp_name.s = p+1;
329
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
330
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
331
0
        cde_engine.s,grp_name.len,grp_name.s);
332
333
0
  }
334
335
0
  cde = lookup_cachedb(&cde_engine);
336
0
  if(cde == NULL)
337
0
  {
338
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
339
0
        " this name registered\n",
340
0
        cde_engine.len,cde_engine.s);
341
0
    return -1;
342
0
  }
343
344
0
  con = cachedb_get_connection(cde,&grp_name);
345
0
  if (con == NULL) {
346
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
347
0
        grp_name.len,grp_name.s);
348
0
    return -1;
349
0
  }
350
351
0
  ret = cde->cdb_func.remove(con,attr);
352
0
  if (ret == 0)
353
0
    ret++;
354
355
0
  return ret;
356
0
}
357
358
int cachedb_store(str* cachedb_name, str* attr, str* val,int expires)
359
0
{
360
0
  cachedb_engine* cde;
361
0
  str cde_engine,grp_name;
362
0
  char *p;
363
0
  cachedb_con *con;
364
0
  int ret;
365
366
0
  if(cachedb_name == NULL || attr == NULL || val == NULL)
367
0
  {
368
0
    LM_ERR("null arguments\n");
369
0
    return -1;
370
0
  }
371
372
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
373
0
  if (p == NULL) {
374
0
    cde_engine = *cachedb_name;
375
0
    grp_name.s = NULL;
376
0
    grp_name.len = 0;
377
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
378
0
  } else {
379
0
    cde_engine.s = cachedb_name->s;
380
0
    cde_engine.len = p - cde_engine.s;
381
0
    grp_name.s = p+1;
382
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
383
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
384
0
        cde_engine.s,grp_name.len,grp_name.s);
385
386
0
  }
387
388
0
  cde = lookup_cachedb(&cde_engine);
389
0
  if(cde == NULL)
390
0
  {
391
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
392
0
        " this name registered\n",
393
0
        cde_engine.len,cde_engine.s);
394
0
    return -1;
395
0
  }
396
397
0
  con = cachedb_get_connection(cde,&grp_name);
398
0
  if (con == NULL) {
399
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
400
0
        grp_name.len,grp_name.s);
401
0
    return -1;
402
0
  }
403
404
0
  ret = cde->cdb_func.set(con,attr,val,expires);
405
0
  if (ret ==0)
406
0
    ret++;
407
408
0
  return ret;
409
0
}
410
411
int cachedb_fetch(str* cachedb_name, str* attr, str* val)
412
0
{
413
0
  cachedb_engine* cde;
414
0
  str cde_engine,grp_name;
415
0
  char *p;
416
0
  cachedb_con *con;
417
0
  int ret;
418
419
0
  if(cachedb_name == NULL || attr == NULL || val == NULL)
420
0
  {
421
0
    LM_ERR("null arguments\n");
422
0
    return -1;
423
0
  }
424
425
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
426
0
  if (p == NULL) {
427
0
    cde_engine = *cachedb_name;
428
0
    grp_name.s = NULL;
429
0
    grp_name.len = 0;
430
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
431
0
  } else {
432
0
    cde_engine.s = cachedb_name->s;
433
0
    cde_engine.len = p - cde_engine.s;
434
0
    grp_name.s = p+1;
435
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
436
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
437
0
        cde_engine.s,grp_name.len,grp_name.s);
438
439
0
  }
440
441
0
  cde = lookup_cachedb(&cde_engine);
442
0
  if(cde == NULL)
443
0
  {
444
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
445
0
        " this name registered\n",
446
0
        cde_engine.len,cde_engine.s);
447
0
    return -1;
448
0
  }
449
450
0
  con = cachedb_get_connection(cde,&grp_name);
451
0
  if (con == NULL) {
452
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
453
0
        grp_name.len,grp_name.s);
454
0
    return -1;
455
0
  }
456
457
0
  ret = cde->cdb_func.get(con,attr,val);
458
0
  if (ret == 0)
459
0
    ret++;
460
461
0
  return ret;
462
0
}
463
464
int cachedb_counter_fetch(str* cachedb_name, str* attr, int* val)
465
0
{
466
0
  cachedb_engine* cde;
467
0
  str cde_engine,grp_name;
468
0
  char *p;
469
0
  cachedb_con *con;
470
0
  int ret;
471
472
0
  if(cachedb_name == NULL || attr == NULL || val == NULL)
473
0
  {
474
0
    LM_ERR("null arguments\n");
475
0
    return -1;
476
0
  }
477
478
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
479
0
  if (p == NULL) {
480
0
    cde_engine = *cachedb_name;
481
0
    grp_name.s = NULL;
482
0
    grp_name.len = 0;
483
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
484
0
  } else {
485
0
    cde_engine.s = cachedb_name->s;
486
0
    cde_engine.len = p - cde_engine.s;
487
0
    grp_name.s = p+1;
488
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
489
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
490
0
        cde_engine.s,grp_name.len,grp_name.s);
491
492
0
  }
493
494
0
  cde = lookup_cachedb(&cde_engine);
495
0
  if(cde == NULL)
496
0
  {
497
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
498
0
        " this name registered\n",
499
0
        cde_engine.len,cde_engine.s);
500
0
    return -1;
501
0
  }
502
503
0
  con = cachedb_get_connection(cde,&grp_name);
504
0
  if (con == NULL) {
505
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
506
0
        grp_name.len,grp_name.s);
507
0
    return -1;
508
0
  }
509
510
0
  ret = cde->cdb_func.get_counter(con,attr,val);
511
0
  if (ret == 0)
512
0
    ret++;
513
514
0
  return ret;
515
0
}
516
517
int cachedb_add(str* cachedb_name, str* attr, int val,int expires,int *new_val)
518
0
{
519
0
  cachedb_engine* cde;
520
0
  str cde_engine,grp_name;
521
0
  char *p;
522
0
  cachedb_con *con;
523
0
  int ret;
524
525
0
  if(cachedb_name == NULL || attr == NULL)
526
0
  {
527
0
    LM_ERR("null arguments\n");
528
0
    return -1;
529
0
  }
530
531
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
532
0
  if (p == NULL) {
533
0
    cde_engine = *cachedb_name;
534
0
    grp_name.s = NULL;
535
0
    grp_name.len = 0;
536
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
537
0
  } else {
538
0
    cde_engine.s = cachedb_name->s;
539
0
    cde_engine.len = p - cde_engine.s;
540
0
    grp_name.s = p+1;
541
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
542
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
543
0
        cde_engine.s,grp_name.len,grp_name.s);
544
545
0
  }
546
547
0
  cde = lookup_cachedb(&cde_engine);
548
0
  if(cde == NULL)
549
0
  {
550
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
551
0
        " this name registered\n",
552
0
        cde_engine.len,cde_engine.s);
553
0
    return -1;
554
0
  }
555
556
0
  if (!CACHEDB_CAPABILITY(&cde->cdb_func,CACHEDB_CAP_ADD)) {
557
0
    LM_ERR("Engine %.*s does not support add ops\n",
558
0
        cde_engine.len,cde_engine.s);
559
0
    return -1;
560
0
  }
561
562
0
  con = cachedb_get_connection(cde,&grp_name);
563
0
  if (con == NULL) {
564
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
565
0
        grp_name.len,grp_name.s);
566
0
    return -1;
567
0
  }
568
569
0
  ret = cde->cdb_func.add(con,attr,val,expires,new_val);
570
0
  if (ret == 0)
571
0
    ret++;
572
573
0
  return ret;
574
0
}
575
576
int cachedb_sub(str* cachedb_name, str* attr, int val,int expires,int *new_val)
577
0
{
578
0
  cachedb_engine* cde;
579
0
  str cde_engine,grp_name;
580
0
  char *p;
581
0
  cachedb_con *con;
582
0
  int ret;
583
584
0
  if(cachedb_name == NULL || attr == NULL)
585
0
  {
586
0
    LM_ERR("null arguments\n");
587
0
    return -1;
588
0
  }
589
590
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
591
0
  if (p == NULL) {
592
0
    cde_engine = *cachedb_name;
593
0
    grp_name.s = NULL;
594
0
    grp_name.len = 0;
595
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
596
0
  } else {
597
0
    cde_engine.s = cachedb_name->s;
598
0
    cde_engine.len = p - cde_engine.s;
599
0
    grp_name.s = p+1;
600
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
601
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
602
0
        cde_engine.s,grp_name.len,grp_name.s);
603
604
0
  }
605
606
0
  cde = lookup_cachedb(&cde_engine);
607
0
  if(cde == NULL)
608
0
  {
609
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
610
0
        " this name registered\n",
611
0
        cde_engine.len,cde_engine.s);
612
0
    return -1;
613
0
  }
614
615
0
  if (!CACHEDB_CAPABILITY(&cde->cdb_func,CACHEDB_CAP_SUB)) {
616
0
    LM_ERR("Engine %.*s does not support sub ops\n",
617
0
        cde_engine.len,cde_engine.s);
618
0
    return -1;
619
0
  }
620
621
0
  con = cachedb_get_connection(cde,&grp_name);
622
0
  if (con == NULL) {
623
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
624
0
        grp_name.len,grp_name.s);
625
0
    return -1;
626
0
  }
627
628
0
  ret = cde->cdb_func.sub(con,attr,val,expires,new_val);
629
0
  if (ret == 0)
630
0
    ret++;
631
632
0
  return ret;
633
0
}
634
635
cachedb_con* cachedb_do_init(str *url,void* (*new_connection)(struct cachedb_id *))
636
0
{
637
0
  struct cachedb_id* id;
638
0
  cachedb_con* res;
639
0
  void *con;
640
641
0
  if (url == NULL || url->s == NULL || new_connection == NULL) {
642
0
    LM_ERR("NULL parameter provided\n");
643
0
    return 0;
644
0
  }
645
646
0
  res = pkg_malloc(sizeof(cachedb_con) + url->len);
647
0
  if (res == NULL) {
648
0
    LM_ERR("no more pkg mem\n");
649
0
    return 0;
650
0
  }
651
652
0
  id = NULL;
653
654
0
  memset(res,0,sizeof(cachedb_con) + url->len);
655
0
  res->url.s = (char *)res + sizeof(cachedb_con);
656
0
  res->url.len = url->len;
657
0
  memcpy(res->url.s,url->s,url->len);
658
659
0
  id = new_cachedb_id(url);
660
0
  if (!id) {
661
0
    LM_ERR("cannot parse url [%s]\n", db_url_escape(url));
662
0
    pkg_free(res);
663
0
    return 0;
664
0
  }
665
666
0
  con = cachedb_pool_get(id);
667
0
  if (con == NULL) {
668
0
    LM_DBG("opening new connection\n");
669
0
    con = new_connection(id);
670
0
    if (con == NULL) {
671
0
      LM_ERR("failed to open connection\n");
672
0
      goto err;
673
0
    }
674
675
0
    cachedb_pool_insert((cachedb_pool_con *)con);
676
0
  } else {
677
0
    LM_DBG("connection already in pool\n");
678
0
    free_cachedb_id(id);
679
0
  }
680
681
0
  res->data = con;
682
0
  return res;
683
684
0
err:
685
0
  if (res)
686
0
    pkg_free(res);
687
0
  if (id)
688
0
    free_cachedb_id(id);
689
690
0
  return 0;
691
0
}
692
693
void cachedb_do_close(cachedb_con *con, void (*free_connection)(cachedb_pool_con *))
694
0
{
695
0
  cachedb_pool_con *tmp;
696
697
0
  if (con == NULL) {
698
0
    LM_ERR("NULL parameter provided\n");
699
0
    return;
700
0
  }
701
702
0
  tmp = (cachedb_pool_con*)con->data;
703
0
  if (cachedb_pool_remove(tmp) == 1) {
704
0
    free_connection(tmp);
705
0
  }
706
707
0
  pkg_free(con);
708
0
}
709
710
int cachedb_raw_query(str* cachedb_name, str* attr, cdb_raw_entry*** reply,int expected_kv_no,int *rpl_no)
711
0
{
712
0
  cachedb_engine* cde;
713
0
  str cde_engine,grp_name;
714
0
  char *p;
715
0
  cachedb_con *con;
716
0
  int ret;
717
718
0
  if(cachedb_name == NULL || attr == NULL)
719
0
  {
720
0
    LM_ERR("null arguments\n");
721
0
    return -1;
722
0
  }
723
724
0
  p = memchr(cachedb_name->s,':',cachedb_name->len);
725
0
  if (p == NULL) {
726
0
    cde_engine = *cachedb_name;
727
0
    grp_name.s = NULL;
728
0
    grp_name.len = 0;
729
0
    LM_DBG("from script [%.*s] - no grp\n",cde_engine.len,cde_engine.s);
730
0
  } else {
731
0
    cde_engine.s = cachedb_name->s;
732
0
    cde_engine.len = p - cde_engine.s;
733
0
    grp_name.s = p+1;
734
0
    grp_name.len = cachedb_name->len - cde_engine.len -1;
735
0
    LM_DBG("from script [%.*s] - with grp [%.*s]\n",cde_engine.len,
736
0
        cde_engine.s,grp_name.len,grp_name.s);
737
738
0
  }
739
740
0
  cde = lookup_cachedb(&cde_engine);
741
0
  if(cde == NULL)
742
0
  {
743
0
    LM_ERR("Wrong argument <%.*s> - no cachedb system with"
744
0
        " this name registered\n",
745
0
        cde_engine.len,cde_engine.s);
746
0
    return -1;
747
0
  }
748
749
0
  if (!CACHEDB_CAPABILITY(&cde->cdb_func,CACHEDB_CAP_RAW)) {
750
0
    LM_ERR("The backend does not support raw queries\n");
751
0
    return -1;
752
0
  }
753
754
0
  con = cachedb_get_connection(cde,&grp_name);
755
0
  if (con == NULL) {
756
0
    LM_ERR("failed to get connection for grp name [%.*s] : check db_url\n",
757
0
        grp_name.len,grp_name.s);
758
0
    return -1;
759
0
  }
760
761
0
  ret = cde->cdb_func.raw_query(con,attr,reply,expected_kv_no,rpl_no);
762
0
  if (ret == 0)
763
0
    ret++;
764
765
0
  return ret;
766
0
}
767
768
void free_raw_fetch(cdb_raw_entry **reply, int num_cols, int num_rows)
769
0
{
770
0
  int i,j;
771
772
0
  for (i=0;i<num_rows;i++) {
773
0
    for (j=0;j<num_cols;j++) {
774
0
      if (reply[i][j].type == CDB_STR)
775
0
        pkg_free(reply[i][j].val.s.s);
776
0
    }
777
0
    pkg_free(reply[i]);
778
0
  }
779
780
0
  pkg_free(reply);
781
0
}