[svn-r22219] Description:

Merge "file image" changes from feature branch back to trunk.

Tested on:
    Mac OSX/64 10.7.3 (amazon) w/debug
    (h5committest upcoming)
This commit is contained in:
Quincey Koziol 2012-03-31 03:49:35 -05:00
parent b51ffb25fe
commit c2a9dcb897
43 changed files with 4256 additions and 327 deletions

View File

@ -963,32 +963,35 @@
./test/filespace_1_8.h5
./test/filespace_1_6.h5
./test/freespace.c
./test/file_image.c
./test/file_image_core_test.h5
./test/fill_old.h5
./test/fillval.c
./test/filter_fail.c
./test/flush1.c
./test/flush2.c
./test/gen_bad_ohdr.c _DO_NOT_DISTRIBUTE_
./test/gen_bad_compound.c _DO_NOT_DISTRIBUTE_
./test/gen_bogus.c _DO_NOT_DISTRIBUTE_
./test/gen_cross.c _DO_NOT_DISTRIBUTE_
./test/gen_deflate.c _DO_NOT_DISTRIBUTE_
./test/gen_filespace.c _DO_NOT_DISTRIBUTE_
./test/gen_mergemsg.c _DO_NOT_DISTRIBUTE_
./test/gen_new_array.c _DO_NOT_DISTRIBUTE_
./test/gen_new_fill.c _DO_NOT_DISTRIBUTE_
./test/gen_new_group.c _DO_NOT_DISTRIBUTE_
./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_
./test/gen_new_super.c _DO_NOT_DISTRIBUTE_
./test/gen_noencoder.c _DO_NOT_DISTRIBUTE_
./test/gen_nullspace.c _DO_NOT_DISTRIBUTE_
./test/gen_old_array.c _DO_NOT_DISTRIBUTE_
./test/gen_old_group.c _DO_NOT_DISTRIBUTE_
./test/gen_old_layout.c _DO_NOT_DISTRIBUTE_
./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_
./test/gen_sizes_lheap.c _DO_NOT_DISTRIBUTE_
./test/gen_specmetaread.c _DO_NOT_DISTRIBUTE_
./test/gen_udlinks.c _DO_NOT_DISTRIBUTE_
./test/gen_bad_ohdr.c _DO_NOT_DISTRIBUTE_
./test/gen_bad_compound.c _DO_NOT_DISTRIBUTE_
./test/gen_bogus.c _DO_NOT_DISTRIBUTE_
./test/gen_cross.c _DO_NOT_DISTRIBUTE_
./test/gen_deflate.c _DO_NOT_DISTRIBUTE_
./test/gen_file_image.c _DO_NOT_DISTRIBUTE_
./test/gen_filespace.c _DO_NOT_DISTRIBUTE_
./test/gen_mergemsg.c _DO_NOT_DISTRIBUTE_
./test/gen_new_array.c _DO_NOT_DISTRIBUTE_
./test/gen_new_fill.c _DO_NOT_DISTRIBUTE_
./test/gen_new_group.c _DO_NOT_DISTRIBUTE_
./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_
./test/gen_new_super.c _DO_NOT_DISTRIBUTE_
./test/gen_noencoder.c _DO_NOT_DISTRIBUTE_
./test/gen_nullspace.c _DO_NOT_DISTRIBUTE_
./test/gen_old_array.c _DO_NOT_DISTRIBUTE_
./test/gen_old_group.c _DO_NOT_DISTRIBUTE_
./test/gen_old_layout.c _DO_NOT_DISTRIBUTE_
./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_
./test/gen_sizes_lheap.c _DO_NOT_DISTRIBUTE_
./test/gen_specmetaread.c _DO_NOT_DISTRIBUTE_
./test/gen_udlinks.c _DO_NOT_DISTRIBUTE_
./test/getname.c
./test/gheap.c
./test/group_old.h5
@ -1083,6 +1086,7 @@
./testpar/t_cache.c
./testpar/t_dset.c
./testpar/t_file.c
./testpar/t_file_image.c
./testpar/t_mdset.c
./testpar/t_mpi.c
./testpar/t_ph5basic.c
@ -2075,6 +2079,7 @@
./hl/test/sepia.pal
./hl/test/gen_test_ds.c
./hl/test/test_ds.c
./hl/test/test_file_image.c
./hl/test/test_image.c
./hl/test/test_lite.c
./hl/test/test_packet.c

View File

@ -109,6 +109,7 @@ $Source = "";
"H5FD_t" => "x",
"H5FD_class_t" => "x",
"H5FD_stream_fapl_t" => "x",
"H5FD_file_image_callbacks_t" => "x",
"H5G_iterate_t" => "x",
"H5G_info_t" => "x",
"H5I_free_t" => "x",

View File

@ -17,6 +17,7 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "H5LTprivate.h"
#include "H5private.h"
@ -31,7 +32,461 @@ char *myinput;
size_t indent = 0;
/* File Image operations
A file image is a representation of an HDF5 file in a memory
buffer. In order to perform operations on an image in a similar way
to a file, the application buffer is copied to a FAPL buffer, which
in turn is copied to a VFD buffer. Buffer copying can decrease
performance, especially when using large file images. A solution to
this issue is to simulate the copying of the application buffer,
when actually the same buffer is used for the FAPL and the VFD.
This is implemented by using callbacks that simulate the standard
functions for memory management (additional callbacks are used for
the management of associated data structures). From the application
standpoint, a file handle can be obtained from a file image by using
the API routine H5LTopen_file_image(). This function takes a flag
argument that indicates the HDF5 library how to handle the given image;
several flag values can be combined by using the bitwise OR operator.
Valid flag values include:
H5LT_FILE_IMAGE_OPEN_RW indicates the HDF5 library to open the file
image in read/write mode. Default is read-only mode.
H5LT_FILE_IMAGE_DONT_COPY indicates the HDF5 library to not copy the
supplied user buffer; the same buffer will be handled by the FAPL and
the VFD driver. Default operation copies the user buffer to the FAPL and
VFD driver.
H5LT_FILE_IMAGE_DONT_RELEASE indicates the HDF5 library to not release
the buffer handled by the FAPL and the VFD upon closing. This flag value
is only applicable when the flag value H5LT_FILE_IMAGE_DONT_COPY is set as
well. The application is responsible to release the image buffer.
*/
/* Data structure to pass application data to callbacks. */
typedef struct {
void *app_image_ptr; /* Pointer to application buffer */
size_t app_image_size; /* Size of application buffer */
void *fapl_image_ptr; /* Pointer to FAPL buffer */
size_t fapl_image_size; /* Size of FAPL buffer */
int fapl_ref_count; /* Reference counter for FAPL buffer */
void *vfd_image_ptr; /* Pointer to VFD buffer */
size_t vfd_image_size; /* Size of VFD buffer */
int vfd_ref_count; /* Reference counter for VFD buffer */
unsigned flags; /* Flags indicate how the file image will */
/* be open */
int ref_count; /* Reference counter on udata struct */
} H5LT_file_image_ud_t;
/* callbacks prototypes for file image ops */
static void *image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *udata);
static void *image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op, void *udata);
static void *image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *udata);
static herr_t image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *udata);
static void *udata_copy(void *udata);
static herr_t udata_free(void *udata);
/* Definition of callbacks for file image operations. */
/*-------------------------------------------------------------------------
* Function: image_malloc
*
* Purpose: Simulates malloc() function to avoid copying file images.
* The application buffer is set to the buffer on only one FAPL.
* Then the FAPL buffer can be copied to other FAPL buffers or
* to only one VFD buffer.
*
* Return: Address of "allocated" buffer, if successful. Otherwise, it returns
* NULL.
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static void *
image_malloc(size_t size, H5FD_file_image_op_t file_image_op, void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
void * return_value = NULL;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
switch ( file_image_op ) {
/* the app buffer is "copied" to only one FAPL. Afterwards, FAPLs can be "copied" */
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
if (udata->app_image_ptr == NULL)
goto out;
if (udata->app_image_size != size)
goto out;
if (udata->fapl_image_ptr != NULL)
goto out;
if (udata->fapl_image_size != 0)
goto out;
if (udata->fapl_ref_count != 0)
goto out;
udata->fapl_image_ptr = udata->app_image_ptr;
udata->fapl_image_size = udata->app_image_size;
return_value = udata->fapl_image_ptr;
udata->fapl_ref_count++;
break;
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
if (udata->fapl_image_ptr == NULL)
goto out;
if (udata->fapl_image_size != size)
goto out;
if (udata->fapl_ref_count == 0)
goto out;
return_value = udata->fapl_image_ptr;
udata->fapl_ref_count++;
break;
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
goto out;
case H5FD_FILE_IMAGE_OP_FILE_OPEN:
/* FAPL buffer is "copied" to only one VFD buffer */
if (udata->vfd_image_ptr != NULL)
goto out;
if (udata->vfd_image_size != 0)
goto out;
if (udata->vfd_ref_count != 0)
goto out;
if (udata->fapl_image_ptr == NULL)
goto out;
if (udata->fapl_image_size != size)
goto out;
if (udata->fapl_ref_count == 0)
goto out;
udata->vfd_image_ptr = udata->fapl_image_ptr;
udata->vfd_image_size = size;
udata->vfd_ref_count++;
return_value = udata->vfd_image_ptr;
break;
/* added unused labels to shut the compiler up */
case H5FD_FILE_IMAGE_OP_NO_OP:
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
default:
goto out;
} /* end switch */
return(return_value);
out:
return NULL;
} /* end image_malloc() */
/*-------------------------------------------------------------------------
* Function: image_memcpy
*
* Purpose: Simulates memcpy() function to avoid copying file images.
* The image buffer can be set to only one FAPL buffer, and
* "copied" to only one VFD buffer. The FAPL buffer can be
* "copied" to other FAPLs buffers.
*
* Return: The address of the destination buffer, if successful. Otherwise, it
* returns NULL.
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static void *
image_memcpy(void *dest, const void *src, size_t size, H5FD_file_image_op_t file_image_op,
void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
switch(file_image_op) {
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
if (dest != udata->fapl_image_ptr)
goto out;
if (src != udata->app_image_ptr)
goto out;
if (size != udata->fapl_image_size)
goto out;
if (size != udata->app_image_size)
goto out;
if (udata->fapl_ref_count == 0)
goto out;
break;
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
if (dest != udata->fapl_image_ptr)
goto out;
if (src != udata->fapl_image_ptr)
goto out;
if (size != udata->fapl_image_size)
goto out;
if (udata->fapl_ref_count < 2)
goto out;
break;
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
goto out;
case H5FD_FILE_IMAGE_OP_FILE_OPEN:
if (dest != udata->vfd_image_ptr)
goto out;
if (src != udata->fapl_image_ptr)
goto out;
if (size != udata->vfd_image_size)
goto out;
if (size != udata->fapl_image_size)
goto out;
if (udata->fapl_ref_count == 0)
goto out;
if (udata->vfd_ref_count != 1)
goto out;
break;
/* added unused labels to shut the compiler up */
case H5FD_FILE_IMAGE_OP_NO_OP:
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
default:
goto out;
} /* end switch */
return(dest);
out:
return NULL;
} /* end image_memcpy() */
/*-------------------------------------------------------------------------
* Function: image_realloc
*
* Purpose: Reallocates the shared application image buffer and updates data
* structures that manage buffer "copying".
*
* Return: Address of reallocated buffer, if successful. Otherwise, it returns
* NULL.
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static void *
image_realloc(void *ptr, size_t size, H5FD_file_image_op_t file_image_op, void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
void * return_value = NULL;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
/* realloc() is not allowed when the HDF5 library won't release the image
buffer because reallocation may change the address of the buffer. The
new address cannot be communicated to the application to release it. */
if (udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE)
goto out;
/* realloc() is not allowed if the image is open in read-only mode */
if (!(udata->flags & H5LT_FILE_IMAGE_OPEN_RW))
goto out;
if (file_image_op == H5FD_FILE_IMAGE_OP_FILE_RESIZE) {
if (udata->vfd_image_ptr != ptr)
goto out;
if (udata->vfd_ref_count != 1)
goto out;
if (NULL == (udata->vfd_image_ptr = HDrealloc(ptr, size)))
goto out;
udata->vfd_image_size = size;
return_value = udata->vfd_image_ptr;
} /* end if */
else
goto out;
return(return_value);
out:
return NULL;
} /* end image_realloc() */
/*-------------------------------------------------------------------------
* Function: image_free
*
* Purpose: Simulates deallocation of FAPL and VFD buffers by decreasing
* reference counters. Shared application buffer is actually
* deallocated if there are no outstanding references.
*
* Return: SUCCEED or FAIL
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static herr_t
image_free(void *ptr, H5FD_file_image_op_t file_image_op, void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
switch(file_image_op) {
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE:
if (udata->fapl_image_ptr != ptr)
goto out;
if (udata->fapl_ref_count == 0)
goto out;
udata->fapl_ref_count--;
/* release the shared buffer only if indicated by the respective flag and there are no outstanding references */
if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 &&
!(udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE)) {
HDfree(udata->fapl_image_ptr);
udata->app_image_ptr = NULL;
udata->fapl_image_ptr = NULL;
udata->vfd_image_ptr = NULL;
} /* end if */
break;
case H5FD_FILE_IMAGE_OP_FILE_CLOSE:
if (udata->vfd_image_ptr != ptr)
goto out;
if (udata->vfd_ref_count != 1)
goto out;
udata->vfd_ref_count--;
/* release the shared buffer only if indicated by the respective flag and there are no outstanding references */
if (udata->fapl_ref_count == 0 && udata->vfd_ref_count == 0 &&
!(udata->flags & H5LT_FILE_IMAGE_DONT_RELEASE)) {
HDfree(udata->vfd_image_ptr);
udata->app_image_ptr = NULL;
udata->fapl_image_ptr = NULL;
udata->vfd_image_ptr = NULL;
} /* end if */
break;
/* added unused labels to keep the compiler quite */
case H5FD_FILE_IMAGE_OP_NO_OP:
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET:
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY:
case H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET:
case H5FD_FILE_IMAGE_OP_FILE_OPEN:
case H5FD_FILE_IMAGE_OP_FILE_RESIZE:
default:
goto out;
} /* end switch */
return(SUCCEED);
out:
return(FAIL);
} /* end image_free() */
/*-------------------------------------------------------------------------
* Function: udata_copy
*
* Purpose: Simulates the copying of the user data structure utilized in the
* management of the "copying" of file images.
*
* Return: Address of "newly allocated" structure, if successful. Otherwise, it
* returns NULL.
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static void *
udata_copy(void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
if (udata->ref_count == 0)
goto out;
udata->ref_count++;
return(udata);
out:
return NULL;
} /* end udata_copy */
/*-------------------------------------------------------------------------
* Function: udata_free
*
* Purpose: Simulates deallocation of the user data structure utilized in the
* management of the "copying" of file images. The data structure is
* actually deallocated when there are no outstanding references.
*
* Return: SUCCEED or FAIL
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
static herr_t
udata_free(void *_udata)
{
H5LT_file_image_ud_t *udata = (H5LT_file_image_ud_t *)_udata;
/* callback is only used if the application buffer is not actually copied */
if (!(udata->flags & H5LT_FILE_IMAGE_DONT_COPY))
goto out;
if (udata->ref_count == 0)
goto out;
udata->ref_count--;
/* checks that there are no references outstanding before deallocating udata */
if (udata->ref_count == 0 && udata->fapl_ref_count == 0 &&
udata->vfd_ref_count == 0)
HDfree(udata);
return(SUCCEED);
out:
return(FAIL);
} /* end udata_free */
/* End of callbacks definitions for file image operations */
/*-------------------------------------------------------------------------
*
@ -388,6 +843,120 @@ out:
return -1;
}
/*-------------------------------------------------------------------------
* Function: H5LTopen_file_image
*
* Purpose: Open a user supplied file image using the core file driver.
*
* Return: File identifier, Failure: -1
*
* Programmer: Christian Chilan
*
* Date: October 3, 2011
*
*-------------------------------------------------------------------------
*/
hid_t H5LTopen_file_image(void *buf_ptr, size_t buf_size, unsigned flags)
{
hid_t fapl, file_id; /* HDF5 identifiers */
unsigned file_open_flags;/* Flags for image open */
char file_name[64]; /* Filename buffer */
size_t alloc_incr; /* Buffer allocation increment */
size_t min_incr = 65536; /* Minimum buffer increment */
double buf_prcnt = 0.1f; /* Percentage of buffer size to set
as increment */
static long file_name_counter;
H5FD_file_image_callbacks_t callbacks = {&image_malloc, &image_memcpy,
&image_realloc, &image_free,
&udata_copy, &udata_free,
(void *)NULL};
/* check arguments */
if (buf_ptr == NULL)
goto out;
if (buf_size == 0)
goto out;
if (flags & (unsigned)~(H5LT_FILE_IMAGE_ALL))
goto out;
/* Create FAPL to transmit file image */
if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
goto out;
/* set allocation increment to a percentage of the supplied buffer size, or
* a pre-defined minimum increment value, whichever is larger
*/
if ((buf_prcnt * buf_size) > min_incr)
alloc_incr = (size_t)(buf_prcnt * buf_size);
else
alloc_incr = min_incr;
/* Configure FAPL to use the core file driver */
if (H5Pset_fapl_core(fapl, alloc_incr, FALSE) < 0)
goto out;
/* Set callbacks for file image ops ONLY if the file image is NOT copied */
if (flags & H5LT_FILE_IMAGE_DONT_COPY) {
H5LT_file_image_ud_t *udata; /* Pointer to udata structure */
/* Allocate buffer to communicate user data to callbacks */
if (NULL == (udata = (H5LT_file_image_ud_t *)HDmalloc(sizeof(H5LT_file_image_ud_t))))
goto out;
/* Initialize udata with info about app buffer containing file image and flags */
udata->app_image_ptr = buf_ptr;
udata->app_image_size = buf_size;
udata->fapl_image_ptr = NULL;
udata->fapl_image_size = 0;
udata->fapl_ref_count = 0;
udata->vfd_image_ptr = NULL;
udata->vfd_image_size = 0;
udata->vfd_ref_count = 0;
udata->flags = flags;
udata->ref_count = 1; /* corresponding to the first FAPL */
/* copy address of udata into callbacks */
callbacks.udata = (void *)udata;
/* Set file image callbacks */
if (H5Pset_file_image_callbacks(fapl, &callbacks) < 0) {
HDfree(udata);
goto out;
} /* end if */
} /* end if */
/* Assign file image in user buffer to FAPL */
if (H5Pset_file_image(fapl, buf_ptr, buf_size) < 0)
goto out;
/* set file open flags */
if (flags & H5LT_FILE_IMAGE_OPEN_RW)
file_open_flags = H5F_ACC_RDWR;
else
file_open_flags = H5F_ACC_RDONLY;
/* define a unique file name */
snprintf(file_name, (sizeof(file_name) - 1), "file_image_%ld", file_name_counter++);
/* Assign file image in FAPL to the core file driver */
if ((file_id = H5Fopen(file_name, file_open_flags, fapl)) < 0)
goto out;
/* Close FAPL */
if (H5Pclose(fapl) < 0)
goto out;
/* Return file identifier */
return file_id;
out:
H5E_BEGIN_TRY {
H5Pclose(fapl);
} H5E_END_TRY;
return -1;
} /* end H5LTopen_file_image() */
/*-------------------------------------------------------------------------
* Function: H5LT_read_dataset
@ -1801,7 +2370,7 @@ print_enum(hid_t type, char* str, size_t *str_len, hbool_t no_ubuf, size_t indt)
out:
if(0 == nmembs) {
HDsnprintf(tmp_str, TMP_LEN, "\n%*s <empty>", indt + 4, "");
HDsnprintf(tmp_str, TMP_LEN, "\n%*s <empty>", (int)(indt + 4), "");
str = realloc_and_append(no_ubuf, str_len, str, tmp_str);
} /* end if */

