Пример #1
0
/** Prepare a query
 * @param cmd DB command structure
 * @param bcmd berkey DB command structure
 * @return 0 on success, -1 on error
 */
int bdb_prepare_query(db_cmd_t *cmd, bdb_cmd_t *bcmd)
{
	bdb_tcache_t *tbc = NULL;
	bdb_table_t *tp = NULL;
	bdb_fld_t *f;
	db_fld_t *fld;
	int mode;
	int i;

	if(bcmd->bcon == NULL || bcmd->bcon->dbp == NULL)
		return -1;

	tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
	if(tbc == NULL) {
		ERR("bdb: table does not exist!\n");
		return -1;
	}

	tp = tbc->dtp;
	if(tp == NULL || tp->db == NULL) {
		ERR("bdb: table not loaded!\n");
		return -1;
	}

	mode = 0;
	if(!DB_FLD_EMPTY(cmd->result)) { /* columns to be returned provided */
		if(cmd->result_count > tp->ncols) {
			ERR("bdb: too many columns in query\n");
			goto error;
		}
	} else {
		mode = 1;
		cmd->result = db_fld(tp->ncols + 1);
		cmd->result_count = tp->ncols;
		for(i = 0; i < cmd->result_count; i++) {
			if(bdb_fld(cmd->result + i, cmd->table.s) < 0)
				goto error;
		}
	}

	for(i = 0; i < cmd->result_count; i++) {
		fld = cmd->result + i;
		f = DB_GET_PAYLOAD(fld);
		if(mode == 1) {
			DBG("bdb: column name [%.*s]\n", tp->colp[i]->name.len,
					tp->colp[i]->name.s);

			f->name = pkg_malloc(tp->colp[i]->name.len + 1);
			if(f->name == NULL) {
				ERR("bdb: Out of private memory\n");
				goto error;
			}
			strncpy(f->name, tp->colp[i]->name.s, tp->colp[i]->name.len);
			f->name[tp->colp[i]->name.len] = '\0';
			fld->name = f->name;
			fld->type = tp->colp[i]->type;
			f->col_pos = i;
		} else {
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Column not found\n");
				goto error;
			}
		}
		switch(fld->type) {
			case DB_INT:
			case DB_BITMAP:
			case DB_FLOAT:
			case DB_DOUBLE:
			case DB_DATETIME:
			case DB_STR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.lstr.s = f->buf.s;
				break;

			case DB_CSTR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.cstr = f->buf.s;
				break;

			case DB_BLOB:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("mysql: No memory left\n");
					goto error;
				}
				fld[i].v.blob.s = f->buf.s;
				break;

			case DB_NONE:
				/* Eliminates gcc warning */
				break;
		}
	}

	if(!DB_FLD_EMPTY(cmd->match)) {
		if(cmd->match_count > tp->ncols) {
			ERR("bdb: too many columns in match struct of query\n");
			goto error;
		}
		for(i = 0; i < cmd->match_count; i++) {
			fld = cmd->result + i;
			f = DB_GET_PAYLOAD(fld);
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Match column not found\n");
				goto error;
			}
		}
	}

	return 0;

error:
	return -1;
}
Пример #2
0
/*
_bdb_delete_cursor -- called from bdb_delete when the query involves operators
  other than equal '='. Adds support for queries like this:
	DELETE from SomeTable WHERE _k[0] < _v[0]
  In this case, the keys _k are not the actually schema keys, so we need to
  iterate via cursor to perform this operation.
*/
int _bdb_delete_cursor(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    db_res_t* _r   = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    int i, ret, klen=MAX_ROW_SIZE;
    DBT key, data;
    DB *db;
    DBC *dbcp;
    int *lkey=NULL;
    str s;

    i = ret = 0;

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE by cursor in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    if(_k)
    {   lkey = bdb_get_colmap(_tp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }

    /* create an empty db_res_t which gets returned even if no result */
    _r = db_new_result();
    if (!_r)
    {   LM_ERR("no memory for result \n");
    }

    RES_ROW_N(_r) = 0;

    /* fill in the col part of db_res_t */
    if ((ret = bdb_get_columns(_tp, _r, 0, 0)) != 0)
    {   LM_ERR("Error while getting column names\n");
        goto error;
    }

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* Acquire a cursor for the database. */
    if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR)) != 0)
    {   LM_ERR("Error creating cursor\n");
    }

    while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
    {
        if(!strncasecmp((char*)key.data,"METADATA",8))
            continue;

        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( _r, dbuf, 0)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

        if(bdb_row_match(_k, _op, _v, _n, _r, lkey ))
        {

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("DELETE ROW by KEY:  [%.*s]\n", (int) key.size,
                   (char *)key.data);
#endif

            if((ret = dbcp->c_del(dbcp, 0)) != 0)
            {
                /* Berkeley DB error handler */
                LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
                bdblib_recover(_tp,ret);
            }

        }

        memset(dbuf, 0, MAX_ROW_SIZE);
        bdb_free_rows( _r);
    }
    ret = 0;

