dlist.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * History:
  23. * ========
  24. * 2005-07-11 get_all_ucontacts returns also the contact's flags (bogdan)
  25. * 2006-11-28 added get_number_of_users() (Jeffrey Magder - SOMA Networks)
  26. * 2007-09-12 added partitioning support for fetching all ul contacts
  27. * (bogdan)
  28. */
  29. /*! \file
  30. * \brief USRLOC - List of registered domains
  31. * \ingroup usrloc
  32. *
  33. * - Module: \ref usrloc
  34. */
  35. #include "dlist.h"
  36. #include <stdlib.h> /* abort */
  37. #include <string.h> /* strlen, memcmp */
  38. #include <stdio.h> /* printf */
  39. #include "../../ut.h"
  40. #include "../../lib/srdb1/db_ut.h"
  41. #include "../../mem/shm_mem.h"
  42. #include "../../dprint.h"
  43. #include "../../ip_addr.h"
  44. #include "../../socket_info.h"
  45. #include "udomain.h" /* new_udomain, free_udomain */
  46. #include "usrloc.h"
  47. #include "utime.h"
  48. #include "ul_mod.h"
  49. /*! \brief Global list of all registered domains */
  50. dlist_t* root = 0;
  51. /*!
  52. * \brief Find domain with the given name
  53. * \param _n domain name
  54. * \param _d pointer to domain
  55. * \return 0 if the domain was found and 1 of not
  56. */
  57. static inline int find_dlist(str* _n, dlist_t** _d)
  58. {
  59. dlist_t* ptr;
  60. ptr = root;
  61. while(ptr) {
  62. if ((_n->len == ptr->name.len) &&
  63. !memcmp(_n->s, ptr->name.s, _n->len)) {
  64. *_d = ptr;
  65. return 0;
  66. }
  67. ptr = ptr->next;
  68. }
  69. return 1;
  70. }
  71. extern int ul_db_raw_fetch_type;
  72. #define UL_DB_RAW_FETCH_COMMON "select %.*s, %.*s, %.*s, %.*s, %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and id %% %u = %u"
  73. #define UL_DB_RAW_FETCH_ORACLE "select %.*s, %.*s, %.*s, %.*s, %.*s, %.*s from %s where %.*s > %.*s and bitand(%.*s, %d) = %d and mod(id, %u) = %u"
  74. /*!
  75. * \brief Get all contacts from the database, in partitions if wanted
  76. * \see get_all_ucontacts
  77. * \param buf target buffer
  78. * \param len length of buffer
  79. * \param flags contact flags
  80. * \param part_idx part index
  81. * \param part_max maximal part
  82. * \return 0 on success, positive if buffer size was not sufficient, negative on failure
  83. */
  84. static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
  85. unsigned int part_idx, unsigned int part_max)
  86. {
  87. static char query_buf[512];
  88. static str query_str;
  89. struct socket_info *sock;
  90. unsigned int dbflags;
  91. db1_res_t* res = NULL;
  92. db_row_t *row;
  93. dlist_t *dom;
  94. char now_s[25];
  95. int now_len;
  96. int port, proto;
  97. char *p;
  98. str addr;
  99. str path;
  100. str ruid;
  101. str host;
  102. unsigned int aorhash;
  103. int i;
  104. void *cp;
  105. int shortage, needed;
  106. if(ul_dbf.raw_query==NULL) {
  107. LM_WARN("DB raw query support is required, but not implemented\n");
  108. return -1;
  109. }
  110. cp = buf;
  111. shortage = 0;
  112. /* Reserve space for terminating 0000 */
  113. len -= sizeof(addr.len);
  114. /* get the current time in DB format */
  115. now_len = 25;
  116. if (db_time2str( time(0), now_s, &now_len)!=0) {
  117. LM_ERR("failed to print now time\n");
  118. return -1;
  119. }
  120. aorhash = 0;
  121. for (dom = root; dom!=NULL ; dom=dom->next) {
  122. /* build query */
  123. i = snprintf( query_buf, sizeof(query_buf),
  124. (ul_db_raw_fetch_type==1)?
  125. UL_DB_RAW_FETCH_ORACLE:UL_DB_RAW_FETCH_COMMON,
  126. received_col.len, received_col.s,
  127. contact_col.len, contact_col.s,
  128. sock_col.len, sock_col.s,
  129. cflags_col.len, cflags_col.s,
  130. path_col.len, path_col.s,
  131. ruid_col.len, ruid_col.s,
  132. dom->d->name->s,
  133. expires_col.len, expires_col.s,
  134. now_len, now_s,
  135. cflags_col.len, cflags_col.s,
  136. flags, flags, part_max, part_idx);
  137. if ( i>=sizeof(query_buf) ) {
  138. LM_ERR("DB query too long\n");
  139. return -1;
  140. }
  141. query_str.s = query_buf;
  142. query_str.len = i;
  143. if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
  144. LM_ERR("raw_query failed\n");
  145. return -1;
  146. }
  147. if( RES_ROW_N(res)==0 ) {
  148. ul_dbf.free_result(ul_dbh, res);
  149. continue;
  150. }
  151. for(i = 0; i < RES_ROW_N(res); i++) {
  152. row = RES_ROWS(res) + i;
  153. /* received */
  154. addr.s = (char*)VAL_STRING(ROW_VALUES(row));
  155. if ( VAL_NULL(ROW_VALUES(row)) || addr.s==0 || addr.s[0]==0 ) {
  156. /* contact */
  157. addr.s = (char*)VAL_STRING(ROW_VALUES(row)+1);
  158. if (VAL_NULL(ROW_VALUES(row)+1) || addr.s==0 || addr.s[0]==0) {
  159. LM_ERR("empty contact -> skipping\n");
  160. continue;
  161. }
  162. }
  163. addr.len = strlen(addr.s);
  164. /* path */
  165. path.s = (char*)VAL_STRING(ROW_VALUES(row)+4);
  166. if (VAL_NULL(ROW_VALUES(row)+4) || path.s==0 || path.s[0]==0){
  167. path.s = NULL;
  168. path.len = 0;
  169. } else {
  170. path.len = strlen(path.s);
  171. }
  172. /* ruid */
  173. ruid.s = (char*)VAL_STRING(ROW_VALUES(row)+5);
  174. if (VAL_NULL(ROW_VALUES(row)+5) || ruid.s==0 || ruid.s[0]==0){
  175. ruid.s = NULL;
  176. ruid.len = 0;
  177. } else {
  178. ruid.len = strlen(ruid.s);
  179. }
  180. needed = (int)(sizeof(addr.len) + addr.len
  181. + sizeof(sock) + sizeof(dbflags)
  182. + sizeof(path.len) + path.len
  183. + sizeof(ruid.len) + ruid.len
  184. + sizeof(aorhash));
  185. if (len < needed) {
  186. shortage += needed ;
  187. continue;
  188. }
  189. /* write received/contact */
  190. memcpy(cp, &addr.len, sizeof(addr.len));
  191. cp = (char*)cp + sizeof(addr.len);
  192. memcpy(cp, addr.s, addr.len);
  193. cp = (char*)cp + addr.len;
  194. /* sock */
  195. p = (char*)VAL_STRING(ROW_VALUES(row) + 2);
  196. if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
  197. sock = 0;
  198. } else {
  199. if (parse_phostport( p, &host.s, &host.len,
  200. &port, &proto)!=0) {
  201. LM_ERR("bad socket <%s>...set to 0\n", p);
  202. sock = 0;
  203. } else {
  204. sock = grep_sock_info( &host, (unsigned short)port, proto);
  205. if (sock==0) {
  206. LM_DBG("non-local socket <%s>...set to 0\n", p);
  207. }
  208. }
  209. }
  210. /* flags */
  211. dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);
  212. /* write sock and flags */
  213. memcpy(cp, &sock, sizeof(sock));
  214. cp = (char*)cp + sizeof(sock);
  215. memcpy(cp, &dbflags, sizeof(dbflags));
  216. cp = (char*)cp + sizeof(dbflags);
  217. /* write path */
  218. memcpy(cp, &path.len, sizeof(path.len));
  219. cp = (char*)cp + sizeof(path.len);
  220. /* copy path only if exist */
  221. if(path.len){
  222. memcpy(cp, path.s, path.len);
  223. cp = (char*)cp + path.len;
  224. }
  225. /* write ruid */
  226. memcpy(cp, &ruid.len, sizeof(ruid.len));
  227. cp = (char*)cp + sizeof(ruid.len);
  228. /* copy ruid only if exist */
  229. if(ruid.len){
  230. memcpy(cp, ruid.s, ruid.len);
  231. cp = (char*)cp + ruid.len;
  232. }
  233. /* aorhash not used for db-only records, but it is added
  234. * (as 0) to match the struct used for mem records */
  235. memcpy(cp, &aorhash, sizeof(aorhash));
  236. cp = (char*)cp + sizeof(aorhash);
  237. len -= needed;
  238. } /* row cycle */
  239. ul_dbf.free_result(ul_dbh, res);
  240. } /* domain cycle */
  241. /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
  242. if (len >= 0)
  243. memset(cp, 0, sizeof(addr.len));
  244. /* Shouldn't happen */
  245. if (shortage > 0 && len > shortage) {
  246. abort();
  247. }
  248. shortage -= len;
  249. return shortage > 0 ? shortage : 0;
  250. }
  251. /*!
  252. * \brief Get all contacts from the memory, in partitions if wanted
  253. * \see get_all_ucontacts
  254. * \param buf target buffer
  255. * \param len length of buffer
  256. * \param flags contact flags
  257. * \param part_idx part index
  258. * \param part_max maximal part
  259. * \return 0 on success, positive if buffer size was not sufficient, negative on failure
  260. */
  261. static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
  262. unsigned int part_idx, unsigned int part_max)
  263. {
  264. dlist_t *p;
  265. urecord_t *r;
  266. ucontact_t *c;
  267. void *cp;
  268. int shortage;
  269. int needed;
  270. int i = 0;
  271. cp = buf;
  272. shortage = 0;
  273. time_t tnow = 0;
  274. if(ul_keepalive_timeout>0)
  275. tnow = time(NULL);
  276. /* Reserve space for terminating 0000 */
  277. len -= sizeof(c->c.len);
  278. for (p = root; p != NULL; p = p->next) {
  279. for(i=0; i<p->d->size; i++) {
  280. if ( (i % part_max) != part_idx )
  281. continue;
  282. lock_ulslot(p->d, i);
  283. if(p->d->table[i].n<=0)
  284. {
  285. unlock_ulslot(p->d, i);
  286. continue;
  287. }
  288. for (r = p->d->table[i].first; r != NULL; r = r->next) {
  289. for (c = r->contacts; c != NULL; c = c->next) {
  290. if (c->c.len <= 0)
  291. continue;
  292. /*
  293. * List only contacts that have all requested
  294. * flags set
  295. */
  296. if ((c->cflags & flags) != flags)
  297. continue;
  298. if(ul_keepalive_timeout>0 && c->last_keepalive>0)
  299. {
  300. if(c->sock!=NULL && c->sock->proto==PROTO_UDP)
  301. {
  302. if(c->last_keepalive+ul_keepalive_timeout < tnow)
  303. {
  304. /* set contact as expired in 10s */
  305. if(c->expires > tnow + 10)
  306. c->expires = tnow + 10;
  307. continue;
  308. }
  309. }
  310. }
  311. if (c->received.s) {
  312. needed = (int)(sizeof(c->received.len)
  313. + c->received.len
  314. + sizeof(c->sock) + sizeof(c->cflags)
  315. + sizeof(c->path.len) + c->path.len
  316. + sizeof(c->ruid.len) + c->ruid.len
  317. + sizeof(r->aorhash));
  318. if (len >= needed) {
  319. memcpy(cp,&c->received.len,sizeof(c->received.len));
  320. cp = (char*)cp + sizeof(c->received.len);
  321. memcpy(cp, c->received.s, c->received.len);
  322. cp = (char*)cp + c->received.len;
  323. memcpy(cp, &c->sock, sizeof(c->sock));
  324. cp = (char*)cp + sizeof(c->sock);
  325. memcpy(cp, &c->cflags, sizeof(c->cflags));
  326. cp = (char*)cp + sizeof(c->cflags);
  327. memcpy(cp, &c->path.len, sizeof(c->path.len));
  328. cp = (char*)cp + sizeof(c->path.len);
  329. memcpy(cp, c->path.s, c->path.len);
  330. cp = (char*)cp + c->path.len;
  331. memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
  332. cp = (char*)cp + sizeof(c->ruid.len);
  333. memcpy(cp, c->ruid.s, c->ruid.len);
  334. cp = (char*)cp + c->ruid.len;
  335. memcpy(cp, &r->aorhash, sizeof(r->aorhash));
  336. cp = (char*)cp + sizeof(r->aorhash);
  337. len -= needed;
  338. } else {
  339. shortage += needed;
  340. }
  341. } else {
  342. needed = (int)(sizeof(c->c.len) + c->c.len
  343. + sizeof(c->sock) + sizeof(c->cflags)
  344. + sizeof(c->path.len) + c->path.len
  345. + sizeof(c->ruid.len) + c->ruid.len
  346. + sizeof(r->aorhash));
  347. if (len >= needed) {
  348. memcpy(cp, &c->c.len, sizeof(c->c.len));
  349. cp = (char*)cp + sizeof(c->c.len);
  350. memcpy(cp, c->c.s, c->c.len);
  351. cp = (char*)cp + c->c.len;
  352. memcpy(cp, &c->sock, sizeof(c->sock));
  353. cp = (char*)cp + sizeof(c->sock);
  354. memcpy(cp, &c->cflags, sizeof(c->cflags));
  355. cp = (char*)cp + sizeof(c->cflags);
  356. memcpy(cp, &c->path.len, sizeof(c->path.len));
  357. cp = (char*)cp + sizeof(c->path.len);
  358. memcpy(cp, c->path.s, c->path.len);
  359. cp = (char*)cp + c->path.len;
  360. memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
  361. cp = (char*)cp + sizeof(c->ruid.len);
  362. memcpy(cp, c->ruid.s, c->ruid.len);
  363. cp = (char*)cp + c->ruid.len;
  364. memcpy(cp, &r->aorhash, sizeof(r->aorhash));
  365. cp = (char*)cp + sizeof(r->aorhash);
  366. len -= needed;
  367. } else {
  368. shortage += needed;
  369. }
  370. }
  371. }
  372. }
  373. unlock_ulslot(p->d, i);
  374. }
  375. }
  376. /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
  377. if (len >= 0)
  378. memset(cp, 0, sizeof(c->c.len));
  379. /* Shouldn't happen */
  380. if (shortage > 0 && len > shortage) {
  381. abort();
  382. }
  383. shortage -= len;
  384. return shortage > 0 ? shortage : 0;
  385. }
  386. /*!
  387. * \brief Get all contacts from the usrloc, in partitions if wanted
  388. *
  389. * Return list of all contacts for all currently registered
  390. * users in all domains. The caller must provide buffer of
  391. * sufficient length for fitting all those contacts. In the
  392. * case when buffer was exhausted, the function returns
  393. * estimated amount of additional space needed, in this
  394. * case the caller is expected to repeat the call using
  395. * this value as the hint.
  396. *
  397. * Information is packed into the buffer as follows:
  398. *
  399. * +------------+----------+-----+------+-----+
  400. * |contact1.len|contact1.s|sock1|flags1|path1|
  401. * +------------+----------+-----+------+-----+
  402. * |contact2.len|contact2.s|sock2|flags2|path1|
  403. * +------------+----------+-----+------+-----+
  404. * |..........................................|
  405. * +------------+----------+-----+------+-----+
  406. * |contactN.len|contactN.s|sockN|flagsN|pathN|
  407. * +------------+----------+-----+------+-----+
  408. * |000000000000|
  409. * +------------+
  410. *
  411. * \param buf target buffer
  412. * \param len length of buffer
  413. * \param flags contact flags
  414. * \param part_idx part index
  415. * \param part_max maximal part
  416. * \return 0 on success, positive if buffer size was not sufficient, negative on failure
  417. */
  418. int get_all_ucontacts(void *buf, int len, unsigned int flags,
  419. unsigned int part_idx, unsigned int part_max)
  420. {
  421. if (db_mode==DB_ONLY)
  422. return get_all_db_ucontacts( buf, len, flags, part_idx, part_max);
  423. else
  424. return get_all_mem_ucontacts( buf, len, flags, part_idx, part_max);
  425. }
  426. /**
  427. *
  428. */
  429. int ul_refresh_keepalive(unsigned int _aorhash, str *_ruid)
  430. {
  431. dlist_t *p;
  432. urecord_t *r;
  433. ucontact_t *c;
  434. int i;
  435. /* todo: get location domain via param */
  436. for (p = root; p != NULL; p = p->next)
  437. {
  438. i = _aorhash&(p->d->size-1);
  439. lock_ulslot(p->d, i);
  440. if(p->d->table[i].n<=0)
  441. {
  442. unlock_ulslot(p->d, i);
  443. continue;
  444. }
  445. for (r = p->d->table[i].first; r != NULL; r = r->next)
  446. {
  447. if(r->aorhash==_aorhash)
  448. {
  449. for (c = r->contacts; c != NULL; c = c->next)
  450. {
  451. if (c->c.len <= 0 || c->ruid.len<=0)
  452. continue;
  453. if(c->ruid.len==_ruid->len
  454. && !memcmp(c->ruid.s, _ruid->s, _ruid->len))
  455. {
  456. /* found */
  457. c->last_keepalive = time(NULL);
  458. LM_DBG("updated keepalive for [%.*s:%u] to %u\n",
  459. _ruid->len, _ruid->s, _aorhash,
  460. (unsigned int)c->last_keepalive);
  461. unlock_ulslot(p->d, i);
  462. return 0;
  463. }
  464. }
  465. }
  466. }
  467. unlock_ulslot(p->d, i);
  468. }
  469. return 0;
  470. }
  471. /*!
  472. * \brief Create a new domain structure
  473. * \return 0 if everything went OK, otherwise value < 0 is returned
  474. *
  475. * \note The structure is NOT created in shared memory so the
  476. * function must be called before the server forks if it should
  477. * be available to all processes
  478. */
  479. static inline int new_dlist(str* _n, dlist_t** _d)
  480. {
  481. dlist_t* ptr;
  482. /* Domains are created before ser forks,
  483. * so we can create them using pkg_malloc
  484. */
  485. ptr = (dlist_t*)shm_malloc(sizeof(dlist_t));
  486. if (ptr == 0) {
  487. LM_ERR("no more share memory\n");
  488. return -1;
  489. }
  490. memset(ptr, 0, sizeof(dlist_t));
  491. /* copy domain name as null terminated string */
  492. ptr->name.s = (char*)shm_malloc(_n->len+1);
  493. if (ptr->name.s == 0) {
  494. LM_ERR("no more memory left\n");
  495. shm_free(ptr);
  496. return -2;
  497. }
  498. memcpy(ptr->name.s, _n->s, _n->len);
  499. ptr->name.len = _n->len;
  500. ptr->name.s[ptr->name.len] = 0;
  501. if (new_udomain(&(ptr->name), ul_hash_size, &(ptr->d)) < 0) {
  502. LM_ERR("creating domain structure failed\n");
  503. shm_free(ptr->name.s);
  504. shm_free(ptr);
  505. return -3;
  506. }
  507. *_d = ptr;
  508. return 0;
  509. }
  510. /*!
  511. * \brief Registers a new domain with usrloc
  512. *
  513. * Find and return a usrloc domain (location table)
  514. * \param _n domain name
  515. * \param _d usrloc domain
  516. * \return 0 on success, -1 on failure
  517. */
  518. int get_udomain(const char* _n, udomain_t** _d)
  519. {
  520. dlist_t* d;
  521. str s;
  522. s.s = (char*)_n;
  523. s.len = strlen(_n);
  524. if (find_dlist(&s, &d) == 0) {
  525. *_d = d->d;
  526. return 0;
  527. }
  528. *_d = NULL;
  529. return -1;
  530. }
  531. /*!
  532. * \brief Registers a new domain with usrloc
  533. *
  534. * Registers a new domain with usrloc. If the domain exists,
  535. * a pointer to existing structure will be returned, otherwise
  536. * a new domain will be created
  537. * \param _n domain name
  538. * \param _d new created domain
  539. * \return 0 on success, -1 on failure
  540. */
  541. int register_udomain(const char* _n, udomain_t** _d)
  542. {
  543. dlist_t* d;
  544. str s;
  545. db1_con_t* con;
  546. s.s = (char*)_n;
  547. s.len = strlen(_n);
  548. if (find_dlist(&s, &d) == 0) {
  549. *_d = d->d;
  550. return 0;
  551. }
  552. if (new_dlist(&s, &d) < 0) {
  553. LM_ERR("failed to create new domain\n");
  554. return -1;
  555. }
  556. /* Test tables from database if we are gonna
  557. * to use database
  558. */
  559. if (db_mode != NO_DB) {
  560. con = ul_dbf.init(&db_url);
  561. if (!con) {
  562. LM_ERR("failed to open database connection\n");
  563. goto err;
  564. }
  565. if(db_check_table_version(&ul_dbf, con, &s, UL_TABLE_VERSION) < 0) {
  566. LM_ERR("error during table version check.\n");
  567. goto err;
  568. }
  569. /* test if DB really exists */
  570. if (testdb_udomain(con, d->d) < 0) {
  571. LM_ERR("testing domain '%.*s' failed\n", s.len, ZSW(s.s));
  572. goto err;
  573. }
  574. ul_dbf.close(con);
  575. }
  576. d->next = root;
  577. root = d;
  578. *_d = d->d;
  579. return 0;
  580. err:
  581. if (con) ul_dbf.close(con);
  582. free_udomain(d->d);
  583. shm_free(d->name.s);
  584. shm_free(d);
  585. return -1;
  586. }
  587. /*!
  588. * \brief Free all allocated memory for domains
  589. */
  590. void free_all_udomains(void)
  591. {
  592. dlist_t* ptr;
  593. while(root) {
  594. ptr = root;
  595. root = root->next;
  596. free_udomain(ptr->d);
  597. shm_free(ptr->name.s);
  598. shm_free(ptr);
  599. }
  600. }
  601. /*!
  602. * \brief Print all domains, just for debugging
  603. * \param _f output file
  604. */
  605. void print_all_udomains(FILE* _f)
  606. {
  607. dlist_t* ptr;
  608. ptr = root;
  609. fprintf(_f, "===Domain list===\n");
  610. while(ptr) {
  611. print_udomain(_f, ptr->d);
  612. ptr = ptr->next;
  613. }
  614. fprintf(_f, "===/Domain list===\n");
  615. }
  616. /*!
  617. * \brief Loops through all domains summing up the number of users
  618. * \return the number of users, could be zero
  619. */
  620. unsigned long get_number_of_users(void)
  621. {
  622. long numberOfUsers = 0;
  623. dlist_t* current_dlist;
  624. current_dlist = root;
  625. while (current_dlist)
  626. {
  627. numberOfUsers += get_stat_val(current_dlist->d->users);
  628. current_dlist = current_dlist->next;
  629. }
  630. return numberOfUsers;
  631. }
  632. /*!
  633. * \brief Run timer handler of all domains
  634. * \return 0 if all timer return 0, != 0 otherwise
  635. */
  636. int synchronize_all_udomains(int istart, int istep)
  637. {
  638. int res = 0;
  639. dlist_t* ptr;
  640. get_act_time(); /* Get and save actual time */
  641. if (db_mode==DB_ONLY) {
  642. for( ptr=root ; ptr ; ptr=ptr->next)
  643. res |= db_timer_udomain(ptr->d);
  644. } else {
  645. for( ptr=root ; ptr ; ptr=ptr->next)
  646. mem_timer_udomain(ptr->d, istart, istep);
  647. }
  648. return res;
  649. }
  650. /*!
  651. * \brief Find a particular domain, small wrapper around find_dlist
  652. * \param _d domain name
  653. * \param _p pointer to domain if found
  654. * \return 1 if domain was found, 0 otherwise
  655. */
  656. int find_domain(str* _d, udomain_t** _p)
  657. {
  658. dlist_t* d;
  659. if (find_dlist(_d, &d) == 0) {
  660. *_p = d->d;
  661. return 0;
  662. }
  663. return 1;
  664. }