View File

@ -16,6 +16,15 @@
#ifndef _H5LTpublic_H
#define _H5LTpublic_H
/* Flag definitions for H5LTopen_file_image() */
#define H5LT_FILE_IMAGE_OPEN_RW 0x0001 /* Open image for read-write */
#define H5LT_FILE_IMAGE_DONT_COPY 0x0002 /* The HDF5 lib won't copy */
/* user supplied image buffer. The same image is open with the core driver. */
#define H5LT_FILE_IMAGE_DONT_RELEASE 0x0004 /* The HDF5 lib won't */
/* deallocate user supplied image buffer. The user application is reponsible */
/* for doing so. */
#define H5LT_FILE_IMAGE_ALL 0x0007
typedef enum H5LT_lang_t {
H5LT_LANG_ERR = -1, /*this is the first*/
H5LT_DDL = 0, /*for DDL*/
@ -344,6 +353,15 @@ H5_HLDLL herr_t H5LTfind_attribute( hid_t loc_id, const char *name );
H5_HLDLL htri_t H5LTpath_valid(hid_t loc_id, const char *path, hbool_t check_object_valid);
/*-------------------------------------------------------------------------
*
* File image operations functions
*
*-------------------------------------------------------------------------
*/
H5_HLDLL hid_t H5LTopen_file_image(void *buf_ptr, size_t buf_size, unsigned flags);
#ifdef __cplusplus
}
#endif

View File

@ -29,7 +29,7 @@ LDADD=$(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
# Test programs. These are our main targets. They should be listed in the
# order to be executed, generally most specific tests to least specific tests.
TEST_PROG=test_lite test_image test_table test_ds test_packet
TEST_PROG=test_lite test_image test_file_image test_table test_ds test_packet
check_PROGRAMS=$(TEST_PROG)
# These programs generate test files for the tests. They don't need to be
@ -45,7 +45,7 @@ endif
# Temporary files. These files are the ones created by running `make test'.
CHECK_CLEANFILES+=combine_tables[1-2].h5 test_ds[1-9].h5 test_image[1-3].h5 \
test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \
file_img[1-2].h5 test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \
test_packet_compress.h5 test_detach.h5
include $(top_srcdir)/config/conclude.am

View File

@ -69,7 +69,8 @@ CONFIG_HEADER = $(top_builddir)/src/H5config.h
CONFIG_CLEAN_FILES = H5srcdir_str.h
CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = test_lite$(EXEEXT) test_image$(EXEEXT) \
test_table$(EXEEXT) test_ds$(EXEEXT) test_packet$(EXEEXT)
test_file_image$(EXEEXT) test_table$(EXEEXT) test_ds$(EXEEXT) \
test_packet$(EXEEXT)
am__EXEEXT_2 = gen_test_ds$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
gen_test_ds_SOURCES = gen_test_ds.c
@ -83,6 +84,10 @@ test_ds_SOURCES = test_ds.c
test_ds_OBJECTS = test_ds.$(OBJEXT)
test_ds_LDADD = $(LDADD)
test_ds_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
test_file_image_SOURCES = test_file_image.c
test_file_image_OBJECTS = test_file_image.$(OBJEXT)
test_file_image_LDADD = $(LDADD)
test_file_image_DEPENDENCIES = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
test_image_SOURCES = test_image.c
test_image_OBJECTS = test_image.$(OBJEXT)
test_image_LDADD = $(LDADD)
@ -125,10 +130,10 @@ am__v_CCLD_0 = @echo " CCLD " $@;
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = gen_test_ds.c test_ds.c test_image.c test_lite.c \
test_packet.c test_table.c
DIST_SOURCES = gen_test_ds.c test_ds.c test_image.c test_lite.c \
test_packet.c test_table.c
SOURCES = gen_test_ds.c test_ds.c test_file_image.c test_image.c \
test_lite.c test_packet.c test_table.c
DIST_SOURCES = gen_test_ds.c test_ds.c test_file_image.c test_image.c \
test_lite.c test_packet.c test_table.c
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
@ -422,16 +427,16 @@ TRACE = perl $(top_srcdir)/bin/trace
# Temporary files. These files are the ones created by running `make test'.
CHECK_CLEANFILES = *.chkexe *.chklog *.clog combine_tables[1-2].h5 \
test_ds[1-9].h5 test_image[1-3].h5 test_lite[1-2].h5 \
test_table.h5 test_packet_table.h5 test_packet_compress.h5 \
test_detach.h5
test_ds[1-9].h5 test_image[1-3].h5 file_img[1-2].h5 \
test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \
test_packet_compress.h5 test_detach.h5
# The tests depend on the hdf5, hdf5 test, and hdf5_hl libraries
LDADD = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)
# Test programs. These are our main targets. They should be listed in the
# order to be executed, generally most specific tests to least specific tests.
TEST_PROG = test_lite test_image test_table test_ds test_packet
TEST_PROG = test_lite test_image test_file_image test_table test_ds test_packet
# These programs generate test files for the tests. They don't need to be
# compiled every time we want to test the library. However, putting
@ -515,6 +520,9 @@ gen_test_ds$(EXEEXT): $(gen_test_ds_OBJECTS) $(gen_test_ds_DEPENDENCIES)
test_ds$(EXEEXT): $(test_ds_OBJECTS) $(test_ds_DEPENDENCIES)
@rm -f test_ds$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_ds_OBJECTS) $(test_ds_LDADD) $(LIBS)
test_file_image$(EXEEXT): $(test_file_image_OBJECTS) $(test_file_image_DEPENDENCIES)
@rm -f test_file_image$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_file_image_OBJECTS) $(test_file_image_LDADD) $(LIBS)
test_image$(EXEEXT): $(test_image_OBJECTS) $(test_image_DEPENDENCIES)
@rm -f test_image$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(test_image_OBJECTS) $(test_image_LDADD) $(LIBS)
@ -536,6 +544,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_test_ds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_file_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lite.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_packet.Po@am__quote@

View File

@ -23,9 +23,6 @@
#ifndef _H5HLTEST_H
#define _H5HLTEST_H
/* Get the HDF5 public header */
#include "hdf5.h"
/* Get the HDF5 test header */
#include "h5test.h"
@ -36,5 +33,8 @@
#define TESTING2(WHAT) {printf("%-70s", "Testing " WHAT); fflush(stdout);}
#define TESTING3(WHAT) {printf("%-70s", "" WHAT); fflush(stdout);}
/* Implrements verbose 'assert' with 'goto error' exit */
#define VERIFY(condition, string) do { if (!(condition)) FAIL_PUTS_ERROR(string) } while(0)
#endif /* _H5HLTEST_H */

518
hl/test/test_file_image.c Normal file
View File

