1 /*
2  * $Id$
3  *
4  * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
5  * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
6  *
7  * The initial version of this code was written by Dragos Vingarzan
8  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
9  * Fruanhofer Institute. It was and still is maintained in a separate
10  * branch of the original SER. We are therefore migrating it to
11  * Kamailio/SR and look forward to maintaining it from here on out.
12  * 2011/2012 Smile Communications, Pty. Ltd.
13  * ported/maintained/improved by
14  * Jason Penton (jason(dot)penton(at)smilecoms.com and
15  * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
16  * effort to add full IMS support to Kamailio/SR using a new and
17  * improved architecture
18  *
19  * NB: Alot of this code was originally part of OpenIMSCore,
20  * FhG Fokus.
21  * Copyright (C) 2004-2006 FhG Fokus
22  * Thanks for great work! This is an effort to
23  * break apart the various CSCF functions into logically separate
24  * components. We hope this will drive wider use. We also feel
25  * that in this way the architecture is more complete and thereby easier
26  * to manage in the Kamailio/SR environment
27  *
28  * This file is part of Kamailio, a free SIP server.
29  *
30  * Kamailio is free software; you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation; either version 2 of the License, or
33  * (at your option) any later version
34  *
35  * Kamailio is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License
41  * along with this program; if not, write to the Free Software
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
43  *
44  */
45 
46 
47 
48 #include "hslot.h"
49 
50 /*! number of locks */
51 int ul_locks_no=4;
52 /*! global list of locks */
53 gen_lock_set_t* ul_locks=0;
54 
55 
56 /*!
57  * \brief Initialize locks for the hash table
58  * \return 0 on success, -1 on failure
59  */
ul_init_locks(void)60 int ul_init_locks(void)
61 {
62 	int i;
63 	i = ul_locks_no;
64 	do {
65 		if ((( ul_locks=lock_set_alloc(i))!=0)&&
66 				(lock_set_init(ul_locks)!=0))
67 		{
68 			ul_locks_no = i;
69 			LM_INFO("locks array size %d\n", ul_locks_no);
70 			return 0;
71 
72 		}
73 		if (ul_locks){
74 			lock_set_dealloc(ul_locks);
75 			ul_locks=0;
76 		}
77 		i--;
78 		if(i==0)
79 		{
80 			LM_ERR("failed to allocate locks\n");
81 			return -1;
82 		}
83 	} while (1);
84 }
85 
86 
87 /*!
88  * \brief Unlock all locks on the list
89  */
ul_unlock_locks(void)90 void ul_unlock_locks(void)
91 {
92 	unsigned int i;
93 
94 	if (ul_locks==0)
95 		return;
96 
97 	for (i=0;i<ul_locks_no;i++) {
98 #ifdef GEN_LOCK_T_PREFERED
99 		lock_release(&ul_locks->locks[i]);
100 #else
101 		ul_release_idx(i);
102 #endif
103 	};
104 }
105 
106 
107 /*!
108  * \brief Destroy all locks on the list
109  */
ul_destroy_locks(void)110 void ul_destroy_locks(void)
111 {
112 	if (ul_locks !=0){
113 		lock_set_destroy(ul_locks);
114 		lock_set_dealloc(ul_locks);
115 	};
116 }
117 
118 #ifndef GEN_LOCK_T_PREFERED
119 /*!
120  * \brief Lock a lock with a certain index
121  * \param idx lock index
122  */
ul_lock_idx(int idx)123 void ul_lock_idx(int idx)
124 {
125 	lock_set_get(ul_locks, idx);
126 }
127 
128 
129 /*!
130  * \brief Release a lock with a certain index
131  * \param idx lock index
132  */
ul_release_idx(int idx)133 void ul_release_idx(int idx)
134 {
135 	lock_set_release(ul_locks, idx);
136 }
137 #endif
138 
139 /*!
140  * \brief Initialize cache slot structure
141  * \param _d domain for the hash slot
142  * \param _s hash slot
143  * \param n used to get the slot number (modulo number or locks)
144  */
init_slot(struct udomain * _d,hslot_t * _s,int n)145 void init_slot(struct udomain* _d, hslot_t* _s, int n)
146 {
147 	_s->n = 0;
148 	_s->first = 0;
149 	_s->last = 0;
150 	_s->d = _d;
151 
152 #ifdef GEN_LOCK_T_PREFERED
153 	_s->lock = &ul_locks->locks[n%ul_locks_no];
154 #else
155 	_s->lockidx = n%ul_locks_no;
156 #endif
157 }
158 
159 
160 /*!
161  * \brief Deinitialize given slot structure
162  * \param _s hash slot
163  */
deinit_slot(hslot_t * _s)164 void deinit_slot(hslot_t* _s)
165 {
166 	struct impurecord* ptr;
167 
168 	     /* Remove all elements */
169 	while(_s->first) {
170 		ptr = _s->first;
171 		_s->first = _s->first->next;
172 		free_impurecord(ptr);
173 	}
174 
175 	_s->n = 0;
176 	_s->last = 0;
177     _s->d = 0;
178 }
179 
180 
181 /*!
182  * \brief Add an element to an slot's linked list
183  * \param _s hash slot
184  * \param _r added record
185  */
slot_add(hslot_t * _s,struct impurecord * _r)186 void slot_add(hslot_t* _s, struct impurecord* _r)
187 {
188 	if (_s->n == 0) {
189 		_s->first = _s->last = _r;
190 	} else {
191 		_r->prev = _s->last;
192 		_s->last->next = _r;
193 		_s->last = _r;
194 	}
195 	_s->n++;
196 	_r->slot = _s;
197 }
198 
199 
200 /*!
201  * \brief Remove an element from slot linked list
202  * \param _s hash slot
203  * \param _r removed record
204  */
slot_rem(hslot_t * _s,struct impurecord * _r)205 void slot_rem(hslot_t* _s, struct impurecord* _r)
206 {
207     LM_DBG("Removing IMPU [%.*s] from hashtable\n", _r->public_identity.len, _r->public_identity.s);
208     if (_r->prev) {
209         _r->prev->next = _r->next;
210     } else {
211         _s->first = _r->next;
212     }
213 
214     if (_r->next) {
215         _r->next->prev = _r->prev;
216     } else {
217         _s->last = _r->prev;
218     }
219 
220     _r->prev = _r->next = 0;
221     _r->slot = 0;
222     _s->n--;
223 }
224