Browse Source

refurbished version of the hash table functions; added support
for variable number of timer lists

Jiri Kuthan 24 years ago
parent
commit
d214be66a7

+ 6 - 0
modules/tm/table/globals.h

@@ -0,0 +1,6 @@
+#ifndef _H_GLOBALS
+#define _H_GLOBALS
+
+extern int table_entries;
+
+#endif

+ 51 - 61
modules/tm/table/h_table.c

@@ -1,8 +1,6 @@
 #include "h_table.h"
 
-#include "hash_func.c"
-#include "semaphore.c"
-#include "timer.c"
+int table_entries;
 
 
 void free_cell( struct cell* dead_cell )
@@ -21,38 +19,39 @@ void free_cell( struct cell* dead_cell )
 }
 
 
-void free_hash_table( table hash_table )
+void free_hash_table( struct s_table *hash_table )
 {
    struct cell* p_cell;
+   struct cell* tmp_cell;
    int   i;
 
    if (hash_table)
    {
       if ( hash_table->entrys )
       {
-         for( i = 0 ; i<TABLE_ENTRYS ; i++)
+
+	 /* remove the hash table entry by entry */
+         for( i = 0 ; i<table_entries; i++)
           {
              remove_sem( hash_table->entrys[i].sem );
-             p_cell = hash_table->entrys[i].first_cell;
-             while( p_cell )
-              {
-                 /* free the cell*/
-                 free_cell( p_cell );
-                 p_cell = p_cell->next_cell;
+	     /* delete all synonyms at hash-collision-slot i */
+	     for( p_cell = hash_table->entrys[i].first_cell; p_cell; p_cell = tmp_cell )
+	     {
+		tmp_cell = p_cell->next_cell;
+                free_cell( p_cell );
               }
           }
           sh_free( hash_table->entrys );
       }
-      if ( hash_table->first_del_hooker )
-      {
-         p_cell = hash_table->first_del_hooker;
-         while (p_cell)
-         {
-            /*free the cell */
-            free_cell( p_cell );
-            p_cell = p_cell->timer_next_cell;
-         }
-      }
+
+	/* delete all cells on the to-be-deleted list */
+       for( p_cell = hash_table->timers[DELETE_LIST].first_cell; p_cell; p_cell = tmp_cell )
+        {
+                tmp_cell = p_cell->tl[DELETE_LIST].timer_next_cell;
+                remove_timer_from_head( hash_table, p_cell, DELETE_LIST );
+                free_cell( p_cell );
+       }
+	
       if ( hash_table->timers)
       {
          sh_free( hash_table->timers );
@@ -63,7 +62,7 @@ void free_hash_table( table hash_table )
 
 
 
-table  init_hash_table()
+struct s_table* init_hash_table()
 {
    struct s_table*  hash_table;
    int       i;
@@ -80,7 +79,8 @@ table  init_hash_table()
    hash_table->time = 0;
 
    /* allocs the entry's table */
-    hash_table->entrys  = sh_malloc( TABLE_ENTRYS * sizeof( struct entry )  );
+    table_entries = TABLE_ENTRIES;
+    hash_table->entrys  = sh_malloc( table_entries * sizeof( struct entry )  );
     if ( !hash_table->entrys )
     {
         free_hash_table( hash_table );
@@ -88,19 +88,15 @@ table  init_hash_table()
     }
 
    /* allocs the timer's table */
-    hash_table->timers  = sh_malloc( 2 * sizeof( struct timer )  );
+    hash_table->timers  = sh_malloc( NR_OF_TIMER_LISTS * sizeof( struct timer )  );
     if ( !hash_table->timers )
     {
         free_hash_table( hash_table );
        return 0;
     }
 
-    /* inits the deleted cells list*/
-    hash_table->first_del_hooker = 0;
-    hash_table->last_del_hooker = 0;
-
     /* inits the entrys */
-    for(  i=0 ; i<TABLE_ENTRYS ; i++ )
+    for(  i=0 ; i<table_entries; i++ )
     {
        hash_table->entrys[i].first_cell = 0;
        hash_table->entrys[i].last_cell = 0;
@@ -109,15 +105,17 @@ table  init_hash_table()
     }
 
    /* inits the timers*/
-    for(  i=0 ; i<2 ; i++ )
+    for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
     {
        hash_table->timers[i].first_cell = 0;
        hash_table->timers[i].last_cell = 0;
        hash_table->timers[i].sem = create_sem( SEM_KEY , 1 ) ;
     }
 
+#ifdef THREAD
    /* starts the timer thread/ process */
    pthread_create( &(hash_table->timer_thread_id), NULL, timer_routine, hash_table );
+#endif
 
    return  hash_table;
 }
@@ -125,14 +123,16 @@ table  init_hash_table()
 
 
 
-struct cell* add_Transaction( table hash_table, char* incoming_req_uri, char* from, char* to, char* tag, char* call_id, char* cseq_nr ,char* cseq_method )
+struct cell* add_Transaction( struct s_table* hash_table, 
+	char* incoming_req_uri, char* from, char* to, char* tag, 
+	char* call_id, char* cseq_nr ,char* cseq_method )
 {
    struct cell*    new_cell;
    struct entry* match_entry;
    char*              via_label;
    int                  hash_index;
 
-   hash_index   = hash( call_id , cseq_nr ) % TABLE_ENTRYS;
+   hash_index   = hash( call_id , cseq_nr );
    /*will it be faster to repolace  x % 256   with   x - (x>>8)<<8  ?  */
    match_entry = &hash_table->entrys[hash_index];
 
@@ -140,6 +140,11 @@ struct cell* add_Transaction( table hash_table, char* incoming_req_uri, char* fr
    if  ( !new_cell )
       return 0;
 
+   memset( new_cell, 0, sizeof( struct cell ) );
+
+   /* remember hash entry where the cell lives */
+   new_cell->hash_index = hash_index;
+
    //incoming_req_uri
    new_cell->incoming_req_uri_length = strlen( incoming_req_uri );
    new_cell->incoming_req_uri = sh_malloc( new_cell->incoming_req_uri_length+1 );
@@ -159,11 +164,6 @@ struct cell* add_Transaction( table hash_table, char* incoming_req_uri, char* fr
       new_cell->req_tag = sh_malloc( new_cell->req_tag_length+1 );
       strcpy( new_cell->req_tag , tag );
    }
-   else
-   {
-      new_cell->req_tag_length = 0;
-      new_cell->req_tag             = 0;
-   }
    //cseq_nr
    new_cell->cseq_nr_length = strlen( cseq_nr );
    new_cell->cseq_nr = sh_malloc( new_cell->cseq_nr_length+1 );
@@ -176,24 +176,10 @@ struct cell* add_Transaction( table hash_table, char* incoming_req_uri, char* fr
    new_cell->call_id_length = strlen( call_id );
    new_cell->call_id = sh_malloc( new_cell->call_id_length+1 );
    strcpy( new_cell->call_id , call_id );
-   //outgoing_req_uri
-   new_cell->outgoing_req_uri = 0;
-   //res_tag
-   new_cell->res_tag_length = 0;
-   new_cell->res_tag             = 0;
    //status
-   new_cell->status = 100;
-   //ref_counter
-   new_cell->ref_counter =  0;
+   /* new_cell->status = 100; */
    //cell semaphore
    new_cell->sem = create_sem( SEM_KEY , 1 ) ;
-   //time_out
-   new_cell ->time_out          = 0;
-   new_cell->timer_prev_cell = 0;
-   new_cell->timer_next_cell = 0;
-   //next cell
-   new_cell -> next_cell = 0;
-   new_cell -> prev_cell = 0;
 
    // critical region - inserting the cell at the end of the list
    change_sem( match_entry->sem , -1  );
@@ -245,7 +231,8 @@ void unref_Cell( struct cell* p_cell)
  *  different than ACK -> perfect To matche is performed.
  *  WARNING : in case of a returned transaction, this transaction is NOT  unref !!!
  */
-struct cell* lookup_for_Transaction_by_req( table hash_table, char* from, char* to, char* tag, char* call_id , char* cseq_nr ,char* cseq_method )
+struct cell* lookup_for_Transaction_by_req( struct s_table* hash_table, char* from, 
+	char* to, char* tag, char* call_id , char* cseq_nr ,char* cseq_method )
 {
    struct cell*  p_cell;
    struct cell* tmp_cell;
@@ -253,7 +240,7 @@ struct cell* lookup_for_Transaction_by_req( table hash_table, char* from, char*
    int                call_id_len, from_len, to_len, tag_len, cseq_nr_len, cseq_method_len;
 
    /* The lenght of the fields that will be comp */
-   hash_index         = hash( call_id , cseq_nr ) % TABLE_ENTRYS;
+   hash_index         = hash( call_id , cseq_nr ) ;
    call_id_len           = strlen(call_id);
    from_len              = strlen(from);
    to_len                   = strlen(to);
@@ -294,7 +281,8 @@ struct cell* lookup_for_Transaction_by_req( table hash_table, char* from, char*
  *  is nor used, only standard search. Being a ACK, a special matching for the tag attr from To header is performed.
  *  WARNING : in case of a returned transaction, this transaction is NOT  unref !!!
  */
-struct cell* lookup_for_Transaction_by_ACK( table hash_table, char* from, char* to, char* tag, char* call_id, char* cseq_nr )
+struct cell* lookup_for_Transaction_by_ACK( struct s_table* hash_table, 
+	char* from, char* to, char* tag, char* call_id, char* cseq_nr )
 {
    struct cell*  p_cell;
    struct cell*  tmp_cell;
@@ -304,7 +292,7 @@ struct cell* lookup_for_Transaction_by_ACK( table hash_table, char* from, char*
    int                trans_tag_len;
 
    /* The lenght of the fields that will be comp */
-   hash_index         = hash( call_id , cseq_nr ) % TABLE_ENTRYS;
+   hash_index         = hash( call_id , cseq_nr ) ;
    call_id_len           = strlen(call_id);
    from_len              = strlen(from);
    to_len                   = strlen(to);
@@ -354,7 +342,8 @@ struct cell* lookup_for_Transaction_by_ACK( table hash_table, char* from, char*
  *  different than ACK -> perfect To match is performed.
  *  WARNING : in case of a returned transaction, this transaction is NOT  unref !!!
  */
-struct cell* lookup_for_Transaction_by_CANCEL( table hash_table,char *req_uri, char* from, char* to, char* tag, char* call_id, char* cseq_nr )
+struct cell* lookup_for_Transaction_by_CANCEL( struct s_table* hash_table,
+	char *req_uri, char* from, char* to, char* tag, char* call_id, char* cseq_nr )
 {
    struct cell*  p_cell;
    struct cell* tmp_cell;
@@ -362,7 +351,7 @@ struct cell* lookup_for_Transaction_by_CANCEL( table hash_table,char *req_uri, c
    int                req_uri_len, call_id_len, from_len, to_len, tag_len, cseq_nr_len;
 
    /* The lenght of the fields that will be comp */
-   hash_index         = hash( call_id , cseq_nr ) % TABLE_ENTRYS;
+   hash_index         = hash( call_id , cseq_nr ) ;
    req_uri_len          = strlen(req_uri);
    call_id_len           = strlen(call_id);
    from_len              = strlen(from);
@@ -403,7 +392,8 @@ struct cell* lookup_for_Transaction_by_CANCEL( table hash_table,char *req_uri, c
  *  request had a tag.
  *  WARNING : in case of a returned transaction, this transaction is NOT  unref !!!
  */
-struct cell* lookup_for_Transaction_by_res( table hash_table, char* label, char* from, char* to, char* tag, char* call_id, char* cseq_nr ,char* cseq_method )
+struct cell* lookup_for_Transaction_by_res( struct s_table* hash_table, char* label, 
+	char* from, char* to, char* tag, char* call_id, char* cseq_nr ,char* cseq_method )
 {
    struct cell*  p_cell;
    struct cell* tmp_cell;
@@ -422,7 +412,7 @@ struct cell* lookup_for_Transaction_by_res( table hash_table, char* label, char*
          hash_index = hash_index * 10 + (*p - '0')  ;
 
       //if the hash index is corect
-      if  ( p && p!=label && hash_index<TABLE_ENTRYS-1 )
+      if  ( p && p!=label && hash_index<table_entries-1 )
       {
          //looking for the entry label value
          for( tmp=++p ; p && *p>='0' && *p<='9' ; p++ )
@@ -453,7 +443,7 @@ struct cell* lookup_for_Transaction_by_res( table hash_table, char* label, char*
    }
 
    //the message doesnot containe a label  or  the label is incorect-> normal seq. search.
-   hash_index         = hash( call_id , cseq_nr ) % TABLE_ENTRYS;
+   hash_index         = hash( call_id , cseq_nr ) ;
    call_id_len           = strlen(call_id);
    from_len              = strlen(from);
    to_len                   = strlen(to);

+ 142 - 0
modules/tm/table/h_table.h

@@ -0,0 +1,142 @@
+#ifndef _H_TABLE_H
+#define _H_TABLE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef THREADS
+#include <pthread.h>
+#endif
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+struct s_table;
+struct timer;
+struct cell;
+
+#include "timer.h"
+
+#define sh_malloc( size )  malloc(size)
+#define sh_free( ptr )        free(ptr)
+
+#define TABLE_ENTRIES  256
+#define SEM_KEY            6688
+
+/* all you need to put a cell in a timer list:
+   links to neighbours and timer value
+*/
+struct timer_link 
+{
+	struct cell *timer_next_cell, *timer_prev_cell;
+	unsigned int time_out;
+} ;
+
+/* timer list: includes head, tail and protection semaphore */
+typedef struct  timer
+{
+   struct cell*    first_cell;
+   struct cell*    last_cell;
+   int                  sem;
+} timer_type;
+
+typedef struct cell
+{
+   /* linking data */
+   struct cell*     next_cell;
+   struct cell*     prev_cell;
+   /* tells in which hash table entry the cell lives */
+   int		    hash_index;
+   /* textual encoding of entry index in hash-table; 
+      used for looking up transactions for replies */
+   char*  via_label;
+   /* sequence number within hash collision slot; ascending
+      across the synonym list
+   */
+   int                   label;
+
+   /*sync data */
+   int      sem;
+   int      ref_counter;
+
+   /* bindings to all timer links in which a cell may be located */
+   struct timer_link tl[NR_OF_TIMER_LISTS];
+
+   /* usefull data */
+   int      status;
+   int      to_length;
+   int      req_tag_length;
+   int      res_tag_length;
+   int      from_length;
+   int      cseq_nr_length;
+   int      cseq_method_length;
+   int      call_id_length;
+   int      incoming_req_uri_length;
+   char*  to;
+   char*  req_tag;
+   char*  res_tag;
+   char*  from;
+   char*  cseq_nr;
+   char*  cseq_method;
+   char*  call_id;
+   char*  incoming_req_uri;
+   char*  outgoing_req_uri;
+}cell_type;
+
+
+/* double-linked list of cells with hash synonyms */
+typedef struct entry
+{
+   struct cell*  first_cell;
+   struct cell*  last_cell;
+   /* currently highest sequence number in a synonym list */
+   int                next_label;
+   /* semaphore */
+   int                sem;
+}entry_type;
+
+/* hash table */
+struct s_table
+{
+   /* table of hash entries; each of them is a list of synonyms  */
+   struct entry*   entrys; 
+   /* table of timer lists */
+   struct timer*   timers;
+   /* pointers to items which had ref-count>0 on the first
+      delete attempt -> garbage'm later
+   */
+/* delete-list put among other lists too;
+   struct cell*      first_del_hooker;
+   struct cell*      last_del_hooker;
+*/
+#ifdef THREADS
+   pthread_t         timer_thread_id;
+#endif
+   /* current time */ 
+   /* jku: who does set it ? */
+   unsigned int   time;
+};
+
+
+struct s_table* init_hash_table();
+void free_hash_table( struct s_table* hash_table );
+struct cell* add_Transaction( 
+	struct s_table* hash_table, char* incoming_req_uri, char* from, char* to, 
+	char* tag, char* call_id, char* cseq_nr ,char* cseq_method );
+struct cell* lookup_for_Transaction_by_req( 
+	struct s_table* hash_table, char* from, char* to, char* tag, 
+	char* call_id , char* cseq_nr ,char* cseq_method );
+struct cell* lookup_for_Transaction_by_ACK( 
+	struct s_table* hash_table, char* from, char* to, char* tag, 
+	char* call_id, char* cseq_nr );
+struct cell* lookup_for_Transaction_by_CANCEL( 
+	struct s_table* hash_table,char *req_uri, char* from, char* to, 
+	char* tag, char* call_id, char* cseq_nr );
+struct cell* lookup_for_Transaction_by_res( 
+	struct s_table* hash_table, char* label, char* from, char* to, 
+	char* tag, char* call_id, char* cseq_nr ,char* cseq_method );
+void unref_Cell( struct cell* p_cell);
+
+void free_cell( struct cell* dead_cell );
+
+
+#endif

+ 2 - 2
modules/tm/table/hash_func.c

@@ -1,4 +1,4 @@
-
+#include "hash_func.h"
 
 int hash( char* call_id , char* cseq_nr )
 {
@@ -10,6 +10,6 @@ int hash( char* call_id , char* cseq_nr )
     if ( cseq_nr )
       for( p=cseq_nr ; *p!=0 ; hash_code+=*p , p++ );
 
-   return hash_code ;
+   hash_code %= table_entries;
 }
 

+ 8 - 0
modules/tm/table/hash_func.h

@@ -0,0 +1,8 @@
+#ifndef _HASH_H
+#define _HASH_H
+
+#include "globals.h"
+
+int hash( char* call_id , char* cseq_nr );
+
+#endif

+ 3 - 0
modules/tm/table/main.c

@@ -0,0 +1,3 @@
+
+int main()
+{}

+ 1 - 5
modules/tm/table/semaphore.c

@@ -1,4 +1,4 @@
-
+#include "semaphore.h"
 
 int create_sem( key_t key , int val)
 {
@@ -36,7 +36,3 @@ int remove_sem( int id )
 {
    return  semctl( id , 0 , IPC_RMID , 0 ) ;
 }
-
-
-
-

+ 16 - 0
modules/tm/table/semaphore.h

@@ -0,0 +1,16 @@
+#ifndef _SEMAPHORE_H
+#define _SEMAPHORE_H
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+
+int create_sem( key_t key , int val);
+
+int change_sem( int id , int val );
+
+int remove_sem( int id );
+
+#endif
+

+ 163 - 168
modules/tm/table/timer.c

@@ -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 */

+ 28 - 0
modules/tm/table/timer.h

@@ -0,0 +1,28 @@
+#ifndef _TIMER_H
+#define _TIMER_H
+
+enum { FR_TIMER_LIST, WT_TIMER_LIST, DELETE_LIST, NR_OF_TIMER_LISTS };
+
+#include "h_table.h"
+
+/* FINAL_RESPONSE_TIMER ... tells how long should the transaction engine
+   wait if no final response comes back
+*/
+#define FR_TIME_OUT     16
+/* WAIT timer ... tells how long state should persist in memory after
+   a transaction was finalized
+*/
+#define WT_TIME_OUT      32
+
+void put_in_tail_of_timer_list( struct s_table* hash_table, struct cell* p_cell,
+                  int list_id, unsigned int time_out );
+void remove_timer( struct s_table* hash_table, struct cell* p_cell,
+                  int list_id);
+void remove_from_hash_table( struct s_table *hash_table,  struct cell * p_cell );
+void remove_timer_from_head( struct s_table* hash_table, struct cell* p_cell, int list_id );
+void del_Transaction( struct s_table *hash_table , struct cell * p_cell );
+void start_FR_timer( struct s_table* hash_table, struct cell* p_cell );
+void start_WT_timer( struct s_table* hash_table, struct cell* p_cell );
+void * timer_routine(void * attr);
+
+#endif