2
0

ts_hash.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * Copyright (C) 2014 Federico Cabiddu ([email protected])
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. /*!
  22. * \file
  23. * \brief Functions and definitions related to per user transaction indexing and searching
  24. * \ingroup tsilo
  25. * Module: \ref tsilo
  26. */
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "../../dprint.h"
  30. #include "../../ut.h"
  31. #include "../../hashes.h"
  32. #include "../../lib/kmi/mi.h"
  33. #include "ts_hash.h"
  34. #include "ts_handlers.h"
  35. /*! global transaction table */
  36. struct ts_table *t_table = 0;
  37. /*!
  38. * \brief Destroy a urecord and free memory
  39. * \param tma destroyed urecord
  40. */
  41. void free_ts_urecord(struct ts_urecord *urecord)
  42. {
  43. LM_DBG("destroying urecord %p\n", urecord);
  44. ts_transaction_t* ptr;
  45. while(urecord->transactions) {
  46. ptr = urecord->transactions;
  47. urecord->transactions = urecord->transactions->next;
  48. free_ts_transaction(ptr);
  49. }
  50. if (urecord->ruri.s) shm_free(urecord->ruri.s);
  51. shm_free(urecord);
  52. urecord = 0;
  53. }
  54. /*!
  55. * \brief Initialize the per user transactions table
  56. * \param size size of the table
  57. * \return 0 on success, -1 on failure
  58. */
  59. int init_ts_table(unsigned int size)
  60. {
  61. unsigned int n;
  62. unsigned int i;
  63. t_table = (struct ts_table*)shm_malloc( sizeof(struct ts_table));
  64. if (t_table==0) {
  65. LM_ERR("no more shm mem (1)\n");
  66. return -1;
  67. }
  68. memset( t_table, 0, sizeof(struct ts_table) );
  69. t_table->size = size;
  70. n = (size<MAX_TS_LOCKS)?size:MAX_TS_LOCKS;
  71. for( ; n>=MIN_TS_LOCKS ; n-- ) {
  72. t_table->locks = lock_set_alloc(n);
  73. if (t_table->locks==0)
  74. continue;
  75. if (lock_set_init(t_table->locks)==0) {
  76. lock_set_dealloc(t_table->locks);
  77. t_table->locks = 0;
  78. continue;
  79. }
  80. t_table->locks_no = n;
  81. break;
  82. }
  83. if (t_table->locks==0) {
  84. LM_ERR("unable to allocted at least %d locks for the hash table\n",
  85. MIN_TS_LOCKS);
  86. goto error;
  87. }
  88. t_table->entries = (ts_entry_t*)shm_malloc(sizeof(ts_entry_t) * size);
  89. if (!t_table->entries) {
  90. LM_ERR("no more shm mem (2)\n");
  91. goto error;
  92. }
  93. for( i=0 ; i<size; i++ ) {
  94. memset( &(t_table->entries[i]), 0, sizeof(struct ts_entry) );
  95. t_table->entries[i].next_id = rand() % (3*size);
  96. t_table->entries[i].lock_idx = i % t_table->locks_no;
  97. }
  98. return 0;
  99. error:
  100. shm_free( t_table );
  101. t_table = NULL;
  102. return -1;
  103. }
  104. /*!
  105. * \brief Destroy the per user transaction table
  106. */
  107. void destroy_ts_table(void)
  108. {
  109. struct ts_urecord *ts_u, *l_ts_u;
  110. unsigned int i;
  111. if (t_table==0)
  112. return;
  113. if (t_table->locks) {
  114. lock_set_destroy(t_table->locks);
  115. lock_set_dealloc(t_table->locks);
  116. }
  117. for( i=0 ; i<t_table->size; i++ ) {
  118. ts_u = t_table->entries[i].first;
  119. while (ts_u) {
  120. l_ts_u = ts_u;
  121. ts_u = ts_u->next;
  122. free_ts_urecord(l_ts_u);
  123. }
  124. }
  125. shm_free(t_table);
  126. t_table = 0;
  127. return;
  128. }
  129. void lock_entry(ts_entry_t *entry) {
  130. ts_lock(t_table, entry);
  131. }
  132. void unlock_entry(ts_entry_t *entry) {
  133. ts_unlock(t_table, entry);
  134. }
  135. void lock_entry_by_ruri(str* ruri)
  136. {
  137. unsigned int sl;
  138. sl = core_hash(ruri, 0, 0) & (t_table->size-1);
  139. ts_lock(t_table, &t_table->entries[sl]);
  140. }
  141. void unlock_entry_by_ruri(str* ruri)
  142. {
  143. unsigned int sl;
  144. sl = core_hash(ruri, 0, 0) & (t_table->size-1);
  145. ts_unlock(t_table, &t_table->entries[sl]);
  146. }
  147. /*
  148. * Obtain a urecord pointer if the urecord exists in the table
  149. */
  150. int get_ts_urecord(str* ruri, struct ts_urecord** _r)
  151. {
  152. int sl, i, rurihash;
  153. ts_urecord_t* r;
  154. rurihash = core_hash(ruri, 0, 0);
  155. sl = rurihash&(t_table->size-1);
  156. r = t_table->entries[sl].first;
  157. for(i = 0; r!=NULL && i < t_table->entries[sl].n; i++) {
  158. if((r->rurihash==rurihash) && (r->ruri.len==ruri->len)
  159. && !memcmp(r->ruri.s,ruri->s,ruri->len)){
  160. *_r = r;
  161. return 0;
  162. }
  163. r = r->next;
  164. }
  165. return 1; /* Nothing found */
  166. }
  167. /*!
  168. * \brief Create and initialize new record structure
  169. * \param ruri request uri
  170. * \param _r pointer to the new record
  171. * \return 0 on success, negative on failure
  172. */
  173. int new_ts_urecord(str* ruri, ts_urecord_t** _r)
  174. {
  175. *_r = (ts_urecord_t*)shm_malloc(sizeof(ts_urecord_t));
  176. if (*_r == 0) {
  177. LM_ERR("no more share memory\n");
  178. return -1;
  179. }
  180. memset(*_r, 0, sizeof(ts_urecord_t));
  181. (*_r)->ruri.s = (char*)shm_malloc(ruri->len);
  182. if ((*_r)->ruri.s == 0) {
  183. LM_ERR("no more share memory\n");
  184. shm_free(*_r);
  185. *_r = 0;
  186. return -2;
  187. }
  188. memcpy((*_r)->ruri.s, ruri->s, ruri->len);
  189. (*_r)->ruri.len = ruri->len;
  190. (*_r)->rurihash = core_hash(ruri, 0, 0);
  191. return 0;
  192. }
  193. /*!
  194. * \brief Insert a new record into transactions table
  195. * \param ruri request uri
  196. * \return 0 on success, -1 on failure
  197. */
  198. int insert_ts_urecord(str* ruri, ts_urecord_t** _r)
  199. {
  200. ts_entry_t* entry;
  201. int sl;
  202. if (new_ts_urecord(ruri, _r) < 0) {
  203. LM_ERR("creating urecord failed\n");
  204. return -1;
  205. }
  206. sl = ((*_r)->rurihash)&(t_table->size-1);
  207. entry = &t_table->entries[sl];
  208. if (entry->n == 0) {
  209. entry->first = entry->last = *_r;
  210. } else {
  211. (*_r)->prev = entry->last;
  212. entry->last->next = *_r;
  213. entry->last = *_r;
  214. }
  215. entry->n++;
  216. (*_r)->entry = entry;
  217. LM_DBG("urecord entry %p",entry);
  218. return 0;
  219. }
  220. /*!
  221. * \brief remove a urecord from table and free the memory
  222. * \param urecord t
  223. * \return 0 on success, -1 on failure
  224. */
  225. void remove_ts_urecord(ts_urecord_t* _r)
  226. {
  227. ts_entry_t* entry;
  228. entry = _r->entry;
  229. if (_r->prev)
  230. _r->prev->next = _r->next;
  231. if (_r->next)
  232. _r->next->prev = _r->prev;
  233. /* it was the last urecord */
  234. if (entry->n == 1) {
  235. entry->first = entry->last = NULL;
  236. }
  237. entry->n--;
  238. free_ts_urecord(_r);
  239. return;
  240. }
  241. /*!
  242. * \brief Insert a new transaction structure into urecord
  243. * \param _r urecord
  244. * \param tindex transaction index in tm table
  245. * \param tlabel transaction label in tm table
  246. * \return 0 on success, -1 otherwise
  247. */
  248. int insert_ts_transaction(struct cell* t, struct sip_msg* msg, struct ts_urecord* _r)
  249. {
  250. ts_transaction_t *ptr, *prev;
  251. ts_transaction_t* ts;
  252. unsigned int tindex;
  253. unsigned int tlabel;
  254. tindex = t->hash_index;
  255. tlabel = t->label;
  256. ptr = prev = 0;
  257. ptr = _r->transactions;
  258. while(ptr) {
  259. if ((ptr->tindex == tindex) && (ptr->tlabel == tlabel)) {
  260. LM_DBG("transaction already inserted\n");
  261. return -1;
  262. }
  263. prev = ptr;
  264. ptr = ptr->next;
  265. }
  266. if ( (ts=new_ts_transaction(tindex, tlabel) ) == 0) {
  267. LM_ERR("failed to create new contact\n");
  268. return -1;
  269. }
  270. ts->urecord = _r;
  271. /* add the new transaction at the end of the list */
  272. if (prev) {
  273. prev->next = ts;
  274. ts->prev = prev;
  275. } else {
  276. _r->transactions = ts;
  277. }
  278. if (ts_set_tm_callbacks(t, msg, ts) < 0) {
  279. LM_ERR("failed to set transaction %d:%d callbacks\n", tindex, tlabel);
  280. }
  281. return 0;
  282. }
  283. /*!
  284. * \brief Create a new transaction structure
  285. * \param tindex transaction index in tm table
  286. * \param tlabel transaction label in tm table
  287. * \return created transaction structure on success, NULL otherwise
  288. */
  289. ts_transaction_t* new_ts_transaction(int tindex, int tlabel)
  290. {
  291. ts_transaction_t *ts;
  292. int len;
  293. len = sizeof(ts_transaction_t);
  294. ts = (ts_transaction_t*)shm_malloc(len);
  295. if (ts==0) {
  296. LM_ERR("no more shm mem (%d)\n",len);
  297. return 0;
  298. }
  299. memset(ts, 0, len);
  300. ts->tindex = tindex;
  301. ts->tlabel = tlabel;
  302. return ts;
  303. }
  304. /*!
  305. * \brief Clone a transaction structure
  306. * \param ts transaction to be cloned
  307. * \return cloned transaction structure on success, NULL otherwise
  308. */
  309. ts_transaction_t* clone_ts_transaction(ts_transaction_t* ts)
  310. {
  311. ts_transaction_t *ts_clone;
  312. int len;
  313. if (ts == NULL)
  314. return NULL;
  315. len = sizeof(ts_transaction_t);
  316. ts_clone = (ts_transaction_t*)shm_malloc(len);
  317. if (ts_clone==NULL) {
  318. LM_ERR("no more shm mem (%d)\n",len);
  319. return NULL;
  320. }
  321. memcpy(ts_clone, ts, len);
  322. return ts_clone;
  323. }
  324. /*!
  325. * \brief remove a transaction from the urecord transactions list
  326. * \param tma unlinked transaction
  327. */
  328. void remove_ts_transaction(ts_transaction_t* ts_t)
  329. {
  330. if (ts_t->next)
  331. ts_t->next->prev = ts_t->prev;
  332. if (ts_t->prev)
  333. ts_t->prev->next = ts_t->next;
  334. if ((ts_t->prev == NULL) && (ts_t->next == NULL))
  335. ts_t->urecord->transactions = NULL;
  336. free_ts_transaction((void*)ts_t);
  337. return;
  338. }
  339. /*!
  340. * \brief Destroy a transaction and free memory
  341. * \param tma destroyed transaction
  342. */
  343. inline void free_ts_transaction(void *ts_t)
  344. {
  345. shm_free((struct ts_transaction*)ts_t);
  346. ts_t = 0;
  347. }