You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules_s/bdb/bdb_base.c

324 lines
7.0 KiB

/* $Id$
*
* Copyright (C) 2006-2007 Sippy Software, Inc. <sales@sippysoft.com>
*
* This file is part of ser, a free SIP server.
*
* ser is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* ser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "bdb.h"
#define BDB_ID "bdb://"
#define BDB_ID_LEN (sizeof(BDB_ID)-1)
#define BDB_PATH_LEN MAXPATHLEN
/*
* Initialize database connection
*/
db_con_t* bdb_init(const char* _sqlurl)
{
db_con_t* _res;
char *p;
char bdb_path[BDB_PATH_LEN];
int ret;
if (!_sqlurl)
{
#ifdef BDB_EXTRA_DEBUG
LOG(L_ERR, "BDB:bdb_init: Invalid parameter value\n");
#endif
return NULL;
}
p = (char *)_sqlurl;
if(strncmp(p, BDB_ID, sizeof(BDB_ID) - 1))
{
LOG(L_ERR, "BDB:bdb_init: invalid database URL - should be:"
" <%s[/]path/to/directory>\n", BDB_ID);
return NULL;
}
p += BDB_ID_LEN;
if(p[0] != '/')
{
if(sizeof(CFG_DIR) + strlen(p) + 2 > BDB_PATH_LEN)
{
LOG(L_ERR, "BDB:bdb_init: path to database is too long\n");
return NULL;
}
strcpy(bdb_path, CFG_DIR);
bdb_path[sizeof(CFG_DIR) - 1] = '/';
strcpy(&bdb_path[sizeof(CFG_DIR)], p);
p = bdb_path;
}
#ifdef BDB_EXTRA_DEBUG
LOG(L_NOTICE, "BDB:bdb_init: bdb_path = %s\n", p);
#endif
_res = pkg_malloc(sizeof(db_con_t) + sizeof(bdb_con_t));
if (!_res)
{
LOG(L_ERR, "BDB:bdb_init: No memory left\n");
return NULL;
}
memset(_res, 0, sizeof(db_con_t) + sizeof(bdb_con_t));
_res->tail = (unsigned long)((char*)_res + sizeof(bdb_con_t));
ret = db_env_create(&BDB_CON_DBENV(_res), 0);
if (ret != 0) {
LOG(L_ERR, "BDB:bdb_init: unable to db_env_create(): %s\n", db_strerror(ret));
pkg_free(_res);
return NULL;
}
ret = BDB_CON_DBENV(_res)->open(BDB_CON_DBENV(_res), p, DB_CREATE | DB_INIT_MPOOL | DB_INIT_CDB, 0);
if (ret != 0) {
LOG(L_ERR, "BDB:bdb_init: unable to open environment: %s\n", db_strerror(ret));
pkg_free(_res);
return NULL;
}
return _res;
}
/*
* Close a database connection
*/
void bdb_close(db_con_t* _h)
{
if (!_h)
{
#ifdef DBT_EXTRA_DEBUG
LOG(L_ERR, "BDB:bdb_close: Invalid parameter value\n");
#endif
return;
}
if (BDB_CON_DB(_h) != NULL) {
bdb_close_table(_h);
}
if (BDB_CON_DBENV(_h) != NULL) {
BDB_CON_DBENV(_h)->close(BDB_CON_DBENV(_h), 0);
}
pkg_free(_h);
return;
}
/*
* Raw SQL query -- is not the case to have this method
*/
int bdb_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
{
*_r = NULL;
LOG(L_ERR, "BDB:bdb_raw_query: method is not supported.\n");
return -1;
}
/*
* Query table for specified rows
* _h: structure representing database connection
* _k: key names
* _op: operators
* _v: values of the keys that must match
* _c: column names to return
* _n: number of key=values pairs to compare
* _nc: number of columns to return
* _o: order by the specified column
*/
int bdb_query(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v,
db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r)
{
bdb_srow_p s_r; /* search keys row */
bdb_rrow_p r_r; /* return keys row */
int ret;
*_r = NULL;
s_r = NULL;
r_r = NULL;
if (_o) {
LOG(L_ERR, "BDB:bdb_query: ORDER BY is not supported.\n");
return -1;
}
if ((ret = bdb_srow_db2bdb(_h, _k, _op, _v, _n, &s_r)) < 0) {
return -1;
};
if ((ret = bdb_rrow_db2bdb(_h, _c, _nc, &r_r)) < 0) {
bdb_free_srow(s_r);
return -1;
};
if ((ret = bdb_query_table(_h, s_r, r_r, _nc, _r)) < 0) {
bdb_free_rrow(r_r);
bdb_free_srow(s_r);
return -1;
};
bdb_free_rrow(r_r);
bdb_free_srow(s_r);
return 0;
}
/*
* Insert a row into table
*/
int bdb_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
{
bdb_row_p r;
DBC *cursorp;
int ret;
if ((ret = bdb_row_db2bdb(_h, _k, _v, _n, &r)) < 0) {
return -1;
};
if (r->key.size == 0) {
LOG(L_ERR, "BDB:bdb_insert: no primary key specified\n");
bdb_free_row(r);
return -1;
}
BDB_CON_DB(_h)->cursor(BDB_CON_DB(_h), NULL, &cursorp, DB_WRITECURSOR);
ret = cursorp->c_put(cursorp, &(r->key), &(r->data), DB_KEYLAST);
if (ret < 0) {
LOG(L_ERR, "BDB:bdb_insert: unable to insert record: %s\n", db_strerror(ret));
}
if (cursorp != NULL) {
cursorp->c_close(cursorp);
}
bdb_free_row(r);
return ret;
}
/*
* Delete a row from table
*/
int bdb_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
{
bdb_srow_p s_r; /* search keys row */
int ret;
s_r = NULL;
if ((ret = bdb_srow_db2bdb(_h, _k, _o, _v, _n, &s_r)) < 0) {
return -1;
};
if ((ret = bdb_delete_table(_h, s_r)) < 0) {
bdb_free_srow(s_r);
return -1;
};
bdb_free_srow(s_r);
return 0;
}
/*
* Update a row in table
*/
int bdb_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
db_key_t* _uk, db_val_t* _uv, int _n, int _un)
{
bdb_srow_p s_r; /* search keys row */
bdb_urow_p u_r; /* update row */
int ret;
s_r = NULL;
u_r = NULL;
if ((ret = bdb_srow_db2bdb(_h, _k, _o, _v, _n, &s_r)) < 0) {
return -1;
};
if ((ret = bdb_urow_db2bdb(_h, _uk, _uv, _un, &u_r)) < 0) {
bdb_free_srow(s_r);
return -1;
};
if ((ret = bdb_update_table(_h, s_r, u_r)) < 0) {
bdb_free_urow(u_r);
bdb_free_srow(s_r);
return -1;
};
bdb_free_urow(u_r);
bdb_free_srow(s_r);
return 0;
}
/*
* Free all memory allocated by get_result
*/
int bdb_free_result(db_con_t* _h, db_res_t* _r)
{
db_row_t* r;
db_val_t* v;
int i, j;
if (!_r) {
#ifdef BDB_EXTRA_DEBUG
LOG(L_NOTICE, "BDB:bdb_free_result: NULL pointer\n");
#endif
return 0;
}
for (i = 0; i < RES_ROW_N(_r); i++) {
r = &(RES_ROWS(_r)[i]);
for (j = 0; j < RES_COL_N(_r); j++) {
v = &(ROW_VALUES(r)[j]);
if (VAL_TYPE(v) == DB_STRING || VAL_TYPE(v) == DB_STR || VAL_TYPE(v) == DB_BLOB) {
free(VAL_STR(v).s);
}
}
free(ROW_VALUES(r));
}
free(RES_ROWS(_r));
for (i = 0; i < RES_COL_N(_r); i++) {
pkg_free((void *)RES_NAMES(_r)[i]);
}
pkg_free(RES_NAMES(_r));
pkg_free(RES_TYPES(_r));
pkg_free(_r);
return 0;
}