error:
    if(dbcp)
        dbcp->c_close(dbcp);
    if(_r)
        bdb_free_result(_r);
    if(lkey)
        pkg_free(lkey);

    return ret;
}
Пример #3
0
/**
 * Execute a query
 * @param cmd DB command structure
 * @param bcmd Berkely DB command structure
 * @return 0 on success, -1 on error
 */
int bdb_query(db_cmd_t *cmd, bdb_cmd_t *bcmd)
{
	DBT key;
	DB *db;
	static char kbuf[MAX_ROW_SIZE];
	int klen;

	bdb_tcache_t *tbc = NULL;
	bdb_table_t *tp = NULL;

	if(bcmd->bcon == NULL || bcmd->bcon->dbp == NULL)
		return -1;

	tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
	if(tbc == NULL) {
		ERR("bdb: table does not exist!\n");
		return -1;
	}

	tp = tbc->dtp;
	if(tp == NULL) {
		ERR("bdb: table not loaded!\n");
		return -1;
	}
	db = tp->db;
	if(db == NULL) {
		ERR("bdb: db structure not initialized!\n");
		return -1;
	}

	if(DB_FLD_EMPTY(cmd->match)) { /* no match constraint */
		if(db->cursor(db, NULL, &bcmd->dbcp, 0) != 0) {
			ERR("bdb: error creating cursor\n");
			goto error;
		}
		bcmd->skey.len = 0;
		return 0;
	}

	memset(&key, 0, sizeof(DBT));
	memset(kbuf, 0, MAX_ROW_SIZE);

	klen = MAX_ROW_SIZE;
	if(bdblib_valtochar(tp, cmd->match, cmd->match_count, kbuf, &klen, BDB_KEY)
			!= 0) {
		ERR("bdb: error creating key\n");
		goto error;
	}

	if(klen > bcmd->skey_size || bcmd->skey.s == NULL) {
		if(bcmd->skey.s != NULL)
			pkg_free(bcmd->skey.s);
		bcmd->skey.s = (char *)pkg_malloc(klen * sizeof(char));
		if(bcmd->skey.s == NULL) {
			ERR("bdb: no pkg memory\n");
			goto error;
		}
		bcmd->skey_size = klen;
	}
	memcpy(bcmd->skey.s, kbuf, klen);
	bcmd->skey.len = klen;

	return 0;
error:
	return -1;
}
Пример #4
0
/*
 * Delete a row from table
 *
 * To delete ALL rows:
 *   do Not specify any keys, or values, and _n <=0
 *
 */
int bdb_delete(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    int i, j, ret, klen;
    int *lkey=NULL;
    DBT key;
    DB *db;
    DBC *dbcp;
    str s;

    i = j = ret = 0;
    klen=MAX_ROW_SIZE;

    if (_op)
        return ( _bdb_delete_cursor(_h, _k, _op, _v, _n) );

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);

    if(!_k || !_v || _n<=0)
    {
        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR) ) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        while ((ret = dbcp->c_get(dbcp, &key, NULL, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data);
#endif
            ret = dbcp->c_del(dbcp, 0);
        }

        dbcp->c_close(dbcp);
        return 0;
    }

    lkey = bdb_get_colmap(_tp, _k, _n);
    if(!lkey)  return -5;

    /* make the key */
    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in bdblib_makekey\n");
        ret = -6;
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    if ((ret = db->del(db, NULL, &key, 0)) == 0)
    {
        bdblib_log(JLOG_DELETE, _tp, kbuf, klen);

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("DELETED ROW \n KEY: %s \n", (char *)key.data);
#endif
    }
    else
    {   /*Berkeley DB error handler*/
        switch(ret) {

        case DB_NOTFOUND:
            ret = 0;
            break;

        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        /* The operation was selected to resolve a deadlock. */
        case DB_SECONDARY_BAD:
        /* A secondary index references a nonexistent primary key. */
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->del error: %s.\n"
                    , db_strerror(ret));
            bdblib_recover(_tp, ret);
            goto error;
        }
    }

    ret = 0;

