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
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.
15
* Additional copyrights may follow
22
* Data packing subsystem.
28
#include "orte_config.h"
30
#include "orte/orte_constants.h"
31
#include "orte/orte_types.h"
33
#include "orte/dss/dss_types.h"
35
#if defined(c_plusplus) || defined(__cplusplus)
39
* Top-level itnerface function to pack one or more values into a
42
* The pack function packs one or more values of a specified type into
43
* the specified buffer. The buffer must have already been
44
* initialized via an OBJ_NEW or OBJ_CONSTRUCT call - otherwise, the
45
* pack_value function will return an error. Providing an unsupported
46
* type flag will likewise be reported as an error.
48
* Note that any data to be packed that is not hard type cast (i.e.,
49
* not type cast to a specific size) may lose precision when unpacked
50
* by a non-homogeneous recipient. The DSS will do its best to deal
51
* with heterogeneity issues between the packer and unpacker in such
52
* cases. Sending a number larger than can be handled by the recipient
53
* will return an error code (generated by the DSS upon unpacking) via
54
* the RML upon transmission - the DSS cannot detect such errors
57
* @param *buffer A pointer to the buffer into which the value is to
60
* @param *src A void* pointer to the data that is to be packed. Note
61
* that strings are to be passed as (char **) - i.e., the caller must
62
* pass the address of the pointer to the string as the void*. This
63
* allows the DSS to use a single interface function, but still allow
64
* the caller to pass multiple strings in a single call.
66
* @param num A size_t value indicating the number of values that are
67
* to be packed, beginning at the location pointed to by src. A string
68
* value is counted as a single value regardless of length. The values
69
* must be contiguous in memory. Arrays of pointers (e.g., string
70
* arrays) should be contiguous, although (obviously) the data pointed
71
* to need not be contiguous across array entries.
73
* @param type The type of the data to be packed - must be one of the
74
* DSS defined data types.
76
* @retval ORTE_SUCCESS The data was packed as requested.
78
* @retval ORTE_ERROR(s) An appropriate ORTE error code indicating the
79
* problem encountered. This error code should be handled
83
* orte_buffer_t *buffer;
86
* status_code = orte_dss.pack(buffer, &src, 1, ORTE_INT32);
89
typedef int (*orte_dss_pack_fn_t)(orte_buffer_t *buffer, void *src,
91
orte_data_type_t type);
94
* Unpack values from a buffer.
96
* The unpack function unpacks the next value (or values) of a
97
* specified type from the specified buffer.
99
* The buffer must have already been initialized via an OBJ_NEW or
100
* OBJ_CONSTRUCT call (and assumedly filled with some data) -
101
* otherwise, the unpack_value function will return an
102
* error. Providing an unsupported type flag will likewise be reported
103
* as an error, as will specifying a data type that DOES NOT match the
104
* type of the next item in the buffer. An attempt to read beyond the
105
* end of the stored data held in the buffer will also return an
108
* NOTE: it is possible for the buffer to be corrupted and that
109
* the DSS will *think* there is a proper variable type at the
110
* beginning of an unpack region - but that the value is bogus (e.g., just
111
* a byte field in a string array that so happens to have a value that
112
* matches the specified data type flag). Therefore, the data type error check
113
* is NOT completely safe. This is true for ALL unpack functions.
116
* Unpacking values is a "destructive" process - i.e., the values are
117
* removed from the buffer, thus reducing the buffer size. It is
118
* therefore not possible for the caller to re-unpack a value from the
121
* Warning: The caller is responsible for providing adequate memory
122
* storage for the requested data. The orte_dss_peek() function is
123
* provided to assist in meeting this requirement. As noted below, the user
124
* must provide a parameter indicating the maximum number of values that
125
* can be unpacked into the allocated memory. If more values exist in the
126
* buffer than can fit into the memory storage, then the dss will unpack
127
* what it can fit into that location and return an error code indicating
128
* that the buffer was only partially unpacked.
130
* Note that any data that was not hard type cast (i.e., not type cast
131
* to a specific size) when packed may lose precision when unpacked by
132
* a non-homogeneous recipient. The DSS will do its best to deal with
133
* heterogeneity issues between the packer and unpacker in such
134
* cases. Sending a number larger than can be handled by the recipient
135
* will return an error code (generated by the DSS upon unpacking) via
136
* the RML upon transmission - the DSS cannot detect such errors
139
* @param *buffer A pointer to the buffer from which the value will be
142
* @param *dest A void* pointer to the memory location into which the
143
* data is to be stored. Note that these values will be stored
144
* contiguously in memory. For strings, this pointer must be to (char
145
* **) to provide a means of supporting multiple string
146
* operations. The DSS unpack function will allocate memory for each
147
* string in the array - the caller must only provide adequate memory
148
* for the array of pointers.
150
* @param *num A pointer to a size_t value indicating the maximum
151
* number of values that are to be unpacked, beginning at the location
152
* pointed to by src. This is provided to help protect the caller from
153
* memory overrun. Note that a string
154
* value is counted as a single value regardless of length.
156
* @note The unpack function will return the actual number of values
157
* unpacked in this location.
159
* @param type The type of the data to be unpacked - must be one of
160
* the DSS defined data types.
162
* @retval *max_num_values The number of values actually unpacked. In
163
* most cases, this should match the maximum number provided in the
164
* parameters - but in no case will it exceed the value of this
165
* parameter. Note that if you unpack fewer values than are actually
166
* available, the buffer will be in an unpackable state - the dss will
167
* return an error code to warn of this condition.
169
* @retval ORTE_SUCCESS The next item in the buffer was successfully
172
* @retval ORTE_ERROR(s) The unpack function returns an error code
173
* under one of several conditions: (a) the number of values in the
174
* item exceeds the max num provided by the caller; (b) the type of
175
* the next item in the buffer does not match the type specified by
176
* the caller; or (c) the unpack failed due to either an error in the
177
* buffer or an attempt to read past the end of the buffer.
180
* orte_buffer_t *buffer;
182
* char **string_array;
186
* status_code = orte_dss.unpack(buffer, (void*)&dest, &num_values, ORTE_INT32);
189
* string_array = malloc(num_values*sizeof(char *));
190
* status_code = orte_dss.unpack(buffer, (void*)(string_array), &num_values, ORTE_STRING);
194
typedef int (*orte_dss_unpack_fn_t)(orte_buffer_t *buffer, void *dest,
195
size_t *max_num_values,
196
orte_data_type_t type);
199
* Get the type and number of values of the next item in the buffer.
201
* The peek function looks at the next item in the buffer and returns
202
* both its type and the number of values in the item. This is a
203
* non-destructive function call that does not disturb the buffer, so
204
* it can be called multiple times if desired.
206
* @param buffer A pointer to the buffer in question.
208
* @param type A pointer to an orte_data_type_t variable where the
209
* type of the next item in the buffer is to be stored. Caller must
210
* have memory backing this location.
212
* @param number A pointer to a size_t variable where the number of
213
* data values in the next item is to be stored. Caller must have
214
* memory backing this location.
216
* @retval ORTE_SUCCESS Requested info was successfully returned.
217
* @retval ORTE_ERROR(s) An appropriate error code indicating the
218
* problem will be returned. This should be handled appropriately by
222
typedef int (*orte_dss_peek_next_item_fn_t)(orte_buffer_t *buffer,
223
orte_data_type_t *type,
227
* Unload the data payload from a buffer.
229
* The unload function provides the caller with a pointer to the data
230
* payload within the buffer and the size of that payload. This allows
231
* the user to directly access the payload - typically used in the RML
232
* to unload the payload from the buffer for transmission.
234
* @note This is a destructive operation. While the payload is
235
* undisturbed, the function will clear the buffer's pointers to the
236
* payload. Thus, the buffer and the payload are completely separated,
237
* leaving the caller free to OBJ_RELEASE the buffer.
239
* @param buffer A pointer to the buffer whose payload is to be
242
* @param payload The address to a void* pointer that is to be loaded
243
* with the address of the data payload in the buffer.
245
* @param size The size (in bytes) of the data payload in the buffer.
247
* @retval ORTE_SUCCESS The request was succesfully completed.
249
* @retval ORTE_ERROR(s) An appropriate error code indicating the
250
* problem will be returned. This should be handled appropriately by
254
* orte_buffer_t *buffer;
258
* status_code = orte_dss.unload(buffer, (void**)(&bytes), &size);
259
* OBJ_RELEASE(buffer);
262
typedef int (*orte_dss_unload_fn_t)(orte_buffer_t *buffer,
267
* Load a data payload into a buffer.
269
* The load function allows the caller to replace the payload in a
270
* buffer with one provided by the caller. If a payload already exists
271
* in the buffer, the function will "free" the existing data to
272
* release it, and then replace the data payload with the one provided
275
* @note The buffer must be allocated in advance via the OBJ_NEW
276
* function call - failing to do so will cause the load function to
277
* return an error code.
279
* @note The caller is responsible for pre-packing the provided
280
* payload - the load function cannot convert to network byte order
281
* any data contained in the provided payload.
283
* @param buffer A pointer to the buffer into which lthe payload is to
286
* @param payload A void* pointer to the payload to be loaded into the
289
* @param size The size (in bytes) of the provided payload.
291
* @retval ORTE_SUCCESS The request was successfully completed
293
* @retval ORTE_ERROR(s) An appropriate error code indicating the
294
* problem will be returned. This should be handled appropriately by
298
* orte_buffer_t *buffer;
302
* buffer = OBJ_NEW(orte_buffer_t);
303
* status_code = orte_dss.load(buffer, (void*)(&bytes), size);
306
typedef int (*orte_dss_load_fn_t)(orte_buffer_t *buffer,
312
* DSS initialization function.
314
* In dynamic libraries, declared objects and functions don't get
315
* loaded until called. We need to ensure that the orte_dss function
316
* structure gets loaded, so we provide an "open" call that is
317
* executed as part of the program startup.
319
OMPI_DECLSPEC int orte_dss_open(void);
322
* DSS finalize function
324
OMPI_DECLSPEC int orte_dss_close(void);
328
* Copy a data value from one location to another.
330
* Since registered data types can be complex structures, the system
331
* needs some way to know how to copy the data from one location to
332
* another (e.g., for storage in the registry). This function, which
333
* can call other copy functions to build up complex data types, defines
334
* the method for making a copy of the specified data type.
336
* @param **dest The address of a pointer into which the
337
* address of the resulting data is to be stored.
339
* @param *src A pointer to the memory location from which the
340
* data is to be copied.
342
* @param type The type of the data to be copied - must be one of
343
* the DSS defined data types.
345
* @retval ORTE_SUCCESS The value was successfully copied.
347
* @retval ORTE_ERROR(s) An appropriate error code.
350
typedef int (*orte_dss_copy_fn_t)(void **dest, void *src, orte_data_type_t type);
353
* Compare two data values.
355
* Since registered data types can be complex structures, the system
356
* needs some way to know how to compare two data values (e.g., when
357
* trying to order them in some fashion). This function, which
358
* can call other compare functions to build up complex data types, defines
359
* the method for comparing two values of the specified data type.
361
* @retval -1 Indicates first value is greater than second value
362
* @retval 0 Indicates two values are equal
363
* @retval +1 Indicates second value is greater than first value
365
typedef int (*orte_dss_compare_fn_t)(void *value1, void *value2,
366
orte_data_type_t type);
370
* Compute size of data value.
372
* Since registered data types can be complex structures, the system
373
* needs some way to compute its size. Some of these types, however, involve
374
* variable amounts of storage (e.g., a string!). Hence, a pointer to the
375
* actual object being "sized" needs to be passed as well.
377
* @param size Address of a size_t value where the size of the data value
378
* (in bytes) will be stored - set to zero in event of error.
380
* @param *src A pointer to the memory location of the data object. It is okay
381
* for this to be NULL - if NULL, the function must return the size of the object
382
* itself, not including any data contained in its fields.
384
* @param type The type of the data value - must be one of
385
* the DSS defined data types or an error will be returned.
387
* @retval ORTE_SUCCESS The value was successfully copied.
389
* @retval ORTE_ERROR(s) An appropriate error code.
391
typedef int (*orte_dss_size_fn_t)(size_t *size, void *src, orte_data_type_t type);
395
* Print a data value.
397
* Since registered data types can be complex structures, the system
398
* needs some way to know how to print them (i.e., convert them to a string
401
* @retval ORTE_SUCCESS The value was successfully printed.
403
* @retval ORTE_ERROR(s) An appropriate error code.
405
typedef int (*orte_dss_print_fn_t)(char **output, char *prefix, void *src, orte_data_type_t type);
411
* Since the data values are stored in an opaque manner, the system needs
412
* a function by which it can set the data value to a specific value. This
413
* is the equivalent to a C++ access function.
415
* NOTE: this function does NOT allocate any memory. It only sets the value pointer
416
* and type to the specified location and type. Use "copy" if you want dynamic allocation
419
* @retval ORTE_SUCCESS The value was successfully stored
421
* @retval ORTE_ERROR(s) An appropriate error code.
423
typedef int (*orte_dss_set_fn_t)(orte_data_value_t *value, void *new_value, orte_data_type_t type);
428
* Since the data values are stored in an opaque manner, the system needs
429
* a function by which it can get the data value from within the data_value object. This
430
* is the equivalent to a C++ access function.
432
* NOTE: this function does NOT allocate any memory. It simply points the "data" location
433
* to that of the value, after ensuring that the value's type matches the specified one.
434
* Use "copy" if you want dynamic allocation of memory.
436
* @retval ORTE_SUCCESS The value was successfully retrieved
438
* @retval ORTE_ERROR(s) An appropriate error code - usually caused by the specified type
439
* not matching the data type within the stored object.
441
typedef int (*orte_dss_get_fn_t)(void **data, orte_data_value_t *value, orte_data_type_t type);
444
* Perform an arithemetic operation on a data value
446
* Since the data values are stored in an opaque manner, the system needs
447
* a function by which it can manipulate the data value within the data_value object. This
448
* is the equivalent to a C++ access function.
450
* @retval ORTE_SUCCESS The value was successfully retrieved
452
* @retval ORTE_ERROR(s) An appropriate error code - usually caused by the specified type
453
* not matching the data type within the stored object.
455
typedef int (*orte_dss_arith_fn_t)(orte_data_value_t *value, void *operand, orte_dss_arith_op_t operation, orte_data_type_t type);
458
* Increment a data value
460
* Since the data values are stored in an opaque manner, the system needs
461
* a function by which it can manipulate the data value within the data_value object. This
462
* is the equivalent to a C++ access function.
464
* @retval ORTE_SUCCESS The value was successfully retrieved
466
* @retval ORTE_ERROR(s) An appropriate error code.
468
typedef int (*orte_dss_increment_fn_t)(orte_data_value_t *value);
471
* Decrement a data value
473
* Since the data values are stored in an opaque manner, the system needs
474
* a function by which it can manipulate the data value within the data_value object. This
475
* is the equivalent to a C++ access function.
477
* @retval ORTE_SUCCESS The value was successfully retrieved
479
* @retval ORTE_ERROR(s) An appropriate error code.
481
typedef int (*orte_dss_decrement_fn_t)(orte_data_value_t *value);
484
* Release the storage used by a data value
486
* Since the data values are stored in an opaque manner, the system needs
487
* a function by which it can release the storage associated with a value
488
* stored in a data value object.
490
typedef void (*orte_dss_release_fn_t)(orte_data_value_t *value);
493
* Register a set of data handling functions.
495
* * This function registers a set of data type functions for a specific
496
* type. An integer is returned that should be used a an argument to
497
* future invocations of orte_dss.pack(), orte_dss.unpack(), orte_dss.copy(),
498
* and orte_dss.compare, which
499
* will trigger calls to the appropriate functions. This
500
* is most useful when extending the datatypes that the dss can
501
* handle; pack and unpack functions can nest calls to orte_dss.pack()
502
* / orte_dss.unpack(), so defining small pack/unpack functions can be
503
* used recursively to build larger types (e.g., packing/unpacking
504
* structs can use calls to orte_dss.pack()/unpack() to serialize /
505
* deserialize individual members). This is likewise true for the copy
506
* and compare functions.
508
* @param release_fn [IN] Function pointer to the release routine
509
* @param pack_fn [IN] Function pointer to the pack routine
510
* @param unpack_fn [IN] Function pointer to the unpack routine
511
* @param copy_fn [IN] Function pointer to copy routine
512
* @param compare_fn [IN] Function pointer to compare routine
513
* @param size_fn [IN] Function pointer to size routine
514
* @param print_fn [IN] Function pointer to print routine
515
* @param structured [IN] Boolean indicator as to whether or not the data is structured. A true
516
* value indicates that this data type is always passed via reference (i.e., a pointer to the
517
* object is passed) as opposed to directly (e.g., the way an int32_t would appear)
518
* @param name [IN] String name for this pair (mainly for debugging)
519
* @param type [OUT] Type number for this registration
521
* @returns ORTE_SUCCESS upon success
524
typedef int (*orte_dss_register_fn_t)(orte_dss_pack_fn_t pack_fn,
525
orte_dss_unpack_fn_t unpack_fn,
526
orte_dss_copy_fn_t copy_fn,
527
orte_dss_compare_fn_t compare_fn,
528
orte_dss_size_fn_t size_fn,
529
orte_dss_print_fn_t print_fn,
530
orte_dss_release_fn_t release_fn,
532
const char *name, orte_data_type_t *type);
534
* This function looks up the string name corresponding to the identified
535
* data type - used for debugging messages.
537
typedef char* (*orte_dss_lookup_data_type_fn_t)(orte_data_type_t type);
540
* Dump the data type list - used for debugging to see what has been registered
542
typedef void (*orte_dss_dump_data_types_fn_t)(int output);
545
* Base structure for the DSS
547
* Base module structure for the DSS - presents the required function
548
* pointers to the calling interface.
551
orte_dss_set_fn_t set;
552
orte_dss_get_fn_t get;
553
orte_dss_arith_fn_t arith;
554
orte_dss_increment_fn_t increment;
555
orte_dss_decrement_fn_t decrement;
556
orte_dss_pack_fn_t pack;
557
orte_dss_unpack_fn_t unpack;
558
orte_dss_copy_fn_t copy;
559
orte_dss_compare_fn_t compare;
560
orte_dss_size_fn_t size;
561
orte_dss_print_fn_t print;
562
orte_dss_release_fn_t release;
563
orte_dss_peek_next_item_fn_t peek;
564
orte_dss_unload_fn_t unload;
565
orte_dss_load_fn_t load;
566
orte_dss_register_fn_t register_type;
567
orte_dss_lookup_data_type_fn_t lookup_data_type;
568
orte_dss_dump_data_types_fn_t dump_data_types;
570
typedef struct orte_dss_t orte_dss_t;
572
OMPI_DECLSPEC extern orte_dss_t orte_dss; /* holds dss function pointers */
574
#if defined(c_plusplus) || defined(__cplusplus)
578
#endif /* ORTE_DSS_H */