root/opal/dss/dss.h

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

INCLUDED FROM


   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   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) 2014-2017 Intel, Inc. All rights reserved.
  15  * Copyright (c) 2018      Triad National Security, LLC. All rights
  16  *                         reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 /**
  24  * @file
  25  *
  26  * Data packing subsystem.
  27  */
  28 
  29 #ifndef OPAL_DSS_H_
  30 #define OPAL_DSS_H_
  31 
  32 #include "opal_config.h"
  33 
  34 #include "opal/dss/dss_types.h"
  35 
  36 BEGIN_C_DECLS
  37 
  38 /* Provide a macro for determining the bool value of an opal_value_t */
  39 #define OPAL_CHECK_BOOL(v, p)           \
  40     do {                                \
  41         if (OPAL_UNDEF == (v)->type) {  \
  42             (p) = true;                 \
  43         } else {                        \
  44             (p) = (v)->data.flag;       \
  45         }                               \
  46     } while(0)
  47 
  48 /* A non-API function for something that happens in a number
  49  * of places throughout the code base - loading a value into
  50  * an opal_value_t structure
  51  */
  52 OPAL_DECLSPEC int opal_value_load(opal_value_t *kv,
  53                                   void *data, opal_data_type_t type);
  54 OPAL_DECLSPEC int opal_value_unload(opal_value_t *kv,
  55                                     void **data, opal_data_type_t type);
  56 OPAL_DECLSPEC int opal_value_xfer(opal_value_t *dest,
  57                                   opal_value_t *src);
  58 /**
  59  * Top-level interface function to pack one or more values into a
  60  * buffer.
  61  *
  62  * The pack function packs one or more values of a specified type into
  63  * the specified buffer.  The buffer must have already been
  64  * initialized via an OBJ_NEW or OBJ_CONSTRUCT call - otherwise, the
  65  * pack_value function will return an error. Providing an unsupported
  66  * type flag will likewise be reported as an error.
  67  *
  68  * Note that any data to be packed that is not hard type cast (i.e.,
  69  * not type cast to a specific size) may lose precision when unpacked
  70  * by a non-homogeneous recipient.  The DSS will do its best to deal
  71  * with heterogeneity issues between the packer and unpacker in such
  72  * cases. Sending a number larger than can be handled by the recipient
  73  * will return an error code (generated by the DSS upon unpacking) via
  74  * the RML upon transmission - the DSS cannot detect such errors
  75  * during packing.
  76  *
  77  * @param *buffer A pointer to the buffer into which the value is to
  78  * be packed.
  79  *
  80  * @param *src A void* pointer to the data that is to be packed. Note
  81  * that strings are to be passed as (char **) - i.e., the caller must
  82  * pass the address of the pointer to the string as the void*. This
  83  * allows the DSS to use a single interface function, but still allow
  84  * the caller to pass multiple strings in a single call.
  85  *
  86  * @param num A size_t value indicating the number of values that are
  87  * to be packed, beginning at the location pointed to by src. A string
  88  * value is counted as a single value regardless of length. The values
  89  * must be contiguous in memory. Arrays of pointers (e.g., string
  90  * arrays) should be contiguous, although (obviously) the data pointed
  91  * to need not be contiguous across array entries.
  92  *
  93  * @param type The type of the data to be packed - must be one of the
  94  * DSS defined data types.
  95  *
  96  * @retval OPAL_SUCCESS The data was packed as requested.
  97  *
  98  * @retval OPAL_ERROR(s) An appropriate OPAL error code indicating the
  99  * problem encountered. This error code should be handled
 100  * appropriately.
 101  *
 102  * @code
 103  * opal_buffer_t *buffer;
 104  * int32_t src;
 105  *
 106  * status_code = opal_dss.pack(buffer, &src, 1, OPAL_INT32);
 107  * @endcode
 108  */
 109 typedef int (*opal_dss_pack_fn_t)(opal_buffer_t *buffer, const void *src,
 110                                   int32_t num_values,
 111                                   opal_data_type_t type);
 112 
 113 /**
 114  * Unpack values from a buffer.
 115  *
 116  * The unpack function unpacks the next value (or values) of a
 117  * specified type from the specified buffer.
 118  *
 119  * The buffer must have already been initialized via an OBJ_NEW or
 120  * OBJ_CONSTRUCT call (and assumedly filled with some data) -
 121  * otherwise, the unpack_value function will return an
 122  * error. Providing an unsupported type flag will likewise be reported
 123  * as an error, as will specifying a data type that DOES NOT match the
 124  * type of the next item in the buffer. An attempt to read beyond the
 125  * end of the stored data held in the buffer will also return an
 126  * error.
 127  *
 128  * NOTE: it is possible for the buffer to be corrupted and that
 129  * the DSS will *think* there is a proper variable type at the
 130  * beginning of an unpack region - but that the value is bogus (e.g., just
 131  * a byte field in a string array that so happens to have a value that
 132  * matches the specified data type flag). Therefore, the data type error check
 133  * is NOT completely safe. This is true for ALL unpack functions.
 134  *
 135  *
 136  * Unpacking values is a "destructive" process - i.e., the values are
 137  * removed from the buffer, thus reducing the buffer size. It is
 138  * therefore not possible for the caller to re-unpack a value from the
 139  * same buffer.
 140  *
 141  * Warning: The caller is responsible for providing adequate memory
 142  * storage for the requested data. The opal_dss_peek() function is
 143  * provided to assist in meeting this requirement. As noted below, the user
 144  * must provide a parameter indicating the maximum number of values that
 145  * can be unpacked into the allocated memory. If more values exist in the
 146  * buffer than can fit into the memory storage, then the dss will unpack
 147  * what it can fit into that location and return an error code indicating
 148  * that the buffer was only partially unpacked.
 149  *
 150  * Note that any data that was not hard type cast (i.e., not type cast
 151  * to a specific size) when packed may lose precision when unpacked by
 152  * a non-homogeneous recipient.  The DSS will do its best to deal with
 153  * heterogeneity issues between the packer and unpacker in such
 154  * cases. Sending a number larger than can be handled by the recipient
 155  * will return an error code (generated by the DSS upon unpacking) via
 156  * the RML upon transmission - the DSS cannot detect such errors
 157  * during packing.
 158  *
 159  * @param *buffer A pointer to the buffer from which the value will be
 160  * extracted.
 161  *
 162  * @param *dest A void* pointer to the memory location into which the
 163  * data is to be stored. Note that these values will be stored
 164  * contiguously in memory. For strings, this pointer must be to (char
 165  * **) to provide a means of supporting multiple string
 166  * operations. The DSS unpack function will allocate memory for each
 167  * string in the array - the caller must only provide adequate memory
 168  * for the array of pointers.
 169  *
 170  * @param *num A pointer to a int32_t value indicating the maximum
 171  * number of values that are to be unpacked, beginning at the location
 172  * pointed to by src. This is provided to help protect the caller from
 173  * memory overrun. Note that a string
 174  * value is counted as a single value regardless of length.
 175  *
 176  * @note The unpack function will return the actual number of values
 177  * unpacked in this location.
 178  *
 179  * @param type The type of the data to be unpacked - must be one of
 180  * the DSS defined data types.
 181  *
 182  * @retval *max_num_values The number of values actually unpacked. In
 183  * most cases, this should match the maximum number provided in the
 184  * parameters - but in no case will it exceed the value of this
 185  * parameter.  Note that if you unpack fewer values than are actually
 186  * available, the buffer will be in an unpackable state - the dss will
 187  * return an error code to warn of this condition.
 188  *
 189  * @retval OPAL_SUCCESS The next item in the buffer was successfully
 190  * unpacked.
 191  *
 192  * @retval OPAL_ERROR(s) The unpack function returns an error code
 193  * under one of several conditions: (a) the number of values in the
 194  * item exceeds the max num provided by the caller; (b) the type of
 195  * the next item in the buffer does not match the type specified by
 196  * the caller; or (c) the unpack failed due to either an error in the
 197  * buffer or an attempt to read past the end of the buffer.
 198  *
 199  * @code
 200  * opal_buffer_t *buffer;
 201  * int32_t dest;
 202  * char **string_array;
 203  * int32_t num_values;
 204  *
 205  * num_values = 1;
 206  * status_code = opal_dss.unpack(buffer, (void*)&dest, &num_values, OPAL_INT32);
 207  *
 208  * num_values = 5;
 209  * string_array = malloc(num_values*sizeof(char *));
 210  * status_code = opal_dss.unpack(buffer, (void*)(string_array), &num_values, OPAL_STRING);
 211  *
 212  * @endcode
 213  */
 214 typedef int (*opal_dss_unpack_fn_t)(opal_buffer_t *buffer, void *dest,
 215                                     int32_t *max_num_values,
 216                                     opal_data_type_t type);
 217 
 218 /**
 219  * Get the type and number of values of the next item in the buffer.
 220  *
 221  * The peek function looks at the next item in the buffer and returns
 222  * both its type and the number of values in the item. This is a
 223  * non-destructive function call that does not disturb the buffer, so
 224  * it can be called multiple times if desired.
 225  *
 226  * @param buffer A pointer to the buffer in question.
 227  *
 228  * @param type A pointer to an opal_data_type_t variable where the
 229  * type of the next item in the buffer is to be stored. Caller must
 230  * have memory backing this location.
 231  *
 232  * @param number A pointer to a int32_t variable where the number of
 233  * data values in the next item is to be stored. Caller must have
 234  * memory backing this location.
 235  *
 236  * @retval OPAL_SUCCESS Requested info was successfully returned.
 237  * @retval OPAL_ERROR(s) An appropriate error code indicating the
 238  * problem will be returned. This should be handled appropriately by
 239  * the caller.
 240  *
 241  */
 242 typedef int (*opal_dss_peek_next_item_fn_t)(opal_buffer_t *buffer,
 243                                             opal_data_type_t *type,
 244                                             int32_t *number);
 245 
 246 /**
 247  * Unload the data payload from a buffer.
 248  *
 249  * The unload function provides the caller with a pointer to the data
 250  * payload within the buffer and the size of that payload. This allows
 251  * the user to directly access the payload - typically used in the RML
 252  * to unload the payload from the buffer for transmission.
 253  *
 254  * @note This is a destructive operation. While the payload is
 255  * undisturbed, the function will clear the buffer's pointers to the
 256  * payload. Thus, the buffer and the payload are completely separated,
 257  * leaving the caller free to OBJ_RELEASE the buffer.
 258  *
 259  * @param buffer A pointer to the buffer whose payload is to be
 260  * unloaded.
 261  *
 262  * @param payload The address to a void* pointer that is to be loaded
 263  * with the address of the data payload in the buffer.
 264  *
 265  * @param size The size (in bytes) of the data payload in the buffer.
 266  *
 267  * @retval OPAL_SUCCESS The request was succesfully completed.
 268  *
 269  * @retval OPAL_ERROR(s) An appropriate error code indicating the
 270  * problem will be returned. This should be handled appropriately by
 271  * the caller.
 272  *
 273  * @code
 274  * opal_buffer_t *buffer;
 275  * uint8_t *bytes;
 276  * int32_t size;
 277  *
 278  * status_code = opal_dss.unload(buffer, (void**)(&bytes), &size);
 279  * OBJ_RELEASE(buffer);
 280  * @endcode
 281  */
 282 typedef int (*opal_dss_unload_fn_t)(opal_buffer_t *buffer,
 283                                     void **payload,
 284                                     int32_t *size);
 285 
 286 /**
 287  * Load a data payload into a buffer.
 288  *
 289  * The load function allows the caller to replace the payload in a
 290  * buffer with one provided by the caller. If a payload already exists
 291  * in the buffer, the function will "free" the existing data to
 292  * release it, and then replace the data payload with the one provided
 293  * by the caller.
 294  *
 295  * @note The buffer must be allocated in advance via the OBJ_NEW
 296  * function call - failing to do so will cause the load function to
 297  * return an error code.
 298  *
 299  * @note The caller is responsible for pre-packing the provided
 300  * payload - the load function cannot convert to network byte order
 301  * any data contained in the provided payload.
 302  *
 303  * @param buffer A pointer to the buffer into which lthe payload is to
 304  * be loaded.
 305  *
 306  * @param payload A void* pointer to the payload to be loaded into the
 307  * buffer.
 308  *
 309  * @param size The size (in bytes) of the provided payload.
 310  *
 311  * @retval OPAL_SUCCESS The request was successfully completed
 312  *
 313  * @retval OPAL_ERROR(s) An appropriate error code indicating the
 314  * problem will be returned. This should be handled appropriately by
 315  * the caller.
 316  *
 317  * @code
 318  * opal_buffer_t *buffer;
 319  * uint8_t bytes;
 320  * int32_t size;
 321  *
 322  * buffer = OBJ_NEW(opal_buffer_t);
 323  * status_code = opal_dss.load(buffer, (void*)(&bytes), size);
 324  * @endcode
 325  */
 326 typedef int (*opal_dss_load_fn_t)(opal_buffer_t *buffer,
 327                                   void *payload,
 328                                   int32_t size);
 329 
 330 
 331 /**
 332  * Copy a payload from one buffer to another
 333  * This function will append a copy of the payload in one buffer into
 334  * another buffer. If the destination buffer is NOT empty, then the
 335  * type of the two buffers MUST match or else an
 336  * error will be returned. If the destination buffer IS empty, then
 337  * its type will be set to that of the source buffer.
 338  * NOTE: This is NOT a destructive procedure - the
 339  * source buffer's payload will remain intact, as will any pre-existing
 340  * payload in the destination's buffer.
 341  */
 342 typedef int (*opal_dss_copy_payload_fn_t)(opal_buffer_t *dest,
 343                                           opal_buffer_t *src);
 344 
 345 /**
 346  * DSS register function
 347  *
 348  * This function registers variables associated with the DSS system.
 349  */
 350 OPAL_DECLSPEC int opal_dss_register_vars (void);
 351 
 352 /**
 353  * DSS initialization function.
 354  *
 355  * In dynamic libraries, declared objects and functions don't get
 356  * loaded until called. We need to ensure that the opal_dss function
 357  * structure gets loaded, so we provide an "open" call that is
 358  * executed as part of the program startup.
 359  */
 360 OPAL_DECLSPEC int opal_dss_open(void);
 361 
 362 /**
 363  * Copy a data value from one location to another.
 364  *
 365  * Since registered data types can be complex structures, the system
 366  * needs some way to know how to copy the data from one location to
 367  * another (e.g., for storage in the registry). This function, which
 368  * can call other copy functions to build up complex data types, defines
 369  * the method for making a copy of the specified data type.
 370  *
 371  * @param **dest The address of a pointer into which the
 372  * address of the resulting data is to be stored.
 373  *
 374  * @param *src A pointer to the memory location from which the
 375  * data is to be copied.
 376  *
 377  * @param type The type of the data to be copied - must be one of
 378  * the DSS defined data types.
 379  *
 380  * @retval OPAL_SUCCESS The value was successfully copied.
 381  *
 382  * @retval OPAL_ERROR(s) An appropriate error code.
 383  *
 384  */
 385 typedef int (*opal_dss_copy_fn_t)(void **dest, void *src, opal_data_type_t type);
 386 
 387 /**
 388  * Compare two data values.
 389  *
 390  * Since registered data types can be complex structures, the system
 391  * needs some way to know how to compare two data values (e.g., when
 392  * trying to order them in some fashion). This function, which
 393  * can call other compare functions to build up complex data types, defines
 394  * the method for comparing two values of the specified data type.
 395  *
 396  * @retval -1 Indicates first value is greater than second value
 397  * @retval 0 Indicates two values are equal
 398  * @retval +1 Indicates second value is greater than first value
 399  */
 400 typedef int (*opal_dss_compare_fn_t)(const void *value1, const void *value2,
 401                                      opal_data_type_t type);
 402 
 403 
 404 /**
 405  * Print a data value.
 406  *
 407  * Since registered data types can be complex structures, the system
 408  * needs some way to know how to print them (i.e., convert them to a string
 409  * representation).
 410  *
 411  * @retval OPAL_SUCCESS The value was successfully printed.
 412  *
 413  * @retval OPAL_ERROR(s) An appropriate error code.
 414  */
 415 typedef int (*opal_dss_print_fn_t)(char **output, char *prefix, void *src, opal_data_type_t type);
 416 
 417 
 418 /**
 419  * Print a data value to an output stream for debugging purposes
 420  *
 421  * Uses the dss.print command to obtain a string version of the data value
 422  * and prints it to the designated output stream.
 423  *
 424  * @retval OPAL_SUCCESS The value was successfully printed.
 425  *
 426  * @retval OPAL_ERROR(s) An appropriate error code.
 427  */
 428 typedef int (*opal_dss_dump_fn_t)(int output_stream, void *src, opal_data_type_t type);
 429 
 430 /**
 431  * Register a set of data handling functions.
 432  *
 433  *  * This function registers a set of data type functions for a specific
 434  * type.  An integer is returned that should be used a an argument to
 435  * future invocations of opal_dss.pack(), opal_dss.unpack(), opal_dss.copy(),
 436  * and opal_dss.compare, which
 437  * will trigger calls to the appropriate functions.  This
 438  * is most useful when extending the datatypes that the dss can
 439  * handle; pack and unpack functions can nest calls to opal_dss.pack()
 440  * / opal_dss.unpack(), so defining small pack/unpack functions can be
 441  * used recursively to build larger types (e.g., packing/unpacking
 442  * structs can use calls to opal_dss.pack()/unpack() to serialize /
 443  * deserialize individual members). This is likewise true for the copy
 444  * and compare functions.
 445  *
 446  * @param pack_fn [IN] Function pointer to the pack routine
 447  * @param unpack_fn [IN] Function pointer to the unpack routine
 448  * @param copy_fn [IN] Function pointer to copy routine
 449  * @param compare_fn [IN] Function pointer to compare routine
 450  * @param print_fn [IN] Function pointer to print routine
 451  * @param structured [IN] Boolean indicator as to whether or not the data is structured. A true
 452  * value indicates that this data type is always passed via reference (i.e., a pointer to the
 453  * object is passed) as opposed to directly (e.g., the way an int32_t would appear)
 454  * @param name [IN] String name for this pair (mainly for debugging)
 455  * @param type [OUT] Type number for this registration
 456  *
 457  * @returns OPAL_SUCCESS upon success
 458  *
 459  */
 460 typedef int (*opal_dss_register_fn_t)(opal_dss_pack_fn_t pack_fn,
 461                                     opal_dss_unpack_fn_t unpack_fn,
 462                                     opal_dss_copy_fn_t copy_fn,
 463                                     opal_dss_compare_fn_t compare_fn,
 464                                     opal_dss_print_fn_t print_fn,
 465                                     bool structured,
 466                                     const char *name, opal_data_type_t *type);
 467 /*
 468  * This function looks up the string name corresponding to the identified
 469  * data type - used for debugging messages.
 470  */
 471 typedef char* (*opal_dss_lookup_data_type_fn_t)(opal_data_type_t type);
 472 
 473 /*
 474  * Dump the data type list - used for debugging to see what has been registered
 475  */
 476 typedef void (*opal_dss_dump_data_types_fn_t)(int output);
 477 
 478 /* return true if the data type is structured */
 479 typedef bool (*opal_dss_structured_fn_t)(opal_data_type_t type);
 480 
 481 /**
 482  * Base structure for the DSS
 483  *
 484  * Base module structure for the DSS - presents the required function
 485  * pointers to the calling interface.
 486  */
 487 struct opal_dss_t {
 488     opal_dss_pack_fn_t              pack;
 489     opal_dss_unpack_fn_t            unpack;
 490     opal_dss_copy_fn_t              copy;
 491     opal_dss_compare_fn_t           compare;
 492     opal_dss_print_fn_t             print;
 493     opal_dss_structured_fn_t        structured;
 494     opal_dss_peek_next_item_fn_t    peek;
 495     opal_dss_unload_fn_t            unload;
 496     opal_dss_load_fn_t              load;
 497     opal_dss_copy_payload_fn_t      copy_payload;
 498     opal_dss_register_fn_t          register_type;
 499     opal_dss_lookup_data_type_fn_t  lookup_data_type;
 500     opal_dss_dump_data_types_fn_t   dump_data_types;
 501     opal_dss_dump_fn_t              dump;
 502 };
 503 typedef struct opal_dss_t opal_dss_t;
 504 
 505 OPAL_DECLSPEC extern opal_dss_t opal_dss;  /* holds dss function pointers */
 506 
 507 END_C_DECLS
 508 
 509 #endif /* OPAL_DSS_H */

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