modules_k/usrloc/udomain.c

Go to the documentation of this file.
00001 /*
00002  * $Id$ 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * ---------
00024  * 2003-03-11 changed to the new locking scheme: locking.h (andrei)
00025  * 2003-03-12 added replication mark and zombie state (nils)
00026  * 2004-06-07 updated to the new DB api (andrei)
00027  * 2004-08-23  hash function changed to process characters as unsigned
00028  *             -> no negative results occur (jku)
00029  */
00030 
00038 #include "udomain.h"
00039 #include <string.h>
00040 #include "../../parser/parse_methods.h"
00041 #include "../../mem/shm_mem.h"
00042 #include "../../dprint.h"
00043 #include "../../lib/srdb1/db.h"
00044 #include "../../socket_info.h"
00045 #include "../../ut.h"
00046 #include "../../hashes.h"
00047 #include "ul_mod.h"            /* usrloc module parameters */
00048 #include "usrloc.h"
00049 #include "utime.h"
00050 #include "usrloc.h"
00051 
00052 #ifdef STATISTICS
00053 static char *build_stat_name( str* domain, char *var_name)
00054 {
00055         int n;
00056         char *s;
00057         char *p;
00058 
00059         n = domain->len + 1 + strlen(var_name) + 1;
00060         s = (char*)shm_malloc( n );
00061         if (s==0) {
00062                 LM_ERR("no more shm mem\n");
00063                 return 0;
00064         }
00065         memcpy( s, domain->s, domain->len);
00066         p = s + domain->len;
00067         *(p++) = '-';
00068         memcpy( p , var_name, strlen(var_name));
00069         p += strlen(var_name);
00070         *(p++) = 0;
00071         return s;
00072 }
00073 #endif
00074 
00075 
00084 int new_udomain(str* _n, int _s, udomain_t** _d)
00085 {
00086         int i;
00087 #ifdef STATISTICS
00088         char *name;
00089 #endif
00090         
00091         /* Must be always in shared memory, since
00092          * the cache is accessed from timer which
00093          * lives in a separate process
00094          */
00095         *_d = (udomain_t*)shm_malloc(sizeof(udomain_t));
00096         if (!(*_d)) {
00097                 LM_ERR("new_udomain(): No memory left\n");
00098                 goto error0;
00099         }
00100         memset(*_d, 0, sizeof(udomain_t));
00101         
00102         (*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * _s);
00103         if (!(*_d)->table) {
00104                 LM_ERR("no memory left 2\n");
00105                 goto error1;
00106         }
00107 
00108         (*_d)->name = _n;
00109         
00110         for(i = 0; i < _s; i++) {
00111                 init_slot(*_d, &((*_d)->table[i]), i);
00112         }
00113 
00114         (*_d)->size = _s;
00115 
00116 #ifdef STATISTICS
00117         /* register the statistics */
00118         if ( (name=build_stat_name(_n,"users"))==0 || register_stat("usrloc",
00119         name, &(*_d)->users, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
00120                 LM_ERR("failed to add stat variable\n");
00121                 goto error2;
00122         }
00123         if ( (name=build_stat_name(_n,"contacts"))==0 || register_stat("usrloc",
00124         name, &(*_d)->contacts, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
00125                 LM_ERR("failed to add stat variable\n");
00126                 goto error2;
00127         }
00128         if ( (name=build_stat_name(_n,"expires"))==0 || register_stat("usrloc",
00129         name, &(*_d)->expires, STAT_SHM_NAME)!=0 ) {
00130                 LM_ERR("failed to add stat variable\n");
00131                 goto error2;
00132         }
00133 #endif
00134 
00135         return 0;
00136 #ifdef STATISTICS
00137 error2:
00138         shm_free((*_d)->table);
00139 #endif
00140 error1:
00141         shm_free(*_d);
00142 error0:
00143         return -1;
00144 }
00145 
00146 
00151 void free_udomain(udomain_t* _d)
00152 {
00153         int i;
00154         
00155         if (_d->table) {
00156                 for(i = 0; i < _d->size; i++) {
00157                         lock_ulslot(_d, i);
00158                         deinit_slot(_d->table + i);
00159                         unlock_ulslot(_d, i);
00160                 }
00161                 shm_free(_d->table);
00162         }
00163         shm_free(_d);
00164 }
00165 
00166 
00173 static inline void get_static_urecord(udomain_t* _d, str* _aor,
00174                                                                                                                 struct urecord** _r)
00175 {
00176         static struct urecord r;
00177 
00178         memset( &r, 0, sizeof(struct urecord) );
00179         r.aor = *_aor;
00180         r.aorhash = ul_get_aorhash(_aor);
00181         r.domain = _d->name;
00182         *_r = &r;
00183 }
00184 
00185 
00189 void print_udomain(FILE* _f, udomain_t* _d)
00190 {
00191         int i;
00192         int max=0, slot=0, n=0;
00193         struct urecord* r;
00194         fprintf(_f, "---Domain---\n");
00195         fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
00196         fprintf(_f, "size : %d\n", _d->size);
00197         fprintf(_f, "table: %p\n", _d->table);
00198         /*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/
00199         fprintf(_f, "\n");
00200         for(i=0; i<_d->size; i++)
00201         {
00202                 r = _d->table[i].first;
00203                 n += _d->table[i].n;
00204                 if(max<_d->table[i].n){
00205                         max= _d->table[i].n;
00206                         slot = i;
00207                 }
00208                 while(r) {
00209                         print_urecord(_f, r);
00210                         r = r->next;
00211                 }
00212         }
00213         fprintf(_f, "\nMax slot: %d (%d/%d)\n", max, slot, n);
00214         fprintf(_f, "\n---/Domain---\n");
00215 }
00216 
00217 
00228 static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
00229 {
00230         static ucontact_info_t ci;
00231         static str callid, ua, received, host, path;
00232         int port, proto;
00233         char *p;
00234 
00235         memset( &ci, 0, sizeof(ucontact_info_t));
00236 
00237         contact->s = (char*)VAL_STRING(vals);
00238         if (VAL_NULL(vals) || contact->s==0 || contact->s[0]==0) {
00239                 LM_CRIT("bad contact\n");
00240                 return 0;
00241         }
00242         contact->len = strlen(contact->s);
00243 
00244         if (VAL_NULL(vals+1)) {
00245                 LM_CRIT("empty expire\n");
00246                 return 0;
00247         }
00248         ci.expires = VAL_TIME(vals+1);
00249 
00250         if (VAL_NULL(vals+2)) {
00251                 LM_CRIT("empty q\n");
00252                 return 0;
00253         }
00254         ci.q = double2q(VAL_DOUBLE(vals+2));
00255 
00256         if (VAL_NULL(vals+4)) {
00257                 LM_CRIT("empty cseq_nr\n");
00258                 return 0;
00259         }
00260         ci.cseq = VAL_INT(vals+4);
00261 
00262         callid.s = (char*)VAL_STRING(vals+3);
00263         if (VAL_NULL(vals+3) || !callid.s || !callid.s[0]) {
00264                 LM_CRIT("bad callid\n");
00265                 return 0;
00266         }
00267         callid.len  = strlen(callid.s);
00268         ci.callid = &callid;
00269 
00270         if (VAL_NULL(vals+5)) {
00271                 LM_CRIT("empty flag\n");
00272                 return 0;
00273         }
00274         ci.flags  = VAL_BITMAP(vals+5);
00275 
00276         if (VAL_NULL(vals+6)) {
00277                 LM_CRIT("empty cflag\n");
00278                 return 0;
00279         }
00280         ci.cflags  = VAL_BITMAP(vals+6);
00281 
00282         ua.s  = (char*)VAL_STRING(vals+7);
00283         if (VAL_NULL(vals+7) || !ua.s || !ua.s[0]) {
00284                 ua.s = 0;
00285                 ua.len = 0;
00286         } else {
00287                 ua.len = strlen(ua.s);
00288         }
00289         ci.user_agent = &ua;
00290 
00291         received.s  = (char*)VAL_STRING(vals+8);
00292         if (VAL_NULL(vals+8) || !received.s || !received.s[0]) {
00293                 received.len = 0;
00294                 received.s = 0;
00295         } else {
00296                 received.len = strlen(received.s);
00297         }
00298         ci.received = received;
00299         
00300         path.s  = (char*)VAL_STRING(vals+9);
00301                 if (VAL_NULL(vals+9) || !path.s || !path.s[0]) {
00302                         path.len = 0;
00303                         path.s = 0;
00304                 } else {
00305                         path.len = strlen(path.s);
00306                 }
00307         ci.path= &path;
00308 
00309         /* socket name */
00310         p  = (char*)VAL_STRING(vals+10);
00311         if (VAL_NULL(vals+10) || p==0 || p[0]==0){
00312                 ci.sock = 0;
00313         } else {
00314                 if (parse_phostport( p, &host.s, &host.len, 
00315                 &port, &proto)!=0) {
00316                         LM_ERR("bad socket <%s>\n", p);
00317                         return 0;
00318                 }
00319                 ci.sock = grep_sock_info( &host, (unsigned short)port, proto);
00320                 if (ci.sock==0) {
00321                         LM_WARN("non-local socket <%s>...ignoring\n", p);
00322                 }
00323         }
00324 
00325         /* supported methods */
00326         if (VAL_NULL(vals+11)) {
00327                 ci.methods = ALL_METHODS;
00328         } else {
00329                 ci.methods = VAL_BITMAP(vals+11);
00330         }
00331 
00332         /* last modified time */
00333         if (!VAL_NULL(vals+12)) {
00334                 ci.last_modified = VAL_TIME(vals+12);
00335         }
00336 
00337         /* record internal uid */
00338         if (!VAL_NULL(vals+13)) {
00339                 ci.ruid.s = (char*)VAL_STRING(vals+13);
00340                 ci.ruid.len = strlen(ci.ruid.s);
00341         }
00342 
00343         /* sip instance */
00344         if (!VAL_NULL(vals+14)) {
00345                 ci.instance.s = (char*)VAL_STRING(vals+14);
00346                 ci.instance.len = strlen(ci.instance.s);
00347         }
00348 
00349         /* reg-id */
00350         if (!VAL_NULL(vals+15)) {
00351                 ci.reg_id = VAL_UINT(vals+15);
00352         }
00353 
00354         return &ci;
00355 }
00356 
00357 
00367 int preload_udomain(db1_con_t* _c, udomain_t* _d)
00368 {
00369         char uri[MAX_URI_SIZE];
00370         ucontact_info_t *ci;
00371         db_row_t *row;
00372         db_key_t columns[18];
00373         db1_res_t* res = NULL;
00374         str user, contact;
00375         char* domain;
00376         int i;
00377         int n;
00378 
00379         urecord_t* r;
00380         ucontact_t* c;
00381 
00382         columns[0] = &user_col;
00383         columns[1] = &contact_col;
00384         columns[2] = &expires_col;
00385         columns[3] = &q_col;
00386         columns[4] = &callid_col;
00387         columns[5] = &cseq_col;
00388         columns[6] = &flags_col;
00389         columns[7] = &cflags_col;
00390         columns[8] = &user_agent_col;
00391         columns[9] = &received_col;
00392         columns[10] = &path_col;
00393         columns[11] = &sock_col;
00394         columns[12] = &methods_col;
00395         columns[13] = &last_mod_col;
00396         columns[14] = &ruid_col;
00397         columns[15] = &instance_col;
00398         columns[16] = &reg_id_col;
00399         columns[17] = &domain_col;
00400 
00401         if (ul_dbf.use_table(_c, _d->name) < 0) {
00402                 LM_ERR("sql use_table failed\n");
00403                 return -1;
00404         }
00405 
00406 #ifdef EXTRA_DEBUG
00407         LM_NOTICE("load start time [%d]\n", (int)time(NULL));
00408 #endif
00409 
00410         if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
00411                 if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
00412                 0) < 0) {
00413                         LM_ERR("db_query (1) failed\n");
00414                         return -1;
00415                 }
00416                 if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
00417                         LM_ERR("fetching rows failed\n");
00418                         return -1;
00419                 }
00420         } else {
00421                 if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
00422                 &res) < 0) {
00423                         LM_ERR("db_query failed\n");
00424                         return -1;
00425                 }
00426         }
00427 
00428         if (RES_ROW_N(res) == 0) {
00429                 LM_DBG("table is empty\n");
00430                 ul_dbf.free_result(_c, res);
00431                 return 0;
00432         }
00433 
00434 
00435         n = 0;
00436         do {
00437                 LM_DBG("loading records - cycle [%d]\n", ++n);
00438                 for(i = 0; i < RES_ROW_N(res); i++) {
00439                         row = RES_ROWS(res) + i;
00440 
00441                         user.s = (char*)VAL_STRING(ROW_VALUES(row));
00442                         if (VAL_NULL(ROW_VALUES(row)) || user.s==0 || user.s[0]==0) {
00443                                 LM_CRIT("empty username record in table %s...skipping\n",
00444                                                 _d->name->s);
00445                                 continue;
00446                         }
00447                         user.len = strlen(user.s);
00448 
00449                         ci = dbrow2info( ROW_VALUES(row)+1, &contact);
00450                         if (ci==0) {
00451                                 LM_ERR("sipping record for %.*s in table %s\n",
00452                                                 user.len, user.s, _d->name->s);
00453                                 continue;
00454                         }
00455 
00456                         if (use_domain) {
00457                                 domain = (char*)VAL_STRING(ROW_VALUES(row) + 17);
00458                                 if (VAL_NULL(ROW_VALUES(row)+17) || domain==0 || domain[0]==0){
00459                                         LM_CRIT("empty domain record for user %.*s...skipping\n",
00460                                                         user.len, user.s);
00461                                         continue;
00462                                 }
00463                                 /* user.s cannot be NULL - checked previosly */
00464                                 user.len = snprintf(uri, MAX_URI_SIZE, "%.*s@%s",
00465                                         user.len, user.s, domain);
00466                                 user.s = uri;
00467                                 if (user.s[user.len]!=0) {
00468                                         LM_CRIT("URI '%.*s@%s' longer than %d\n", user.len, user.s,
00469                                                         domain, MAX_URI_SIZE);
00470                                         continue;
00471                                 }
00472                         }
00473 
00474                 
00475                         lock_udomain(_d, &user);
00476                         if (get_urecord(_d, &user, &r) > 0) {
00477                                 if (mem_insert_urecord(_d, &user, &r) < 0) {
00478                                         LM_ERR("failed to create a record\n");
00479                                         unlock_udomain(_d, &user);
00480                                         goto error;
00481                                 }
00482                         }
00483 
00484                         if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
00485                                 LM_ERR("inserting contact failed\n");
00486                                 unlock_udomain(_d, &user);
00487                                 goto error1;
00488                         }
00489 
00490                         /* We have to do this, because insert_ucontact sets state to CS_NEW
00491                          * and we have the contact in the database already */
00492                         c->state = CS_SYNC;
00493                         unlock_udomain(_d, &user);
00494                 }
00495 
00496                 if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
00497                         if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
00498                                 LM_ERR("fetching rows (1) failed\n");
00499                                 ul_dbf.free_result(_c, res);
00500                                 return -1;
00501                         }
00502                 } else {
00503                         break;
00504                 }
00505         } while(RES_ROW_N(res)>0);
00506 
00507         ul_dbf.free_result(_c, res);
00508 
00509 #ifdef EXTRA_DEBUG
00510         LM_NOTICE("load end time [%d]\n", (int)time(NULL));
00511 #endif
00512 
00513         return 0;
00514 error1:
00515         free_ucontact(c);
00516 error:
00517         ul_dbf.free_result(_c, res);
00518         return -1;
00519 }
00520 
00521 
00529 urecord_t* db_load_urecord(db1_con_t* _c, udomain_t* _d, str *_aor)
00530 {
00531         ucontact_info_t *ci;
00532         db_key_t columns[16];
00533         db_key_t keys[2];
00534         db_key_t order;
00535         db_val_t vals[2];
00536         db1_res_t* res = NULL;
00537         str contact;
00538         char *domain;
00539         int i;
00540 
00541         urecord_t* r;
00542         ucontact_t* c;
00543 
00544         keys[0] = &user_col;
00545         vals[0].type = DB1_STR;
00546         vals[0].nul = 0;
00547         if (use_domain) {
00548                 keys[1] = &domain_col;
00549                 vals[1].type = DB1_STR;
00550                 vals[1].nul = 0;
00551                 domain = memchr(_aor->s, '@', _aor->len);
00552                 vals[0].val.str_val.s   = _aor->s;
00553                 if (domain==0) {
00554                         vals[0].val.str_val.len = 0;
00555                         vals[1].val.str_val = *_aor;
00556                 } else {
00557                         vals[0].val.str_val.len = domain - _aor->s;
00558                         vals[1].val.str_val.s   = domain+1;
00559                         vals[1].val.str_val.len = _aor->s + _aor->len - domain - 1;
00560                 }
00561         } else {
00562                 vals[0].val.str_val = *_aor;
00563         }
00564 
00565         columns[0] = &contact_col;
00566         columns[1] = &expires_col;
00567         columns[2] = &q_col;
00568         columns[3] = &callid_col;
00569         columns[4] = &cseq_col;
00570         columns[5] = &flags_col;
00571         columns[6] = &cflags_col;
00572         columns[7] = &user_agent_col;
00573         columns[8] = &received_col;
00574         columns[9] = &path_col;
00575         columns[10] = &sock_col;
00576         columns[11] = &methods_col;
00577         columns[12] = &last_mod_col;
00578         columns[13] = &ruid_col;
00579         columns[14] = &instance_col;
00580         columns[15] = &reg_id_col;
00581 
00582         if (desc_time_order)
00583                 order = &last_mod_col;
00584         else
00585                 order = &q_col;
00586 
00587         if (ul_dbf.use_table(_c, _d->name) < 0) {
00588                 LM_ERR("failed to use table %.*s\n", _d->name->len, _d->name->s);
00589                 return 0;
00590         }
00591 
00592         if (ul_dbf.query(_c, keys, 0, vals, columns, (use_domain)?2:1, 16, order,
00593                                 &res) < 0) {
00594                 LM_ERR("db_query failed\n");
00595                 return 0;
00596         }
00597 
00598         if (RES_ROW_N(res) == 0) {
00599                 LM_DBG("aor %.*s not found in table %.*s\n",_aor->len, _aor->s, _d->name->len, _d->name->s);
00600                 ul_dbf.free_result(_c, res);
00601                 return 0;
00602         }
00603 
00604         r = 0;
00605 
00606         for(i = 0; i < RES_ROW_N(res); i++) {
00607                 ci = dbrow2info(  ROW_VALUES(RES_ROWS(res) + i), &contact);
00608                 if (ci==0) {
00609                         LM_ERR("skipping record for %.*s in table %s\n",
00610                                         _aor->len, _aor->s, _d->name->s);
00611                         continue;
00612                 }
00613                 
00614                 if ( r==0 )
00615                         get_static_urecord( _d, _aor, &r);
00616 
00617                 if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
00618                         LM_ERR("mem_insert failed\n");
00619                         free_urecord(r);
00620                         ul_dbf.free_result(_c, res);
00621                         return 0;
00622                 }
00623 
00624                 /* We have to do this, because insert_ucontact sets state to CS_NEW
00625                  * and we have the contact in the database already */
00626                 c->state = CS_SYNC;
00627         }
00628 
00629         ul_dbf.free_result(_c, res);
00630         return r;
00631 }
00632 
00640 urecord_t* db_load_urecord_by_ruid(db1_con_t* _c, udomain_t* _d, str *_ruid)
00641 {
00642         ucontact_info_t *ci;
00643         db_key_t columns[18];
00644         db_key_t keys[1];
00645         db_key_t order;
00646         db_val_t vals[1];
00647         db1_res_t* res = NULL;
00648         db_row_t *row;
00649         str contact;
00650         str aor;
00651         char aorbuf[512];
00652         str domain;
00653 
00654         urecord_t* r;
00655         ucontact_t* c;
00656 
00657         keys[0] = &ruid_col;
00658         vals[0].type = DB1_STR;
00659         vals[0].nul = 0;
00660         vals[0].val.str_val = *_ruid;
00661 
00662         columns[0] = &contact_col;
00663         columns[1] = &expires_col;
00664         columns[2] = &q_col;
00665         columns[3] = &callid_col;
00666         columns[4] = &cseq_col;
00667         columns[5] = &flags_col;
00668         columns[6] = &cflags_col;
00669         columns[7] = &user_agent_col;
00670         columns[8] = &received_col;
00671         columns[9] = &path_col;
00672         columns[10] = &sock_col;
00673         columns[11] = &methods_col;
00674         columns[12] = &last_mod_col;
00675         columns[13] = &ruid_col;
00676         columns[14] = &instance_col;
00677         columns[15] = &reg_id_col;
00678         columns[16] = &user_col;
00679         columns[17] = &domain_col;
00680 
00681         if (desc_time_order)
00682                 order = &last_mod_col;
00683         else
00684                 order = &q_col;
00685 
00686         if (ul_dbf.use_table(_c, _d->name) < 0) {
00687                 LM_ERR("failed to use table %.*s\n", _d->name->len, _d->name->s);
00688                 return 0;
00689         }
00690 
00691         if (ul_dbf.query(_c, keys, 0, vals, columns, 1, 18, order,
00692                                 &res) < 0) {
00693                 LM_ERR("db_query failed\n");
00694                 return 0;
00695         }
00696 
00697         if (RES_ROW_N(res) == 0) {
00698                 LM_DBG("aor %.*s not found in table %.*s\n",_ruid->len, _ruid->s,
00699                                 _d->name->len, _d->name->s);
00700                 ul_dbf.free_result(_c, res);
00701                 return 0;
00702         }
00703 
00704         r = 0;
00705 
00706         /* use first row - shouldn't be more */
00707         row = RES_ROWS(res);
00708 
00709         ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact);
00710         if (ci==0) {
00711                 LM_ERR("skipping record for %.*s in table %s\n",
00712                                 _ruid->len, _ruid->s, _d->name->s);
00713                 goto done;
00714         }
00715 
00716         aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 16);
00717         aor.len = strlen(aor.s);
00718 
00719         if (use_domain) {
00720                 domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 17);
00721                 if (VAL_NULL(ROW_VALUES(row)+17) || domain.s==0 || domain.s[0]==0){
00722                         LM_CRIT("empty domain record for user %.*s...skipping\n",
00723                                         aor.len, aor.s);
00724                         goto done;
00725                 }
00726                 domain.len = strlen(domain.s);
00727                 if(aor.len + domain.len + 2 >= 512) {
00728                         LM_ERR("AoR is too big\n");
00729                         goto done;
00730                 }
00731                 memcpy(aorbuf, aor.s, aor.len);
00732                 aorbuf[aor.len] = '@';
00733                 memcpy(aorbuf + aor.len + 1, domain.s, domain.len);
00734                 aor.len += 1 + domain.len;
00735                 aor.s = aorbuf;
00736                 aor.s[aor.len] = '\0';
00737         }
00738         get_static_urecord( _d, &aor, &r);
00739 
00740         if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
00741                 LM_ERR("mem_insert failed\n");
00742                 free_urecord(r);
00743                 ul_dbf.free_result(_c, res);
00744                 return 0;
00745         }
00746 
00747         /* We have to do this, because insert_ucontact sets state to CS_NEW
00748          * and we have the contact in the database already */
00749         c->state = CS_SYNC;
00750 
00751 done:
00752         ul_dbf.free_result(_c, res);
00753         return r;
00754 }
00755 
00756 
00762 int db_timer_udomain(udomain_t* _d)
00763 {
00764         db_key_t keys[2];
00765         db_op_t  ops[2];
00766         db_val_t vals[2];
00767 
00768         keys[0] = &expires_col;
00769         ops[0] = "<";
00770         vals[0].type = DB1_DATETIME;
00771         vals[0].nul = 0;
00772         vals[0].val.time_val = act_time + 1;
00773 
00774         keys[1] = &expires_col;
00775         ops[1] = "!=";
00776         vals[1].type = DB1_DATETIME;
00777         vals[1].nul = 0;
00778         vals[1].val.time_val = 0;
00779 
00780         if (ul_dbf.use_table(ul_dbh, _d->name) < 0) {
00781                 LM_ERR("use_table failed\n");
00782                 return -1;
00783         }
00784 
00785         if (ul_dbf.delete(ul_dbh, keys, ops, vals, 2) < 0) {
00786                 LM_ERR("failed to delete from table %s\n",_d->name->s);
00787                 return -1;
00788         }
00789 
00790         return 0;
00791 }
00792 
00793 
00799 int testdb_udomain(db1_con_t* con, udomain_t* d)
00800 {
00801         db_key_t key[1], col[1];
00802         db_val_t val[1];
00803         db1_res_t* res = NULL;
00804 
00805         if (ul_dbf.use_table(con, d->name) < 0) {
00806                 LM_ERR("failed to change table\n");
00807                 return -1;
00808         }
00809 
00810         key[0] = &user_col;
00811 
00812         col[0] = &user_col;
00813         VAL_TYPE(val) = DB1_STRING;
00814         VAL_NULL(val) = 0;
00815         VAL_STRING(val) = "dummy_user";
00816         
00817         if (ul_dbf.query( con, key, 0, val, col, 1, 1, 0, &res) < 0) {
00818                 LM_ERR("failure in db_query\n");
00819                 return -1;
00820         }
00821 
00822         ul_dbf.free_result( con, res);
00823         return 0;
00824 }
00825 
00826 
00834 int mem_insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
00835 {
00836         int sl;
00837         
00838         if (new_urecord(_d->name, _aor, _r) < 0) {
00839                 LM_ERR("creating urecord failed\n");
00840                 return -1;
00841         }
00842 
00843         sl = ((*_r)->aorhash)&(_d->size-1);
00844         slot_add(&_d->table[sl], *_r);
00845         update_stat( _d->users, 1);
00846         return 0;
00847 }
00848 
00849 
00855 void mem_delete_urecord(udomain_t* _d, struct urecord* _r)
00856 {
00857         slot_rem(_r->slot, _r);
00858         free_urecord(_r);
00859         update_stat( _d->users, -1);
00860 }
00861 
00862 
00867 void mem_timer_udomain(udomain_t* _d, int istart, int istep)
00868 {
00869         struct urecord* ptr, *t;
00870         int i;
00871 
00872         for(i=istart; i<_d->size; i+=istep)
00873         {
00874                 lock_ulslot(_d, i);
00875 
00876                 ptr = _d->table[i].first;
00877 
00878                 while(ptr) {
00879                         timer_urecord(ptr);
00880                         /* Remove the entire record if it is empty */
00881                         if (ptr->contacts == 0) {
00882                                 t = ptr;
00883                                 ptr = ptr->next;
00884                                 mem_delete_urecord(_d, t);
00885                         } else {
00886                                 ptr = ptr->next;
00887                         }
00888                 }
00889                 unlock_ulslot(_d, i);
00890         }
00891 }
00892 
00893 
00899 void lock_udomain(udomain_t* _d, str* _aor)
00900 {
00901         unsigned int sl;
00902         if (db_mode!=DB_ONLY)
00903         {
00904                 sl = ul_get_aorhash(_aor) & (_d->size - 1);
00905 
00906 #ifdef GEN_LOCK_T_PREFERED
00907                 lock_get(_d->table[sl].lock);
00908 #else
00909                 ul_lock_idx(_d->table[sl].lockidx);
00910 #endif
00911         }
00912 }
00913 
00914 
00920 void unlock_udomain(udomain_t* _d, str* _aor)
00921 {
00922         unsigned int sl;
00923         if (db_mode!=DB_ONLY)
00924         {
00925                 sl = ul_get_aorhash(_aor) & (_d->size - 1);
00926 #ifdef GEN_LOCK_T_PREFERED
00927                 lock_release(_d->table[sl].lock);
00928 #else
00929                 ul_release_idx(_d->table[sl].lockidx);
00930 #endif
00931         }
00932 }
00933 
00939 void lock_ulslot(udomain_t* _d, int i)
00940 {
00941         if (db_mode!=DB_ONLY)
00942 #ifdef GEN_LOCK_T_PREFERED
00943                 lock_get(_d->table[i].lock);
00944 #else
00945                 ul_lock_idx(_d->table[i].lockidx);
00946 #endif
00947 }
00948 
00949 
00955 void unlock_ulslot(udomain_t* _d, int i)
00956 {
00957         if (db_mode!=DB_ONLY)
00958 #ifdef GEN_LOCK_T_PREFERED
00959                 lock_release(_d->table[i].lock);
00960 #else
00961                 ul_release_idx(_d->table[i].lockidx);
00962 #endif
00963 }
00964 
00965 
00966 
00974 int insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
00975 {
00976         if (db_mode!=DB_ONLY) {
00977                 if (mem_insert_urecord(_d, _aor, _r) < 0) {
00978                         LM_ERR("inserting record failed\n");
00979                         return -1;
00980                 }
00981         } else {
00982                 get_static_urecord( _d, _aor, _r);
00983         }
00984         return 0;
00985 }
00986 
00987 
00995 int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
00996 {
00997         unsigned int sl, i, aorhash;
00998         urecord_t* r;
00999 
01000         if (db_mode!=DB_ONLY) {
01001                 /* search in cache */
01002                 aorhash = ul_get_aorhash(_aor);
01003                 sl = aorhash&(_d->size-1);
01004                 r = _d->table[sl].first;
01005 
01006                 for(i = 0; i < _d->table[sl].n; i++) {
01007                         if((r->aorhash==aorhash) && (r->aor.len==_aor->len)
01008                                                 && !memcmp(r->aor.s,_aor->s,_aor->len)){
01009                                 *_r = r;
01010                                 return 0;
01011                         }
01012 
01013                         r = r->next;
01014                 }
01015         } else {
01016                 /* search in DB */
01017                 r = db_load_urecord( ul_dbh, _d, _aor);
01018                 if (r) {
01019                         *_r = r;
01020                         return 0;
01021                 }
01022         }
01023 
01024         return 1;   /* Nothing found */
01025 }
01026 
01036 int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
01037                 str *_ruid, struct urecord** _r, struct ucontact** _c)
01038 {
01039         unsigned int sl, i;
01040         urecord_t* r;
01041         ucontact_t* c;
01042 
01043         sl = _aorhash&(_d->size-1);
01044         lock_ulslot(_d, sl);
01045 
01046         if (db_mode!=DB_ONLY) {
01047                 /* search in cache */
01048                 r = _d->table[sl].first;
01049 
01050                 for(i = 0; i < _d->table[sl].n; i++) {
01051                         if(r->aorhash==_aorhash) {
01052                                 c = r->contacts;
01053                                 while(c) {
01054                                         if(c->ruid.len==_ruid->len
01055                                                         && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
01056                                                 *_r = r;
01057                                                 *_c = c;
01058                                                 return 0;
01059                                         }
01060                                 }
01061                         }
01062                         r = r->next;
01063                 }
01064         } else {
01065                 /* search in DB */
01066                 r = db_load_urecord_by_ruid(ul_dbh, _d, _ruid);
01067                 if (r) {
01068                         if(r->aorhash==_aorhash) {
01069                                 c = r->contacts;
01070                                 while(c) {
01071                                         if(c->ruid.len==_ruid->len
01072                                                         && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
01073                                                 *_r = r;
01074                                                 *_c = c;
01075                                                 return 0;
01076                                         }
01077                                 }
01078                         }
01079                 }
01080         }
01081 
01082         unlock_ulslot(_d, (_aorhash & (_d->size - 1)));
01083         return -1;   /* Nothing found */
01084 }
01085 
01093 int delete_urecord(udomain_t* _d, str* _aor, struct urecord* _r)
01094 {
01095         struct ucontact* c, *t;
01096 
01097         if (db_mode==DB_ONLY) {
01098                 if (_r==0)
01099                         get_static_urecord( _d, _aor, &_r);
01100                 if (db_delete_urecord(_r)<0) {
01101                         LM_ERR("DB delete failed\n");
01102                         return -1;
01103                 }
01104                 free_urecord(_r);
01105                 return 0;
01106         }
01107 
01108         if (_r==0) {
01109                 if (get_urecord(_d, _aor, &_r) > 0) {
01110                         return 0;
01111                 }
01112         }
01113 
01114         c = _r->contacts;
01115         while(c) {
01116                 t = c;
01117                 c = c->next;
01118                 if (delete_ucontact(_r, t) < 0) {
01119                         LM_ERR("deleting contact failed\n");
01120                         return -1;
01121                 }
01122         }
01123         release_urecord(_r);
01124         return 0;
01125 }