@ -0,0 +1,518 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "h5hltest.h"
#include "H5LTpublic.h"
#define DSET_NAME "dset"
#define RANK 2
/* Test of file image operations.
The following code provides a means to thoroughly test the file image
operations. Main objectives are testing operations with multiple open
images and using all possible flag combinations, which are set in the
main calling routine. Since the number of open images and flag combinations
may differ, the flag combinations are assigned to the images in round-robin
fashion. In order to simulate a realistic operation environment, the code
operates on as many open objects as possible by using several for-loops
instead of using a single loop that opens image i, accesses it, and closes
it. The first loop creates the files and obtains images using the function
H5Fget_file_image(); two images are set incorrectly (one image is filled
with "wrong" data while the other image is not valid). The second loop opens
the images using the function H5LTopen_file_image(), and test whether the
images have been copied in accordance to the H5LT_FILE_IMAGE_DONT_COPY flag.
The third loop reads the open images and verifies that the contents are
correct. The fourth loop first perform writes in the images that do not
extend the image, and then performs writes that extend the images. The fifth
loop reads the extended images and verify that the content are correct. The
sixth and final loop closes the file images and deallocates the image
buffers if appropriate. */
/*-------------------------------------------------------------------------
* test file image operations
*-------------------------------------------------------------------------
*/
static int
test_file_image(size_t open_images, size_t nflags, unsigned *flags)
{
hid_t *file_id, *dset_id, file_space, plist; /* HDF5 ids */
hsize_t dims1[RANK] = {2,3}; /* original dimension of datasets */
hsize_t max_dims[RANK] = {H5S_UNLIMITED, H5S_UNLIMITED};
int data1[6] = {1,2,3,4,5,6}; /* original contents of dataset */
int data2[6] = {7,8,9,10,11,12}; /* "wrong" contents of dataset */
hsize_t dims3[RANK]; /* array to read dataset dimensions */
int data3[15]; /* array to read dataset contents */
hsize_t dims4[RANK] = {3,5}; /* extended dimensions of datasets */
int data4[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
/* extended contents of dataset */
ssize_t *buf_size; /* pointer to array of buffer sizes */
void **buf_ptr; /* pointer to array of pointers to image buffers */
char **filename; /* pointer to array of pointers to filenames */
unsigned *input_flags; /* pointer to array of flag combinations */
size_t i, j, k, nrow, n_values;
herr_t status1;
void *handle_ptr = NULL; /* pointers to driver buffer */
unsigned char **core_buf_ptr_ptr = NULL;
VERIFY(open_images > 1 , "The number of open images must be greater than 1");
VERIFY(nflags > 0, "The number of flag combinations must be greater than 0");
/* allocate array of flags for open images */
if (NULL == (input_flags = (unsigned *)HDmalloc(sizeof(unsigned) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
/* allocate array of pointers for each of the open images */
if (NULL == (buf_ptr = (void **)malloc(sizeof(void *) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
/* allocate array to store the name of each of the open images */
if (NULL == (filename = (char **)malloc(sizeof(char *) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
/* allocate array to store the size of each of the open images */
if (NULL == (buf_size = (ssize_t *)malloc(sizeof(ssize_t) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
/* allocate array for each of the file identifiers */
if (NULL == (file_id = (hid_t *)malloc(sizeof(hid_t) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
/* allocate array for each of the dataset identifiers */
if (NULL == (dset_id = (hid_t *)malloc(sizeof(hid_t) * open_images)))
FAIL_PUTS_ERROR("malloc() failed");
TESTING("get file images");
/* create several file images */
for (i = 0; i < open_images; i++) {
/* populate array for flags combinations */
input_flags[i] = flags[(nflags + i) % nflags];
/* allocate name buffer for image i */
filename[i] = (char *)HDmalloc(sizeof(char) * 32);
/* create file name */
sprintf(filename[i], "image_file%d.h5", (int)i);
/* create file */
if ((file_id[i] = H5Fcreate(filename[i], H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
FAIL_PUTS_ERROR("H5Fcreate() failed");
/* define dataspace for the dataset */
if ((file_space = H5Screate_simple(RANK, dims1, max_dims)) < 0)
FAIL_PUTS_ERROR("H5Screate_simple() failed");
/* create dataset property list */
if ((plist = H5Pcreate(H5P_DATASET_CREATE)) < 0)
FAIL_PUTS_ERROR("H5Pcreate() failed");
/* set property list to create chunked dataset */
if (H5Pset_chunk(plist, RANK, dims1) < 0)
FAIL_PUTS_ERROR("H5Pset_chunk() failed");
/* create and write an integer type dataset named "dset" */
if ((dset_id[i] = H5Dcreate2(file_id[i], DSET_NAME, H5T_NATIVE_INT, file_space, H5P_DEFAULT, plist, H5P_DEFAULT)) < 0)
FAIL_PUTS_ERROR("H5Dcreate() failed");
/* dataset in open image 1 is written with "wrong" data */
if (i == 1) {
if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data2) < 0)
FAIL_PUTS_ERROR("H5Dwrite() failed");
} /* end if*/
/* dataset in the rest of the open images is written with correct data */
else {
if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1) < 0)
FAIL_PUTS_ERROR("H5Dwrite() failed");
} /* end else */
/* flush into the file */
if (H5Fflush(file_id[i], H5F_SCOPE_LOCAL) < 0)
FAIL_PUTS_ERROR("H5Fflush() failed");
/* close dataset property list */
if (H5Pclose(plist) < 0)
FAIL_PUTS_ERROR("H5Pclose() failed");
/* close dataspace */
if (H5Sclose(file_space) < 0)
FAIL_PUTS_ERROR("H5Sclose() failed");
/* close dataset */
if (H5Dclose(dset_id[i]) < 0)
FAIL_PUTS_ERROR("H5Dclose() failed");
/* get size of the file image i */
if ((buf_size[i] = H5Fget_file_image(file_id[i], NULL, 0)) < 0)
FAIL_PUTS_ERROR("H5Fget_file_image() failed");
/* allocate buffer for the file image i */
if (NULL == (buf_ptr[i] = (void *)HDmalloc((size_t)buf_size[i])))
FAIL_PUTS_ERROR("malloc() failed");
/* buffer for file image 2 is filled with counter data (non-valid image) */
if (i == 2) {
for (j = 0; j < (size_t)buf_size[i]; j++)
((char*)(buf_ptr[i]))[j] = (char)j;
} /* end if */
/* buffers for the rest of the file images are filled with data from the respective files */
else {
if ((buf_size[i] = H5Fget_file_image(file_id[i], buf_ptr[i], (size_t)buf_size[i])) < 0)
FAIL_PUTS_ERROR("H5Fget_file_image() failed");
} /* end else */
/* file close */
if (H5Fclose (file_id[i]) < 0)
FAIL_PUTS_ERROR("H5Fclose() failed");
} /* end for */
PASSED();
TESTING("open file images and check image copies");
/* open the file images with the core driver for data access */
for (i = 0; i < open_images; i++) {
/* open file image 2 filled with counter data (non-valid image) */
if (i == 2) {
H5E_BEGIN_TRY {
/* attempt to set file image in the core driver */
file_id[i] = H5LTopen_file_image(buf_ptr[i], (size_t)buf_size[i], input_flags[i]);
} H5E_END_TRY
VERIFY(file_id[i] < 0, "H5LTopen_file_image() should have failed");
} /* end if */
/* open rest of valid file images */
else {
/* set file image in the core driver */
if ((file_id[i] = H5LTopen_file_image(buf_ptr[i], (size_t)buf_size[i], input_flags[i])) < 0)
FAIL_PUTS_ERROR("H5LTopen_file_image() failed");
/* get pointer to the image buffer of the core driver */
if (H5Fget_vfd_handle(file_id[i], H5P_DEFAULT, &handle_ptr) < 0)
FAIL_PUTS_ERROR("H5Fget_vfd_handle() failed");
core_buf_ptr_ptr = (unsigned char **)handle_ptr;
/* test whether the user buffer has been copied or not */
if (input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY)
VERIFY(*core_buf_ptr_ptr == buf_ptr[i], "vfd buffer and user buffer should have been the same");
else
VERIFY(*core_buf_ptr_ptr != buf_ptr[i], "vfd buffer and user buffer should be different");
/* test whether the contents of the user buffer and driver buffer */
/* are equal. */
if (HDmemcmp(*core_buf_ptr_ptr, buf_ptr[i], (size_t)buf_size[i]) != 0)
FAIL_PUTS_ERROR("comparison of vfd and user buffer failed");
} /* end else */
} /* end for */
PASSED();
TESTING("read file images");
/* read open file images and verify data */
for (i = 0; i < open_images; i++) {
/* if opening the file image failed, continue next iteration */
if (file_id[i] < 0) {
HDassert(i == 2);
continue;
} /* end if */
/* open dataset in file image */
if ((dset_id[i] = H5Dopen2(file_id[i], DSET_NAME, H5P_DEFAULT)) < 0)
FAIL_PUTS_ERROR("H5Dopen() failed");
/* get dataspace for the dataset */
if ((file_space = H5Dget_space(dset_id[i])) < 0)
FAIL_PUTS_ERROR("H5Dget_space() failed");
/* get dimensions for the dataset */
if (H5Sget_simple_extent_dims(file_space, dims3, NULL) < 0)
FAIL_PUTS_ERROR("H5Sget_simple_extent_dims() failed");
/* read dataset */
if (H5Dread(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data3) < 0)
FAIL_PUTS_ERROR("H5Dread() failed");
/* compute number of elements in dataset */
n_values = (size_t)(dims3[0] * dims3[1]);
/* determine the number of rows in dataset */
nrow = (size_t)dims3[1];
/* verify contents for file image 1 with "wrong" data */
if (i == 1) {
/* compare file image values with original data */
for (j = 0; j < n_values / nrow; j++)
for (k = 0; k < nrow; k++)
if (data3[j * nrow + k ] == data1[j * nrow + k ])
FAIL_PUTS_ERROR("comparison of image values with original data should have failed");
} /* end if */
/* verify contents for the rest of the file images */
else {
/* compare file image values with original data */
for (j = 0; j < n_values / nrow; j++)
for (k = 0; k < nrow; k++)
if (data3[j * nrow + k ] != data1[j * nrow + k ])
FAIL_PUTS_ERROR("comparison of image values with original data failed");
} /* end else */
/* close dataspace */
if (H5Sclose (file_space) < 0)
FAIL_PUTS_ERROR("H5Sclose() failed");
} /* end for */
PASSED();
TESTING("write and extend file images");
/* write open file images and verify data */
for (i = 0; i < open_images; i++) {
/* if opening the file image failed, continue next iteration */
if (file_id[i] < 0) {
HDassert(i == 2);
continue;
} /* end if */
/* test data write when file image access is read-only */
if (!(input_flags[i] & H5LT_FILE_IMAGE_OPEN_RW)) {
/* write dataset without extending it */
H5E_BEGIN_TRY {
status1 = H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1);
} H5E_END_TRY;
VERIFY(status1 < 0, "H5Dwrite() should have failed");
/* extend dimensions of dataset */
H5E_BEGIN_TRY {
status1 = H5Dset_extent(dset_id[i], dims4);
} H5E_END_TRY;
VERIFY(status1 < 0, "H5Dset_extent() should have failed");
/* write extended dataset */
H5E_BEGIN_TRY {
status1 = H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data4);
} H5E_END_TRY;
VERIFY(status1 < 0, "H5Dwrite() should have failed");
/* close dataset */
if (H5Dclose(dset_id[i]) < 0)
FAIL_PUTS_ERROR("H5Dclose() failed");
} /* end if */
/* test data write where file image access is read-write */
else {
if ((input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY) && (input_flags[i] & H5LT_FILE_IMAGE_DONT_RELEASE)) {
/* This test is disabled currently, since the new attribute causes the file
* to increase in size, but the realloc call in H5FD_core_write() fails, causing
* the flush operation to fail and the file to fail to close, eventually
* triggering the "infinite loop shutting down the library" problem.
*
* In theory, we could address this through a variety of methods, ranging from
* ignoring failures in H5F_dest() (when called from H5F_try_close()), to
* allocating space more aggressively when creating the attribute, etc.
*
* For now, we will just leave the test commented out and assume that
* application developers who mark their file image as "don't copy" won't
* be likely candidates for modifying their data. - QAK - March 29, 2012
*/
#if 0
int attr_rank = 1;
hsize_t attr_dims[] = {4096};
int attr_data[4096];
hid_t attr_space_id = -1;
hid_t attr_id = -1;
herr_t status2;
size_t l;
if ((attr_space_id = H5Screate_simple(attr_rank, attr_dims, attr_dims)) < 0)
FAIL_PUTS_ERROR("attr_space H5Screate_simple() failed");
if((attr_id = H5Acreate_by_name(dset_id[i], ".", "int array_addr", H5T_NATIVE_INT, attr_space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
FAIL_PUTS_ERROR("H5Acreate_by_name() failed");
for(l = 0; l < 4096; l++)
attr_data[l] = (int)l;
/* write data to the attribute and then flush the file. One or the other should
* should trigger an extension to the EOA, which in turn should cause the realloc
* callback to fail.
*/
H5E_BEGIN_TRY {
status1 = status2 = -1;
status1 = H5Awrite(attr_id, H5T_NATIVE_INT, (const void *)attr_data);
if(status1 >= 0)
status2 = H5Fflush(file_id[i], H5F_SCOPE_GLOBAL);
VERIFY(status1 < 0 || status2 < 0, "writing and flushing attr should have failed");
} H5E_END_TRY;
/* close attr and attr_space -- expect errors on close */
H5E_BEGIN_TRY {
H5Sclose(attr_space_id);
H5Aclose(attr_id);
} H5E_END_TRY;
#endif
file_id[i] = -1;
} /* end if */
else {
/* write dataset without extending it */
if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1) < 0)
FAIL_PUTS_ERROR("H5Dwrite() failed");
/* extend dimensions of dataset */
if (H5Dset_extent(dset_id[i], dims4) < 0)
FAIL_PUTS_ERROR("H5Dset_extent() failed");
/* write extended dataset */
if (H5Dwrite(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data4) < 0)
FAIL_PUTS_ERROR("H5Dwrite() failed");
/* close dataset */
if (H5Dclose(dset_id[i]) < 0)
FAIL_PUTS_ERROR("H5Dclose() failed");
} /* end else */
} /* end else */
} /* end for */
PASSED();
TESTING("read extended file images");
/* read open file images and verify data */
for (i = 0; i < open_images; i++) {
/* if opening the file image failed, continue next iteration */
if ((file_id[i] < 0) || (!(input_flags[i] & H5LT_FILE_IMAGE_OPEN_RW )))
continue;
/* open dataset in file image */
if ((dset_id[i] = H5Dopen2(file_id[i], DSET_NAME, H5P_DEFAULT)) < 0)
FAIL_PUTS_ERROR("H5Dopen() failed");
/* get dataspace for the dataset */
if ((file_space = H5Dget_space(dset_id[i])) < 0)
FAIL_PUTS_ERROR("H5Dget_space() failed");
/* get dimensions for the dataset */
if (H5Sget_simple_extent_dims(file_space, dims3, NULL) < 0)
FAIL_PUTS_ERROR("H5Sget_simple_extent_dims() failed");
/* read dataset */
if (H5Dread(dset_id[i], H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data3) < 0)
FAIL_PUTS_ERROR("H5Dread() failed");
/* compute number of elements in dataset */
n_values = (size_t)(dims3[0] * dims3[1]);
/* determine the number of rows in dataset */
nrow = (size_t)dims3[1];
/* verify contents for the file images */
for (j = 0; j < n_values / nrow; j++)
for (k = 0; k < nrow; k++)
if (data3[j * nrow + k ] != data4[j * nrow + k ])
FAIL_PUTS_ERROR("comparison of image values with original data failed");
/* close dataspace */
if (H5Sclose (file_space) < 0)
FAIL_PUTS_ERROR("H5Sclose() failed");
/* close dataset */
if (H5Dclose(dset_id[i]) < 0)
FAIL_PUTS_ERROR("H5Dclose() failed");
} /* end for */
PASSED()
TESTING("close file images");
/* close file images and release buffer if appropriate */
for (i = 0; i < open_images; i++) {
/* close file is appropriate */
if (file_id[i] >= 0) {
/* close file image */
if (H5Fclose(file_id[i]) < 0)
FAIL_PUTS_ERROR("H5Fclose() failed");
} /* end if */
/* delete test data files */
if (HDremove(filename[i]) < 0)
FAIL_PUTS_ERROR("HDremove() failed");
/* free shared buffer if appropriate */
if (!(input_flags[i] & H5LT_FILE_IMAGE_DONT_COPY) || (input_flags[i] & H5LT_FILE_IMAGE_DONT_RELEASE)) {
VERIFY(buf_ptr[i] != NULL, "buffer pointer must be non NULL");
HDfree(buf_ptr[i]);
} /* end if */
} /* end for */
/* release temporary working buffers */
HDfree(filename);
HDfree(file_id);
HDfree(dset_id);
HDfree(buf_ptr);
HDfree(buf_size);
HDfree(input_flags);
PASSED();
H5close();
return 0;
error:
H5_FAILED();
return -1;
}
/*-------------------------------------------------------------------------
* the main program
*-------------------------------------------------------------------------
*/
int main( void )
{
int nerrors = 0;
size_t open_images = 10; /* number of open file images */
size_t nflags = 8; /* number of flag combinations */
unsigned flags[8]; /* array with flag combinations */
/* set flag combinations for testing */
flags[0] = 0;
flags[1] = H5LT_FILE_IMAGE_DONT_RELEASE;
flags[2] = H5LT_FILE_IMAGE_DONT_COPY;
flags[3] = H5LT_FILE_IMAGE_DONT_COPY | H5LT_FILE_IMAGE_DONT_RELEASE;
flags[4] = H5LT_FILE_IMAGE_OPEN_RW;
flags[5] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_RELEASE;
flags[6] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_COPY;
flags[7] = H5LT_FILE_IMAGE_OPEN_RW | H5LT_FILE_IMAGE_DONT_COPY | H5LT_FILE_IMAGE_DONT_RELEASE;
/* Test file image operations. The flag combinations are assigned to file images in round-robin fashion */
nerrors += test_file_image(open_images, nflags, flags) < 0? 1 : 0;
if (nerrors) goto error;
printf("File image tests passed.\n");
return 0;
error:
printf("***** %d IMAGE TEST%s FAILED! *****\n",nerrors, 1 == nerrors ? "" : "S");
return 1;
}

View File

@ -2436,7 +2436,8 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id)
udata.dxpl_id = dxpl_id;
/* Iterate over all the open datasets */
H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE);
if(H5I_iterate(H5I_DATASET, H5D_flush_cb, &udata, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info")
done:
FUNC_LEAVE_NOAPI(ret_value)

View File

@ -107,7 +107,7 @@ static H5E_cls_t *H5E_register_class(const char *cls_name, const char *lib_name,
const char *version);
static herr_t H5E_unregister_class(H5E_cls_t *cls);
static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size);
static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key);
static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata);
static herr_t H5E_close_msg(H5E_msg_t *err);
static H5E_msg_t *H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg);
static H5E_t *H5E_get_current_stack(void);
@ -543,8 +543,8 @@ H5E_unregister_class(H5E_cls_t *cls)
HDassert(cls);
/* Iterate over all the messages and delete those in this error class */
/* (Ignore return value, since callback isn't designed to return a particular object) */
(void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE);
if(H5I_iterate(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class")
/* Free error class structure */
if(H5E_free_class(cls) < 0)
@ -631,7 +631,7 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size)
/*-------------------------------------------------------------------------
* Function: H5E_close_msg_cb
*
* Purpose: H5I_search callback function to close error messages in the
* Purpose: H5I_iterate callback function to close error messages in the
* error class.
*
* Return: Non-negative value on success/Negative on failure
@ -642,10 +642,10 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size)
*-------------------------------------------------------------------------
*/
static int
H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key)
H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata)
{
H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr;
H5E_cls_t *cls = (H5E_cls_t*)key;
H5E_cls_t *cls = (H5E_cls_t*)udata;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT

View File

@ -93,6 +93,7 @@ hid_t H5E_CANTRELEASE_g = FAIL; /* Unable to release object */
hid_t H5E_CANTGET_g = FAIL; /* Can't get value */
hid_t H5E_CANTSET_g = FAIL; /* Can't set value */
hid_t H5E_DUPCLASS_g = FAIL; /* Duplicate class name in parent class */
hid_t H5E_SETDISALLOWED_g = FAIL; /* Disallowed operation */
/* Free space errors */
hid_t H5E_CANTMERGE_g = FAIL; /* Can't merge objects */

View File

@ -339,6 +339,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Duplicate class name in parent class")
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_SETDISALLOWED_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Disallowed operation"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_SETDISALLOWED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Free space errors */
assert(H5E_CANTMERGE_g==(-1));

View File

@ -155,9 +155,11 @@ H5_DLLVAR hid_t H5E_CANTRELEASE_g; /* Unable to release object */
#define H5E_CANTGET (H5OPEN H5E_CANTGET_g)
#define H5E_CANTSET (H5OPEN H5E_CANTSET_g)
#define H5E_DUPCLASS (H5OPEN H5E_DUPCLASS_g)
#define H5E_SETDISALLOWED (H5OPEN H5E_SETDISALLOWED_g)
H5_DLLVAR hid_t H5E_CANTGET_g; /* Can't get value */
H5_DLLVAR hid_t H5E_CANTSET_g; /* Can't set value */
H5_DLLVAR hid_t H5E_DUPCLASS_g; /* Duplicate class name in parent class */
H5_DLLVAR hid_t H5E_SETDISALLOWED_g; /* Disallowed operation */
/* Free space errors */
#define H5E_CANTMERGE (H5OPEN H5E_CANTMERGE_g)

View File

@ -94,7 +94,8 @@ H5E_CANTRELEASE_g=
/* Property list errors */
H5E_CANTGET_g=
H5E_CANTSET_g=
H5E_DUPCLASS_g=
H5E_DUPCLASS_g=
H5E_SETDISALLOWED_g=
/* Free space errors */
H5E_CANTMERGE_g=

284
src/H5F.c
View File

@ -52,7 +52,7 @@ typedef struct H5F_olist_t {
} H5F_olist_t;
/* PRIVATE PROTOTYPES */
static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id,
H5FD_t *lf);
@ -363,11 +363,6 @@ done:
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value to ssize_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
@ -375,18 +370,24 @@ ssize_t
H5Fget_obj_count(hid_t file_id, unsigned types)
{
H5F_t *f = NULL; /* File to query */
ssize_t ret_value; /* Return value */
size_t obj_count = 0; /* Number of opened objects */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("Zs", "iIu", file_id, types);
/* Check arguments */
if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
/* H5F_get_obj_count doesn't fail */
ret_value = (ssize_t)H5F_get_obj_count(f, types, TRUE);
/* Perform the query */
if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
/* Set the return value */
ret_value = (ssize_t)obj_count;
done:
FUNC_LEAVE_API(ret_value)
@ -399,31 +400,30 @@ done:
* Purpose: Private function return the number of opened object IDs
* (files, datasets, groups, datatypes) in the same file.
*
* Return: Non-negative on success; can't fail.
* Return: SUCCEED on success, FAIL on failure.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value to size_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
size_t
H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
herr_t
H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr)
{
size_t ret_value; /* Return value */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT_NOERR
FUNC_ENTER_NOAPI(FAIL)
/* H5F_get_objects doesn't fail */
ret_value = H5F_get_objects(f, types, 0, NULL, app_ref);
/* Sanity check */
HDassert(obj_id_count_ptr);
/* Perform the query */
if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
} /* end H5F_get_obj_count() */
/*-------------------------------------------------------------------------
@ -448,19 +448,25 @@ ssize_t
H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
{
H5F_t *f = NULL; /* File to query */
ssize_t ret_value; /* Return value */
size_t obj_id_count = 0; /* Number of open objects */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list);
/* Check arguments */
if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
HDassert(oid_list);
/* H5F_get_objects doesn't fail */
ret_value = (ssize_t)H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE);
/* Perform the query */
if(H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_id_count) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed")
/* Set the return value */
ret_value = (ssize_t)obj_id_count;
done:
FUNC_LEAVE_API(ret_value)
@ -477,26 +483,25 @@ done:
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value and MAX_OBJTS to size_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
size_t
H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref)
herr_t
H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr)
{
size_t ret_value; /* Return value */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
FUNC_ENTER_NOAPI(FAIL)
/* H5F_get_objects doesn't fail */
ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref);
/* Sanity check */
HDassert(obj_id_count_ptr);
/* Perform the query */
if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
} /* end H5F_get_obj_ids() */
/*---------------------------------------------------------------------------
@ -512,14 +517,18 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list
*
*---------------------------------------------------------------------------
*/
static size_t
H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref)
static herr_t
H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr)
{
size_t obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
size_t ret_value; /* Return value */
htri_t type_exists; /* Whether objects of a type are open */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
FUNC_ENTER_NOAPI_NOINIT
/* Sanity check */
HDassert(obj_id_count_ptr);
/* Set up search information */
olist.obj_id_list = (max_index==0 ? NULL : obj_id_list);
@ -537,45 +546,50 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_
olist.file_info.ptr.shared = f ? f->shared : NULL;
} /* end else */
/* Search through file IDs to count the number, and put their
* IDs on the object list. H5I_search returns NULL if no object
* is found, so don't return failure in this function. */
/* Iterate through file IDs to count the number, and put their
* IDs on the object list. */
if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
(void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref);
if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
} /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATASET) {
olist.obj_type = H5I_DATASET;
(void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref);
}
if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
} /* end if */
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
if(types & H5F_OBJ_GROUP) {
olist.obj_type = H5I_GROUP;
(void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref);
}
if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
} /* end if */
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATATYPE) {
olist.obj_type = H5I_DATATYPE;
(void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref);
}
if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
} /* end if */
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
if(types & H5F_OBJ_ATTR) {
olist.obj_type = H5I_ATTR;
(void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref);
}
if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
} /* end if */
/* Set the number of objects currently open */
ret_value = obj_id_count;
*obj_id_count_ptr = obj_id_count;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_objects() */
@ -593,8 +607,6 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
*
*-------------------------------------------------------------------------
*/
static int
@ -626,8 +638,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
* preset to FALSE) because H5I_search needs the return value of FALSE
* to continue searching. */
* preset to FALSE) because H5I_iterate needs the return value of
* FALSE to continue the iteration. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
}
@ -691,8 +703,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
* preset to FALSE) because H5I_search needs the return value of FALSE
* to continue searching. */
* preset to FALSE) because H5I_iterate needs the return value of
* FALSE to continue iterating. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
} /* end if */
@ -1785,8 +1797,6 @@ done:
* Programmer: Quincey Koziol
* Tuesday, July 19, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
@ -1868,27 +1878,36 @@ H5F_try_close(H5F_t *f)
if(f->nopen_objs > 0) {
size_t obj_count; /* # of open objects */
hid_t objs[128]; /* Array of objects to close */
herr_t result; /* Local result from obj ID query */
size_t u; /* Local index variable */
/* Get the list of IDs of open dataset, group, & attribute objects */
while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
&& obj_count != 0 ) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
if(result < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)")
/* Get the list of IDs of open named datatype objects */
/* (Do this separately from the dataset & attribute IDs, because
* they could be using one of the named datatypes and then the
* open named datatype ID will get closed twice)
*/
while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
&& obj_count != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
if(result < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)")
} /* end if */
} /* end if */
@ -2549,6 +2568,139 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_filesize() */
/*-------------------------------------------------------------------------
* Function: H5Fget_file_image
*
* Purpose: If a buffer is provided (via the buf_ptr argument) and is
* big enough (size in buf_len argument), load *buf_ptr with
* an image of the open file whose ID is provided in the
* file_id parameter, and return the number of bytes copied
* to the buffer.
*
* If the buffer exists, but is too small to contain an image
* of the indicated file, return a negative number.
*
* Finally, if no buffer is provided, return the size of the
* buffer needed. This value is simply the eoa of the target
* file.
*
* Note that any user block is skipped.
*
* Also note that the function may not be used on files
* opened with either the split/multi file driver or the
* family file driver.
*
* In the former case, the sparse address space makes the
* get file image operation impractical, due to the size of
* the image typically required.
*
* In the case of the family file driver, the problem is
* the driver message in the super block, which will prevent
* the image being opened with any driver other than the
* family file driver -- which negates the purpose of the
* operation. This can be fixed, but no resources for
* this now.
*
* Return: Success: Bytes copied / number of bytes needed.
* Failure: negative value
*
* Programmer: John Mainzer
* 11/15/11
*
*-------------------------------------------------------------------------
*/
ssize_t
H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
{
H5F_t *file; /* File object for file ID */
H5FD_t *fd_ptr; /* file driver */
haddr_t eoa; /* End of file address */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("Zs", "i*xz", file_id, buf_ptr, buf_len);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
if(!file || !file->shared || !file->shared->lf)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer")
fd_ptr = file->shared->lf;
if(!fd_ptr->cls)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer")
/* the address space used by the split and multi file drivers is not
* a good fit for this call. Since the plan is to depreciate these
* drivers anyway, don't bother to do a "force fit".
*
* The following clause tests for the multi file driver, and fails
* if the supplied file has the multi file driver as its top level
* file driver. However, this test will not work if there is some
* other file driver sitting on top of the multi file driver.
*
* I'm not sure if this is possible at present, but in all likelyhood,
* it will become possible in the future. On the other hand, we may
* remove the split/multi file drivers before then.
*
* I am leaving this solution in for now, but we should review it,
* and improve the solution if necessary.
*
* JRM -- 11/11/22
*/
if(HDstrcmp(fd_ptr->cls->name, "multi") == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.")
/* While the family file driver is conceptually fully compatible
* with the get file image operation, it sets a file driver message
* in the super block that prevents the image being opened with any
* driver other than the family file driver. Needless to say, this
* rather defeats the purpose of the get file image operation.
*
* While this problem is quire solvable, the required time and
* resources are lacking at present. Hence, for now, we don't
* allow the get file image operation to be perfomed on files
* opened with the family file driver.
*
* Observe that the following test only looks at the top level
* driver, and fails if there is some other driver sitting on to
* of the family file driver.
*
* I don't think this can happen at present, but that may change
* in the future.
* JRM -- 12/21/11
*/
if(HDstrcmp(fd_ptr->cls->name, "family") == 0)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.")
/* Go get the actual file size */
if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
/* set ret_value = to eoa -- will overwrite this if appropriate */
ret_value = (ssize_t)eoa;
/* test to see if a buffer was provided -- if not, we are done */
if(buf_ptr != NULL) {
size_t space_needed; /* size of file image */
/* Check for buffer too small */
if((haddr_t)buf_len < eoa)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small")
space_needed = (size_t)eoa;
/* read in the file image */
/* (Note compensation for base address addition in internal routine) */
if(H5FD_read(fd_ptr, H5AC_ind_dxpl_id, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed")
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_file_image() */
/*-------------------------------------------------------------------------
* Function: H5Fget_mdc_config

View File

@ -70,6 +70,10 @@ static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size,
static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *),
void *pl);
static herr_t H5FD_free_cls(H5FD_class_t *cls);
static herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl);
static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl);
static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
static int H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/);
/*********************/
/* Package Variables */
@ -750,17 +754,15 @@ done:
* Programmer: Robb Matzke
* Tuesday, August 3, 1999
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
static herr_t
H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl)
{
H5FD_class_t *driver;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
FUNC_ENTER_NOAPI_NOINIT
/* Check args */
if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
@ -871,17 +873,15 @@ done:
* Programmer: Robb Matzke
* Tuesday, August 3, 1999
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
static herr_t
H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl, void **copied_dxpl)
{
H5FD_class_t *driver;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
FUNC_ENTER_NOAPI_NOINIT
/* Check args */
if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
@ -1039,6 +1039,8 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
H5FD_t *file = NULL; /* VFD file struct */
hid_t driver_id = -1; /* VFD ID */
H5P_genplist_t *plist; /* Property list pointer */
unsigned long driver_flags = 0; /* File-inspecific driver feature flags */
H5FD_file_image_info_t file_image_info; /* Initial file image */
H5FD_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@ -1061,6 +1063,19 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
if(NULL == driver->open)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method")
/* Query driver flag */
H5FD_driver_query(driver, &driver_flags);
/* Get initial file image info */
if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file image info")
/* If an image is provided, make sure the driver supports this feature */
HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) ||
((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
if((file_image_info.buffer != NULL) && !(driver_flags & H5FD_FEAT_ALLOW_FILE_IMAGE))
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file image set, but not supported.")
/* Dispatch to file driver */
if(HADDR_UNDEF == maxaddr)
maxaddr = driver->maxaddr;
@ -1318,19 +1333,17 @@ done:
* Programmer: Quincey Koziol
* Friday, August 25, 2000
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
static int
H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/)
{
int ret_value=0;
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
FUNC_ENTER_NOAPI_NOINIT
assert(f);
assert(flags);
HDassert(f);
HDassert(flags);
/* Check for query driver and call it */
if(f->cls->query)
@ -1340,7 +1353,44 @@ H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
} /* end H5FD_query() */
/*-------------------------------------------------------------------------
* Function: H5FD_driver_query
*
* Purpose: Similar to H5FD_query(), but intended for cases when we don't
* have a file available (e.g. before one is opened). Since we
* can't use the file to get the driver, the driver is passed in
* as a parameter.
*
* Return: Success: non-negative
* Failure: negative
*
* Programmer: Jacob Gruber
* Wednesday, August 17, 2011
*
*-------------------------------------------------------------------------
*/
static int
H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/)
{
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
HDassert(driver);
HDassert(flags);
/* Check for the driver to query and then query it */
if(driver->query)
ret_value = (driver->query)(NULL, flags);
else
*flags = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_driver_query() */
/*-------------------------------------------------------------------------

View File

@ -101,6 +101,7 @@ typedef struct H5FD_core_t {
HANDLE hFile; /* Native windows file handle */
#endif /* H5_HAVE_WIN32_API */
hbool_t dirty; /*changes not saved? */
H5FD_file_image_callbacks_t fi_callbacks; /* file image callbacks */
} H5FD_core_t;
/* Driver-specific file access properties */
@ -412,6 +413,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
#endif
h5_stat_t sb;
int fd=-1;
H5FD_file_image_info_t file_image_info;
H5FD_t *ret_value;
FUNC_ENTER_NOAPI_NOINIT
@ -434,10 +436,32 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
if(H5F_ACC_CREAT & flags) o_flags |= O_CREAT;
if(H5F_ACC_EXCL & flags) o_flags |= O_EXCL;
/* Retrieve initial file image info */
if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial file image info")
/* If the file image exists and this is an open, make sure the file doesn't exist */
HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) ||
((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) {
if(HDopen(name, o_flags, 0666) >= 0)
HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists")
/* If backing store is requested, create and stat the file
* Note: We are forcing the O_CREAT flag here, even though this is
* technically an open.
*/
if(fa->backing_store) {
if((fd = HDopen(name, o_flags | O_CREAT, 0666)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file")
if(HDfstat(fd, &sb) < 0)
HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
} /* end if */
} /* end if */
/* Open backing store, and get stat() from file. The only case that backing
* store is off is when the backing_store flag is off and H5F_ACC_CREAT is
* on. */
if(fa->backing_store || !(H5F_ACC_CREAT & flags)) {
else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) {
if(fa && (fd = HDopen(name, o_flags, 0666)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
if(HDfstat(fd, &sb) < 0)
@ -460,6 +484,9 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
/* If save data in backing store. */
file->backing_store = fa->backing_store;
/* Save file image callbacks */
file->fi_callbacks = file_image_info.callbacks;
if(fd >= 0) {
/* Retrieve information for determining uniqueness of file */
#ifdef H5_HAVE_WIN32_API
@ -491,51 +518,70 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
size_t size;
/* Retrieve file size */
size = (size_t)sb.st_size;
if(file_image_info.buffer && file_image_info.size > 0)
size = file_image_info.size;
else
size = (size_t)sb.st_size;
/* Check if we should allocate the memory buffer and read in existing data */
if(size) {
/* Allocate memory for the file's data */
if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory block")
/* Allocate memory for the file's data, using the file image callback if available. */
if(file->fi_callbacks.image_malloc) {
if(NULL == (file->mem = (unsigned char*)file->fi_callbacks.image_malloc(size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "image malloc callback failed")
} /* end if */
else {
if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate memory block")
} /* end else */
/* Set up data structures */
file->eof = size;
/* Read in existing data, being careful of interrupted system calls,
* partial results, and the end of the file.
*/
while(size > 0) {
h5_core_io_t bytes_in = 0; /* # of bytes to read */
h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */
/* Trying to read more bytes than the return type can handle is
* undefined behavior in POSIX.
*/
if(size > H5_CORE_MAX_IO_BYTES_g)
bytes_in = H5_CORE_MAX_IO_BYTES_g;
else
bytes_in = (h5_core_io_t)size;
do {
bytes_read = HDread(file->fd, file->mem, bytes_in);
} while(-1 == bytes_read && EINTR == errno);
if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset);
/* If there is an initial file image, copy it, using the callback if possible */
if(file_image_info.buffer && file_image_info.size > 0) {
if(file->fi_callbacks.image_memcpy) {
if(file->mem != file->fi_callbacks.image_memcpy(file->mem, file_image_info.buffer, size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata))
HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed")
} /* end if */
HDassert(bytes_read >= 0);
HDassert((size_t)bytes_read <= size);
size -= (size_t)bytes_read;
} /* end while */
else
HDmemcpy(file->mem, file_image_info.buffer, size);
} /* end if */
/* Read in existing data from the file if there is no image */
else {
/* Read in existing data, being careful of interrupted system calls,
* partial results, and the end of the file.
*/
while(size > 0) {
h5_core_io_t bytes_in = 0; /* # of bytes to read */
h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */
/* Trying to read more bytes than the return type can handle is
* undefined behavior in POSIX.
*/
if(size > H5_CORE_MAX_IO_BYTES_g)
bytes_in = H5_CORE_MAX_IO_BYTES_g;
else
bytes_in = (h5_core_io_t)size;
do {
bytes_read = HDread(file->fd, file->mem, bytes_in);
} while(-1 == bytes_read && EINTR == errno);
if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset);
} /* end if */
HDassert(bytes_read >= 0);
HDassert((size_t)bytes_read <= size);
size -= (size_t)bytes_read;
} /* end while */
} /* end else */
} /* end if */
} /* end if */
@ -578,8 +624,15 @@ H5FD_core_close(H5FD_t *_file)
HDclose(file->fd);
if(file->name)
H5MM_xfree(file->name);
if(file->mem)
H5MM_xfree(file->mem);
if(file->mem) {
/* Use image callback if available */
if(file->fi_callbacks.image_free) {
if(file->fi_callbacks.image_free(file->mem, H5FD_FILE_IMAGE_OP_FILE_CLOSE, file->fi_callbacks.udata) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "image_free callback failed")
} /* end if */
else
H5MM_xfree(file->mem);
} /* end if */
HDmemset(file, 0, sizeof(H5FD_core_t));
H5MM_xfree(file);
@ -700,9 +753,11 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
*flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
*flags |= H5FD_FEAT_ALLOW_FILE_IMAGE; /* OK to use file image feature with this VFD */
*flags |= H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS; /* OK to use file image callbacks with this VFD */
/* If the backing store is open, a POSIX file handle is available */
if(file->fd >= 0 && file->backing_store)
if(file && file->fd >= 0 && file->backing_store)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
} /* end if */
@ -976,9 +1031,16 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had
if((addr + size) % file->increment)
new_eof += file->increment;
/* (Re)allocate memory for the file buffer */
if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof)
/* (Re)allocate memory for the file buffer, using callbacks if available */
if(file->fi_callbacks.image_realloc) {
if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes with callback", (unsigned long long)new_eof)
} /* end if */
else {
if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof)
} /* end else */
#ifdef H5_CLEAR_MEMORY
HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
#endif /* H5_CLEAR_MEMORY */
@ -989,6 +1051,8 @@ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
/* Write from BUF to memory */
HDmemcpy(file->mem + addr, buf, size);
/* Mark memory buffer as modified */
file->dirty = TRUE;
done:
@ -1075,6 +1139,28 @@ done:
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
*
* Addendum -- 12/2/11
* For file images opened with the core file driver, it is
* necessary that we avoid reallocating the core file driver's
* buffer uneccessarily.
*
* To this end, I have made the following functional changes
* to this function.
*
* If we are closing, and there is no backing store, this
* function becomes a no-op.
*
* If we are closing, and there is backing store, we set the
* eof to equal the eoa, and truncate the backing store to
* the new eof
*
* If we are not closing, we realloc the buffer to size equal
* to the smallest multiple of the allocation increment that
* equals or exceeds the eoa and set the eof accordingly.
* Note that we no longer truncate the backing store to the
* new eof if applicable.
* -- JRM
*
* Return: Success: Non-negative
* Failure: Negative
*
@ -1085,7 +1171,7 @@ done:
*/
/* ARGSUSED */
static herr_t
H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
{
H5FD_core_t *file = (H5FD_core_t*)_file;
size_t new_eof; /* New size of memory buffer */
@ -1095,68 +1181,83 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
HDassert(file);
/* Determine new size of memory buffer */
H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t);
if(file->eoa % file->increment)
new_eof += file->increment;
/* if we are closing and not using backing store, do nothing */
if(!closing || file->backing_store) {
if(closing) /* set eof to eoa */
new_eof = file->eoa;
else { /* set eof to smallest multiple of increment that exceeds eoa */
/* Determine new size of memory buffer */
H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t);
if(file->eoa % file->increment)
new_eof += file->increment;
} /* end else */
/* Extend the file to make sure it's large enough */
if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) {
unsigned char *x; /* Pointer to new buffer for file data */
/* Extend the file to make sure it's large enough */
if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) {
unsigned char *x; /* Pointer to new buffer for file data */
/* (Re)allocate memory for the file buffer, using callback if available */
if(file->fi_callbacks.image_realloc) {
if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block with callback")
} /* end if */
else {
if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block")
} /* end else */
/* (Re)allocate memory for the file buffer */
if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
#ifdef H5_CLEAR_MEMORY
if(file->eof < new_eof)
HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
if(file->eof < new_eof)
HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
#endif /* H5_CLEAR_MEMORY */
file->mem = x;
file->mem = x;
/* Update backing store, if using it */
if(file->fd >= 0 && file->backing_store) {
/* Update backing store, if using it and if closing */
if(closing && (file->fd >= 0) && file->backing_store) {
#ifdef H5_HAVE_WIN32_API
LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
* Only used as an error code here.
*/
DWORD dwError; /* DWORD error code from GetLastError() */
BOOL bError; /* Boolean error flag */
LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
* Only used as an error code here.
*/
DWORD dwError; /* DWORD error code from GetLastError() */
BOOL bError; /* Boolean error flag */
/* Windows uses this odd QuadPart union for 32/64-bit portability */
li.QuadPart = (__int64)file->eoa;
/* Windows uses this odd QuadPart union for 32/64-bit portability */
li.QuadPart = (__int64)file->eoa;
/* Extend the file to make sure it's large enough.
*
* Since INVALID_SET_FILE_POINTER can technically be a valid return value
* from SetFilePointer(), we also need to check GetLastError().
*/
dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
if(INVALID_SET_FILE_POINTER == dwPtrLow) {
dwError = GetLastError();
if(dwError != NO_ERROR )
HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
}
/* Extend the file to make sure it's large enough.
*
* Since INVALID_SET_FILE_POINTER can technically be a valid return value
* from SetFilePointer(), we also need to check GetLastError().
*/
dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
if(INVALID_SET_FILE_POINTER == dwPtrLow) {
dwError = GetLastError();
if(dwError != NO_ERROR )
HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
}
bError = SetEndOfFile(file->hFile);
if(0 == bError)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
bError = SetEndOfFile(file->hFile);
if(0 == bError)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* H5_HAVE_WIN32_API */
#ifdef H5_VMS
/* Reset seek offset to the beginning of the file, so that the file isn't
* re-extended later. This may happen on Open VMS. */
if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
/* Reset seek offset to the beginning of the file, so that the file isn't
* re-extended later. This may happen on Open VMS. */
if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
#endif /* H5_VMS */
if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* H5_HAVE_WIN32_API */
} /* end if */
} /* end if */
/* Update the eof value */
file->eof = new_eof;
} /* end if */
/* Update the eof value */
file->eof = new_eof;
} /* end if */
} /* end if(file->eof < file->eoa) */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_core_truncate() */

View File

@ -995,7 +995,7 @@ H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
/* Check for flags that are set by h5repart */
if(file->repart_members)
if(file && file->repart_members)
*flags |= H5FD_FEAT_DIRTY_SBLK_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */
} /* end if */

View File

@ -918,7 +918,7 @@ H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
/* Check for flags that are set by h5repart */
if(file->fam_to_sec2)
if(file && file->fam_to_sec2)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */

View File

@ -52,6 +52,29 @@ typedef enum {
} H5FD_file_op_t;
/* Define structure to hold initial file image and other relevant information */
typedef struct {
void *buffer;
size_t size;
H5FD_file_image_callbacks_t callbacks;
} H5FD_file_image_info_t;
/* Define default file image info */
#define H5FD_DEFAULT_FILE_IMAGE_INFO { \
/* file image buffer */ NULL, \
/* buffer size */ 0, \
{ /* Callbacks */ \
/* image_malloc */ NULL, \
/* image_memcpy */ NULL, \
/* image_realloc */ NULL, \
/* image_free */ NULL, \
/* udata_copy */ NULL, \
/* udata_free */ NULL, \
/* udata */ NULL, \
} \
}
/*****************************/
/* Library Private Variables */
/*****************************/
@ -72,17 +95,14 @@ H5_DLL herr_t H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf);
H5_DLL herr_t H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf);
H5_DLL void *H5FD_fapl_get(H5FD_t *file);
H5_DLL herr_t H5FD_fapl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info);
H5_DLL herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl);
H5_DLL herr_t H5FD_fapl_close(hid_t driver_id, void *fapl);
H5_DLL herr_t H5FD_dxpl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info);
H5_DLL herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl);
H5_DLL herr_t H5FD_dxpl_close(hid_t driver_id, void *dxpl);
H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref);
H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
H5_DLL herr_t H5FD_close(H5FD_t *file);
H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2);
H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f,
hsize_t size, haddr_t *align_addr, hsize_t *align_size);
H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f,

