Joining and leaving a group
In the following example, Process 1 bellow creates a group with only itself as member, then puts the main ULT to sleep for 10 seconds before destroying it and terminating. Mercury communication proceed in the backgroup to detect joining and leaving processes.
The process uses ssg_group_id_store()
to store information
about the group in a file. The first argument of this function is
the file name. The second is the group id. The third is the number
of current member addresses to include in the file.
proc1.c (show/hide)
#include <assert.h>
#include <stdio.h>
#include <ssg.h>
static void my_membership_update_cb(void* uargs,
ssg_member_id_t member_id,
ssg_member_update_type_t update_type)
{
switch(update_type) {
case SSG_MEMBER_JOINED:
printf("Member %ld joined\n", member_id);
break;
case SSG_MEMBER_LEFT:
printf("Member %ld left\n", member_id);
break;
case SSG_MEMBER_DIED:
printf("Member %ld died\n", member_id);
break;
}
}
int main(int argc, char** argv)
{
margo_instance_id mid = margo_init("tcp", MARGO_SERVER_MODE, 1, 0);
assert(mid);
int ret = ssg_init();
assert(ret == SSG_SUCCESS);
hg_addr_t my_addr;
margo_addr_self(mid, &my_addr);
char my_addr_str[128];
size_t my_addr_str_size = 128;
margo_addr_to_string(mid, my_addr_str, &my_addr_str_size, my_addr);
margo_addr_free(mid, my_addr);
const char* group_addr_strs[] = { my_addr_str };
ssg_group_config_t config = {
.swim_period_length_ms = 1000,
.swim_suspect_timeout_periods = 5,
.swim_subgroup_member_count = 1,
.swim_disabled = 0,
.ssg_credential = -1
};
ssg_group_id_t gid;
ret = ssg_group_create(
mid, "mygroup", group_addr_strs, 1,
&config, my_membership_update_cb, NULL, &gid);
ret = ssg_group_id_store("mygroup.ssg", gid, 1);
// ...
// do stuff using the group
// ...
margo_thread_sleep(mid, 10000);
ret = ssg_group_leave(gid);
assert(ret == SSG_SUCCESS);
ret = ssg_group_destroy(gid);
assert(ret == SSG_SUCCESS);
ret = ssg_finalize();
assert(ret == SSG_SUCCESS);
margo_finalize(mid);
return 0;
}
Process 2, whose code is shown bellow, reads the group file using
ssg_group_id_load()
. It then joins the group by calling
ssg_group_join()
. Note that this function takes a membership
callback and user-data pointer, but does not include the group name
nor the group configuration. These pieces of information are retrieved
from the loaded group itself.
The process sleeps for 2 seconds, then calls ssg_group_leave()
to leave the group. When running this code, you should see Process 1 display
messages upon Process 2 joining and leaving.
proc2.c (show/hide)
#include <assert.h>
#include <stdio.h>
#include <ssg.h>
static void my_membership_update_cb(void* uargs,
ssg_member_id_t member_id,
ssg_member_update_type_t update_type)
{
switch(update_type) {
case SSG_MEMBER_JOINED:
printf("Member %ld joined\n", member_id);
break;
case SSG_MEMBER_LEFT:
printf("Member %ld left\n", member_id);
break;
case SSG_MEMBER_DIED:
printf("Member %ld died\n", member_id);
break;
}
}
int main(int argc, char** argv)
{
margo_instance_id mid = margo_init("tcp", MARGO_SERVER_MODE, 1, 0);
assert(mid);
int ret = ssg_init();
assert(ret == SSG_SUCCESS);
ssg_group_id_t gid;
int num_addrs = 1;
ret = ssg_group_id_load("mygroup.ssg", &num_addrs, &gid);
assert(ret == SSG_SUCCESS);
ret = ssg_group_join(mid, gid, my_membership_update_cb, NULL);
assert(ret == SSG_SUCCESS);
margo_thread_sleep(mid, 10000);
// ...
// do stuff using the group
// ...
ret = ssg_group_leave(gid);
assert(ret == SSG_SUCCESS);
ret = ssg_group_destroy(gid);
assert(ret == SSG_SUCCESS);
ret = ssg_finalize();
assert(ret == SSG_SUCCESS);
margo_finalize(mid);
return 0;
}
Note that ssg_group_join
and ssg_group_leave
both
have a variant, ssg_group_join_target
and ssg_group_leave_target
,
respectively, which can be used to specify he address of another member of
the group to inform of the process joining/leaving. The
ssg_group_join
and ssg_group_leave
functions simply
contact a random group member for this purpose.