root/opal/mca/pmix/pmix4x/pmix/src/mca/bfrops/bfrops.h

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

INCLUDED FROM


   1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2005 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2012      Los Alamos National Security, Inc. All rights reserved.
  14  * Copyright (c) 2013-2018 Intel, Inc. All rights reserved.
  15  * Copyright (c) 2015      Research Organization for Information Science
  16  *                         and Technology (RIST). All rights reserved.
  17  * Copyright (c) 2016      Mellanox Technologies, Inc.
  18  *                         All rights reserved.
  19  * $COPYRIGHT$
  20  *
  21  * Additional copyrights may follow
  22  *
  23  * $HEADER$
  24  */
  25 /**
  26  * @file
  27  *
  28  * Data packing subsystem.
  29  */
  30 
  31 #ifndef PMIX_BFROP_H_
  32 #define PMIX_BFROP_H_
  33 
  34 #include <src/include/pmix_config.h>
  35 #include <pmix_common.h>
  36 #include <src/include/types.h>
  37 
  38 #include "src/mca/mca.h"
  39 
  40 #include "bfrops_types.h"
  41 
  42 BEGIN_C_DECLS
  43 
  44 /* The overall objective of this framework is to provide seamless
  45  * cross-version support for communications by allowing a process
  46  * to communicate with a peer:
  47  *
  48  * (a) using a different version of the buffer operations. We are
  49  *     allowing changes in the structure compositions and/or data
  50  *     type definitions between versions. This specifically affects
  51  *     our ability to pack/unpack across versions.
  52  *
  53  * (b) using a different buffer type (described vs non-described).
  54  *     This resolves conflicts when one side was compiled with a
  55  *     debug option, while the other side has been "optimized".
  56  *
  57  * This is a mult-select framework - i.e., multiple components
  58  * are selected and "active" at the same time. The intent is
  59  * to have one component for each data type variation, with the
  60  * expectation that the community will do its best not to revise
  61  * existing data type definitions. Thus, new variations should be
  62  * rare, and only a few components will exist.
  63  *
  64  * The framework itself reflects the fact that any given peer
  65  * will utilize only one variation of the data type definitions.
  66  * Thus, once a peer is identified, it will pass its version string
  67  * to this framework's "assign_module" function, which will then
  68  * pass it to each component until one returns a module capable of
  69  * processing the given version. This module is then "attached" to
  70  * the pmix_peer_t object so it can be used for all subsequent
  71  * communication to/from that peer.
  72  *
  73  * Buffer type is included in the buffer metadata. Unfortunately,
  74  * the metadata is not communicated at each exchange. Thus, the
  75  * peers will indicate during the connection handshake the type
  76  * of buffer they will use for all subsequent communications. The
  77  * peer must then utilize that same buffer type for all messages
  78  * sent to that remote proc, so we provide new macros for creating
  79  * and constructing buffers that ensures the correct buffer type
  80  * is marked.
  81  *
  82  * Accordingly, there are two levels of APIs defined for this
  83  * framework:
  84  *
  85  * (a) component level - these allow for init/finalize of the
  86  *     component, and assignment of a module to a given peer
  87  *     based on the version that peer is using
  88  *
  89  * (b) module level - implement pack/unpack/copy/recv/etc. of
  90  *     the various datatypes. Note that the module only needs
  91  *     to provide those functions that differ from the base
  92  *     functions - they don't need to duplicate all that code!
  93  */
  94 
  95 
  96 /* The following functions are exposed to the user - they
  97  * therefore are implemented in the bfrops/base functions
  98  * as wrappers to the real functions.
  99  *
 100  * NOTE: THESE FUNCTIONS ARE NOT TO BE USED INTERNALLY -
 101  * USE THE MACROS INSTEAD
 102  */
 103 bool pmix_value_cmp(pmix_value_t *p, pmix_value_t *p1);
 104 
 105 
 106 
 107 /****    MODULE INTERFACE DEFINITION    ****/
 108 
 109 /* initialize the module - the module is expected
 110  * to register its datatype functions at this time */
 111 typedef pmix_status_t (*pmix_bfrop_init_fn_t)(void);
 112 
 113 /* finalize the module */
 114 typedef void (*pmix_bfrop_finalize_fn_t)(void);
 115 
 116 /**
 117  * Pack one or more values into a buffer.
 118  *
 119  * The pack function packs one or more values of a specified type into
 120  * the specified buffer.  The buffer must have already been
 121  * initialized via an PMIX_NEW or PMIX_CONSTRUCT call - otherwise, the
 122  * pack_value function will return an error. Providing an unsupported
 123  * type flag will likewise be reported as an error.
 124  *
 125  * Note that any data to be packed that is not hard type cast (i.e.,
 126  * not type cast to a specific size) may lose precision when unpacked
 127  * by a non-homogeneous recipient.  The BFROP will do its best to deal
 128  * with heterogeneity issues between the packer and unpacker in such
 129  * cases. Sending a number larger than can be handled by the recipient
 130  * will return an error code (generated by the BFROP upon unpacking) -
 131  * the BFROP cannot detect such errors during packing.
 132  *
 133  * @param *buffer A pointer to the buffer into which the value is to
 134  * be packed.
 135  *
 136  * @param *src A void* pointer to the data that is to be packed. This
 137  * is interpreted as a pointer to an array of that data type containing
 138  * length num_values. Note that strings are of data type char*, and so
 139  * they are to be passed as (char **) - i.e., the caller must
 140  * pass the address of the pointer to the string as the void*. This
 141  * allows the BFROP to use a single interface function, but still allow
 142  * the caller to pass multiple strings in a single call.
 143  *
 144  * @param num_values An int32_t indicating the number of values that are
 145  * to be packed, beginning at the location pointed to by src. A string
 146  * value is counted as a single value regardless of length. The values
 147  * must be contiguous in memory. Arrays of pointers (e.g., string
 148  * arrays) should be contiguous, although (obviously) the data pointed
 149  * to need not be contiguous across array entries.
 150  *
 151  * @param type The type of the data to be packed - must be one of the
 152  * PMIX defined data types.
 153  *
 154  * @retval PMIX_SUCCESS The data was packed as requested.
 155  *
 156  * @retval PMIX_ERROR(s) An appropriate PMIX error code indicating the
 157  * problem encountered. This error code should be handled
 158  * appropriately.
 159  *
 160  * @code
 161  * pmix_buffer_t *buffer;
 162  * int32_t src;
 163  *
 164  * status_code = pmix_bfrop.pack(buffer, &src, 1, PMIX_INT32);
 165  * @endcode
 166  */
 167 typedef pmix_status_t (*pmix_bfrop_pack_fn_t)(pmix_buffer_t *buffer,
 168                                               const void *src,
 169                                               int32_t num_values,
 170                                               pmix_data_type_t type);
 171 
 172 /**
 173  * Unpack values from a buffer.
 174  *
 175  * The unpack function unpacks the next value (or values) of a
 176  * specified type from the specified buffer.
 177  *
 178  * The buffer must have already been initialized via an PMIX_NEW or
 179  * PMIX_CONSTRUCT call (and assumedly filled with some data) -
 180  * otherwise, the unpack_value function will return an
 181  * error. Providing an unsupported type flag will likewise be reported
 182  * as an error, as will specifying a data type that DOES NOT match the
 183  * type of the next item in the buffer. An attempt to read beyond the
 184  * end of the stored data held in the buffer will also return an
 185  * error.
 186  *
 187  * NOTE: it is possible for the buffer to be corrupted and that
 188  * the BFROP will *think* there is a proper variable type at the
 189  * beginning of an unpack region - but that the value is bogus (e.g., just
 190  * a byte field in a string array that so happens to have a value that
 191  * matches the specified data type flag). Therefore, the data type error check
 192  * is NOT completely safe. This is true for ALL unpack functions.
 193  *
 194  * Warning: The caller is responsible for providing adequate memory
 195  * storage for the requested data. As noted below, the user
 196  * must provide a parameter indicating the maximum number of values that
 197  * can be unpacked into the allocated memory. If more values exist in the
 198  * buffer than can fit into the memory storage, then the bfrop will unpack
 199  * what it can fit into that location and return an error code indicating
 200  * that the buffer was only partially unpacked.
 201  *
 202  * Note that any data that was not hard type cast (i.e., not type cast
 203  * to a specific size) when packed may lose precision when unpacked by
 204  * a non-homogeneous recipient.  The BFROP will do its best to deal with
 205  * heterogeneity issues between the packer and unpacker in such
 206  * cases. Sending a number larger than can be handled by the recipient
 207  * will return an error code generated by the BFROP upon unpacking - the
 208  * BFROP cannot detect such errors during packing.
 209  *
 210  * @param *buffer A pointer to the buffer from which the value will be
 211  * extracted.
 212  *
 213  * @param *dest A void* pointer to the memory location into which the
 214  * data is to be stored. Note that these values will be stored
 215  * contiguously in memory. For strings, this pointer must be to (char
 216  * **) to provide a means of supporting multiple string
 217  * operations. The BFROP unpack function will allocate memory for each
 218  * string in the array - the caller must only provide adequate memory
 219  * for the array of pointers.
 220  *
 221  * @param type The type of the data to be unpacked - must be one of
 222  * the BFROP defined data types.
 223  *
 224  * @retval *max_num_values The number of values actually unpacked. In
 225  * most cases, this should match the maximum number provided in the
 226  * parameters - but in no case will it exceed the value of this
 227  * parameter.  Note that if you unpack fewer values than are actually
 228  * available, the buffer will be in an unpackable state - the bfrop will
 229  * return an error code to warn of this condition.
 230  *
 231  * @note The unpack function will return the actual number of values
 232  * unpacked in this location.
 233  *
 234  * @retval PMIX_SUCCESS The next item in the buffer was successfully
 235  * unpacked.
 236  *
 237  * @retval PMIX_ERROR(s) The unpack function returns an error code
 238  * under one of several conditions: (a) the number of values in the
 239  * item exceeds the max num provided by the caller; (b) the type of
 240  * the next item in the buffer does not match the type specified by
 241  * the caller; or (c) the unpack failed due to either an error in the
 242  * buffer or an attempt to read past the end of the buffer.
 243  *
 244  * @code
 245  * pmix_buffer_t *buffer;
 246  * int32_t dest;
 247  * char **string_array;
 248  * int32_t num_values;
 249  *
 250  * num_values = 1;
 251  * status_code = pmix_bfrop.unpack(buffer, (void*)&dest, &num_values, PMIX_INT32);
 252  *
 253  * num_values = 5;
 254  * string_array = malloc(num_values*sizeof(char *));
 255  * status_code = pmix_bfrop.unpack(buffer, (void*)(string_array), &num_values, PMIX_STRING);
 256  *
 257  * @endcode
 258  */
 259 typedef pmix_status_t (*pmix_bfrop_unpack_fn_t)(pmix_buffer_t *buffer, void *dest,
 260                                                 int32_t *max_num_values,
 261                                                 pmix_data_type_t type);
 262 /**
 263  * Copy a payload from one buffer to another
 264  * This function will append a copy of the payload in one buffer into
 265  * another buffer. If the destination buffer is NOT empty, then the
 266  * type of the two buffers MUST match or else an
 267  * error will be returned. If the destination buffer IS empty, then
 268  * its type will be set to that of the source buffer.
 269  * NOTE: This is NOT a destructive procedure - the
 270  * source buffer's payload will remain intact, as will any pre-existing
 271  * payload in the destination's buffer.
 272  */
 273 typedef pmix_status_t (*pmix_bfrop_copy_payload_fn_t)(pmix_buffer_t *dest,
 274                                                       pmix_buffer_t *src);
 275 
 276 /**
 277  * Copy a data value from one location to another.
 278  *
 279  * Since registered data types can be complex structures, the system
 280  * needs some way to know how to copy the data from one location to
 281  * another (e.g., for storage in the registry). This function, which
 282  * can call other copy functions to build up complex data types, defines
 283  * the method for making a copy of the specified data type.
 284  *
 285  * @param **dest The address of a pointer into which the
 286  * address of the resulting data is to be stored.
 287  *
 288  * @param *src A pointer to the memory location from which the
 289  * data is to be copied.
 290  *
 291  * @param type The type of the data to be copied - must be one of
 292  * the BFROP defined data types.
 293  *
 294  * @retval PMIX_SUCCESS The value was successfully copied.
 295  *
 296  * @retval PMIX_ERROR(s) An appropriate error code.
 297  *
 298  */
 299 typedef pmix_status_t (*pmix_bfrop_copy_fn_t)(void **dest, void *src,
 300                                               pmix_data_type_t type);
 301 
 302 /**
 303  * Print a data value.
 304  *
 305  * Since registered data types can be complex structures, the system
 306  * needs some way to know how to print them (i.e., convert them to a string
 307  * representation). Provided for debug purposes.
 308  *
 309  * @retval PMIX_SUCCESS The value was successfully printed.
 310  *
 311  * @retval PMIX_ERROR(s) An appropriate error code.
 312  */
 313 typedef pmix_status_t (*pmix_bfrop_print_fn_t)(char **output, char *prefix,
 314                                                void *src, pmix_data_type_t type);
 315 
 316 /**
 317  * Transfer a value from one pmix_value_t to another. Ordinarily,
 318  * this would be executed as a base function. However, it is
 319  * possible that future versions may add new data types, and
 320  * thus the xfer function may differ
 321  *
 322  * @retval PMIX_SUCCESS The value was successfully transferred
 323  *
 324  * @retval PMIX_ERROR(s) An appropriate error code
 325  */
 326 typedef pmix_status_t (*pmix_bfrop_value_xfer_fn_t)(pmix_value_t *dest,
 327                                                     const pmix_value_t *src);
 328 
 329 
 330 /**
 331  * Load data into a pmix_value_t object. Again, this is provided
 332  * as a component function to support different data types
 333  */
 334 typedef void (*pmix_bfrop_value_load_fn_t)(pmix_value_t *v, const void *data,
 335                                            pmix_data_type_t type);
 336 
 337 /**
 338  * Unload data from a pmix_value_t object
 339  *
 340  * @retval PMIX_SUCCESS The value was successfully unloaded
 341  *
 342  * @retval PMIX_ERROR(s) An appropriate error code
 343  */
 344 typedef pmix_status_t (*pmix_bfrop_value_unload_fn_t)(pmix_value_t *kv,
 345                                                       void **data, size_t *sz);
 346 
 347 /**
 348  * Compare two pmix_value_t structs
 349  */
 350 typedef pmix_value_cmp_t (*pmix_bfrop_value_cmp_fn_t)(pmix_value_t *p1, pmix_value_t *p2);
 351 
 352 /* define a component-level API for registering a new
 353  * datatype, providing all the required functions */
 354 typedef pmix_status_t (*pmix_bfrop_base_register_fn_t)(const char *name, pmix_data_type_t type,
 355                                                        pmix_bfrop_pack_fn_t pack,
 356                                                        pmix_bfrop_unpack_fn_t unpack,
 357                                                        pmix_bfrop_copy_fn_t copy,
 358                                                        pmix_bfrop_print_fn_t print);
 359 
 360 /* return the string name of a provided data type */
 361 typedef const char* (*pmix_bfrop_data_type_string_fn_t)(pmix_data_type_t type);
 362 
 363 /**
 364  * Base structure for a BFROP module
 365  */
 366 typedef struct {
 367     char *version;
 368     pmix_bfrop_init_fn_t              init;
 369     pmix_bfrop_finalize_fn_t          finalize;
 370     pmix_bfrop_pack_fn_t              pack;
 371     pmix_bfrop_unpack_fn_t            unpack;
 372     pmix_bfrop_copy_fn_t              copy;
 373     pmix_bfrop_print_fn_t             print;
 374     pmix_bfrop_copy_payload_fn_t      copy_payload;
 375     pmix_bfrop_value_xfer_fn_t        value_xfer;
 376     pmix_bfrop_value_load_fn_t        value_load;
 377     pmix_bfrop_value_unload_fn_t      value_unload;
 378     pmix_bfrop_value_cmp_fn_t         value_cmp;
 379     pmix_bfrop_base_register_fn_t     register_type;
 380     pmix_bfrop_data_type_string_fn_t  data_type_string;
 381 } pmix_bfrops_module_t;
 382 
 383 
 384 /* get a list of available versions - caller must free results
 385  * when done */
 386 PMIX_EXPORT char* pmix_bfrops_base_get_available_modules(void);
 387 
 388 /* Select a bfrops module for a given version */
 389 PMIX_EXPORT pmix_bfrops_module_t* pmix_bfrops_base_assign_module(const char *version);
 390 
 391 /* provide a backdoor to access the framework debug output */
 392 PMIX_EXPORT extern int pmix_bfrops_base_output;
 393 
 394 /* MACROS FOR EXECUTING BFROPS FUNCTIONS */
 395 #define PMIX_BFROPS_ASSIGN_TYPE(p, b)               \
 396     (b)->type = (p)->nptr->compat.type
 397 
 398 #define PMIX_BFROPS_PACK(r, p, b, s, n, t)                          \
 399     do {                                                            \
 400         pmix_output_verbose(2, pmix_bfrops_base_output,             \
 401                             "[%s:%d] PACK version %s",              \
 402                             __FILE__, __LINE__,                     \
 403                             (p)->nptr->compat.bfrops->version);     \
 404         if (PMIX_BFROP_BUFFER_UNDEF == (b)->type) {                 \
 405             (b)->type = (p)->nptr->compat.type;                     \
 406             (r) = (p)->nptr->compat.bfrops->pack(b, s, n, t);       \
 407         } else if ((b)->type == (p)->nptr->compat.type) {           \
 408             (r) = (p)->nptr->compat.bfrops->pack(b, s, n, t);       \
 409         } else {                                                    \
 410             (r) = PMIX_ERR_PACK_MISMATCH;                           \
 411         }                                                           \
 412     } while(0)
 413 
 414 #define PMIX_BFROPS_UNPACK(r, p, b, d, m, t)                        \
 415     do {                                                            \
 416         pmix_output_verbose(2, pmix_bfrops_base_output,             \
 417                             "[%s:%d] UNPACK version %s",            \
 418                             __FILE__, __LINE__,                     \
 419                             (p)->nptr->compat.bfrops->version);     \
 420         if ((b)->type == (p)->nptr->compat.type) {                  \
 421             (r) = (p)->nptr->compat.bfrops->unpack(b, d, m, t);     \
 422         } else {                                                    \
 423             (r) = PMIX_ERR_UNPACK_FAILURE;                          \
 424         }                                                           \
 425     } while(0)
 426 
 427 #define PMIX_BFROPS_COPY(r, p, d, s, t)             \
 428     (r) = (p)->nptr->compat.bfrops->copy(d, s, t)
 429 
 430 #define PMIX_BFROPS_PRINT(r, p, o, pr, s, t)        \
 431     (r) = (p)->nptr->compat.bfrops->print(o, pr, s, t)
 432 
 433 #define PMIX_BFROPS_COPY_PAYLOAD(r, p, d, s)                    \
 434     do {                                                        \
 435         if (PMIX_BFROP_BUFFER_UNDEF == (d)->type) {             \
 436             (d)->type = (p)->nptr->compat.type;                 \
 437             (r) = (p)->nptr->compat.bfrops->copy_payload(d, s); \
 438         } else if ((d)->type == (p)->nptr->compat.type) {       \
 439             (r) = (p)->nptr->compat.bfrops->copy_payload(d, s); \
 440         } else {                                                \
 441             (r) = PMIX_ERR_PACK_MISMATCH;                       \
 442         }                                                       \
 443     } while(0)
 444 
 445 #define PMIX_BFROPS_VALUE_XFER(r, p, d, s)          \
 446     (r) = (p)->nptr->compat.bfrops->value_xfer(d, s)
 447 
 448 #define PMIX_BFROPS_VALUE_LOAD(p, v, d, t)          \
 449     (p)->nptr->compat.bfrops->value_load(v, d, t)
 450 
 451 #define PMIX_BFROPS_VALUE_UNLOAD(r, p, k, d, s)     \
 452     (r) = (p)->nptr->compat.bfrops->value_unload(k,, d, s)
 453 
 454 #define PMIX_BFROPS_VALUE_CMP(r, p, q, s)           \
 455     (r) = (p)->nptr->compat.bfrops->value_cmp(q, s)
 456 
 457 #define PMIX_BFROPS_REGISTER(r, p, n, t, pk, u, c, pr)   \
 458     (r) = (p)->nptr->compat.bfrops->register_type(n, t, pk, u, c, pr)
 459 
 460 #define PMIX_BFROPS_PRINT_TYPE(c, p, t)             \
 461     (c) = (p)->nptr->compat.bfrops->data_type_string(t)
 462 
 463 
 464 /****    COMPONENT STRUCTURE DEFINITION    ****/
 465 
 466 /* define a component-level API for getting a module */
 467 typedef pmix_bfrops_module_t* (*pmix_bfrop_base_component_assign_module_fn_t)(void);
 468 
 469 /*
 470  * the standard component data structure
 471  */
 472 struct pmix_bfrops_base_component_t {
 473     pmix_mca_base_component_t                           base;
 474     pmix_mca_base_component_data_t                      data;
 475     int                                                 priority;
 476     pmix_pointer_array_t                                types;
 477     pmix_bfrop_base_component_assign_module_fn_t        assign_module;
 478 };
 479 typedef struct pmix_bfrops_base_component_t pmix_bfrops_base_component_t;
 480 
 481 /*
 482  * Macro for use in components that are of type bfrops
 483  */
 484 #define PMIX_BFROPS_BASE_VERSION_1_0_0 \
 485     PMIX_MCA_BASE_VERSION_1_0_0("bfrops", 1, 0, 0)
 486 
 487 END_C_DECLS
 488 
 489 #endif /* PMIX_BFROP_H */

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