ssg.c 15.7 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (c) 2016 UChicago Argonne, LLC
 *
 * See COPYRIGHT in top-level directory.
 */

7
#include "ssg-config.h"
Shane Snyder's avatar
Shane Snyder committed
8

Jonathan Jenkins's avatar
Jonathan Jenkins committed
9 10 11 12
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
13
#include <errno.h>
Jonathan Jenkins's avatar
Jonathan Jenkins committed
14 15
#include <stdlib.h>
#include <string.h>
Jonathan Jenkins's avatar
Jonathan Jenkins committed
16
#include <assert.h>
Shane Snyder's avatar
Shane Snyder committed
17
#ifdef SSG_HAVE_MPI
18 19
#include <mpi.h>
#endif
Jonathan Jenkins's avatar
Jonathan Jenkins committed
20

Shane Snyder's avatar
Shane Snyder committed
21
#include <mercury.h>
22
#include <abt.h>
Shane Snyder's avatar
Shane Snyder committed
23
#include <margo.h>
24

25
#include "ssg.h"
Shane Snyder's avatar
Shane Snyder committed
26 27 28
#ifdef SSG_HAVE_MPI
#include "ssg-mpi.h"
#endif
29
#include "ssg-internal.h"
30
#ifdef SSG_USE_SWIM_FD
31 32
#include "swim-fd/swim-fd.h"
#endif
33
#include "uthash.h"
34

35
/* SSG helper routine prototypes */
Shane Snyder's avatar
Shane Snyder committed
36 37
static ssg_group_descriptor_t * ssg_generate_group_descriptor(
    const char * name, const char * leader_addr_str);
38 39
static const char ** ssg_setup_addr_str_list(
    char * buf, int num_addrs);
40 41
static int ssg_group_destroy_internal(
    ssg_group_t *g);
42

43 44
/* XXX: i think we ultimately need per-mid ssg instances rather than 1 global? */
ssg_instance_t *ssg_inst = NULL;
45

46 47 48
/***************************************************
 *** SSG runtime intialization/shutdown routines ***
 ***************************************************/
49

50 51
int ssg_init(
    margo_instance_id mid)
Jonathan Jenkins's avatar
Jonathan Jenkins committed
52
{
53 54 55 56 57 58 59 60 61 62
    if (ssg_inst)
        return SSG_FAILURE;

    /* initialize an SSG instance for this margo instance */
    ssg_inst = malloc(sizeof(*ssg_inst));
    if (!ssg_inst)
        return SSG_FAILURE;
    memset(ssg_inst, 0, sizeof(*ssg_inst));
    ssg_inst->mid = mid;

63
    ssg_register_rpcs();
64

65 66
    return SSG_SUCCESS;
}
Jonathan Jenkins's avatar
Jonathan Jenkins committed
67

68
int ssg_finalize()
69
{
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    ssg_group_t *g, *tmp;

    if (!ssg_inst)
        return SSG_FAILURE;

    /* destroy all active groups */
    HASH_ITER(hh, ssg_inst->group_table, g, tmp)
    {
        HASH_DELETE(hh, ssg_inst->group_table, g);
        ssg_group_destroy_internal(g);
    }

    free(ssg_inst);
    ssg_inst = NULL;

85
    return SSG_SUCCESS;
86
}
Jonathan Jenkins's avatar
Jonathan Jenkins committed
87

88 89 90
/*************************************
 *** SSG group management routines ***
 *************************************/
Jonathan Jenkins's avatar
Jonathan Jenkins committed
91

Shane Snyder's avatar
Shane Snyder committed
92
ssg_group_id_t ssg_group_create(
93 94
    const char * group_name,
    const char * const group_addr_strs[],
Shane Snyder's avatar
Shane Snyder committed
95
    int group_size)
