Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:47:25

0001 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
0002 /*
0003  * Copyright (c) 2016-2020 Mellanox Technologies, Inc.
0004  *                         All rights reserved.
0005  * Copyright (c) 2016-2020 Intel, Inc.  All rights reserved.
0006  * Copyright (c) 2018      IBM Corporation.  All rights reserved.
0007  * Copyright (c) 2021-2024 Nanook Consulting  All rights reserved.
0008  * Copyright (c) 2022      Triad National Security, LLC. All rights reserved.
0009  * $COPYRIGHT$
0010  *
0011  * Additional copyrights may follow
0012  *
0013  * $HEADER$
0014  */
0015 
0016 #ifndef PMIX_GDS_H
0017 #define PMIX_GDS_H
0018 
0019 #include "src/include/pmix_config.h"
0020 
0021 #include "pmix_common.h"
0022 #include "src/mca/base/pmix_mca_base_framework.h"
0023 #include "src/mca/base/pmix_mca_base_var.h"
0024 #include "src/mca/bfrops/bfrops_types.h"
0025 #include "src/mca/mca.h"
0026 
0027 /* The client dictates the GDS module that will be used to interact
0028  * with the server - this module is stored in pmix_globals.mypeer->compat.gds
0029  * Because that is a long address to keep typing out, convenience macros
0030  * are provided for when that module is to be used in an operation.
0031  *
0032  * However, an application can open any number of GDS modules for
0033  * purposes other than exchanging info with the server. For example,
0034  * an application may wish to utilize a DHT module for its own
0035  * peer-to-peer data sharing. Thus, the public and private interfaces
0036  * are deliberately designed to be generic. The macros should make
0037  * things easier for the typical internal operations
0038  *
0039  * NOTE: ALTHOUGH SOME GDS COMPONENTS MAY UTILIZE THEIR OWN INTERNAL
0040  * PROGRESS THREADS, THE GDS IS NOT GUARANTEED TO BE THREAD-SAFE.
0041  * GDS FUNCTIONS SHOULD THEREFORE ALWAYS BE CALLED IN A THREAD-SAFE
0042  * CONDITION - E.G., FROM WITHIN AN EVENT
0043  */
0044 
0045 BEGIN_C_DECLS
0046 /* forward declaration */
0047 struct pmix_peer_t;
0048 struct pmix_namespace_t;
0049 
0050 /* backdoor to base verbosity */
0051 PMIX_EXPORT extern int pmix_gds_base_output;
0052 
0053 /**
0054  * Initialize the module. Returns an error if the module cannot
0055  * run, success if it can.
0056  */
0057 typedef pmix_status_t (*pmix_gds_base_module_init_fn_t)(pmix_info_t info[], size_t ninfo);
0058 
0059 /**
0060  * Finalize the module. Tear down any allocated storage, disconnect
0061  * from any system support.
0062  */
0063 typedef void (*pmix_gds_base_module_fini_fn_t)(void);
0064 
0065 /**
0066  * Assign a module per the requested directives. Modules should
0067  * review the provided directives to determine if they can support
0068  * the request. Modules are "scanned" in component priority order
0069  * and given an opportunity to respond. If a module offers itself,
0070  * it will provide a priority (which can be based on the directives
0071  * and therefore different from the component priority). The highest
0072  * returned priority received from a responder will be selected
0073  * and a pointer to its module returned */
0074 typedef pmix_status_t (*pmix_gds_base_assign_module_fn_t)(pmix_info_t *info, size_t ninfo,
0075                                                           int *priority);
0076 
0077 #define PMIX_GDS_CHECK_COMPONENT(p, s) (0 == strcmp((p)->nptr->compat.gds->name, (s)))
0078 #define PMIX_GDS_CHECK_PEER_COMPONENT(p1, p2) \
0079     (0 == strcmp((p1)->nptr->compat.gds->name, (p2)->nptr->compat.gds->name))
0080 
0081 /* SERVER FN: assemble the keys buffer for server answer */
0082 typedef pmix_status_t (*pmix_gds_base_module_assemb_kvs_req_fn_t)(const pmix_proc_t *proc,
0083                                                                   pmix_list_t *kvs,
0084                                                                   pmix_buffer_t *buf, void *cbdata);
0085 
0086 /* define a macro for server keys answer based on peer */
0087 #define PMIX_GDS_ASSEMB_KVS_REQ(s, p, r, k, b, c)                              \
0088     do {                                                                       \
0089         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                    \
0090         (s) = PMIX_SUCCESS;                                                    \
0091         if (NULL == _g->assemb_kvs_req) {                                      \
0092             if (0 == strcmp(_g->name, "hash")) {                               \
0093                 (s) = PMIX_ERR_NOT_SUPPORTED;                                  \
0094             } else {                                                           \
0095                 _g = pmix_globals.mypeer->nptr->compat.gds;                    \
0096             }                                                                  \
0097         }                                                                      \
0098         if (NULL != _g->assemb_kvs_req) {                                      \
0099             pmix_output_verbose(1, pmix_gds_base_output,                       \
0100                                 "[%s:%d] GDS ASSEMBLE REQ WITH %s",            \
0101                                 __FILE__, __LINE__, _g->name);                 \
0102             (s) = _g->assemb_kvs_req(r, k, b, (void *) c);                     \
0103         }                                                                      \
0104     } while (0)
0105 
0106 /* CLIENT FN: unpack buffer and key processing */
0107 typedef pmix_status_t (*pmix_gds_base_module_accept_kvs_resp_fn_t)(pmix_buffer_t *buf);
0108 
0109 /* define a macro for client key processing from a server response based on peer */
0110 #define PMIX_GDS_ACCEPT_KVS_RESP(s, p, b)                                      \
0111     do {                                                                       \
0112         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                    \
0113         (s) = PMIX_SUCCESS;                                                    \
0114         if (NULL == _g->accept_kvs_resp) {                                     \
0115             if (0 == strcmp(_g->name, "hash")) {                               \
0116                 (s) = PMIX_ERR_NOT_SUPPORTED;                                  \
0117             } else {                                                           \
0118                 _g = pmix_globals.mypeer->nptr->compat.gds;                    \
0119             }                                                                  \
0120         }                                                                      \
0121         if (NULL != _g->accept_kvs_resp) {                                     \
0122             pmix_output_verbose(1, pmix_gds_base_output,                       \
0123                                 "[%s:%d] GDS ACCEPT RESP WITH %s",             \
0124                                 __FILE__, __LINE__, _g->name);                 \
0125             (s) = _g->accept_kvs_resp(b);                                      \
0126         }                                                                      \
0127     } while (0)
0128 
0129 /* SERVER FN: cache job-level info in the server's GDS until client
0130  * procs connect and we discover which GDS module to use for them.
0131  * Note that this is essentially the same function as store_job_info,
0132  * only we don't have packed data on the server side, and don't want
0133  * to incur the overhead of packing it just to unpack it in the function.
0134  */
0135 typedef pmix_status_t (*pmix_gds_base_module_cache_job_info_fn_t)(struct pmix_namespace_t *ns,
0136                                                                   pmix_info_t info[], size_t ninfo);
0137 
0138 /* define a convenience macro for caching job info */
0139 #define PMIX_GDS_CACHE_JOB_INFO(s, p, n, i, ni)                                            \
0140     do {                                                                                   \
0141         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                                \
0142         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS CACHE JOB INFO WITH %s", \
0143                             __FILE__, __LINE__, _g->name);                                 \
0144         (s) = _g->cache_job_info((struct pmix_namespace_t *) (n), (i), (ni));              \
0145     } while (0)
0146 
0147 /* register job-level info - this is provided as a special function
0148  * to allow for optimization. Called solely by the server. We cannot
0149  * prepare the job-level info provided at PMIx_Register_nspace, because
0150  * we don't know the GDS component to use for that application until
0151  * a local client contacts us. Thus, the module is required to process
0152  * the job-level info cached in the pmix_namespace_t for this job and
0153  * do whatever is necessary to support the client, packing any required
0154  * return message into the provided buffer.
0155  *
0156  * This function will be called once for each local client of
0157  * a given nspace. PMIx assumes that all peers of a given nspace
0158  * will use the same GDS module. Thus, the module is free to perform
0159  * any relevant optimizations (e.g., packing the data only once and
0160  * then releasing the cached buffer once all local clients have
0161  * been serviced, or storing it once in shared memory and simply
0162  * returning the shared memory rendezvous information for subsequent
0163  * calls).
0164  *
0165  * Info provided in the reply buffer will be given to the "store_job_info"
0166  * API of the GDS module on the client. Since this should match the
0167  * module used by the server, each module has full knowledge and control
0168  * over what is in the reply buffer.
0169  *
0170  * The pmix_peer_t of the requesting client is provided here so that
0171  * the module can access the job-level info cached on the corresponding
0172  * pmix_namespace_t pointed to by the pmix_peer_t
0173  */
0174 typedef pmix_status_t (*pmix_gds_base_module_register_job_info_fn_t)(struct pmix_peer_t *pr,
0175                                                                      pmix_buffer_t *reply);
0176 
0177 /* define a convenience macro for registering job info for
0178  * a given peer */
0179 #define PMIX_GDS_REGISTER_JOB_INFO(s, p, b)                                                        \
0180     do {                                                                                           \
0181         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                                        \
0182         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS REG JOB INFO WITH %s", __FILE__, \
0183                             __LINE__, _g->name);                                                   \
0184         (s) = _g->register_job_info((struct pmix_peer_t *) (p), b);                                \
0185     } while (0)
0186 
0187 /* update job-level info - this is provided as a special function
0188  * to allow for optimization. Called solely by the client. The buffer
0189  * provided to this API is the same one given to the server by the
0190  * corresponding "register_job_info" function
0191  */
0192 typedef pmix_status_t (*pmix_gds_base_module_store_job_info_fn_t)(const char *nspace,
0193                                                                   pmix_buffer_t *buf);
0194 
0195 /* define a convenience macro for storing job info based on peer */
0196 #define PMIX_GDS_STORE_JOB_INFO(s, p, n, b)                                                \
0197     do {                                                                                   \
0198         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                                \
0199         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS STORE JOB INFO WITH %s", \
0200                             __FILE__, __LINE__, _g->name);                                 \
0201         (s) = _g->store_job_info(n, b);                                                    \
0202     } while (0)
0203 
0204 /**
0205  * store key/value pair - these will either be values committed by the peer
0206  * and transmitted to the server, or values stored locally by the peer.
0207  * The format of the data depends on the GDS module. Note that data stored
0208  * with PMIX_INTERNAL scope should be stored solely within the process and
0209  * is never shared.
0210  *
0211  * @param peer   pointer to pmix_peer_t object of the peer that
0212  *               provided the data
0213  *
0214  * @param proc   the proc that the data describes
0215  *
0216  * @param scope  scope of the data
0217  *
0218  * @param kv     key/value pair.
0219  *
0220  * @return PMIX_SUCCESS on success.
0221  */
0222 typedef pmix_status_t (*pmix_gds_base_module_store_fn_t)(const pmix_proc_t *proc,
0223                                                          pmix_scope_t scope, pmix_kval_t *kv);
0224 
0225 /* define a convenience macro for storing key-val pairs based on peer */
0226 #define PMIX_GDS_STORE_KV(s, p, pc, sc, k)                                     \
0227     do {                                                                       \
0228         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                    \
0229         (s) = PMIX_SUCCESS;                                                    \
0230         if (NULL == _g->store) {                                               \
0231             if (0 == strcmp(_g->name, "hash")) {                               \
0232                 (s) = PMIX_ERR_NOT_SUPPORTED;                                  \
0233             } else {                                                           \
0234                 _g = pmix_globals.mypeer->nptr->compat.gds;                    \
0235             }                                                                  \
0236         }                                                                      \
0237         if (NULL != _g->store) {                                               \
0238             pmix_output_verbose(1, pmix_gds_base_output,                       \
0239                                 "[%s:%d] GDS STORE KV WITH %s",                \
0240                                 __FILE__, __LINE__, _g->name);                 \
0241             (s) = _g->store(pc, sc, k);                                        \
0242         }                                                                      \
0243     } while (0)
0244 
0245 /**
0246  * unpack and store a data "blob" from a peer so that the individual
0247  * elements can later be retrieved. This is an optimization path to
0248  * avoid repeatedly storing pmix_kval_t's for multiple local procs
0249  * from the same nspace.
0250  *
0251  * ranks - a list of pmix_rank_info_t for the local ranks from this
0252  *         nspace - this is to be used to filter the cbs list
0253  *
0254  * cbdata - pointer to modex callback data
0255  *
0256  * bo - pointer to the byte object containing the data
0257  *
0258  */
0259 typedef pmix_status_t (*pmix_gds_base_module_store_modex_fn_t)(struct pmix_namespace_t *ns,
0260                                                                pmix_buffer_t *buff, void *cbdata);
0261 
0262 /**
0263  * define a convenience macro for storing modex byte objects
0264  *
0265  * r - return status code
0266  *
0267  * n - pointer to the pmix_namespace_t this blob is to be stored for
0268  *
0269  * b - pointer to pmix_buffer_t containing the data
0270  *
0271  * t - pointer to the modex server tracker
0272  */
0273 #define PMIX_GDS_STORE_MODEX(r, n, b, t)                                    \
0274     do {                                                                    \
0275         pmix_gds_base_module_t *_g = pmix_globals.mypeer->nptr->compat.gds; \
0276         pmix_output_verbose(1, pmix_gds_base_output,                        \
0277                             "[%s:%d] GDS STORE MODEX WITH %s", __FILE__,    \
0278                             __LINE__, _g->name);                            \
0279         (r) = _g->store_modex((struct pmix_namespace_t *)n, b, t);          \
0280     } while (0)
0281 
0282 typedef pmix_status_t (*pmix_gds_base_module_mark_modex_complete_fn_t)(struct pmix_peer_t *peer,
0283                                                                        pmix_list_t *nslist,
0284                                                                        pmix_buffer_t *buff);
0285 #define PMIX_GDS_MARK_MODEX_COMPLETE(r, p, l, b)                            \
0286     do {                                                                    \
0287         pmix_gds_base_module_t *_g = pmix_globals.mypeer->nptr->compat.gds; \
0288         pmix_output_verbose(1, pmix_gds_base_output,                        \
0289                             "[%s:%d] GDS MARK MODEX COMPLETE WITH %s",      \
0290                             __FILE__, __LINE__, _g->name);                  \
0291         (r) = _g->mark_modex_complete(p, l, b);                             \
0292     } while (0)
0293 
0294 typedef pmix_status_t (*pmix_gds_base_module_recv_modex_complete_fn_t)(pmix_buffer_t *buff);
0295 #define PMIX_GDS_RECV_MODEX_COMPLETE(r, p, b)                               \
0296     do {                                                                    \
0297         pmix_gds_base_module_t *_g = pmix_globals.mypeer->nptr->compat.gds; \
0298         pmix_output_verbose(1, pmix_gds_base_output,                        \
0299                             "[%s:%d] GDS RECV MODEX COMPLETE WITH %s",      \
0300                             __FILE__, __LINE__, _g->name);                  \
0301         (r) = _g->recv_modex_complete(b);                                   \
0302     } while (0)
0303 
0304 /**
0305  * fetch value corresponding to provided key from within the defined
0306  * scope. A NULL key returns all values committed by the given peer
0307  * for that scope.
0308  *
0309  * @param proc    namespace and rank whose info is being requested
0310  *
0311  * @param key     key.
0312  *
0313  * @param scope   scope of the data to be considered
0314  *
0315  * @param copy    true if the caller _requires_ a copy of the data. This
0316  *                is used when the requestor is off-node. If
0317  *                set to false, then the GDS component can provide
0318  *                either a copy of the data, or shmem contact info
0319  *                to the location of the data
0320  *
0321  * @param info    array of pmix_info_t the caller provided as
0322  *                qualifiers to guide the request
0323  *
0324  * @param ninfo   number of elements in the info array
0325  *
0326  * @param kvs     pointer to a list that will be populated with the
0327  *                returned pmix_kval_t data
0328  *
0329  * @return       PMIX_SUCCESS on success.
0330  *
0331  * Note: all available job-level data for a given nspace can be fetched
0332  * by passing a proc with rank=PMIX_RANK_WILDCARD and a NULL key. Similarly,
0333  * passing a NULL key for a non-wildcard rank will return all data "put"
0334  * by that rank. Scope is ignored for job-level data requests.
0335  *
0336  * When a specific rank if provided with a NULL key, then data for only
0337  * that rank is returned. If the scope is PMIX_LOCAL, then the returned
0338  * data shall include only data that was specifically "put" to local scope,
0339  * plus any data that was put to PMIX_GLOBAL scope. Similarly, a scope of
0340  * PMIX_REMOTE will return data that was "put" to remote scope, plus
0341  * any data that was put to PMIX_GLOBAL scope. A scope of PMIX_GLOBAL
0342  * will return LOCAL, REMOTE, and GLOBAL data.
0343  *
0344  * Data stored with PMIX_INTERNAL scope can be retrieved with that scope.
0345  */
0346 typedef pmix_status_t (*pmix_gds_base_module_fetch_fn_t)(const pmix_proc_t *proc,
0347                                                          pmix_scope_t scope, bool copy,
0348                                                          const char *key, pmix_info_t info[],
0349                                                          size_t ninfo, pmix_list_t *kvs);
0350 
0351 /* define a convenience macro for fetch key-val pairs based on peer,
0352  * passing a pmix_cb_t containing all the required info */
0353 #define PMIX_GDS_FETCH_KV(s, p, c)                                                             \
0354     do {                                                                                       \
0355         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds;                                    \
0356         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS FETCH KV WITH %s", __FILE__, \
0357                             __LINE__, _g->name);                                               \
0358         (s) = _g->fetch((c)->proc, (c)->scope, (c)->copy, (c)->key, (c)->info, (c)->ninfo,     \
0359                         &(c)->kvs);                                                            \
0360     } while (0)
0361 
0362 /**
0363  * Add any envars to a peer's environment that the module needs
0364  * to communicate. The API stub will rotate across all active modules, giving
0365  * each a chance to contribute
0366  *
0367  * @return PMIX_SUCCESS on success.
0368  */
0369 typedef pmix_status_t (*pmix_gds_base_module_setup_fork_fn_t)(const pmix_proc_t *proc, char ***env);
0370 
0371 /**
0372  * Define a new nspace in the GDS
0373  *
0374  * @param nspace   namespace string
0375  *
0376  * @return PMIX_SUCCESS on success.
0377  */
0378 typedef pmix_status_t (*pmix_gds_base_module_add_nspace_fn_t)(const char *nspace,
0379                                                               uint32_t nlocalprocs,
0380                                                               pmix_info_t info[], size_t ninfo);
0381 
0382 /* define a convenience macro for add_nspace based on peer */
0383 #define PMIX_GDS_ADD_NSPACE(s, n, ls, i, ni)                                                \
0384     do {                                                                                    \
0385         pmix_gds_base_active_module_t *_g;                                                  \
0386         pmix_status_t _s = PMIX_SUCCESS;                                                    \
0387         (s) = PMIX_SUCCESS;                                                                 \
0388         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS ADD NSPACE %s", __FILE__, \
0389                             __LINE__, (n));                                                 \
0390         PMIX_LIST_FOREACH (_g, &pmix_gds_globals.actives, pmix_gds_base_active_module_t) {  \
0391             if (NULL != _g->module->add_nspace) {                                           \
0392                 _s = _g->module->add_nspace(n, ls, i, ni);                                  \
0393             }                                                                               \
0394             if (PMIX_SUCCESS != _s) {                                                       \
0395                 (s) = PMIX_ERROR;                                                           \
0396             }                                                                               \
0397         }                                                                                   \
0398     } while (0)
0399 
0400 /**
0401  * Delete nspace and its associated data
0402  *
0403  * @param nspace   namespace string
0404  *
0405  * @return PMIX_SUCCESS on success.
0406  */
0407 typedef pmix_status_t (*pmix_gds_base_module_del_nspace_fn_t)(const char *nspace);
0408 
0409 /* define a convenience macro for del_nspace based on peer */
0410 #define PMIX_GDS_DEL_NSPACE(s, n)                                                           \
0411     do {                                                                                    \
0412         pmix_gds_base_active_module_t *_g;                                                  \
0413         pmix_status_t _s = PMIX_SUCCESS;                                                    \
0414         (s) = PMIX_SUCCESS;                                                                 \
0415         pmix_output_verbose(1, pmix_gds_base_output, "[%s:%d] GDS DEL NSPACE %s", __FILE__, \
0416                             __LINE__, (n));                                                 \
0417         PMIX_LIST_FOREACH (_g, &pmix_gds_globals.actives, pmix_gds_base_active_module_t) {  \
0418             if (NULL != _g->module->del_nspace) {                                           \
0419                 _s = _g->module->del_nspace(n);                                             \
0420             }                                                                               \
0421             if (PMIX_SUCCESS != _s) {                                                       \
0422                 (s) = PMIX_ERROR;                                                           \
0423             }                                                                               \
0424         }                                                                                   \
0425     } while (0)
0426 
0427 /* define a convenience macro for is_tsafe for fetch operation */
0428 #define PMIX_GDS_FETCH_IS_TSAFE(s, p)                       \
0429     do {                                                    \
0430         pmix_gds_base_module_t *_g = (p)->nptr->compat.gds; \
0431         pmix_output_verbose(1, pmix_gds_base_output,        \
0432                 "[%s:%d] GDS FETCH IS THREAD SAFE WITH %s", \
0433                             __FILE__, __LINE__, _g->name);  \
0434         if (true == _g->is_tsafe) {                         \
0435             (s) = PMIX_SUCCESS;                             \
0436         } else {                                            \
0437             (s) = PMIX_ERR_NOT_SUPPORTED;                   \
0438         }                                                   \
0439     } while(0)
0440 
0441 typedef pmix_status_t (*pmix_gds_base_module_fetch_array_fn_t)(struct pmix_peer_t *pr,
0442                                                                pmix_buffer_t *reply);
0443 /* define a convenience macro for fetching array info for
0444  * a given peer */
0445 #define PMIX_GDS_FETCH_INFO_ARRAYS(s, p, b)                                 \
0446     do {                                                                    \
0447         pmix_gds_base_module_t *_g = pmix_globals.mypeer->nptr->compat.gds; \
0448         pmix_output_verbose(1, pmix_gds_base_output,                        \
0449                             "[%s:%d] GDS FETCH ARRAYS WITH %s",             \
0450                             __FILE__, __LINE__, _g->name);                  \
0451         (s) = _g->fetch_arrays((struct pmix_peer_t*)(p), b);                \
0452     } while(0)
0453 
0454 
0455 /* structure for gds modules */
0456 typedef struct {
0457     const char *name;
0458     const bool is_tsafe;
0459     pmix_gds_base_module_init_fn_t                  init;
0460     pmix_gds_base_module_fini_fn_t                  finalize;
0461     pmix_gds_base_assign_module_fn_t                assign_module;
0462     pmix_gds_base_module_cache_job_info_fn_t        cache_job_info;
0463     pmix_gds_base_module_register_job_info_fn_t     register_job_info;
0464     pmix_gds_base_module_store_job_info_fn_t        store_job_info;
0465     pmix_gds_base_module_store_fn_t                 store;
0466     pmix_gds_base_module_store_modex_fn_t           store_modex;
0467     pmix_gds_base_module_fetch_fn_t                 fetch;
0468     pmix_gds_base_module_setup_fork_fn_t            setup_fork;
0469     pmix_gds_base_module_add_nspace_fn_t            add_nspace;
0470     pmix_gds_base_module_del_nspace_fn_t            del_nspace;
0471     pmix_gds_base_module_assemb_kvs_req_fn_t        assemb_kvs_req;
0472     pmix_gds_base_module_accept_kvs_resp_fn_t       accept_kvs_resp;
0473     pmix_gds_base_module_fetch_array_fn_t           fetch_arrays;
0474     pmix_gds_base_module_mark_modex_complete_fn_t   mark_modex_complete;
0475     pmix_gds_base_module_recv_modex_complete_fn_t   recv_modex_complete;
0476 } pmix_gds_base_module_t;
0477 
0478 /* NOTE: there is no public GDS interface structure - all access is
0479  * done directly to/from an assigned module */
0480 
0481 /* define the component structure */
0482 typedef pmix_mca_base_component_t pmix_gds_base_component_t;
0483 
0484 /*
0485  * Macro for use in components that are of type gds
0486  */
0487 #define PMIX_GDS_BASE_VERSION_1_0_0 PMIX_MCA_BASE_VERSION_1_0_0("gds", 1, 0, 0)
0488 
0489 END_C_DECLS
0490 
0491 #endif