error:
    if(lkey)
        pkg_free(lkey);

    return ret;

}
Пример #5
0
/*
 * Insert a row into table
 */
int bdb_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    int i, j, ret, klen, dlen;
    int *lkey=NULL;
    DBT key, data;
    DB *db;
    str s;

    i = j = ret = 0;
    klen=MAX_ROW_SIZE;
    dlen=MAX_ROW_SIZE;

    if ((!_h) || (!_v) || !CON_TABLE(_h))
    {   return -1;
    }

    if (!_k)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_ERR("DB INSERT without KEYs not implemented! \n");
#endif
        return -2;
    }

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("INSERT in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);

    if(_tp->ncols<_n)
    {   LM_WARN("more values than columns!!\n");
        return -5;
    }

    lkey = bdb_get_colmap(_tp, _k, _n);
    if(!lkey)  return -7;

    /* verify col types provided */
    for(i=0; i<_n; i++)
    {   j = (lkey)?lkey[i]:i;
        if(bdb_is_neq_type(_tp->colp[j]->type, _v[i].type))
        {
            LM_WARN("incompatible types v[%d] - c[%d]!\n", i, j);
            ret = -8;
            goto error;
        }
    }

    /* make the key */
    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in bdblib_valtochar  \n");
        ret = -9;
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    //make the value (row)
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    if ( (ret = bdblib_valtochar(_tp, lkey, dbuf, &dlen, _v, _n, BDB_VALUE)) != 0 )
    {   LM_ERR("Error in bdblib_valtochar \n");
        ret = -9;
        goto error;
    }

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;
    data.size = dlen;

    if ((ret = db->put(db, NULL, &key, &data, 0)) == 0)
    {
        bdblib_log(JLOG_INSERT, _tp, dbuf, dlen);

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("INSERT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   data.size
               , (char *)data.data);
#endif
    }
    else
    {   /*Berkeley DB error handler*/
        switch(ret)
        {
        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        /* The operation was selected to resolve a deadlock. */

        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->put error: %s.\n", db_strerror(ret));
            bdblib_recover(_tp, ret);
            goto error;
        }
    }

error:
    if(lkey)
        pkg_free(lkey);

    return ret;

}
Пример #6
0
/*
 * Query table for specified rows
 * _con: 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* _con, 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)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    u_int32_t i, len, ret;
    int klen=MAX_ROW_SIZE;
    int *lkey=NULL, *lres=NULL;
    str s;
    DBT key, data;
    DB *db;
    DBC *dbcp;

    if ((!_con) || (!_r) || !CON_TABLE(_con))
    {
#ifdef BDB_EXTRA_DEBUG
        LM_ERR("Invalid parameter value\n");
#endif
        return -1;
    }
    *_r = NULL;

    /*check if underlying DB file has changed inode */
    if(auto_reload)
        bdb_check_reload(_con);

    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -1;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -1;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("QUERY in %.*s\n", _tp->name.len, _tp->name.s);

    if (_o)  LM_DBG("DONT-CARE : _o: order by the specified column \n");
    if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
#endif

    db = _tp->db;
    if(!db) return -1;

    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, MAX_ROW_SIZE);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* if _c is NULL and _nc is zero, you will get all table
       columns in the result
    */
    if (_c)
    {   lres = bdb_get_colmap(_tbc->dtp, _c, _nc);
        if(!lres)
        {   ret = -1;
            goto error;
        }
    }

    if(_k)
    {   lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }
    else
    {
        DB_HASH_STAT st;
        memset(&st, 0, sizeof(DB_HASH_STAT));
        i =0 ;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("SELECT * FROM %.*s\n", _tp->name.len, _tp->name.s);
#endif

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*count the number of records*/
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {   if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
            i++;
        }

        dbcp->c_close(dbcp);
        ret=0;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("%i = SELECT COUNT(*) FROM %.*s\n", i, _tp->name.len, _tp->name.s);
#endif

        *_r = db_new_result();
        if (!*_r)
        {   LM_ERR("no memory left for result \n");
            ret = -2;
            goto error;
        }

        if(i == 0)
        {
            /*return empty table*/
            RES_ROW_N(*_r) = 0;
            BDB_CON_RESULT(_con) = *_r;
            return 0;
        }

        /*allocate N rows in the result*/
        RES_ROW_N(*_r) = i;
        len  = sizeof(db_row_t) * i;
        RES_ROWS(*_r) = (db_row_t*)pkg_malloc( len );
        memset(RES_ROWS(*_r), 0, len);

        /*fill in the column part of db_res_t (metadata) */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*convert each record into a row in the result*/
        i =0 ;
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\nDATA: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data
                   , (int)   data.size
                   , (char *)data.data);
