changeset 563:dc9764591567

Automatic load-balancing between peers that have the same routing score. Use rt_ereg to obtain stable routes.
author Sebastien Decugis <sdecugis@nict.go.jp>
date Thu, 16 Sep 2010 16:41:44 +0900
parents e837ef4bdf35
children 603f70bf1453
files freeDiameter/routing_dispatch.c libfreeDiameter/rt_data.c
diffstat 2 files changed, 33 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/routing_dispatch.c	Thu Sep 16 14:35:48 2010 +0900
+++ b/freeDiameter/routing_dispatch.c	Thu Sep 16 16:41:44 2010 +0900
@@ -843,7 +843,7 @@
 	if (rtd == NULL) {
 		CHECK_FCT( fd_rtd_init(&rtd) );
 
-		/* Add all peers in OPEN state */
+		/* Add all peers currently in OPEN state */
 		CHECK_FCT( pthread_rwlock_rdlock(&fd_g_activ_peers_rw) );
 		for (li = fd_g_activ_peers.next; li != &fd_g_activ_peers; li = li->next) {
 			struct fd_peer * p = (struct fd_peer *)li->o;
--- a/libfreeDiameter/rt_data.c	Thu Sep 16 14:35:48 2010 +0900
+++ b/libfreeDiameter/rt_data.c	Thu Sep 16 16:41:44 2010 +0900
@@ -249,10 +249,12 @@
 	return;
 }
 
-/* Reorder the list of peers */
+/* Reorder the list of peers. If several peer have the same highest score, they are randomized. */
 int  fd_rtd_candidate_reorder(struct fd_list * candidates)
 {
 	struct fd_list unordered = FD_LIST_INITIALIZER(unordered), *li;
+	struct fd_list highest = FD_LIST_INITIALIZER(highest);
+	int hs = -1;
 	
 	TRACE_ENTRY("%p", candidates);
 	CHECK_PARAMS( candidates );
@@ -266,17 +268,39 @@
 		
 		fd_list_unlink(&c->chain);
 		
-		/* Find the position in ordered candidates list */
-		for (li = candidates->next; li != candidates; li = li->next) {
-			struct rtd_candidate * cnext = (struct rtd_candidate *) li;
-			if (cnext->score >= c->score)
-				break;
+		/* If this candidate has a higher score than the previous ones */
+		if (c->score > hs) {
+			/* Then we move the previous high score items at end of the list */
+			fd_list_move_end(candidates, &highest);
+			
+			/* And the new high score is this reset */
+			hs = c->score;
 		}
 		
-		/* Add the element there */
-		fd_list_insert_before(li, &c->chain);
+		/* If this candidate equals the higher score, add it into highest list at a random place */
+		if (c->score == hs) {
+			if (rand() & 1) {
+				fd_list_insert_after(&highest, &c->chain);
+			} else {
+				fd_list_insert_before(&highest, &c->chain);
+			}
+		/* Otherwise, insert at normal place in the list */
+		} else {
+			/* Find the position in ordered candidates list */
+			for (li = candidates->next; li != candidates; li = li->next) {
+				struct rtd_candidate * cnext = (struct rtd_candidate *) li;
+				if (cnext->score >= c->score)
+					break;
+			}
+
+			/* Add the element there */
+			fd_list_insert_before(li, &c->chain);
+		}
 	}
 	
+	/* Now simply move back all the "highest" candidates at the end of the list */
+	fd_list_move_end(candidates, &highest);
+	
 	return 0;
 }
 
"Welcome to our mercurial repository"