View File

@ -222,6 +222,19 @@ typedef enum H5F_mem_t H5FD_mem_t;
* instead of the default H5D_ALLOC_TIME_LATE
*/
#define H5FD_FEAT_ALLOCATE_EARLY 0x00000200
/*
* Defining the H5FD_FEAT_ALLOW_FILE_IMAGE for a VFL driver means that
* the driver is able to use a file image in the fapl as the initial
* contents of a file.
*/
#define H5FD_FEAT_ALLOW_FILE_IMAGE 0x00000400
/*
* Defining the H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS for a VFL driver
* means that the driver is able to use callbacks to make a copy of the
* image to store in memory.
*/
#define H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS 0x00000800
/* Forward declaration */
typedef struct H5FD_t H5FD_t;
@ -291,6 +304,33 @@ struct H5FD_t {
hsize_t alignment; /* Allocation alignment */
};
/* Define enum for the source of file image callbacks */
typedef enum {
H5FD_FILE_IMAGE_OP_NO_OP,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE,
H5FD_FILE_IMAGE_OP_FILE_OPEN,
H5FD_FILE_IMAGE_OP_FILE_RESIZE,
H5FD_FILE_IMAGE_OP_FILE_CLOSE,
} H5FD_file_image_op_t;
/* Define structure to hold file image callbacks */
typedef struct {
void *(*image_malloc)(size_t size, H5FD_file_image_op_t file_image_op,
void *udata);
void *(*image_memcpy)(void *dest, const void *src, size_t size,
H5FD_file_image_op_t file_image_op, void *udata);
void *(*image_realloc)(void *ptr, size_t size,
H5FD_file_image_op_t file_image_op, void *udata);
herr_t (*image_free)(void *ptr, H5FD_file_image_op_t file_image_op,
void *udata);
void *(*udata_copy)(void *udata);
herr_t (*udata_free)(void *udata);
void *udata;
} H5FD_file_image_callbacks_t;
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -560,7 +560,7 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */)
*flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
/* Check for flags that are set by h5repart */
if(file->fam_to_sec2)
if(file && file->fam_to_sec2)
*flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
} /* end if */

