From 2468fb8bafb28aaaf05ece5bf65e98f9ec7d5e3e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 19 Aug 1999 13:50:22 -0500 Subject: [svn-r1576] Added H5Dvlen_get_buf_size function. --- src/H5D.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Dprivate.h | 2 + src/H5Dpublic.h | 1 + src/H5Spoint.c | 12 ++++ src/H5Sselect.c | 2 +- src/H5TB.c | 101 +++++++++++++++--------------- src/H5Tprivate.h | 12 ++++ src/H5Tvlen.c | 1 + 8 files changed, 268 insertions(+), 50 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index cdb165a..49de18d 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -2662,8 +2662,10 @@ H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, /* Check args */ if (NULL==op) HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid operator"); +#ifdef OLD_WAY if (buf==NULL) HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); +#endif /* OLD_WAY */ if (H5I_DATATYPE != H5I_get_type(type_id)) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype"); if (H5I_DATASPACE != H5I_get_type(space_id) || @@ -2724,6 +2726,191 @@ H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf) FUNC_LEAVE(ret_value); } /* end H5Dvlen_reclaim() */ +/*------------------------------------------------------------------------- + * Function: H5D_vlen_get_buf_size_alloc + * + * Purpose: This routine makes certain there is enough space in the temporary + * buffer for the new data to read in. All the VL data read in is actually + * placed in this buffer, overwriting the previous data. Needless to say, + * this data is not actually usable. + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 17, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void *H5D_vlen_get_buf_size_alloc(size_t size, void *info) +{ + H5T_vlen_bufsize_t *vlen_bufsize=(H5T_vlen_bufsize_t *)info; + void *ret_value=NULL; /* Pointer to return */ + + FUNC_ENTER(H5D_vlen_get_buf_size_alloc, NULL); + + /* Get a temporary pointer to space for the VL data */ + if (H5TB_resize_buf(vlen_bufsize->vl_tbuf_id,size,&ret_value)>=0) + vlen_bufsize->size+=size; + + FUNC_LEAVE(ret_value); +} /* end H5D_vlen_get_buf_size_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_vlen_get_buf_size + * + * Purpose: This routine checks the number of bytes required to store a single + * element from a dataset in memory, creating a selection with just the + * single element selected to read in the element and using a custom memory + * allocator for any VL data encountered. + * The *size value is modified according to how many bytes are + * required to store the element in memory. + * + * Implementation: This routine actually performs the read with a custom + * memory manager which basically just counts the bytes requested and + * uses a temporary memory buffer (through the H5TB API) to make certain + * enough space is available to perform the read. Then the temporary + * buffer is released and the number of bytes allocated is returned. + * Kinda kludgy, but easier than the other method of trying to figure out + * the sizes without actually reading the data in... - QAK + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 17, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_vlen_get_buf_size(void UNUSED *elem, hid_t type_id, hsize_t UNUSED ndim, hssize_t *point, void *op_data) +{ + H5T_vlen_bufsize_t *vlen_bufsize=(H5T_vlen_bufsize_t *)op_data; + void *tbuf; /* pointer to temporary buffer */ + H5T_t *dt = NULL; + herr_t ret_value=FAIL; + + FUNC_ENTER(H5D_vlen_get_buf_size, FAIL); + + assert(op_data); + assert(H5I_DATATYPE == H5I_get_type(type_id)); + + /* Check args */ + if (NULL==(dt=H5I_object(type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Make certain there is enough fixed-length buffer available */ + if (H5TB_resize_buf(vlen_bufsize->fl_tbuf_id,H5T_get_size(dt),&tbuf)<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't resize tbuf"); + + /* Select point to read in */ + if (H5Sselect_elements(vlen_bufsize->space_id,H5S_SELECT_SET,1,(const hssize_t **)point)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't select point"); + + /* Read in the point (with the custom VL memory allocator) */ + if(H5Dread(vlen_bufsize->dataset_id,type_id,H5S_ALL,vlen_bufsize->space_id,vlen_bufsize->xfer_pid,tbuf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read point"); + + /* Set the correct return value, if we get this far */ + ret_value=0; + +done: + + FUNC_LEAVE(ret_value); +} /* end H5D_vlen_get_buf_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dvlen_get_buf_size + * + * Purpose: This routine checks the number of bytes required to store the VL + * data from the dataset, using the space_id for the selection in the + * dataset on disk and the type_id for the memory representation of the + * VL data, in memory. The *size value is modified according to how many + * bytes are required to store the VL data in memory. + * + * Implementation: This routine actually performs the read with a custom + * memory manager which basically just counts the bytes requested and + * uses a temporary memory buffer (through the H5TB API) to make certain + * enough space is available to perform the read. Then the temporary + * buffer is released and the number of bytes allocated is returned. + * Kinda kludgy, but easier than the other method of trying to figure out + * the sizes without actually reading the data in... - QAK + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, August 11, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, + hsize_t *size) +{ + H5T_vlen_bufsize_t vlen_bufsize={0}; + char bogus; /* bogus value to pass to H5Diterate() */ + herr_t ret_value=FAIL; + + FUNC_ENTER(H5Dvlen_get_buf_size, FAIL); + + /* Check args */ + if (H5I_DATASET!=H5I_get_type(dataset_id) || + H5I_DATATYPE!=H5I_get_type(type_id) || + H5I_DATASPACE!=H5I_get_type(space_id) || size==NULL) { + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument"); + } + + /* Initialize the callback data block */ + /* Save the dataset ID */ + vlen_bufsize.dataset_id=dataset_id; + + /* Get a copy of the dataspace ID */ + if((vlen_bufsize.space_id=H5Dget_space(dataset_id))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy dataspace"); + + /* Grab the temporary buffers required */ + if((vlen_bufsize.fl_tbuf_id=H5TB_get_buf(1,0,NULL))<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available"); + if((vlen_bufsize.vl_tbuf_id=H5TB_get_buf(1,0,NULL))<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available"); + + /* Change to the custom memory allocation routines for reading VL data */ + if((vlen_bufsize.xfer_pid=H5Pcreate(H5P_DATA_XFER))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "no dataset xfer plists available"); + + if(H5Pset_vlen_mem_manager(vlen_bufsize.xfer_pid,H5D_vlen_get_buf_size_alloc,&vlen_bufsize,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set VL data allocation routine"); + + /* Set the initial number of bytes required */ + vlen_bufsize.size=0; + + /* Call H5Diterate with args, etc. */ + ret_value=H5Diterate(&bogus,type_id,space_id,H5D_vlen_get_buf_size, + &vlen_bufsize); + + /* Get the size if we succeeded */ + if(ret_value>=0) + *size=vlen_bufsize.size; + +done: + if(vlen_bufsize.space_id>0) + H5Sclose(vlen_bufsize.space_id); + if(vlen_bufsize.fl_tbuf_id>0) + H5TB_release_buf(vlen_bufsize.fl_tbuf_id); + if(vlen_bufsize.vl_tbuf_id>0) + H5TB_release_buf(vlen_bufsize.vl_tbuf_id); + if(vlen_bufsize.xfer_pid>0) + H5Pclose(vlen_bufsize.xfer_pid); + + FUNC_LEAVE(ret_value); +} /* end H5Dvlen_get_buf_size() */ + /*------------------------------------------------------------------------- * Function: H5Ddebug diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index ab289e6..7fabb66 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -74,5 +74,7 @@ __DLL__ H5S_t *H5D_get_space(H5D_t *dset); __DLL__ H5D_t * H5D_open_oid(H5G_entry_t *ent); __DLL__ H5F_t * H5D_get_file(const H5D_t *dset); __DLL__ hsize_t H5D_get_storage_size(H5D_t *dset); +__DLL__ void *H5D_vlen_get_buf_size_alloc(size_t size, void *info); +__DLL__ herr_t H5D_vlen_get_buf_size(void *elem, hid_t type_id, hsize_t ndim, hssize_t *point, void *op_data); #endif diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index a0eddd1..1090a40 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -55,6 +55,7 @@ __DLL__ herr_t H5Dextend (hid_t dset_id, const hsize_t *size); __DLL__ herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, void *operator_data); __DLL__ herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf); +__DLL__ herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); __DLL__ herr_t H5Ddebug(hid_t dset_id, unsigned int flags); #ifdef __cplusplus diff --git a/src/H5Spoint.c b/src/H5Spoint.c index a7062e9..3386275 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -816,11 +816,20 @@ H5S_point_select_valid (const H5S_t *space) assert(space); +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ /* Check each point to determine whether selection+offset is within extent */ curr=space->select.sel_info.pnt_lst->head; while(curr!=NULL) { /* Check each dimension */ for(i=0; iextent.u.simple.rank; i++) { +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +printf("%s: curr->pnt[%d]=%d\n",FUNC,(int)i,(int)curr->pnt[i]); +printf("%s: space->select.offset[%d]=%d\n",FUNC,(int)i,(int)space->select.offset[i]); +printf("%s: space->extent.u.simple.size[%d]=%d\n",FUNC,(int)i,(int)space->extent.u.simple.size[i]); +#endif /* QAK */ /* Check if an offset has been defined */ /* Bounds check the selected point + offset against the extent */ if(((curr->pnt[i]+space->select.offset[i])>(hssize_t)space->extent.u.simple.size[i]) @@ -832,6 +841,9 @@ H5S_point_select_valid (const H5S_t *space) curr=curr->next; } /* end while */ +#ifdef QAK +printf("%s: check 3.0\n",FUNC); +#endif /* QAK */ FUNC_LEAVE (ret_value); } /* end H5S_point_select_valid() */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 556ae7e..fdf7dc4 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -519,7 +519,7 @@ herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, done: FUNC_LEAVE (ret_value); -} /* H5Sselect_elements() */ +} /* H5S_select_elements() */ /*-------------------------------------------------------------------------- NAME diff --git a/src/H5TB.c b/src/H5TB.c index 0396524..7712de8 100644 --- a/src/H5TB.c +++ b/src/H5TB.c @@ -377,59 +377,62 @@ H5TB_resize_buf(hid_t tbuf_id, hsize_t size, void **ptr) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a temp. buffer"); } - /* Save old pointer for later */ - old_ptr=tbuf->buf; - - /* Try to resize buffer to new size */ - if((tbuf->buf = H5MM_realloc(tbuf->buf, size))==NULL) { - tbuf->buf=old_ptr; /* restore pointer if no memory available */ - HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, - "unable to allocate space for temporary buffer"); - } + /* Check if we actually need to re-size the buffer */ + if(size > tbuf->size) { + /* Save old pointer for later */ + old_ptr=tbuf->buf; + + /* Try to resize buffer to new size */ + if((tbuf->buf = H5MM_realloc(tbuf->buf, size))==NULL) { + tbuf->buf=old_ptr; /* restore pointer if no memory available */ + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate space for temporary buffer"); + } - /* Change the size of the buffer */ - tbuf->size=size; + /* Change the size of the buffer */ + tbuf->size=size; + + /* + * Check if we need to move the buffer in the sorted list + */ + + /* Check if this is not the last node and it needs to move */ + if(tbuf->next!=NULL && tbuf->next->size < tbuf->size) { + /* Remove this node from the list */ + if(tbuf->prev==NULL) { /* remove from head of list */ + H5TB_list_head=tbuf->next; + tbuf->next->prev=NULL; + } else { /* remove from middle of list */ + tbuf->prev->next=tbuf->next; + tbuf->next->prev=tbuf->prev; + } /* end if */ - /* - * Check if we need to move the buffer in the sorted list - */ + /* Find correct position in list */ + curr=H5TB_list_head; + while(curr!=NULL) { + if(!curr->inuse && sizesize) + break; + curr=curr->next; + } /* end while */ - /* Check if this is not the last node and it need's to move */ - if(tbuf->next!=NULL && tbuf->next->size < tbuf->size) { - /* Remove this node from the list */ - if(tbuf->prev==NULL) { /* remove from head of list */ - H5TB_list_head=tbuf->next; - tbuf->next->prev=NULL; - } else { /* remove from middle of list */ - tbuf->prev->next=tbuf->next; - tbuf->next->prev=tbuf->prev; + /* Insert into correct position in list */ + if(curr!=NULL) { + /* + * Can't be adding to the beginning of list, so this is in the + * middle somewhere. + */ + curr->prev->next=tbuf; + tbuf->prev=curr->prev; + curr->prev=tbuf; + tbuf->next=curr; + } else { /* append to end of list */ + H5TB_list_tail->next=tbuf; + tbuf->prev=H5TB_list_tail; + tbuf->next=NULL; + H5TB_list_tail=tbuf; + } /* end else */ } /* end if */ - - /* Find correct position in list */ - curr=H5TB_list_head; - while(curr!=NULL) { - if(!curr->inuse && sizesize) - break; - curr=curr->next; - } /* end while */ - - /* Insert into correct position in list */ - if(curr!=NULL) { - /* - * Can't be adding to the beginning of list, so this is in the - * middle somewhere. - */ - curr->prev->next=tbuf; - tbuf->prev=curr->prev; - curr->prev=tbuf; - tbuf->next=curr; - } else { /* append to end of list */ - H5TB_list_tail->next=tbuf; - tbuf->prev=H5TB_list_tail; - tbuf->next=NULL; - H5TB_list_tail=tbuf; - } /* end else */ - } /* end if */ + } /* end if */ /* Assign the pointer to the buffer, if requested */ if(ptr!=NULL) diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index a870e0b..ca11e99 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -64,6 +64,18 @@ typedef enum { } H5T_vlen_type_t; /* + * Internal data structure for passing information to H5T_vlen_get_buf_size + */ +typedef struct { + hid_t dataset_id; /* ID of the dataset we are working on */ + hid_t space_id; /* ID of the dataset's dataspace we are working on */ + hid_t fl_tbuf_id; /* ID of the temporary buffer we are using for fixed-length data */ + hid_t vl_tbuf_id; /* ID of the temporary buffer we are using for VL data */ + hid_t xfer_pid; /* ID of the dataset xfer property list */ + hsize_t size; /* Accumulated number of bytes for the selection */ +} H5T_vlen_bufsize_t; + +/* * Is the path the special no-op path? The no-op function can be set by the * application and there might be more than one no-op path in a * multi-threaded application if one thread is using the no-op path when some diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index 446b1fb..ea341db 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -558,3 +558,4 @@ H5T_vlen_mark(H5T_t *dt, H5F_t *f, H5T_vlen_type_t loc) done: FUNC_LEAVE(ret_value); } /* end H5T_vlen_mark() */ + -- cgit v0.12