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