96
{
97
    hg_class_t *hgcl = NULL;
Shane Snyder's avatar
Shane Snyder committed
98
    hg_addr_t self_addr = HG_ADDR_NULL;
99
    char *self_addr_str = NULL;
100
    hg_size_t self_addr_str_size = 0;
101 102 103
    const char *self_addr_substr = NULL;
    const char *addr_substr = NULL;
    int i;
Shane Snyder's avatar
Shane Snyder committed
104
    ssg_group_descriptor_t *group_descriptor = NULL;
105
    ssg_group_t *g = NULL;
106
    hg_return_t hret;
Shane Snyder's avatar
Shane Snyder committed
107
    ssg_group_id_t group_id = SSG_GROUP_ID_NULL;
108

109 110 111
    if (!ssg_inst) goto fini;

    hgcl = margo_get_class(ssg_inst->mid);
112
    if (!hgcl) goto fini;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
113

114
    /* generate a unique ID for this group  */
Shane Snyder's avatar
Shane Snyder committed
115 116
    group_descriptor = ssg_generate_group_descriptor(group_name, group_addr_strs[0]);
    if (group_descriptor == NULL) goto fini;
117

Shane Snyder's avatar
Shane Snyder committed
118 119 120
    /* make sure we aren't re-creating an existing group */
    HASH_FIND(hh, ssg_inst->group_table, &group_descriptor->name_hash,
        sizeof(uint64_t), g);
121 122 123 124 125 126 127 128
    if (g) goto fini;

    /* allocate an SSG group data structure and initialize some of it */
    g = malloc(sizeof(*g));
    if (!g) goto fini;
    memset(g, 0, sizeof(*g));
    g->group_name = strdup(group_name);
    if (!g->group_name) goto fini;
Shane Snyder's avatar
Shane Snyder committed
129
    g->group_descriptor = group_descriptor;
130 131 132 133 134 135 136 137
    // TODO? g->self_id = -1;
    g->group_view.size = group_size;
    g->group_view.member_states = malloc(
        group_size * sizeof(*g->group_view.member_states));
    if (!g->group_view.member_states) goto fini;
    memset(g->group_view.member_states, 0,
        group_size * sizeof(*g->group_view.member_states));

138
    /* get my address */
139 140
    hret = HG_Addr_self(hgcl, &self_addr);
    if (hret != HG_SUCCESS) goto fini;
141
    hret = HG_Addr_to_string(hgcl, NULL, &self_addr_str_size, self_addr);
142
    if (hret != HG_SUCCESS) goto fini;
143
    self_addr_str = malloc(self_addr_str_size);
144
    if (self_addr_str == NULL) goto fini;
145
    hret = HG_Addr_to_string(hgcl, self_addr_str, &self_addr_str_size, self_addr);
146 147
    if (hret != HG_SUCCESS) goto fini;

148 149 150 151
    /* strstr is used here b/c there may be inconsistencies in whether the class
     * is included in the address or not (it should not be in HG_Addr_to_string,
     * but it's possible that it is in the list of group address strings)
     */
152
    self_addr_substr = strstr(self_addr_str, "://");
Shane Snyder's avatar
Shane Snyder committed
153 154 155 156
    if (self_addr_substr == NULL)
        self_addr_substr = self_addr_str;
    else
        self_addr_substr += 3;
Shane Snyder's avatar
Shane Snyder committed
157

158 159 160 161
    /* resolve my rank within the group */
    for (i = 0; i < group_size; i++)
    {
        addr_substr = strstr(group_addr_strs[i], "://");
Shane Snyder's avatar
Shane Snyder committed
162 163 164 165
        if (addr_substr == NULL)
            addr_substr = group_addr_strs[i];
        else
            addr_substr += 3;
166 167 168
        if (strcmp(self_addr_substr, addr_substr) == 0)
        {
            /* this is my address -- my rank is the offset in the address array */
169 170
            g->self_id = i; // TODO 
            g->group_view.member_states[i].addr = self_addr;
171 172 173 174
        }
        else
        {
            /* initialize group member addresses to NULL before looking them up */
175
            g->group_view.member_states[i].addr = HG_ADDR_NULL;
176
        }
177
        g->group_view.member_states[i].is_member = 1;
178
    }
179
#if 0
180
    /* TODO: if unable to resolve my rank within the group, error out */
181
    if (g->self_id == -1)
182 183 184 185 186
    {
        fprintf(stderr, "Error: SSG unable to resolve rank in group %s\n",
            group_name);
        goto fini;
    }
187
#endif
188

189
    /* lookup hg address information for all group members */
190 191 192 193 194 195 196 197
    hret = ssg_group_lookup(g, group_addr_strs);
    if (hret != HG_SUCCESS)
    {
        fprintf(stderr, "Error: SSG unable to complete lookup for group %s\n",
            group_name);
        goto fini;
    }

198
#ifdef SSG_USE_SWIM_FD
199 200 201 202 203 204
    int swim_active = 1;
#ifdef SWIM_FORCE_FAIL
    if (g->self_rank == 1)
        swim_active = 0;
#endif

205
    /* initialize swim failure detector */
206 207
    // TODO: we should probably barrier or sync somehow to avoid rpc failures
    // due to timing skew of different ranks initializing swim
208
    g->fd_ctx = (void *)swim_init(g, swim_active);
209
    if (g->fd_ctx == NULL) goto fini;
210 211
#endif

212
    /* add this group reference to our group table */
Shane Snyder's avatar
Shane Snyder committed
213 214
    HASH_ADD(hh, ssg_inst->group_table, group_descriptor->name_hash,
        sizeof(uint64_t), g);
215

Shane Snyder's avatar
Shane Snyder committed
216 217 218 219 220 221
    /* everything successful -- set the output group identifier, which is just
     * an opaque pointer to the group descriptor structure
     */
    group_id = (ssg_group_id_t)group_descriptor;

    SSG_DEBUG(g, "group create successful (size=%d)\n", group_size);
222

223
    /* don't free these pointers on success */
Shane Snyder's avatar
Shane Snyder committed
224
    group_descriptor = NULL;
225
    self_addr = HG_ADDR_NULL;
226 227
    g = NULL;
fini:
Shane Snyder's avatar
Shane Snyder committed
228 229
    if (hgcl && self_addr != HG_ADDR_NULL) HG_Addr_free(hgcl, self_addr);
    free(self_addr_str);
Shane Snyder's avatar
Shane Snyder committed
230
    free(group_descriptor);
231 232
    if (g)
    {
233 234
        free(g->group_name);
        free(g->group_view.member_states);
235 236 237
        free(g);
    }

Shane Snyder's avatar
Shane Snyder committed
238
    return group_id;
239 240
}

