root/opal/mca/pmix/pmix4x/pmix/examples/client.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. notification_fn
  2. release_fn
  3. evhandler_reg_callbk
  4. main

   1 /*
   2  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2011 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2006-2013 Los Alamos National Security, LLC.
  13  *                         All rights reserved.
  14  * Copyright (c) 2009-2012 Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2011      Oak Ridge National Labs.  All rights reserved.
  16  * Copyright (c) 2013-2019 Intel, Inc.  All rights reserved.
  17  * Copyright (c) 2015      Mellanox Technologies, Inc.  All rights reserved.
  18  * $COPYRIGHT$
  19  *
  20  * Additional copyrights may follow
  21  *
  22  * $HEADER$
  23  *
  24  */
  25 
  26 #define _GNU_SOURCE
  27 #include <stdbool.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <unistd.h>
  31 #include <time.h>
  32 
  33 #include <pmix.h>
  34 #include "examples.h"
  35 
  36 static pmix_proc_t myproc;
  37 
  38 /* this is the event notification function we pass down below
  39  * when registering for general events - i.e.,, the default
  40  * handler. We don't technically need to register one, but it
  41  * is usually good practice to catch any events that occur */
  42 static void notification_fn(size_t evhdlr_registration_id,
  43                             pmix_status_t status,
  44                             const pmix_proc_t *source,
  45                             pmix_info_t info[], size_t ninfo,
  46                             pmix_info_t results[], size_t nresults,
  47                             pmix_event_notification_cbfunc_fn_t cbfunc,
  48                             void *cbdata)
  49 {
  50     if (NULL != cbfunc) {
  51         cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
  52     }
  53 }
  54 
  55 /* this is an event notification function that we explicitly request
  56  * be called when the PMIX_ERR_DEBUGGER_RELEASE notification is issued.
  57  * We could catch it in the general event notification function and test
  58  * the status to see if it was "debugger release", but it often is simpler
  59  * to declare a use-specific notification callback point. In this case,
  60  * we are asking to know when we are told the debugger released us */
  61 static void release_fn(size_t evhdlr_registration_id,
  62                        pmix_status_t status,
  63                        const pmix_proc_t *source,
  64                        pmix_info_t info[], size_t ninfo,
  65                        pmix_info_t results[], size_t nresults,
  66                        pmix_event_notification_cbfunc_fn_t cbfunc,
  67                        void *cbdata)
  68 {
  69     myrel_t *lock;
  70     size_t n;
  71 
  72     /* find the return object */
  73     lock = NULL;
  74     for (n=0; n < ninfo; n++) {
  75         if (0 == strncmp(info[n].key, PMIX_EVENT_RETURN_OBJECT, PMIX_MAX_KEYLEN)) {
  76             lock = (myrel_t*)info[n].value.data.ptr;
  77             break;
  78         }
  79     }
  80     /* if the object wasn't returned, then that is an error */
  81     if (NULL == lock) {
  82         fprintf(stderr, "LOCK WASN'T RETURNED IN RELEASE CALLBACK\n");
  83         /* let the event handler progress */
  84         if (NULL != cbfunc) {
  85             cbfunc(PMIX_SUCCESS, NULL, 0, NULL, NULL, cbdata);
  86         }
  87         return;
  88     }
  89 
  90     /* tell the event handler state machine that we are the last step */
  91     if (NULL != cbfunc) {
  92         cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
  93     }
  94     /* the status will be PMIX_ERR_DEBUGGER_RELEASE since that is the code
  95      * we registered to receive, so just return success */
  96     lock->lock.status = PMIX_SUCCESS;
  97     /* release the lock */
  98     DEBUG_WAKEUP_THREAD(&lock->lock);
  99 }
 100 
 101 /* event handler registration is done asynchronously because it
 102  * may involve the PMIx server registering with the host RM for
 103  * external events. So we provide a callback function that returns
 104  * the status of the request (success or an error), plus a numerical index
 105  * to the registered event. The index is used later on to deregister
 106  * an event handler - if we don't explicitly deregister it, then the
 107  * PMIx server will do so when it see us exit */
 108 static void evhandler_reg_callbk(pmix_status_t status,
 109                                  size_t evhandler_ref,
 110                                  void *cbdata)
 111 {
 112     mylock_t *lock = (mylock_t*)cbdata;
 113 
 114     if (PMIX_SUCCESS != status) {
 115         fprintf(stderr, "Client %s:%d EVENT HANDLER REGISTRATION FAILED WITH STATUS %d, ref=%lu\n",
 116                    myproc.nspace, myproc.rank, status, (unsigned long)evhandler_ref);
 117     }
 118     lock->status = status;
 119     lock->evhandler_ref = evhandler_ref;
 120     DEBUG_WAKEUP_THREAD(lock);
 121 }
 122 
 123 int main(int argc, char **argv)
 124 {
 125     pmix_status_t rc;
 126     pmix_value_t value;
 127     pmix_value_t *val = &value;
 128     char *tmp;
 129     pmix_proc_t proc;
 130     uint32_t nprocs, n;
 131     pmix_info_t *info;
 132     bool flag;
 133     mylock_t mylock;
 134     myrel_t myrel;
 135     pmix_status_t dbg = PMIX_ERR_DEBUGGER_RELEASE;
 136     pid_t pid;
 137 
 138     pid = getpid();
 139     fprintf(stderr, "Client %lu: Running\n", (unsigned long)pid);
 140 
 141     /* init us - note that the call to "init" includes the return of
 142      * any job-related info provided by the RM. This includes any
 143      * debugger flag instructing us to stop-in-init. If such a directive
 144      * is included, then the process will be stopped in this call until
 145      * the "debugger release" notification arrives */
 146     if (PMIX_SUCCESS != (rc = PMIx_Init(&myproc, NULL, 0))) {
 147         fprintf(stderr, "Client ns %s rank %d: PMIx_Init failed: %d\n", myproc.nspace, myproc.rank, rc);
 148         exit(0);
 149     }
 150     fprintf(stderr, "Client ns %s rank %d pid %lu: Running\n", myproc.nspace, myproc.rank, (unsigned long)pid);
 151 
 152 
 153     /* register our default event handler - again, this isn't strictly
 154      * required, but is generally good practice */
 155     DEBUG_CONSTRUCT_LOCK(&mylock);
 156     PMIx_Register_event_handler(NULL, 0, NULL, 0,
 157                                 notification_fn, evhandler_reg_callbk, (void*)&mylock);
 158     DEBUG_WAIT_THREAD(&mylock);
 159     rc = mylock.status;
 160     DEBUG_DESTRUCT_LOCK(&mylock);
 161 
 162     if (PMIX_SUCCESS != rc) {
 163         fprintf(stderr, "[%s:%d] Default handler registration failed\n", myproc.nspace, myproc.rank);
 164         goto done;
 165     }
 166 
 167     /* job-related info is found in our nspace, assigned to the
 168      * wildcard rank as it doesn't relate to a specific rank. Setup
 169      * a name to retrieve such values */
 170     PMIX_PROC_CONSTRUCT(&proc);
 171     (void)strncpy(proc.nspace, myproc.nspace, PMIX_MAX_NSLEN);
 172     proc.rank = PMIX_RANK_WILDCARD;
 173 
 174     /* check to see if we have been instructed to wait for a debugger
 175      * to attach to us. We won't get both a stop-in-init AND a
 176      * wait-for-notify directive, so we should never stop twice. This
 177      * directive is provided so that something like an MPI implementation
 178      * can do some initial setup in MPI_Init prior to pausing for the
 179      * debugger */
 180     if (PMIX_SUCCESS == (rc = PMIx_Get(&proc, PMIX_DEBUG_WAIT_FOR_NOTIFY, NULL, 0, &val))) {
 181         /* register for debugger release */
 182         DEBUG_CONSTRUCT_LOCK(&mylock);
 183         PMIX_INFO_CREATE(info, 1);
 184         DEBUG_CONSTRUCT_MYREL(&myrel);
 185         PMIX_INFO_LOAD(&info[0], PMIX_EVENT_RETURN_OBJECT, &myrel, PMIX_POINTER);
 186         PMIx_Register_event_handler(&dbg, 1, info, 1,
 187                                     release_fn, evhandler_reg_callbk, (void*)&mylock);
 188         /* wait for registration to complete */
 189         DEBUG_WAIT_THREAD(&mylock);
 190         rc = mylock.status;
 191         DEBUG_DESTRUCT_LOCK(&mylock);
 192         PMIX_INFO_FREE(info, 1);
 193         if (PMIX_SUCCESS != rc) {
 194             fprintf(stderr, "[%s:%d] Debug handler registration failed\n", myproc.nspace, myproc.rank);
 195             goto done;
 196         }
 197         /* wait for debugger release */
 198         DEBUG_WAIT_THREAD(&myrel.lock);
 199         DEBUG_DESTRUCT_MYREL(&myrel);
 200     }
 201 
 202     /* get our universe size */
 203     if (PMIX_SUCCESS != (rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, &val))) {
 204         fprintf(stderr, "Client ns %s rank %d: PMIx_Get universe size failed: %d\n", myproc.nspace, myproc.rank, rc);
 205         goto done;
 206     }
 207     fprintf(stderr, "Client %s:%d universe size %d\n", myproc.nspace, myproc.rank, val->data.uint32);
 208     /* get the number of procs in our job - univ size is the total number of allocated
 209      * slots, not the number of procs in the job */
 210     if (PMIX_SUCCESS != (rc = PMIx_Get(&proc, PMIX_JOB_SIZE, NULL, 0, &val))) {
 211         fprintf(stderr, "Client ns %s rank %d: PMIx_Get job size failed: %d\n", myproc.nspace, myproc.rank, rc);
 212         goto done;
 213     }
 214     nprocs = val->data.uint32;
 215     PMIX_VALUE_RELEASE(val);
 216     fprintf(stderr, "Client %s:%d num procs %d\n", myproc.nspace, myproc.rank, nprocs);
 217 
 218     /* put a few values */
 219     if (0 > asprintf(&tmp, "%s-%d-internal", myproc.nspace, myproc.rank)) {
 220         exit(1);
 221     }
 222     value.type = PMIX_UINT32;
 223     value.data.uint32 = 1234;
 224     if (PMIX_SUCCESS != (rc = PMIx_Store_internal(&myproc, tmp, &value))) {
 225         fprintf(stderr, "Client ns %s rank %d: PMIx_Store_internal failed: %d\n", myproc.nspace, myproc.rank, rc);
 226         goto done;
 227     }
 228     free(tmp);
 229 
 230     if (0 > asprintf(&tmp, "%s-%d-local", myproc.nspace, myproc.rank)) {
 231         exit(1);
 232     }
 233     value.type = PMIX_UINT64;
 234     value.data.uint64 = 1234;
 235     if (PMIX_SUCCESS != (rc = PMIx_Put(PMIX_LOCAL, tmp, &value))) {
 236         fprintf(stderr, "Client ns %s rank %d: PMIx_Put internal failed: %d\n", myproc.nspace, myproc.rank, rc);
 237         goto done;
 238     }
 239     free(tmp);
 240 
 241     if (0 > asprintf(&tmp, "%s-%d-remote", myproc.nspace, myproc.rank)) {
 242         exit(1);
 243     }
 244     value.type = PMIX_STRING;
 245     value.data.string = "1234";
 246     if (PMIX_SUCCESS != (rc = PMIx_Put(PMIX_REMOTE, tmp, &value))) {
 247         fprintf(stderr, "Client ns %s rank %d: PMIx_Put internal failed: %d\n", myproc.nspace, myproc.rank, rc);
 248         goto done;
 249     }
 250     free(tmp);
 251 
 252     /* push the data to our PMIx server */
 253     if (PMIX_SUCCESS != (rc = PMIx_Commit())) {
 254         fprintf(stderr, "Client ns %s rank %d: PMIx_Commit failed: %d\n", myproc.nspace, myproc.rank, rc);
 255         goto done;
 256     }
 257 
 258     /* call fence to synchronize with our peers - instruct
 259      * the fence operation to collect and return all "put"
 260      * data from our peers */
 261     PMIX_INFO_CREATE(info, 1);
 262     flag = true;
 263     PMIX_INFO_LOAD(info, PMIX_COLLECT_DATA, &flag, PMIX_BOOL);
 264     if (PMIX_SUCCESS != (rc = PMIx_Fence(&proc, 1, info, 1))) {
 265         fprintf(stderr, "Client ns %s rank %d: PMIx_Fence failed: %d\n", myproc.nspace, myproc.rank, rc);
 266         goto done;
 267     }
 268     PMIX_INFO_FREE(info, 1);
 269 
 270     /* check the returned data */
 271     for (n=0; n < nprocs; n++) {
 272         if (0 > asprintf(&tmp, "%s-%d-local", myproc.nspace, myproc.rank)) {
 273             exit(1);
 274         }
 275         if (PMIX_SUCCESS != (rc = PMIx_Get(&myproc, tmp, NULL, 0, &val))) {
 276             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s failed: %d\n", myproc.nspace, myproc.rank, tmp, rc);
 277             goto done;
 278         }
 279         if (PMIX_UINT64 != val->type) {
 280             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned wrong type: %d\n", myproc.nspace, myproc.rank, tmp, val->type);
 281             PMIX_VALUE_RELEASE(val);
 282             free(tmp);
 283             goto done;
 284         }
 285         if (1234 != val->data.uint64) {
 286             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned wrong value: %d\n", myproc.nspace, myproc.rank, tmp, (int)val->data.uint64);
 287             PMIX_VALUE_RELEASE(val);
 288             free(tmp);
 289             goto done;
 290         }
 291         fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned correct\n", myproc.nspace, myproc.rank, tmp);
 292         PMIX_VALUE_RELEASE(val);
 293         free(tmp);
 294         if (0 > asprintf(&tmp, "%s-%d-remote", myproc.nspace, myproc.rank)) {
 295             exit(1);
 296         }
 297         if (PMIX_SUCCESS != (rc = PMIx_Get(&myproc, tmp, NULL, 0, &val))) {
 298             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s failed: %d\n", myproc.nspace, myproc.rank, tmp, rc);
 299             goto done;
 300         }
 301         if (PMIX_STRING != val->type) {
 302             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned wrong type: %d\n", myproc.nspace, myproc.rank, tmp, val->type);
 303             PMIX_VALUE_RELEASE(val);
 304             free(tmp);
 305             goto done;
 306         }
 307         if (0 != strcmp(val->data.string, "1234")) {
 308             fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned wrong value: %s\n", myproc.nspace, myproc.rank, tmp, val->data.string);
 309             PMIX_VALUE_RELEASE(val);
 310             free(tmp);
 311             goto done;
 312         }
 313         fprintf(stderr, "Client ns %s rank %d: PMIx_Get %s returned correct\n", myproc.nspace, myproc.rank, tmp);
 314         PMIX_VALUE_RELEASE(val);
 315         free(tmp);
 316     }
 317 
 318  done:
 319     /* finalize us */
 320     fprintf(stderr, "Client ns %s rank %d: Finalizing\n", myproc.nspace, myproc.rank);
 321     if (PMIX_SUCCESS != (rc = PMIx_Finalize(NULL, 0))) {
 322         fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize failed: %d\n", myproc.nspace, myproc.rank, rc);
 323     } else {
 324         fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize successfully completed\n", myproc.nspace, myproc.rank);
 325     }
 326     fflush(stderr);
 327     return(0);
 328 }

/* [<][>][^][v][top][bottom][index][help] */