0f40c64d465dfa9c6d85e48aead76a05c2f8bb11
[sip-router] / modules / tm / h_table.c
1 /*
2  * $Id$
3  */
4
5 #include "hash_func.h"
6 #include "h_table.h"
7 #include "../../dprint.h"
8 #include "sh_malloc.h"
9
10
11 /*   Frees the all the containes of a cell and the cell's body itself
12   */
13 void free_cell( struct cell* dead_cell )
14 {
15         int i;
16         struct retrans_buff* rb;
17         char *b;
18
19         DBG("DEBUG: free_cell: start\n");
20         /* UA Server */
21         DBG("DEBUG: free_cell: inbound request %p\n",dead_cell->inbound_request);
22         shm_lock();
23         if ( dead_cell->inbound_request )
24                 sip_msg_free_unsafe( dead_cell->inbound_request );
25         DBG("DEBUG: free_cell: outbound response %p\n",dead_cell->outbound_response);
26         if (b=dead_cell->outbound_response.retr_buffer) shm_free_unsafe( b );
27
28         /* UA Clients */
29         for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
30         {
31                 /* outbound requests*/
32                 DBG("DEBUG: free_cell: outbound_request[%d] %p\n",i,dead_cell->outbound_request[i]);
33                 if ( rb=dead_cell->outbound_request[i] )
34                 {
35                         if (rb->retr_buffer) shm_free_unsafe( rb->retr_buffer );
36                         dead_cell->outbound_request[i] = NULL;
37                         shm_free_unsafe( rb );
38                 }
39                 /* outbound requests*/
40                 DBG("DEBUG: free_cell: inbound_response[%d] %p\n",i,dead_cell->inbound_response[i]);
41                 if ( dead_cell -> inbound_response[i] )
42                 sip_msg_free_unsafe( dead_cell->inbound_response[i] );
43         }
44         /* mutex */
45         /* release_cell_lock( dead_cell ); */
46         /* the cell's body */
47         shm_free_unsafe( dead_cell );
48         shm_unlock();
49         DBG("DEBUG: free_cell: done\n");
50 }
51
52
53
54
55 /* Release all the data contained by the hash table. All the aux. structures
56   *  as sems, lists, etc, are also released
57   */
58 void free_hash_table( struct s_table *hash_table )
59 {
60    struct cell* p_cell;
61    struct cell* tmp_cell;
62    int   i;
63
64    if (hash_table)
65    {
66       /* remove the data contained by each entry */
67       for( i = 0 ; i<TABLE_ENTRIES; i++)
68       {
69          release_entry_lock( (hash_table->entrys)+i );
70          /* delete all synonyms at hash-collision-slot i */
71          for( p_cell = hash_table->entrys[i].first_cell; p_cell; p_cell = tmp_cell )
72          {
73             tmp_cell = p_cell->next_cell;
74             free_cell( p_cell );
75          }
76       }
77
78       /* the mutexs for sync the lists are released*/
79       for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
80          release_timerlist_lock( &(hash_table->timers[i]) );
81
82       sh_free( hash_table );
83    }
84 }
85
86
87
88
89 /*
90   */
91 struct s_table* init_hash_table()
92 {
93    struct s_table*  hash_table;
94    pthread_t  thread;
95    int       i;
96
97    /*allocs the table*/
98    hash_table = (struct s_table*)sh_malloc( sizeof( struct s_table ) );
99    if ( !hash_table )
100       goto error;
101
102    memset( hash_table, 0, sizeof (struct s_table ) );
103
104    /* try first allocating all the structures needed for syncing */
105    if (lock_initialize()==-1)
106      goto error;
107
108    /* inits the entrys */
109    for(  i=0 ; i<TABLE_ENTRIES; i++ )
110       init_entry_lock( hash_table , (hash_table->entrys)+i );
111
112    /* inits the timers*/
113    for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
114       init_timer_list( hash_table, i );
115
116    return  hash_table;
117
118 error:
119    free_hash_table( hash_table );
120    lock_cleanup();
121    return 0;
122 }
123
124
125
126 struct cell*  build_cell( struct sip_msg* p_msg )
127 {
128    struct cell*  new_cell;
129    int                i;
130
131     DBG("DEBUG: build_cell : start\n");
132     /* do we have the source for the build process? */
133    if (!p_msg)
134       return NULL;
135
136    /* allocs a new cell */
137    new_cell = (struct cell*)sh_malloc( sizeof( struct cell ) );
138    DBG("DEBUG: build_cell : malloc done\n");
139    if  ( !new_cell )
140       return NULL;
141
142    /* filling with 0 */
143    memset( new_cell, 0, sizeof( struct cell ) );
144    /* hash index of the entry */
145    new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number );
146    /* mutex */
147    /* ref counter is 0 */
148    /* all pointers from timers list tl are NULL */
149    new_cell->wait_tl.payload = new_cell;
150    new_cell->dele_tl.payload = new_cell;
151
152    new_cell->inbound_request =  sip_msg_cloner(p_msg) ;
153    DBG("DEBUG: build_cell : clone done\n");
154    if (!new_cell->inbound_request)
155         goto error;
156    /* inbound response is NULL*/
157    /* status is 0 */
158    /* tag pointer is NULL */
159    //if ( p_msg->tag )      TO DO !!!!!!!!!!!!!!!!!!!!!!
160    //   new_cell->tag  =  &(new_cell->inbound_request->tag->body);
161    /* nr of outbound requests is 0 */
162    /* all pointers from outbound_request array are NULL */
163    /* all pointers from outbound_response array are NULL */
164    /*init the links with the canceled / canceler transaction */
165    new_cell->relaied_reply_branch   = -1;
166    new_cell->T_canceled = T_UNDEFINED;
167
168    /* init_cell_lock(  new_cell ); */
169
170    DBG("DEBUG: build_cell : done\n");
171    return new_cell;
172
173 error:
174         sh_free(new_cell);
175         return NULL;
176 }
177
178
179
180
181 /*  Takes an already created cell and links it into hash table on the
182   *  appropiate entry.
183   */
184 void    insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
185 {
186    struct entry* p_entry;
187
188    /* do we have or not something to insert? */
189    if (!p_cell)
190       return;
191
192    /* locates the apropiate entry */
193    p_entry = &hash_table->entrys[ p_cell->hash_index ];
194
195    /* critical region - inserting the cell at the end of the list */
196    lock( p_entry->mutex );
197
198    p_cell->label = p_entry->next_label++;
199    if ( p_entry->last_cell )
200    {
201       p_entry->last_cell->next_cell = p_cell;
202       p_cell->prev_cell = p_entry->last_cell;
203    }
204    else
205       p_entry->first_cell = p_cell;
206    p_entry->last_cell = p_cell;
207
208    unlock( p_entry->mutex );
209 }
210
211
212
213
214 /*  Un-link a  cell from hash_table, but the cell itself is not released
215   */
216 void remove_from_hash_table( struct s_table *hash_table,  struct cell * p_cell )
217 {
218    struct entry*  p_entry  = &(hash_table->entrys[p_cell->hash_index]);
219
220    /* unlink the cell from entry list */
221    lock( p_entry->mutex );
222
223    if ( p_cell->prev_cell )
224       p_cell->prev_cell->next_cell = p_cell->next_cell;
225    else
226       p_entry->first_cell = p_cell->next_cell;
227
228    if ( p_cell->next_cell )
229       p_cell->next_cell->prev_cell = p_cell->prev_cell;
230    else
231       p_entry->last_cell = p_cell->prev_cell;
232
233    unlock( p_entry->mutex );
234 }
235
236
237
238
239
240