Shane Snyder's avatar
Shane Snyder committed
241
ssg_group_id_t ssg_group_create_config(
242
    const char * group_name,
Shane Snyder's avatar
Shane Snyder committed
243
    const char * file_name)
244 245 246 247 248 249 250 251 252 253
{
    int fd;
    struct stat st;
    char *rd_buf = NULL;
    ssize_t rd_buf_sz;
    char *tok;
    void *addr_buf = NULL;
    int addr_buf_len = 0, num_addrs = 0;
    int ret;
    const char **addr_strs = NULL;
Shane Snyder's avatar
Shane Snyder committed
254
    ssg_group_id_t group_id = SSG_GROUP_ID_NULL;
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289

    /* open config file for reading */
    fd = open(file_name, O_RDONLY);
    if (fd == -1)
    {
        fprintf(stderr, "Error: SSG unable to open config file %s for group %s\n",
            file_name, group_name);
        goto fini;
    }

    /* get file size and allocate a buffer to store it */
    ret = fstat(fd, &st);
    if (ret == -1)
    {
        fprintf(stderr, "Error: SSG unable to stat config file %s for group %s\n",
            file_name, group_name);
        goto fini;
    }
    rd_buf = malloc(st.st_size+1);
    if (rd_buf == NULL) goto fini;

    /* load it all in one fell swoop */
    rd_buf_sz = read(fd, rd_buf, st.st_size);
    if (rd_buf_sz != st.st_size)
    {
        fprintf(stderr, "Error: SSG unable to read config file %s for group %s\n",
            file_name, group_name);
        goto fini;
    }
    rd_buf[rd_buf_sz]='\0';

    /* strtok the result - each space-delimited address is assumed to be
     * a unique mercury address
     */
    tok = strtok(rd_buf, "\r\n\t ");
Jonathan Jenkins's avatar
Jonathan Jenkins committed
290 291
    if (tok == NULL) goto fini;

292 293
    /* build up the address buffer */
    addr_buf = malloc(rd_buf_sz);
294
    if (addr_buf == NULL) goto fini;
295 296
    do
    {
Jonathan Jenkins's avatar
Jonathan Jenkins committed
297
        int tok_sz = strlen(tok);
298 299
        memcpy((char*)addr_buf + addr_buf_len, tok, tok_sz+1);
        addr_buf_len += tok_sz+1;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
300 301 302
        num_addrs++;
        tok = strtok(NULL, "\r\n\t ");
    } while (tok != NULL);
303 304 305 306 307 308 309
    if (addr_buf_len != rd_buf_sz)
    {
        /* adjust buffer size if our initial guess was wrong */
        void *tmp = realloc(addr_buf, addr_buf_len);
        if (tmp == NULL) goto fini;
        addr_buf = tmp;
    }
Jonathan Jenkins's avatar
Jonathan Jenkins committed
310

311 312 313
    /* set up address string array for group members */
    addr_strs = ssg_setup_addr_str_list(addr_buf, num_addrs);
    if (!addr_strs) goto fini;
314

315
    /* invoke the generic group create routine using our list of addrs */
Shane Snyder's avatar
Shane Snyder committed
316
    group_id = ssg_group_create(group_name, addr_strs, num_addrs);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
317 318

fini:
319
    /* cleanup before returning */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
320
    if (fd != -1) close(fd);
321
    free(rd_buf);
322
    free(addr_buf);
323 324
    free(addr_strs);

Shane Snyder's avatar
Shane Snyder committed
325
    return group_id;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
326 327
}

