ssg-launch-group.c 5.78 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * Copyright (c) 2016 UChicago Argonne, LLC
 *
 * See COPYRIGHT in top-level directory.
 */

#include <ssg-config.h>

#include <unistd.h>
#include <stdio.h>
#include <string.h>
Shane Snyder's avatar
Shane Snyder committed
12
#ifdef SSG_HAVE_MPI
13 14
#include <mpi.h>
#endif
Shane Snyder's avatar
Shane Snyder committed
15 16 17
#ifdef SSG_HAVE_PMIX
#include <pmix.h>
#endif
18 19 20

#include <margo.h>
#include <ssg.h>
Shane Snyder's avatar
Shane Snyder committed
21
#ifdef SSG_HAVE_MPI
22 23
#include <ssg-mpi.h>
#endif
24 25 26
#ifdef SSG_HAVE_PMIX
#include <ssg-pmix.h>
#endif
27 28 29 30 31 32

#define DIE_IF(cond_expr, err_fmt, ...) \
    do { \
        if (cond_expr) { \
            fprintf(stderr, "ERROR at %s:%d (" #cond_expr "): " \
                    err_fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
33
            exit(EXIT_FAILURE); \
34 35 36
        } \
    } while(0)

37 38
struct group_launch_opts
{
39
    char *addr_str;
40
    char *group_mode;
41
    int shutdown_time;
42 43
    char *gid_file;
    char *group_name;
44 45
};

46 47 48 49
static void usage()
{
    fprintf(stderr,
        "Usage: "
50
        "ssg-launch-group [OPTIONS] <ADDR> <MODE>\n"
51
        "Create and launch group using given Mercury ADDR string and group create MODE (\"mpi\" or \"pmix\").\n"
52 53
        "\n"
        "OPTIONS:\n"
54 55 56
        "\t-s <TIME>\t\tTime duration (in seconds) to run the group before shutting down\n"
        "\t-f <FILE>\t\tFile path to store group ID in\n"
        "\t-n <NAME>\t\tName of the group to launch\n");
57 58
}

59
static void parse_args(int argc, char *argv[], struct group_launch_opts *opts)
60
{
61
    int c;
62
    const char *options = "s:f:n:";
63
    char *check = NULL;
64

65
    while ((c = getopt(argc, argv, options)) != -1)
66
    {
67
        switch (c)
68
        {
69 70 71
            case 's':
                opts->shutdown_time = (int)strtol(optarg, &check, 0);
                if (opts->shutdown_time < 0 || (check && *check != '\0'))
72 73 74 75 76 77 78 79
                {
                    usage();
                    exit(EXIT_FAILURE);
                }
                break;
            case 'f':
                opts->gid_file = optarg;
                break;
80 81 82
            case 'n':
                opts->group_name = optarg;
                break;
83 84 85
            default:
                usage();
                exit(EXIT_FAILURE);
86 87 88
        }
    }

89 90 91 92 93
    if ((argc - optind) < 2)
    {
        usage();
        exit(EXIT_FAILURE);
    }
94

95 96
    opts->addr_str = argv[optind++];
    opts->group_mode = argv[optind++];
97
    if (strcmp(opts->group_mode, "mpi") == 0)
98
    {
99 100
#ifdef SSG_HAVE_MPI
        if (optind != argc)
101 102
        {
            usage();
103
            exit(EXIT_FAILURE);
104
        }
105 106 107 108
#else
        fprintf(stderr, "Error: MPI support not built in\n");
        exit(EXIT_FAILURE);
#endif
109
    }
110
    else if (strcmp(opts->group_mode, "pmix") == 0)
111
    {
112
#ifdef SSG_HAVE_PMIX
113
        if (optind != argc)
114 115
        {
            usage();
116
            exit(EXIT_FAILURE);
117 118
        }
#else
119
        fprintf(stderr, "Error: PMIx support not built in\n");
120
        exit(EXIT_FAILURE);
121 122 123 124 125
#endif
    }
    else
    {
        usage();
126
        exit(EXIT_FAILURE);
127
    }
128 129

    return;
130 131 132 133
}

int main(int argc, char *argv[])
{
134
    struct group_launch_opts opts;
135
    margo_instance_id mid = MARGO_INSTANCE_NULL;
136
    ssg_group_id_t g_id = SSG_GROUP_ID_INVALID;
137
    ssg_member_id_t my_id;
138
    ssg_group_config_t g_conf = SSG_GROUP_CONFIG_INITIALIZER;
139
    int group_size;
140
    int sret;
141

142
    /* set any default options (that may be overwritten by cmd args) */
143
    opts.shutdown_time = 10; /* default to running group for 10 seconds */
144 145 146 147
    opts.group_name = "simple_group";
    opts.gid_file = NULL;

    /* parse cmdline arguments */
148
    parse_args(argc, argv, &opts);
149

Shane Snyder's avatar
Shane Snyder committed
150
#ifdef SSG_HAVE_MPI
151
    int mpi_rank, mpi_size;
152
    if (strcmp(opts.group_mode, "mpi") == 0)
153
    {
154
        MPI_Init(&argc, &argv);
155 156 157
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
        MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
    }
158
#endif
159 160 161 162 163 164 165 166 167
#ifdef SSG_HAVE_PMIX
    pmix_status_t ret;
    pmix_proc_t proc;
    if (strcmp(opts.group_mode, "pmix") == 0)
    {
        ret = PMIx_Init(&proc, NULL, 0);
        DIE_IF(ret != PMIX_SUCCESS, "PMIx_Init");
    }
#endif
168

169 170
    /* init margo */
    /* use the main xstream to drive progress & run handlers */
171
    mid = margo_init(opts.addr_str, MARGO_SERVER_MODE, 0, -1);
172 173 174
    DIE_IF(mid == MARGO_INSTANCE_NULL, "margo_init");

    /* initialize SSG */
175
    sret = ssg_init();
176
    DIE_IF(sret != SSG_SUCCESS, "ssg_init");
177

178 179 180 181 182
    /* set non-default group config parameters */
    g_conf.swim_period_length_ms = 1000; /* 1-second period length */
    g_conf.swim_suspect_timeout_periods = 4; /* 4-period suspicion length */
    g_conf.swim_subgroup_member_count = 3; /* 3-member subgroups for SWIM */

183
    /* XXX do we want to use callback for testing anything about group??? */
Shane Snyder's avatar
Shane Snyder committed
184
#ifdef SSG_HAVE_MPI
185
    if(strcmp(opts.group_mode, "mpi") == 0)
186 187
        g_id = ssg_group_create_mpi(mid, opts.group_name, MPI_COMM_WORLD, &g_conf,
            NULL, NULL);
188 189 190
#endif
#ifdef SSG_HAVE_PMIX
    if(strcmp(opts.group_mode, "pmix") == 0)
191 192
        g_id = ssg_group_create_pmix(mid, opts.group_name, proc, &g_conf,
            NULL, NULL);
193
#endif
194
    DIE_IF(g_id == SSG_GROUP_ID_INVALID, "ssg_group_create");
195

196 197 198 199 200
    /* store the gid if requested */
    if (opts.gid_file)
        ssg_group_id_store(opts.gid_file, g_id);

    /* sleep for given duration to allow group time to run */
201 202
    if (opts.shutdown_time > 0)
        margo_thread_sleep(mid, opts.shutdown_time * 1000.0);
203

204
    /* get my group id and the size of the group */
205
    my_id = ssg_get_self_id(mid);
206
    DIE_IF(my_id == SSG_MEMBER_ID_INVALID, "ssg_get_group_self_id");
207 208 209
    group_size = ssg_get_group_size(g_id);
    DIE_IF(group_size == 0, "ssg_get_group_size");

210 211
    /* print group at each member */
    ssg_group_dump(g_id);
212
    ssg_group_destroy(g_id);
213

214
    /** cleanup **/
215 216
    ssg_finalize();
    margo_finalize(mid);
Shane Snyder's avatar
Shane Snyder committed
217
#ifdef SSG_HAVE_MPI
218
    if (strcmp(opts.group_mode, "mpi") == 0)
219
        MPI_Finalize();
220
#endif
221 222 223 224
#ifdef SSG_HAVE_PMIX
    if (strcmp(opts.group_mode, "pmix") == 0)
        PMIx_Finalize(NULL, 0);
#endif
225 226 227

    return 0;
}