changeset 778:003df4a9ade2

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
author Sebastien Decugis <sdecugis@nict.go.jp>
date Sat, 21 Jan 2012 16:11:34 +0100
parents cfc714065cb8
children 867156be8353
files include/freeDiameter/libfdproto.h libfdproto/dictionary.c libfdproto/sessions.c tests/testdict.c tests/testsess.c
diffstat 5 files changed, 115 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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                            */
 /*============================================================*/
--- 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; i<NB_LISTS_PER_OBJ; i++) {
+		if (!_OBINFO(obj).haslist[i] && !(FD_IS_LIST_EMPTY(&obj->list[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;
--- 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;
+}
--- 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();
 } 
--- 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 */
 	{
"Welcome to our mercurial repository"