dbt_lib.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dbt_lib.c 5196 2008-11-13 12:46:34Z henningw $
00003  *
00004  * DBText library
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  * 
00024  * History:
00025  * --------
00026  * 2003-01-30 created by Daniel
00027  * 
00028  */
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <time.h>
00033 #include <sys/types.h>
00034 #include <dirent.h>
00035 
00036 #include "../../mem/shm_mem.h"
00037 #include "../../mem/mem.h"
00038 #include "../../dprint.h"
00039 
00040 #include "dbt_util.h"
00041 #include "dbt_lib.h"
00042 
00043 static dbt_cache_p *_dbt_cachedb = NULL;
00044 static gen_lock_t *_dbt_cachesem = NULL;
00045 
00046 static dbt_tbl_cachel_p _dbt_cachetbl = NULL;
00047 
00048 #define DBT_CACHETBL_SIZE  16
00049 
00050 /**
00051  *
00052  */
00053 int dbt_init_cache(void)
00054 {
00055    int i, j;
00056    if(!_dbt_cachesem)
00057    {
00058    /* init locks */
00059       _dbt_cachesem = lock_alloc();
00060       if(!_dbt_cachesem)
00061       {
00062          LM_CRIT("could not alloc a lock\n");
00063          return -1;
00064       }
00065       if (lock_init(_dbt_cachesem)==0)
00066       {
00067          LM_CRIT("could not initialize a lock\n");
00068          lock_dealloc(_dbt_cachesem);
00069          return -1;
00070       }
00071    }
00072    /* init pointer to caches list */
00073    if (!_dbt_cachedb) {
00074       _dbt_cachedb = shm_malloc( sizeof(dbt_cache_p) );
00075       if (!_dbt_cachedb) {
00076          LM_CRIT("no enough shm mem\n");
00077          lock_dealloc(_dbt_cachesem);
00078          return -1;
00079       }
00080       *_dbt_cachedb = NULL;
00081    }
00082    /* init tables' hash table */
00083    if (!_dbt_cachetbl) {
00084       _dbt_cachetbl 
00085          = (dbt_tbl_cachel_p)shm_malloc(DBT_CACHETBL_SIZE*
00086                sizeof(dbt_tbl_cachel_t));
00087       if(_dbt_cachetbl==NULL)
00088       {
00089          LM_CRIT("no enough shm mem\n");
00090          lock_dealloc(_dbt_cachesem);
00091          shm_free(_dbt_cachedb);
00092          return -1;
00093       }
00094       memset(_dbt_cachetbl, 0, DBT_CACHETBL_SIZE*sizeof(dbt_tbl_cachel_t));
00095       for(i=0; i<DBT_CACHETBL_SIZE; i++)
00096       {
00097          if (lock_init(&_dbt_cachetbl[i].sem)==0)
00098          {
00099             LM_CRIT("cannot init tables' sem's\n");
00100             for(j=i-1; j>=0; j--)
00101                lock_destroy(&_dbt_cachetbl[j].sem);
00102             lock_dealloc(_dbt_cachesem);
00103             shm_free(_dbt_cachedb);
00104             return -1;
00105          }
00106       }
00107    }
00108 
00109    
00110    return 0;
00111 }
00112 
00113 /**
00114  *
00115  */
00116 dbt_cache_p dbt_cache_get_db(str *_s)
00117 {
00118    dbt_cache_p _dcache=NULL;;
00119    if(!_dbt_cachesem || !_dbt_cachedb)
00120    {
00121       LM_ERR("dbtext cache is not initialized! Check if you loaded"
00122             " dbtext before any other module that uses it\n");
00123       return NULL;
00124    }
00125    if(!_s || !_s->s || _s->len<=0)
00126       return NULL;
00127 
00128    LM_DBG("looking for db %.*s!\n",_s->len,_s->s);
00129 
00130    lock_get(_dbt_cachesem);
00131    
00132    _dcache = *_dbt_cachedb;
00133    while(_dcache)
00134    {
00135       if(_dcache->name.len==_s->len 
00136             && !strncasecmp(_dcache->name.s, _s->s, _s->len))
00137       {
00138          LM_DBG("db already cached!\n");
00139          goto done;
00140       }
00141       
00142       _dcache = _dcache->next;
00143    }
00144    if(!dbt_is_database(_s))
00145    {
00146       LM_ERR("database [%.*s] does not exists!\n", _s->len, _s->s);
00147       goto done;
00148    }
00149    LM_DBG("new db!\n");
00150    
00151    _dcache = (dbt_cache_p)shm_malloc(sizeof(dbt_cache_t));
00152    if(!_dcache)
00153    {
00154       LM_ERR(" no shm memory for dbt_cache_t.\n");
00155       goto done;
00156    }
00157    memset(_dcache, 0, sizeof(dbt_cache_t));
00158    
00159    _dcache->name.s = (char*)shm_malloc((_s->len+1)*sizeof(char));
00160    if(!_dcache->name.s)
00161    {
00162       LM_ERR(" no shm memory for s!!\n");
00163       shm_free(_dcache);
00164       _dcache = NULL;
00165       goto done;
00166    }
00167    
00168    memcpy(_dcache->name.s, _s->s, _s->len);
00169    _dcache->name.s[_s->len] = '\0';
00170    _dcache->name.len = _s->len;
00171    
00172    if(*_dbt_cachedb)
00173       _dcache->next = *_dbt_cachedb;
00174 
00175    *_dbt_cachedb = _dcache;
00176 
00177 done:
00178    lock_release(_dbt_cachesem);
00179    return _dcache;
00180 }
00181 
00182 /**
00183  *
00184  */
00185 int dbt_cache_check_db(str *_s)
00186 {
00187    dbt_cache_p _dcache=NULL;;
00188    if(!_dbt_cachesem || !(*_dbt_cachedb)
00189          || !_s || !_s->s || _s->len<=0)
00190       return -1;
00191    
00192    lock_get(_dbt_cachesem);
00193    
00194    _dcache = *_dbt_cachedb;
00195    while(_dcache)
00196    {
00197       if(_dcache->name.len == _s->len &&
00198          strncasecmp(_dcache->name.s, _s->s, _s->len))
00199       {
00200          lock_release(_dbt_cachesem);
00201          return 0;
00202       }
00203       _dcache = _dcache->next;
00204    }
00205    
00206    lock_release(_dbt_cachesem);
00207    return -1;
00208 }
00209 
00210 /**
00211  *
00212  */
00213 int dbt_db_del_table(dbt_cache_p _dc, const str *_s, int sync)
00214 {
00215    dbt_table_p _tbc = NULL;
00216    int hash;
00217    int hashidx;
00218    if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0)
00219       return -1;
00220 
00221    hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE);
00222    hashidx = hash % DBT_CACHETBL_SIZE;
00223    
00224    if(sync)
00225       lock_get(&_dbt_cachetbl[hashidx].sem);
00226 
00227    _tbc = _dbt_cachetbl[hashidx].dtp;
00228 
00229    while(_tbc)
00230    {
00231       if(_tbc->hash==hash && _tbc->dbname.len == _dc->name.len
00232             && _tbc->name.len == _s->len
00233             && !strncasecmp(_tbc->dbname.s, _dc->name.s, _dc->name.len)
00234             && !strncasecmp(_tbc->name.s, _s->s, _s->len))
00235       {
00236          if(_tbc->prev)
00237             (_tbc->prev)->next = _tbc->next;
00238          else
00239             _dbt_cachetbl[hashidx].dtp = _tbc->next;
00240    
00241          if(_tbc->next)
00242             (_tbc->next)->prev = _tbc->prev;
00243          break;
00244       }
00245       _tbc = _tbc->next;
00246    }
00247 
00248    if(sync)
00249       lock_release(&_dbt_cachetbl[hashidx].sem);
00250 
00251    dbt_table_free(_tbc);
00252    
00253    return 0;
00254 }
00255 
00256 /**
00257  *
00258  */
00259 dbt_table_p dbt_db_get_table(dbt_cache_p _dc, const str *_s)
00260 {
00261    dbt_table_p _tbc = NULL;
00262    int hash;
00263    int hashidx;
00264 
00265    if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0) {
00266       LM_ERR("invalid parameter");
00267       return NULL;
00268    }
00269 
00270    hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE);
00271    hashidx = hash % DBT_CACHETBL_SIZE;
00272       
00273    lock_get(&_dbt_cachetbl[hashidx].sem);
00274 
00275    _tbc = _dbt_cachetbl[hashidx].dtp;
00276 
00277    while(_tbc)
00278    {
00279       if(_tbc->hash==hash && _tbc->dbname.len == _dc->name.len
00280             && _tbc->name.len == _s->len
00281             && !strncasecmp(_tbc->dbname.s, _dc->name.s, _dc->name.len)
00282             && !strncasecmp(_tbc->name.s, _s->s, _s->len))
00283       {
00284          /* found - if cache mode or no-change, return */
00285          if(db_mode==0 || dbt_check_mtime(_s, &(_dc->name), &(_tbc->mt))!=1)
00286          {
00287             LM_DBG("cache or mtime succeeded for [%.*s]\n",
00288                   _tbc->name.len, _tbc->name.s);
00289             return _tbc;
00290          }
00291          break;
00292       }
00293       _tbc = _tbc->next;
00294    }
00295    
00296    /* new table */
00297    if(_tbc) /* free old one */
00298    {
00299       dbt_db_del_table(_dc, _s, 0);
00300    }
00301 
00302    _tbc = dbt_load_file(_s, &(_dc->name));
00303 
00304    if(!_tbc)
00305    {
00306       LM_ERR("could not load database from file [%.*s]", _s->len, _s->s);
00307       lock_release(&_dbt_cachetbl[hashidx].sem);
00308       return NULL;
00309    }
00310 
00311    _tbc->hash = hash;
00312    _tbc->next = _dbt_cachetbl[hashidx].dtp;
00313    if(_dbt_cachetbl[hashidx].dtp)
00314       _dbt_cachetbl[hashidx].dtp->prev = _tbc;
00315    
00316    _dbt_cachetbl[hashidx].dtp = _tbc;
00317 
00318    /* table is locked */
00319    return _tbc;
00320 }
00321 
00322 int dbt_release_table(dbt_cache_p _dc, const str *_s)
00323 {
00324    int hash;
00325    int hashidx;
00326 
00327    if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0)
00328       return -1;
00329 
00330    hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE);
00331    hashidx = hash % DBT_CACHETBL_SIZE;
00332       
00333    lock_release(&_dbt_cachetbl[hashidx].sem);
00334 
00335    return 0;
00336 }
00337 
00338 /**
00339  *
00340  */
00341 int dbt_cache_destroy(void)
00342 {
00343    int i;
00344    dbt_cache_p _dc=NULL, _dc0=NULL;
00345    dbt_table_p _tbc = NULL;
00346    dbt_table_p _tbc0 = NULL;
00347    
00348    if(!_dbt_cachesem)
00349       return -1;
00350    
00351    lock_get(_dbt_cachesem);
00352    if(   _dbt_cachedb!=NULL )
00353    {
00354       _dc = *_dbt_cachedb;
00355       while(_dc)
00356       {
00357          _dc0 = _dc;
00358          _dc = _dc->next;
00359          shm_free(_dc0->name.s);
00360          shm_free(_dc0);
00361       }
00362       shm_free(_dbt_cachedb);
00363    }
00364    lock_destroy(_dbt_cachesem);
00365    lock_dealloc(_dbt_cachesem);
00366 
00367    /* destroy tables' hash table*/
00368    if(_dbt_cachetbl==0)
00369       return 0;
00370    for(i=0; i<DBT_CACHETBL_SIZE; i++)
00371    {
00372       lock_destroy(&_dbt_cachetbl[i].sem);
00373       _tbc = _dbt_cachetbl[i].dtp;
00374       while(_tbc)
00375       {
00376          _tbc0 = _tbc;
00377          _tbc = _tbc->next;
00378          dbt_table_free(_tbc0);
00379       }
00380    }
00381    shm_free(_dbt_cachetbl);
00382    return 0;
00383 }
00384 
00385 /**
00386  *
00387  */
00388 int dbt_cache_print(int _f)
00389 {
00390    int i;
00391    dbt_table_p _tbc;
00392 
00393    if(!_dbt_cachetbl)
00394       return -1;
00395    
00396    for(i=0; i< DBT_CACHETBL_SIZE; i++)
00397    {
00398       lock_get(&_dbt_cachetbl[i].sem);
00399       _tbc = _dbt_cachetbl[i].dtp;
00400       while(_tbc)
00401       {
00402          if(_f)
00403             fprintf(stdout, "\n--- Database [%.*s]\n", _tbc->dbname.len,
00404                         _tbc->dbname.s);
00405          if(_f)
00406          {
00407             fprintf(stdout, "\n----- Table [%.*s]\n",
00408                   _tbc->name.len, _tbc->name.s);
00409             fprintf(stdout, "-------  LA=<%d> FL=<%x> AC=<%d>"
00410                   " AV=<%d>\n", _tbc->mark, _tbc->flag,
00411                   _tbc->auto_col, _tbc->auto_val);
00412             dbt_print_table(_tbc, NULL);
00413          } else {
00414             if(_tbc->flag & DBT_TBFL_MODI)
00415             {
00416                dbt_print_table(_tbc, &(_tbc->dbname));
00417                dbt_table_update_flags(_tbc,DBT_TBFL_MODI, DBT_FL_UNSET, 0);
00418             }
00419          }
00420          _tbc = _tbc->next;
00421       }
00422       lock_release(&_dbt_cachetbl[i].sem);
00423    }
00424    
00425    return 0;
00426 }
00427 
00428 int dbt_is_neq_type(db_type_t _t0, db_type_t _t1)
00429 {
00430    // LM_DBG("t0=%d t1=%d!\n", _t0, _t1);
00431    if(_t0 == _t1)
00432       return 0;
00433    switch(_t1)
00434    {
00435       case DB_INT:
00436          if(_t0==DB_DATETIME || _t0==DB_BITMAP)
00437             return 0;
00438 
00439       case DB_BIGINT:
00440          LM_ERR("BIGINT not supported");
00441          return 0;
00442 
00443       case DB_DATETIME:
00444          if(_t0==DB_INT)
00445             return 0;
00446          if(_t0==DB_BITMAP)
00447             return 0;
00448       case DB_DOUBLE:
00449          break;
00450       case DB_STRING:
00451          if(_t0==DB_STR)
00452             return 0;
00453       case DB_STR:
00454          if(_t0==DB_STRING || _t0==DB_BLOB)
00455             return 0;
00456       case DB_BLOB:
00457          if(_t0==DB_STR)
00458             return 0;
00459       case DB_BITMAP:
00460          if (_t0==DB_INT)
00461             return 0;
00462    }
00463    return 1;
00464 }
00465 

Generated on Tue May 22 14:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6