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