#endif

            /*fill in the row part of db_res_t */
            if ((ret=bdb_append_row( *_r, dbuf, lres, i)) < 0)
            {   LM_ERR("Error while converting row\n");
                goto error;
            }
            i++;
        }

        dbcp->c_close(dbcp);
        BDB_CON_RESULT(_con) = *_r;
        return 0;
    }

    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("error in query key \n");
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /*create an empty db_res_t which gets returned even if no result*/
    *_r = db_new_result();
    if (!*_r)
    {   LM_ERR("no memory left for result \n");
        ret = -2;
        goto error;
    }
    RES_ROW_N(*_r) = 0;
    BDB_CON_RESULT(_con) = *_r;

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("SELECT  KEY: [%.*s]\n"
           , (int)   key.size
           , (char *)key.data );
#endif

    /*query Berkely DB*/
    if ((ret = db->get(db, NULL, &key, &data, 0)) == 0)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("RESULT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   data.size
               , (char *)data.data);
#endif

        /*fill in the col part of db_res_t */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }
        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( *_r, dbuf, lres)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

    }
    else
    {
        /*Berkeley DB error handler*/
        switch(ret)
        {

        case DB_NOTFOUND:

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("NO RESULT for QUERY \n");
#endif

            ret=0;
            break;
        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        // The operation was selected to resolve a deadlock.
        case DB_SECONDARY_BAD:
        // A secondary index references a nonexistent primary key.
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
            bdblib_recover(_tp,ret);
            goto error;
        }
    }

    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);

    return ret;

error:
    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);
    if(*_r)
        bdb_free_result(*_r);
    *_r = NULL;

    return ret;
}
Пример #7
0
/*
 * Attempts to reload a Berkeley database; reloads when the inode changes
 */
void bdb_check_reload(db_con_t* _con)
{

    str s;
    char* p;
    int rc, len;
    struct stat st;
    database_p db;
    char n[MAX_ROW_SIZE];
    char t[MAX_TABLENAME_SIZE];
    table_p tp = NULL;
    tbl_cache_p tbc = NULL;

    p=n;
    rc = len = 0;

    /*get dbenv name*/
    db = BDB_CON_CONNECTION(_con);
    if(!db->dbenv)	return;
    s.s = db->name.s;
    s.len = db->name.len;
    len+=s.len;

    if(len > MAX_ROW_SIZE)
    {   LM_ERR("dbenv name too long \n");
        return;
    }

    strncpy(p, s.s, s.len);
    p+=s.len;

    len++;
    if(len > MAX_ROW_SIZE)
    {   LM_ERR("dbenv name too long \n");
        return;
    }

    /*append slash */
    *p = '/';
    p++;

    /*get table name*/
    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));
    len+=s.len;

    if((len>MAX_ROW_SIZE) || (s.len > MAX_TABLENAME_SIZE) )
    {   LM_ERR("table name too long \n");
        return;
    }

    strncpy(t, s.s, s.len);
    t[s.len] = 0;

    strncpy(p, s.s, s.len);
    p+=s.len;
    *p=0;

    if( (tbc = bdblib_get_table(db, &s)) == NULL)
        return;

    if( (tp = tbc->dtp) == NULL)
        return;

    LM_DBG("stat file [%.*s]\n", len, n);
    rc = stat(n, &st);
    if(!rc)
    {   if((tp->ino!=0) && (st.st_ino != tp->ino))
            bdb_reload(t); /*file changed on disk*/

        tp->ino = st.st_ino;
    }

}
Пример #8
0
/*
 * Updates a row in table
 * Limitation: only knows how to update a single row
 *
 * _con: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _uk: update keys; cols that need to be updated
 * _uv: update values; col values that need to be commited
 * _un: number of rows to update
 */