Shane Snyder's avatar
Shane Snyder committed
328
#ifdef SSG_HAVE_MPI
Shane Snyder's avatar
Shane Snyder committed
329
ssg_group_id_t ssg_group_create_mpi(
330
    const char * group_name,
Shane Snyder's avatar
Shane Snyder committed
331
    MPI_Comm comm)
Jonathan Jenkins's avatar
Jonathan Jenkins committed
332
{
333
    hg_class_t *hgcl = NULL;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
334
    hg_addr_t self_addr = HG_ADDR_NULL;
335
    char *self_addr_str = NULL;
336 337
    hg_size_t self_addr_str_size = 0;
    int self_addr_str_size_int = 0; /* for mpi-friendly conversion */
338 339 340 341 342
    char *addr_buf = NULL;
    int *sizes = NULL;
    int *sizes_psum = NULL;
    int comm_size = 0, comm_rank = 0;
    const char **addr_strs = NULL;
343
    hg_return_t hret;
Shane Snyder's avatar
Shane Snyder committed
344
    ssg_group_id_t group_id = SSG_GROUP_ID_NULL;
345

346 347 348
    if (!ssg_inst) goto fini;

    hgcl = margo_get_class(ssg_inst->mid);
349
    if (!hgcl) goto fini;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
350

351
    /* get my address */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
352 353
    hret = HG_Addr_self(hgcl, &self_addr);
    if (hret != HG_SUCCESS) goto fini;
354
    hret = HG_Addr_to_string(hgcl, NULL, &self_addr_str_size, self_addr);
Shane Snyder's avatar
Shane Snyder committed
355
    if (hret != HG_SUCCESS) goto fini;
356
    self_addr_str = malloc(self_addr_str_size);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
357
    if (self_addr_str == NULL) goto fini;
358
    hret = HG_Addr_to_string(hgcl, self_addr_str, &self_addr_str_size, self_addr);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
359
    if (hret != HG_SUCCESS) goto fini;
360
    self_addr_str_size_int = (int)self_addr_str_size; /* null char included in call */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
361

362
    /* gather the buffer sizes */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
363 364 365 366
    MPI_Comm_size(comm, &comm_size);
    MPI_Comm_rank(comm, &comm_rank);
    sizes = malloc(comm_size * sizeof(*sizes));
    if (sizes == NULL) goto fini;
367
    sizes[comm_rank] = self_addr_str_size_int;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
368 369
    MPI_Allgather(MPI_IN_PLACE, 0, MPI_BYTE, sizes, 1, MPI_INT, comm);

370 371 372
    /* compute a exclusive prefix sum of the data sizes, including the
     * total at the end
     */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
373 374 375 376 377 378
    sizes_psum = malloc((comm_size+1) * sizeof(*sizes_psum));
    if (sizes_psum == NULL) goto fini;
    sizes_psum[0] = 0;
    for (int i = 1; i < comm_size+1; i++)
        sizes_psum[i] = sizes_psum[i-1] + sizes[i-1];

379
    /* allgather the addresses */
380 381
    addr_buf = malloc(sizes_psum[comm_size]);
    if (addr_buf == NULL) goto fini;
382
    MPI_Allgatherv(self_addr_str, self_addr_str_size_int, MPI_BYTE,
383
            addr_buf, sizes, sizes_psum, MPI_BYTE, comm);
Jonathan Jenkins's avatar
Jonathan Jenkins committed
384

385 386 387 388 389
    /* set up address string array for group members */
    addr_strs = ssg_setup_addr_str_list(addr_buf, comm_size);
    if (!addr_strs) goto fini;

    /* invoke the generic group create routine using our list of addrs */
Shane Snyder's avatar
Shane Snyder committed
390
    group_id = ssg_group_create(group_name, addr_strs, comm_size);
Shane Snyder's avatar
Shane Snyder committed
391 392

fini:
393
    /* cleanup before returning */
Shane Snyder's avatar
Shane Snyder committed
394 395
    free(sizes);
    free(sizes_psum);
396
    free(addr_buf);
397 398
    if (hgcl && self_addr != HG_ADDR_NULL) HG_Addr_free(hgcl, self_addr);
    free(self_addr_str);
399 400
    free(addr_strs);

Shane Snyder's avatar
Shane Snyder committed
401
    return group_id;
Shane Snyder's avatar
Shane Snyder committed
402 403 404
}
#endif

