![]() |
|
|||
File indexing completed on 2025-02-22 10:47:24
0001 /* -*- Mode: C; c-basic-offset:4 ; -*- */ 0002 /* 0003 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana 0004 * University Research and Technology 0005 * Corporation. All rights reserved. 0006 * Copyright (c) 2004-2005 The University of Tennessee and The University 0007 * of Tennessee Research Foundation. All rights 0008 * reserved. 0009 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 0010 * University of Stuttgart. All rights reserved. 0011 * Copyright (c) 2004-2005 The Regents of the University of California. 0012 * All rights reserved. 0013 * Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved. 0014 * Copyright (c) 2013-2020 Intel, Inc. All rights reserved. 0015 * Copyright (c) 2015 Research Organization for Information Science 0016 * and Technology (RIST). All rights reserved. 0017 * Copyright (c) 2016 Mellanox Technologies, Inc. 0018 * All rights reserved. 0019 * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. 0020 * $COPYRIGHT$ 0021 * 0022 * Additional copyrights may follow 0023 * 0024 * $HEADER$ 0025 */ 0026 /** 0027 * @file 0028 * 0029 * Data packing subsystem. 0030 */ 0031 0032 #ifndef PMIX_BFROP_H_ 0033 #define PMIX_BFROP_H_ 0034 0035 #include "src/include/pmix_config.h" 0036 #include "pmix_common.h" 0037 #include "src/include/pmix_types.h" 0038 0039 #include "src/mca/mca.h" 0040 0041 #include "bfrops_types.h" 0042 0043 BEGIN_C_DECLS 0044 0045 /* The overall objective of this framework is to provide seamless 0046 * cross-version support for communications by allowing a process 0047 * to communicate with a peer: 0048 * 0049 * (a) using a different version of the buffer operations. We are 0050 * allowing changes in the structure compositions and/or data 0051 * type definitions between versions. This specifically affects 0052 * our ability to pack/unpack across versions. 0053 * 0054 * (b) using a different buffer type (described vs non-described). 0055 * This resolves conflicts when one side was compiled with a 0056 * debug option, while the other side has been "optimized". 0057 * 0058 * This is a mult-select framework - i.e., multiple components 0059 * are selected and "active" at the same time. The intent is 0060 * to have one component for each data type variation, with the 0061 * expectation that the community will do its best not to revise 0062 * existing data type definitions. Thus, new variations should be 0063 * rare, and only a few components will exist. 0064 * 0065 * The framework itself reflects the fact that any given peer 0066 * will utilize only one variation of the data type definitions. 0067 * Thus, once a peer is identified, it will pass its version string 0068 * to this framework's "assign_module" function, which will then 0069 * pass it to each component until one returns a module capable of 0070 * processing the given version. This module is then "attached" to 0071 * the pmix_peer_t object so it can be used for all subsequent 0072 * communication to/from that peer. 0073 * 0074 * Buffer type is included in the buffer metadata. Unfortunately, 0075 * the metadata is not communicated at each exchange. Thus, the 0076 * peers will indicate during the connection handshake the type 0077 * of buffer they will use for all subsequent communications. The 0078 * peer must then utilize that same buffer type for all messages 0079 * sent to that remote proc, so we provide new macros for creating 0080 * and constructing buffers that ensures the correct buffer type 0081 * is marked. 0082 * 0083 * Accordingly, there are two levels of APIs defined for this 0084 * framework: 0085 * 0086 * (a) component level - these allow for init/finalize of the 0087 * component, and assignment of a module to a given peer 0088 * based on the version that peer is using 0089 * 0090 * (b) module level - implement pack/unpack/copy/recv/etc. of 0091 * the various datatypes. Note that the module only needs 0092 * to provide those functions that differ from the base 0093 * functions - they don't need to duplicate all that code! 0094 */ 0095 0096 /* The following functions are exposed to the user - they 0097 * therefore are implemented in the bfrops/base functions 0098 * as wrappers to the real functions. 0099 * 0100 * NOTE: THESE FUNCTIONS ARE NOT TO BE USED INTERNALLY - 0101 * USE THE MACROS INSTEAD 0102 */ 0103 bool pmix_value_cmp(pmix_value_t *p, pmix_value_t *p1); 0104 0105 /**** MODULE INTERFACE DEFINITION ****/ 0106 0107 /* initialize the module - the module is expected 0108 * to register its datatype functions at this time */ 0109 typedef pmix_status_t (*pmix_bfrop_init_fn_t)(void); 0110 0111 /* finalize the module */ 0112 typedef void (*pmix_bfrop_finalize_fn_t)(void); 0113 0114 /** 0115 * Pack one or more values into a buffer. 0116 * 0117 * The pack function packs one or more values of a specified type into 0118 * the specified buffer. The buffer must have already been 0119 * initialized via an PMIX_NEW or PMIX_CONSTRUCT call - otherwise, the 0120 * pack_value function will return an error. Providing an unsupported 0121 * type flag will likewise be reported as an error. 0122 * 0123 * Note that any data to be packed that is not hard type cast (i.e., 0124 * not type cast to a specific size) may lose precision when unpacked 0125 * by a non-homogeneous recipient. The BFROP will do its best to deal 0126 * with heterogeneity issues between the packer and unpacker in such 0127 * cases. Sending a number larger than can be handled by the recipient 0128 * will return an error code (generated by the BFROP upon unpacking) - 0129 * the BFROP cannot detect such errors during packing. 0130 * 0131 * @param *buffer A pointer to the buffer into which the value is to 0132 * be packed. 0133 * 0134 * @param *src A void* pointer to the data that is to be packed. This 0135 * is interpreted as a pointer to an array of that data type containing 0136 * length num_values. Note that strings are of data type char*, and so 0137 * they are to be passed as (char **) - i.e., the caller must 0138 * pass the address of the pointer to the string as the void*. This 0139 * allows the BFROP to use a single interface function, but still allow 0140 * the caller to pass multiple strings in a single call. 0141 * 0142 * @param num_values An int32_t indicating the number of values that are 0143 * to be packed, beginning at the location pointed to by src. A string 0144 * value is counted as a single value regardless of length. The values 0145 * must be contiguous in memory. Arrays of pointers (e.g., string 0146 * arrays) should be contiguous, although (obviously) the data pointed 0147 * to need not be contiguous across array entries. 0148 * 0149 * @param type The type of the data to be packed - must be one of the 0150 * PMIX defined data types. 0151 * 0152 * @retval PMIX_SUCCESS The data was packed as requested. 0153 * 0154 * @retval PMIX_ERROR(s) An appropriate PMIX error code indicating the 0155 * problem encountered. This error code should be handled 0156 * appropriately. 0157 * 0158 * @code 0159 * pmix_buffer_t *buffer; 0160 * int32_t src; 0161 * 0162 * status_code = pmix_bfrop.pack(buffer, &src, 1, PMIX_INT32); 0163 * @endcode 0164 */ 0165 typedef pmix_status_t (*pmix_bfrop_pack_fn_t)(pmix_buffer_t *buffer, const void *src, 0166 int32_t num_values, pmix_data_type_t type); 0167 0168 /** 0169 * Unpack values from a buffer. 0170 * 0171 * The unpack function unpacks the next value (or values) of a 0172 * specified type from the specified buffer. 0173 * 0174 * The buffer must have already been initialized via an PMIX_NEW or 0175 * PMIX_CONSTRUCT call (and assumedly filled with some data) - 0176 * otherwise, the unpack_value function will return an 0177 * error. Providing an unsupported type flag will likewise be reported 0178 * as an error, as will specifying a data type that DOES NOT match the 0179 * type of the next item in the buffer. An attempt to read beyond the 0180 * end of the stored data held in the buffer will also return an 0181 * error. 0182 * 0183 * NOTE: it is possible for the buffer to be corrupted and that 0184 * the BFROP will *think* there is a proper variable type at the 0185 * beginning of an unpack region - but that the value is bogus (e.g., just 0186 * a byte field in a string array that so happens to have a value that 0187 * matches the specified data type flag). Therefore, the data type error check 0188 * is NOT completely safe. This is true for ALL unpack functions. 0189 * 0190 * Warning: The caller is responsible for providing adequate memory 0191 * storage for the requested data. As noted below, the user 0192 * must provide a parameter indicating the maximum number of values that 0193 * can be unpacked into the allocated memory. If more values exist in the 0194 * buffer than can fit into the memory storage, then the bfrop will unpack 0195 * what it can fit into that location and return an error code indicating 0196 * that the buffer was only partially unpacked. 0197 * 0198 * Note that any data that was not hard type cast (i.e., not type cast 0199 * to a specific size) when packed may lose precision when unpacked by 0200 * a non-homogeneous recipient. The BFROP will do its best to deal with 0201 * heterogeneity issues between the packer and unpacker in such 0202 * cases. Sending a number larger than can be handled by the recipient 0203 * will return an error code generated by the BFROP upon unpacking - the 0204 * BFROP cannot detect such errors during packing. 0205 * 0206 * @param *buffer A pointer to the buffer from which the value will be 0207 * extracted. 0208 * 0209 * @param *dest A void* pointer to the memory location into which the 0210 * data is to be stored. Note that these values will be stored 0211 * contiguously in memory. For strings, this pointer must be to (char 0212 * **) to provide a means of supporting multiple string 0213 * operations. The BFROP unpack function will allocate memory for each 0214 * string in the array - the caller must only provide adequate memory 0215 * for the array of pointers. 0216 * 0217 * @param type The type of the data to be unpacked - must be one of 0218 * the BFROP defined data types. 0219 * 0220 * @retval *max_num_values The number of values actually unpacked. In 0221 * most cases, this should match the maximum number provided in the 0222 * parameters - but in no case will it exceed the value of this 0223 * parameter. Note that if you unpack fewer values than are actually 0224 * available, the buffer will be in an unpackable state - the bfrop will 0225 * return an error code to warn of this condition. 0226 * 0227 * @note The unpack function will return the actual number of values 0228 * unpacked in this location. 0229 * 0230 * @retval PMIX_SUCCESS The next item in the buffer was successfully 0231 * unpacked. 0232 * 0233 * @retval PMIX_ERROR(s) The unpack function returns an error code 0234 * under one of several conditions: (a) the number of values in the 0235 * item exceeds the max num provided by the caller; (b) the type of 0236 * the next item in the buffer does not match the type specified by 0237 * the caller; or (c) the unpack failed due to either an error in the 0238 * buffer or an attempt to read past the end of the buffer. 0239 * 0240 * @code 0241 * pmix_buffer_t *buffer; 0242 * int32_t dest; 0243 * char **string_array; 0244 * int32_t num_values; 0245 * 0246 * num_values = 1; 0247 * status_code = pmix_bfrop.unpack(buffer, (void*)&dest, &num_values, PMIX_INT32); 0248 * 0249 * num_values = 5; 0250 * string_array = malloc(num_values*sizeof(char *)); 0251 * status_code = pmix_bfrop.unpack(buffer, (void*)(string_array), &num_values, PMIX_STRING); 0252 * 0253 * @endcode 0254 */ 0255 typedef pmix_status_t (*pmix_bfrop_unpack_fn_t)(pmix_buffer_t *buffer, void *dest, 0256 int32_t *max_num_values, pmix_data_type_t type); 0257 /** 0258 * Copy a payload from one buffer to another 0259 * This function will append a copy of the payload in one buffer into 0260 * another buffer. If the destination buffer is NOT empty, then the 0261 * type of the two buffers MUST match or else an 0262 * error will be returned. If the destination buffer IS empty, then 0263 * its type will be set to that of the source buffer. 0264 * NOTE: This is NOT a destructive procedure - the 0265 * source buffer's payload will remain intact, as will any pre-existing 0266 * payload in the destination's buffer. 0267 */ 0268 typedef pmix_status_t (*pmix_bfrop_copy_payload_fn_t)(pmix_buffer_t *dest, pmix_buffer_t *src); 0269 0270 /** 0271 * Copy a data value from one location to another. 0272 * 0273 * Since registered data types can be complex structures, the system 0274 * needs some way to know how to copy the data from one location to 0275 * another (e.g., for storage in the registry). This function, which 0276 * can call other copy functions to build up complex data types, defines 0277 * the method for making a copy of the specified data type. 0278 * 0279 * @param **dest The address of a pointer into which the 0280 * address of the resulting data is to be stored. 0281 * 0282 * @param *src A pointer to the memory location from which the 0283 * data is to be copied. 0284 * 0285 * @param type The type of the data to be copied - must be one of 0286 * the BFROP defined data types. 0287 * 0288 * @retval PMIX_SUCCESS The value was successfully copied. 0289 * 0290 * @retval PMIX_ERROR(s) An appropriate error code. 0291 * 0292 */ 0293 typedef pmix_status_t (*pmix_bfrop_copy_fn_t)(void **dest, void *src, pmix_data_type_t type); 0294 0295 /** 0296 * Print a data value. 0297 * 0298 * Since registered data types can be complex structures, the system 0299 * needs some way to know how to print them (i.e., convert them to a string 0300 * representation). Provided for debug purposes. 0301 * 0302 * @retval PMIX_SUCCESS The value was successfully printed. 0303 * 0304 * @retval PMIX_ERROR(s) An appropriate error code. 0305 */ 0306 typedef pmix_status_t (*pmix_bfrop_print_fn_t)(char **output, char *prefix, void *src, 0307 pmix_data_type_t type); 0308 0309 /** 0310 * Transfer a value from one pmix_value_t to another. Ordinarily, 0311 * this would be executed as a base function. However, it is 0312 * possible that future versions may add new data types, and 0313 * thus the xfer function may differ 0314 * 0315 * @retval PMIX_SUCCESS The value was successfully transferred 0316 * 0317 * @retval PMIX_ERROR(s) An appropriate error code 0318 */ 0319 typedef pmix_status_t (*pmix_bfrop_value_xfer_fn_t)(pmix_value_t *dest, const pmix_value_t *src); 0320 0321 /** 0322 * Load data into a pmix_value_t object. Again, this is provided 0323 * as a component function to support different data types 0324 */ 0325 typedef void (*pmix_bfrop_value_load_fn_t)(pmix_value_t *v, const void *data, 0326 pmix_data_type_t type); 0327 0328 /** 0329 * Unload data from a pmix_value_t object 0330 * 0331 * @retval PMIX_SUCCESS The value was successfully unloaded 0332 * 0333 * @retval PMIX_ERROR(s) An appropriate error code 0334 */ 0335 typedef pmix_status_t (*pmix_bfrop_value_unload_fn_t)(pmix_value_t *kv, void **data, size_t *sz); 0336 0337 /** 0338 * Compare two pmix_value_t structs 0339 */ 0340 typedef pmix_value_cmp_t (*pmix_bfrop_value_cmp_fn_t)(pmix_value_t *p1, pmix_value_t *p2); 0341 0342 /* return the string name of a provided data type */ 0343 typedef const char *(*pmix_bfrop_data_type_string_fn_t)(pmix_data_type_t type); 0344 0345 /** 0346 * Base structure for a BFROP module 0347 */ 0348 typedef struct { 0349 char *version; 0350 pmix_bfrop_init_fn_t init; 0351 pmix_bfrop_finalize_fn_t finalize; 0352 pmix_bfrop_pack_fn_t pack; 0353 pmix_bfrop_unpack_fn_t unpack; 0354 pmix_bfrop_copy_fn_t copy; 0355 pmix_bfrop_print_fn_t print; 0356 pmix_bfrop_copy_payload_fn_t copy_payload; 0357 pmix_bfrop_value_xfer_fn_t value_xfer; 0358 pmix_bfrop_value_load_fn_t value_load; 0359 pmix_bfrop_value_unload_fn_t value_unload; 0360 pmix_bfrop_value_cmp_fn_t value_cmp; 0361 pmix_bfrop_data_type_string_fn_t data_type_string; 0362 } pmix_bfrops_module_t; 0363 0364 /* get a list of available versions - caller must free results 0365 * when done */ 0366 PMIX_EXPORT char *pmix_bfrops_base_get_available_modules(void); 0367 0368 /* Select a bfrops module for a given version */ 0369 PMIX_EXPORT pmix_bfrops_module_t *pmix_bfrops_base_assign_module(const char *version); 0370 0371 /* provide a backdoor to access the framework debug output */ 0372 PMIX_EXPORT extern int pmix_bfrops_base_output; 0373 0374 /* MACROS FOR EXECUTING BFROPS FUNCTIONS */ 0375 #define PMIX_BFROPS_ASSIGN_TYPE(p, b) (b)->type = (p)->nptr->compat.type 0376 0377 #define PMIX_BFROPS_PACK(r, p, b, s, n, t) \ 0378 do { \ 0379 pmix_output_verbose(2, pmix_bfrops_base_output, "[%s:%d] PACK version %s type %s", \ 0380 __FILE__, __LINE__, (p)->nptr->compat.bfrops->version, \ 0381 PMIx_Data_type_string(t)); \ 0382 if (PMIX_BFROP_BUFFER_UNDEF == (b)->type) { \ 0383 (b)->type = (p)->nptr->compat.type; \ 0384 (r) = (p)->nptr->compat.bfrops->pack(b, s, n, t); \ 0385 } else if ((b)->type == (p)->nptr->compat.type) { \ 0386 (r) = (p)->nptr->compat.bfrops->pack(b, s, n, t); \ 0387 } else { \ 0388 (r) = PMIX_ERR_PACK_MISMATCH; \ 0389 } \ 0390 } while (0) 0391 0392 #define PMIX_BFROPS_UNPACK(r, p, b, d, m, t) \ 0393 do { \ 0394 pmix_output_verbose(2, pmix_bfrops_base_output, "[%s:%d] UNPACK version %s type %s", \ 0395 __FILE__, __LINE__, (p)->nptr->compat.bfrops->version, \ 0396 PMIx_Data_type_string(t)); \ 0397 if ((b)->type == (p)->nptr->compat.type) { \ 0398 (r) = (p)->nptr->compat.bfrops->unpack(b, d, m, t); \ 0399 } else { \ 0400 (r) = PMIX_ERR_UNPACK_FAILURE; \ 0401 } \ 0402 } while (0) 0403 0404 #define PMIX_BFROPS_COPY(r, p, d, s, t) (r) = (p)->nptr->compat.bfrops->copy(d, s, t) 0405 0406 #define PMIX_BFROPS_PRINT(r, p, o, pr, s, t) (r) = (p)->nptr->compat.bfrops->print(o, pr, s, t) 0407 0408 #define PMIX_BFROPS_COPY_PAYLOAD(r, p, d, s) \ 0409 do { \ 0410 if (PMIX_BFROP_BUFFER_UNDEF == (d)->type) { \ 0411 (d)->type = (p)->nptr->compat.type; \ 0412 (r) = (p)->nptr->compat.bfrops->copy_payload(d, s); \ 0413 } else if ((d)->type == (p)->nptr->compat.type) { \ 0414 (r) = (p)->nptr->compat.bfrops->copy_payload(d, s); \ 0415 } else { \ 0416 (r) = PMIX_ERR_PACK_MISMATCH; \ 0417 } \ 0418 } while (0) 0419 0420 #define PMIX_BFROPS_VALUE_XFER(r, p, d, s) (r) = (p)->nptr->compat.bfrops->value_xfer(d, s) 0421 0422 #define PMIX_BFROPS_VALUE_LOAD(p, v, d, t) (p)->nptr->compat.bfrops->value_load(v, d, t) 0423 0424 #define PMIX_BFROPS_VALUE_UNLOAD(r, p, k, d, s) \ 0425 (r) = (p)->nptr->compat.bfrops->value_unload(k, , d, s) 0426 0427 #define PMIX_BFROPS_VALUE_CMP(r, p, q, s) (r) = (p)->nptr->compat.bfrops->value_cmp(q, s) 0428 0429 #define PMIX_BFROPS_REGISTER(r, p, n, t, pk, u, c, pr) \ 0430 (r) = (p)->nptr->compat.bfrops->register_type(n, t, pk, u, c, pr) 0431 0432 #define PMIX_BFROPS_PRINT_TYPE(c, p, t) (c) = (p)->nptr->compat.bfrops->data_type_string(t) 0433 0434 /**** COMPONENT STRUCTURE DEFINITION ****/ 0435 0436 /* define a component-level API for getting a module */ 0437 typedef pmix_bfrops_module_t *(*pmix_bfrop_base_component_assign_module_fn_t)(void); 0438 0439 /* 0440 * the standard component data structure 0441 */ 0442 struct pmix_bfrops_base_component_t { 0443 pmix_mca_base_component_t base; 0444 int priority; 0445 pmix_pointer_array_t types; 0446 pmix_bfrop_base_component_assign_module_fn_t assign_module; 0447 }; 0448 typedef struct pmix_bfrops_base_component_t pmix_bfrops_base_component_t; 0449 0450 /* 0451 * Macro for use in components that are of type bfrops 0452 */ 0453 #define PMIX_BFROPS_BASE_VERSION_1_0_0 PMIX_MCA_BASE_VERSION_1_0_0("bfrops", 1, 0, 0) 0454 0455 END_C_DECLS 0456 0457 #endif /* PMIX_BFROP_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |