Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 10:12:52

0001 /*
0002  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
0003  *                         University Research and Technology
0004  *                         Corporation.  All rights reserved.
0005  * Copyright (c) 2004-2006 The University of Tennessee and The University
0006  *                         of Tennessee Research Foundation.  All rights
0007  *                         reserved.
0008  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
0009  *                         University of Stuttgart.  All rights reserved.
0010  * Copyright (c) 2004-2005 The Regents of the University of California.
0011  *                         All rights reserved.
0012  * Copyright (c) 2015-2020 Intel, Inc.  All rights reserved.
0013  * Copyright (c) 2019      Mellanox Technologies, Inc.
0014  *                         All rights reserved.
0015  * Copyright (c) 2021-2024 Nanook Consulting  All rights reserved.
0016  * Copyright (c) 2022      IBM Corporation.  All rights reserved.
0017  * Copyright (c) 2022-2023 Triad National Security, LLC. All rights reserved.
0018  * $COPYRIGHT$
0019  *
0020  * Additional copyrights may follow
0021  *
0022  * $HEADER$
0023  */
0024 
0025 /**
0026  * Houses infrastructure that supports custom memory allocators for bfrops.
0027  * If tma is NULL, then the default heap manager is used.
0028  */
0029 
0030 #ifndef PMIX_BFROP_BASE_TMA_H
0031 #define PMIX_BFROP_BASE_TMA_H
0032 
0033 #include "src/include/pmix_config.h"
0034 #include "src/include/pmix_globals.h"
0035 
0036 #include "src/hwloc/pmix_hwloc.h"
0037 
0038 #include "src/mca/preg/preg.h"
0039 #include "src/mca/bfrops/base/base.h"
0040 
0041 #include "src/util/pmix_printf.h"
0042 
0043 extern char **environ;
0044 
0045 static inline
0046 void pmix_bfrops_base_tma_value_destruct(pmix_value_t *v,
0047                                          pmix_tma_t *tma);
0048 
0049 static inline
0050 pmix_status_t pmix_bfrops_base_tma_value_xfer(pmix_value_t *p,
0051                                               const pmix_value_t *src,
0052                                               pmix_tma_t *tma);
0053 
0054 static inline
0055 char* pmix_bfrops_base_tma_buffer_extend(pmix_buffer_t *buffer,
0056                                          size_t bytes_to_add,
0057                                          pmix_tma_t *tma)
0058 {
0059     size_t required, to_alloc;
0060     size_t pack_offset, unpack_offset;
0061 
0062     /* Check to see if we have enough space already */
0063     if (0 == bytes_to_add) {
0064         return buffer->pack_ptr;
0065     }
0066 
0067     if ((buffer->bytes_allocated - buffer->bytes_used) >= bytes_to_add) {
0068         return buffer->pack_ptr;
0069     }
0070 
0071     required = buffer->bytes_used + bytes_to_add;
0072     if (required >= pmix_bfrops_globals.threshold_size) {
0073         to_alloc = ((required + pmix_bfrops_globals.threshold_size - 1)
0074                     / pmix_bfrops_globals.threshold_size)
0075                    * pmix_bfrops_globals.threshold_size;
0076     } else {
0077         to_alloc = buffer->bytes_allocated;
0078         if (0 == to_alloc) {
0079             to_alloc = pmix_bfrops_globals.initial_size;
0080         }
0081         while (to_alloc < required) {
0082             to_alloc <<= 1;
0083         }
0084     }
0085 
0086     if (NULL != buffer->base_ptr) {
0087         pack_offset = ((char *) buffer->pack_ptr) - ((char *) buffer->base_ptr);
0088         unpack_offset = ((char *) buffer->unpack_ptr) - ((char *) buffer->base_ptr);
0089         buffer->base_ptr = (char *) pmix_tma_realloc(tma, buffer->base_ptr, to_alloc);
0090         memset(buffer->base_ptr + pack_offset, 0, to_alloc - buffer->bytes_allocated);
0091     } else {
0092         pack_offset = 0;
0093         unpack_offset = 0;
0094         buffer->bytes_used = 0;
0095         buffer->base_ptr = (char *)pmix_tma_malloc(tma, to_alloc);
0096         memset(buffer->base_ptr, 0, to_alloc);
0097     }
0098 
0099     if (NULL == buffer->base_ptr) {
0100         return NULL;
0101     }
0102     buffer->pack_ptr = ((char *) buffer->base_ptr) + pack_offset;
0103     buffer->unpack_ptr = ((char *) buffer->base_ptr) + unpack_offset;
0104     buffer->bytes_allocated = to_alloc;
0105 
0106     /* All done */
0107     return buffer->pack_ptr;
0108 }
0109 
0110 static inline
0111 pmix_status_t pmix_bfrops_base_tma_copy_payload(pmix_buffer_t *dest,
0112                                                 pmix_buffer_t *src,
0113                                                 pmix_tma_t *tma)
0114 {
0115     size_t to_copy = 0;
0116     char *ptr;
0117 
0118     /* deal with buffer type */
0119     if (NULL == dest->base_ptr) {
0120         /* destination buffer is empty - derive src buffer type */
0121         dest->type = src->type;
0122     } else if (PMIX_UNLIKELY(dest->type != src->type)) {
0123         /* buffer types mismatch */
0124         PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
0125         return PMIX_ERR_BAD_PARAM;
0126     }
0127 
0128     /* if the src buffer is empty, then there is
0129      * nothing to do */
0130     if (PMIX_BUFFER_IS_EMPTY(src)) {
0131         return PMIX_SUCCESS;
0132     }
0133 
0134     /* extend the dest if necessary */
0135     to_copy = src->pack_ptr - src->unpack_ptr;
0136     if (NULL == (ptr = pmix_bfrops_base_tma_buffer_extend(dest, to_copy, tma))) {
0137         PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
0138         return PMIX_ERR_OUT_OF_RESOURCE;
0139     }
0140     memcpy(ptr, src->unpack_ptr, to_copy);
0141     dest->bytes_used += to_copy;
0142     dest->pack_ptr += to_copy;
0143     return PMIX_SUCCESS;
0144 }
0145 
0146 static inline
0147 pmix_status_t pmix_bfrops_base_tma_embed_payload(pmix_buffer_t *dest,
0148                                                  pmix_byte_object_t *src,
0149                                                  pmix_tma_t *tma)
0150 {
0151     char *ptr;
0152 
0153     /* deal with buffer type */
0154     if (NULL == dest->base_ptr) {
0155         /* destination buffer is empty - derive src buffer type */
0156         dest->type = pmix_bfrops_globals.default_type;
0157     }
0158 
0159     /* if the src is empty, then there is
0160      * nothing to do */
0161     if (NULL == src->bytes) {
0162         return PMIX_SUCCESS;
0163     }
0164 
0165     /* extend the dest if necessary */
0166     if (NULL == (ptr = pmix_bfrops_base_tma_buffer_extend(dest, src->size, tma))) {
0167         PMIX_ERROR_LOG(PMIX_ERR_OUT_OF_RESOURCE);
0168         return PMIX_ERR_OUT_OF_RESOURCE;
0169     }
0170     memcpy(ptr, src->bytes, src->size);
0171     dest->bytes_used += src->size;
0172     dest->pack_ptr += src->size;
0173     return PMIX_SUCCESS;
0174 }
0175 
0176 static inline
0177 void pmix_bfrops_base_tma_load_key(pmix_key_t key,
0178                                    const char *src,
0179                                    pmix_tma_t *tma)
0180 {
0181     PMIX_HIDE_UNUSED_PARAMS(tma);
0182 
0183     memset(key, 0, PMIX_MAX_KEYLEN + 1);
0184     if (NULL != src) {
0185         pmix_strncpy((char *)key, src, PMIX_MAX_KEYLEN);
0186     }
0187 }
0188 
0189 static inline
0190 bool pmix_bfrops_base_tma_check_key(const char *key,
0191                                     const char *str,
0192                                     pmix_tma_t *tma)
0193 {
0194     PMIX_HIDE_UNUSED_PARAMS(tma);
0195 
0196     if (0 == strncmp(key, str, PMIX_MAX_KEYLEN)) {
0197         return true;
0198     }
0199     return false;
0200 }
0201 
0202 static inline
0203 bool pmix_bfrops_base_tma_nspace_invalid(const char *nspace,
0204                                          pmix_tma_t *tma)
0205 {
0206     PMIX_HIDE_UNUSED_PARAMS(tma);
0207 
0208     if (NULL == nspace || 0 == pmix_nslen(nspace)) {
0209         return true;
0210     }
0211     return false;
0212 }
0213 
0214 static inline
0215 bool pmix_bfrops_base_tma_check_nspace(const char *nspace1,
0216                                        const char *nspace2,
0217                                        pmix_tma_t *tma)
0218 {
0219     if (pmix_bfrops_base_tma_nspace_invalid(nspace1, tma)) {
0220         return true;
0221     }
0222     if (pmix_bfrops_base_tma_nspace_invalid(nspace2, tma)) {
0223         return true;
0224     }
0225     if (0 == strncmp(nspace1, nspace2, PMIX_MAX_NSLEN)) {
0226         return true;
0227     }
0228     return false;
0229 }
0230 
0231 static inline
0232 bool pmix_bfrops_base_tma_check_reserved_key(const char *key,
0233                                              pmix_tma_t *tma)
0234 {
0235     PMIX_HIDE_UNUSED_PARAMS(tma);
0236 
0237     if (0 == strncmp(key, "pmix", 4)) {
0238         return true;
0239     }
0240     return false;
0241 }
0242 
0243 static inline
0244 void pmix_bfrops_base_tma_xfer_procid(pmix_proc_t *dst,
0245                                       const pmix_proc_t *src,
0246                                       pmix_tma_t *tma)
0247 {
0248     PMIX_HIDE_UNUSED_PARAMS(tma);
0249 
0250     memcpy(dst, src, sizeof(pmix_proc_t));
0251 }
0252 
0253 static inline
0254 bool pmix_bfrops_base_tma_check_rank(pmix_rank_t a,
0255                                      pmix_rank_t b,
0256                                      pmix_tma_t *tma)
0257 {
0258     PMIX_HIDE_UNUSED_PARAMS(tma);
0259 
0260     if (a == b) {
0261         return true;
0262     }
0263     if (PMIX_RANK_WILDCARD == a ||
0264         PMIX_RANK_WILDCARD == b) {
0265         return true;
0266     }
0267     return false;
0268 }
0269 
0270 static inline
0271 bool pmix_bfrops_base_tma_check_procid(const pmix_proc_t *a,
0272                                        const pmix_proc_t *b,
0273                                        pmix_tma_t *tma)
0274 {
0275     if (!pmix_bfrops_base_tma_check_nspace(a->nspace, b->nspace, tma)) {
0276         return false;
0277     }
0278     return pmix_bfrops_base_tma_check_rank(a->rank, b->rank, tma);
0279 }
0280 
0281 static inline
0282 bool pmix_bfrops_base_tma_procid_invalid(const pmix_proc_t *p,
0283                                          pmix_tma_t *tma)
0284 {
0285     if (pmix_bfrops_base_tma_nspace_invalid(p->nspace, tma)) {
0286         return true;
0287     }
0288     if (PMIX_RANK_INVALID == p->rank) {
0289         return true;
0290     }
0291     return false;
0292 }
0293 
0294 static inline
0295 void pmix_bfrops_base_tma_load_nspace(pmix_nspace_t nspace,
0296                                       const char *str,
0297                                       pmix_tma_t *tma)
0298 {
0299     PMIX_HIDE_UNUSED_PARAMS(tma);
0300 
0301     memset(nspace, 0, PMIX_MAX_NSLEN + 1);
0302     if (NULL != str) {
0303         pmix_strncpy((char *)nspace, str, PMIX_MAX_NSLEN);
0304     }
0305 }
0306 
0307 static inline
0308 void pmix_bfrops_base_tma_load_procid(pmix_proc_t *p,
0309                                       const char *ns,
0310                                       pmix_rank_t rk,
0311                                       pmix_tma_t *tma)
0312 {
0313     pmix_bfrops_base_tma_load_nspace(p->nspace, ns, tma);
0314     p->rank = rk;
0315 }
0316 
0317 static inline
0318 void pmix_bfrops_base_tma_data_buffer_load(pmix_data_buffer_t *b,
0319                                            char *bytes,
0320                                            size_t sz,
0321                                            pmix_tma_t *tma)
0322 {
0323     PMIX_HIDE_UNUSED_PARAMS(tma);
0324 
0325     pmix_byte_object_t bo;
0326 
0327     bo.bytes = bytes;
0328     bo.size = sz;
0329     // TODO(skg) Add TMA support when necessary.
0330     PMIx_Data_load(b, &bo);
0331 }
0332 
0333 static inline
0334 void pmix_bfrops_base_tma_data_buffer_unload(pmix_data_buffer_t *b,
0335                                              char **bytes,
0336                                              size_t *sz,
0337                                              pmix_tma_t *tma)
0338 {
0339     PMIX_HIDE_UNUSED_PARAMS(tma);
0340 
0341     pmix_byte_object_t bo;
0342     pmix_status_t r;
0343 
0344     // TODO(skg) Add TMA support when necessary.
0345     r = PMIx_Data_unload(b, &bo);
0346     if (PMIX_SUCCESS == r) {
0347         *bytes = bo.bytes;
0348         *sz = bo.size;
0349     } else {
0350         *bytes = NULL;
0351         *sz = 0;
0352     }
0353 }
0354 
0355 static inline
0356 void pmix_bfrops_base_tma_proc_construct(pmix_proc_t *p,
0357                                          pmix_tma_t *tma)
0358 {
0359     PMIX_HIDE_UNUSED_PARAMS(tma);
0360 
0361     memset(p, 0, sizeof(pmix_proc_t));
0362     p->rank = PMIX_RANK_UNDEF;
0363 }
0364 
0365 static inline
0366 void pmix_bfrops_base_tma_proc_destruct(pmix_proc_t *p,
0367                                         pmix_tma_t *tma)
0368 {
0369     // Destruct in this case is only setting data members
0370     // to default values, so call proc_construct.
0371     pmix_bfrops_base_tma_proc_construct(p, tma);
0372 }
0373 
0374 static inline
0375 void pmix_bfrops_base_tma_proc_load(pmix_proc_t *p,
0376                                     const char *nspace,
0377                                     pmix_rank_t rank,
0378                                     pmix_tma_t *tma)
0379 {
0380     pmix_bfrops_base_tma_proc_construct(p, tma);
0381     pmix_bfrops_base_tma_load_procid(p, nspace, rank, tma);
0382 }
0383 
0384 static inline
0385 pmix_proc_t* pmix_bfrops_base_tma_proc_create(size_t n,
0386                                               pmix_tma_t *tma)
0387 {
0388     if (0 == n) {
0389         return NULL;
0390     }
0391     pmix_proc_t *p = (pmix_proc_t*)pmix_tma_malloc(tma, n * sizeof(pmix_proc_t));
0392     if (PMIX_LIKELY(NULL != p)) {
0393         for (size_t m = 0; m < n; m++) {
0394             pmix_bfrops_base_tma_proc_construct(&p[m], tma);
0395         }
0396     }
0397     return p;
0398 }
0399 
0400 static inline
0401 void pmix_bfrops_base_tma_proc_free(pmix_proc_t *p,
0402                                     size_t n,
0403                                     pmix_tma_t *tma)
0404 {
0405     if (NULL != p) {
0406         for (size_t m = 0; m < n; m++) {
0407             pmix_bfrops_base_tma_proc_destruct(&p[m], tma);
0408         }
0409         pmix_tma_free(tma, p);
0410     }
0411 }
0412 
0413 static inline
0414 void pmix_bfrops_base_tma_multicluster_nspace_construct(pmix_nspace_t target,
0415                                                         pmix_nspace_t cluster,
0416                                                         pmix_nspace_t nspace,
0417                                                         pmix_tma_t *tma)
0418 {
0419     pmix_bfrops_base_tma_load_nspace(target, NULL, tma);
0420     size_t len = pmix_nslen(cluster);
0421     if ((len + pmix_nslen(nspace)) < PMIX_MAX_NSLEN) {
0422         pmix_strncpy((char*)target, cluster, PMIX_MAX_NSLEN);
0423         target[len] = ':';
0424         pmix_strncpy((char*)&target[len+1], nspace, PMIX_MAX_NSLEN - len);
0425     }
0426 }
0427 
0428 static inline
0429 void pmix_bfrops_base_tma_multicluster_nspace_parse(pmix_nspace_t target,
0430                                                     pmix_nspace_t cluster,
0431                                                     pmix_nspace_t nspace,
0432                                                     pmix_tma_t *tma)
0433 {
0434     size_t n, j;
0435 
0436     pmix_bfrops_base_tma_load_nspace(cluster, NULL, tma);
0437     for (n=0; '\0' != target[n] && ':' != target[n] && n < PMIX_MAX_NSLEN; n++) {
0438         cluster[n] = target[n];
0439     }
0440     n++;
0441     for (j=0; n < PMIX_MAX_NSLEN && '\0' != target[n]; n++, j++) {
0442         nspace[j] = target[n];
0443     }
0444 }
0445 
0446 static inline
0447 void pmix_bfrops_base_tma_proc_info_construct(pmix_proc_info_t *p,
0448                                               pmix_tma_t *tma)
0449 {
0450     PMIX_HIDE_UNUSED_PARAMS(tma);
0451 
0452     memset(p, 0, sizeof(pmix_proc_info_t));
0453     p->state = PMIX_PROC_STATE_UNDEF;
0454 }
0455 
0456 static inline
0457 void pmix_bfrops_base_tma_proc_info_destruct(pmix_proc_info_t *p,
0458                                              pmix_tma_t *tma)
0459 {
0460     if (NULL != p->hostname) {
0461         pmix_tma_free(tma, p->hostname);
0462     }
0463     if (NULL != p->executable_name) {
0464         pmix_tma_free(tma, p->executable_name);
0465     }
0466     pmix_bfrops_base_tma_proc_info_construct(p, tma);
0467 }
0468 
0469 static inline
0470 void pmix_bfrops_base_tma_proc_info_free(pmix_proc_info_t *p,
0471                                          size_t n,
0472                                          pmix_tma_t *tma)
0473 {
0474     if (NULL != p) {
0475         for (size_t m = 0; m < n; m++) {
0476             pmix_bfrops_base_tma_proc_info_destruct(&p[m], tma);
0477         }
0478         pmix_tma_free(tma, p);
0479     }
0480 }
0481 
0482 static inline
0483 pmix_proc_info_t* pmix_bfrops_base_tma_proc_info_create(size_t n,
0484                                                         pmix_tma_t *tma)
0485 {
0486     if (0 == n) {
0487         return NULL;
0488     }
0489     pmix_proc_info_t *p = (pmix_proc_info_t *)pmix_tma_malloc(tma, n * sizeof(pmix_proc_info_t));
0490     if (PMIX_LIKELY(NULL != p)) {
0491         for (size_t m = 0; m < n; m++) {
0492             pmix_bfrops_base_tma_proc_info_construct(&p[m], tma);
0493         }
0494     }
0495     return p;
0496 }
0497 
0498 static inline
0499 pmix_status_t pmix_bfrops_base_tma_copy_pinfo(pmix_proc_info_t **dest,
0500                                               pmix_proc_info_t *src,
0501                                               pmix_data_type_t type,
0502                                               pmix_tma_t *tma)
0503 {
0504     PMIX_HIDE_UNUSED_PARAMS(type);
0505 
0506     pmix_proc_info_t *p = pmix_bfrops_base_tma_proc_info_create(1, tma);
0507     if (PMIX_UNLIKELY(NULL == p)) {
0508         return PMIX_ERR_NOMEM;
0509     }
0510     memcpy(&p->proc, &src->proc, sizeof(pmix_proc_t));
0511     if (NULL != src->hostname) {
0512         p->hostname = pmix_tma_strdup(tma, src->hostname);
0513     }
0514     if (NULL != src->executable_name) {
0515         p->executable_name = pmix_tma_strdup(tma, src->executable_name);
0516     }
0517     memcpy(&p->pid, &src->pid, sizeof(pid_t));
0518     memcpy(&p->exit_code, &src->exit_code, sizeof(int));
0519     memcpy(&p->state, &src->state, sizeof(pmix_proc_state_t));
0520     *dest = p;
0521     return PMIX_SUCCESS;
0522 }
0523 
0524 static inline
0525 void pmix_bfrops_base_tma_value_construct(pmix_value_t *val,
0526                                           pmix_tma_t *tma)
0527 {
0528     PMIX_HIDE_UNUSED_PARAMS(tma);
0529 
0530     memset(val, 0, sizeof(pmix_value_t));
0531     val->type = PMIX_UNDEF;
0532 }
0533 
0534 static inline
0535 pmix_value_t* pmix_bfrops_base_tma_value_create(size_t n,
0536                                                 pmix_tma_t *tma)
0537 {
0538     if (0 == n) {
0539         return NULL;
0540     }
0541     pmix_value_t *v = (pmix_value_t *)pmix_tma_malloc(tma, n * sizeof(pmix_value_t));
0542     if (PMIX_LIKELY(NULL != v)) {
0543         for (size_t m = 0; m < n; m++) {
0544             pmix_bfrops_base_tma_value_construct(&v[m], tma);
0545         }
0546     }
0547     return v;
0548 }
0549 
0550 static inline
0551 pmix_status_t pmix_bfrops_base_tma_value_load(pmix_value_t *v,
0552                                               const void *data,
0553                                               pmix_data_type_t type,
0554                                               pmix_tma_t *tma)
0555 {
0556     PMIX_HIDE_UNUSED_PARAMS(tma);
0557     // TODO(skg) Add TMA support when necessary.
0558     pmix_bfrops_base_value_load(v, data, type);
0559     return PMIX_SUCCESS;
0560 }
0561 
0562 static inline
0563 pmix_boolean_t pmix_bfrops_base_tma_value_true(const pmix_value_t *value,
0564                                                pmix_tma_t *tma)
0565 {
0566     PMIX_HIDE_UNUSED_PARAMS(tma);
0567 
0568     char *ptr;
0569 
0570     if (PMIX_UNDEF == value->type) {
0571         return PMIX_BOOL_TRUE; // default to true
0572     }
0573     if (PMIX_BOOL == value->type) {
0574         if (value->data.flag) {
0575             return PMIX_BOOL_TRUE;
0576         } else {
0577             return PMIX_BOOL_FALSE;
0578         }
0579     }
0580     if (PMIX_STRING == value->type) {
0581         if (NULL == value->data.string) {
0582             return PMIX_BOOL_TRUE;
0583         }
0584         ptr = value->data.string;
0585         /* Trim leading whitespace */
0586         while (isspace(*ptr)) {
0587             ++ptr;
0588         }
0589         if ('\0' == *ptr) {
0590             return PMIX_BOOL_TRUE;
0591         }
0592         if (isdigit(*ptr)) {
0593             if (0 == atoi(ptr)) {
0594                 return PMIX_BOOL_FALSE;
0595             } else {
0596                 return PMIX_BOOL_TRUE;
0597             }
0598         } else if (0 == strncasecmp(ptr, "yes", 3) ||
0599                    0 == strncasecmp(ptr, "true", 4)) {
0600             return PMIX_BOOL_TRUE;
0601         } else if (0 == strncasecmp(ptr, "no", 2) ||
0602                    0 == strncasecmp(ptr, "false", 5)) {
0603             return PMIX_BOOL_FALSE;
0604         }
0605     }
0606 
0607     return PMIX_NON_BOOL;
0608 }
0609 
0610 static inline
0611 bool pmix_bfrops_base_tma_info_is_persistent(const pmix_info_t *p,
0612                                              pmix_tma_t *tma)
0613 {
0614     PMIX_HIDE_UNUSED_PARAMS(tma);
0615 
0616     return PMIX_CHECK_BIT_IS_SET(p->flags, PMIX_INFO_PERSISTENT);
0617 }
0618 
0619 static inline
0620 void pmix_bfrops_base_tma_info_destruct(pmix_info_t *p,
0621                                         pmix_tma_t *tma)
0622 {
0623     if (!pmix_bfrops_base_tma_info_is_persistent(p, tma)) {
0624         pmix_bfrops_base_tma_value_destruct(&p->value, tma);
0625     }
0626 }
0627 
0628 static inline
0629 void pmix_bfrops_base_tma_info_free(pmix_info_t *p,
0630                                     size_t n,
0631                                     pmix_tma_t *tma)
0632 {
0633     if (NULL != p) {
0634         for (size_t m = 0; m < n; m++) {
0635             pmix_bfrops_base_tma_info_destruct(&p[m], tma);
0636         }
0637         pmix_tma_free(tma, p);
0638     }
0639 }
0640 
0641 static inline
0642 void pmix_bfrops_base_tma_info_construct(pmix_info_t *p,
0643                                          pmix_tma_t *tma)
0644 {
0645     pmix_bfrops_base_tma_load_key(p->key, NULL, tma);
0646     p->flags = 0;  // default to non-persistent for historical reasons
0647     pmix_bfrops_base_tma_value_construct(&p->value, tma);
0648 }
0649 
0650 static inline
0651 pmix_info_t* pmix_bfrops_base_tma_info_create(size_t n,
0652                                               pmix_tma_t *tma)
0653 {
0654     if (0 == n) {
0655         return NULL;
0656     }
0657     pmix_info_t *i = (pmix_info_t *)pmix_tma_malloc(tma, n * sizeof(pmix_info_t));
0658     if (PMIX_UNLIKELY(NULL == i)) {
0659         return NULL;
0660     }
0661     for (size_t m = 0; m < n; m++) {
0662         pmix_bfrops_base_tma_info_construct(&i[m], tma);
0663     }
0664     return i;
0665 }
0666 
0667 static inline
0668 pmix_status_t pmix_bfrops_base_tma_info_load(pmix_info_t *info,
0669                                              const char *key,
0670                                              const void *data,
0671                                              pmix_data_type_t type,
0672                                              pmix_tma_t *tma)
0673 {
0674     pmix_bfrops_base_tma_info_construct(info, tma);
0675     if (NULL == key) {
0676         return PMIX_ERR_BAD_PARAM;
0677     }
0678     pmix_bfrops_base_tma_load_key(info->key, key, tma);
0679     return pmix_bfrops_base_tma_value_load(&info->value, data, type, tma);
0680 }
0681 
0682 static inline
0683 pmix_boolean_t pmix_bfrops_base_tma_info_true(const pmix_info_t *p,
0684                                               pmix_tma_t *tma)
0685 {
0686     return pmix_bfrops_base_tma_value_true(&p->value, tma);
0687 }
0688 
0689 static inline
0690 pmix_status_t pmix_bfrops_base_tma_fill_coord(pmix_coord_t *dst,
0691                                               pmix_coord_t *src,
0692                                               pmix_tma_t *tma)
0693 {
0694     dst->view = src->view;
0695     dst->dims = src->dims;
0696     if (0 < dst->dims) {
0697         dst->coord = (uint32_t *)pmix_tma_malloc(tma, dst->dims * sizeof(uint32_t));
0698         if (PMIX_UNLIKELY(NULL == dst->coord)) {
0699             return PMIX_ERR_NOMEM;
0700         }
0701         memcpy(dst->coord, src->coord, dst->dims * sizeof(uint32_t));
0702     }
0703     return PMIX_SUCCESS;
0704 }
0705 
0706 static inline
0707 void pmix_bfrops_base_tma_coord_destruct(pmix_coord_t *m,
0708                                          pmix_tma_t *tma)
0709 {
0710     if (NULL != m) {
0711         m->view = PMIX_COORD_VIEW_UNDEF;
0712         if (NULL != m->coord) {
0713             pmix_tma_free(tma, m->coord);
0714             m->coord = NULL;
0715             m->dims = 0;
0716         }
0717     }
0718 }
0719 
0720 static inline
0721 pmix_coord_t* pmix_bfrops_base_tma_coord_create(size_t dims,
0722                                                 size_t number,
0723                                                 pmix_tma_t *tma)
0724 {
0725     if (0 == number) {
0726         return NULL;
0727     }
0728     pmix_coord_t *m = (pmix_coord_t *)pmix_tma_malloc(tma, number * sizeof(pmix_coord_t));
0729     if (PMIX_UNLIKELY(NULL == m)) {
0730         return NULL;
0731     }
0732     m->view = PMIX_COORD_VIEW_UNDEF;
0733     m->dims = dims;
0734     if (0 == dims) {
0735         m->coord = NULL;
0736     } else {
0737         m->coord = (uint32_t *)pmix_tma_malloc(tma, dims * sizeof(uint32_t));
0738         if (PMIX_LIKELY(NULL != m->coord)) {
0739             memset(m->coord, 0, dims * sizeof(uint32_t));
0740         }
0741     }
0742     return m;
0743 }
0744 
0745 static inline
0746 void pmix_bfrops_base_tma_coord_free(pmix_coord_t *m,
0747                                      size_t number,
0748                                      pmix_tma_t *tma)
0749 {
0750     if (NULL != m) {
0751         for (size_t n = 0; n < number; n++) {
0752             pmix_bfrops_base_tma_coord_destruct(&m[n], tma);
0753         }
0754         pmix_tma_free(tma, m);
0755     }
0756 }
0757 
0758 static inline
0759 void pmix_bfrops_base_tma_info_required(pmix_info_t *p,
0760                                         pmix_tma_t *tma)
0761 {
0762     PMIX_HIDE_UNUSED_PARAMS(tma);
0763 
0764     PMIX_SET_BIT(p->flags, PMIX_INFO_REQD);
0765 }
0766 
0767 static inline
0768 bool pmix_bfrops_base_tma_info_is_required(const pmix_info_t *p,
0769                                            pmix_tma_t *tma)
0770 {
0771     PMIX_HIDE_UNUSED_PARAMS(tma);
0772 
0773     return PMIX_CHECK_BIT_IS_SET(p->flags, PMIX_INFO_REQD);
0774 }
0775 
0776 static inline
0777 void pmix_bfrops_base_tma_info_optional(pmix_info_t *p,
0778                                         pmix_tma_t *tma)
0779 {
0780     PMIX_HIDE_UNUSED_PARAMS(tma);
0781 
0782     PMIX_UNSET_BIT(p->flags, PMIX_INFO_REQD);
0783 }
0784 
0785 static inline
0786 bool pmix_bfrops_base_tma_info_is_optional(const pmix_info_t *p,
0787                                            pmix_tma_t *tma)
0788 {
0789     PMIX_HIDE_UNUSED_PARAMS(tma);
0790 
0791     return PMIX_CHECK_BIT_NOT_SET(p->flags, PMIX_INFO_REQD);
0792 }
0793 
0794 static inline
0795 void pmix_bfrops_base_tma_info_processed(pmix_info_t *p,
0796                                          pmix_tma_t *tma)
0797 {
0798     PMIX_HIDE_UNUSED_PARAMS(tma);
0799 
0800     PMIX_SET_BIT(p->flags, PMIX_INFO_REQD_PROCESSED);
0801 }
0802 
0803 static inline
0804 bool pmix_bfrops_base_tma_info_was_processed(const pmix_info_t *p,
0805                                              pmix_tma_t *tma)
0806 {
0807     PMIX_HIDE_UNUSED_PARAMS(tma);
0808 
0809     return PMIX_CHECK_BIT_IS_SET(p->flags, PMIX_INFO_REQD_PROCESSED);
0810 }
0811 
0812 static inline
0813 void pmix_bfrops_base_tma_info_set_end(pmix_info_t *p,
0814                                        pmix_tma_t *tma)
0815 {
0816     PMIX_HIDE_UNUSED_PARAMS(tma);
0817 
0818     PMIX_SET_BIT(p->flags, PMIX_INFO_ARRAY_END);
0819 }
0820 
0821 static inline
0822 bool pmix_bfrops_base_tma_info_is_end(const pmix_info_t *p,
0823                                       pmix_tma_t *tma)
0824 {
0825     PMIX_HIDE_UNUSED_PARAMS(tma);
0826 
0827     return PMIX_CHECK_BIT_IS_SET(p->flags, PMIX_INFO_ARRAY_END);
0828 }
0829 
0830 static inline
0831 void pmix_bfrops_base_tma_info_qualifier(pmix_info_t *p,
0832                                          pmix_tma_t *tma)
0833 {
0834     PMIX_HIDE_UNUSED_PARAMS(tma);
0835 
0836 PMIX_SET_BIT(p->flags, PMIX_INFO_QUALIFIER);
0837 }
0838 
0839 static inline
0840 bool pmix_bfrops_base_tma_info_is_qualifier(const pmix_info_t *p,
0841                                             pmix_tma_t *tma)
0842 {
0843     PMIX_HIDE_UNUSED_PARAMS(tma);
0844 
0845     return PMIX_CHECK_BIT_IS_SET(p->flags, PMIX_INFO_QUALIFIER);
0846 }
0847 
0848 static inline
0849 void pmix_bfrops_base_tma_info_persistent(pmix_info_t *p,
0850                                           pmix_tma_t *tma)
0851 {
0852     PMIX_HIDE_UNUSED_PARAMS(tma);
0853 
0854     PMIX_SET_BIT(p->flags, PMIX_INFO_PERSISTENT);
0855 }
0856 
0857 static inline
0858 pmix_status_t pmix_bfrops_base_tma_info_xfer(pmix_info_t *dest,
0859                                              const pmix_info_t *src,
0860                                              pmix_tma_t *tma)
0861 {
0862     pmix_status_t rc;
0863 
0864     if (PMIX_UNLIKELY(NULL == dest || NULL == src)) {
0865         return PMIX_ERR_BAD_PARAM;
0866     }
0867     pmix_bfrops_base_tma_load_key(dest->key, src->key, tma);
0868     dest->flags = src->flags;
0869     if (pmix_bfrops_base_tma_info_is_persistent(src, tma)) {
0870         memcpy(&dest->value, &src->value, sizeof(pmix_value_t));
0871         rc = PMIX_SUCCESS;
0872     }
0873     else {
0874         rc = pmix_bfrops_base_tma_value_xfer(&dest->value, &src->value, tma);
0875     }
0876     return rc;
0877 }
0878 
0879 static inline
0880 void pmix_bfrops_base_tma_coord_construct(pmix_coord_t *m,
0881                                           pmix_tma_t *tma)
0882 {
0883     PMIX_HIDE_UNUSED_PARAMS(tma);
0884 
0885     if (NULL == m) {
0886         return;
0887     }
0888     m->view = PMIX_COORD_VIEW_UNDEF;
0889     m->coord = NULL;
0890     m->dims = 0;
0891 }
0892 
0893 static inline
0894 pmix_status_t pmix_bfrops_base_tma_copy_coord(pmix_coord_t **dest,
0895                                               pmix_coord_t *src,
0896                                               pmix_data_type_t type,
0897                                               pmix_tma_t *tma)
0898 {
0899     PMIX_HIDE_UNUSED_PARAMS(type);
0900 
0901     pmix_coord_t *d = (pmix_coord_t *)pmix_tma_malloc(tma, sizeof(pmix_coord_t));
0902     if (PMIX_UNLIKELY(NULL == d)) {
0903         return PMIX_ERR_NOMEM;
0904     }
0905 
0906     pmix_bfrops_base_tma_coord_construct(d, tma);
0907     pmix_status_t rc = pmix_bfrops_base_tma_fill_coord(d, src, tma);
0908     if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
0909         pmix_bfrops_base_tma_coord_destruct(d, tma);
0910         pmix_tma_free(tma, d);
0911     }
0912     else {
0913         *dest = d;
0914     }
0915     return rc;
0916 }
0917 
0918 static inline
0919 void pmix_bfrops_base_tma_topology_construct(pmix_topology_t *t,
0920                                              pmix_tma_t *tma)
0921 {
0922     PMIX_HIDE_UNUSED_PARAMS(tma);
0923 
0924     memset(t, 0, sizeof(pmix_topology_t));
0925 }
0926 
0927 static inline
0928 void pmix_bfrops_base_tma_topology_destruct(pmix_topology_t *t,
0929                                             pmix_tma_t *tma)
0930 {
0931     PMIX_HIDE_UNUSED_PARAMS(tma);
0932     // TODO(skg) Add TMA support when necessary.
0933     pmix_hwloc_destruct_topology(t);
0934 }
0935 
0936 static inline
0937 pmix_topology_t* pmix_bfrops_base_tma_topology_create(size_t n,
0938                                                       pmix_tma_t *tma)
0939 {
0940     if (0 == n) {
0941         return NULL;
0942     }
0943     pmix_topology_t *t = (pmix_topology_t *)pmix_tma_malloc(tma, n * sizeof(pmix_topology_t));
0944     if (PMIX_LIKELY(NULL != t)) {
0945         for (size_t m = 0; m < n; m++) {
0946             pmix_bfrops_base_tma_topology_construct(&t[m], tma);
0947         }
0948     }
0949     return t;
0950 }
0951 
0952 static inline
0953 pmix_status_t pmix_bfrops_base_tma_copy_topology(pmix_topology_t **dest,
0954                                                  pmix_topology_t *src,
0955                                                  pmix_data_type_t type,
0956                                                  pmix_tma_t *tma)
0957 {
0958     PMIX_HIDE_UNUSED_PARAMS(type);
0959 
0960     pmix_topology_t *dst = pmix_bfrops_base_tma_topology_create(1, tma);
0961     if (PMIX_UNLIKELY(NULL == dst)) {
0962         return PMIX_ERR_NOMEM;
0963     }
0964     // TODO(skg) Add TMA support when necessary.
0965     pmix_status_t rc = pmix_hwloc_copy_topology(dst, src);
0966     if (PMIX_SUCCESS == rc) {
0967         *dest = dst;
0968     }
0969     else {
0970         pmix_tma_free(tma, dst);
0971     }
0972     return rc;
0973 }
0974 
0975 static inline
0976 void pmix_bfrops_base_tma_topology_free(pmix_topology_t *t,
0977                                         size_t n,
0978                                         pmix_tma_t *tma)
0979 {
0980     if (NULL != t) {
0981         for (size_t m = 0; m < n; m++) {
0982             pmix_bfrops_base_tma_topology_destruct(&t[m], tma);
0983         }
0984         pmix_tma_free(tma, t);
0985     }
0986 }
0987 
0988 static inline
0989 void pmix_bfrops_base_tma_cpuset_construct(pmix_cpuset_t *c,
0990                                            pmix_tma_t *tma)
0991 {
0992     PMIX_HIDE_UNUSED_PARAMS(tma);
0993 
0994     memset(c, 0, sizeof(pmix_cpuset_t));
0995 }
0996 
0997 static inline
0998 void pmix_bfrops_base_tma_cpuset_destruct(pmix_cpuset_t *c,
0999                                           pmix_tma_t *tma)
1000 {
1001     PMIX_HIDE_UNUSED_PARAMS(tma);
1002     // TODO(skg) Add TMA support when necessary.
1003     pmix_hwloc_destruct_cpuset(c);
1004 }
1005 
1006 static inline
1007 void pmix_bfrops_base_tma_cpuset_free(pmix_cpuset_t *c,
1008                                       size_t n,
1009                                       pmix_tma_t *tma)
1010 {
1011     if (NULL != c) {
1012         for (size_t m = 0; m < n; m++) {
1013             pmix_bfrops_base_tma_cpuset_destruct(&c[m], tma);
1014         }
1015         pmix_tma_free(tma, c);
1016     }
1017 }
1018 
1019 static inline
1020 pmix_cpuset_t* pmix_bfrops_base_tma_cpuset_create(size_t n,
1021                                                   pmix_tma_t *tma)
1022 {
1023     if (0 == n) {
1024         return NULL;
1025     }
1026     pmix_cpuset_t *c = (pmix_cpuset_t *)pmix_tma_malloc(tma, n * sizeof(pmix_cpuset_t));
1027     if (PMIX_LIKELY(NULL != c)) {
1028         for (size_t m = 0; m < n; m++) {
1029             pmix_bfrops_base_tma_cpuset_construct(&c[m], tma);
1030         }
1031     }
1032     return c;
1033 }
1034 
1035 static inline
1036 pmix_status_t pmix_bfrops_base_tma_copy_cpuset(pmix_cpuset_t **dest,
1037                                                pmix_cpuset_t *src,
1038                                                pmix_data_type_t type,
1039                                                pmix_tma_t *tma)
1040 {
1041     PMIX_HIDE_UNUSED_PARAMS(type);
1042 
1043     pmix_cpuset_t *dst = pmix_bfrops_base_tma_cpuset_create(1, tma);
1044     if (PMIX_UNLIKELY(NULL == dst)) {
1045         return PMIX_ERR_NOMEM;
1046     }
1047     // TODO(skg) Add TMA support when necessary.
1048     pmix_status_t rc = pmix_hwloc_copy_cpuset(dst, src);
1049     if (PMIX_SUCCESS == rc) {
1050         *dest = dst;
1051     }
1052     else {
1053         pmix_tma_free(tma, dst);
1054     }
1055     return rc;
1056 }
1057 
1058 static inline
1059 void pmix_bfrops_base_tma_geometry_construct(pmix_geometry_t *g,
1060                                              pmix_tma_t *tma)
1061 {
1062     PMIX_HIDE_UNUSED_PARAMS(tma);
1063 
1064     memset(g, 0, sizeof(pmix_geometry_t));
1065 }
1066 
1067 static inline
1068 pmix_geometry_t* pmix_bfrops_base_tma_geometry_create(size_t n,
1069                                                       pmix_tma_t *tma)
1070 {
1071     if (0 == n) {
1072         return NULL;
1073     }
1074     pmix_geometry_t *g = (pmix_geometry_t *)pmix_tma_malloc(tma, n * sizeof(pmix_geometry_t));
1075     if (PMIX_LIKELY(NULL != g)) {
1076         for (size_t m = 0; m < n; m++) {
1077             pmix_bfrops_base_tma_geometry_construct(&g[m], tma);
1078         }
1079     }
1080     return g;
1081 }
1082 
1083 static inline
1084 void pmix_bfrops_base_tma_geometry_destruct(pmix_geometry_t *g,
1085                                             pmix_tma_t *tma)
1086 {
1087     if (NULL != g->uuid) {
1088         pmix_tma_free(tma, g->uuid);
1089         g->uuid = NULL;
1090     }
1091     if (NULL != g->osname) {
1092         pmix_tma_free(tma, g->osname);
1093         g->osname = NULL;
1094     }
1095     if (NULL != g->coordinates) {
1096         pmix_bfrops_base_tma_coord_free(g->coordinates, g->ncoords, tma);
1097     }
1098 }
1099 
1100 static inline
1101 void pmix_bfrops_base_tma_geometry_free(pmix_geometry_t *g,
1102                                         size_t n,
1103                                         pmix_tma_t *tma)
1104 {
1105     if (NULL != g) {
1106         for (size_t m = 0; m < n; m++) {
1107             pmix_bfrops_base_tma_geometry_destruct(&g[m], tma);
1108         }
1109         pmix_tma_free(tma, g);
1110     }
1111 }
1112 
1113 static inline
1114 pmix_status_t pmix_bfrops_base_tma_copy_geometry(pmix_geometry_t **dest,
1115                                                  pmix_geometry_t *src,
1116                                                  pmix_data_type_t type,
1117                                                  pmix_tma_t *tma)
1118 {
1119     PMIX_HIDE_UNUSED_PARAMS(type);
1120 
1121     pmix_geometry_t *dst = pmix_bfrops_base_tma_geometry_create(1, tma);
1122     if (PMIX_UNLIKELY(NULL == dst)) {
1123         return PMIX_ERR_NOMEM;
1124     }
1125 
1126     dst->fabric = src->fabric;
1127     if (NULL != src->uuid) {
1128         dst->uuid = pmix_tma_strdup(tma, src->uuid);
1129     }
1130     if (NULL != src->osname) {
1131         dst->osname = pmix_tma_strdup(tma, src->osname);
1132     }
1133     if (NULL != src->coordinates) {
1134         dst->ncoords = src->ncoords;
1135         dst->coordinates = (pmix_coord_t *)pmix_tma_calloc(tma, dst->ncoords, sizeof(pmix_coord_t));
1136         for (size_t n = 0; n < dst->ncoords; n++) {
1137             pmix_status_t rc = pmix_bfrops_base_tma_fill_coord(&dst->coordinates[n], &src->coordinates[n], tma);
1138             if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
1139                 PMIX_GEOMETRY_FREE(dst, 1);
1140                 return rc;
1141             }
1142         }
1143     }
1144     *dest = dst;
1145     return PMIX_SUCCESS;
1146 }
1147 
1148 static inline
1149 pmix_status_t pmix_bfrops_base_tma_copy_nspace(pmix_nspace_t **dest,
1150                                                pmix_nspace_t *src,
1151                                                pmix_data_type_t type,
1152                                                pmix_tma_t *tma)
1153 {
1154     PMIX_HIDE_UNUSED_PARAMS(type);
1155 
1156     pmix_nspace_t *dst = (pmix_nspace_t *)pmix_tma_malloc(tma, sizeof(pmix_nspace_t));
1157     if (PMIX_UNLIKELY(NULL == dst)) {
1158         return PMIX_ERR_NOMEM;
1159     }
1160     pmix_bfrops_base_tma_load_nspace(*dst, (char *)src, tma);
1161     *dest = dst;
1162     return PMIX_SUCCESS;
1163 }
1164 
1165 static inline
1166 void pmix_bfrops_base_tma_device_distance_destruct(pmix_device_distance_t *d,
1167                                                    pmix_tma_t *tma)
1168 {
1169     if (NULL != (d->uuid)) {
1170         pmix_tma_free(tma, d->uuid);
1171     }
1172     if (NULL != (d->osname)) {
1173         pmix_tma_free(tma, d->osname);
1174     }
1175 }
1176 
1177 static inline
1178 void pmix_bfrops_base_tma_device_distance_free(pmix_device_distance_t *d,
1179                                                size_t n,
1180                                                pmix_tma_t *tma)
1181 {
1182     if (NULL != d) {
1183         for (size_t m = 0; m < n; m++) {
1184             pmix_bfrops_base_tma_device_distance_destruct(&d[m], tma);
1185         }
1186         pmix_tma_free(tma, d);
1187     }
1188 }
1189 
1190 static inline
1191 void pmix_bfrops_base_tma_device_distance_construct(pmix_device_distance_t *d,
1192                                                     pmix_tma_t *tma)
1193 {
1194     PMIX_HIDE_UNUSED_PARAMS(tma);
1195 
1196     memset(d, 0, sizeof(pmix_device_distance_t));
1197     d->type = PMIX_DEVTYPE_UNKNOWN;
1198     d->mindist = UINT16_MAX;
1199     d->maxdist = UINT16_MAX;
1200 }
1201 
1202 static inline
1203 pmix_device_distance_t* pmix_bfrops_base_tma_device_distance_create(size_t n,
1204                                                                     pmix_tma_t *tma)
1205 {
1206     if (0 == n) {
1207         return NULL;
1208     }
1209     pmix_device_distance_t *d = (pmix_device_distance_t *)pmix_tma_malloc(tma, n * sizeof(pmix_device_distance_t));
1210     if (PMIX_LIKELY(NULL != d)) {
1211         for (size_t m = 0; m < n; m++) {
1212             pmix_bfrops_base_tma_device_distance_construct(&d[m], tma);
1213         }
1214     }
1215     return d;
1216 }
1217 
1218 static inline
1219 pmix_status_t pmix_bfrops_base_tma_copy_devdist(pmix_device_distance_t **dest,
1220                                                 pmix_device_distance_t *src,
1221                                                 pmix_data_type_t type,
1222                                                 pmix_tma_t *tma)
1223 {
1224     PMIX_HIDE_UNUSED_PARAMS(type);
1225 
1226     pmix_device_distance_t *dst = pmix_bfrops_base_tma_device_distance_create(1, tma);
1227     if (PMIX_UNLIKELY(NULL == dst)) {
1228         return PMIX_ERR_NOMEM;
1229     }
1230 
1231     if (NULL != src->uuid) {
1232         dst->uuid = pmix_tma_strdup(tma, src->uuid);
1233     }
1234     if (NULL != src->osname) {
1235         dst->osname = pmix_tma_strdup(tma, src->osname);
1236     }
1237     dst->type = src->type;
1238     dst->mindist = src->mindist;
1239     dst->maxdist = src->maxdist;
1240 
1241     *dest = dst;
1242     return PMIX_SUCCESS;
1243 }
1244 
1245 static inline
1246 void pmix_bfrops_base_tma_byte_object_construct(pmix_byte_object_t *b,
1247                                                 pmix_tma_t *tma)
1248 {
1249     PMIX_HIDE_UNUSED_PARAMS(tma);
1250 
1251     b->bytes = NULL;
1252     b->size = 0;
1253 }
1254 
1255 static inline
1256 void pmix_bfrops_base_tma_byte_object_destruct(pmix_byte_object_t *b,
1257                                                pmix_tma_t *tma)
1258 {
1259     if (NULL != b->bytes) {
1260         pmix_tma_free(tma, b->bytes);
1261     }
1262     b->bytes = NULL;
1263     b->size = 0;
1264 }
1265 
1266 static inline
1267 pmix_byte_object_t* pmix_bfrops_base_tma_byte_object_create(size_t n,
1268                                                             pmix_tma_t *tma)
1269 {
1270     if (0 == n) {
1271         return NULL;
1272     }
1273     pmix_byte_object_t *b = (pmix_byte_object_t *)pmix_tma_malloc(tma, n * sizeof(pmix_byte_object_t));
1274     if (PMIX_LIKELY(NULL != b)) {
1275         for (size_t m = 0; m < n; m++) {
1276             pmix_bfrops_base_tma_byte_object_construct(&b[m], tma);
1277         }
1278     }
1279     return b;
1280 }
1281 
1282 static inline
1283 void pmix_bfrops_base_tma_byte_object_free(pmix_byte_object_t *b,
1284                                            size_t n,
1285                                            pmix_tma_t *tma)
1286 {
1287     if (NULL != b) {
1288         for (size_t m = 0; m < n; m++) {
1289             pmix_bfrops_base_tma_byte_object_destruct(&b[m], tma);
1290         }
1291         pmix_tma_free(tma, b);
1292     }
1293 }
1294 
1295 static inline
1296 void pmix_bfrops_base_tma_endpoint_construct(pmix_endpoint_t *e,
1297                                              pmix_tma_t *tma)
1298 {
1299     PMIX_HIDE_UNUSED_PARAMS(tma);
1300 
1301     memset(e, 0, sizeof(pmix_endpoint_t));
1302 }
1303 
1304 static inline
1305 void pmix_bfrops_base_tma_endpoint_destruct(pmix_endpoint_t *e,
1306                                             pmix_tma_t *tma)
1307 {
1308     if (NULL != e->uuid) {
1309         pmix_tma_free(tma, e->uuid);
1310     }
1311     if (NULL != e->osname) {
1312         pmix_tma_free(tma, e->osname);
1313     }
1314     if (NULL != e->endpt.bytes) {
1315         pmix_tma_free(tma, e->endpt.bytes);
1316     }
1317 }
1318 
1319 static inline
1320 void pmix_bfrops_base_tma_endpoint_free(pmix_endpoint_t *e,
1321                                         size_t n,
1322                                         pmix_tma_t *tma)
1323 {
1324     if (NULL != e) {
1325         for (size_t m = 0; m < n; m++) {
1326             pmix_bfrops_base_tma_endpoint_destruct(&e[m], tma);
1327         }
1328         pmix_tma_free(tma, e);
1329     }
1330 }
1331 
1332 static inline
1333 pmix_endpoint_t* pmix_bfrops_base_tma_endpoint_create(size_t n,
1334                                                       pmix_tma_t *tma)
1335 {
1336     if (0 == n) {
1337         return NULL;
1338     }
1339 
1340     pmix_endpoint_t *e = (pmix_endpoint_t *)pmix_tma_malloc(tma, n * sizeof(pmix_endpoint_t));
1341     if (PMIX_LIKELY(NULL != e)) {
1342         for (size_t m = 0; m < n; m++) {
1343             pmix_bfrops_base_tma_endpoint_construct(&e[m], tma);
1344         }
1345     }
1346     return e;
1347 }
1348 
1349 static inline
1350 pmix_status_t pmix_bfrops_base_tma_copy_endpoint(pmix_endpoint_t **dest,
1351                                                  pmix_endpoint_t *src,
1352                                                  pmix_data_type_t type,
1353                                                  pmix_tma_t *tma)
1354 {
1355     PMIX_HIDE_UNUSED_PARAMS(type);
1356 
1357     pmix_endpoint_t *dst = pmix_bfrops_base_tma_endpoint_create(1, tma);
1358     if (PMIX_UNLIKELY(NULL == dst)) {
1359         return PMIX_ERR_NOMEM;
1360     }
1361 
1362     if (NULL != src->uuid) {
1363         dst->uuid = pmix_tma_strdup(tma, src->uuid);
1364     }
1365     if (NULL != src->osname) {
1366         dst->osname = pmix_tma_strdup(tma, src->osname);
1367     }
1368     if (NULL != src->endpt.bytes) {
1369         dst->endpt.bytes = (char *)pmix_tma_malloc(tma, src->endpt.size);
1370         memcpy(dst->endpt.bytes, src->endpt.bytes, src->endpt.size);
1371         dst->endpt.size = src->endpt.size;
1372     }
1373 
1374     *dest = dst;
1375     return PMIX_SUCCESS;
1376 }
1377 
1378 static inline
1379 int pmix_bfrops_base_tma_argv_count(char **argv,
1380                                     pmix_tma_t *tma)
1381 {
1382     PMIX_HIDE_UNUSED_PARAMS(tma);
1383 
1384     char **p;
1385     int i;
1386 
1387     if (NULL == argv)
1388         return 0;
1389 
1390     for (i = 0, p = argv; *p; i++, p++)
1391         continue;
1392 
1393     return i;
1394 }
1395 
1396 static inline
1397 pmix_status_t pmix_bfrops_base_tma_argv_append_nosize(char ***argv,
1398                                                       const char *arg,
1399                                                       pmix_tma_t *tma)
1400 {
1401     int argc;
1402 
1403     /* Create new argv. */
1404 
1405     if (NULL == *argv) {
1406         *argv = (char **)pmix_tma_malloc(tma, 2 * sizeof(char *));
1407         if (NULL == *argv) {
1408             return PMIX_ERR_OUT_OF_RESOURCE;
1409         }
1410         argc = 0;
1411         (*argv)[0] = NULL;
1412         (*argv)[1] = NULL;
1413     }
1414 
1415     /* Extend existing argv. */
1416     else {
1417         /* count how many entries currently exist */
1418         argc = pmix_bfrops_base_tma_argv_count(*argv, tma);
1419 
1420         *argv = (char **)pmix_tma_realloc(tma, *argv, (argc + 2) * sizeof(char *));
1421         if (NULL == *argv) {
1422             return PMIX_ERR_OUT_OF_RESOURCE;
1423         }
1424     }
1425 
1426     /* Set the newest element to point to a copy of the arg string */
1427 
1428     (*argv)[argc] = pmix_tma_strdup(tma, arg);
1429     if (NULL == (*argv)[argc]) {
1430         return PMIX_ERR_OUT_OF_RESOURCE;
1431     }
1432 
1433     argc = argc + 1;
1434     (*argv)[argc] = NULL;
1435 
1436     return PMIX_SUCCESS;
1437 }
1438 
1439 static inline
1440 pmix_status_t pmix_bfrops_base_tma_argv_prepend_nosize(char ***argv,
1441                                                        const char *arg,
1442                                                        pmix_tma_t *tma)
1443 {
1444     int argc;
1445     int i;
1446 
1447     /* Create new argv. */
1448 
1449     if (NULL == *argv) {
1450         *argv = (char **)pmix_tma_malloc(tma, 2 * sizeof(char *));
1451         if (NULL == *argv) {
1452             return PMIX_ERR_OUT_OF_RESOURCE;
1453         }
1454         (*argv)[0] = pmix_tma_strdup(tma, arg);
1455         (*argv)[1] = NULL;
1456     } else {
1457         /* count how many entries currently exist */
1458         argc = pmix_bfrops_base_tma_argv_count(*argv, tma);
1459 
1460         *argv = (char **)pmix_tma_realloc(tma, *argv, (argc + 2) * sizeof(char *));
1461         if (NULL == *argv) {
1462             return PMIX_ERR_OUT_OF_RESOURCE;
1463         }
1464         (*argv)[argc + 1] = NULL;
1465 
1466         /* shift all existing elements down 1 */
1467         for (i = argc; 0 < i; i--) {
1468             (*argv)[i] = (*argv)[i - 1];
1469         }
1470         (*argv)[0] = pmix_tma_strdup(tma, arg);
1471     }
1472 
1473     return PMIX_SUCCESS;
1474 }
1475 
1476 static inline
1477 pmix_status_t pmix_bfrops_base_tma_argv_append_unique_nosize(char ***argv,
1478                                                              const char *arg,
1479                                                              pmix_tma_t *tma)
1480 {
1481     int i;
1482 
1483     /* if the provided array is NULL, then the arg cannot be present,
1484      * so just go ahead and append
1485      */
1486     if (NULL == *argv) {
1487         return pmix_bfrops_base_tma_argv_append_nosize(argv, arg, tma);
1488     }
1489 
1490     /* see if this arg is already present in the array */
1491     for (i = 0; NULL != (*argv)[i]; i++) {
1492         if (0 == strcmp(arg, (*argv)[i])) {
1493             /* already exists */
1494             return PMIX_SUCCESS;
1495         }
1496     }
1497 
1498     /* we get here if the arg is not in the array - so add it */
1499     return pmix_bfrops_base_tma_argv_append_nosize(argv, arg, tma);
1500 }
1501 
1502 static inline
1503 void pmix_bfrops_base_tma_argv_free(char **argv,
1504                                     pmix_tma_t *tma)
1505 {
1506     if (NULL != argv) {
1507         for (char **p = argv; NULL != *p; ++p) {
1508             pmix_tma_free(tma, *p);
1509         }
1510         pmix_tma_free(tma, argv);
1511     }
1512 }
1513 
1514 static inline
1515 char** pmix_bfrops_base_tma_argv_split_inter(const char *src_string,
1516                                              int delimiter,
1517                                              bool include_empty,
1518                                              pmix_tma_t *tma)
1519 {
1520     char arg[512];
1521     char **argv = NULL;
1522     const char *p;
1523     char *argtemp;
1524     size_t arglen;
1525 
1526     while (src_string && *src_string) {
1527         p = src_string;
1528         arglen = 0;
1529 
1530         while (('\0' != *p) && (*p != delimiter)) {
1531             ++p;
1532             ++arglen;
1533         }
1534 
1535         /* zero length argument, skip */
1536 
1537         if (src_string == p) {
1538             if (include_empty) {
1539                 arg[0] = '\0';
1540                 if (PMIX_SUCCESS != pmix_bfrops_base_tma_argv_append_nosize(&argv, arg, NULL)) {
1541                     return NULL;
1542                 }
1543             }
1544             src_string = p + 1;
1545             continue;
1546         }
1547 
1548         /* tail argument, add straight from the original string */
1549 
1550         else if ('\0' == *p) {
1551             if (PMIX_SUCCESS != pmix_bfrops_base_tma_argv_append_nosize(&argv, src_string, tma)) {
1552                 return NULL;
1553             }
1554             src_string = p;
1555             continue;
1556         }
1557 
1558         /* long argument, malloc buffer, copy and add */
1559 
1560         else if (arglen > 511) {
1561             argtemp = (char *)pmix_tma_malloc(tma, arglen + 1);
1562             if (NULL == argtemp)
1563                 return NULL;
1564 
1565             pmix_strncpy(argtemp, src_string, arglen);
1566             argtemp[arglen] = '\0';
1567 
1568             if (PMIX_SUCCESS != pmix_bfrops_base_tma_argv_append_nosize(&argv, argtemp, tma)) {
1569                 pmix_tma_free(tma, argtemp);
1570                 return NULL;
1571             }
1572 
1573             pmix_tma_free(tma, argtemp);
1574         }
1575 
1576         /* short argument, copy to buffer and add */
1577 
1578         else {
1579             pmix_strncpy(arg, src_string, arglen);
1580             arg[arglen] = '\0';
1581 
1582             if (PMIX_SUCCESS != pmix_bfrops_base_tma_argv_append_nosize(&argv, arg, tma)) {
1583                 return NULL;
1584             }
1585         }
1586 
1587         src_string = p + 1;
1588     }
1589 
1590     /* All done */
1591 
1592     return argv;
1593 }
1594 
1595 static inline
1596 char** pmix_bfrops_base_tma_argv_split_with_empty(const char *src_string,
1597                                                   int delimiter,
1598                                                   pmix_tma_t *tma)
1599 {
1600     return pmix_bfrops_base_tma_argv_split_inter(src_string, delimiter, true, tma);
1601 }
1602 
1603 static inline
1604 char** pmix_bfrops_base_tma_argv_split(const char *src_string,
1605                                        int delimiter,
1606                                        pmix_tma_t *tma)
1607 {
1608     return pmix_bfrops_base_tma_argv_split_inter(src_string, delimiter, false, tma);
1609 }
1610 
1611 static inline
1612 char* pmix_bfrops_base_tma_argv_join(char **argv,
1613                                      int delimiter,
1614                                      pmix_tma_t *tma)
1615 {
1616     char **p;
1617     char *pp;
1618     char *str;
1619     size_t str_len = 0;
1620     size_t i;
1621 
1622     /* Bozo case */
1623 
1624     if (NULL == argv || NULL == argv[0]) {
1625         return pmix_tma_strdup(tma, "");
1626     }
1627 
1628     /* Find the total string length in argv including delimiters.  The
1629      last delimiter is replaced by the NULL character. */
1630 
1631     for (p = argv; *p; ++p) {
1632         str_len += strlen(*p) + 1;
1633     }
1634 
1635     /* Allocate the string. */
1636 
1637     if (NULL == (str = (char *)pmix_tma_malloc(tma, str_len)))
1638         return NULL;
1639 
1640     /* Loop filling in the string. */
1641 
1642     str[--str_len] = '\0';
1643     p = argv;
1644     pp = *p;
1645 
1646     for (i = 0; i < str_len; ++i) {
1647         if ('\0' == *pp) {
1648 
1649             /* End of a string, fill in a delimiter and go to the next
1650              string. */
1651 
1652             str[i] = (char) delimiter;
1653             ++p;
1654             pp = *p;
1655         } else {
1656             str[i] = *pp++;
1657         }
1658     }
1659 
1660     /* All done */
1661 
1662     return str;
1663 }
1664 
1665 static inline
1666 char** pmix_bfrops_base_tma_argv_copy(char **argv,
1667                                       pmix_tma_t *tma)
1668 {
1669     if (NULL == argv) {
1670         return NULL;
1671     }
1672     /* create an "empty" list, so that we return something valid if we
1673      were passed a valid list with no contained elements */
1674     char **dupv = (char **)pmix_tma_malloc(tma, sizeof(char *));
1675     dupv[0] = NULL;
1676 
1677     while (NULL != *argv) {
1678         if (PMIX_SUCCESS != pmix_bfrops_base_tma_argv_append_nosize(&dupv, *argv, tma)) {
1679             pmix_bfrops_base_tma_argv_free(dupv, tma);
1680             return NULL;
1681         }
1682         ++argv;
1683     }
1684     /* All done */
1685     return dupv;
1686 }
1687 
1688 static inline
1689 void pmix_bfrops_base_tma_query_destruct(pmix_query_t *p,
1690                                          pmix_tma_t *tma)
1691 {
1692     if (NULL != p->keys) {
1693         pmix_bfrops_base_tma_argv_free(p->keys, tma);
1694         p->keys = NULL;
1695     }
1696     if (NULL != p->qualifiers) {
1697         pmix_bfrops_base_tma_info_free(p->qualifiers, p->nqual, tma);
1698         p->qualifiers = NULL;
1699         p->nqual = 0;
1700     }
1701 }
1702 
1703 static inline
1704 void pmix_bfrops_base_tma_query_free(pmix_query_t *p,
1705                                      size_t n,
1706                                      pmix_tma_t *tma)
1707 {
1708     if (NULL != p) {
1709         for (size_t m = 0; m < n; m++) {
1710             pmix_bfrops_base_tma_query_destruct(&p[m], tma);
1711         }
1712         pmix_tma_free(tma, p);
1713     }
1714 }
1715 
1716 static inline
1717 void pmix_bfrops_base_tma_query_release(pmix_query_t *p,
1718                                         pmix_tma_t *tma)
1719 {
1720     pmix_bfrops_base_tma_query_free(p, 1, tma);
1721 }
1722 
1723 static inline
1724 void pmix_bfrops_base_tma_pdata_construct(pmix_pdata_t *p,
1725                                           pmix_tma_t *tma)
1726 {
1727     PMIX_HIDE_UNUSED_PARAMS(tma);
1728 
1729     memset(p, 0, sizeof(pmix_pdata_t));
1730     p->value.type = PMIX_UNDEF;
1731 }
1732 
1733 static inline
1734 void pmix_bfrops_base_tma_pdata_destruct(pmix_pdata_t *p,
1735                                          pmix_tma_t *tma)
1736 {
1737     pmix_bfrops_base_tma_value_destruct(&p->value, tma);
1738 }
1739 
1740 static inline
1741 pmix_pdata_t* pmix_bfrops_base_tma_pdata_create(size_t n,
1742                                                 pmix_tma_t *tma)
1743 {
1744     if (0 == n) {
1745         return NULL;
1746     }
1747     pmix_pdata_t *p = (pmix_pdata_t *)pmix_tma_malloc(tma, n * sizeof(pmix_pdata_t));
1748     if (PMIX_LIKELY(NULL != p)) {
1749         for (size_t m = 0; m < n; m++) {
1750             pmix_bfrops_base_tma_pdata_construct(&p[m], tma);
1751         }
1752     }
1753     return p;
1754 }
1755 
1756 static inline
1757 void pmix_bfrops_base_tma_pdata_xfer(pmix_pdata_t *dest,
1758                                      const pmix_pdata_t *src,
1759                                      pmix_tma_t *tma)
1760 {
1761     if (NULL != dest) {
1762         memset(dest, 0, sizeof(*dest));
1763         pmix_bfrops_base_tma_load_nspace(
1764             dest->proc.nspace, src->proc.nspace, tma
1765         );
1766         dest->proc.rank = src->proc.rank;
1767         pmix_bfrops_base_tma_load_key(dest->key, src->key, tma);
1768         pmix_bfrops_base_tma_value_xfer(&dest->value, &src->value, tma);
1769     }
1770 }
1771 
1772 static inline
1773 void pmix_bfrops_base_tma_pdata_free(pmix_pdata_t *p,
1774                                      size_t n,
1775                                      pmix_tma_t *tma)
1776 {
1777     if (NULL != p) {
1778         for (size_t m = 0; m < n; m++) {
1779             pmix_bfrops_base_tma_pdata_destruct(&p[m], tma);
1780         }
1781         pmix_tma_free(tma, p);
1782     }
1783 }
1784 
1785 static inline
1786 void pmix_bfrops_base_tma_app_destruct(pmix_app_t *p,
1787                                        pmix_tma_t *tma)
1788 {
1789     if (NULL != p->cmd) {
1790         pmix_tma_free(tma, p->cmd);
1791         p->cmd = NULL;
1792     }
1793     if (NULL != p->argv) {
1794         pmix_bfrops_base_tma_argv_free(p->argv, tma);
1795         p->argv = NULL;
1796     }
1797     if (NULL != p->env) {
1798         pmix_bfrops_base_tma_argv_free(p->env, tma);
1799         p->env = NULL;
1800     }
1801     if (NULL != p->cwd) {
1802         pmix_tma_free(tma, p->cwd);
1803         p->cwd = NULL;
1804     }
1805     if (NULL != p->info) {
1806         pmix_bfrops_base_tma_info_free(p->info, p->ninfo, tma);
1807         p->info = NULL;
1808         p->ninfo = 0;
1809     }
1810 }
1811 
1812 static inline
1813 void pmix_bfrops_base_tma_app_construct(pmix_app_t *p,
1814                                         pmix_tma_t *tma)
1815 {
1816     PMIX_HIDE_UNUSED_PARAMS(tma);
1817 
1818     memset(p, 0, sizeof(pmix_app_t));
1819 }
1820 
1821 static inline
1822 pmix_app_t* pmix_bfrops_base_tma_app_create(size_t n,
1823                                             pmix_tma_t *tma)
1824 {
1825     if (0 == n) {
1826         return NULL;
1827     }
1828     pmix_app_t *p = (pmix_app_t *)pmix_tma_malloc(tma, n * sizeof(pmix_app_t));
1829     if (PMIX_LIKELY(NULL != p)) {
1830         for (size_t m = 0; m < n; m++) {
1831             pmix_bfrops_base_tma_app_construct(&p[m], tma);
1832         }
1833     }
1834     return p;
1835 }
1836 
1837 static inline
1838 void pmix_bfrops_base_tma_app_info_create(pmix_app_t *p,
1839                                           size_t n,
1840                                           pmix_tma_t *tma)
1841 {
1842     p->ninfo = n;
1843     p->info = pmix_bfrops_base_tma_info_create(n, tma);
1844 }
1845 
1846 static inline
1847 void pmix_bfrops_base_tma_app_free(pmix_app_t *p,
1848                                    size_t n,
1849                                    pmix_tma_t *tma)
1850 {
1851     if (NULL != p) {
1852         for (size_t m = 0; m < n; m++) {
1853             pmix_bfrops_base_tma_app_destruct(&p[m], tma);
1854         }
1855         pmix_tma_free(tma, p);
1856     }
1857 }
1858 
1859 static inline
1860 void pmix_bfrops_base_tma_app_release(pmix_app_t *p,
1861                                       pmix_tma_t *tma)
1862 {
1863     pmix_bfrops_base_tma_app_free(p, 1, tma);
1864 }
1865 
1866 static inline
1867 void pmix_bfrops_base_tma_query_construct(pmix_query_t *p,
1868                                           pmix_tma_t *tma)
1869 {
1870     PMIX_HIDE_UNUSED_PARAMS(tma);
1871 
1872     memset(p, 0, sizeof(pmix_query_t));
1873 }
1874 
1875 static inline
1876 pmix_query_t* pmix_bfrops_base_tma_query_create(size_t n,
1877                                                 pmix_tma_t *tma)
1878 {
1879     if (0 == n) {
1880         return NULL;
1881     }
1882     pmix_query_t *p = (pmix_query_t *)pmix_tma_malloc(tma, n * sizeof(pmix_query_t));
1883     if (PMIX_LIKELY(NULL != p)) {
1884         for (size_t m = 0; m < n; m++) {
1885             pmix_bfrops_base_tma_query_construct(&p[m], tma);
1886         }
1887     }
1888     return p;
1889 }
1890 
1891 static inline
1892 void pmix_bfrops_base_tma_query_qualifiers_create(pmix_query_t *p,
1893                                                   size_t n,
1894                                                   pmix_tma_t *tma)
1895 {
1896     p->nqual = n;
1897     p->qualifiers = pmix_bfrops_base_tma_info_create(n, tma);
1898 }
1899 
1900 static inline
1901 void pmix_bfrops_base_tma_regattr_destruct(pmix_regattr_t *p,
1902                                            pmix_tma_t *tma)
1903 {
1904     if (NULL != p) {
1905         if (NULL != p->name) {
1906             pmix_tma_free(tma, p->name);
1907             p->name = NULL;
1908         }
1909         if (NULL != p->description) {
1910             pmix_bfrops_base_tma_argv_free(p->description, tma);
1911             p->description = NULL;
1912         }
1913     }
1914 }
1915 
1916 static inline
1917 void pmix_bfrops_base_tma_regattr_free(pmix_regattr_t *p,
1918                                        size_t n,
1919                                        pmix_tma_t *tma)
1920 {
1921     if (NULL != p) {
1922         for (size_t m = 0; m < n; m++) {
1923             pmix_bfrops_base_tma_regattr_destruct(&p[m], tma);
1924         }
1925         pmix_tma_free(tma, p);
1926     }
1927 }
1928 
1929 static inline
1930 void pmix_bfrops_base_tma_regattr_construct(pmix_regattr_t *p,
1931                                             pmix_tma_t *tma)
1932 {
1933     p->name = NULL;
1934     pmix_bfrops_base_tma_load_key(p->string, NULL, tma);
1935     p->type = PMIX_UNDEF;
1936     p->description = NULL;
1937 }
1938 
1939 static inline
1940 pmix_regattr_t* pmix_bfrops_base_tma_regattr_create(size_t n,
1941                                                     pmix_tma_t *tma)
1942 {
1943     if (0 == n) {
1944         return NULL;
1945     }
1946 
1947     pmix_regattr_t *p = (pmix_regattr_t*)pmix_tma_malloc(tma, n * sizeof(pmix_regattr_t));
1948     if (PMIX_LIKELY(NULL != p)) {
1949         for (size_t m = 0; m < n; m++) {
1950             pmix_bfrops_base_tma_regattr_construct(&p[m], tma);
1951         }
1952     }
1953     return p;
1954 }
1955 
1956 static inline
1957 void pmix_bfrops_base_tma_regattr_load(pmix_regattr_t *p,
1958                                        const char *name,
1959                                        const char *key,
1960                                        pmix_data_type_t type,
1961                                        const char *description,
1962                                        pmix_tma_t *tma)
1963 {
1964     if (NULL != name) {
1965         p->name = pmix_tma_strdup(tma, name);
1966     }
1967     if (NULL != key) {
1968         pmix_bfrops_base_tma_load_key(p->string, key, tma);
1969     }
1970     p->type = type;
1971     if (NULL != description) {
1972         pmix_bfrops_base_tma_argv_append_nosize(&p->description, description, tma);
1973     }
1974 }
1975 
1976 static inline
1977 void pmix_bfrops_base_tma_regattr_xfer(pmix_regattr_t *dest,
1978                                        const pmix_regattr_t *src,
1979                                        pmix_tma_t *tma)
1980 {
1981     pmix_bfrops_base_tma_regattr_construct(dest, tma);
1982     if (NULL != (src->name)) {
1983         dest->name = pmix_tma_strdup(tma, src->name);
1984     }
1985     pmix_bfrops_base_tma_load_key(dest->string, src->string, tma);
1986     dest->type = src->type;
1987     if (NULL != src->description) {
1988         dest->description = pmix_bfrops_base_tma_argv_copy(src->description, tma);
1989     }
1990 }
1991 
1992 static inline
1993 pmix_status_t pmix_bfrops_base_tma_setenv(const char *name,
1994                                           const char *value,
1995                                           bool overwrite,
1996                                           char ***env,
1997                                           pmix_tma_t *tma)
1998 {
1999     // Note to developers: we don't use the TMA here because the values we
2000     // allocate on the heap are values that are inconsequential to the way we
2001     // currently use the TMA.
2002     PMIX_HIDE_UNUSED_PARAMS(tma);
2003 
2004     /* Check the bozo case */
2005     if (NULL == env) {
2006         return PMIX_ERR_BAD_PARAM;
2007     }
2008 
2009     /* If this is the "environ" array, use setenv */
2010     if (*env == environ) {
2011         if (NULL == value) {
2012             /* this is actually an unsetenv request */
2013             unsetenv(name);
2014         } else {
2015             setenv(name, value, overwrite);
2016         }
2017         return PMIX_SUCCESS;
2018     }
2019 
2020     /* Make the new value */
2021     char *newvalue = NULL;
2022     if (NULL == value) {
2023         pmix_asprintf(&newvalue, "%s=", name);
2024     } else {
2025         pmix_asprintf(&newvalue, "%s=%s", name, value);
2026     }
2027     if (NULL == newvalue) {
2028         return PMIX_ERR_OUT_OF_RESOURCE;
2029     }
2030 
2031     if (NULL == *env) {
2032         pmix_bfrops_base_tma_argv_append_nosize(env, newvalue, NULL);
2033         free(newvalue);
2034         return PMIX_SUCCESS;
2035     }
2036 
2037     /* Make something easy to compare to */
2038     char *compare = NULL;
2039     pmix_asprintf(&compare, "%s=", name);
2040     if (NULL == compare) {
2041         free(newvalue);
2042         return PMIX_ERR_OUT_OF_RESOURCE;
2043     }
2044 
2045     /* Look for a duplicate that's already set in the env */
2046     const size_t len = strlen(compare);
2047     for (int i = 0; (*env)[i] != NULL; ++i) {
2048         if (0 == strncmp((*env)[i], compare, len)) {
2049             if (overwrite) {
2050                 free((*env)[i]);
2051                 (*env)[i] = newvalue;
2052                 free(compare);
2053                 return PMIX_SUCCESS;
2054             } else {
2055                 free(compare);
2056                 free(newvalue);
2057                 return PMIX_ERR_EXISTS;
2058             }
2059         }
2060     }
2061 
2062     /* If we found no match, append this value */
2063     pmix_bfrops_base_tma_argv_append_nosize(env, newvalue, NULL);
2064 
2065     /* All done */
2066     free(compare);
2067     free(newvalue);
2068     return PMIX_SUCCESS;
2069 }
2070 
2071 static inline
2072 void pmix_bfrops_base_tma_data_array_init(pmix_data_array_t *p,
2073                                           pmix_data_type_t type,
2074                                           pmix_tma_t *tma)
2075 {
2076     PMIX_HIDE_UNUSED_PARAMS(tma);
2077 
2078     p->array = NULL;
2079     p->type = type;
2080     p->size = 0;
2081 }
2082 
2083 static inline
2084 void pmix_bfrops_base_tma_data_buffer_construct(pmix_data_buffer_t *b,
2085                                                 pmix_tma_t *tma)
2086 {
2087     PMIX_HIDE_UNUSED_PARAMS(tma);
2088 
2089     memset(b, 0, sizeof(pmix_data_buffer_t));
2090 }
2091 
2092 static inline
2093 pmix_data_buffer_t* pmix_bfrops_base_tma_data_buffer_create(pmix_tma_t *tma)
2094 {
2095     pmix_data_buffer_t *b = (pmix_data_buffer_t *)pmix_tma_malloc(tma, sizeof(pmix_data_buffer_t));
2096     if (PMIX_LIKELY(NULL != b)) {
2097         pmix_bfrops_base_tma_data_buffer_construct(b, tma);
2098     }
2099     return b;
2100 }
2101 
2102 static inline
2103 void pmix_bfrops_base_tma_data_buffer_destruct(pmix_data_buffer_t *b,
2104                                                pmix_tma_t *tma)
2105 {
2106     if (NULL != b->base_ptr) {
2107         pmix_tma_free(tma, b->base_ptr);
2108         b->base_ptr = NULL;
2109     }
2110     b->pack_ptr = NULL;
2111     b->unpack_ptr = NULL;
2112     b->bytes_allocated = 0;
2113     b->bytes_used = 0;
2114 }
2115 
2116 static inline
2117 void pmix_bfrops_base_tma_data_buffer_release(pmix_data_buffer_t *b,
2118                                               pmix_tma_t *tma)
2119 {
2120     if (NULL != b) {
2121         pmix_bfrops_base_tma_data_buffer_destruct(b, tma);
2122         pmix_tma_free(tma, b);
2123     }
2124 }
2125 
2126 static inline
2127 pmix_status_t pmix_bfrops_base_tma_copy_dbuf(pmix_data_buffer_t **dest,
2128                                              pmix_data_buffer_t *src,
2129                                              pmix_data_type_t type,
2130                                              pmix_tma_t *tma)
2131 {
2132     PMIX_HIDE_UNUSED_PARAMS(type);
2133 
2134     pmix_data_buffer_t *p = pmix_bfrops_base_tma_data_buffer_create(tma);
2135     if (PMIX_UNLIKELY(NULL == p)) {
2136         return PMIX_ERR_NOMEM;
2137     }
2138     *dest = p;
2139     // TODO(skg) Add TMA support when necessary.
2140     return PMIx_Data_copy_payload(p, src);
2141 }
2142 
2143 static inline
2144 void pmix_bfrops_base_tma_value_free(pmix_value_t *v,
2145                                      size_t n,
2146                                      pmix_tma_t *tma)
2147 {
2148     if (NULL != v) {
2149         for (size_t m = 0; m < n; m++) {
2150             pmix_bfrops_base_tma_value_destruct(&v[m], tma);
2151         }
2152         pmix_tma_free(tma, v);
2153     }
2154 }
2155 
2156 static inline
2157 pmix_status_t pmix_bfrops_base_tma_value_unload(pmix_value_t *kv,
2158                                                 void **data,
2159                                                 size_t *sz,
2160                                                 pmix_tma_t *tma)
2161 {
2162     PMIX_HIDE_UNUSED_PARAMS(tma);
2163     // TODO(skg) Add TMA support when necessary.
2164     return pmix_bfrops_base_value_unload(kv, data, sz);
2165 }
2166 
2167 static inline
2168 pmix_status_t pmix_bfrops_base_tma_copy_regattr(pmix_regattr_t **dest,
2169                                                 pmix_regattr_t *src,
2170                                                 pmix_data_type_t type,
2171                                                 pmix_tma_t *tma)
2172 {
2173     PMIX_HIDE_UNUSED_PARAMS(type);
2174 
2175     *dest = pmix_bfrops_base_tma_regattr_create(1, tma);
2176     if (PMIX_UNLIKELY(NULL == (*dest))) {
2177         return PMIX_ERR_NOMEM;
2178     }
2179     if (NULL != src->name) {
2180         (*dest)->name = pmix_tma_strdup(tma, src->name);
2181     }
2182     pmix_bfrops_base_tma_load_key((*dest)->string, src->string, tma);
2183     (*dest)->type = src->type;
2184     (*dest)->description = pmix_bfrops_base_tma_argv_copy(src->description, tma);
2185     return PMIX_SUCCESS;
2186 }
2187 
2188 static inline
2189 void pmix_bfrops_base_tma_envar_construct(pmix_envar_t *e,
2190                                           pmix_tma_t *tma)
2191 {
2192     PMIX_HIDE_UNUSED_PARAMS(tma);
2193 
2194     e->envar = NULL;
2195     e->value = NULL;
2196     e->separator = '\0';
2197 }
2198 
2199 static inline
2200 void pmix_bfrops_base_tma_envar_destruct(pmix_envar_t *e,
2201                                          pmix_tma_t *tma)
2202 {
2203     if (NULL != e->envar) {
2204         pmix_tma_free(tma, e->envar);
2205         e->envar = NULL;
2206     }
2207     if (NULL != e->value) {
2208         pmix_tma_free(tma, e->value);
2209         e->value = NULL;
2210     }
2211 }
2212 
2213 static inline
2214 pmix_envar_t* pmix_bfrops_base_tma_envar_create(size_t n,
2215                                                 pmix_tma_t *tma)
2216 {
2217     if (0 == n) {
2218         return NULL;
2219     }
2220     pmix_envar_t *e = (pmix_envar_t *)pmix_tma_malloc(tma, n * sizeof(pmix_envar_t));
2221     if (PMIX_LIKELY(NULL != e)) {
2222         for (size_t m = 0; m < n; m++) {
2223             pmix_bfrops_base_tma_envar_construct(&e[m], tma);
2224         }
2225     }
2226     return e;
2227 }
2228 
2229 static inline
2230 void pmix_bfrops_base_tma_envar_free(pmix_envar_t *e,
2231                                      size_t n,
2232                                      pmix_tma_t *tma)
2233 {
2234     if (NULL != e) {
2235         for (size_t m = 0; m < n; m++) {
2236             pmix_bfrops_base_tma_envar_destruct(&e[m], tma);
2237         }
2238         pmix_tma_free(tma, e);
2239     }
2240 }
2241 
2242 static inline
2243 void pmix_bfrops_base_tma_envar_load(pmix_envar_t *e,
2244                                      char *var,
2245                                      char *value,
2246                                      char separator,
2247                                      pmix_tma_t *tma)
2248 {
2249     if (NULL != var) {
2250         e->envar = pmix_tma_strdup(tma, var);
2251     }
2252     if (NULL != value) {
2253         e->value = pmix_tma_strdup(tma, value);
2254     }
2255     e->separator = separator;
2256 }
2257 
2258 static inline
2259 void pmix_bfrops_base_tma_proc_stats_construct(pmix_proc_stats_t *p,
2260                                                pmix_tma_t *tma)
2261 {
2262     PMIX_HIDE_UNUSED_PARAMS(tma);
2263 
2264     memset(p, 0, sizeof(pmix_proc_stats_t));
2265 }
2266 
2267 static inline
2268 void pmix_bfrops_base_tma_proc_stats_destruct(pmix_proc_stats_t *p,
2269                                               pmix_tma_t *tma)
2270 {
2271     if (NULL != p->node) {
2272         pmix_tma_free(tma, p->node);
2273         p->node = NULL;
2274     }
2275     if (NULL != p->cmd) {
2276         pmix_tma_free(tma, p->cmd);
2277         p->cmd = NULL;
2278     }
2279 }
2280 
2281 static inline
2282 pmix_proc_stats_t* pmix_bfrops_base_tma_proc_stats_create(size_t n,
2283                                                           pmix_tma_t *tma)
2284 {
2285     if (0 == n) {
2286         return NULL;
2287     }
2288     pmix_proc_stats_t *p = (pmix_proc_stats_t*)pmix_tma_malloc(tma, n * sizeof(pmix_proc_stats_t));
2289     if (PMIX_LIKELY(NULL != p)) {
2290         for (size_t m = 0; m < n; m++) {
2291             pmix_bfrops_base_tma_proc_stats_construct(&p[m], tma);
2292         }
2293     }
2294     return p;
2295 }
2296 
2297 static inline
2298 void pmix_bfrops_base_tma_proc_stats_free(pmix_proc_stats_t *p,
2299                                           size_t n,
2300                                           pmix_tma_t *tma)
2301 {
2302     if (NULL != p) {
2303         for (size_t m = 0; m < n; m++) {
2304             pmix_bfrops_base_tma_proc_stats_destruct(&p[m], tma);
2305         }
2306         pmix_tma_free(tma, p);
2307     }
2308 }
2309 
2310 static inline
2311 void pmix_bfrops_base_tma_populate_pstats(pmix_proc_stats_t *p,
2312                                           pmix_proc_stats_t *src,
2313                                           pmix_tma_t *tma)
2314 {
2315     /* copy the individual fields */
2316     if (NULL != src->node) {
2317         p->node = pmix_tma_strdup(tma, src->node);
2318     }
2319     memcpy(&p->proc, &src->proc, sizeof(pmix_proc_t));
2320     p->pid = src->pid;
2321     if (NULL != src->cmd) {
2322         p->cmd = pmix_tma_strdup(tma, src->cmd);
2323     }
2324     p->state = src->state;
2325     p->time = src->time;
2326     p->priority = src->priority;
2327     p->num_threads = src->num_threads;
2328     p->pss = src->pss;
2329     p->vsize = src->vsize;
2330     p->rss = src->rss;
2331     p->peak_vsize = src->peak_vsize;
2332     p->processor = src->processor;
2333     p->sample_time.tv_sec = src->sample_time.tv_sec;
2334     p->sample_time.tv_usec = src->sample_time.tv_usec;
2335 }
2336 
2337 static inline
2338 pmix_status_t pmix_bfrops_base_tma_copy_pstats(pmix_proc_stats_t **dest,
2339                                                pmix_proc_stats_t *src,
2340                                                pmix_data_type_t type,
2341                                                pmix_tma_t *tma)
2342 {
2343     PMIX_HIDE_UNUSED_PARAMS(type);
2344     /* create the new object */
2345     pmix_proc_stats_t *p = pmix_bfrops_base_tma_proc_stats_create(1, tma);
2346     if (PMIX_UNLIKELY(NULL == p)) {
2347         return PMIX_ERR_NOMEM;
2348     }
2349     *dest = p;
2350     pmix_bfrops_base_tma_populate_pstats(p, src, tma);
2351     return PMIX_SUCCESS;
2352 }
2353 
2354 static inline
2355 void pmix_bfrops_base_tma_disk_stats_construct(pmix_disk_stats_t *p,
2356                                                pmix_tma_t *tma)
2357 {
2358     PMIX_HIDE_UNUSED_PARAMS(tma);
2359 
2360     memset(p, 0, sizeof(pmix_disk_stats_t));
2361 }
2362 
2363 static inline
2364 void pmix_bfrops_base_tma_disk_stats_destruct(pmix_disk_stats_t *p,
2365                                               pmix_tma_t *tma)
2366 {
2367     if (NULL != p->disk) {
2368         pmix_tma_free(tma, p->disk);
2369         p->disk = NULL;
2370     }
2371 }
2372 
2373 static inline
2374 pmix_disk_stats_t* pmix_bfrops_base_tma_disk_stats_create(size_t n,
2375                                                           pmix_tma_t *tma)
2376 {
2377     if (0 == n) {
2378         return NULL;
2379     }
2380     pmix_disk_stats_t *p = (pmix_disk_stats_t *)pmix_tma_malloc(tma, n * sizeof(pmix_disk_stats_t));
2381     if (PMIX_LIKELY(NULL != p)) {
2382         for (size_t m = 0; m < n; m++) {
2383             pmix_bfrops_base_tma_disk_stats_construct(&p[m], tma);
2384         }
2385     }
2386     return p;
2387 }
2388 
2389 static inline
2390 void pmix_bfrops_base_tma_disk_stats_free(pmix_disk_stats_t *p,
2391                                           size_t n,
2392                                           pmix_tma_t *tma)
2393 {
2394     if (NULL != p) {
2395         for (size_t m = 0; m < n; m++) {
2396             pmix_bfrops_base_tma_disk_stats_destruct(&p[m], tma);
2397         }
2398         pmix_tma_free(tma, p);
2399     }
2400 }
2401 
2402 static inline
2403 void pmix_bfrops_base_tma_populate_dkstats(pmix_disk_stats_t *p,
2404                                            pmix_disk_stats_t *src,
2405                                            pmix_tma_t *tma)
2406 {
2407     if (NULL != src->disk) {
2408         p->disk = pmix_tma_strdup(tma, src->disk);
2409     }
2410     p->num_reads_completed = src->num_reads_completed;
2411     p->num_reads_merged = src->num_reads_merged;
2412     p->num_sectors_read = src->num_sectors_read;
2413     p->milliseconds_reading = src->milliseconds_reading;
2414     p->num_writes_completed = src->num_writes_completed;
2415     p->num_writes_merged = src->num_writes_merged;
2416     p->num_sectors_written = src->num_sectors_written;
2417     p->milliseconds_writing = src->milliseconds_writing;
2418     p->num_ios_in_progress = src->num_ios_in_progress;
2419     p->milliseconds_io = src->milliseconds_io;
2420     p->weighted_milliseconds_io = src->weighted_milliseconds_io;
2421 }
2422 
2423 static inline
2424 pmix_status_t pmix_bfrops_base_tma_copy_dkstats(pmix_disk_stats_t **dest,
2425                                                 pmix_disk_stats_t *src,
2426                                                 pmix_data_type_t type,
2427                                                 pmix_tma_t *tma)
2428 {
2429     PMIX_HIDE_UNUSED_PARAMS(type);
2430     /* create the new object */
2431     pmix_disk_stats_t *p = pmix_bfrops_base_tma_disk_stats_create(1, tma);
2432     if (PMIX_UNLIKELY(NULL == p)) {
2433         return PMIX_ERR_NOMEM;
2434     }
2435     *dest = p;
2436     pmix_bfrops_base_tma_populate_dkstats(p, src, tma);
2437     return PMIX_SUCCESS;
2438 }
2439 
2440 static inline
2441 void pmix_bfrops_base_tma_net_stats_construct(pmix_net_stats_t *p,
2442                                               pmix_tma_t *tma)
2443 {
2444     PMIX_HIDE_UNUSED_PARAMS(tma);
2445 
2446     memset(p, 0, sizeof(pmix_net_stats_t));
2447 }
2448 
2449 static inline
2450 void pmix_bfrops_base_tma_net_stats_destruct(pmix_net_stats_t *p,
2451                                              pmix_tma_t *tma)
2452 {
2453     if (NULL != p->net_interface) {
2454         pmix_tma_free(tma, p->net_interface);
2455         p->net_interface = NULL;
2456     }
2457 }
2458 
2459 static inline
2460 void pmix_bfrops_base_tma_net_stats_free(pmix_net_stats_t *p,
2461                                          size_t n,
2462                                          pmix_tma_t *tma)
2463 {
2464     if (NULL != p) {
2465         for (size_t m = 0; m < n; m++) {
2466             pmix_bfrops_base_tma_net_stats_destruct(&p[m], tma);
2467         }
2468         pmix_tma_free(tma, p);
2469     }
2470 }
2471 
2472 static inline
2473 pmix_net_stats_t* pmix_bfrops_base_tma_net_stats_create(size_t n,
2474                                                         pmix_tma_t *tma)
2475 {
2476     if (0 == n) {
2477         return NULL;
2478     }
2479     pmix_net_stats_t *p = (pmix_net_stats_t*)pmix_tma_malloc(tma, n * sizeof(pmix_net_stats_t));
2480     if (PMIX_LIKELY(NULL != p)) {
2481         for (size_t m = 0; m < n; m++) {
2482             pmix_bfrops_base_tma_net_stats_construct(&p[m], tma);
2483         }
2484     }
2485     return p;
2486 }
2487 
2488 static inline
2489 void pmix_bfrops_base_tma_populate_netstats(pmix_net_stats_t *p,
2490                                             pmix_net_stats_t *src,
2491                                             pmix_tma_t *tma)
2492 {
2493     if (NULL != src->net_interface) {
2494         p->net_interface = pmix_tma_strdup(tma, src->net_interface);
2495     }
2496     p->num_bytes_recvd = src->num_bytes_recvd;
2497     p->num_packets_recvd = src->num_packets_recvd;
2498     p->num_recv_errs = src->num_recv_errs;
2499     p->num_bytes_sent = src->num_bytes_sent;
2500     p->num_packets_sent = src->num_packets_sent;
2501     p->num_send_errs = src->num_send_errs;
2502 }
2503 
2504 static inline
2505 pmix_status_t pmix_bfrops_base_tma_copy_netstats(pmix_net_stats_t **dest,
2506                                                  pmix_net_stats_t *src,
2507                                                  pmix_data_type_t type,
2508                                                  pmix_tma_t *tma)
2509 {
2510     PMIX_HIDE_UNUSED_PARAMS(type);
2511     /* create the new object */
2512     pmix_net_stats_t *p = pmix_bfrops_base_tma_net_stats_create(1, tma);
2513     if (PMIX_UNLIKELY(NULL == p)) {
2514         return PMIX_ERR_NOMEM;
2515     }
2516     *dest = p;
2517     pmix_bfrops_base_tma_populate_netstats(p, src, tma);
2518     return PMIX_SUCCESS;
2519 }
2520 
2521 static inline
2522 void pmix_bfrops_base_tma_node_stats_construct(pmix_node_stats_t *p,
2523                                                pmix_tma_t *tma)
2524 {
2525     PMIX_HIDE_UNUSED_PARAMS(tma);
2526 
2527     memset(p, 0, sizeof(pmix_node_stats_t));
2528 }
2529 
2530 static inline
2531 void pmix_bfrops_base_tma_node_stats_destruct(pmix_node_stats_t *p,
2532                                               pmix_tma_t *tma)
2533 {
2534     if (NULL != p->node) {
2535         pmix_tma_free(tma, p->node);
2536         p->node = NULL;
2537     }
2538     if (NULL != p->diskstats) {
2539         pmix_bfrops_base_tma_disk_stats_free(p->diskstats, p->ndiskstats, tma);
2540         p->diskstats = NULL;
2541         p->ndiskstats = 0;
2542     }
2543     if (NULL != p->netstats) {
2544         pmix_bfrops_base_tma_net_stats_free(p->netstats, p->nnetstats, tma);
2545         p->netstats = NULL;
2546         p->nnetstats = 0;
2547     }
2548 }
2549 
2550 static inline
2551 pmix_node_stats_t* pmix_bfrops_base_tma_node_stats_create(size_t n,
2552                                                           pmix_tma_t *tma)
2553 {
2554     if (0 == n) {
2555         return NULL;
2556     }
2557     pmix_node_stats_t *p = (pmix_node_stats_t *)pmix_tma_malloc(tma, n * sizeof(pmix_node_stats_t));
2558     if (PMIX_LIKELY(NULL != p)) {
2559         for (size_t m = 0; m < n; m++) {
2560             pmix_bfrops_base_tma_node_stats_construct(&p[m], tma);
2561         }
2562     }
2563     return p;
2564 }
2565 
2566 static inline
2567 void pmix_bfrops_base_tma_node_stats_free(pmix_node_stats_t *p,
2568                                           size_t n,
2569                                           pmix_tma_t *tma)
2570 {
2571     if (NULL != p) {
2572         for (size_t m = 0; m < n; m++) {
2573             pmix_bfrops_base_tma_node_stats_destruct(&p[m], tma);
2574         }
2575         pmix_tma_free(tma, p);
2576     }
2577 }
2578 
2579 static inline
2580 void pmix_bfrops_base_tma_populate_ndstats(pmix_node_stats_t *p,
2581                                            pmix_node_stats_t *src,
2582                                            pmix_tma_t *tma)
2583 {
2584     /* copy the individual fields */
2585     if (NULL != src->node) {
2586         p->node = pmix_tma_strdup(tma, src->node);
2587     }
2588     p->la = src->la;
2589     p->la5 = src->la5;
2590     p->la15 = src->la15;
2591     p->total_mem = src->total_mem;
2592     p->free_mem = src->free_mem;
2593     p->buffers = src->buffers;
2594     p->cached = src->cached;
2595     p->swap_cached = src->swap_cached;
2596     p->swap_total = src->swap_total;
2597     p->swap_free = src->swap_free;
2598     p->mapped = src->mapped;
2599     p->sample_time.tv_sec = src->sample_time.tv_sec;
2600     p->sample_time.tv_usec = src->sample_time.tv_usec;
2601     p->ndiskstats = src->ndiskstats;
2602     if (0 < p->ndiskstats) {
2603         p->diskstats = pmix_bfrops_base_tma_disk_stats_create(p->ndiskstats, tma);
2604         for (size_t n = 0; n < p->ndiskstats; n++) {
2605             pmix_bfrops_base_tma_populate_dkstats(
2606                 &p->diskstats[n], &src->diskstats[n], tma
2607             );
2608         }
2609     }
2610     p->nnetstats = src->nnetstats;
2611     if (0 < p->nnetstats) {
2612         p->netstats = pmix_bfrops_base_tma_net_stats_create(p->nnetstats, tma);
2613         for (size_t n = 0; n < p->nnetstats; n++) {
2614             pmix_bfrops_base_tma_populate_netstats(
2615                 &p->netstats[n], &src->netstats[n], tma
2616             );
2617         }
2618     }
2619 }
2620 
2621 static inline
2622 pmix_status_t pmix_bfrops_base_tma_copy_ndstats(pmix_node_stats_t **dest,
2623                                                 pmix_node_stats_t *src,
2624                                                 pmix_data_type_t type,
2625                                                 pmix_tma_t *tma)
2626 {
2627     PMIX_HIDE_UNUSED_PARAMS(type);
2628     /* create the new object */
2629     pmix_node_stats_t *p = pmix_bfrops_base_tma_node_stats_create(1, tma);
2630     if (PMIX_UNLIKELY(NULL == p)) {
2631         return PMIX_ERR_NOMEM;
2632     }
2633     *dest = p;
2634     pmix_bfrops_base_tma_populate_ndstats(p, src, tma);
2635     return PMIX_SUCCESS;
2636 }
2637 
2638 static inline
2639 pmix_value_cmp_t pmix_bfrops_base_tma_value_compare(pmix_value_t *v1,
2640                                                     pmix_value_t *v2,
2641                                                     pmix_tma_t *tma)
2642 {
2643     PMIX_HIDE_UNUSED_PARAMS(tma);
2644     // Note: No need for TMA here because no heap management, just comparisons.
2645     return pmix_bfrops_base_value_cmp(v1, v2);
2646 }
2647 
2648 /*
2649  * The pmix_data_array_t is a little different in that it is an array of values,
2650  * and so we cannot just copy one value at a time. So handle all value types
2651  * here.
2652  */
2653 static inline
2654 pmix_status_t pmix_bfrops_base_tma_copy_darray(pmix_data_array_t **dest,
2655                                                pmix_data_array_t *src,
2656                                                pmix_data_type_t type,
2657                                                pmix_tma_t *tma)
2658 {
2659     PMIX_HIDE_UNUSED_PARAMS(type);
2660 
2661     pmix_status_t rc = PMIX_SUCCESS;
2662     *dest = NULL;
2663 
2664     pmix_data_array_t *p = (pmix_data_array_t *)pmix_tma_calloc(tma, 1, sizeof(pmix_data_array_t));
2665     if (PMIX_UNLIKELY(NULL == p)) {
2666         return PMIX_ERR_NOMEM;
2667     }
2668 
2669     p->type = src->type;
2670     p->size = src->size;
2671     if (0 == p->size || NULL == src->array) {
2672         *dest = p;
2673         return PMIX_SUCCESS;
2674     }
2675 
2676     /* process based on type of array element */
2677     switch (src->type) {
2678     case PMIX_UINT8:
2679     case PMIX_INT8:
2680     case PMIX_BYTE:
2681         p->array = pmix_tma_malloc(tma, src->size);
2682         if (PMIX_UNLIKELY(NULL == p->array)) {
2683             rc = PMIX_ERR_NOMEM;
2684             break;
2685         }
2686         memcpy(p->array, src->array, src->size);
2687         break;
2688     case PMIX_UINT16:
2689     case PMIX_INT16:
2690         p->array = pmix_tma_malloc(tma, src->size * sizeof(uint16_t));
2691         if (PMIX_UNLIKELY(NULL == p->array)) {
2692             rc = PMIX_ERR_NOMEM;
2693             break;
2694         }
2695         memcpy(p->array, src->array, src->size * sizeof(uint16_t));
2696         break;
2697     case PMIX_UINT32:
2698     case PMIX_INT32:
2699         p->array = pmix_tma_malloc(tma, src->size * sizeof(uint32_t));
2700         if (PMIX_UNLIKELY(NULL == p->array)) {
2701             rc = PMIX_ERR_NOMEM;
2702             break;
2703         }
2704         memcpy(p->array, src->array, src->size * sizeof(uint32_t));
2705         break;
2706     case PMIX_UINT64:
2707     case PMIX_INT64:
2708         p->array = pmix_tma_malloc(tma, src->size * sizeof(uint64_t));
2709         if (PMIX_UNLIKELY(NULL == p->array)) {
2710             rc = PMIX_ERR_NOMEM;
2711             break;
2712         }
2713         memcpy(p->array, src->array, src->size * sizeof(uint64_t));
2714         break;
2715     case PMIX_BOOL:
2716         p->array = pmix_tma_malloc(tma, src->size * sizeof(bool));
2717         if (PMIX_UNLIKELY(NULL == p->array)) {
2718             rc = PMIX_ERR_NOMEM;
2719             break;
2720         }
2721         memcpy(p->array, src->array, src->size * sizeof(bool));
2722         break;
2723     case PMIX_SIZE:
2724         p->array = (char *)pmix_tma_malloc(tma, src->size * sizeof(size_t));
2725         if (PMIX_UNLIKELY(NULL == p->array)) {
2726             rc = PMIX_ERR_NOMEM;
2727             break;
2728         }
2729         memcpy(p->array, src->array, src->size * sizeof(size_t));
2730         break;
2731     case PMIX_PID:
2732         p->array = pmix_tma_malloc(tma, src->size * sizeof(pid_t));
2733         if (PMIX_UNLIKELY(NULL == p->array)) {
2734             rc = PMIX_ERR_NOMEM;
2735             break;
2736         }
2737         memcpy(p->array, src->array, src->size * sizeof(pid_t));
2738         break;
2739     case PMIX_STRING: {
2740         p->array = pmix_tma_malloc(tma, src->size * sizeof(char *));
2741         if (PMIX_UNLIKELY(NULL == p->array)) {
2742             rc = PMIX_ERR_NOMEM;
2743             break;
2744         }
2745         char **prarray = (char **)p->array;
2746         char **strarray = (char **)src->array;
2747         for (size_t n = 0; n < src->size; n++) {
2748             if (NULL != strarray[n]) {
2749                 prarray[n] = pmix_tma_strdup(tma, strarray[n]);
2750             }
2751         }
2752         break;
2753     }
2754     case PMIX_INT:
2755     case PMIX_UINT:
2756         p->array = pmix_tma_malloc(tma, src->size * sizeof(int));
2757         if (PMIX_UNLIKELY(NULL == p->array)) {
2758             rc = PMIX_ERR_NOMEM;
2759             break;
2760         }
2761         memcpy(p->array, src->array, src->size * sizeof(int));
2762         break;
2763     case PMIX_FLOAT:
2764         p->array = pmix_tma_malloc(tma, src->size * sizeof(float));
2765         if (PMIX_UNLIKELY(NULL == p->array)) {
2766             rc = PMIX_ERR_NOMEM;
2767             break;
2768         }
2769         memcpy(p->array, src->array, src->size * sizeof(float));
2770         break;
2771     case PMIX_DOUBLE:
2772         p->array = pmix_tma_malloc(tma, src->size * sizeof(double));
2773         if (PMIX_UNLIKELY(NULL == p->array)) {
2774             rc = PMIX_ERR_NOMEM;
2775             break;
2776         }
2777         memcpy(p->array, src->array, src->size * sizeof(double));
2778         break;
2779     case PMIX_TIMEVAL:
2780         p->array = pmix_tma_malloc(tma, src->size * sizeof(struct timeval));
2781         if (PMIX_UNLIKELY(NULL == p->array)) {
2782             rc = PMIX_ERR_NOMEM;
2783             break;
2784         }
2785         memcpy(p->array, src->array, src->size * sizeof(struct timeval));
2786         break;
2787     case PMIX_TIME:
2788         p->array = pmix_tma_malloc(tma, src->size * sizeof(time_t));
2789         if (PMIX_UNLIKELY(NULL == p->array)) {
2790             rc = PMIX_ERR_NOMEM;
2791             break;
2792         }
2793         memcpy(p->array, src->array, src->size * sizeof(time_t));
2794         break;
2795     case PMIX_STATUS:
2796         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_status_t));
2797         if (PMIX_UNLIKELY(NULL == p->array)) {
2798             rc = PMIX_ERR_NOMEM;
2799             break;
2800         }
2801         memcpy(p->array, src->array, src->size * sizeof(pmix_status_t));
2802         break;
2803     case PMIX_VALUE: {
2804         p->array = pmix_bfrops_base_tma_value_create(src->size, tma);
2805         if (PMIX_UNLIKELY(NULL == p->array)) {
2806             rc = PMIX_ERR_NOMEM;
2807             break;
2808         }
2809         pmix_value_t *const pv = (pmix_value_t *)p->array;
2810         pmix_value_t *const sv = (pmix_value_t *)src->array;
2811         for (size_t n = 0; n < src->size; n++) {
2812             if (PMIX_SUCCESS != (rc = pmix_bfrops_base_value_xfer(&pv[n], &sv[n]))) {
2813                 pmix_bfrops_base_tma_value_free(pv, src->size, tma);
2814                 break;
2815             }
2816         }
2817         break;
2818     }
2819     case PMIX_PROC:
2820         p->array = pmix_bfrops_base_tma_proc_create(src->size, tma);
2821         if (PMIX_UNLIKELY(NULL == p->array)) {
2822             rc = PMIX_ERR_NOMEM;
2823             break;
2824         }
2825         memcpy(p->array, src->array, src->size * sizeof(pmix_proc_t));
2826         break;
2827     case PMIX_PROC_RANK:
2828         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_rank_t));
2829         if (PMIX_UNLIKELY(NULL == p->array)) {
2830             rc = PMIX_ERR_NOMEM;
2831             break;
2832         }
2833         memcpy(p->array, src->array, src->size * sizeof(pmix_rank_t));
2834         break;
2835     case PMIX_APP: {
2836         p->array = pmix_bfrops_base_tma_app_create(src->size, tma);
2837         if (PMIX_UNLIKELY(NULL == p->array)) {
2838             rc = PMIX_ERR_NOMEM;
2839             break;
2840         }
2841         pmix_app_t *const pa = (pmix_app_t *)p->array;
2842         pmix_app_t *const sa = (pmix_app_t *)src->array;
2843         for (size_t n = 0; n < src->size; n++) {
2844             if (NULL != sa[n].cmd) {
2845                 pa[n].cmd = pmix_tma_strdup(tma, sa[n].cmd);
2846             }
2847             if (NULL != sa[n].argv) {
2848                 pa[n].argv = pmix_bfrops_base_tma_argv_copy(sa[n].argv, tma);
2849             }
2850             if (NULL != sa[n].env) {
2851                 pa[n].env = pmix_bfrops_base_tma_argv_copy(sa[n].env, tma);
2852             }
2853             if (NULL != sa[n].cwd) {
2854                 pa[n].cwd = pmix_tma_strdup(tma, sa[n].cwd);
2855             }
2856             pa[n].maxprocs = sa[n].maxprocs;
2857             if (0 < sa[n].ninfo && NULL != sa[n].info) {
2858                 pa[n].info = pmix_bfrops_base_tma_info_create(sa[n].ninfo, tma);
2859                 if (PMIX_UNLIKELY(NULL == pa[n].info)) {
2860                     pmix_bfrops_base_tma_app_free(pa, p->size, tma);
2861                     rc = PMIX_ERR_NOMEM;
2862                     break;
2863                 }
2864                 pa[n].ninfo = sa[n].ninfo;
2865                 for (size_t m = 0; m < pa[n].ninfo; m++) {
2866                     pmix_bfrops_base_tma_info_xfer(
2867                         &pa[n].info[m], &sa[n].info[m], tma
2868                     );
2869                 }
2870             }
2871         }
2872         break;
2873     }
2874     case PMIX_INFO: {
2875         p->array = pmix_bfrops_base_tma_info_create(src->size, tma);
2876         if (PMIX_UNLIKELY(NULL == p->array)) {
2877             rc = PMIX_ERR_NOMEM;
2878             break;
2879         }
2880         pmix_info_t *const p1 = (pmix_info_t *)p->array;
2881         pmix_info_t *const s1 = (pmix_info_t *)src->array;
2882         for (size_t n = 0; n < src->size; n++) {
2883             pmix_bfrops_base_tma_info_xfer(&p1[n], &s1[n], tma);
2884         }
2885         break;
2886     }
2887     case PMIX_PDATA: {
2888         p->array = pmix_bfrops_base_tma_pdata_create(src->size, tma);
2889         if (PMIX_UNLIKELY(NULL == p->array)) {
2890             rc = PMIX_ERR_NOMEM;
2891             break;
2892         }
2893         pmix_pdata_t *const pd = (pmix_pdata_t *)p->array;
2894         pmix_pdata_t *const sd = (pmix_pdata_t *)src->array;
2895         for (size_t n = 0; n < src->size; n++) {
2896             pmix_bfrops_base_tma_pdata_xfer(&pd[n], &sd[n], tma);
2897         }
2898         break;
2899     }
2900     case PMIX_BUFFER: {
2901         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_buffer_t));
2902         if (PMIX_UNLIKELY(NULL == p->array)) {
2903             rc = PMIX_ERR_NOMEM;
2904             break;
2905         }
2906         pmix_buffer_t *const pb = (pmix_buffer_t *)p->array;
2907         pmix_buffer_t *const sb = (pmix_buffer_t *)src->array;
2908         for (size_t n = 0; n < src->size; n++) {
2909             PMIX_CONSTRUCT(&pb[n], pmix_buffer_t, tma);
2910             pmix_bfrops_base_tma_copy_payload(&pb[n], &sb[n], tma);
2911         }
2912         break;
2913     }
2914     case PMIX_BYTE_OBJECT:
2915     case PMIX_COMPRESSED_STRING: {
2916         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_byte_object_t));
2917         if (PMIX_UNLIKELY(NULL == p->array)) {
2918             rc = PMIX_ERR_NOMEM;
2919             break;
2920         }
2921         pmix_byte_object_t *const pbo = (pmix_byte_object_t *)p->array;
2922         pmix_byte_object_t *const sbo = (pmix_byte_object_t *)src->array;
2923         for (size_t n = 0; n < src->size; n++) {
2924             if (NULL != sbo[n].bytes && 0 < sbo[n].size) {
2925                 pbo[n].size = sbo[n].size;
2926                 pbo[n].bytes = (char *)pmix_tma_malloc(tma, pbo[n].size);
2927                 memcpy(pbo[n].bytes, sbo[n].bytes, pbo[n].size);
2928             } else {
2929                 pbo[n].bytes = NULL;
2930                 pbo[n].size = 0;
2931             }
2932         }
2933         break;
2934     }
2935     case PMIX_KVAL: {
2936         p->array = pmix_tma_calloc(tma, src->size, sizeof(pmix_kval_t));
2937         if (PMIX_UNLIKELY(NULL == p->array)) {
2938             rc = PMIX_ERR_NOMEM;
2939             break;
2940         }
2941         pmix_kval_t *const pk = (pmix_kval_t *)p->array;
2942         pmix_kval_t *const sk = (pmix_kval_t *)src->array;
2943         for (size_t n = 0; n < src->size; n++) {
2944             if (NULL != sk[n].key) {
2945                 pk[n].key = pmix_tma_strdup(tma, sk[n].key);
2946             }
2947             if (NULL != sk[n].value) {
2948                 pk[n].value = pmix_bfrops_base_tma_value_create(1, tma);
2949                 if (PMIX_UNLIKELY(NULL == pk[n].value)) {
2950                     rc = PMIX_ERR_NOMEM;
2951                     break;
2952                 }
2953                 rc = pmix_bfrops_base_tma_value_xfer(pk[n].value, sk[n].value, tma);
2954                 if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
2955                     pmix_bfrops_base_tma_value_free(pk[n].value, 1, tma);
2956                     rc = PMIX_ERR_NOMEM;
2957                     break;
2958                 }
2959             }
2960         }
2961         break;
2962     }
2963     case PMIX_PERSIST:
2964         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_persistence_t));
2965         if (PMIX_UNLIKELY(NULL == p->array)) {
2966             rc = PMIX_ERR_NOMEM;
2967             break;
2968         }
2969         memcpy(p->array, src->array, src->size * sizeof(pmix_persistence_t));
2970         break;
2971     case PMIX_POINTER: {
2972         p->array = pmix_tma_malloc(tma, src->size * sizeof(char *));
2973         char **prarray = (char **)p->array;
2974         char **strarray = (char **)src->array;
2975         for (size_t n = 0; n < src->size; n++) {
2976             prarray[n] = strarray[n];
2977         }
2978         break;
2979     }
2980     case PMIX_SCOPE:
2981         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_scope_t));
2982         if (PMIX_UNLIKELY(NULL == p->array)) {
2983             rc = PMIX_ERR_NOMEM;
2984             break;
2985         }
2986         memcpy(p->array, src->array, src->size * sizeof(pmix_scope_t));
2987         break;
2988     case PMIX_DATA_RANGE:
2989         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_data_range_t));
2990         if (PMIX_UNLIKELY(NULL == p->array)) {
2991             rc = PMIX_ERR_NOMEM;
2992             break;
2993         }
2994         memcpy(p->array, src->array, src->size * sizeof(pmix_data_range_t));
2995         break;
2996     case PMIX_COMMAND:
2997         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_cmd_t));
2998         if (PMIX_UNLIKELY(NULL == p->array)) {
2999             rc = PMIX_ERR_NOMEM;
3000             break;
3001         }
3002         memcpy(p->array, src->array, src->size * sizeof(pmix_cmd_t));
3003         break;
3004     case PMIX_INFO_DIRECTIVES:
3005         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_info_directives_t));
3006         if (PMIX_UNLIKELY(NULL == p->array)) {
3007             rc = PMIX_ERR_NOMEM;
3008             break;
3009         }
3010         memcpy(p->array, src->array, src->size * sizeof(pmix_info_directives_t));
3011         break;
3012     case PMIX_PROC_INFO: {
3013         p->array = pmix_bfrops_base_tma_proc_info_create( src->size, tma);
3014         if (PMIX_UNLIKELY(NULL == p->array)) {
3015             rc = PMIX_ERR_NOMEM;
3016             break;
3017         }
3018         pmix_proc_info_t *const pi = (pmix_proc_info_t *)p->array;
3019         pmix_proc_info_t *const si = (pmix_proc_info_t *)src->array;
3020         for (size_t n = 0; n < src->size; n++) {
3021             memcpy(&pi[n].proc, &si[n].proc, sizeof(pmix_proc_t));
3022             if (NULL != si[n].hostname) {
3023                 pi[n].hostname = pmix_tma_strdup(tma, si[n].hostname);
3024             } else {
3025                 pi[n].hostname = NULL;
3026             }
3027             if (NULL != si[n].executable_name) {
3028                 pi[n].executable_name = pmix_tma_strdup(tma, si[n].executable_name);
3029             } else {
3030                 pi[n].executable_name = NULL;
3031             }
3032             pi[n].pid = si[n].pid;
3033             pi[n].exit_code = si[n].exit_code;
3034             pi[n].state = si[n].state;
3035         }
3036         break;
3037     }
3038     case PMIX_DATA_ARRAY:
3039         rc = PMIX_ERR_NOT_SUPPORTED; // don't support iterative arrays
3040         break;
3041     case PMIX_QUERY: {
3042         p->array = pmix_bfrops_base_tma_query_create(src->size, tma);
3043         if (PMIX_UNLIKELY(NULL == p->array)) {
3044             rc = PMIX_ERR_NOMEM;
3045             break;
3046         }
3047         pmix_query_t *const pq = (pmix_query_t *)p->array;
3048         pmix_query_t *const sq = (pmix_query_t *)src->array;
3049         for (size_t n = 0; n < src->size; n++) {
3050             if (NULL != sq[n].keys) {
3051                 pq[n].keys = pmix_bfrops_base_tma_argv_copy(sq[n].keys, tma);
3052             }
3053             if (NULL != sq[n].qualifiers && 0 < sq[n].nqual) {
3054                 pq[n].qualifiers = pmix_bfrops_base_tma_info_create(sq[n].nqual, tma);
3055                 if (NULL == pq[n].qualifiers) {
3056                     rc = PMIX_ERR_NOMEM;
3057                     break;
3058                 }
3059                 for (size_t m = 0; m < sq[n].nqual; m++) {
3060                     pmix_bfrops_base_tma_info_xfer(
3061                         &pq[n].qualifiers[m], &sq[n].qualifiers[m], tma
3062                     );
3063                 }
3064                 pq[n].nqual = sq[n].nqual;
3065             }
3066             else {
3067                 pq[n].qualifiers = NULL;
3068                 pq[n].nqual = 0;
3069             }
3070         }
3071         break;
3072     }
3073     case PMIX_ENVAR: {
3074         p->array = pmix_bfrops_base_tma_envar_create(src->size, tma);
3075         if (PMIX_UNLIKELY(NULL == p->array)) {
3076             rc = PMIX_ERR_NOMEM;
3077             break;
3078         }
3079         pmix_envar_t *const pe = (pmix_envar_t *)p->array;
3080         pmix_envar_t *const se = (pmix_envar_t *)src->array;
3081         for (size_t n = 0; n < src->size; n++) {
3082             if (NULL != se[n].envar) {
3083                 pe[n].envar = pmix_tma_strdup(tma, se[n].envar);
3084             }
3085             if (NULL != se[n].value) {
3086                 pe[n].value = pmix_tma_strdup(tma, se[n].value);
3087             }
3088             pe[n].separator = se[n].separator;
3089         }
3090         break;
3091     }
3092     case PMIX_COORD: {
3093         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_coord_t));
3094         if (PMIX_UNLIKELY(NULL == p->array)) {
3095             rc = PMIX_ERR_NOMEM;
3096             break;
3097         }
3098         pmix_coord_t *const pc = (pmix_coord_t *)p->array;
3099         pmix_coord_t *const sc = (pmix_coord_t *)src->array;
3100         for (size_t n = 0; n < src->size; n++) {
3101             rc = pmix_bfrops_base_tma_fill_coord(&pc[n], &sc[n], tma);
3102             if (PMIX_SUCCESS != rc) {
3103                 pmix_bfrops_base_tma_coord_free(pc, src->size, tma);
3104                 break;
3105             }
3106         }
3107         break;
3108     }
3109     case PMIX_REGATTR: {
3110         p->array = pmix_bfrops_base_tma_regattr_create(src->size, tma);
3111         if (PMIX_UNLIKELY(NULL == p->array)) {
3112             rc = PMIX_ERR_NOMEM;
3113             break;
3114         }
3115         pmix_regattr_t *const pr = (pmix_regattr_t *)p->array;
3116         pmix_regattr_t *const sr = (pmix_regattr_t *)src->array;
3117         for (size_t n = 0; n < src->size; n++) {
3118             if (NULL != sr[n].name) {
3119                 pr[n].name = pmix_tma_strdup(tma, sr[n].name);
3120             }
3121             pmix_bfrops_base_tma_load_key(pr[n].string, sr[n].string, tma);
3122             pr[n].type = sr[n].type;
3123             pr[n].description = pmix_bfrops_base_tma_argv_copy(sr[n].description, tma);
3124         }
3125         break;
3126     }
3127     case PMIX_PROC_CPUSET: {
3128         p->array = pmix_bfrops_base_tma_cpuset_create(src->size, tma);
3129         if (PMIX_UNLIKELY(NULL == p->array)) {
3130             rc = PMIX_ERR_NOMEM;
3131             break;
3132         }
3133         pmix_cpuset_t *const pcpuset = (pmix_cpuset_t *)p->array;
3134         pmix_cpuset_t *const scpuset = (pmix_cpuset_t *)src->array;
3135         for (size_t n = 0; n < src->size; n++) {
3136             // TODO(skg) Add TMA support when necessary.
3137             rc = pmix_hwloc_copy_cpuset(&pcpuset[n], &scpuset[n]);
3138             if (PMIX_SUCCESS != rc) {
3139                 // TODO(skg) Add TMA support when necessary.
3140                 pmix_hwloc_release_cpuset(pcpuset, src->size);
3141                 pmix_tma_free(tma, p->array);
3142                 break;
3143             }
3144         }
3145         break;
3146     }
3147     case PMIX_GEOMETRY: {
3148         p->array = pmix_bfrops_base_tma_geometry_create(src->size, tma);
3149         if (PMIX_UNLIKELY(NULL == p->array)) {
3150             rc = PMIX_ERR_NOMEM;
3151             break;
3152         }
3153         pmix_geometry_t *const pgeoset = (pmix_geometry_t *)p->array;
3154         pmix_geometry_t *const sgeoset = (pmix_geometry_t *)src->array;
3155         for (size_t n = 0; n < src->size; n++) {
3156             pgeoset[n].fabric = sgeoset[n].fabric;
3157             if (NULL != sgeoset[n].uuid) {
3158                 pgeoset[n].uuid = pmix_tma_strdup(tma, sgeoset[n].uuid);
3159             }
3160             if (NULL != sgeoset[n].osname) {
3161                 pgeoset[n].osname = pmix_tma_strdup(tma, sgeoset[n].osname);
3162             }
3163             if (NULL != sgeoset[n].coordinates) {
3164                 pgeoset[n].ncoords = sgeoset[n].ncoords;
3165                 pgeoset[n].coordinates = (pmix_coord_t *)pmix_tma_malloc(tma, pgeoset[n].ncoords * sizeof(pmix_coord_t));
3166                 if (PMIX_UNLIKELY(NULL == pgeoset[n].coordinates)) {
3167                     rc = PMIX_ERR_NOMEM;
3168                     break;
3169                 }
3170                 for (size_t m = 0; m < pgeoset[n].ncoords; m++) {
3171                     rc = pmix_bfrops_base_tma_fill_coord(
3172                         &pgeoset[n].coordinates[m], &sgeoset[n].coordinates[m], tma
3173                     );
3174                     if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
3175                         pmix_bfrops_base_tma_geometry_free(pgeoset, src->size, tma);
3176                         break;
3177                     }
3178                 }
3179             }
3180             if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
3181                 break;
3182             }
3183         }
3184         break;
3185     }
3186     case PMIX_DEVICE_DIST: {
3187         p->array = pmix_bfrops_base_tma_device_distance_create(src->size, tma);
3188         if (PMIX_UNLIKELY(NULL == p->array)) {
3189             rc = PMIX_ERR_NOMEM;
3190             break;
3191         }
3192         pmix_device_distance_t *const pdevdist = (pmix_device_distance_t *)p->array;
3193         pmix_device_distance_t *const sdevdist = (pmix_device_distance_t *)src->array;
3194         for (size_t n = 0; n < src->size; n++) {
3195             if (NULL != sdevdist[n].uuid) {
3196                 pdevdist[n].uuid = pmix_tma_strdup(tma, sdevdist[n].uuid);
3197             }
3198             if (NULL != sdevdist[n].osname) {
3199                 pdevdist[n].osname = pmix_tma_strdup(tma, sdevdist[n].osname);
3200             }
3201             pdevdist[n].type = sdevdist[n].type;
3202             pdevdist[n].mindist = sdevdist[n].mindist;
3203             pdevdist[n].maxdist = sdevdist[n].maxdist;
3204         }
3205         break;
3206     }
3207     case PMIX_ENDPOINT: {
3208         p->array = pmix_bfrops_base_tma_endpoint_create(src->size, tma);
3209         if (PMIX_UNLIKELY(NULL == p->array)) {
3210             rc = PMIX_ERR_NOMEM;
3211             break;
3212         }
3213         pmix_endpoint_t *const pendpt = (pmix_endpoint_t *)p->array;
3214         pmix_endpoint_t *const sendpt = (pmix_endpoint_t *)src->array;
3215         for (size_t n = 0; n < src->size; n++) {
3216             if (NULL != sendpt[n].uuid) {
3217                 pendpt[n].uuid = pmix_tma_strdup(tma, sendpt[n].uuid);
3218             }
3219             if (NULL != sendpt[n].osname) {
3220                 pendpt[n].osname = pmix_tma_strdup(tma, sendpt[n].osname);
3221             }
3222             if (NULL != sendpt[n].endpt.bytes) {
3223                 pendpt[n].endpt.bytes = (char *)pmix_tma_malloc(tma, sendpt[n].endpt.size);
3224                 memcpy(pendpt[n].endpt.bytes, sendpt[n].endpt.bytes, sendpt[n].endpt.size);
3225                 pendpt[n].endpt.size = sendpt[n].endpt.size;
3226             }
3227         }
3228         break;
3229     }
3230     case PMIX_PROC_NSPACE: {
3231         p->array = pmix_tma_malloc(tma, src->size * sizeof(pmix_nspace_t));
3232         if (PMIX_UNLIKELY(NULL == p->array)) {
3233             rc = PMIX_ERR_NOMEM;
3234             break;
3235         }
3236         p->size = src->size;
3237         pmix_nspace_t *const pns = (pmix_nspace_t *)p->array;
3238         pmix_nspace_t *const sns = (pmix_nspace_t *)src->array;
3239         for (size_t n = 0; n < src->size; n++) {
3240             pmix_bfrops_base_tma_load_nspace(pns[n], sns[n], tma);
3241         }
3242         break;
3243     }
3244     case PMIX_PROC_STATS: {
3245         p->array = pmix_bfrops_base_tma_proc_stats_create(src->size, tma);
3246         if (PMIX_UNLIKELY(NULL == p->array)) {
3247             rc = PMIX_ERR_NOMEM;
3248             break;
3249         }
3250         pmix_proc_stats_t *const pstats = (pmix_proc_stats_t *)p->array;
3251         pmix_proc_stats_t *const sstats = (pmix_proc_stats_t *)src->array;
3252         for (size_t n = 0; n < src->size; n++) {
3253             pmix_bfrops_base_tma_populate_pstats(&pstats[n], &sstats[n], tma);
3254         }
3255         break;
3256     }
3257     case PMIX_DISK_STATS: {
3258         p->array = pmix_bfrops_base_tma_disk_stats_create(src->size, tma);
3259         if (PMIX_UNLIKELY(NULL == p->array)) {
3260             rc = PMIX_ERR_NOMEM;
3261             break;
3262         }
3263         pmix_disk_stats_t *const dkdest = (pmix_disk_stats_t *)p->array;
3264         pmix_disk_stats_t *const dksrc = (pmix_disk_stats_t *)src->array;
3265         for (size_t n = 0; n < src->size; n++) {
3266             pmix_bfrops_base_tma_populate_dkstats(&dkdest[n], &dksrc[n], tma);
3267         }
3268         break;
3269     }
3270     case PMIX_NET_STATS: {
3271         p->array = pmix_bfrops_base_tma_net_stats_create(src->size, tma);
3272         if (PMIX_UNLIKELY(NULL == p->array)) {
3273             rc = PMIX_ERR_NOMEM;
3274             break;
3275         }
3276         pmix_net_stats_t *const ntdest = (pmix_net_stats_t *)p->array;
3277         pmix_net_stats_t *const ntsrc = (pmix_net_stats_t *)src->array;
3278         for (size_t n = 0; n < src->size; n++) {
3279             pmix_bfrops_base_tma_populate_netstats(&ntdest[n], &ntsrc[n], tma);
3280         }
3281         break;
3282     }
3283     case PMIX_NODE_STATS: {
3284         p->array = pmix_bfrops_base_tma_node_stats_create(src->size, tma);
3285         if (PMIX_UNLIKELY(NULL == p->array)) {
3286             rc = PMIX_ERR_NOMEM;
3287             break;
3288         }
3289         pmix_node_stats_t *const nddest = (pmix_node_stats_t *)p->array;
3290         pmix_node_stats_t *const ndsrc = (pmix_node_stats_t *)src->array;
3291         for (size_t n = 0; n < src->size; n++) {
3292             pmix_bfrops_base_tma_populate_ndstats(&nddest[n], &ndsrc[n], tma);
3293         }
3294         break;
3295     }
3296     default:
3297         rc = PMIX_ERR_UNKNOWN_DATA_TYPE;
3298     }
3299     if (PMIX_UNLIKELY(PMIX_SUCCESS != rc)) {
3300         PMIX_ERROR_LOG(rc);
3301         pmix_tma_free(tma, p);
3302         p = NULL;
3303     }
3304     *dest = p;
3305     return rc;
3306 }
3307 
3308 static inline
3309 pmix_status_t pmix_bfrops_base_tma_value_xfer(pmix_value_t *p,
3310                                               const pmix_value_t *src,
3311                                               pmix_tma_t *tma)
3312 {
3313     pmix_status_t rc;
3314 
3315     /* copy the right field */
3316     p->type = src->type;
3317     switch (src->type) {
3318     case PMIX_UNDEF:
3319         break;
3320     case PMIX_BOOL:
3321         p->data.flag = src->data.flag;
3322         break;
3323     case PMIX_BYTE:
3324         p->data.byte = src->data.byte;
3325         break;
3326     case PMIX_STRING:
3327         if (NULL != src->data.string) {
3328             p->data.string = pmix_tma_strdup(tma, src->data.string);
3329         } else {
3330             p->data.string = NULL;
3331         }
3332         break;
3333     case PMIX_SIZE:
3334         p->data.size = src->data.size;
3335         break;
3336     case PMIX_PID:
3337         p->data.pid = src->data.pid;
3338         break;
3339     case PMIX_INT:
3340         /* to avoid alignment issues */
3341         memcpy(&p->data.integer, &src->data.integer, sizeof(int));
3342         break;
3343     case PMIX_INT8:
3344         p->data.int8 = src->data.int8;
3345         break;
3346     case PMIX_INT16:
3347         /* to avoid alignment issues */
3348         memcpy(&p->data.int16, &src->data.int16, 2);
3349         break;
3350     case PMIX_INT32:
3351         /* to avoid alignment issues */
3352         memcpy(&p->data.int32, &src->data.int32, 4);
3353         break;
3354     case PMIX_INT64:
3355         /* to avoid alignment issues */
3356         memcpy(&p->data.int64, &src->data.int64, 8);
3357         break;
3358     case PMIX_UINT:
3359         /* to avoid alignment issues */
3360         memcpy(&p->data.uint, &src->data.uint, sizeof(unsigned int));
3361         break;
3362     case PMIX_UINT8:
3363         p->data.uint8 = src->data.uint8;
3364         break;
3365     case PMIX_UINT16:
3366     case PMIX_STOR_ACCESS_TYPE:
3367         /* to avoid alignment issues */
3368         memcpy(&p->data.uint16, &src->data.uint16, 2);
3369         break;
3370     case PMIX_UINT32:
3371         /* to avoid alignment issues */
3372         memcpy(&p->data.uint32, &src->data.uint32, 4);
3373         break;
3374     case PMIX_UINT64:
3375     case PMIX_STOR_MEDIUM:
3376     case PMIX_STOR_ACCESS:
3377     case PMIX_STOR_PERSIST:
3378        /* to avoid alignment issues */
3379         memcpy(&p->data.uint64, &src->data.uint64, 8);
3380         break;
3381     case PMIX_FLOAT:
3382         p->data.fval = src->data.fval;
3383         break;
3384     case PMIX_DOUBLE:
3385         p->data.dval = src->data.dval;
3386         break;
3387     case PMIX_TIMEVAL:
3388         memcpy(&p->data.tv, &src->data.tv, sizeof(struct timeval));
3389         break;
3390     case PMIX_TIME:
3391         memcpy(&p->data.time, &src->data.time, sizeof(time_t));
3392         break;
3393     case PMIX_STATUS:
3394         memcpy(&p->data.status, &src->data.status, sizeof(pmix_status_t));
3395         break;
3396     case PMIX_PROC_RANK:
3397         memcpy(&p->data.rank, &src->data.rank, sizeof(pmix_rank_t));
3398         break;
3399     case PMIX_PROC_NSPACE:
3400         return pmix_bfrops_base_tma_copy_nspace(&p->data.nspace, src->data.nspace, PMIX_PROC_NSPACE, tma);
3401     case PMIX_PROC:
3402         p->data.proc = pmix_bfrops_base_tma_proc_create(1, tma);
3403         if (PMIX_UNLIKELY(NULL == p->data.proc)) {
3404             return PMIX_ERR_NOMEM;
3405         }
3406         memcpy(p->data.proc, src->data.proc, sizeof(pmix_proc_t));
3407         break;
3408     case PMIX_BYTE_OBJECT:
3409     case PMIX_COMPRESSED_STRING:
3410     case PMIX_REGEX:
3411     case PMIX_COMPRESSED_BYTE_OBJECT:
3412         memset(&p->data.bo, 0, sizeof(pmix_byte_object_t));
3413         if (NULL != src->data.bo.bytes && 0 < src->data.bo.size) {
3414             p->data.bo.bytes = pmix_tma_malloc(tma, src->data.bo.size);
3415             memcpy(p->data.bo.bytes, src->data.bo.bytes, src->data.bo.size);
3416             p->data.bo.size = src->data.bo.size;
3417         } else {
3418             p->data.bo.bytes = NULL;
3419             p->data.bo.size = 0;
3420         }
3421         break;
3422     case PMIX_PERSIST:
3423         memcpy(&p->data.persist, &src->data.persist, sizeof(pmix_persistence_t));
3424         break;
3425     case PMIX_SCOPE:
3426         memcpy(&p->data.scope, &src->data.scope, sizeof(pmix_scope_t));
3427         break;
3428     case PMIX_DATA_RANGE:
3429         memcpy(&p->data.range, &src->data.range, sizeof(pmix_data_range_t));
3430         break;
3431     case PMIX_PROC_STATE:
3432         memcpy(&p->data.state, &src->data.state, sizeof(pmix_proc_state_t));
3433         break;
3434     case PMIX_PROC_INFO:
3435         return pmix_bfrops_base_tma_copy_pinfo(&p->data.pinfo, src->data.pinfo, PMIX_PROC_INFO, tma);
3436     case PMIX_DATA_ARRAY:
3437         return pmix_bfrops_base_tma_copy_darray(&p->data.darray, src->data.darray, PMIX_DATA_ARRAY, tma);
3438     case PMIX_POINTER:
3439         p->data.ptr = src->data.ptr;
3440         break;
3441     case PMIX_ALLOC_DIRECTIVE:
3442         memcpy(&p->data.adir, &src->data.adir, sizeof(pmix_alloc_directive_t));
3443         break;
3444     case PMIX_ENVAR:
3445         pmix_bfrops_base_tma_envar_construct(&p->data.envar, tma);
3446 
3447         if (NULL != src->data.envar.envar) {
3448             p->data.envar.envar = pmix_tma_strdup(tma, src->data.envar.envar);
3449         }
3450         if (NULL != src->data.envar.value) {
3451             p->data.envar.value = pmix_tma_strdup(tma, src->data.envar.value);
3452         }
3453         p->data.envar.separator = src->data.envar.separator;
3454         break;
3455     case PMIX_COORD:
3456         return pmix_bfrops_base_tma_copy_coord(&p->data.coord, src->data.coord, PMIX_COORD, tma);
3457     case PMIX_LINK_STATE:
3458         memcpy(&p->data.linkstate, &src->data.linkstate, sizeof(pmix_link_state_t));
3459         break;
3460     case PMIX_JOB_STATE:
3461         memcpy(&p->data.jstate, &src->data.jstate, sizeof(pmix_job_state_t));
3462         break;
3463     case PMIX_TOPO:
3464         rc = pmix_bfrops_base_tma_copy_topology(&p->data.topo, src->data.topo, PMIX_TOPO, tma);
3465         if (PMIX_ERR_INIT == rc || PMIX_ERR_NOT_SUPPORTED == rc) {
3466             /* we are being asked to do this before init, so
3467              * just copy the pointer across */
3468             p->data.topo = src->data.topo;
3469         }
3470         break;
3471     case PMIX_PROC_CPUSET:
3472         rc = pmix_bfrops_base_tma_copy_cpuset(&p->data.cpuset, src->data.cpuset, PMIX_PROC_CPUSET, tma);
3473         if (PMIX_ERR_INIT == rc || PMIX_ERR_NOT_SUPPORTED == rc) {
3474             /* we are being asked to do this before init, so
3475              * just copy the pointer across */
3476             p->data.cpuset = src->data.cpuset;
3477         }
3478         break;
3479     case PMIX_LOCTYPE:
3480         memcpy(&p->data.locality, &src->data.locality, sizeof(pmix_locality_t));
3481         break;
3482     case PMIX_GEOMETRY:
3483         return pmix_bfrops_base_tma_copy_geometry(&p->data.geometry, src->data.geometry, PMIX_GEOMETRY, tma);
3484     case PMIX_DEVTYPE:
3485         memcpy(&p->data.devtype, &src->data.devtype, sizeof(pmix_device_type_t));
3486         break;
3487     case PMIX_DEVICE_DIST:
3488         return pmix_bfrops_base_tma_copy_devdist(&p->data.devdist, src->data.devdist, PMIX_DEVICE_DIST, tma);
3489     case PMIX_ENDPOINT:
3490         return pmix_bfrops_base_tma_copy_endpoint(&p->data.endpoint, src->data.endpoint, PMIX_ENDPOINT, tma);
3491     case PMIX_REGATTR:
3492         return pmix_bfrops_base_tma_copy_regattr((pmix_regattr_t **) &p->data.ptr, src->data.ptr,
3493                                                  PMIX_REGATTR, tma);
3494     case PMIX_DATA_BUFFER:
3495         return pmix_bfrops_base_tma_copy_dbuf(&p->data.dbuf, src->data.dbuf, PMIX_DATA_BUFFER, tma);
3496     case PMIX_PROC_STATS:
3497         return pmix_bfrops_base_tma_copy_pstats(&p->data.pstats, src->data.pstats, PMIX_PROC_STATS, tma);
3498     case PMIX_DISK_STATS:
3499         return pmix_bfrops_base_tma_copy_dkstats(&p->data.dkstats, src->data.dkstats, PMIX_DISK_STATS, tma);
3500     case PMIX_NET_STATS:
3501         return pmix_bfrops_base_tma_copy_netstats(&p->data.netstats, src->data.netstats,
3502                                                   PMIX_NET_STATS, tma);
3503     case PMIX_NODE_STATS:
3504         return pmix_bfrops_base_tma_copy_ndstats(&p->data.ndstats, src->data.ndstats, PMIX_NODE_STATS, tma);
3505     default:
3506         pmix_output(0, "PMIX-XFER-VALUE: UNSUPPORTED TYPE %d", (int) src->type);
3507         return PMIX_ERROR;
3508     }
3509     return PMIX_SUCCESS;
3510 }
3511 
3512 static inline
3513 pmix_status_t pmix_bfrops_base_tma_copy_value(pmix_value_t **dest,
3514                                               pmix_value_t *src,
3515                                               pmix_data_type_t type,
3516                                               pmix_tma_t *tma)
3517 {
3518     PMIX_HIDE_UNUSED_PARAMS(type);
3519 
3520     *dest = (pmix_value_t *)pmix_tma_malloc(tma, sizeof(pmix_value_t));
3521     if (PMIX_UNLIKELY(NULL == *dest)) {
3522         return PMIX_ERR_OUT_OF_RESOURCE;
3523     }
3524 
3525     pmix_value_t *p = *dest;
3526     /* copy the type */
3527     p->type = src->type;
3528     /* copy the data */
3529     return pmix_bfrops_base_tma_value_xfer(p, src, tma);
3530 }
3531 
3532 static inline
3533 void pmix_bfrops_base_tma_data_array_destruct(pmix_data_array_t *d,
3534                                               pmix_tma_t *tma)
3535 {
3536     switch (d->type) {
3537         case PMIX_STRING: {
3538             char **s = (char**)d->array;
3539             for (size_t n = 0; n < d->size; n++) {
3540                 if (NULL != s[n]) {
3541                     pmix_tma_free(tma, s[n]);
3542                 }
3543             }
3544             pmix_tma_free(tma, d->array);
3545             break;
3546         }
3547         case PMIX_VALUE:
3548             pmix_bfrops_base_tma_value_free(d->array, d->size, tma);
3549             break;
3550         case PMIX_APP:
3551             pmix_bfrops_base_tma_app_free(d->array, d->size, tma);
3552             break;
3553         case PMIX_INFO:
3554             pmix_bfrops_base_tma_info_free(d->array, d->size, tma);
3555             break;
3556         case PMIX_PDATA:
3557             pmix_bfrops_base_tma_pdata_free(d->array, d->size, tma);
3558             break;
3559         case PMIX_BUFFER: {
3560             pmix_buffer_t *const pb = (pmix_buffer_t *)d->array;
3561             for (size_t n = 0; n < d->size; n++) {
3562                 PMIX_DESTRUCT(&pb[n]);
3563             }
3564             pmix_tma_free(tma, d->array);
3565             break;
3566         }
3567         case PMIX_BYTE_OBJECT:
3568         case PMIX_COMPRESSED_STRING:
3569         case PMIX_COMPRESSED_BYTE_OBJECT: {
3570         pmix_byte_object_t *const bo = (pmix_byte_object_t *)d->array;
3571             for (size_t n = 0; n < d->size; n++) {
3572                 if (NULL != bo[n].bytes) {
3573                     pmix_tma_free(tma, bo[n].bytes);
3574                 }
3575             }
3576             pmix_tma_free(tma, d->array);
3577             break;
3578         }
3579         case PMIX_KVAL: {
3580             pmix_kval_t *const kv = (pmix_kval_t *)d->array;
3581             for (size_t n = 0; n < d->size; n++) {
3582                 if (NULL != kv[n].key) {
3583                     pmix_tma_free(tma, kv[n].key);
3584                 }
3585                 if (NULL != kv[n].value) {
3586                     pmix_bfrops_base_tma_value_free(kv[n].value, 1, tma);
3587                 }
3588             }
3589             pmix_tma_free(tma, d->array);
3590             break;
3591         }
3592         case PMIX_PROC_INFO:
3593             pmix_bfrops_base_tma_proc_info_free(d->array, d->size, tma);
3594             break;
3595         case PMIX_DATA_ARRAY:
3596             pmix_bfrops_base_tma_data_array_destruct(d->array, tma);
3597             break;
3598         case PMIX_QUERY:
3599             pmix_bfrops_base_tma_query_free(d->array, d->size, tma);
3600             break;
3601         case PMIX_ENVAR:
3602             pmix_bfrops_base_tma_envar_free(d->array, d->size, tma);
3603             break;
3604         case PMIX_COORD:
3605             pmix_bfrops_base_tma_coord_free(d->array, d->size, tma);
3606             break;
3607         case PMIX_REGATTR:
3608             pmix_bfrops_base_tma_regattr_free(d->array, d->size, tma);
3609             break;
3610         case PMIX_PROC_CPUSET:
3611             // TODO(skg) Add TMA support when necessary.
3612             pmix_hwloc_release_cpuset(d->array, d->size);
3613             break;
3614         case PMIX_TOPO:
3615             // TODO(skg) Add TMA support when necessary.
3616             pmix_hwloc_release_topology(d->array, d->size);
3617             break;
3618         case PMIX_GEOMETRY:
3619             pmix_bfrops_base_tma_geometry_free(d->array, d->size, tma);
3620             break;
3621         case PMIX_DEVICE_DIST:
3622             pmix_bfrops_base_tma_device_distance_free(d->array, d->size, tma);
3623             break;
3624         case PMIX_ENDPOINT:
3625             pmix_bfrops_base_tma_endpoint_free(d->array, d->size, tma);
3626             break;
3627         case PMIX_REGEX: {
3628             pmix_byte_object_t *const bo = (pmix_byte_object_t *)d->array;
3629             for (size_t n = 0; n < d->size; n++) {
3630                 if (NULL != bo[n].bytes) {
3631                     // TODO(skg) Add TMA support when necessary.
3632                     pmix_preg.release(bo[n].bytes);
3633                 }
3634             }
3635             pmix_tma_free(tma, d->array);
3636             break;
3637         }
3638         case PMIX_DATA_BUFFER: {
3639             pmix_data_buffer_t *const db = (pmix_data_buffer_t *)d->array;
3640             for (size_t n = 0; n < d->size; n++) {
3641                 pmix_bfrops_base_tma_data_buffer_destruct(&db[n], tma);
3642             }
3643             pmix_tma_free(tma, d->array);
3644             break;
3645         }
3646         case PMIX_PROC_STATS:
3647             pmix_bfrops_base_tma_proc_stats_free(d->array, d->size, tma);
3648             break;
3649         case PMIX_DISK_STATS:
3650             pmix_bfrops_base_tma_disk_stats_free(d->array, d->size, tma);
3651             break;
3652         case PMIX_NET_STATS:
3653             pmix_bfrops_base_tma_net_stats_free(d->array, d->size, tma);
3654             break;
3655         case PMIX_NODE_STATS:
3656             pmix_bfrops_base_tma_node_stats_free(d->array, d->size, tma);
3657             break;
3658         default:
3659             if (NULL != d->array) {
3660                 pmix_tma_free(tma, d->array);
3661             }
3662             break;
3663     }
3664     d->array = NULL;
3665     d->type = PMIX_UNDEF;
3666     d->size = 0;
3667 }
3668 
3669 static inline
3670 void pmix_bfrops_base_tma_data_array_free(pmix_data_array_t *p,
3671                                           pmix_tma_t *tma)
3672 {
3673     if (NULL != p) {
3674         pmix_bfrops_base_tma_data_array_destruct(p, tma);
3675         pmix_tma_free(tma, p);
3676     }
3677 }
3678 
3679 static inline
3680 void pmix_bfrops_base_tma_data_array_construct(pmix_data_array_t *p,
3681                                                size_t num,
3682                                                pmix_data_type_t type,
3683                                                pmix_tma_t *tma)
3684 {
3685     p->type = type;
3686     p->size = num;
3687     if (0 < num) {
3688         if (PMIX_INFO == type) {
3689             p->array = pmix_bfrops_base_tma_info_create(num, tma);
3690 
3691         } else if (PMIX_PROC == type) {
3692             p->array = pmix_bfrops_base_tma_proc_create(num, tma);
3693 
3694         } else if (PMIX_PROC_INFO == type) {
3695             p->array = pmix_bfrops_base_tma_proc_info_create(num, tma);
3696 
3697         } else if (PMIX_ENVAR == type) {
3698             p->array = pmix_bfrops_base_tma_envar_create(num, tma);
3699 
3700         } else if (PMIX_VALUE == type) {
3701             p->array = pmix_bfrops_base_tma_value_create(num, tma);
3702 
3703         } else if (PMIX_PDATA == type) {
3704             p->array = pmix_bfrops_base_tma_pdata_create(num, tma);
3705 
3706         } else if (PMIX_QUERY == type) {
3707             p->array = pmix_bfrops_base_tma_query_create(num, tma);
3708 
3709         } else if (PMIX_APP == type) {
3710             p->array = pmix_bfrops_base_tma_app_create(num, tma);
3711 
3712         } else if (PMIX_BYTE_OBJECT == type ||
3713                    PMIX_COMPRESSED_STRING == type) {
3714             p->array = pmix_bfrops_base_tma_byte_object_create(num, tma);
3715 
3716         } else if (PMIX_ALLOC_DIRECTIVE == type ||
3717                    PMIX_PROC_STATE == type ||
3718                    PMIX_PERSIST == type ||
3719                    PMIX_SCOPE == type ||
3720                    PMIX_DATA_RANGE == type ||
3721                    PMIX_BYTE == type ||
3722                    PMIX_INT8 == type ||
3723                    PMIX_UINT8 == type ||
3724                    PMIX_POINTER == type) {
3725             p->array = pmix_tma_malloc(tma, num * sizeof(int8_t));
3726             memset(p->array, 0, num * sizeof(int8_t));
3727 
3728         } else if (PMIX_STRING == type) {
3729             p->array = pmix_tma_malloc(tma, num * sizeof(char*));
3730             memset(p->array, 0, num * sizeof(char*));
3731 
3732         } else if (PMIX_SIZE == type) {
3733             p->array = pmix_tma_malloc(tma, num * sizeof(size_t));
3734             memset(p->array, 0, num * sizeof(size_t));
3735 
3736         } else if (PMIX_PID == type) {
3737             p->array = pmix_tma_malloc(tma, num * sizeof(pid_t));
3738             memset(p->array, 0, num * sizeof(pid_t));
3739 
3740         } else if (PMIX_INT == type ||
3741                    PMIX_UINT == type ||
3742                    PMIX_STATUS == type) {
3743             p->array = pmix_tma_malloc(tma, num * sizeof(int));
3744             memset(p->array, 0, num * sizeof(int));
3745 
3746         } else if (PMIX_IOF_CHANNEL == type ||
3747                    PMIX_DATA_TYPE == type ||
3748                    PMIX_INT16 == type ||
3749                    PMIX_UINT16 == type) {
3750             p->array = pmix_tma_malloc(tma, num * sizeof(int16_t));
3751             memset(p->array, 0, num * sizeof(int16_t));
3752 
3753         } else if (PMIX_PROC_RANK == type ||
3754                    PMIX_INFO_DIRECTIVES == type ||
3755                    PMIX_INT32 == type ||
3756                    PMIX_UINT32 == type) {
3757             p->array = pmix_tma_malloc(tma, num * sizeof(int32_t));
3758             memset(p->array, 0, num * sizeof(int32_t));
3759 
3760         } else if (PMIX_INT64 == type ||
3761                    PMIX_UINT64 == type) {
3762             p->array = pmix_tma_malloc(tma, num * sizeof(int64_t));
3763             memset(p->array, 0, num * sizeof(int64_t));
3764 
3765         } else if (PMIX_FLOAT == type) {
3766             p->array = pmix_tma_malloc(tma, num * sizeof(float));
3767             memset(p->array, 0, num * sizeof(float));
3768 
3769         } else if (PMIX_DOUBLE == type) {
3770             p->array = pmix_tma_malloc(tma, num * sizeof(double));
3771             memset(p->array, 0, num * sizeof(double));
3772 
3773         } else if (PMIX_TIMEVAL == type) {
3774             p->array = pmix_tma_malloc(tma, num * sizeof(struct timeval));
3775             memset(p->array, 0, num * sizeof(struct timeval));
3776 
3777         } else if (PMIX_TIME == type) {
3778             p->array = pmix_tma_malloc(tma, num * sizeof(time_t));
3779             memset(p->array, 0, num * sizeof(time_t));
3780 
3781         } else if (PMIX_REGATTR == type) {
3782             p->array = pmix_bfrops_base_tma_regattr_create(num, tma);
3783 
3784         } else if (PMIX_BOOL == type) {
3785             p->array = pmix_tma_malloc(tma, num * sizeof(bool));
3786             memset(p->array, 0, num * sizeof(bool));
3787 
3788         } else if (PMIX_COORD == type) {
3789             /* cannot use PMIx_Coord_create as we do not
3790              * know the number of dimensions */
3791             p->array = pmix_tma_malloc(tma, num * sizeof(pmix_coord_t));
3792             memset(p->array, 0, num * sizeof(pmix_coord_t));
3793 
3794         } else if (PMIX_LINK_STATE == type) {
3795             p->array = pmix_tma_malloc(tma, num * sizeof(pmix_link_state_t));
3796             memset(p->array, 0, num * sizeof(pmix_link_state_t));
3797 
3798         } else if (PMIX_ENDPOINT == type) {
3799             p->array = pmix_bfrops_base_tma_endpoint_create(num, tma);
3800 
3801         } else if (PMIX_PROC_NSPACE == type) {
3802             p->array = pmix_tma_malloc(tma, num * sizeof(pmix_nspace_t));
3803             memset(p->array, 0, num * sizeof(pmix_nspace_t));
3804 
3805         } else if (PMIX_PROC_STATS == type) {
3806             p->array = pmix_bfrops_base_tma_proc_stats_create(num, tma);
3807 
3808         } else if (PMIX_DISK_STATS == type) {
3809             p->array = pmix_bfrops_base_tma_disk_stats_create(num, tma);
3810 
3811         } else if (PMIX_NET_STATS == type) {
3812             p->array = pmix_bfrops_base_tma_net_stats_create(num, tma);
3813 
3814         } else if (PMIX_NODE_STATS == type) {
3815             p->array = pmix_bfrops_base_tma_node_stats_create(num, tma);
3816 
3817         } else if (PMIX_DEVICE_DIST == type) {
3818             p->array = pmix_bfrops_base_tma_device_distance_create(num, tma);
3819 
3820         } else if (PMIX_GEOMETRY == type) {
3821             p->array = pmix_bfrops_base_tma_geometry_create(num, tma);
3822 
3823         } else if (PMIX_PROC_CPUSET == type) {
3824             p->array = pmix_bfrops_base_tma_cpuset_create(num, tma);
3825 
3826         } else {
3827             p->array = NULL;
3828             p->size = 0;
3829         }
3830     } else {
3831         p->array = NULL;
3832     }
3833 }
3834 
3835 static inline
3836 pmix_data_array_t* pmix_bfrops_base_tma_data_array_create(size_t n,
3837                                                           pmix_data_type_t type,
3838                                                           pmix_tma_t *tma)
3839 {
3840     if (0 == n) {
3841         return NULL;
3842     }
3843     pmix_data_array_t *p = (pmix_data_array_t *)pmix_tma_malloc(tma, sizeof(pmix_data_array_t));
3844     if (PMIX_LIKELY(NULL != p)) {
3845         pmix_bfrops_base_tma_data_array_construct(p, n, type, tma);
3846     }
3847     return p;
3848 }
3849 
3850 // Note **v to maintain sematics of PMIX_VALUE_RELEASE().
3851 static inline
3852 void pmix_bfrops_base_tma_value_release(pmix_value_t **v,
3853                                         pmix_tma_t *tma)
3854 {
3855     pmix_bfrops_base_tma_value_destruct(*v, tma);
3856     pmix_tma_free(tma, *v);
3857     *v = NULL;
3858 }
3859 
3860 static inline
3861 void pmix_bfrops_base_tma_value_destruct(pmix_value_t *v,
3862                                          pmix_tma_t *tma)
3863 {
3864     switch (v->type) {
3865         case PMIX_STRING:
3866             if (NULL != v->data.string) {
3867                 pmix_tma_free(tma, v->data.string);
3868             }
3869             break;
3870         case PMIX_PROC:
3871             if (NULL != v->data.proc) {
3872                 pmix_bfrops_base_tma_proc_free(v->data.proc, 1, tma);
3873             }
3874             break;
3875         case PMIX_BYTE_OBJECT:
3876         case PMIX_COMPRESSED_STRING:
3877         case PMIX_COMPRESSED_BYTE_OBJECT:
3878             if (NULL != v->data.bo.bytes) {
3879                 pmix_tma_free(tma, v->data.bo.bytes);
3880             }
3881             break;
3882         case PMIX_PROC_INFO:
3883             if (NULL != v->data.pinfo) {
3884                 pmix_bfrops_base_tma_proc_info_free(v->data.pinfo, 1, tma);
3885             }
3886             break;
3887         case PMIX_DATA_ARRAY:
3888             if (NULL != v->data.darray) {
3889                 pmix_bfrops_base_tma_data_array_free(v->data.darray, tma);
3890             }
3891             break;
3892         case PMIX_ENVAR:
3893             if (NULL != v->data.envar.envar) {
3894                 pmix_tma_free(tma, v->data.envar.envar);
3895             }
3896             if (NULL != v->data.envar.value) {
3897                 pmix_tma_free(tma, v->data.envar.value);
3898             }
3899             break;
3900         case PMIX_COORD:
3901             if (NULL != v->data.coord) {
3902                 pmix_bfrops_base_tma_coord_free(v->data.coord, 1, tma);
3903             }
3904             break;
3905         case PMIX_TOPO:
3906             if (NULL != v->data.topo) {
3907                 pmix_bfrops_base_tma_topology_free(v->data.topo, 1, tma);
3908             }
3909             break;
3910         case PMIX_PROC_CPUSET:
3911             if (NULL != v->data.cpuset) {
3912                 // TODO(skg) Add TMA support when necessary.
3913                 pmix_hwloc_release_cpuset(v->data.cpuset, 1);
3914             }
3915             break;
3916         case PMIX_GEOMETRY:
3917             if (NULL != v->data.geometry) {
3918                 pmix_bfrops_base_tma_geometry_free(v->data.geometry, 1, tma);
3919             }
3920             break;
3921         case PMIX_DEVICE_DIST:
3922             if (NULL != v->data.devdist) {
3923                 pmix_bfrops_base_tma_device_distance_free(v->data.devdist, 1, tma);
3924             }
3925             break;
3926         case PMIX_ENDPOINT:
3927             if (NULL != v->data.endpoint) {
3928                 pmix_bfrops_base_tma_endpoint_free(v->data.endpoint, 1, tma);
3929             }
3930             break;
3931         case PMIX_REGATTR:
3932             if (NULL != v->data.ptr) {
3933                 pmix_bfrops_base_tma_regattr_free(v->data.ptr, 1, tma);
3934             }
3935             break;
3936         case PMIX_REGEX:
3937             if (NULL != v->data.bo.bytes) {
3938                 // TODO(skg) Add TMA support when necessary.
3939                 pmix_preg.release(v->data.bo.bytes);
3940             }
3941             break;
3942         case PMIX_DATA_BUFFER:
3943             if (NULL != v->data.dbuf) {
3944                 pmix_bfrops_base_tma_data_buffer_release(v->data.dbuf, tma);
3945             }
3946             break;
3947         case PMIX_PROC_STATS:
3948             if (NULL != v->data.pstats) {
3949                 pmix_bfrops_base_tma_proc_stats_free(v->data.pstats, 1, tma);
3950                 v->data.pstats = NULL;
3951             }
3952             break;
3953         case PMIX_DISK_STATS:
3954             if (NULL != v->data.dkstats) {
3955                 pmix_bfrops_base_tma_disk_stats_free(v->data.dkstats, 1, tma);
3956                 v->data.dkstats = NULL;
3957             }
3958             break;
3959         case PMIX_NET_STATS:
3960             if (NULL != v->data.netstats) {
3961                 pmix_bfrops_base_tma_net_stats_free(v->data.netstats, 1, tma);
3962                 v->data.netstats = NULL;
3963             }
3964             break;
3965         case PMIX_NODE_STATS:
3966             if (NULL != v->data.ndstats) {
3967                 pmix_bfrops_base_tma_node_stats_free(v->data.ndstats, 1, tma);
3968                 v->data.ndstats = NULL;
3969             }
3970             break;
3971 
3972         default:
3973             /* silence warnings */
3974             break;
3975     }
3976     // mark the value as no longer defined
3977     memset(v, 0, sizeof(pmix_value_t));
3978     v->type = PMIX_UNDEF;
3979     return;
3980 }
3981 
3982 #endif