405 406
int ssg_group_destroy(
    ssg_group_id_t group_id)
Shane Snyder's avatar
Shane Snyder committed
407
{
Shane Snyder's avatar
Shane Snyder committed
408
    ssg_group_descriptor_t *group_descriptor = (ssg_group_descriptor_t *)group_id;
409 410
    ssg_group_t *g;
    int sret;
411

Shane Snyder's avatar
Shane Snyder committed
412
    if (!ssg_inst || group_id == SSG_GROUP_ID_NULL)
413
        return SSG_FAILURE;
414

415
    /* find the group structure and destroy it */
Shane Snyder's avatar
Shane Snyder committed
416 417
    HASH_FIND(hh, ssg_inst->group_table, &group_descriptor->name_hash,
        sizeof(uint64_t), g);
418 419
    HASH_DELETE(hh, ssg_inst->group_table, g);
    sret = ssg_group_destroy_internal(g);
420

421
    return sret;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
422 423
}

424 425 426
int ssg_group_attach(
    ssg_group_id_t group_id)
{
Shane Snyder's avatar
Shane Snyder committed
427
    ssg_group_descriptor_t *group_descriptor = (ssg_group_descriptor_t *)group_id;
428 429
    hg_return_t hret;

Shane Snyder's avatar
Shane Snyder committed
430
    if (!ssg_inst || group_id == SSG_GROUP_ID_NULL)
431
        return SSG_FAILURE;
432

Shane Snyder's avatar
Shane Snyder committed
433
    hret = ssg_group_attach_send(group_descriptor);
434 435
    if (hret != HG_SUCCESS)
        return SSG_FAILURE;
436 437 438 439 440 441 442 443 444 445

    return SSG_SUCCESS;
}

int ssg_group_detach(
    ssg_group_id_t group_id)
{
    return SSG_SUCCESS;
}

446 447 448
/*********************************
 *** SSG group access routines ***
 *********************************/
Shane Snyder's avatar
Shane Snyder committed
449

450
ssg_member_id_t ssg_get_group_self_id(
451
    ssg_group_id_t group_id)
Shane Snyder's avatar
Shane Snyder committed
452
{
Shane Snyder's avatar
Shane Snyder committed
453
    ssg_group_descriptor_t *group_descriptor = (ssg_group_descriptor_t *)group_id;
454 455
    ssg_group_t *g;

Shane Snyder's avatar
Shane Snyder committed
456 457
    if (!ssg_inst || group_id == SSG_GROUP_ID_NULL)
        return SSG_MEMBER_ID_NULL;
458

Shane Snyder's avatar
Shane Snyder committed
459 460
    HASH_FIND(hh, ssg_inst->group_table, &group_descriptor->name_hash,
        sizeof(uint64_t), g);
461
    if (!g)
Shane Snyder's avatar
Shane Snyder committed
462
        return SSG_MEMBER_ID_NULL;
463 464

    return g->self_id;
Shane Snyder's avatar
Shane Snyder committed
465 466
}

467 468
int ssg_get_group_size(
    ssg_group_id_t group_id)
