306 lines
7.6 KiB
C
Executable File
306 lines
7.6 KiB
C
Executable File
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifdef UNIT_TEST
|
|
#define cpr_malloc malloc
|
|
#define cpr_free free
|
|
#define CCAPP_DEBUG printf
|
|
#else
|
|
#include "cpr_stdlib.h"
|
|
#endif
|
|
|
|
#include "sessionHash.h"
|
|
|
|
#define HASHBUCKETS 67
|
|
|
|
hash_table_t *hashtable[HASHBUCKETS]={0};
|
|
|
|
void hashItrInit(hashItr_t *itr)
|
|
{
|
|
itr->bucket = 0;
|
|
itr->node = NULL;
|
|
}
|
|
|
|
void * hashItrNext(hashItr_t *itr)
|
|
{
|
|
int i;
|
|
|
|
if ( itr->node != NULL ) {
|
|
if ( itr->node->next != NULL ) {
|
|
itr->node = itr->node->next;
|
|
return itr->node->data;
|
|
}
|
|
// We just iterated to the end of the list.
|
|
// Increment the bucket to search next
|
|
itr->bucket++;
|
|
}
|
|
|
|
for(i=itr->bucket; i< HASHBUCKETS; i++) {
|
|
if (hashtable[i] != NULL) {
|
|
itr->bucket = i;
|
|
itr->node = hashtable[i];
|
|
return itr->node->data;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* sessionHash
|
|
* function to add generate hash given the key
|
|
*
|
|
* @param key -
|
|
*
|
|
* @return the hash index
|
|
*/
|
|
unsigned int sessionHash (unsigned int key)
|
|
{
|
|
// since the key is session_id create the hashval to be line_id + call_id
|
|
unsigned int hashval = key + ((key & 0xFFFF0000)>>16);
|
|
|
|
return hashval%67;
|
|
}
|
|
|
|
/**
|
|
* addhash
|
|
* function to add data for a given key in the table
|
|
*
|
|
* @param key
|
|
* @param data - pointer to data stored
|
|
*
|
|
* @return - 0 for success
|
|
*/
|
|
|
|
int addhash (unsigned int key, void *data)
|
|
{
|
|
hash_table_t *newhash;
|
|
hash_table_t *cur_hash;
|
|
unsigned int hashval;
|
|
|
|
newhash = (hash_table_t *)(cpr_malloc(sizeof(hash_table_t)));
|
|
if (newhash == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
newhash->key = key;
|
|
|
|
newhash->data = data;
|
|
|
|
hashval = sessionHash(key);
|
|
|
|
if (hashtable[hashval] == NULL) {
|
|
hashtable[hashval] = newhash;
|
|
hashtable[hashval]->prev = NULL;
|
|
hashtable[hashval]->next = NULL;
|
|
}
|
|
else {
|
|
cur_hash=hashtable[hashval];
|
|
while(cur_hash->next != NULL) {
|
|
cur_hash=cur_hash->next;
|
|
}
|
|
cur_hash->next = newhash;
|
|
newhash->next = NULL;
|
|
newhash->prev = cur_hash;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* returns the session id given a callid
|
|
* @param call_id
|
|
* @return sessionID or 0
|
|
*/
|
|
|
|
unsigned int ccpro_get_sessionId_by_callid(unsigned short call_id) {
|
|
int i;
|
|
hash_table_t *cur_hash;
|
|
|
|
for ( i=0; i<HASHBUCKETS ;i++){
|
|
cur_hash = hashtable[i];
|
|
while ( cur_hash) {
|
|
if ( (cur_hash->key & 0xffff) == call_id ) {
|
|
return cur_hash->key;
|
|
}
|
|
cur_hash = cur_hash->next;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* findhash
|
|
* function retrieve the data for the given key
|
|
*
|
|
* @param key
|
|
*
|
|
* @return the data ptr or NULL
|
|
*/
|
|
|
|
void *findhash(unsigned int key)
|
|
{
|
|
unsigned int hashval;
|
|
hash_table_t *cur_hash;
|
|
|
|
hashval = 0;
|
|
|
|
hashval = sessionHash(key);
|
|
|
|
|
|
cur_hash = hashtable[hashval];
|
|
while ( cur_hash != NULL ) {
|
|
if ( cur_hash->key == key) {
|
|
return cur_hash->data;
|
|
}
|
|
cur_hash = cur_hash->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* delhash
|
|
* function to remove the hash entry for a given key
|
|
*
|
|
* @param key
|
|
*
|
|
* @return - 0 for success
|
|
*/
|
|
|
|
int delhash(unsigned int key)
|
|
{
|
|
unsigned int hashval;
|
|
hash_table_t *cur_hash;
|
|
|
|
hashval = 0;
|
|
|
|
hashval = sessionHash(key);
|
|
|
|
|
|
if (hashtable[hashval] == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (hashtable[hashval]->key == key) {
|
|
cur_hash = hashtable[hashval];
|
|
hashtable[hashval] = cur_hash->next;
|
|
if ( hashtable[hashval] != NULL ) {
|
|
hashtable[hashval]->prev = NULL;
|
|
}
|
|
cpr_free(cur_hash);
|
|
return 0;
|
|
}
|
|
else {
|
|
|
|
cur_hash = hashtable[hashval]->next;
|
|
|
|
while (cur_hash != NULL) {
|
|
if (cur_hash->key == key) {
|
|
cur_hash->prev->next = cur_hash->next;
|
|
if (cur_hash->next != NULL) {
|
|
cur_hash->next->prev = cur_hash->prev;
|
|
}
|
|
cpr_free(cur_hash);
|
|
return 0;
|
|
}
|
|
cur_hash = cur_hash->next;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#ifdef UNIT_TEST
|
|
|
|
void hashstats(int detail)
|
|
{
|
|
static const char *fname="hashstats";
|
|
int max, total, i, nodes, used;
|
|
double avg;
|
|
hash_table_t *cur_hash;
|
|
|
|
max = total = i = nodes = used = 0;
|
|
avg = 0;
|
|
|
|
if (detail > 0) {
|
|
for (i = 0; i < HASHBUCKETS; i++) {
|
|
if (hashtable[i] != NULL) {
|
|
used++;
|
|
nodes = 0;
|
|
cur_hash = hashtable[i];
|
|
while(cur_hash != NULL) {
|
|
nodes++;
|
|
if (detail > 3) {
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx -> %lx: (%lx) (%lx) -> %lx\n",
|
|
DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname),
|
|
cur_hash->prev, cur_hash, cur_hash->key, cur_hash->data, cur_hash->next);
|
|
}
|
|
cur_hash = cur_hash->next;
|
|
}
|
|
if (nodes != 0) total += nodes;
|
|
if (nodes > max) {
|
|
max = nodes;
|
|
}
|
|
if (detail > 1) {
|
|
CCAPPDEBUG(DEB_F_PREFIX"i: %d\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), i);
|
|
}
|
|
}
|
|
}
|
|
avg = (double)(total) / (double)(used);
|
|
CCAPPDEBUG(DEB_F_PREFIX"total: %d\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), total);
|
|
CCAPPDEBUG(DEB_F_PREFIX"max: %d\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), max);
|
|
CCAPPDEBUG(DEB_F_PREFIX"used: %lf\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), 100 * ((double)(used) / (double)(HASHBUCKETS)));
|
|
CCAPPDEBUG(DEB_F_PREFIX"average: %lf\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), avg);
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
static const char *fname="main";
|
|
hashItr_t itr;
|
|
void * data;
|
|
|
|
addhash(0x01010001,0x1234);
|
|
addhash(0x01060001,0x4567);
|
|
addhash(0x01060002,0x9324);
|
|
addhash(0x01070002,0x4321);
|
|
addhash(0x01070004,0x2134);
|
|
addhash(0x01080005,0x1324);
|
|
addhash(0x01030001,0x1243);
|
|
hashstats(7);
|
|
|
|
hashItrInit(&itr);
|
|
while ( data = hashItrNext(&itr) ) {
|
|
CCAPPDEBUG(DEB_F_PREFIX"Itr found %lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), data);
|
|
}
|
|
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01010001));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01060001));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01060002));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01070002));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01070004));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01080005));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01030001));
|
|
|
|
delhash(0x01030001);
|
|
delhash(0x01060001);
|
|
hashstats(7);
|
|
|
|
hashItrInit(&itr);
|
|
while ( data = hashItrNext(&itr) ) {
|
|
CCAPPDEBUG(DEB_F_PREFIX"Itr found %lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HAS, fname), data);
|
|
}
|
|
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01010001));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01060001));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01060002));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01070002));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01070004));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01080005));
|
|
CCAPPDEBUG(DEB_F_PREFIX"%lx\n", DEB_F_PREFIX_ARGS(SIP_SES_HASH, fname), findhash(0x01030001));
|
|
}
|
|
#endif
|
|
|