View File

@ -417,6 +417,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
#define H5F_ACS_LATEST_FORMAT_NAME "latest_format" /* 'Use latest format version' flag */
#define H5F_ACS_WANT_POSIX_FD_NAME "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address */
#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */
#define H5F_ACS_FILE_IMAGE_INFO_NAME "file_image_info" /* struct containing initial file image and callback info */
/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
@ -528,8 +529,8 @@ H5_DLL H5F_t *H5F_get_parent(const H5F_t *f);
H5_DLL unsigned H5F_get_nmounts(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref);
H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr);
H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr);
/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);

View File

@ -192,6 +192,7 @@ H5_DLL herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist);
H5_DLL herr_t H5Funmount(hid_t loc, const char *name);
H5_DLL hssize_t H5Fget_freespace(hid_t file_id);
H5_DLL herr_t H5Fget_filesize(hid_t file_id, hsize_t *size);
H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void * buf_ptr, size_t buf_len);
H5_DLL herr_t H5Fget_mdc_config(hid_t file_id,
H5AC_cache_config_t * config_ptr);
H5_DLL herr_t H5Fset_mdc_config(hid_t file_id,

View File

@ -782,7 +782,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_name_replace_cb
*
* Purpose: H5I_search callback function to replace group entry names
* Purpose: H5I_iterate callback function to replace group entry names
*
* Return: Success: 0, Failure: -1
*
@ -1166,15 +1166,18 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
/* Search through group IDs */
if(search_group)
H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE);
if(H5I_iterate(H5I_GROUP, H5G_name_replace_cb, &names, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over groups")
/* Search through dataset IDs */
if(search_dataset)
H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE);
if(H5I_iterate(H5I_DATASET, H5G_name_replace_cb, &names, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datasets")
/* Search through datatype IDs */
if(search_datatype)
H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE);
if(H5I_iterate(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datatypes")
} /* end if */
} /* end if */

144
src/H5I.c
View File

@ -108,6 +108,11 @@ typedef struct {
H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */
} H5I_id_type_t;
typedef struct {
H5I_search_func_t app_cb; /* Application's callback routine */
void *app_key; /* Application's "key" (user data) */
void *ret_obj; /* Object to return */
} H5I_search_ud_t;
/*-------------------- Locally scoped variables -----------------------------*/
@ -127,6 +132,7 @@ H5FL_DEFINE_STATIC(H5I_id_info_t);
/*--------------------- Local function prototypes ---------------------------*/
static H5I_id_info_t *H5I_find_id(hid_t id);
static int H5I_search_cb(void *obj, hid_t id, void *udata);
#ifdef H5I_DEBUG_OUTPUT
static herr_t H5I_debug(H5I_type_t type);
#endif /* H5I_DEBUG_OUTPUT */
@ -1903,6 +1909,40 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Iis_valid() */
/*-------------------------------------------------------------------------
* Function: H5I_search_cb
*
* Purpose: Callback routine for H5Isearch, when it calls H5I_iterate.
* Calls "user" callback search function, and then sets return
* value, based on the result of that callback.
*
* Return: Success: The first object in the type for which FUNC
* returns non-zero. NULL if FUNC returned zero
* for every object in the type.
* Failure: NULL
*
* Programmer: Quincey Koziol
* Friday, March 30, 2012
*
*-------------------------------------------------------------------------
*/
static int
H5I_search_cb(void *obj, hid_t id, void *_udata)
{
H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */
int ret_value; /* Callback return value */
FUNC_ENTER_NOAPI_NOINIT
ret_value = (*udata->app_cb)(obj, id, udata->app_key);
if(ret_value > 0)
udata->ret_obj = obj;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_search_cb() */
/*-------------------------------------------------------------------------
* Function: H5Isearch
@ -1931,14 +1971,27 @@ done:
void *
H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
{
void * ret_value; /* Return value */
H5I_search_ud_t udata; /* Context for iteration */
void *ret_value; /* Return value */
FUNC_ENTER_API(NULL)
/* Check arguments */
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
ret_value = H5I_search(type, func, key, TRUE);
/* Set up udata struct */
udata.app_cb = func;
udata.app_key = key;
udata.ret_obj = NULL;
/* Note that H5I_iterate returns an error code. We ignore it
* here, as we can't do anything with it without revising the API.
*/
H5I_iterate(type, H5I_search_cb, &udata, TRUE);
/* Set return value */
ret_value = udata.ret_obj;
done:
FUNC_LEAVE_API(ret_value)
@ -1946,62 +1999,71 @@ done:
/*-------------------------------------------------------------------------
* Function: H5I_search
* Function: H5I_iterate
*
* Purpose: Apply function FUNC to each member of type TYPE and return a
* pointer to the first object for which FUNC returns non-zero.
* The FUNC should take a pointer to the object and the KEY as
* arguments and return non-zero to terminate the search (zero
* to continue).
* Purpose: Apply function FUNC to each member of type TYPE (with
* non-zero application reference count if app_ref is TRUE).
* Stop if FUNC returns a non zero value (i.e. anything
* other than H5_ITER_CONT).
*
* Limitation: Currently there is no way to start searching from where a
* previous search left off.
* If FUNC returns a positive value (i.e. H5_ITER_STOP),
* return SUCCEED.
*
* Return: Success: The first object in the type for which FUNC
* returns non-zero. NULL if FUNC returned zero
* for every object in the type.
* Failure: NULL
* If FUNC returns a negative value (i.e. H5_ITER_ERROR),
* return FAIL.
*
* The FUNC should take a pointer to the object and the
* udata as arguments and return non-zero to terminate
* siteration, and zero to continue.
*
* Programmer: Robb Matzke
* Friday, February 19, 1999
* Limitation: Currently there is no way to start the iteration from
* where a previous iteration left off.
*
* Modifications: Neil Fortner
* Wednesday, October 1, 2008
* Added app_ref parameter. When set to TRUE, the function will only
* operate on ids that have a nonzero application reference count.
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* Monday, December 6, 2011
*
*-------------------------------------------------------------------------
*/
void *
H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
herr_t
H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref)
{
H5I_id_type_t *type_ptr; /*ptr to the type */
void *ret_value = NULL; /*return value */
H5I_id_type_t *type_ptr; /*ptr to the type */
herr_t ret_value = SUCCEED; /*return value */
FUNC_ENTER_NOAPI(NULL)
FUNC_ENTER_NOAPI(FAIL)
/* Check arguments */
if(type <= H5I_BADID || type >= H5I_next_type)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
if(type_ptr == NULL || type_ptr->count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
/* Only iterate through hash table if there are IDs in group */
if(type_ptr->ids > 0) {
H5I_id_info_t *id_ptr; /*ptr to the new ID */
H5I_id_info_t *next_id; /*ptr to the next ID */
unsigned i; /*counter */
/* Only iterate through hash table if it is initialized and there are IDs in group */
if(type_ptr && type_ptr->count > 0 && type_ptr->ids > 0) {
unsigned u; /* Counter */
/* Start at the beginning of the array */
for(i = 0; i < type_ptr->hash_size; i++) {
id_ptr = type_ptr->id_list[i];
for(u = 0; u < type_ptr->hash_size; u++) {
H5I_id_info_t *id_ptr; /* Ptr to the new ID */
id_ptr = type_ptr->id_list[u];
while(id_ptr) {
next_id = id_ptr->next; /* Protect against ID being deleted in callback */
/* (Casting away const OK -QAK) */
if((!app_ref || id_ptr->app_count) && (*func)((void *)id_ptr->obj_ptr, id_ptr->id, key))
/* (Casting away const OK -QAK) */
HGOTO_DONE((void *)id_ptr->obj_ptr); /*found the item*/
H5I_id_info_t *next_id; /* Ptr to the next ID */
/* Protect against ID being deleted in callback */
next_id = id_ptr->next;
if((!app_ref) || (id_ptr->app_count > 0)) {
herr_t cb_ret_val; /* Callback return value */
/* (Casting away const OK) */
cb_ret_val = (*func)((void *)id_ptr->obj_ptr, id_ptr->id, udata);
if(cb_ret_val > 0)
HGOTO_DONE(SUCCEED) /* terminate iteration early */
else if(cb_ret_val < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "func failed")
} /* end if */
id_ptr = next_id;
} /* end while */
} /* end for */
@ -2009,7 +2071,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_search() */
} /* end H5I_iterate() */
/*-------------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref);
H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref);
H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_dec_ref(hid_t id);

View File

@ -703,18 +703,23 @@ H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_t
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
/* Count all opened attributes */
num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE);
if(H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE, &num_open_attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't count opened attributes")
/* Find out whether the attribute has been opened */
if(num_open_attr) {
size_t check_num_attr; /* Number of open attribute IDs */
size_t u; /* Local index variable */
/* Allocate space for the attribute ID list */
if(NULL == (attr_id_list = (hid_t *)H5MM_malloc(num_open_attr * sizeof(hid_t))))
HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "unable to allocate memory for attribute ID list")
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "unable to allocate memory for attribute ID list")
/* Retrieve the IDs of all opened attributes */
H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE);
if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE, &check_num_attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get IDs of opened attributes")
if(check_num_attr != num_open_attr)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "open attribute count mismatch")
/* Iterate over the attributes */
for(u = 0; u < num_open_attr; u++) {

View File

@ -40,6 +40,7 @@
#include "H5Fprivate.h" /* Files */
#include "H5FDprivate.h" /* File drivers */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory Management */
#include "H5Ppkg.h" /* Property lists */
/* Includes needed to set as default file driver */
@ -122,6 +123,12 @@
/* Definition for external file cache size */
#define H5F_ACS_EFC_SIZE_SIZE sizeof(unsigned)
#define H5F_ACS_EFC_SIZE_DEF 0
/* Definition of pointer to initial file image info */
#define H5F_ACS_FILE_IMAGE_INFO_SIZE sizeof(H5FD_file_image_info_t)
#define H5F_ACS_FILE_IMAGE_INFO_DEF H5FD_DEFAULT_FILE_IMAGE_INFO
#define H5F_ACS_FILE_IMAGE_INFO_DEL H5P_file_image_info_del
#define H5F_ACS_FILE_IMAGE_INFO_COPY H5P_file_image_info_copy
#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P_file_image_info_close
/******************/
@ -149,6 +156,10 @@ static herr_t H5P_facc_reg_prop(H5P_genclass_t *pclass);
static herr_t H5P_facc_create(hid_t fapl_id, void *copy_data);
static herr_t H5P_facc_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data);
/* File image info property callbacks */
static herr_t H5P_file_image_info_del(hid_t prop_id, const char *name, size_t size, void *value);
static herr_t H5P_file_image_info_copy(const char *name, size_t size, void *value);
static herr_t H5P_file_image_info_close(const char *name, size_t size, void *value);
/*********************/
/* Package Variables */
@ -215,6 +226,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
hbool_t latest_format = H5F_ACS_LATEST_FORMAT_DEF; /* Default setting for "use the latest version of the format" flag */
hbool_t want_posix_fd = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */
unsigned efc_size = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */
H5FD_file_image_info_t file_image_info = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@ -300,6 +312,10 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
if(H5P_register_real(pclass, H5F_ACS_EFC_SIZE_NAME, H5F_ACS_EFC_SIZE_SIZE, &efc_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
/* Register the initial file image info */
if(H5P_register_real(pclass, H5F_ACS_FILE_IMAGE_INFO_NAME, H5F_ACS_FILE_IMAGE_INFO_SIZE, &file_image_info, NULL, NULL, NULL, H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, NULL, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_facc_reg_prop() */
@ -2101,3 +2117,484 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_elink_file_cache_size() */
/*-------------------------------------------------------------------------
* Function: H5Pset_file_image
*
* Purpose: Sets the initial file image. Some file drivers can initialize
* the starting data in a file from a buffer.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len)
{
H5P_genplist_t *fapl; /* Property list pointer */
H5FD_file_image_info_t image_info; /* File image info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*xz", fapl_id, buf_ptr, buf_len);
/* validate parameters */
if(!(((buf_ptr == NULL) && (buf_len == 0)) || ((buf_ptr != NULL) && (buf_len > 0))))
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "inconsistant buf_ptr and buf_len");
/* Get the plist structure */
if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get old image info */
if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image pointer")
/* Release previous buffer, if it exists */
if(image_info.buffer != NULL) {
if(image_info.callbacks.image_free) {
if(SUCCEED != image_info.callbacks.image_free(image_info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
} /* end if */
else
H5MM_xfree(image_info.buffer);
} /* end if */
/* Update struct */
if(buf_ptr) {
/* Allocate memory */
if(image_info.callbacks.image_malloc) {
if(NULL == (image_info.buffer = image_info.callbacks.image_malloc(buf_len,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
} /* end if */
else
if(NULL == (image_info.buffer = H5MM_malloc(buf_len)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
/* Copy data */
if(image_info.callbacks.image_memcpy) {
if(image_info.buffer != image_info.callbacks.image_memcpy(image_info.buffer,
buf_ptr, buf_len, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET,
image_info.callbacks.udata))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
HDmemcpy(image_info.buffer, buf_ptr, buf_len);
} /* end if */
else
image_info.buffer = NULL;
image_info.size = buf_len;
/* Set values */
if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_file_image() */
/*-------------------------------------------------------------------------
* Function: H5Pget_file_image
*
* Purpose: If the file image exists and buf_ptr_ptr is not NULL,
* allocate a buffer of the correct size, copy the image into
* the new buffer, and return the buffer to the caller in
* *buf_ptr_ptr. Do this using the file image callbacks
* if defined.
*
* NB: It is the responsibility of the caller to free the
* buffer whose address is returned in *buf_ptr_ptr. Do
* this using free if the file image callbacks are not
* defined, or with whatever method is appropriate if
* the callbacks are defined.
*
* If buf_ptr_ptr is not NULL, and no image exists, set
* *buf_ptr_ptr to NULL.
*
* If buf_len_ptr is not NULL, set *buf_len_ptr equal
* to the length of the file image if it exists, and
* to 0 if it does not.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr)
{
H5P_genplist_t *fapl; /* Property list pointer */
H5FD_file_image_info_t image_info; /* File image info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i**x*z", fapl_id, buf_ptr_ptr, buf_len_ptr);
/* Get the plist structure */
if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get values */
if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info")
/* verify file image field consistancy */
HDassert(((image_info.buffer != NULL) && (image_info.size > 0)) ||
((image_info.buffer == NULL) && (image_info.size == 0)));
/* Set output size */
if(buf_len_ptr != NULL)
*buf_len_ptr = image_info.size;
/* Duplicate the image if desired, using callbacks if available */
if(buf_ptr_ptr != NULL) {
void * copy_ptr = NULL; /* Copy of memory image */
if(image_info.buffer != NULL) {
/* Allocate memory */
if(image_info.callbacks.image_malloc) {
if(NULL == (copy_ptr = image_info.callbacks.image_malloc(image_info.size,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, image_info.callbacks.udata)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
} /* end if */
else
if(NULL == (copy_ptr = H5MM_malloc(image_info.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate copy")
/* Copy data */
if(image_info.callbacks.image_memcpy) {
if(copy_ptr != image_info.callbacks.image_memcpy(copy_ptr, image_info.buffer,
image_info.size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET,
image_info.callbacks.udata))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
HDmemcpy(copy_ptr, image_info.buffer, image_info.size);
} /* end if */
*buf_ptr_ptr = copy_ptr;
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_file_image */
/*-------------------------------------------------------------------------
* Function: H5Pset_file_image_callbacks
*
* Purpose: Sets the callbacks for file images. Some file drivers allow
* the use of user-defined callbacks for allocating, freeing and
* copying the drivers internal buffer, potentially allowing a
* clever user to do optimizations such as avoiding large mallocs
* and memcpys or to perform detailed logging.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr)
{
H5P_genplist_t *fapl; /* Property list pointer */
H5FD_file_image_info_t info; /* File image info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, callbacks_ptr);
/* Get the plist structure */
if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get old info */
if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image info")
/* verify file image field consistancy */
HDassert(((info.buffer != NULL) && (info.size > 0)) ||
((info.buffer == NULL) && (info.size == 0)));
/* Make sure a file image hasn't already been set */
if(info.buffer != NULL || info.size > 0)
HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "setting callbacks when an image is already set is forbidden. It could cause memory leaks.")
/* verify that callbacks_ptr is not NULL */
if(NULL == callbacks_ptr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr")
/* Make sure udata callbacks are going to be set if udata is going to be set */
if(callbacks_ptr->udata)
if(callbacks_ptr->udata_copy == NULL || callbacks_ptr->udata_free == NULL)
HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "udata callbacks must be set if udata is set")
/* Release old udata if it exists */
if(info.callbacks.udata != NULL) {
HDassert(info.callbacks.udata_free);
if(info.callbacks.udata_free(info.callbacks.udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
} /* end if */
/* Update struct */
info.callbacks = *callbacks_ptr;
if(callbacks_ptr->udata) {
HDassert(callbacks_ptr->udata_copy);
HDassert(callbacks_ptr->udata_free);
if((info.callbacks.udata = callbacks_ptr->udata_copy(callbacks_ptr->udata)) == NULL)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the suppplied udata")
} /* end if */
/* Set values */
if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pset_file_image_callbacks() */
/*-------------------------------------------------------------------------
* Function: H5Pget_file_image_callbacks
*
* Purpose: Sets the callbacks for file images. Some file drivers allow
* the use of user-defined callbacks for allocating, freeing and
* copying the drivers internal buffer, potentially allowing a
* clever user to do optimizations such as avoiding large mallocs
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5Pget_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr)
{
H5P_genplist_t *fapl; /* Property list pointer */
H5FD_file_image_info_t info; /* File image info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, callbacks_ptr);
/* Get the plist structure */
if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get old info */
if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info")
/* verify file image field consistancy */
HDassert(((info.buffer != NULL) && (info.size > 0)) ||
((info.buffer == NULL) && (info.size == 0)));
/* verify that callbacks_ptr is not NULL */
if(NULL == callbacks_ptr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr")
/* Transfer values to parameters */
*callbacks_ptr = info.callbacks;
/* Copy udata if it exists */
if(info.callbacks.udata != NULL) {
HDassert(info.callbacks.udata_copy);
if((callbacks_ptr->udata = info.callbacks.udata_copy(info.callbacks.udata)) == 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy udata")
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_file_image_callbacks() */
/*-------------------------------------------------------------------------
* Function: H5P_file_image_info_del
*
* Purpose: Delete callback for the file image info property, called
* when the property is deleted from the plist. The buffer
* and udata may need to be freed, possibly using their
* respective callbacks so the default free won't work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5P_file_image_info_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value)
{
H5FD_file_image_info_t info; /* Image info struct */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
if(value) {
info = *(H5FD_file_image_info_t *)value;
/* verify file image field consistancy */
HDassert(((info.buffer != NULL) && (info.size > 0)) ||
((info.buffer == NULL) && (info.size == 0)));
if(info.buffer && info.size > 0) {
/* Free buffer */
if(info.callbacks.image_free) {
if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, info.callbacks.udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
} /* end if */
else
free(info.buffer);
} /* end if */
/* Free udata if it exists */
if(info.callbacks.udata) {
if(NULL == info.callbacks.udata_free)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined")
if(info.callbacks.udata_free(info.callbacks.udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
} /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_file_image_info_del() */
/*-------------------------------------------------------------------------
* Function: H5P_file_image_info_copy
*
* Purpose: Copy callback for the file image info property. The buffer
* and udata may need to be copied, possibly using their
* respective callbacks so the default copy won't work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *value)
{
H5FD_file_image_info_t *info; /* Image info struct */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
if(value) {
info = (H5FD_file_image_info_t *)value;
/* verify file image field consistancy */
HDassert(((info->buffer != NULL) && (info->size > 0)) ||
((info->buffer == NULL) && (info->size == 0)));
if(info->buffer && info->size > 0) {
void *old_buffer; /* Pointer to old image buffer */
/* Store the old buffer */
old_buffer = info->buffer;
/* Allocate new buffer */
if(info->callbacks.image_malloc) {
if(NULL == (info->buffer = info->callbacks.image_malloc(info->size,
H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, info->callbacks.udata)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed")
} /* end if */
else {
if(NULL == (info->buffer = H5MM_malloc(info->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
} /* end else */
/* Copy data to new buffer */
if(info->callbacks.image_memcpy) {
if(info->buffer != info->callbacks.image_memcpy(info->buffer, old_buffer,
info->size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY,
info->callbacks.udata))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed")
} /* end if */
else
HDmemcpy(info->buffer, old_buffer, info->size);
} /* end if */
} /* end if */
/* Copy udata if it exists */
if(info->callbacks.udata) {
void *old_udata = info->callbacks.udata;
if(NULL == info->callbacks.udata_copy)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined")
info->callbacks.udata = info->callbacks.udata_copy(old_udata);
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_file_image_info_copy() */
/*-------------------------------------------------------------------------
* Function: H5P_file_image_info_close
*
* Purpose: Close callback for the file image info property. The buffer
* and udata may need to be freed, possibly using their
* respective callbacks so the standard free won't work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jacob Gruber
* Thurday, August 11, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5P_file_image_info_close(const char UNUSED *name, size_t UNUSED size, void *value)
{
H5FD_file_image_info_t info; /* Image info struct */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
if(value) {
info = *(H5FD_file_image_info_t *)value;
if(info.buffer != NULL && info.size > 0) {
/* Free buffer */
if(info.callbacks.image_free) {
if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE,
info.callbacks.udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed")
} /* end if */
else
H5MM_xfree(info.buffer);
} /* end if */
} /* end if */
/* Free udata if it exists */
if(info.callbacks.udata) {
if(NULL == info.callbacks.udata_free)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined")
if(info.callbacks.udata_free(info.callbacks.udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed")
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_file_image_info_close() */

View File

@ -51,6 +51,7 @@
typedef struct {
const H5P_genclass_t *parent; /* Pointer to parent class */
const char *name; /* Pointer to name to check */
H5P_genclass_t *new_class; /* Pointer to class during path traversal */
} H5P_check_class_t;
@ -1358,11 +1359,11 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
/*--------------------------------------------------------------------------
NAME
H5P_check_class
H5P_open_class_path_cb
PURPOSE
Internal callback routine to check for duplicated names in parent class.
USAGE
int H5P_check_class(obj, id, key)
int H5P_open_class_path_cb(obj, id, key)
H5P_genclass_t *obj; IN: Pointer to class
hid_t id; IN: ID of object being looked at
const void *key; IN: Pointer to information used to compare
@ -1378,27 +1379,29 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
REVISION LOG
--------------------------------------------------------------------------*/
static int
H5P_check_class(void *_obj, hid_t UNUSED id, void *_key)
H5P_open_class_path_cb(void *_obj, hid_t UNUSED id, void *_key)
{
H5P_genclass_t *obj=(H5P_genclass_t *)_obj; /* Pointer to the class for this ID */
const H5P_check_class_t *key=(const H5P_check_class_t *)_key; /* Pointer to key information for comparison */
int ret_value=0; /* Return value */
H5P_genclass_t *obj = (H5P_genclass_t *)_obj; /* Pointer to the class for this ID */
H5P_check_class_t *key = (H5P_check_class_t *)_key; /* Pointer to key information for comparison */
int ret_value = 0; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(obj);
HDassert(H5I_GENPROP_CLS==H5I_get_type(id));
HDassert(H5I_GENPROP_CLS == H5I_get_type(id));
HDassert(key);
/* Check if the class object has the same parent as the new class */
if(obj->parent==key->parent) {
if(obj->parent == key->parent) {
/* Check if they have the same name */
if(HDstrcmp(obj->name,key->name)==0)
ret_value=1; /* Indicate a match */
if(HDstrcmp(obj->name, key->name) == 0) {
key->new_class = obj;
ret_value = 1; /* Indicate a match */
} /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_check_class() */
} /* end H5P_open_class_path_cb() */
/*--------------------------------------------------------------------------
@ -4555,8 +4558,8 @@ H5P_open_class_path(const char *path)
char *curr_name; /* Pointer to current component of path name */
char *delimit; /* Pointer to path delimiter during traversal */
H5P_genclass_t *curr_class; /* Pointer to class during path traversal */
H5P_genclass_t *ret_value; /* Return value */
H5P_check_class_t check_info; /* Structure to hold the information for checking duplicate names */
H5P_genclass_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@ -4569,20 +4572,24 @@ H5P_open_class_path(const char *path)
/* Find the generic property class with this full path */
curr_name = tmp_path;
curr_class = NULL;
while((delimit=HDstrchr(curr_name,'/'))!=NULL) {
while(NULL != (delimit = HDstrchr(curr_name, '/'))) {
/* Change the delimiter to terminate the string */
*delimit='\0';
*delimit = '\0';
/* Set up the search structure */
check_info.parent=curr_class;
check_info.name=curr_name;
check_info.parent = curr_class;
check_info.name = curr_name;
check_info.new_class = NULL;
/* Find the class with this name & parent by iterating over the open classes */
if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes")
else if(NULL == check_info.new_class)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Advance the pointer in the path to the start of the next component */
curr_name=delimit+1;
curr_class = check_info.new_class;
curr_name = delimit + 1;
} /* end while */
/* Should be pointing to the last component in the path name now... */
@ -4590,13 +4597,16 @@ H5P_open_class_path(const char *path)
/* Set up the search structure */
check_info.parent = curr_class;
check_info.name = curr_name;
check_info.new_class = NULL;
/* Find the class with this name & parent by iterating over the open classes */
if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes")
else if(NULL == check_info.new_class)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Copy it */
if(NULL == (ret_value = H5P_copy_pclass(curr_class)))
if(NULL == (ret_value = H5P_copy_pclass(check_info.new_class)))
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class")
done:
@ -4604,7 +4614,7 @@ done:
H5MM_xfree(tmp_path);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_open_class_path() */
} /* H5P_open_class_path() */
/*--------------------------------------------------------------------------

View File

@ -322,6 +322,12 @@ H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low,
H5F_libver_t *high);
H5_DLL herr_t H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size);
H5_DLL herr_t H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size);
H5_DLL herr_t H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len);
H5_DLL herr_t H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr);
H5_DLL herr_t H5Pset_file_image_callbacks(hid_t fapl_id,
H5FD_file_image_callbacks_t *callbacks_ptr);
H5_DLL herr_t H5Pget_file_image_callbacks(hid_t fapl_id,
H5FD_file_image_callbacks_t *callbacks_ptr);
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);

View File

@ -1449,7 +1449,8 @@ H5T_term_interface(void)
H5T_g.asoft = 0;
/* Unlock all datatypes, then free them */
H5I_search(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
/* note that we are ignoring the return value from H5I_iterate() */
H5I_iterate(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
H5I_dec_type_ref(H5I_DATATYPE);
/* Reset all the datatype IDs */

View File

@ -220,6 +220,7 @@ MINOR, DSPACE, H5E_CANTCOMPARE, Can't compare objects
MINOR, PLIST, H5E_CANTGET, Can't get value
MINOR, PLIST, H5E_CANTSET, Can't set value
MINOR, PLIST, H5E_DUPCLASS, Duplicate class name in parent class
MINOR, PLIST, H5E_SETDISALLOWED, Disallowed operation
# Link errors
MINOR, LINK, H5E_TRAVERSE, Link traversal failure

View File

@ -42,7 +42,7 @@ TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
getname vfd ntypes dangle dtransform reserved cross_read \
freespace mf farray earray btree2 fheap
freespace mf farray earray btree2 fheap file_image
# List programs to be built when testing here. error_test and err_compat are
# built at the same time as the other tests, but executed by testerror.sh.
@ -63,7 +63,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version testmeta links_
BUILD_ALL_PROGS=gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_new_array \
gen_new_fill gen_new_group gen_new_mtime gen_new_super gen_noencoder \
gen_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \
gen_sizes_lheap
gen_sizes_lheap gen_file_image
if BUILD_ALL_CONDITIONAL
noinst_PROGRAMS=$(BUILD_ALL_PROGS)

View File

@ -92,7 +92,8 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
ttsafe$(EXEEXT) getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) \
dangle$(EXEEXT) dtransform$(EXEEXT) reserved$(EXEEXT) \
cross_read$(EXEEXT) freespace$(EXEEXT) mf$(EXEEXT) \
farray$(EXEEXT) earray$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT)
farray$(EXEEXT) earray$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT) \
file_image$(EXEEXT)
am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \
gen_new_array$(EXEEXT) gen_new_fill$(EXEEXT) \
@ -100,7 +101,7 @@ am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \
gen_new_super$(EXEEXT) gen_noencoder$(EXEEXT) \
gen_nullspace$(EXEEXT) gen_udlinks$(EXEEXT) \
space_overflow$(EXEEXT) gen_filespace$(EXEEXT) \
gen_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT)
gen_specmetaread$(EXEEXT) gen_sizes_lheap$(EXEEXT) gen_file_image$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
accum_SOURCES = accum.c
accum_OBJECTS = accum.$(OBJEXT)
@ -198,6 +199,10 @@ fheap_SOURCES = fheap.c
fheap_OBJECTS = fheap.$(OBJEXT)
fheap_LDADD = $(LDADD)
fheap_DEPENDENCIES = libh5test.la $(LIBHDF5)
file_image_SOURCES = file_image.c
file_image_OBJECTS = file_image.$(OBJEXT)
file_image_LDADD = $(LDADD)
file_image_DEPENDENCIES = libh5test.la $(LIBHDF5)
fillval_SOURCES = fillval.c
fillval_OBJECTS = fillval.$(OBJEXT)
fillval_LDADD = $(LDADD)
@ -282,6 +287,10 @@ gen_udlinks_SOURCES = gen_udlinks.c
gen_udlinks_OBJECTS = gen_udlinks.$(OBJEXT)
gen_udlinks_LDADD = $(LDADD)
gen_udlinks_DEPENDENCIES = libh5test.la $(LIBHDF5)
gen_file_image_SOURCES = gen_file_image.c
gen_file_image_OBJECTS = gen_file_image.$(OBJEXT)
gen_file_image_LDADD = $(LDADD)
gen_file_image_DEPENDENCIES = libh5test.la $(LIBHDF5)
getname_SOURCES = getname.c
getname_OBJECTS = getname.$(OBJEXT)
getname_LDADD = $(LDADD)
@ -418,31 +427,32 @@ SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \
btree2.c cache.c cache_api.c cache_tagging.c cmpd_dset.c \
cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c \
earray.c efc.c enum.c err_compat.c error_test.c extend.c \
external.c farray.c fheap.c fillval.c filter_fail.c flush1.c \
flush2.c freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \
gen_deflate.c gen_filespace.c gen_filters.c gen_new_array.c \
gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c \
gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \
gen_specmetaread.c gen_udlinks.c getname.c gheap.c hyperslab.c \
istore.c lheap.c links.c links_env.c mf.c mount.c mtime.c \
ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c \
space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \
testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \
bittests.c btree2.c cache.c cache_api.c cache_tagging.c \
cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \
dtransform.c dtypes.c earray.c efc.c enum.c err_compat.c \
error_test.c extend.c external.c farray.c fheap.c fillval.c \
external.c farray.c fheap.c file_image.c fillval.c \
filter_fail.c flush1.c flush2.c freespace.c gen_bad_ohdr.c \
gen_bogus.c gen_cross.c gen_deflate.c gen_filespace.c \
gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c \
gen_new_mtime.c gen_new_super.c gen_noencoder.c \
gen_nullspace.c gen_sizes_lheap.c gen_specmetaread.c \
gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c \
gen_udlinks.c gen_file_image.c getname.c gheap.c hyperslab.c istore.c lheap.c \
links.c links_env.c mf.c mount.c mtime.c ntypes.c objcopy.c \
ohdr.c pool.c reserved.c set_extent.c space_overflow.c stab.c \
tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
$(ttsafe_SOURCES) unlink.c vfd.c
DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \
bittests.c btree2.c cache.c cache_api.c cache_tagging.c \
cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \
dtransform.c dtypes.c earray.c efc.c enum.c err_compat.c \
error_test.c extend.c external.c farray.c fheap.c file_image.c \
fillval.c filter_fail.c flush1.c flush2.c freespace.c \
gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \
gen_filespace.c gen_filters.c gen_new_array.c gen_new_fill.c \
gen_new_group.c gen_new_mtime.c gen_new_super.c \
gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \
gen_specmetaread.c gen_udlinks.c gen_file_image.c getname.c gheap.c hyperslab.c \
istore.c lheap.c links.c links_env.c mf.c mount.c mtime.c \
ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c \
space_overflow.c stab.c tcheck_version.c $(testhdf5_SOURCES) \
testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
@ -778,7 +788,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
getname vfd ntypes dangle dtransform reserved cross_read \
freespace mf farray earray btree2 fheap
freespace mf farray earray btree2 fheap file_image
# These programs generate test files for the tests. They don't need to be
@ -791,7 +801,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
BUILD_ALL_PROGS = gen_bad_ohdr gen_bogus gen_cross gen_deflate gen_filters gen_new_array \
gen_new_fill gen_new_group gen_new_mtime gen_new_super gen_noencoder \
gen_nullspace gen_udlinks space_overflow gen_filespace gen_specmetaread \
gen_sizes_lheap
gen_sizes_lheap gen_file_image
# The libh5test library provides common support code for the tests.
@ -978,6 +988,9 @@ farray$(EXEEXT): $(farray_OBJECTS) $(farray_DEPENDENCIES)
fheap$(EXEEXT): $(fheap_OBJECTS) $(fheap_DEPENDENCIES)
@rm -f fheap$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(fheap_OBJECTS) $(fheap_LDADD) $(LIBS)
file_image$(EXEEXT): $(file_image_OBJECTS) $(file_image_DEPENDENCIES)
@rm -f file_image$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(file_image_OBJECTS) $(file_image_LDADD) $(LIBS)
fillval$(EXEEXT): $(fillval_OBJECTS) $(fillval_DEPENDENCIES)
@rm -f fillval$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(fillval_OBJECTS) $(fillval_LDADD) $(LIBS)
@ -1041,6 +1054,9 @@ gen_specmetaread$(EXEEXT): $(gen_specmetaread_OBJECTS) $(gen_specmetaread_DEPEND
gen_udlinks$(EXEEXT): $(gen_udlinks_OBJECTS) $(gen_udlinks_DEPENDENCIES)
@rm -f gen_udlinks$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(gen_udlinks_OBJECTS) $(gen_udlinks_LDADD) $(LIBS)
gen_file_image$(EXEEXT): $(gen_file_image_OBJECTS) $(gen_file_image_DEPENDENCIES)
@rm -f gen_file_image$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(gen_file_image_OBJECTS) $(gen_file_image_LDADD) $(LIBS)
getname$(EXEEXT): $(getname_OBJECTS) $(getname_DEPENDENCIES)
@rm -f getname$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(getname_OBJECTS) $(getname_LDADD) $(LIBS)
@ -1145,6 +1161,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/external.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/farray.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fheap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillval.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter_fail.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush1.Po@am__quote@
@ -1166,6 +1183,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_sizes_lheap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_specmetaread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_udlinks.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_file_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getname.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gheap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5test.Plo@am__quote@

1335
test/file_image.c Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

91
test/gen_file_image.c Normal file
View File

@ -0,0 +1,91 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* Friday, March 30, 2012
*
* Purpose: Create a simple file for use with the file image tests.
*
*/
#include "hdf5.h"
#define TESTFILE "file_image_core_test.h5"
/* 2-D dataset with fixed dimensions */
#define SPACE_RANK 2
#define SPACE_DIM1 128
#define SPACE_DIM2 32
/* Dataset data */
int data[SPACE_DIM1][SPACE_DIM2];
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose:
*
* Return: Success:
*
* Failure:
*
* Programmer: Quincey Koziol
* Friday, March 30, 2012
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
hid_t file, space, dset;
hsize_t dims[SPACE_RANK] = {SPACE_DIM1, SPACE_DIM2};
size_t i, j; /* Local index variables */
/* Initialize the data */
for(i = 0; i < SPACE_DIM1; i++)
for(j = 0; j < SPACE_DIM2; j++)
data[i][j] = (int)(j % 5);
/* Create the file */
file = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
if(file < 0)
printf("file < 0!\n");
/* Create the dataspace */
space = H5Screate_simple(SPACE_RANK, dims, NULL);
if(space < 0)
printf("space < 0!\n");
/* Create the compressed dataset */
dset = H5Dcreate2(file, "Dataset1", H5T_NATIVE_INT, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if(dset < 0)
printf("dset < 0!\n");
/* Write the data to the dataset */
if(H5Dwrite(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
printf("H5Dwrite() failed!\n");
/* Close everything */
if(H5Dclose(dset) < 0)
printf("H5Dclose() failed!\n");
if(H5Sclose(space) < 0)
printf("H5Sclose() failed!\n");
if(H5Fclose(file) < 0)
printf("H5Fclose() failed!\n");
return 0;
}

View File

@ -31,8 +31,8 @@ TEST_SCRIPT_PARA=testph5.sh
check_PROGRAMS = $(TEST_PROG_PARA)
check_SCRIPTS= $(TEST_SCRIPT)
testphdf5_SOURCES=testphdf5.c t_dset.c t_file.c t_mdset.c t_ph5basic.c \
t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c
testphdf5_SOURCES=testphdf5.c t_dset.c t_file.c t_file_image.c t_mdset.c \
t_ph5basic.c t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c
# The tests all depend on the hdf5 library and the test library
LDADD = $(LIBH5TEST) $(LIBHDF5)

View File

@ -95,9 +95,10 @@ t_shapesame_OBJECTS = t_shapesame.$(OBJEXT)
t_shapesame_LDADD = $(LDADD)
t_shapesame_DEPENDENCIES = $(LIBH5TEST) $(LIBHDF5)
am_testphdf5_OBJECTS = testphdf5.$(OBJEXT) t_dset.$(OBJEXT) \
t_file.$(OBJEXT) t_mdset.$(OBJEXT) t_ph5basic.$(OBJEXT) \
t_coll_chunk.$(OBJEXT) t_span_tree.$(OBJEXT) \
t_chunk_alloc.$(OBJEXT) t_filter_read.$(OBJEXT)
t_file.$(OBJEXT) t_file_image.$(OBJEXT) t_mdset.$(OBJEXT) \
t_ph5basic.$(OBJEXT) t_coll_chunk.$(OBJEXT) \
t_span_tree.$(OBJEXT) t_chunk_alloc.$(OBJEXT) \
t_filter_read.$(OBJEXT)
testphdf5_OBJECTS = $(am_testphdf5_OBJECTS)
testphdf5_LDADD = $(LDADD)
testphdf5_DEPENDENCIES = $(LIBH5TEST) $(LIBHDF5)
@ -431,8 +432,8 @@ INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/test
TEST_PROG_PARA = t_mpi t_posix_compliant testphdf5 t_cache t_pflush1 t_pflush2 t_shapesame
TEST_SCRIPT_PARA = testph5.sh
check_SCRIPTS = $(TEST_SCRIPT)
testphdf5_SOURCES = testphdf5.c t_dset.c t_file.c t_mdset.c t_ph5basic.c \
t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c
testphdf5_SOURCES = testphdf5.c t_dset.c t_file.c t_file_image.c t_mdset.c \
t_ph5basic.c t_coll_chunk.c t_span_tree.c t_chunk_alloc.c t_filter_read.c
# The tests all depend on the hdf5 library and the test library
@ -532,6 +533,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_coll_chunk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_dset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_file_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_filter_read.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_mdset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_mpi.Po@am__quote@

395
testpar/t_file_image.c Normal file
View File

@ -0,0 +1,395 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Parallel tests for file image operations
*/
#include "testphdf5.h"
/* file_image_daisy_chain_test
*
* Process zero:
*
* 1) Creates a core file with an integer vector data set of
* length n (= mpi_size),
*
* 2) Initializes the vector to zero in * location 0, and to -1
* everywhere else.
*
* 3) Flushes the core file, and gets an image of it. Closes
* the core file.
*
* 4) Sends the image to process 1.
*
* 5) Awaits receipt on a file image from process n-1.
*
* 6) opens the image received from process n-1, verifies that
* it contains a vector of length equal to mpi_size, and
* that the vector contains (0, 1, 2, ... n-1)
*
* 7) closes the core file and exits.
*
* Process i (0 < i < n)
*
* 1) Await receipt of file image from process (i - 1).
*
* 2) Open the image with the core file driver, verify that i
* contains a vector v of length, and that v[j] = j for
* 0 <= j < i, and that v[j] == -1 for i <= j < n
*
* 3) Set v[i] = i in the core file.
*
* 4) Flush the core file and send it to process (i + 1) % n.
*
* 5) close the core file and exit.
*
* Test fails on a hang (if an image is not received), or on invalid data.
*
* JRM -- 11/28/11
*/
void
file_image_daisy_chain_test(void)
{
char file_name[1024] = "\0";
int mpi_size, mpi_rank;
int mpi_result;
int i;
int space_ndims;
MPI_Status rcvstat;
int * vector_ptr = NULL;
hid_t fapl_id = -1;
hid_t file_id; /* file IDs */
hid_t dset_id = -1;
hid_t dset_type_id = -1;
hid_t space_id = -1;
herr_t err;
hsize_t dims[1];
void * image_ptr = NULL;
ssize_t bytes_read;
ssize_t image_len;
hbool_t vector_ok = TRUE;
htri_t tri_result;
/* set up MPI parameters */
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
/* setup file name */
HDsnprintf(file_name, 1024, "file_image_daisy_chain_test_%05d.h5",
(int)mpi_rank);
if(mpi_rank == 0) {
/* 1) Creates a core file with an integer vector data set
* of length mpi_size,
*/
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
VRFY((fapl_id >= 0), "creating fapl");
err = H5Pset_fapl_core(fapl_id, (size_t)(64 *1024), FALSE);
VRFY((err >= 0), "setting core file driver in fapl.");
file_id = H5Fcreate(file_name, 0, H5P_DEFAULT, fapl_id);
VRFY((file_id >= 0), "created core file");
dims[0] = (hsize_t)mpi_size;
space_id = H5Screate_simple(1, dims, dims);
VRFY((space_id >= 0), "created data space");
dset_id = H5Dcreate2(file_id, "v", H5T_NATIVE_INT, space_id,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
VRFY((dset_id >= 0), "created data set");
/* 2) Initialize the vector to zero in location 0, and
* to -1 everywhere else.
*/
vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int));
VRFY((vector_ptr != NULL), "allocated in memory representation of vector");
vector_ptr[0] = 0;
for(i = 1; i < mpi_size; i++)
vector_ptr[i] = -1;
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, (void *)vector_ptr);
VRFY((err >= 0), "wrote initial data to vector.");
HDfree(vector_ptr);
vector_ptr = NULL;
/* 3) Flush the core file, and get an image of it. Close
* the core file.
*/
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
VRFY((err >= 0), "flushed core file.");
image_len = H5Fget_file_image(file_id, NULL, (size_t)0);
VRFY((image_len > 0), "got image file size");
image_ptr = (void *)HDmalloc((size_t)image_len);
VRFY(image_ptr != NULL, "allocated file image buffer.");
bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_len);
VRFY(bytes_read == image_len, "wrote file into image buffer");
err = H5Sclose(space_id);
VRFY((err >= 0), "closed data space.");
err = H5Dclose(dset_id);
VRFY((err >= 0), "closed data set.");
err = H5Fclose(file_id);
VRFY((err >= 0), "closed core file(1).");
err = H5Pclose(fapl_id);
VRFY((err >= 0), "closed fapl(1).");
/* 4) Send the image to process 1. */
mpi_result = MPI_Ssend((void *)(&image_len), (int)sizeof(ssize_t),
MPI_BYTE, 1, 0, MPI_COMM_WORLD);
VRFY((mpi_result == MPI_SUCCESS), "sent image size to process 1");
mpi_result = MPI_Ssend((void *)image_ptr, (int)image_len,
MPI_BYTE, 1, 0, MPI_COMM_WORLD);
VRFY((mpi_result == MPI_SUCCESS), "sent image to process 1");
HDfree(image_ptr);
image_ptr = NULL;
image_len = 0;
/* 5) Await receipt on a file image from process n-1. */
mpi_result = MPI_Recv((void *)(&image_len), (int)sizeof(ssize_t),
MPI_BYTE, mpi_size - 1, 0, MPI_COMM_WORLD,
&rcvstat);
VRFY((mpi_result == MPI_SUCCESS), "received image len from process n-1");
image_ptr = (void *)HDmalloc((size_t)image_len);
VRFY(image_ptr != NULL, "allocated file image receive buffer.");
mpi_result = MPI_Recv((void *)image_ptr, (int)image_len,
MPI_BYTE, mpi_size - 1, 0, MPI_COMM_WORLD,
&rcvstat);
VRFY((mpi_result == MPI_SUCCESS), \
"received file image from process n-1");
/* 6) open the image received from process n-1, verify that
* it contains a vector of length equal to mpi_size, and
* that the vector contains (0, 1, 2, ... n-1).
*/
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
VRFY((fapl_id >= 0), "creating fapl");
err = H5Pset_fapl_core(fapl_id, (size_t)(64 *1024), FALSE);
VRFY((err >= 0), "setting core file driver in fapl.");
err = H5Pset_file_image(fapl_id, image_ptr, (size_t)image_len);
VRFY((err >= 0), "set file image in fapl.");
file_id = H5Fopen(file_name, H5F_ACC_RDWR, fapl_id);
VRFY((file_id >= 0), "opened received file image file");
dset_id = H5Dopen1(file_id, "v");
VRFY((dset_id >= 0), "opened data set");
dset_type_id = H5Dget_type(dset_id);
VRFY((dset_type_id >= 0), "obtained data set type");
tri_result = H5Tequal(dset_type_id, H5T_NATIVE_INT);
VRFY((tri_result == TRUE), "verified data set type");
space_id = H5Dget_space(dset_id);
VRFY((space_id >= 0), "opened data space");
space_ndims = H5Sget_simple_extent_ndims(space_id);
VRFY((space_ndims == 1), "verified data space num dims(1)");
space_ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
VRFY((space_ndims == 1), "verified data space num dims(2)");
VRFY((dims[0] == (hsize_t)mpi_size), "verified data space dims");
vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int));
VRFY((vector_ptr != NULL), "allocated in memory rep of vector");
err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, (void *)vector_ptr);
VRFY((err >= 0), "read received vector.");
vector_ok = TRUE;
for(i = 0; i < mpi_size; i++)
if(vector_ptr[i] != i)
vector_ok = FALSE;
VRFY((vector_ok), "verified received vector.");
/* 7) closes the core file and exit. */
err = H5Sclose(space_id);
VRFY((err >= 0), "closed data space.");
err = H5Dclose(dset_id);
VRFY((err >= 0), "closed data set.");
err = H5Fclose(file_id);
VRFY((err >= 0), "closed core file(1).");
err = H5Pclose(fapl_id);
VRFY((err >= 0), "closed fapl(1).");
HDfree(image_ptr);
image_ptr = NULL;
image_len = 0;
} else {
/* 1) Await receipt of file image from process (i - 1). */
mpi_result = MPI_Recv((void *)(&image_len), (int)sizeof(ssize_t),
MPI_BYTE, mpi_rank - 1, 0, MPI_COMM_WORLD,
&rcvstat);
VRFY((mpi_result == MPI_SUCCESS), \
"received image size from process mpi_rank-1");
image_ptr = (void *)HDmalloc((size_t)image_len);
VRFY(image_ptr != NULL, "allocated file image receive buffer.");
mpi_result = MPI_Recv((void *)image_ptr, (int)image_len,
MPI_BYTE, mpi_rank - 1, 0, MPI_COMM_WORLD,
&rcvstat);
VRFY((mpi_result == MPI_SUCCESS), \
"received file image from process mpi_rank-1");
/* 2) Open the image with the core file driver, verify that it
* contains a vector v of length, and that v[j] = j for
* 0 <= j < i, and that v[j] == -1 for i <= j < n
*/
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
VRFY((fapl_id >= 0), "creating fapl");
err = H5Pset_fapl_core(fapl_id, (size_t)(64 * 1024), FALSE);
VRFY((err >= 0), "setting core file driver in fapl.");
err = H5Pset_file_image(fapl_id, image_ptr, (size_t)image_len);
VRFY((err >= 0), "set file image in fapl.");
file_id = H5Fopen(file_name, H5F_ACC_RDWR, fapl_id);
H5Eprint1(stderr);
VRFY((file_id >= 0), "opened received file image file");
dset_id = H5Dopen1(file_id, "v");
VRFY((dset_id >= 0), "opened data set");
dset_type_id = H5Dget_type(dset_id);
VRFY((dset_type_id >= 0), "obtained data set type");
tri_result = H5Tequal(dset_type_id, H5T_NATIVE_INT);
VRFY((tri_result == TRUE), "verified data set type");
space_id = H5Dget_space(dset_id);
VRFY((space_id >= 0), "opened data space");
space_ndims = H5Sget_simple_extent_ndims(space_id);
VRFY((space_ndims == 1), "verified data space num dims(1)");
space_ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
VRFY((space_ndims == 1), "verified data space num dims(2)");
VRFY((dims[0] == (hsize_t)mpi_size), "verified data space dims");
vector_ptr = (int *)HDmalloc((size_t)(mpi_size) * sizeof(int));
VRFY((vector_ptr != NULL), "allocated in memory rep of vector");
err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, (void *)vector_ptr);
VRFY((err >= 0), "read received vector.");
vector_ok = TRUE;
for(i = 0; i < mpi_size; i++){
if(i < mpi_rank) {
if(vector_ptr[i] != i)
vector_ok = FALSE;
} else {
if(vector_ptr[i] != -1)
vector_ok = FALSE;
}
}
VRFY((vector_ok), "verified received vector.");
/* 3) Set v[i] = i in the core file. */
vector_ptr[mpi_rank] = mpi_rank;
err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, (void *)vector_ptr);
VRFY((err >= 0), "wrote modified data to vector.");
HDfree(vector_ptr);
vector_ptr = NULL;
/* 4) Flush the core file and send it to process (mpi_rank + 1) % n. */
err = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
VRFY((err >= 0), "flushed core file.");
image_len = H5Fget_file_image(file_id, NULL, (size_t)0);
VRFY((image_len > 0), "got (possibly modified) image file len");
image_ptr = (void *)HDrealloc((void *)image_ptr, (size_t)image_len);
VRFY(image_ptr != NULL, "re-allocated file image buffer.");
bytes_read = H5Fget_file_image(file_id, image_ptr, (size_t)image_len);
VRFY(bytes_read == image_len, "wrote file into image buffer");
mpi_result = MPI_Ssend((void *)(&image_len), (int)sizeof(ssize_t),
MPI_BYTE, (mpi_rank + 1) % mpi_size, 0,
MPI_COMM_WORLD);
VRFY((mpi_result == MPI_SUCCESS), \
"sent image size to process (mpi_rank + 1) % mpi_size");
mpi_result = MPI_Ssend((void *)image_ptr, (int)image_len,
MPI_BYTE, (mpi_rank + 1) % mpi_size, 0,
MPI_COMM_WORLD);
VRFY((mpi_result == MPI_SUCCESS), \
"sent image to process (mpi_rank + 1) % mpi_size");
HDfree(image_ptr);
image_ptr = NULL;
image_len = 0;
/* 5) close the core file and exit. */
err = H5Sclose(space_id);
VRFY((err >= 0), "closed data space.");
err = H5Dclose(dset_id);
VRFY((err >= 0), "closed data set.");
err = H5Fclose(file_id);
VRFY((err >= 0), "closed core file(1).");
err = H5Pclose(fapl_id);
VRFY((err >= 0), "closed fapl(1).");
}
return;
} /* file_image_daisy_chain_test() */

View File

@ -502,6 +502,13 @@ int main(int argc, char **argv)
"test actual io mode proprerty",
PARATESTFILE);
if((mpi_size < 2) && MAINPROCESS) {
printf("File Image Ops daisy chain test needs at least 2 processes.\n");
printf("File Image Ops daisy chain test will be skipped \n");
}
AddTest((mpi_size < 2)? "-fiodc" : "fiodc", file_image_daisy_chain_test, NULL,
"file image ops daisy chain", NULL);
/* Display testing information */
TestInfo(argv[0]);

View File

@ -269,6 +269,7 @@ void lower_dim_size_comp_test(void);
void link_chunk_collective_io_test(void);
void contig_hyperslab_dr_pio_test(ShapeSameTestMethods sstest_type);
void checker_board_hyperslab_dr_pio_test(ShapeSameTestMethods sstest_type);
void file_image_daisy_chain_test(void);
#ifdef H5_HAVE_FILTER_DEFLATE
void compress_readAll(void);
#endif /* H5_HAVE_FILTER_DEFLATE */