Shane Snyder's avatar
Shane Snyder committed
469
{
Shane Snyder's avatar
Shane Snyder committed
470
    ssg_group_descriptor_t *group_descriptor = (ssg_group_descriptor_t *)group_id;
471 472
    ssg_group_t *g;

Shane Snyder's avatar
Shane Snyder committed
473
    if (!ssg_inst || group_id == SSG_GROUP_ID_NULL)
474 475
        return 0;

Shane Snyder's avatar
Shane Snyder committed
476 477
    HASH_FIND(hh, ssg_inst->group_table, &group_descriptor->name_hash,
        sizeof(uint64_t), g);
478 479 480 481
    if (!g)
        return 0;

    return g->group_view.size;
Shane Snyder's avatar
Shane Snyder committed
482 483
}

484 485 486
hg_addr_t ssg_get_addr(
    ssg_group_id_t group_id,
    ssg_member_id_t member_id)
Shane Snyder's avatar
Shane Snyder committed
487
{
Shane Snyder's avatar
Shane Snyder committed
488
    ssg_group_descriptor_t *group_descriptor = (ssg_group_descriptor_t *)group_id;
489 490
    ssg_group_t *g;

Shane Snyder's avatar
Shane Snyder committed
491
    if (!ssg_inst || group_id == SSG_GROUP_ID_NULL)
492 493
        return HG_ADDR_NULL;

Shane Snyder's avatar
Shane Snyder committed
494 495
    HASH_FIND(hh, ssg_inst->group_table, &group_descriptor->name_hash,
        sizeof(uint64_t), g);
496 497 498
    if (!g)
        return HG_ADDR_NULL;

499
    return g->group_view.member_states[member_id].addr;
Shane Snyder's avatar
Shane Snyder committed
500 501
}

502 503 504
/************************************
 *** SSG internal helper routines ***
 ************************************/
505

Shane Snyder's avatar
Shane Snyder committed
506 507
static ssg_group_descriptor_t * ssg_generate_group_descriptor(
    const char * name, const char * leader_addr_str)
508
{
Shane Snyder's avatar
Shane Snyder committed
509
    ssg_group_descriptor_t *group_descriptor;
510 511
    uint32_t upper, lower;

Shane Snyder's avatar
Shane Snyder committed
512 513 514
    group_descriptor = malloc(sizeof(*group_descriptor));
    if (!group_descriptor) return NULL;

515 516 517
    /* hash the group name to obtain an 64-bit unique ID */
    ssg_hashlittle2(name, strlen(name), &lower, &upper);

Shane Snyder's avatar
Shane Snyder committed
518 519 520 521 522 523 524 525
    group_descriptor->magic_nr = SSG_MAGIC_NR;
    group_descriptor->name_hash = lower + (((uint64_t)upper)<<32);
    group_descriptor->addr_str = strdup(leader_addr_str);
    if (!group_descriptor->addr_str)
    {
        free(group_descriptor);
        return NULL;
    }
526

Shane Snyder's avatar
Shane Snyder committed
527
    return group_descriptor;
528 529
}

530 531 532 533 534 535 536
static const char ** ssg_setup_addr_str_list(
    char * buf, int num_addrs)
{
    const char **ret = malloc(num_addrs * sizeof(*ret));
    if (ret == NULL) return NULL;

    ret[0] = buf;
537 538
    for (int i = 1; i < num_addrs; i++)
    {
539 540
        const char * a = ret[i-1];
        ret[i] = a + strlen(a) + 1;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
541
    }
542
    return ret;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
543
}
544 545 546

static int ssg_group_destroy_internal(ssg_group_t *g)
{
Shane Snyder's avatar
Shane Snyder committed
547
    unsigned int i;
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571

    /* TODO: send a leave message to the group ? */

#ifdef SSG_USE_SWIM_FD
    /* free up failure detector state */
    if(g->fd_ctx)
        swim_finalize(g->fd_ctx);
#endif

    /* destroy group state */
    for (i = 0; i < g->group_view.size; i++)
    {
        if (g->group_view.member_states[i].addr != HG_ADDR_NULL)
        {
            HG_Addr_free(margo_get_class(ssg_inst->mid),
                g->group_view.member_states[i].addr);
        }
    }
    free(g->group_name);
    free(g->group_view.member_states);
    free(g);

    return SSG_SUCCESS;
}