From e77a30ba342ee2461469dbac867f58908b47949a Mon Sep 17 00:00:00 2001 From: Graham Fagg Date: Wed, 11 Aug 2004 07:04:38 +0000 Subject: [PATCH] Finished (2nd?) version of the public pack/unpack routines. - Correctly pack previously packed buffers.. but makes flat storage - Buffers are managed by system (they are now objects) Todo: complete realloc code, checkin my test code in tests/util add a few more pack types and then remove oob_pack as no-one is using it This commit was SVN r2034. --- src/util/Makefile.am | 2 + src/util/pack.c | 413 +++++++++++++++++++++++++++++++++++++++++++ src/util/pack.h | 6 +- 3 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 src/util/pack.c diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 0ab4cd0993..db5a04e307 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -20,6 +20,7 @@ headers = \ numtostr.h \ output.h \ path.h \ + pack.h \ sys_info.h \ printf.h \ proc_info.h \ @@ -39,6 +40,7 @@ libutil_la_SOURCES = \ numtostr.c \ output.c \ path.c \ + pack.c \ printf.c \ proc_info.c \ sys_info.c \ diff --git a/src/util/pack.c b/src/util/pack.c new file mode 100644 index 0000000000..379328f629 --- /dev/null +++ b/src/util/pack.c @@ -0,0 +1,413 @@ +/* + * $HEADER$ + */ + +/** @file + * + * pack/unpack buffer management functions + * + */ +#include +#include +#include + + +#include "ompi_config.h" + +#include "include/constants.h" +#include "class/ompi_object.h" + +#include "pack.h" + +typedef struct ompi_buffer_internal_t { + /* first member must be the objects parent */ + ompi_object_t parent; + /* now for the real elements of the type */ + + void* base_ptr; /* start of my memory */ + void* data_ptr; /* location of where next data will go */ + void* from_ptr; /* location of where to get the next data from */ + + /* counters */ + + size_t size; /* total size of this buffer */ + size_t len; /* total amount already packed */ + size_t space; /* how much space we have left */ + /* yep, size=len+space */ + + size_t toend; /* how many bytes till the end when unpacking :) */ + /* yep, toend is the opposite of len */ + + + size_t cnt; /* temp cnt of buffer usage (debugging) */ +} ompi_buffer_internal_t; + +/* formalise the declaration */ +OBJ_CLASS_DECLARATION (ompi_buffer_internal_t); + + +/* some internal functions */ +/* which must be declared before creating an instance of the obj class */ +static int ompi_buffer_get_ptrs (ompi_buffer_t buffer, void** baseptr, void** dataptr, void** fromptr); +static void ompi_buffer_construct (ompi_buffer_internal_t* buffer); +static void ompi_buffer_destruct (ompi_buffer_internal_t* buffer); + +OBJ_CLASS_INSTANCE(ompi_buffer_internal_t, ompi_object_t, + ompi_buffer_construct, ompi_buffer_destruct); + + +static size_t ompi_buffer_cnts = 0; + + +static void ompi_buffer_construct (ompi_buffer_internal_t* buffer) +{ + buffer->base_ptr = buffer->data_ptr = buffer->from_ptr = NULL; + buffer->size = buffer->len = buffer-> space = buffer-> toend = 0; + buffer->cnt = 0; +} + +static void ompi_buffer_destruct (ompi_buffer_internal_t* buffer) +{ + /* paranoid check */ + if (buffer->base_ptr) free (buffer->base_ptr); + + /* just clean up */ + buffer->base_ptr = buffer->data_ptr = buffer->from_ptr = NULL; + buffer->size = buffer->len = buffer-> space = buffer-> toend = 0; +} + +/** + * This function creates a managed buffer + * users then pack this buffer as many times as op_size + * as the buffer is managed, we grow it as op_size + * + * @param pointer to new buffer handle + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_init (ompi_buffer_t *buffer) +{ +ompi_buffer_internal_t* bptr; +size_t isize=4096; /* we should check the mca params here */ + + /* check that we can return a buffer atall.. */ + if (!buffer) return (OMPI_ERROR); + + /* create new buffer object */ + bptr = (ompi_buffer_internal_t *) OBJ_NEW (ompi_buffer_internal_t); + + if (!bptr) return (OMPI_ERROR); + + ompi_buffer_cnts++; + + /* we have a buffer now, so lets populate it */ + bptr->base_ptr = (void*) malloc (isize); /* BAD fixed initial size */ + + bptr->data_ptr = bptr->base_ptr; /* set the start of the buffer */ + /* leave from_ptr NULL so we catch an unpack before pack! */ + + /* set counts for size and space */ + bptr->size = bptr->space = isize; + bptr->cnt = ompi_buffer_cnts; + + /* ok, all is well, return the buffer back to the user */ + *buffer = bptr; + + return (OMPI_SUCCESS); +} + +/** + * This function gets the size of packed data in an ompi_buffer + * + * @param buffer handle + * @param pointer to buffer size + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_size (ompi_buffer_t buffer, size_t *size) +{ + /* check that we can return a size atall.. */ + if (!size) return (OMPI_ERROR); + /* check that buffer is not null */ + if (!buffer) return (OMPI_ERROR); + + /* deref and pass back */ + *size = buffer->len; + + return (OMPI_SUCCESS); +} + +/** + * This function gets the base/data/from ptrs of data in an ompi_buffer + * + * @param buffer handle + * @param pointer to buffer start (base) + * @param pointer to next data storage in buffer (data) + * @param pointer to start of next buffer read (from) + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_get_ptrs (ompi_buffer_t buffer, + void** baseptr, void** dataptr, void** fromptr) +{ + /* check that buffer is not null */ + if (!buffer) return (OMPI_ERROR); + + /* deref and pass back */ + if (baseptr) *baseptr = buffer->base_ptr; + if (dataptr) *dataptr = buffer->data_ptr; + if (fromptr) *fromptr = buffer->from_ptr; + + return (OMPI_SUCCESS); +} + +/** + * This function frees a given buffer + * If the buffer has data still, it is lost + * + * @param buffer handle + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_buffer_free (ompi_buffer_t buffer) +{ +ompi_buffer_internal_t *bptr; + + /* check that buffer is not null */ + if (!buffer) return (OMPI_ERROR); + + bptr = buffer; + + OBJ_RELEASE (bptr); + + return (OMPI_SUCCESS); +} + + + +/** + * This function packs the passed data according to the type enum. + * + * @param buffer the destination for the packed data + * @param src the source of the data + * @param n the number of elements in the src + * @param type the type of data + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + */ + int ompi_pack(ompi_buffer_t buffer, void * src, size_t n, ompi_pack_type_t type) +{ + int i, rc; + void *dest; + ompi_buffer_internal_t* bptr; + size_t op_size=0; + uint16_t * d16; + uint32_t * d32; + uint16_t * s16; + uint32_t * s32; + + /* first find the destination location in the buffer */ + if (!buffer) return (OMPI_ERROR); + + bptr = (ompi_buffer_internal_t *) buffer; /* get buffer */ + + + dest = bptr->data_ptr; /* get location in buffer */ + + /* calculate op_size data size */ + switch(type) { + case OMPI_BYTE: + op_size = n; + break; + case OMPI_STRING: + op_size = n; + break; + case OMPI_PACKED: + { + void *base, *data, *from; + + rc = ompi_buffer_size ((ompi_buffer_t)src, &op_size); + rc = ompi_buffer_get_ptrs ((ompi_buffer_t)src, + &base, &data, &from); + /* check if packing from empty buffer.. */ + if (NULL==from) return OMPI_ERROR; + else + src = (ompi_buffer_t) from; + } + if (OMPI_ERROR==rc) return OMPI_ERROR; + break; + case OMPI_INT16: + op_size = n*2; + break; + case OMPI_INT32: + op_size = n*4; + break; + default: + return OMPI_ERROR; + } + + if (op_size > bptr->space) { /* need to expand the buffer */ + /* todo resize buffer */ + /* after resizing, if it worked we would need to update the dest */ + /* as it could have moved. (Learned this bug from Edgar :) */ + dest = bptr->data_ptr; /* get location in buffer */ + + return (OMPI_ERROR); /* for tonight */ + } + + switch(type) { + case OMPI_BYTE: + memcpy(dest, src, n); + break; + case OMPI_PACKED: + memcpy(dest, src, op_size); + break; + case OMPI_INT16: + d16 = (uint16_t *) dest; + s16 = (uint16_t *) src; + for (i=0;idata_ptr = ((char*)bptr->data_ptr) + op_size; + + bptr->len += op_size; + bptr->toend += op_size; + + bptr->space -= op_size; + + /* if first pack also set the from_ptr as it is now valid */ + if (!bptr->from_ptr) bptr->from_ptr = bptr->base_ptr; + + return OMPI_SUCCESS; +} + +/** + * This function unpacks the passed data according to the type enum. + * + * @param buffer the source of the packed data + * @param dest the destination for the unpacked data + * @param n the number of elements in the src + * @param type the type of the data to unpack + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + */ + int ompi_unpack(ompi_buffer_t buffer, void * dest, size_t n, ompi_pack_type_t type) +{ + int i; + void *src; + ompi_buffer_internal_t* bptr; + size_t op_size=0; + uint16_t * d16; + uint32_t * d32; + uint16_t * s16; + uint32_t * s32; + + /* first find the source location in the buffer */ + if (!buffer) return (OMPI_ERROR); + + bptr = (ompi_buffer_internal_t *) buffer; /* get buffer */ + + src = bptr->from_ptr; /* get location in buffer */ + + /* calculate op_size data size */ + switch(type) { + case OMPI_BYTE: + case OMPI_STRING: + op_size = n; + break; + case OMPI_PACKED: + /* once a buffer is packed, the DS becomes 'flat'.. */ + /* so you cannot do a recursive unpack.. sorry. GEF */ + return OMPI_ERROR; + case OMPI_INT16: + op_size = n*2; + break; + case OMPI_INT32: + op_size = n*4; + break; + default: + return OMPI_ERROR; + } + + /* now we need to do a TRUNCATION buffer check... */ + /* as this is used by user level OMPI users this should be nicer */ + /* i.e. attempt to unpack as much as possible */ + /* but for now if attempt to unpack something invalid it will error. GEF */ + + if (op_size > bptr->toend) { /* truncation of requested data */ + /* todo nicer best effort unpack */ + return (OMPI_ERROR); /* for tonight */ + } + + + switch(type) { + case OMPI_BYTE: + memcpy(dest, src, n); + case OMPI_PACKED: + return OMPI_ERROR; + case OMPI_INT16: + d16 = (uint16_t *) dest; + s16 = (uint16_t *) src; + for (i=0;ifrom_ptr = ((char*)bptr->from_ptr) + op_size; + + bptr->toend -= op_size; /* closer to the end */ + bptr->len -= op_size; /* and less data left */ + + return OMPI_SUCCESS; +} + diff --git a/src/util/pack.h b/src/util/pack.h index 7845de7935..4d5d88726f 100644 --- a/src/util/pack.h +++ b/src/util/pack.h @@ -39,6 +39,9 @@ typedef enum { typedef struct ompi_buffer_internal_t* ompi_buffer_t; +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif /** * This function creates a managed buffer @@ -80,9 +83,6 @@ typedef struct ompi_buffer_internal_t* ompi_buffer_t; int ompi_buffer_free (ompi_buffer_t buffer); -#if defined(c_plusplus) || defined(__cplusplus) -extern "C" { -#endif /*