|
@@ -1,36 +1,98 @@
|
|
|
-void free_cell( struct cell* dead_cell );
|
|
|
+#include "timer.h"
|
|
|
+
|
|
|
+/* jku: currently, we add all timer items in the list's tail;
|
|
|
+ this works as long as timers have fixed values; this
|
|
|
+ will change with variable timers (e.g., such as those
|
|
|
+ generated by users of CPL scripts or different-size
|
|
|
+ retransmission timers); then some searching technique
|
|
|
+ would be good; perhaps binary starting from tail?
|
|
|
+*/
|
|
|
|
|
|
+/* put a new cell into a list nr. list_id within a hash_table;
|
|
|
+ set initial timeout
|
|
|
+*/
|
|
|
|
|
|
-/*
|
|
|
-* The cell is inserted at the end of the FINAL RESPONSE timer list.
|
|
|
-* The expire time is given by the current time plus the FINAL RESPONSE timeout - FR_TIME_OUT
|
|
|
+void put_in_tail_of_timer_list( struct s_table* hash_table, struct cell* p_cell,
|
|
|
+ int list_id, unsigned int time_out )
|
|
|
+{
|
|
|
+ struct timer* timer_list = &(hash_table->timers[ list_id ]);
|
|
|
+ struct timer_link* tl = &(p_cell->tl[ list_id ]);
|
|
|
+
|
|
|
+ /* the entire timer list is locked now -- noone else can
|
|
|
+ manipulate it */
|
|
|
+ change_sem( timer_list->sem , -1 );
|
|
|
+ tl->time_out = time_out;
|
|
|
+ if (timer_list->last_cell)
|
|
|
+ {
|
|
|
+ tl->timer_next_cell= 0;
|
|
|
+ tl->timer_prev_cell=timer_list->last_cell;
|
|
|
+ timer_list->last_cell->tl[list_id].timer_next_cell=p_cell;
|
|
|
+ timer_list->last_cell = p_cell;
|
|
|
+ } else {
|
|
|
+ tl->timer_prev_cell = 0;
|
|
|
+ tl->timer_next_cell = 0;
|
|
|
+ timer_list->first_cell = p_cell;
|
|
|
+ timer_list->last_cell = p_cell;
|
|
|
+ }
|
|
|
+ /* give the list lock away */
|
|
|
+ change_sem( timer_list->sem , -1 );
|
|
|
+}
|
|
|
+
|
|
|
+/* remove a cell from a list nr. list_id within a hash_table;
|
|
|
*/
|
|
|
-void start_FR_timer( table hash_table, struct cell* p_cell )
|
|
|
+
|
|
|
+void remove_timer( struct s_table* hash_table, struct cell* p_cell,
|
|
|
+ int list_id)
|
|
|
{
|
|
|
- struct timer* timers= hash_table->timers;
|
|
|
+ struct timer* timers=&(hash_table->timers[ list_id ]);
|
|
|
+ struct timer_link* tl = &(p_cell->tl[ list_id ]);
|
|
|
|
|
|
- /* adds the cell int FINAL RESPONSE timer list*/
|
|
|
- change_sem( timers[0].sem , -1 );
|
|
|
- p_cell -> time_out = FR_TIME_OUT + hash_table->time;
|
|
|
- if ( timers[0].last_cell )
|
|
|
- {
|
|
|
- p_cell -> timer_next_cell = 0;
|
|
|
- p_cell->timer_prev_cell = timers[0].last_cell;
|
|
|
- timers[0].last_cell->timer_next_cell = p_cell;
|
|
|
- timers[0].last_cell = p_cell;
|
|
|
- }
|
|
|
- else
|
|
|
+ if (tl->timer_next_cell || tl->timer_prev_cell ||
|
|
|
+ (!tl->timer_next_cell && !tl->timer_prev_cell &&
|
|
|
+ p_cell==timers->first_cell) )
|
|
|
{
|
|
|
- p_cell->timer_prev_cell = 0;
|
|
|
- p_cell->timer_next_cell = 0;
|
|
|
- timers[0].first_cell = p_cell;
|
|
|
- timers[0].last_cell = p_cell;
|
|
|
+
|
|
|
+ /* jku: shouldn't we decrease the reference counter here ??? */
|
|
|
+
|
|
|
+ change_sem( timers->sem , -1 );
|
|
|
+ if ( tl->timer_prev_cell )
|
|
|
+ tl->timer_prev_cell->tl[list_id].timer_next_cell = tl->timer_next_cell;
|
|
|
+ else
|
|
|
+ timers->first_cell = tl->timer_next_cell;
|
|
|
+ if ( tl->timer_next_cell )
|
|
|
+ tl->timer_next_cell->tl[list_id].timer_prev_cell = tl->timer_prev_cell;
|
|
|
+ else
|
|
|
+ timers->last_cell = tl->timer_prev_cell;
|
|
|
+ change_sem( timers[FR_TIMER_LIST].sem , +1 );
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- change_sem( timers[0].sem , +1 );
|
|
|
+void remove_timer_from_head( struct s_table* hash_table, struct cell* p_cell, int list_id )
|
|
|
+{
|
|
|
+ struct timer* timers=&(hash_table->timers[ list_id ]);
|
|
|
+ struct timer_link* tl = &(p_cell->tl[ list_id ]);
|
|
|
+ change_sem( timers->sem , -1 );
|
|
|
+ timers->first_cell = tl->timer_next_cell;
|
|
|
+ if (!timers->first_cell) timers->last_cell=0;
|
|
|
+ else tl->timer_next_cell->tl[list_id].timer_prev_cell = NULL;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+/*
|
|
|
+* The cell is inserted at the end of the FINAL RESPONSE timer list.
|
|
|
+* The expire time is given by the current time plus the FINAL
|
|
|
+ RESPONSE timeout - FR_TIME_OUT
|
|
|
+*/
|
|
|
+void start_FR_timer( struct s_table* hash_table, struct cell* p_cell )
|
|
|
+{
|
|
|
+
|
|
|
+ /* adds the cell int FINAL RESPONSE timer list*/
|
|
|
+ put_in_tail_of_timer_list( hash_table, p_cell, FR_TIMER_LIST, FR_TIME_OUT + hash_table->time );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
/*
|
|
|
* The cell is inserted at the end of the WAIT timer list. Before adding to the WT list, it's verify if the cell is
|
|
@@ -39,47 +101,33 @@ void start_FR_timer( table hash_table, struct cell* p_cell )
|
|
|
* The expire time is given by the current time plus the WAIT timeout - WT_TIME_OUT
|
|
|
*/
|
|
|
|
|
|
-void start_WT_timer( table hash_table, struct cell* p_cell )
|
|
|
+void start_WT_timer( struct s_table* hash_table, struct cell* p_cell )
|
|
|
{
|
|
|
- struct timer* timers= hash_table->timers;
|
|
|
+ struct timer* timers= hash_table->timers;
|
|
|
|
|
|
- //if is in FR list -> first it must be removed from there
|
|
|
- if ( p_cell->timer_next_cell || p_cell->timer_prev_cell || (!p_cell->timer_next_cell && !p_cell->timer_prev_cell && p_cell==timers[0].first_cell) )
|
|
|
- {
|
|
|
- change_sem( timers[0].sem , -1 );
|
|
|
- if ( p_cell->timer_prev_cell )
|
|
|
- p_cell->timer_prev_cell->timer_next_cell = p_cell->timer_next_cell;
|
|
|
- else
|
|
|
- timers[0].first_cell = p_cell->timer_next_cell;
|
|
|
- if ( p_cell->timer_next_cell )
|
|
|
- p_cell->timer_next_cell->timer_prev_cell = p_cell->timer_prev_cell;
|
|
|
- else
|
|
|
- timers[0].last_cell = p_cell->timer_prev_cell;
|
|
|
- change_sem( timers[0].sem , +1 );
|
|
|
- }
|
|
|
+ //if is in FR list -> first it must be removed from there
|
|
|
+ remove_timer( hash_table, p_cell, FR_TIMER_LIST );
|
|
|
|
|
|
- /* adds the cell int WAIT timer list*/
|
|
|
- change_sem( timers[1].sem , -1 );
|
|
|
- p_cell -> time_out = WT_TIME_OUT + hash_table->time;
|
|
|
- if ( timers[1].last_cell )
|
|
|
- {
|
|
|
- p_cell -> timer_next_cell = 0;
|
|
|
- p_cell ->timer_prev_cell = timers[1].last_cell;
|
|
|
- timers[1].last_cell->timer_next_cell = p_cell;
|
|
|
- timers[1].last_cell = p_cell;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- p_cell->timer_prev_cell = 0;
|
|
|
- p_cell->timer_next_cell = 0;
|
|
|
- timers[1].first_cell = p_cell;
|
|
|
- timers[1].last_cell = p_cell;
|
|
|
- }
|
|
|
-
|
|
|
- change_sem( timers[1].sem , +1 );
|
|
|
+ /* adds the cell int WAIT timer list*/
|
|
|
+ put_in_tail_of_timer_list( hash_table, p_cell, WT_TIMER_LIST, WT_TIME_OUT + hash_table->time );
|
|
|
}
|
|
|
|
|
|
|
|
|
+void remove_from_hash_table( struct s_table *hash_table, struct cell * p_cell )
|
|
|
+{
|
|
|
+ struct entry* p_entry = &(hash_table->entrys[p_cell->hash_index]);
|
|
|
+ change_sem( p_entry->sem , -1 );
|
|
|
+ if ( p_cell->prev_cell )
|
|
|
+ p_cell->prev_cell->next_cell = p_cell->next_cell;
|
|
|
+ else
|
|
|
+ p_entry->first_cell = p_cell->next_cell;
|
|
|
+ if ( p_cell->next_cell )
|
|
|
+ p_cell->next_cell->prev_cell = p_cell->prev_cell;
|
|
|
+ else
|
|
|
+ p_entry->last_cell = p_cell->prev_cell;
|
|
|
+ change_sem( p_entry->sem , +1 );
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -89,29 +137,12 @@ void start_WT_timer( table hash_table, struct cell* p_cell )
|
|
|
* (ref conter is 0) the cell is immediatly deleted. Otherwise it is put in a waitting list (del_hooker list) for
|
|
|
* future del. This list is veify by the the timer every sec and the cell that finaly have ref_counter 0 are del.
|
|
|
*/
|
|
|
-void del_Transaction( table hash_table , struct cell * p_cell )
|
|
|
+void del_Transaction( struct s_table *hash_table , struct cell * p_cell )
|
|
|
{
|
|
|
- int ref_counter = 0;
|
|
|
- int hash_index = 0;
|
|
|
- char* p = p_cell->via_label;
|
|
|
- struct entry* p_entry = 0 ;
|
|
|
-
|
|
|
- /* gets the entry number from the label */
|
|
|
- for( ; p && *p>='0' && *p<='9' ; p++ )
|
|
|
- hash_index = hash_index * 10 + (*p - '0') ;
|
|
|
- p_entry = &(hash_table->entrys[hash_index]);
|
|
|
+ int ref_counter = 0;
|
|
|
|
|
|
/* the cell is removed from the list */
|
|
|
- change_sem( p_entry->sem , -1 );
|
|
|
- if ( p_cell->prev_cell )
|
|
|
- p_cell->prev_cell->next_cell = p_cell->next_cell;
|
|
|
- else
|
|
|
- p_entry->first_cell = p_cell->next_cell;
|
|
|
- if ( p_cell->next_cell )
|
|
|
- p_cell->next_cell->prev_cell = p_cell->prev_cell;
|
|
|
- else
|
|
|
- p_entry->last_cell = p_cell->prev_cell;
|
|
|
- change_sem( p_entry->sem , +1 );
|
|
|
+ remove_from_hash_table( hash_table, p_cell );
|
|
|
|
|
|
/* gets the cell's ref counter*/
|
|
|
change_sem( p_cell->sem , -1 );
|
|
@@ -122,21 +153,7 @@ void del_Transaction( table hash_table , struct cell * p_cell )
|
|
|
if ( ref_counter==0 )
|
|
|
free_cell( p_cell );
|
|
|
/* else it's added to del hooker list for future del */
|
|
|
- else
|
|
|
- if ( hash_table->last_del_hooker )
|
|
|
- {
|
|
|
- p_cell -> timer_next_cell = 0;
|
|
|
- p_cell ->timer_prev_cell = hash_table->last_del_hooker;
|
|
|
- hash_table->last_del_hooker->timer_next_cell = p_cell;
|
|
|
- hash_table->last_del_hooker = p_cell;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- p_cell->timer_prev_cell = 0;
|
|
|
- p_cell->timer_next_cell = 0;
|
|
|
- hash_table->first_del_hooker = p_cell;
|
|
|
- hash_table->last_del_hooker = p_cell;
|
|
|
- }
|
|
|
+ else put_in_tail_of_timer_list( hash_table, p_cell, DELETE_LIST, 0 );
|
|
|
}
|
|
|
|
|
|
|
|
@@ -145,7 +162,7 @@ void del_Transaction( table hash_table , struct cell * p_cell )
|
|
|
|
|
|
void * timer_routine(void * attr)
|
|
|
{
|
|
|
- table hash_table = (table)attr;
|
|
|
+ struct s_table *hash_table = (struct s_table *)attr;
|
|
|
struct timer* timers= hash_table->timers;
|
|
|
struct timeval a_sec;
|
|
|
struct cell* p_cell;
|
|
@@ -162,82 +179,60 @@ void * timer_routine(void * attr)
|
|
|
printf("%d\n", *time);
|
|
|
|
|
|
|
|
|
- /* del hooker list */
|
|
|
- for( p_cell = hash_table->first_del_hooker ; p_cell ; p_cell = tmp_cell )
|
|
|
- {
|
|
|
- int ref_counter;
|
|
|
- /*gets the cell's ref counter*/
|
|
|
- change_sem( p_cell->sem , -1 );
|
|
|
- ref_counter = p_cell->ref_counter;
|
|
|
- change_sem( p_cell->sem , +1 );
|
|
|
- /*if the ref counter is 0 (nobody is reading the cell any more) -> remove from list and del*/
|
|
|
- if (ref_counter==0)
|
|
|
- {
|
|
|
- tmp_cell = p_cell->timer_next_cell;
|
|
|
- /*remove from the list*/
|
|
|
- if ( p_cell->timer_prev_cell )
|
|
|
- p_cell->timer_prev_cell->timer_next_cell = p_cell->timer_next_cell;
|
|
|
- else
|
|
|
- hash_table->first_del_hooker = p_cell->timer_next_cell;
|
|
|
- if ( p_cell->timer_next_cell )
|
|
|
- p_cell->timer_next_cell->timer_prev_cell = p_cell->timer_prev_cell;
|
|
|
- else
|
|
|
- hash_table->last_del_hooker = p_cell->timer_prev_cell;
|
|
|
- /* del the cell*/
|
|
|
- free_cell( p_cell );
|
|
|
- }
|
|
|
- else
|
|
|
- tmp_cell = p_cell->timer_next_cell;
|
|
|
-
|
|
|
+ /* del hooker list */
|
|
|
+
|
|
|
+ /* jku: can I traverse the list without syncing ? */
|
|
|
+ for( p_cell = hash_table->timers[DELETE_LIST].first_cell; p_cell; p_cell = tmp_cell )
|
|
|
+ {
|
|
|
+ int ref_counter;
|
|
|
+ /*gets the cell's ref counter*/
|
|
|
+ change_sem( p_cell->sem , -1 );
|
|
|
+ ref_counter = p_cell->ref_counter;
|
|
|
+ change_sem( p_cell->sem , +1 );
|
|
|
+
|
|
|
+ tmp_cell = p_cell->tl[DELETE_LIST].timer_next_cell;
|
|
|
+ /*if the ref counter is 0 (nobody is reading the cell any more) ->
|
|
|
+ remove from list and del*/
|
|
|
+ if (ref_counter==0)
|
|
|
+ {
|
|
|
+ remove_timer( hash_table, p_cell, DELETE_LIST );
|
|
|
+ free_cell( p_cell );
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- /* final response timer list*/
|
|
|
- for( p_cell = timers[0].first_cell ; p_cell ; p_cell=tmp_cell )
|
|
|
- /* if the time out expired -> send a 408 and move the trans in the WAIT timer queue */
|
|
|
- if ( (p_cell->time_out == *time) )
|
|
|
- {
|
|
|
- // TO DO - send r0 = 408
|
|
|
- printf("FR timeout !!!\n");
|
|
|
- /* next cell in FR list */
|
|
|
- tmp_cell = p_cell->timer_next_cell;
|
|
|
- /* and added to WT timer list */
|
|
|
- start_WT_timer( hash_table, p_cell );
|
|
|
- }
|
|
|
- /* the search stops - no further matched found*/
|
|
|
- else
|
|
|
- {
|
|
|
- tmp_cell = 0;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /* wait timer list */
|
|
|
- for( p_cell = timers[1].first_cell ; p_cell ; p_cell = tmp_cell )
|
|
|
- /* if the timeout expired - > release the tranzactin*/
|
|
|
- if ( p_cell->time_out == *time)
|
|
|
- {
|
|
|
- printf("WT timeout !!!\n");
|
|
|
- /* next cell in WT list */
|
|
|
- tmp_cell = p_cell->timer_next_cell;
|
|
|
- /* the cell is removed from the WT timer list */
|
|
|
- change_sem( timers[1].sem , -1 );
|
|
|
- timers[1].first_cell = p_cell->timer_next_cell;
|
|
|
- if ( !timers[1].first_cell ) timers[1].last_cell = 0;
|
|
|
- change_sem( timers[1].sem , +1 );
|
|
|
- /* release the trasaction*/
|
|
|
- del_Transaction( hash_table , p_cell );
|
|
|
- }
|
|
|
- /* the search stops - no further matched found*/
|
|
|
- else
|
|
|
- {
|
|
|
- tmp_cell = 0;
|
|
|
+ for( p_cell = hash_table->timers[FR_TIMER_LIST].first_cell; p_cell; p_cell = tmp_cell )
|
|
|
+ {
|
|
|
+ /* jku: list is time-ordered; if I "get in the future"
|
|
|
+ I can stop processing
|
|
|
+ */
|
|
|
+ if (p_cell->tl[FR_TIMER_LIST].time_out > *time) break;
|
|
|
+ /* otherwise the timer is due */
|
|
|
+ /* -> send a 408, remove the cell from FR_TIMER_LIST,
|
|
|
+ put it on WT_TIMER_LIST (transaction is over) */
|
|
|
+ printf("FR timeout !!!\n");
|
|
|
+ tmp_cell = p_cell->tl[FR_TIMER_LIST].timer_next_cell;
|
|
|
+ remove_timer_from_head( hash_table, p_cell, FR_TIMER_LIST );
|
|
|
+ start_WT_timer( hash_table, p_cell );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /* wait timer list */
|
|
|
+ for( p_cell = hash_table->timers[WT_TIMER_LIST].first_cell; p_cell; p_cell = tmp_cell )
|
|
|
+ {
|
|
|
+ /* jku: list is time-ordered; if I "get in the future"
|
|
|
+ I can stop processing
|
|
|
+ */
|
|
|
+ if (p_cell->tl[WT_TIMER_LIST].time_out > *time) break;
|
|
|
+ /* if the timeout expired - > release the tranzactin*/
|
|
|
+ printf("WT timeout !!!\n");
|
|
|
+ /* next cell in WT list */
|
|
|
+ tmp_cell = p_cell->tl[WT_TIMER_LIST].timer_next_cell;
|
|
|
+ /* jku: could be optimized here -- I'm sure to be at
|
|
|
+ list's head; simply call 'remove_from_head' */
|
|
|
+ remove_timer_from_head( hash_table, p_cell, WT_TIMER_LIST );
|
|
|
+ /* release the trasaction*/
|
|
|
+ del_Transaction( hash_table , p_cell );
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ } /* while (1) */
|
|
|
+} /* timer_routine */
|