margo-example-mp-server.c 4.57 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * (C) 2015 The University of Chicago
 * 
 * See COPYRIGHT in top-level directory.
 */

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <abt.h>
#include <margo.h>
12
#include <margo-config.h>
13 14 15
#ifdef HAVE_ABT_SNOOZER
#include <abt-snoozer.h>
#endif
Philip Carns's avatar
Philip Carns committed
16 17
#include "svc1-server.h"
#include "svc2-server.h"
18 19 20 21 22 23 24 25 26 27 28 29 30

/* example server program that starts a skeleton for sub-services within
 * this process to register with
 */

/* this is a "common" rpc that is handled by the core daemon
 */

static void my_rpc_shutdown_ult(hg_handle_t handle)
{
    hg_return_t hret;
    margo_instance_id mid;

31
    //printf("Got RPC request to shutdown\n");
32

33
    mid = margo_hg_handle_get_instance(handle);
34
    assert(mid != MARGO_INSTANCE_NULL);
35 36 37 38

    hret = margo_respond(mid, handle, NULL);
    assert(hret == HG_SUCCESS);

Shane Snyder's avatar
Shane Snyder committed
39
    margo_destroy(mid, handle);
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

    /* NOTE: we assume that the server daemon is using
     * margo_wait_for_finalize() to suspend until this RPC executes, so there
     * is no need to send any extra signal to notify it.
     */
    margo_finalize(mid);

    return;
}
DEFINE_MARGO_RPC_HANDLER(my_rpc_shutdown_ult)


int main(int argc, char **argv) 
{
    int ret;
    margo_instance_id mid;
56
    hg_return_t hret;
57 58 59
    hg_addr_t addr_self;
    char addr_self_string[128];
    hg_size_t addr_self_string_sz = 128;
60 61
    ABT_xstream svc1_xstream2;
    ABT_pool svc1_pool2;
Philip Carns's avatar
Philip Carns committed
62
    ABT_pool *handler_pool;
63 64 65 66 67 68 69 70

    if(argc != 2)
    {
        fprintf(stderr, "Usage: ./server <listen_addr>\n");
        fprintf(stderr, "Example: ./server na+sm://\n");
        return(-1);
    }

71 72 73
    /* actually start margo -- this step encapsulates the Mercury and
     * Argobots initialization and must precede their use */
    /* Use the calling xstream to drive progress and execute handlers. */
74
    /***************************************/
75 76
    mid = margo_init(argv[1], MARGO_SERVER_MODE, 0, -1);
    if(mid == MARGO_INSTANCE_NULL)
77
    {
78
        fprintf(stderr, "Error: margo_init()\n");
79 80 81 82
        return(-1);
    }

    /* figure out what address this server is listening on */
83 84
    hret = margo_addr_self(mid, &addr_self);
    if(hret != HG_SUCCESS)
85
    {
86 87
        fprintf(stderr, "Error: margo_addr_self()\n");
        margo_finalize(mid);
88 89
        return(-1);
    }
90 91
    hret = margo_addr_to_string(mid, addr_self_string, &addr_self_string_sz, addr_self);
    if(hret != HG_SUCCESS)
92
    {
93 94 95
        fprintf(stderr, "Error: margo_addr_to_string()\n");
        margo_addr_free(mid, addr_self);
        margo_finalize(mid);
96 97
        return(-1);
    }
98
    margo_addr_free(mid, addr_self);
99

100
    printf("# accepting RPCs on address \"%s\"\n", addr_self_string);
101

102 103 104
    /* register RPCs and services */
    /***************************************/

105 106 107
    /* register a shutdown RPC as just a generic handler; not part of a
     * multiplexed service
     */
108
    MARGO_REGISTER(mid, "my_shutdown_rpc", void, void, my_rpc_shutdown_ult);
109

110 111 112
    /* register svc1, with mplex_id 1, to execute on the default handler pool
     * used by Margo
     */
Philip Carns's avatar
Philip Carns committed
113 114
    handler_pool = margo_get_handler_pool(mid);
    ret = svc1_register(mid, *handler_pool, 1);
115 116
    assert(ret == 0);

117
    /* create a dedicated xstream and pool for another instance of svc1 */
118
#ifdef HAVE_ABT_SNOOZER
119
    ret = ABT_snoozer_xstream_create(1, &svc1_pool2, &svc1_xstream2);
120 121 122 123 124 125 126
	assert(ret == 0);
#else
	ret = ABT_xstream_create(ABT_SCHED_NULL, &svc1_xstream2);
	assert(ret == 0);
	ret = ABT_xstream_get_main_pools(svc1_xstream2, 1, &svc1_pool2);
	assert(ret == 0);
#endif
127 128 129 130 131 132 133
    /* register svc1, with mplex_id 2, to execute on a separate pool.  This
     * will result in svc1 being registered twice, with the client being able
     * to dictate which instance they want to target
     */
    ret = svc1_register(mid, svc1_pool2, 2);
    assert(ret == 0);

134 135 136
    /* register svc2, with mplex_id 3, to execute on the default handler pool
     * used by Margo
     */
Philip Carns's avatar
Philip Carns committed
137 138
    handler_pool = margo_get_handler_pool(mid);
    ret = svc2_register(mid, *handler_pool, 3);
139 140 141 142
    assert(ret == 0);

    /* shut things down */
    /****************************************/
143

144 145 146 147 148 149 150
    /* NOTE: there isn't anything else for the server to do at this point
     * except wait for itself to be shut down.  The
     * margo_wait_for_finalize() call here yields to let Margo drive
     * progress until that happens.
     */
    margo_wait_for_finalize(mid);

151
    /*  TODO: rethink this; can't touch mid or use ABT after wait for finalize */
Philip Carns's avatar
Philip Carns committed
152
#if 0
Philip Carns's avatar
Philip Carns committed
153 154 155
    svc1_deregister(mid, *handler_pool, 1);
    svc1_deregister(mid, svc1_pool2, 2);
    svc2_deregister(mid, *handler_pool, 3);
156 157 158

    ABT_xstream_join(svc1_xstream2);
    ABT_xstream_free(&svc1_xstream2);
159
#endif
160 161 162 163

    return(0);
}