[Spread-cvs] commit: r252 - trunk/daemon
jschultz at spread.org
jschultz at spread.org
Thu Jul 28 10:50:56 EDT 2005
Author: jschultz
Date: 2005-07-28 10:50:56 -0400 (Thu, 28 Jul 2005)
New Revision: 252
Modified:
trunk/daemon/groups.c
trunk/daemon/sess_body.h
Log:
Removed iterators from sess_body.h structures and insert/removals. Changed all skiplist's to function as unique key sets (i.e. - no values): this requires that the members used for key comparison in the referenced structs are the first members of those structs. Changed grp->mboxes to be an unsorted dynamic array (stdarr). Changed G-analize_groups to be more like it was before, but I "upgraded" it a bit, it should be slightly faster now than before. Added some comments for clarity and potential future work in TODO and FIXME comments.
Modified: trunk/daemon/groups.c
===================================================================
--- trunk/daemon/groups.c 2005-07-22 08:40:34 UTC (rev 251)
+++ trunk/daemon/groups.c 2005-07-28 14:50:56 UTC (rev 252)
@@ -123,7 +123,9 @@
static int Groups_control_down_queue;
-static stdskl GroupsList; /* (char*) -> (group*) */
+static stdskl GroupsList; /* (group*) -> nil */
+/* TODO: might want to add a "secondary" index of daemon IDs -> groups for potentially faster performance */
+/* TODO: might want to add a "secondary" index of member IDs -> groups for potentially faster performance */
static synced_set MySyncedSet;
static membership_id unknown_memb_id = { -1, -1 }; /* See explanation above. */
@@ -167,6 +169,7 @@
static int G_check_if_changed_by_cascade( group *grp );
static void G_remove_daemon( group *grp, daemon_members *dmn );
static void G_remove_group( group *grp );
+static void G_remove_mailbox( group *grp, mailbox m );
static int G_compare_cstrptr(const void *, const void *);
static int G_compare_proc_ids_by_conf( const void *, const void * );
@@ -183,8 +186,8 @@
static int G_compare_proc_ids_by_conf(const void *a, const void *b)
{
proc dummy_proc;
- int ia = Conf_proc_by_id( *(const int32*) a, &dummy_proc );
- int ib = Conf_proc_by_id( *(const int32*) b, &dummy_proc );
+ int ia = Conf_proc_by_id( **(const int32**) a, &dummy_proc );
+ int ib = Conf_proc_by_id( **(const int32**) b, &dummy_proc );
assert( ia > -1 );
assert( ib > -1 );
@@ -236,7 +239,7 @@
MySyncedSet.proc_ids[0] = My.id;
G_print_synced_set( SPLOG_INFO, &MySyncedSet, "G_init" );
- ret = stdskl_construct(&GroupsList, sizeof(char*), sizeof(group*), G_compare_cstrptr);
+ ret = stdskl_construct(&GroupsList, sizeof(group*), 0, G_compare_cstrptr);
if (ret != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "G_init: Failure to Initialize GroupsList\n");
}
@@ -334,7 +337,7 @@
{
for (stdskl_begin(&GroupsList, &it); !stdskl_is_end(&GroupsList, &it); )
{
- grp = *(group**) stdskl_it_val(&it);
+ grp = *(group**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
if( grp->changed )
@@ -358,7 +361,7 @@
grp->changed = 0;
G_print_group_id( SPLOG_DEBUG, grp->grp_id, "G_handle_reg_memb" );
G_update_daemon_memb_ids( grp );
- if( !stdskl_empty(&grp->mboxes) )
+ if( !stdarr_empty(&grp->mboxes) )
{
G_send_heavyweight_memb( grp );
}
@@ -385,7 +388,7 @@
for (stdskl_begin(&GroupsList, &it); !stdskl_is_end(&GroupsList, &it); )
{
- grp = *(group**) stdskl_it_val(&it);
+ grp = *(group**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
if( grp->changed )
@@ -487,7 +490,7 @@
*/
for (stdskl_begin(&GroupsList, &it); !stdskl_is_end(&GroupsList, &it); )
{
- grp = *(group**) stdskl_it_val(&it);
+ grp = *(group**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
group_changed = G_eliminate_partitioned_daemons( grp );
@@ -565,14 +568,14 @@
for (stdskl_begin(&GroupsList, &git); !stdskl_is_end(&GroupsList, &git); )
{
- grp = *(group**) stdskl_it_val(&git);
+ grp = *(group**) stdskl_it_key(&git);
stdskl_it_next(&git); /* NOTE: need to do advancement before potential erasure below */
group_changed = 0;
for (stdskl_begin(&grp->DaemonsList, &dit); !stdskl_is_end(&grp->DaemonsList, &dit); )
{
- dmn = *(daemon_members**) stdskl_it_val(&dit);
+ dmn = *(daemon_members**) stdskl_it_key(&dit);
stdskl_it_next(&dit); /* NOTE: need to do advancement before potential erasure below */
if( Conf_id_in_conf( &Trans_memb, dmn->proc_id ) == -1 )
@@ -584,7 +587,7 @@
}
if( group_changed )
{
- if( !stdskl_empty(&grp->mboxes) )
+ if( !stdarr_empty(&grp->mboxes) )
{
G_send_trans_memb( grp );
}
@@ -649,7 +652,7 @@
for (stdskl_begin(&GroupsList, &git); !stdskl_is_end(&GroupsList, &git); )
{
- grp = *(group**) stdskl_it_val(&git);
+ grp = *(group**) stdskl_it_key(&git);
stdskl_it_next(&git); /* NOTE: need to do advancement before potential erasure below */
group_changed = G_check_if_changed_by_cascade( grp );
@@ -733,11 +736,11 @@
memset( new_grp->name, 0, MAX_GROUP_NAME );
strcpy( new_grp->name, group_name );
- if (stdskl_construct(&new_grp->DaemonsList, sizeof(int32), sizeof(daemon_members*), G_compare_proc_ids_by_conf) != 0) {
+ if (stdskl_construct(&new_grp->DaemonsList, sizeof(daemon_members*), 0, G_compare_proc_ids_by_conf) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
- if (stdskl_construct(&new_grp->mboxes, sizeof(mailbox), 0, NULL) != 0) {
+ if (stdarr_construct(&new_grp->mboxes, sizeof(mailbox), 0) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -757,7 +760,7 @@
new_grp->num_members = 0;
- if (stdskl_insert(&GroupsList, &new_grp->GroupsListIt, &new_grp->name, &new_grp, STDFALSE) != 0) {
+ if (stdskl_put(&GroupsList, NULL, &new_grp, NULL, STDFALSE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -782,7 +785,7 @@
new_dmn->memb_id = unknown_memb_id;
}
- if (stdskl_insert(&grp->DaemonsList, &new_dmn->DaemonsListIt, &new_dmn->proc_id, &new_dmn, STDFALSE) != 0) {
+ if (stdskl_put(&grp->DaemonsList, NULL, &new_dmn, NULL, STDFALSE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -801,7 +804,7 @@
memset( new_mbr->name, 0, MAX_GROUP_NAME );
strcpy( new_mbr->name, private_group_name );
- if (stdskl_insert(&dmn->MembersList, &new_mbr->MembersListIt, &new_mbr, NULL, STDFALSE) != 0) {
+ if (stdskl_put(&dmn->MembersList, NULL, &new_mbr, NULL, STDFALSE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -816,7 +819,11 @@
new_mbox = Sessions[ ses ].mbox;
- if (stdskl_put(&grp->mboxes, NULL, &new_mbox, NULL, STDFALSE) != 0) {
+ /* TODO: do we need to ensure the insert is
+ unique or is that externally implied? Seems
+ to be implied by above checks. */
+
+ if (stdarr_push_back(&grp->mboxes, &new_mbox) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
} else
@@ -825,7 +832,7 @@
if( Is_partitioned_daemon( dmn ) && !grp->changed )
grp->changed = 1;
- if( !stdskl_empty(&grp->mboxes) ) {
+ if( !stdarr_empty(&grp->mboxes) ) {
if( grp->changed )
{
G_send_heavyweight_join( grp, new_mbr, new_mbox );
@@ -864,6 +871,7 @@
group *grp;
daemon_members *dmn;
member *mbr;
+ stdit it;
Alarmp( SPLOG_INFO, GROUPS, "G_handle_leave: %s leaves group %s\n", private_group_name, group_name );
@@ -920,18 +928,29 @@
if( p.id == My.id )
{
- /* notify this local member and extract its mbox from group */
- ses = Sess_get_session( private_name );
- G_send_self_leave( grp, ses );
- stdskl_erase_key(&grp->mboxes, &Sessions[ses].mbox);
+ /* notify this local member and extract its mbox from group */
+ ses = Sess_get_session( private_name );
+
+ if (ses < 0) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_handle_leave: member '%s' has no local session in group '%s'\n", private_name, grp->name );
+ }
+
+ G_send_self_leave( grp, ses );
+ G_remove_mailbox( grp, Sessions[ ses ].mbox );
}
/* extract this member from group */
memcpy( departing_private_group_name, mbr->name, MAX_GROUP_NAME );
- stdskl_erase(&dmn->MembersList, &mbr->MembersListIt);
+
+ if (stdskl_is_end(&dmn->MembersList, stdskl_find(&dmn->MembersList, &it, &mbr))) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_handle_leave: couldn't extract member(%s) from MembersList!\n", mbr->name );
+ }
+
+ stdskl_erase(&dmn->MembersList, &it);
+
dispose(mbr);
grp->num_members--;
- if( dmn->MembersList.size == 0 )
+ if( stdskl_empty(&dmn->MembersList) )
{
G_remove_daemon( grp, dmn );
}
@@ -949,7 +968,7 @@
* We never need to mark a group as changed here, or in G_handle_kill.
*/
- if( !stdskl_empty(&grp->mboxes) )
+ if( !stdarr_empty(&grp->mboxes) )
{
if( grp->changed )
{
@@ -988,7 +1007,7 @@
daemon_members *dmn;
member *mbr;
int ses = -1; /* Fool compiler */
- stdit it;
+ stdit it, tit;
Alarmp( SPLOG_INFO, GROUPS, "G_handle_kill: %s is killed\n", private_group_name );
@@ -1021,11 +1040,11 @@
return;
}
- if( p.id == My.id ) ses = Sess_get_session( private_name );
+ if( p.id == My.id ) ses = Sess_get_session( private_name ); /* FIXME: check for negative answer and error? */
for (stdskl_begin(&GroupsList, &it); !stdskl_is_end(&GroupsList, &it); )
{
- grp = *(group**) stdskl_it_val(&it);
+ grp = *(group**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
dmn = G_get_daemon( grp, p.id );
@@ -1036,13 +1055,19 @@
/* Extract this member from group */
if( p.id == My.id )
{
- stdskl_erase_key(&grp->mboxes, &Sessions[ses].mbox);
+ G_remove_mailbox( grp, Sessions[ ses ].mbox );
}
memcpy( departing_private_group_name, mbr->name, MAX_GROUP_NAME );
- stdskl_erase(&dmn->MembersList, &mbr->MembersListIt);
+
+ if (stdskl_is_end(&dmn->MembersList, stdskl_find(&dmn->MembersList, &tit, &mbr))) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_handle_kill: unable to extract member(%s) from MembersList!\n", private_group_name );
+ }
+
+ stdskl_erase_key(&dmn->MembersList, &tit);
+
dispose(mbr);
grp->num_members--;
- if( dmn->MembersList.size == 0 )
+ if( stdskl_empty(&dmn->MembersList) )
{
G_remove_daemon( grp, dmn );
}
@@ -1056,7 +1081,7 @@
/* Increment group id */
grp->grp_id.index++;
- if( !stdskl_empty(&grp->mboxes) )
+ if( !stdarr_empty(&grp->mboxes) )
{
if( grp->changed )
{
@@ -1098,7 +1123,8 @@
char *vs_set_offset_ptr; /* Byte offset into the vs_set region of my vs_set */
char *num_vs_ptr; /* num members in virtual-synchrony/failure-atomicity set */
char *vs_ptr; /* the virtual synchrony set */
- stdit it;
+ mailbox *mbox_ptr;
+ mailbox *endbox_ptr;
msg = Message_new_message();
num_bytes = G_build_memb_buf( grp, msg, Mess_buf, caused );
@@ -1132,9 +1158,14 @@
Obj_Inc_Refcount(mess_link->mess);
needed = 0;
- for (stdskl_begin(&grp->mboxes, &it); !stdskl_is_end(&grp->mboxes, &it); stdskl_it_next(&it))
+
+ mbox_ptr = (mailbox*) grp->mboxes.begin;
+ endbox_ptr = mbox_ptr + grp->mboxes.size;
+
+ for (; mbox_ptr != endbox_ptr; ++mbox_ptr)
{
- ses = Sess_get_session_index ( *(mailbox*) stdskl_it_key(&it) );
+ ses = Sess_get_session_index ( *mbox_ptr );
+
if( Is_memb_session( Sessions[ ses ].status ) )
Sess_write( ses, mess_link, &needed );
}
@@ -1190,7 +1221,8 @@
char *local_vs_set_offset_ptr;
int needed, joiner_needed;
int ses;
- stdit it;
+ mailbox *mbox_ptr;
+ mailbox *endbox_ptr;
msg = Message_new_message();
num_bytes = G_build_memb_vs_buf( grp, msg, Mess_buf, CAUSED_BY_NETWORK, joiner );
@@ -1203,14 +1235,16 @@
/* notify local members */
needed = 0;
- for (stdskl_begin(&grp->mboxes, &it); !stdskl_is_end(&grp->mboxes, &it); stdskl_it_next(&it))
+
+ mbox_ptr = (mailbox*) grp->mboxes.begin;
+ endbox_ptr = mbox_ptr + grp->mboxes.size;
+
+ for (; mbox_ptr != endbox_ptr; ++mbox_ptr)
{
- mailbox m = *(mailbox*) stdskl_it_key(&it);
-
/* if new member is local we do not notify it here. */
- if( joiner != NULL && new_mbox == m) continue;
+ if( joiner != NULL && new_mbox == *mbox_ptr) continue;
- ses = Sess_get_session_index ( m );
+ ses = Sess_get_session_index ( *mbox_ptr );
if( Is_memb_session( Sessions[ ses ].status ) )
Sess_write( ses, mess_link, &needed );
}
@@ -1253,16 +1287,19 @@
message_link *mess_link;
int needed;
int ses;
- stdit it;
+ mailbox *mbox_ptr;
+ mailbox *endbox_ptr;
/* send members transitional membership */
mess_link = G_build_trans_mess( grp );
needed = 0;
- for (stdskl_begin(&grp->mboxes, &it); !stdskl_is_end(&grp->mboxes, &it); stdskl_it_next(&it))
+
+ mbox_ptr = (mailbox*) grp->mboxes.begin;
+ endbox_ptr = mbox_ptr + grp->mboxes.size;
+
+ for (; mbox_ptr != endbox_ptr; ++mbox_ptr)
{
- mailbox m = *(mailbox*) stdskl_it_key(&it);
-
- ses = Sess_get_session_index ( m );
+ ses = Sess_get_session_index ( *mbox_ptr );
if( Is_memb_session( Sessions[ ses ].status ) )
Sess_write( ses, mess_link, &needed );
}
@@ -1453,7 +1490,7 @@
for (stdskl_begin(&GroupsList, &it); !stdskl_is_end(&GroupsList, &it); )
{
- grp = *(group**) stdskl_it_val(&it);
+ grp = *(group**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
/*
@@ -1481,7 +1518,7 @@
grp->grp_id.memb_id = Reg_memb_id;
grp->grp_id.index = 1;
grp->changed = 0;
- if( !stdskl_empty(&grp->mboxes) )
+ if( !stdarr_empty(&grp->mboxes) )
G_send_heavyweight_memb( grp );
G_update_daemon_memb_ids( grp );
}
@@ -1511,16 +1548,17 @@
stdskl_find(&GroupsList, &it, &group_name);
- return (!stdskl_is_end(&GroupsList, &it) ? *(group**) stdskl_it_val(&it) : NULL);
+ return (!stdskl_is_end(&GroupsList, &it) ? *(group**) stdskl_it_key(&it) : NULL);
}
static daemon_members *G_get_daemon( group *grp, int32u proc_id )
{
- stdit it;
+ stdit it;
+ int32u * proc_id_ptr = &proc_id;
- stdskl_find(&grp->DaemonsList, &it, &proc_id);
+ stdskl_find(&grp->DaemonsList, &it, &proc_id_ptr);
- return (!stdskl_is_end(&grp->DaemonsList, &it) ? *(daemon_members**) stdskl_it_val(&it) : NULL);
+ return (!stdskl_is_end(&grp->DaemonsList, &it) ? *(daemon_members**) stdskl_it_key(&it) : NULL);
}
static member *G_get_member( daemon_members *dmn, char *private_group_name )
@@ -1586,12 +1624,12 @@
num_bytes = 0;
for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); )
{
- dmn = *(daemon_members**) stdskl_it_val(&it);
+ dmn = *(daemon_members**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: need to do advancement before potential erasure below */
for (stdskl_begin(&dmn->MembersList, &mit); !stdskl_is_end(&dmn->MembersList, &mit); )
{
- mbr = *(member**) stdskl_it_val(&mit);
+ mbr = *(member**) stdskl_it_key(&mit);
stdskl_it_next(&mit); /* NOTE: need to do advancement before potential erasure below */
memb_ptr = &buf[num_bytes];
@@ -1682,16 +1720,14 @@
/* Points to the front of the vs_sets */
vs_set_region_ptr = &buf[num_bytes];
- /* Basically, use the skiplist to do an insertion sort. */
+ /* use a skiplist to sort all of the group's daemons by memb_id (primary) and then by proc_id (secondary) */
+
if (stdskl_construct(&temp, sizeof(daemon_members*), 0, G_compare_daemon_vs_set) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
- for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); stdskl_it_next(&it))
- {
- if (stdskl_insert(&temp, NULL, (daemon_members**) stdskl_it_val(&it), NULL, STDFALSE) != 0) {
- Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
- }
+ if (stdskl_put_seq_n(&temp, NULL, stdskl_begin(&grp->DaemonsList, &it), stdskl_size(&grp->DaemonsList), STDFALSE) != 0) {
+ Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
curr_vs_set_memb_id = unknown_memb_id;
@@ -1727,12 +1763,13 @@
/* Handle changed-group join during transitional. The joiner does not
* get to be listed with everyone else from his daemon, but rather at
* the end, in a self vs set. */
- if( joiner != NULL && !found_joiner )
+ if( joiner != NULL && !found_joiner ) {
if( strcmp( joiner->name, mbr->name ) == 0 )
{
found_joiner = 1;
continue;
}
+ }
membs_ptr = &buf[num_bytes];
num_bytes += MAX_GROUP_NAME;
head_ptr->data_len += MAX_GROUP_NAME;
@@ -1865,7 +1902,7 @@
couldnt_fit_daemon = 0;
while (!stdskl_is_end(&GroupsList, git))
{
- grp = *(group**) stdskl_it_val(git);
+ grp = *(group**) stdskl_it_key(git);
if (first_time) { /* initialize dit on first call to this fcn */
stdskl_begin(&grp->DaemonsList, dit);
@@ -1888,12 +1925,12 @@
for (; !stdskl_is_end(&grp->DaemonsList, dit); stdskl_it_next(dit))
{
- dmn = *(daemon_members**) stdskl_it_val(dit);
+ dmn = *(daemon_members**) stdskl_it_key(dit);
/* To store this daemon's information about the current group,
* we need to be able to store its proc_id, memb_id, number of
* local members, and the private group names of its local members. */
size_needed = sizeof(int32) + sizeof(membership_id) + sizeof(int16u) +
- (dmn->MembersList.size * MAX_GROUP_NAME) + Message_get_data_header_size();
+ (stdskl_size(&dmn->MembersList) * MAX_GROUP_NAME) + Message_get_data_header_size();
/* This requires that the number of local group members be limited. */
if( size_needed > GROUPS_BUF_SIZE - num_bytes )
{
@@ -1923,9 +1960,9 @@
}
memcpy( num_memb_ptr, &num_memb, sizeof(int16u) );
- if( num_memb != dmn->MembersList.size )
+ if( num_memb != stdskl_size(&dmn->MembersList) )
Alarmp( SPLOG_FATAL, GROUPS, "G_build_groups_buf: group %s has %d %d members\n",
- grp->name, num_memb, dmn->MembersList.size );
+ grp->name, num_memb, stdskl_size(&dmn->MembersList) );
num_dmns++;
}
memcpy( num_dmns_ptr, &num_dmns, sizeof(int16u) );
@@ -1935,7 +1972,7 @@
stdskl_it_next(git); /* advance group iterator */
if (!stdskl_is_end(&GroupsList, git)) { /* if loop not done, then init dit iterator for the advanced git */
- grp = *(group**) stdskl_it_val(git);
+ grp = *(group**) stdskl_it_key(git);
stdskl_begin(&grp->DaemonsList, dit);
}
}
@@ -2087,11 +2124,11 @@
memset( grp->name, 0, MAX_GROUP_NAME );
strcpy( grp->name, group_name_ptr );
- if (stdskl_construct(&grp->DaemonsList, sizeof(int32), sizeof(daemon_members*), G_compare_proc_ids_by_conf) != 0) {
+ if (stdskl_construct(&grp->DaemonsList, sizeof(daemon_members*), 0, G_compare_proc_ids_by_conf) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
- if (stdskl_construct(&grp->mboxes, sizeof(mailbox), 0, NULL) != 0) {
+ if (stdarr_construct(&grp->mboxes, sizeof(mailbox), 0) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -2109,7 +2146,7 @@
grp->grp_id.index = Flip_int32( grp->grp_id.index );
}
- if (stdskl_insert(&GroupsList, &grp->GroupsListIt, &grp->name, &grp, STDFALSE) != 0) {
+ if (stdskl_put(&GroupsList, NULL, &grp, NULL, STDFALSE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -2156,7 +2193,7 @@
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
- if (stdskl_insert(&grp->DaemonsList, &dmn->DaemonsListIt, &dmn->proc_id, &dmn, STDFALSE) != 0) {
+ if (stdskl_put(&grp->DaemonsList, NULL, &dmn, NULL, STDFALSE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
@@ -2164,17 +2201,17 @@
!Memb_is_equal( dmn->memb_id, grp->grp_id.memb_id ) )
grp->changed = 1;
- stdskl_end(&dmn->MembersList, &it);
-
/* creating members */
- for( j = 0, stdskl_end(&dmn->MembersList, &it); j < num_memb; ++j, stdskl_it_next(&it))
+ for( j = 0; j < num_memb; ++j )
{
mbr = new( MEMBER );
memcpy( mbr->name, &Temp_buf[num_bytes], MAX_GROUP_NAME );
Alarmp( SPLOG_DEBUG, GROUPS, "G_mess_to_groups: \t\t%s\n", mbr->name );
num_bytes += MAX_GROUP_NAME;
- if (stdskl_insert(&dmn->MembersList, &it, &mbr, NULL, STDTRUE) != 0) { /* NOTE: hint insert at end */
+ /* this inserts into MembersList hinting that the insertion should be at the end of the list (faster if input sorted) */
+
+ if (stdskl_put(&dmn->MembersList, stdskl_end(&dmn->MembersList, &it), &mbr, NULL, STDTRUE) != 0) {
Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
}
}
@@ -2184,71 +2221,110 @@
return( 0 );
}
+/* TODO: G_analize_groups is O(n) when num_groups = 1 and O(n^2) when
+ num_groups > 1 (multi_group_multicast) in the number of targeted
+ mailboxes. In the latter case, if n is large a O(n lg n) solution
+ leveraging a skiplist would be preferable.
+*/
+
int G_analize_groups( int num_groups, char target_groups[][MAX_GROUP_NAME], int target_sessions[] )
{
+static mailbox mboxes[MAX_SESSIONS];
int num_mbox;
+ mailbox *bigbox_ptr;
+ mailbox *bigend_ptr;
+ mailbox *litbox_ptr;
+ mailbox *litend_ptr;
group *grp;
char proc_name[MAX_PROC_NAME];
char private_name[MAX_PRIVATE_NAME+1];
int ses;
int ret;
int i;
- stdskl mboxes;
- stdit it;
- if (stdskl_construct(&mboxes, sizeof(mailbox), 0, NULL) != 0) {
- Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
- }
+ /* collect the target local mailboxen */
- /* get the mbox */
- num_mbox = 0;
- for( i=0; i < num_groups; i++ )
+ num_mbox = 0;
+ litbox_ptr = NULL;
+ litend_ptr = NULL;
+
+ for ( i=0; i < num_groups; ++i )
{
- if( target_groups[i][0] == '#' )
+ if( target_groups[i][0] != '#' )
{
+ /* regular group */
+ grp = G_get_group( target_groups[i] );
+
+ if( grp == NULL ) {
+ continue;
+ }
+
+ if( Gstate == GOP || Gstate == GTRANS ) {
+ litbox_ptr = (mailbox*) grp->mboxes.begin; /* point litbox pointer at grp->mboxes */
+ litend_ptr = litbox_ptr + grp->mboxes.size;
+
+ } else {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_analize_groups: Gstate is %d\n", Gstate );
+ }
+
+ } else {
/* private group */
ret = G_private_to_names( target_groups[i], private_name, proc_name );
- /* Illegal group */
- if( ret < 0 ) continue;
+ /* Illegal group OR this private group is not local OR we have no such session */
+ if( ret < 0 || strcmp( My.name, proc_name ) != 0 || (ses = Sess_get_session( private_name )) < 0) {
+ continue;
+ }
- /* this private group is not local */
- if( strcmp( My.name, proc_name ) != 0 ) continue;
+ litbox_ptr = &Sessions[ ses ].mbox; /* just point litbox pointer at the session's mbox */
+ litend_ptr = litbox_ptr + 1;
+ }
- ses = Sess_get_session( private_name );
+ /* NOTE: this code assumes that grp->mboxes contains no duplicates */
- /* we have no such session */
- if( ses < 0 ) continue;
+ if (num_groups == 1) { /* no need to do extra copy work if only one group -> just use litbox 'array' directly */
+ break;
+ }
- if (stdskl_put(&mboxes, NULL, &Sessions[ ses ].mbox, NULL, STDFALSE) != 0) {
- Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
+ if (num_mbox != 0) {
+ bigend_ptr = mboxes + num_mbox;
+
+ for (; litbox_ptr != litend_ptr; ++litbox_ptr)
+ {
+ mailbox m = *litbox_ptr;
+
+ /* linear search over mboxes for 'm' */
+
+ for (bigbox_ptr = mboxes; bigbox_ptr != bigend_ptr && *bigbox_ptr != m; ++bigbox_ptr);
+
+ if (bigbox_ptr == bigend_ptr) {
+ mboxes[ num_mbox++ ] = m;
+ }
}
} else {
- /* regular group */
- grp = G_get_group( target_groups[i] );
- if( grp == NULL ) continue;
- if( Gstate == GOP || Gstate == GTRANS ) {
+ num_mbox = (int) (litend_ptr - litbox_ptr); /* if num_mbox is (still) zero, then adopt litbox 'array' */
+ memcpy(mboxes, litbox_ptr, num_mbox * sizeof(mailbox));
+ }
+ }
- if (stdskl_put_seq_n(&mboxes, NULL, stdskl_begin(&grp->mboxes, &it), stdskl_size(&grp->mboxes), STDFALSE) != 0) {
- Alarmp( SPLOG_FATAL, GROUPS, "%s: %d: memory allocation failed\n", __FILE__, __LINE__ );
- }
+ /* convert mailboxes to sessions */
- } else {
- Alarmp( SPLOG_FATAL, GROUPS, "G_analize_groups: Gstate is %d\n", Gstate );
- }
- }
+ if (num_groups == 1) { /* on non-multi group multicast just use litbox 'array' in place */
+ bigbox_ptr = litbox_ptr;
+ bigend_ptr = litend_ptr;
+
+ } else {
+ bigbox_ptr = mboxes;
+ bigend_ptr = mboxes + num_mbox;
}
-
- /* convert mbox to sessions */
- for (i = 0, stdskl_begin(&mboxes, &it); !stdskl_is_end(&mboxes, &it); ++i, stdskl_it_next(&it))
+
+ for (; bigbox_ptr != bigend_ptr; ++bigbox_ptr, ++target_sessions)
{
- target_sessions[i] = Sess_get_session_index( *(mailbox*) stdskl_it_key(&it) );
+ *target_sessions = Sess_get_session_index( *bigbox_ptr );
}
- stdskl_destruct(&mboxes); /* TODO: old code of array searching probably faster at least for small groups/memberships */
-
- return i;
+ return (int) (bigend_ptr - bigbox_ptr);
}
static void G_compute_group_mask( group *grp, char *func_name )
@@ -2266,8 +2342,11 @@
}
for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); stdskl_it_next(&it))
{
- dmn = *(daemon_members**) stdskl_it_val(&it);
+ dmn = *(daemon_members**) stdskl_it_key(&it);
Conf_proc_by_id( dmn->proc_id, &p );
+
+ /* FIXME: TODO: isn't the following loop the same as: temp = (0x1 << (p.seg_index & 0x1F)); ??? */
+
temp = 1;
for( i = 0; i < p.seg_index%32; i++ )
{
@@ -2417,12 +2496,12 @@
for (i = 0, stdskl_begin(&GroupsList, &git); !stdskl_is_end(&GroupsList, &git); ++i, stdskl_it_next(&git))
{
- grp = *(group**) stdskl_it_val(&git);
+ grp = *(group**) stdskl_it_key(&git);
Alarmp( SPLOG_PRINT, GROUPS, "[%d] group %s with %d members:\n", i+1, grp->name, grp->num_members );
for (j = 0, stdskl_begin(&grp->DaemonsList, &dit); !stdskl_is_end(&grp->DaemonsList, &dit); ++j, stdskl_it_next(&dit))
{
- dmn = *(daemon_members**) stdskl_it_val(&dit);
+ dmn = *(daemon_members**) stdskl_it_key(&dit);
for (k = 0, stdskl_begin(&dmn->MembersList, &mit); !stdskl_is_end(&dmn->MembersList, &mit); ++k, stdskl_it_next(&mit))
{
@@ -2438,7 +2517,7 @@
{
group *grp = G_get_group( group_name );
if( grp == NULL ) return 0;
- return stdskl_size(&grp->mboxes);
+ return stdarr_size(&grp->mboxes);
}
/* Add new members to my synced set. */
@@ -2513,7 +2592,7 @@
for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); )
{
- dmn = *(daemon_members**) stdskl_it_val(&it);
+ dmn = *(daemon_members**) stdskl_it_key(&it);
stdskl_it_next(&it); /* NOTE: advance here to protect against potential removal below */
needed = 0;
@@ -2554,7 +2633,7 @@
for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); stdskl_it_next(&it))
{
- dmn = *(daemon_members**) stdskl_it_val(&it);
+ dmn = *(daemon_members**) stdskl_it_key(&it);
if( Conf_id_in_conf( &Trans_memb, dmn->proc_id ) == -1 )
{
group_changed = 1;
@@ -2566,31 +2645,65 @@
static void G_remove_daemon( group *grp, daemon_members *dmn )
{
- stdit it;
+ stdit it;
+ int32 * proc_id_ptr = &dmn->proc_id;
+
+ if (stdskl_is_end(&grp->DaemonsList, stdskl_find(&grp->DaemonsList, &it, &proc_id_ptr))) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_remove_daemon: invalid daemon(%d.%d.%d.%d) removal from group(%s)\n",
+ IP1(dmn->proc_id), IP2(dmn->proc_id), IP3(dmn->proc_id), IP4(dmn->proc_id), grp->name );
+ }
+ stdskl_erase(&grp->DaemonsList, &it);
+
grp->num_members -= stdskl_size(&dmn->MembersList);
for (stdskl_begin(&dmn->MembersList, &it); !stdskl_is_end(&dmn->MembersList, &it); stdskl_it_next(&it)) {
- dispose(*(member**) stdskl_it_val(&it)); /* NOTE: this is only safe because we do destruct immediately after */
+ dispose(*(member**) stdskl_it_key(&it)); /* NOTE: this is only safe because we do destruct immediately after */
}
stdskl_destruct(&dmn->MembersList);
- stdskl_erase(&grp->DaemonsList, &dmn->DaemonsListIt);
dispose(dmn);
}
/* Remove a group that is known to be empty. */
static void G_remove_group( group *grp )
{
+ stdit it;
+
assert( stdskl_empty(&grp->DaemonsList) );
+ assert( stdarr_empty(&grp->mboxes) );
+
+ if (stdskl_is_end(&GroupsList, stdskl_find(&GroupsList, &it, &grp))) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_remove_group: invalid group removal(%s)\n", grp->name );
+ }
+
+ stdskl_erase(&GroupsList, &it);
+
stdskl_destruct(&grp->DaemonsList);
- stdskl_destruct(&grp->mboxes);
- stdskl_erase(&GroupsList, &grp->GroupsListIt);
+ stdarr_destruct(&grp->mboxes);
dispose(grp);
Num_groups--;
GlobalStatus.num_groups = Num_groups;
}
+/* Remove a local mailbox from grp->mboxes */
+static void G_remove_mailbox( group *grp, mailbox m )
+{
+ mailbox *mbox_ptr = (mailbox*) grp->mboxes.begin; /* address of first entry */
+ mailbox *endbox_ptr = mbox_ptr + grp->mboxes.size; /* address of 1 past last entry */
+
+ for (; mbox_ptr != endbox_ptr && *mbox_ptr != m; ++mbox_ptr); /* linear search over grp->mboxes */
+
+ if (mbox_ptr == endbox_ptr) {
+ Alarmp( SPLOG_FATAL, GROUPS, "G_remove_mailbox: didn't find local mailbox %d in group '%s'\n", m, grp->name );
+ }
+
+ --endbox_ptr; /* point at last entry in grp->mboxes */
+ *mbox_ptr = *endbox_ptr; /* overwrite 'm' entry w/ last entry */
+
+ stdarr_pop_back(&grp->mboxes); /* pop off redundant last entry */
+}
+
/* All non-partitioned daemons get the membership ID component of the
* groups current group ID. */
static void G_update_daemon_memb_ids( group *grp )
@@ -2599,7 +2712,7 @@
for (stdskl_begin(&grp->DaemonsList, &it); !stdskl_is_end(&grp->DaemonsList, &it); stdskl_it_next(&it))
{
- daemon_members *dmn = *(daemon_members**) stdskl_it_val(&it);
+ daemon_members *dmn = *(daemon_members**) stdskl_it_key(&it);
if( Is_established_daemon( dmn ) ) {
dmn->memb_id = grp->grp_id.memb_id;
Modified: trunk/daemon/sess_body.h
===================================================================
--- trunk/daemon/sess_body.h 2005-07-22 08:40:34 UTC (rev 251)
+++ trunk/daemon/sess_body.h 2005-07-28 14:50:56 UTC (rev 252)
@@ -72,26 +72,23 @@
/* All the information we need to maintain per group member is its private
* group name. */
typedef struct dummy_member {
- char name[MAX_GROUP_NAME];
- stdit MembersListIt;
+ char name[MAX_GROUP_NAME]; /* NOTE: groups.c depends on 'name' being first member (MembersList) */
} member;
typedef struct dummy_daemon_members {
- int32 proc_id;
- membership_id memb_id; /* Used for vs_set sorting; unknown_memb_id means partitioned. */
- stdskl MembersList; /* (member*) -> nil */
- stdit DaemonsListIt;
+ int32 proc_id; /* NOTE: groups.c depends on 'proc_id' being the first member (DaemonsList) */
+ membership_id memb_id; /* used for vs_set sorting in G_build_memb_vs_buf; unknown_memb_id means partitioned. */
+ stdskl MembersList; /* (member*) -> nil */
} daemon_members;
typedef struct dummy_group {
- char name[MAX_GROUP_NAME];
+ char name[MAX_GROUP_NAME]; /* NOTE: groups.c depends on 'name' being the first member (GroupsList) */
group_id grp_id;
int changed;
- int num_members; /* sums over all daemons in DaemonsList */
- stdskl DaemonsList; /* (int32) -> (daemon_members*) */
- stdskl mboxes; /* (mailbox) -> nil: mailboxes of local clients */
+ int num_members; /* sums over all daemons in DaemonsList */
+ stdskl DaemonsList; /* (daemon_members*) -> nil */
+ stdarr mboxes; /* (mailbox): local clients unordered */
route_mask grp_mask;
- stdit GroupsListIt;
} group;
#undef ext
More information about the Spread-cvs
mailing list