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

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

DEFINITIONS

This source file includes following definitions.
  1. infocbfunc
  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 #include <stdbool.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include <unistd.h>
  30 #include <time.h>
  31 
  32 #include <pmix.h>
  33 #include "examples.h"
  34 
  35 /* this is a callback function for the PMIx_Query and
  36  * PMIx_Allocate APIs. The query will callback with a status indicating
  37  * if the request could be fully satisfied, partially
  38  * satisfied, or completely failed. The info parameter
  39  * contains an array of the returned data, with the
  40  * info->key field being the key that was provided in
  41  * the query call. Thus, you can correlate the returned
  42  * data in the info->value field to the requested key.
  43  *
  44  * Once we have dealt with the returned data, we must
  45  * call the release_fn so that the PMIx library can
  46  * cleanup */
  47 static void infocbfunc(pmix_status_t status,
  48                        pmix_info_t *info, size_t ninfo,
  49                        void *cbdata,
  50                        pmix_release_cbfunc_t release_fn,
  51                        void *release_cbdata)
  52 {
  53     myquery_data_t *mq = (myquery_data_t*)cbdata;
  54     size_t n;
  55 
  56     fprintf(stderr, "Allocation request returned %s", PMIx_Error_string(status));
  57 
  58     /* save the returned info - the PMIx library "owns" it
  59      * and will release it and perform other cleanup actions
  60      * when release_fn is called */
  61     if (0 < ninfo) {
  62         PMIX_INFO_CREATE(mq->info, ninfo);
  63         mq->ninfo = ninfo;
  64         for (n=0; n < ninfo; n++) {
  65             fprintf(stderr, "Transferring %s\n", info[n].key);
  66             PMIX_INFO_XFER(&mq->info[n], &info[n]);
  67         }
  68     }
  69     /* the status returned here indicates whether the requested
  70      * information was found or not - preserve it */
  71     mq->lock.status = status;
  72 
  73     /* let the library release the data and cleanup from
  74      * the operation */
  75     if (NULL != release_fn) {
  76         release_fn(release_cbdata);
  77     }
  78 
  79     /* release the block */
  80     DEBUG_WAKEUP_THREAD(&mq->lock);
  81 }
  82 
  83 /* this is an event notification function that we explicitly request
  84  * be called when the PMIX_ERR_ALLOC_COMPLETE notification is issued.
  85  * We could catch it in the general event notification function and test
  86  * the status to see if it was "alloc complete", but it often is simpler
  87  * to declare a use-specific notification callback point. In this case,
  88  * we are asking to know when the allocation request completes */
  89 static void release_fn(size_t evhdlr_registration_id,
  90                        pmix_status_t status,
  91                        const pmix_proc_t *source,
  92                        pmix_info_t info[], size_t ninfo,
  93                        pmix_info_t results[], size_t nresults,
  94                        pmix_event_notification_cbfunc_fn_t cbfunc,
  95                        void *cbdata)
  96 {
  97     myrel_t *lock;
  98     size_t n;
  99 
 100     /* find the return object */
 101     lock = NULL;
 102     for (n=0; n < ninfo; n++) {
 103         if (0 == strncmp(info[n].key, PMIX_EVENT_RETURN_OBJECT, PMIX_MAX_KEYLEN)) {
 104             lock = (myrel_t*)info[n].value.data.ptr;
 105             break;
 106         }
 107     }
 108     /* if the object wasn't returned, then that is an error */
 109     if (NULL == lock) {
 110         fprintf(stderr, "LOCK WASN'T RETURNED IN RELEASE CALLBACK\n");
 111         /* let the event handler progress */
 112         if (NULL != cbfunc) {
 113             cbfunc(PMIX_SUCCESS, NULL, 0, NULL, NULL, cbdata);
 114         }
 115         return;
 116     }
 117 
 118     /* tell the event handler state machine that we are the last step */
 119     if (NULL != cbfunc) {
 120         cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
 121     }
 122     /* the status will be PMIX_ERR_ALLOC_COMPLETE since that is the code
 123      * we registered to receive. The result of the allocation request is
 124      * in the info array - for now, just assume success */
 125     lock->lock.status = PMIX_SUCCESS;
 126     /* release the lock */
 127     DEBUG_WAKEUP_THREAD(&lock->lock);
 128 }
 129 
 130 /* event handler registration is done asynchronously because it
 131  * may involve the PMIx server registering with the host RM for
 132  * external events. So we provide a callback function that returns
 133  * the status of the request (success or an error), plus a numerical index
 134  * to the registered event. The index is used later on to deregister
 135  * an event handler - if we don't explicitly deregister it, then the
 136  * PMIx server will do so when it sees us exit */
 137 static void evhandler_reg_callbk(pmix_status_t status,
 138                                  size_t evhandler_ref,
 139                                  void *cbdata)
 140 {
 141     mylock_t *lock = (mylock_t*)cbdata;
 142 
 143     if (PMIX_SUCCESS != status) {
 144         fprintf(stderr, "EVENT HANDLER REGISTRATION FAILED WITH STATUS %d, ref=%lu\n",
 145                 status, (unsigned long)evhandler_ref);
 146     }
 147     lock->status = status;
 148     lock->evhandler_ref = evhandler_ref;
 149     DEBUG_WAKEUP_THREAD(lock);
 150 }
 151 
 152 int main(int argc, char **argv)
 153 {
 154     pmix_proc_t myproc;
 155     int rc;
 156     pmix_value_t value;
 157     pmix_value_t *val = &value;
 158     pmix_proc_t proc;
 159     uint32_t nprocs;
 160     pmix_info_t *info;
 161     uint64_t nnodes = 12;
 162     myquery_data_t mydata;
 163     pmix_query_t *query;
 164     char *myallocation = "MYALLOCATION";
 165     mylock_t mylock;
 166     pmix_status_t code;
 167     myrel_t myrel;
 168 
 169     /* init us */
 170     if (PMIX_SUCCESS != (rc = PMIx_Init(&myproc, NULL, 0))) {
 171         fprintf(stderr, "Client ns %s rank %d: PMIx_Init failed: %d\n", myproc.nspace, myproc.rank, rc);
 172         exit(0);
 173     }
 174     fprintf(stderr, "Client ns %s rank %d: Running\n", myproc.nspace, myproc.rank);
 175 
 176     /* get our universe size */
 177     PMIX_PROC_CONSTRUCT(&proc);
 178     (void)strncpy(proc.nspace, myproc.nspace, PMIX_MAX_NSLEN);
 179     proc.rank = PMIX_RANK_WILDCARD;
 180     if (PMIX_SUCCESS != (rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, &val))) {
 181         fprintf(stderr, "Client ns %s rank %d: PMIx_Get universe size failed: %d\n", myproc.nspace, myproc.rank, rc);
 182         goto done;
 183     }
 184     nprocs = val->data.uint32;
 185     PMIX_VALUE_RELEASE(val);
 186     fprintf(stderr, "Client %s:%d universe size %d\n", myproc.nspace, myproc.rank, nprocs);
 187 
 188     if (0 == myproc.rank) {
 189         /* try to get an allocation */
 190         DEBUG_CONSTRUCT_MYQUERY(&mydata);
 191         PMIX_INFO_CREATE(info, 2);
 192         PMIX_INFO_LOAD(&info[0], PMIX_ALLOC_NUM_NODES, &nnodes, PMIX_UINT64);
 193         PMIX_INFO_LOAD(&info[0], PMIX_ALLOC_ID, myallocation, PMIX_STRING);
 194         if (PMIX_SUCCESS != (rc = PMIx_Allocation_request_nb(PMIX_ALLOC_NEW, info, 2, infocbfunc, &mydata))) {
 195             fprintf(stderr, "Client ns %s rank %d: PMIx_Allocation_request_nb failed: %d\n", myproc.nspace, myproc.rank, rc);
 196             goto done;
 197         }
 198         DEBUG_WAIT_THREAD(&mydata.lock);
 199         PMIX_INFO_FREE(info, 2);
 200         fprintf(stderr, "Client ns %s rank %d: Allocation returned status: %s\n",
 201                 myproc.nspace, myproc.rank, PMIx_Error_string(mydata.lock.status));
 202         DEBUG_DESTRUCT_MYQUERY(&mydata);
 203 
 204     } else if (1 == myproc.rank) {
 205         /* demonstrate a notification based approach - register a handler
 206          * specifically for when the allocation operation completes */
 207         DEBUG_CONSTRUCT_MYREL(&myrel);
 208         PMIX_INFO_CREATE(info, 2);
 209         PMIX_INFO_LOAD(&info[0], PMIX_ALLOC_ID, myallocation, PMIX_STRING);
 210         PMIX_INFO_LOAD(&info[1], PMIX_EVENT_RETURN_OBJECT, &myrel, PMIX_POINTER);
 211         DEBUG_CONSTRUCT_LOCK(&mylock);
 212         code = PMIX_NOTIFY_ALLOC_COMPLETE;
 213         PMIx_Register_event_handler(&code, 1, info, 2,
 214                                     release_fn, evhandler_reg_callbk, (void*)&mylock);
 215         DEBUG_WAIT_THREAD(&mylock);
 216         PMIX_INFO_FREE(info, 2);
 217         rc = mylock.status;
 218         DEBUG_DESTRUCT_LOCK(&mylock);
 219 
 220         /* now wait to hear that the request is complete */
 221         DEBUG_WAIT_THREAD(&myrel.lock);
 222         fprintf(stderr, "[%s:%d] Allocation returned status: %s\n",
 223                 myproc.nspace, myproc.rank, PMIx_Error_string(myrel.lock.status));
 224         DEBUG_DESTRUCT_MYREL(&myrel);
 225 
 226     } else {
 227         /* demonstrate a query-based approach - wait a little while and ask to
 228          * see if it was done */
 229         usleep(10);
 230         DEBUG_CONSTRUCT_MYQUERY(&mydata);
 231 
 232         PMIX_QUERY_CREATE(query, 1);
 233         PMIX_ARGV_APPEND(rc, query[0].keys, PMIX_QUERY_ALLOC_STATUS);
 234         PMIX_INFO_CREATE(query[0].qualifiers, 1);
 235         PMIX_INFO_LOAD(&query[0].qualifiers[0], PMIX_ALLOC_ID, myallocation, PMIX_STRING);
 236 
 237         if (PMIX_SUCCESS != (rc = PMIx_Query_info_nb(query, 1, infocbfunc, (void*)&mydata))) {
 238             fprintf(stderr, "PMIx_Query_info failed: %d\n", rc);
 239             goto done;
 240         }
 241         DEBUG_WAIT_THREAD(&mydata.lock);
 242         PMIX_QUERY_FREE(query, 1);
 243         fprintf(stderr, "[%s:%d] Allocation returned status: %s\n",
 244                 myproc.nspace, myproc.rank, PMIx_Error_string(mydata.lock.status));
 245         DEBUG_DESTRUCT_MYQUERY(&mydata);
 246     }
 247 
 248   done:
 249     /* finalize us */
 250     fprintf(stderr, "Client ns %s rank %d: Finalizing\n", myproc.nspace, myproc.rank);
 251     if (PMIX_SUCCESS != (rc = PMIx_Finalize(NULL, 0))) {
 252         fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize failed: %d\n", myproc.nspace, myproc.rank, rc);
 253     } else {
 254         fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize successfully completed\n", myproc.nspace, myproc.rank);
 255     }
 256     fflush(stderr);
 257     return(0);
 258 }

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