int bdb_update(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
               db_key_t* _uk, db_val_t* _uv, int _n, int _un)
{
    str s;
    char *c, *t;
    int ret, i, qcol, len, sum;
    int *lkey=NULL;
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char qbuf[MAX_ROW_SIZE];
    char ubuf[MAX_ROW_SIZE];
    DBT key, qdata, udata;
    DB *db;

    sum = ret = i = qcol = len = 0;

    if (!_con || !CON_TABLE(_con) || !_uk || !_uv || _un <= 0)
        return -1;

    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), &s);
    if(!_tbc)
    {   LM_ERR("table does not exist\n");
        return -1;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_ERR("table not loaded\n");
        return -1;
    }

    db = _tp->db;
    if(!db)
    {   LM_ERR("DB null ptr\n");
        return -1;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("UPDATE in %.*s\n", _tp->name.len, _tp->name.s);
    if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
#endif

    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, MAX_ROW_SIZE);
    memset(&qdata, 0, sizeof(DBT));
    memset(qbuf, 0, MAX_ROW_SIZE);

    qdata.data = qbuf;
    qdata.ulen = MAX_ROW_SIZE;
    qdata.flags = DB_DBT_USERMEM;

    if(_k)
    {   lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
        if(!lkey) return -4;
    }
    else
    {
        LM_ERR("Null keys in update _k=0 \n");
        return -1;
    }

    len = MAX_ROW_SIZE;

    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &len, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in query key \n");
        goto cleanup;
    }

    if(lkey) pkg_free(lkey);

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = len;

    /*stage 1: QUERY Berkely DB*/
    if ((ret = db->get(db, NULL, &key, &qdata, 0)) == 0)
    {

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("RESULT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   qdata.size
               , (char *)qdata.data);
#endif

    }
    else
    {   goto db_error;
    }

    /* stage 2: UPDATE row with new values */

    /* map the provided keys to those in our schema */
    lkey = bdb_get_colmap(_tbc->dtp, _uk, _un);
    if(!lkey) return -4;

    /* build a new row for update data (udata) */
    memset(&udata, 0, sizeof(DBT));
    memset(ubuf, 0, MAX_ROW_SIZE);

    /* loop over each column of the qbuf and copy it to our new ubuf unless
       its a field that needs to update
    */
    c = strtok(qbuf, DELIM);
    t = ubuf;
    while( c!=NULL)
    {   char* delim = DELIM;
        int k;

        len = strlen(c);
        sum+=len;

        if(sum > MAX_ROW_SIZE)
        {   LM_ERR("value too long for string \n");
            ret = -3;
            goto cleanup;
        }

        for(i=0; i<_un; i++)
        {
            k = lkey[i];
            if (qcol == k)
            {   /* update this col */
                int j = MAX_ROW_SIZE - sum;
                if( bdb_val2str( &_uv[i], t, &j) )
                {   LM_ERR("value too long for string \n");
                    ret = -3;
                    goto cleanup;
                }

                goto next;
            }

        }

        /* copy original column to the new column */
        strncpy(t, c, len);

next:
        t+=len;

        /* append DELIM */
        sum += DELIM_LEN;
        if(sum > MAX_ROW_SIZE)
        {   LM_ERR("value too long for string \n");
            ret = -3;
            goto cleanup;
        }

        strncpy(t, delim, DELIM_LEN);
        t += DELIM_LEN;

        c = strtok(NULL, DELIM);
        qcol++;
    }

    ubuf[sum]  = '0';
    udata.data = ubuf;
    udata.ulen  = MAX_ROW_SIZE;
    udata.flags = DB_DBT_USERMEM;
    udata.size  = sum;

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("MODIFIED Data\nKEY:  [%.*s]\nDATA: [%.*s]\n"
           , (int)   key.size
           , (char *)key.data
           , (int)   udata.size
           , (char *)udata.data);
#endif
    /* stage 3: DELETE old row using key*/
    if ((ret = db->del(db, NULL, &key, 0)) == 0)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("DELETED ROW\nKEY: %s \n", (char *)key.data);
#endif
    }
    else
    {   goto db_error;
    }

    /* stage 4: INSERT new row with key*/
    if ((ret = db->put(db, NULL, &key, &udata, 0)) == 0)
    {
        bdblib_log(JLOG_UPDATE, _tp, ubuf, sum);
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("INSERT \nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   udata.size
               , (char *)udata.data);
#endif
    }
    else
    {   goto db_error;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("UPDATE COMPLETE \n");
#endif


cleanup:
    if(lkey)
        pkg_free(lkey);

    return ret;


db_error:

    /*Berkeley DB error handler*/
    switch(ret)
    {

    case DB_NOTFOUND:

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("NO RESULT \n");
#endif
        return -1;

    /* The following are all critical/fatal */
    case DB_LOCK_DEADLOCK:
    /* The operation was selected to resolve a deadlock. */
    case DB_SECONDARY_BAD:
    /* A secondary index references a nonexistent primary key.*/
    case DB_RUNRECOVERY:
    default:
        LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
        bdblib_recover(_tp,ret);
    }

    if(lkey)
        pkg_free(lkey);

    return ret;
}