# HG changeset patch # User Sebastien Decugis # Date 1327158694 -3600 # Node ID 003df4a9ade2550b21d36519177f1e9c466f2a52 # Parent cfc714065cb8ed5aa538e3d7700e2f2679018b08 Added two new interfaces on Zach requests http://lists.freediameter.net/pipermail/help/2012-January/000312.html and http://lists.freediameter.net/pipermail/help/2012-January/000311.html diff -r cfc714065cb8 -r 003df4a9ade2 include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Tue Nov 22 16:37:40 2011 -0800 +++ b/include/freeDiameter/libfdproto.h Sat Jan 21 16:11:34 2012 +0100 @@ -850,6 +850,10 @@ /* Function to access full contents of the dictionary, see doc in dictionary.c */ int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel); +/* Function to remove an entry from the dictionary. + This cannot be used if the object has children (for example a vendor with vendor-specific AVPs). + In such case, the children must be removed first. */ +int fd_dict_delete(struct dict_object * obj); /* *************************************************************************** @@ -1859,6 +1863,9 @@ void fd_sess_dump(int level, struct session * session); void fd_sess_dump_hdl(int level, struct session_handler * handler); +/* For statistics / monitoring: get the number of struct session in memory */ +int fd_sess_getcount(uint32_t *cnt); + /*============================================================*/ /* ROUTING */ /*============================================================*/ diff -r cfc714065cb8 -r 003df4a9ade2 libfdproto/dictionary.c --- a/libfdproto/dictionary.c Tue Nov 22 16:37:40 2011 -0800 +++ b/libfdproto/dictionary.c Sat Jan 21 16:11:34 2012 +0100 @@ -1811,6 +1811,44 @@ return ret; } + +int fd_dict_delete(struct dict_object * obj) +{ + int i; + struct dictionary * dict; + int ret=0; + + /* check params */ + CHECK_PARAMS( verify_object(obj) && obj->dico); + dict = obj->dico; + + /* Lock the dictionary for change */ + CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) ); + + /* check the object is not sentinel for another list */ + for (i=0; ilist[i]))) { + /* There are children, this is not good */ + ret = EINVAL; + TRACE_DEBUG (FULL, "Cannot delete object, list %d not empty:", i); + #if 0 + dump_list(&obj->list[i], 0,0,0); + #endif + break; + } + } + + /* ok, now destroy the object */ + if (!ret) + destroy_object(obj); + + /* Unlock */ + CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); + + return ret; +} + + int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, void * what, struct dict_object **result, int retval ) { int ret = 0; diff -r cfc714065cb8 -r 003df4a9ade2 libfdproto/sessions.c --- a/libfdproto/sessions.c Tue Nov 22 16:37:40 2011 -0800 +++ b/libfdproto/sessions.c Sat Jan 21 16:11:34 2012 +0100 @@ -114,6 +114,8 @@ #define H_LIST( _hash ) (&(sess_hash[H_MASK(_hash)].sentinel)) #define H_LOCK( _hash ) (&(sess_hash[H_MASK(_hash)].lock )) +static uint32_t sess_cnt = 0; /* counts all active session (that are in the expiry list) */ + /* The following are used to generate sid values that are eternaly unique */ static uint32_t sid_h; /* initialized to the current time in fd_sess_init */ static uint32_t sid_l; /* incremented each time a session id is created */ @@ -484,6 +486,7 @@ break; } fd_list_insert_after( li, &sess->expire ); + sess_cnt++; /* We added a new expiring element, we must signal */ if (li == &exp_sentinel) { @@ -611,7 +614,10 @@ /* Unlink from the expiry list */ CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); - fd_list_unlink( &sess->expire ); /* no need to signal the condition here */ + if (!FD_IS_LIST_EMPTY(&sess->expire)) { + sess_cnt--; + fd_list_unlink( &sess->expire ); /* no need to signal the condition here */ + } CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } ); /* Now move all states associated to this session into deleted_states */ @@ -889,3 +895,12 @@ } fd_log_debug("\t %*s -- end of handler @%p --\n", level, "", handler); } + +int fd_sess_getcount(uint32_t *cnt) +{ + CHECK_PARAMS(cnt); + CHECK_POSIX( pthread_mutex_lock( &exp_lock ) ); + *cnt = sess_cnt; + CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) ); + return 0; +} diff -r cfc714065cb8 -r 003df4a9ade2 tests/testdict.c --- a/tests/testdict.c Tue Nov 22 16:37:40 2011 -0800 +++ b/tests/testdict.c Sat Jan 21 16:11:34 2012 +0100 @@ -165,6 +165,44 @@ } } + /* Test delete function */ + { + struct fd_list * li = NULL; + struct fd_list * sentinel = NULL; + struct dict_object * obj=NULL; + vendor_id_t vid = 0; + int count = 0, cntbkp; + + CHECK( 0, fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vid, &obj, ENOENT) ); + + CHECK( EINVAL, fd_dict_delete(obj) ); + + + CHECK( 0, fd_dict_getlistof(AVP_BY_NAME, obj, &sentinel)); + obj = NULL; + + for (li = sentinel->next; li != sentinel; li = li->next) { + struct dict_avp_data data; + CHECK( 0, fd_dict_getval(li->o, &data) ); + count++; + if (data.avp_basetype != AVP_TYPE_GROUPED) + obj = li->o; + } + + CHECK(1, obj ? 1 : 0 ); +#if 1 + fd_dict_dump_object(obj); +#endif + CHECK( 0, fd_dict_delete(obj) ); + cntbkp = count; + count = 0; + for (li = sentinel->next; li != sentinel; li = li->next) { + count++; + } + CHECK( 1, cntbkp - count ); + + } + /* That's all for the tests yet */ PASSTEST(); } diff -r cfc714065cb8 -r 003df4a9ade2 tests/testsess.c --- a/tests/testsess.c Tue Nov 22 16:37:40 2011 -0800 +++ b/tests/testsess.c Sat Jan 21 16:11:34 2012 +0100 @@ -173,6 +173,22 @@ CHECK( 0, fd_sess_destroy( &sess2 ) ); CHECK( 0, fd_sess_destroy( &sess1 ) ); } + + /* Test fd_sess_getcount */ + { + uint32_t cnt; + CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) ); + CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) ); + CHECK( 0, fd_sess_getcount(&cnt)); + CHECK( 2, cnt); + CHECK( 0, fd_sess_destroy( &sess2 ) ); + CHECK( 0, fd_sess_getcount(&cnt)); + CHECK( 1, cnt); + CHECK( 0, fd_sess_destroy( &sess1 ) ); + CHECK( 0, fd_sess_getcount(&cnt)); + CHECK( 0, cnt); + + } /* Test fd_sess_fromsid */ {