- 'template-ized' the hash table mechanism so that it can be used by others as well (until now, only for sip transactions).

- moved the transaction table and related items into trans_table.{h,cpp}.
sayer/1.4-spce2.6
Raphael Coeffic 16 years ago
parent 2cb7cb0ab1
commit b8444a196e

@ -30,8 +30,8 @@
#define _hash_table_h
#include "cstring.h"
#include <pthread.h>
#include "../AmThread.h"
#include "../log.h"
#include <list>
using std::list;
@ -40,104 +40,115 @@ struct sip_trans;
struct sip_msg;
#define H_TABLE_POWER 10
#define H_TABLE_ENTRIES (1<<H_TABLE_POWER)
class trans_bucket
template<class Value>
class ht_bucket: public AmMutex
{
public:
typedef list<sip_trans*> trans_list;
typedef list<Value*> value_list;
private:
unsigned long id;
pthread_mutex_t m;
trans_list elmts;
ht_bucket(unsigned long id) : id(id) {}
~ht_bucket() {}
/**
* Finds a transaction ptr in this bucket.
* This is used to check if the transaction
* still exists.
*
* @return iterator pointing at the transaction.
* Caution: The bucket MUST be locked before you can
* do anything with it.
*/
trans_list::iterator find_trans(sip_trans* t);
sip_trans* match_200_ack(sip_trans* t,sip_msg* msg);
sip_trans* match_1xx_prack(sip_trans* t,sip_msg* msg);
public:
/**
* Kept public to allow for static construction.
* !!! DO CREATE ANY BUCKETS ON YOUR OWN !!!
* Searches for the value ptr in this bucket.
* This is used to check if the value
* still exists.
*
* @return true if the value still exists.
*/
trans_bucket();
~trans_bucket();
bool exist(Value* t) {
return find(t) != elmts.end();
}
/**
* The bucket MUST be locked before you can
* do anything with it.
* Remove the value from this bucket,
* if it was still present.
*/
void lock();
void remove(Value* t) {
typename value_list::iterator it = find(t);
if(it != elmts.end()){
elmts.erase(it);
delete t;
DBG("~sip_trans()\n");
}
}
/**
* Unlocks the bucket after work has been done.
* Returns the bucket id, which should be an index
* into the corresponding hash table.
*/
void unlock();
// Match a request to UAS transactions
// in this bucket
sip_trans* match_request(sip_msg* msg);
// Match a reply to UAC transactions
// in this bucket
sip_trans* match_reply(sip_msg* msg);
unsigned long get_id() const {
return id;
}
sip_trans* add_trans(sip_msg* msg, int ttype);
// debug method
void dump() const {
if(elmts.empty())
return;
DBG("*** Bucket ID: %i ***\n",(int)get_id());
for(typename value_list::const_iterator it = elmts.begin(); it != elmts.end(); ++it) {
(*it)->dump();
}
}
protected:
/**
* Searches for a transaction ptr in this bucket.
* Finds a transaction ptr in this bucket.
* This is used to check if the transaction
* still exists.
*
* @return true if the transaction still exists.
* @return iterator pointing at the value.
*/
bool exist(sip_trans* t);
/**
* Remove a transaction from this bucket,
* if it was still present.
*/
void remove_trans(sip_trans* t);
unsigned long get_id() {
return id;
typename value_list::iterator find(Value* t)
{
typename value_list::iterator it = elmts.begin();
for(;it!=elmts.end();++it)
if(*it == t)
break;
return it;
}
// debug method
void dump();
unsigned long id;
value_list elmts;
};
trans_bucket* get_trans_bucket(const cstring& callid, const cstring& cseq_num);
trans_bucket* get_trans_bucket(unsigned int h);
unsigned int hash(const cstring& ci, const cstring& cs);
template<class Bucket, unsigned long size>
class hash_table
{
Bucket* _table[size];
public:
hash_table() {
for(unsigned long i=0; i<size; i++)
_table[i] = new Bucket(i);
}
#define BRANCH_BUF_LEN 8
~hash_table() {
for(unsigned long i=0; i<size; i++)
delete _table[i];
}
void compute_branch(char* branch/*[BRANCH_BUF_LEN]*/,
const cstring& callid, const cstring& cseq);
Bucket* get_bucket(unsigned long hash) const {
return _table[hash % size];
}
#define SL_TOTAG_LEN BRANCH_BUF_LEN
Bucket* operator [](unsigned long hash) const {
return get_bucket(hash);
}
};
void compute_sl_to_tag(char* to_tag/*[SL_TOTAG_LEN]*/, sip_msg* msg);
void dumps_transactions();
#endif

@ -28,7 +28,7 @@
#include "sip_trans.h"
#include "sip_parser.h"
#include "wheeltimer.h"
#include "hash_table.h"
#include "trans_table.h"
#include "trans_layer.h"
#include "log.h"
@ -179,6 +179,12 @@ void sip_trans::reset_all_timers()
}
}
void sip_trans::dump() const
{
DBG("type=0x%x; msg=%p; to_tag=%.*s; reply_status=%i; state=%i; retr_buf=%p\n",
type,msg,to_tag.len,to_tag.s,reply_status,state,retr_buf);
}
/** EMACS **
* Local variables:
* mode: c++

@ -188,6 +188,8 @@ class sip_trans
sip_trans();
~sip_trans();
void dump() const;
};
#endif

@ -27,7 +27,7 @@
#include "trans_layer.h"
#include "sip_parser.h"
#include "hash_table.h"
#include "trans_table.h"
#include "parse_cseq.h"
#include "parse_from_to.h"
#include "parse_100rel.h"
@ -730,7 +730,7 @@ void trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
ua->handle_sip_reply(&msg);
bucket->remove_trans(t);
bucket->remove(t);
}
int trans_layer::send_request(sip_msg* msg, trans_ticket* tt)
@ -877,7 +877,7 @@ int trans_layer::cancel(trans_ticket* tt)
case TS_CALLING:
// do not send a request:
// just remove the transaction
bucket->remove_trans(t);
bucket->remove(t);
bucket->unlock();
return 0;
@ -1465,7 +1465,7 @@ int trans_layer::update_uas_request(trans_bucket* bucket, sip_trans* t, sip_msg*
case TS_TERMINATED_200:
// remove transaction
bucket->remove_trans(t);
bucket->remove(t);
return TS_REMOVED;
default:
@ -1610,7 +1610,7 @@ void trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
tr->clear_timer(type);
////ua->timer_expired(tr,STIMER_H);
ua->handle_reply_timeout(AmSipTimeoutEvent::noACK, tr);
bucket->remove_trans(tr);
bucket->remove(tr);
handled = true;
break;
@ -1633,7 +1633,7 @@ void trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
// else, send ACK & BYE.
tr->clear_timer(type);
bucket->remove_trans(tr);
bucket->remove(tr);
break;
case STIMER_E: // Trying/Proceeding: (re-)send request

@ -25,10 +25,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "hash_table.h"
#include "hash.h"
#include "AmSipHeaders.h"
#include "trans_table.h"
#include "sip_parser.h"
#include "parse_header.h"
#include "parse_cseq.h"
@ -36,43 +34,32 @@
#include "parse_from_to.h"
#include "parse_100rel.h"
#include "sip_trans.h"
#include "hash.h"
#include "log.h"
#include <sys/time.h>
#include <time.h>
#include <assert.h>
//
// Global transaction table
//
trans_bucket _trans_table[H_TABLE_ENTRIES];
//trans_bucket _trans_table[H_TABLE_ENTRIES];
hash_table<trans_bucket,H_TABLE_ENTRIES> _trans_table;
trans_bucket::trans_bucket()
trans_bucket::trans_bucket(unsigned long id)
: ht_bucket<sip_trans>::ht_bucket(id)
{
id = (unsigned long)(trans_bucket*)(this - _trans_table);
pthread_mutex_init(&m,NULL);
}
trans_bucket::~trans_bucket()
{
pthread_mutex_destroy(&m);
}
// trans_bucket::trans_bucket()
// : ht_bucket<sip_trans>::ht_bucket((unsigned long)this - (unsigned long)_trans_table)
// {
// }
void trans_bucket::lock()
{
pthread_mutex_lock(&m);
}
void trans_bucket::unlock()
trans_bucket::~trans_bucket()
{
pthread_mutex_unlock(&m);
}
sip_trans* trans_bucket::match_request(sip_msg* msg)
{
// assert(msg && msg->cseq && msg->callid);
@ -421,31 +408,6 @@ sip_trans* trans_bucket::add_trans(sip_msg* msg, int ttype)
return t;
}
trans_bucket::trans_list::iterator trans_bucket::find_trans(sip_trans* t)
{
trans_list::iterator it = elmts.begin();
for(;it!=elmts.end();++it)
if(*it == t)
break;
return it;
}
bool trans_bucket::exist(sip_trans* t)
{
return find_trans(t) != elmts.end();
}
void trans_bucket::remove_trans(sip_trans* t)
{
trans_list::iterator it = find_trans(t);
if(it != elmts.end()){
elmts.erase(it);
delete t;
DBG("~sip_trans()\n");
}
}
unsigned int hash(const cstring& ci, const cstring& cs)
{
@ -532,13 +494,13 @@ void compute_branch(char* branch/*[8]*/, const cstring& callid, const cstring& c
trans_bucket* get_trans_bucket(const cstring& callid, const cstring& cseq_num)
{
return &_trans_table[hash(callid,cseq_num)];
return /*&*/_trans_table[hash(callid,cseq_num)];
}
trans_bucket* get_trans_bucket(unsigned int h)
{
assert(h < H_TABLE_ENTRIES);
return &_trans_table[h];
return /*&*/_trans_table[h];
}
void dumps_transactions()
@ -553,20 +515,6 @@ void dumps_transactions()
}
}
void trans_bucket::dump()
{
if(elmts.empty())
return;
DBG("*** Bucket ID: %i ***\n",(int)get_id());
for(trans_list::iterator it = elmts.begin(); it != elmts.end(); ++it) {
DBG("type=0x%x; msg=%p; to_tag=%.*s; reply_status=%i; state=%i; retr_buf=%p\n",
(*it)->type,(*it)->msg,(*it)->to_tag.len,(*it)->to_tag.s,(*it)->reply_status,(*it)->state,(*it)->retr_buf);
}
}
/** EMACS **
* Local variables:

@ -0,0 +1,62 @@
#ifndef _trans_table_h_
#define _trans_table_h_
#include "hash_table.h"
#define H_TABLE_POWER 10
#define H_TABLE_ENTRIES (1<<H_TABLE_POWER)
class trans_bucket:
public ht_bucket<sip_trans>
{
public:
typedef ht_bucket<sip_trans>::value_list trans_list;
/**
* Kept public to allow for static construction.
* !!! DO CREATE ANY BUCKETS ON YOUR OWN !!!
*/
// trans_bucket();
trans_bucket(unsigned long id);
~trans_bucket();
// Match a request to UAS transactions
// in this bucket
sip_trans* match_request(sip_msg* msg);
// Match a reply to UAC transactions
// in this bucket
sip_trans* match_reply(sip_msg* msg);
sip_trans* add_trans(sip_msg* msg, int ttype);
// /**
// * Remove a transaction from this bucket,
// * if it was still present.
// */
// void remove_trans(sip_trans* t);
private:
sip_trans* match_200_ack(sip_trans* t,sip_msg* msg);
sip_trans* match_1xx_prack(sip_trans* t,sip_msg* msg);
};
trans_bucket* get_trans_bucket(const cstring& callid, const cstring& cseq_num);
trans_bucket* get_trans_bucket(unsigned int h);
unsigned int hash(const cstring& ci, const cstring& cs);
#define BRANCH_BUF_LEN 8
void compute_branch(char* branch/*[BRANCH_BUF_LEN]*/,
const cstring& callid, const cstring& cseq);
#define SL_TOTAG_LEN BRANCH_BUF_LEN
void compute_sl_to_tag(char* to_tag/*[SL_TOTAG_LEN]*/, sip_msg* msg);
void dumps_transactions();
#endif
Loading…
Cancel
Save