diff options
-rw-r--r-- | java/src/hdf/hdf5lib/HDF5Constants.java | 6 | ||||
-rw-r--r-- | java/src/jni/h5Constants.c | 4 | ||||
-rw-r--r-- | release_docs/RELEASE.txt | 8 | ||||
-rw-r--r-- | src/H5Aint.c | 6 | ||||
-rw-r--r-- | src/H5Dchunk.c | 9 | ||||
-rw-r--r-- | src/H5Dcompact.c | 7 | ||||
-rw-r--r-- | src/H5Dvirtual.c | 7 | ||||
-rw-r--r-- | src/H5Pint.c | 105 | ||||
-rw-r--r-- | src/H5Pprivate.h | 1 | ||||
-rw-r--r-- | src/H5Ppublic.h | 4 | ||||
-rw-r--r-- | src/H5Shyper.c | 1053 | ||||
-rw-r--r-- | src/H5Sselect.c | 11 | ||||
-rw-r--r-- | src/H5VL.c | 22 | ||||
-rw-r--r-- | src/H5trace.c | 3 | ||||
-rw-r--r-- | test/vds.c | 720 | ||||
-rw-r--r-- | test/vol.c | 51 |
16 files changed, 1621 insertions, 396 deletions
diff --git a/java/src/hdf/hdf5lib/HDF5Constants.java b/java/src/hdf/hdf5lib/HDF5Constants.java index 9294bad..8054ee8 100644 --- a/java/src/hdf/hdf5lib/HDF5Constants.java +++ b/java/src/hdf/hdf5lib/HDF5Constants.java @@ -374,6 +374,7 @@ public class HDF5Constants { public static final long H5P_OBJECT_COPY = H5P_OBJECT_COPY(); public static final long H5P_LINK_CREATE = H5P_LINK_CREATE(); public static final long H5P_LINK_ACCESS = H5P_LINK_ACCESS(); + public static final long H5P_VOL_INITIALIZE = H5P_VOL_INITIALIZE(); public static final long H5P_FILE_CREATE_DEFAULT = H5P_FILE_CREATE_DEFAULT(); public static final long H5P_FILE_ACCESS_DEFAULT = H5P_FILE_ACCESS_DEFAULT(); public static final long H5P_DATASET_CREATE_DEFAULT = H5P_DATASET_CREATE_DEFAULT(); @@ -389,6 +390,7 @@ public class HDF5Constants { public static final long H5P_OBJECT_COPY_DEFAULT = H5P_OBJECT_COPY_DEFAULT(); public static final long H5P_LINK_CREATE_DEFAULT = H5P_LINK_CREATE_DEFAULT(); public static final long H5P_LINK_ACCESS_DEFAULT = H5P_LINK_ACCESS_DEFAULT(); + public static final long H5P_VOL_INITIALIZE_DEFAULT = H5P_VOL_INITIALIZE_DEFAULT(); public static final int H5P_CRT_ORDER_TRACKED = H5P_CRT_ORDER_TRACKED(); public static final int H5P_CRT_ORDER_INDEXED = H5P_CRT_ORDER_INDEXED(); public static final long H5P_DEFAULT = H5P_DEFAULT(); @@ -1352,6 +1354,8 @@ public class HDF5Constants { private static native final long H5P_LINK_ACCESS(); + private static native final long H5P_VOL_INITIALIZE(); + private static native final long H5P_FILE_CREATE_DEFAULT(); private static native final long H5P_FILE_ACCESS_DEFAULT(); @@ -1382,6 +1386,8 @@ public class HDF5Constants { private static native final long H5P_LINK_ACCESS_DEFAULT(); + private static native final long H5P_VOL_INITIALIZE_DEFAULT(); + private static native final int H5P_CRT_ORDER_TRACKED(); private static native final int H5P_CRT_ORDER_INDEXED(); diff --git a/java/src/jni/h5Constants.c b/java/src/jni/h5Constants.c index 74eb436..4b10479 100644 --- a/java/src/jni/h5Constants.c +++ b/java/src/jni/h5Constants.c @@ -731,6 +731,8 @@ Java_hdf_hdf5lib_HDF5Constants_H5P_1LINK_1CREATE(JNIEnv *env, jclass cls){return JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1LINK_1ACCESS(JNIEnv *env, jclass cls){return H5P_LINK_ACCESS;} JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5P_1VOL_1INITIALIZE(JNIEnv *env, jclass cls){return H5P_VOL_INITIALIZE;} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1FILE_1CREATE_1DEFAULT(JNIEnv *env, jclass cls){return H5P_FILE_CREATE_DEFAULT;} JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1FILE_1ACCESS_1DEFAULT(JNIEnv *env, jclass cls){return H5P_FILE_ACCESS_DEFAULT;} @@ -760,6 +762,8 @@ JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1LINK_1CREATE_1DEFAULT(JNIEnv *env, jclass cls){return H5P_LINK_CREATE_DEFAULT;} JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1LINK_1ACCESS_1DEFAULT(JNIEnv *env, jclass cls){return H5P_LINK_ACCESS_DEFAULT;} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5P_1VOL_1INITIALIZE_1DEFAULT(JNIEnv *env, jclass cls){return H5P_VOL_INITIALIZE_DEFAULT;} JNIEXPORT jint JNICALL Java_hdf_hdf5lib_HDF5Constants_H5P_1CRT_1ORDER_1TRACKED(JNIEnv *env, jclass cls){return H5P_CRT_ORDER_TRACKED;} JNIEXPORT jint JNICALL diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 6d1c8b2..649ae24 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -130,6 +130,14 @@ New Features Library: -------- + - Improved the performance of virtual dataset I/O + + Refactored the internal dataspace routines used by the virtual dataset + code to improve performance, especially when one of the selections + involved is very long and non-contiguous. + + (NAF - 2019/05/31, HDFFV-10693) + - Allow pre-generated H5Tinit.c and H5make_libsettings.c to be used. Rather than always running H5detect and generating H5Tinit.c and diff --git a/src/H5Aint.c b/src/H5Aint.c index d8ba92a..6162401 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -2396,9 +2396,13 @@ H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src, /* Check for expanding references */ if(cpy_info->expand_ref) { size_t ref_count; + size_t dst_dt_size; /* Destination datatype size */ + /* Determine size of the destination datatype */ + if(0 == (dst_dt_size = H5T_get_size(attr_dst->shared->dt))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size") /* Determine # of reference elements to copy */ - ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt); + ref_count = attr_dst->shared->data_size / dst_dt_size; /* Copy objects referenced in source buffer to destination file and set destination elements */ if(H5O_copy_expand_ref(file_src, attr_dst->shared->data, file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_dst->shared->dt), cpy_info) < 0) diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 60f2d8b..a8dc398 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -707,15 +707,18 @@ H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, /* Compute the # of chunks in dataset dimensions */ for(u = 0, layout->nchunks = 1, layout->max_nchunks = 1; u < ndims; u++) { - /* Sanity check */ - HDassert(layout->dim[u] > 0); - /* Round up to the next integer # of chunks, to accommodate partial chunks */ layout->chunks[u] = ((curr_dims[u] + layout->dim[u]) - 1) / layout->dim[u]; if(H5S_UNLIMITED == max_dims[u]) layout->max_chunks[u] = H5S_UNLIMITED; else + { + /* Sanity check */ + if(layout->dim[u] == 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimension size must be > 0, dim = %u ", u) + layout->max_chunks[u] = ((max_dims[u] + layout->dim[u]) - 1) / layout->dim[u]; + } /* Accumulate the # of chunks */ layout->nchunks *= layout->chunks[u]; diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index df61856..29401f8 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -559,9 +559,14 @@ H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_ds /* Check for expanding references */ if(cpy_info->expand_ref) { size_t ref_count; + size_t src_dt_size; /* Source datatype size */ + + /* Determine largest datatype size */ + if(0 == (src_dt_size = H5T_get_size(dt_src))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size") /* Determine # of reference elements to copy */ - ref_count = storage_src->size / H5T_get_size(dt_src); + ref_count = storage_src->size / src_dt_size; /* Copy objects referenced in source buffer to destination file and set destination elements */ if(H5O_copy_expand_ref(f_src, storage_src->buf, f_dst, diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index e3e0aa5..53640e7 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -35,6 +35,13 @@ * until the virtual dataset is closed. */ +/* + * Note: H5S_select_project_intersection has been updated to no longer require + * that the source and source intersect spaces have the same extent. This file + * should therefore be updated to remove code that ensures this condition, which + * should improve both maintainability and performance. + */ + /****************/ /* Module Setup */ /****************/ diff --git a/src/H5Pint.c b/src/H5Pint.c index b07f42d..04411a5 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -127,62 +127,65 @@ static herr_t H5P__free_del_name_cb(void *item, void H5_ATTR_UNUSED *key, void H * Predefined property list classes. These are initialized at runtime by * H5P__init_package() in this source file. */ -hid_t H5P_CLS_ROOT_ID_g = FAIL; +hid_t H5P_CLS_ROOT_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ROOT_g = NULL; -hid_t H5P_CLS_OBJECT_CREATE_ID_g = FAIL; +hid_t H5P_CLS_OBJECT_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_OBJECT_CREATE_g = NULL; -hid_t H5P_CLS_FILE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_FILE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_CREATE_g = NULL; -hid_t H5P_CLS_FILE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_FILE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_ACCESS_g = NULL; -hid_t H5P_CLS_DATASET_CREATE_ID_g = FAIL; +hid_t H5P_CLS_DATASET_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_CREATE_g = NULL; -hid_t H5P_CLS_DATASET_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_DATASET_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_ACCESS_g = NULL; -hid_t H5P_CLS_DATASET_XFER_ID_g = FAIL; +hid_t H5P_CLS_DATASET_XFER_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATASET_XFER_g = NULL; -hid_t H5P_CLS_FILE_MOUNT_ID_g = FAIL; +hid_t H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_FILE_MOUNT_g = NULL; -hid_t H5P_CLS_GROUP_CREATE_ID_g = FAIL; +hid_t H5P_CLS_GROUP_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_GROUP_CREATE_g = NULL; -hid_t H5P_CLS_GROUP_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_GROUP_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_GROUP_ACCESS_g = NULL; -hid_t H5P_CLS_DATATYPE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATATYPE_CREATE_g = NULL; -hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_DATATYPE_ACCESS_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = FAIL; +hid_t H5P_CLS_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ATTRIBUTE_CREATE_g = NULL; -hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_ATTRIBUTE_ACCESS_g = NULL; -hid_t H5P_CLS_OBJECT_COPY_ID_g = FAIL; +hid_t H5P_CLS_OBJECT_COPY_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_OBJECT_COPY_g = NULL; -hid_t H5P_CLS_LINK_CREATE_ID_g = FAIL; +hid_t H5P_CLS_LINK_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_LINK_CREATE_g = NULL; -hid_t H5P_CLS_LINK_ACCESS_ID_g = FAIL; +hid_t H5P_CLS_LINK_ACCESS_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_LINK_ACCESS_g = NULL; -hid_t H5P_CLS_STRING_CREATE_ID_g = FAIL; +hid_t H5P_CLS_STRING_CREATE_ID_g = H5I_INVALID_HID; H5P_genclass_t *H5P_CLS_STRING_CREATE_g = NULL; +hid_t H5P_CLS_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; +H5P_genclass_t *H5P_CLS_VOL_INITIALIZE_g = NULL; /* * Predefined property lists for each predefined class. These are initialized * at runtime by H5P__init_package() in this source file. */ -hid_t H5P_LST_FILE_CREATE_ID_g = FAIL; -hid_t H5P_LST_FILE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATASET_CREATE_ID_g = FAIL; -hid_t H5P_LST_DATASET_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATASET_XFER_ID_g = FAIL; -hid_t H5P_LST_FILE_MOUNT_ID_g = FAIL; -hid_t H5P_LST_GROUP_CREATE_ID_g = FAIL; -hid_t H5P_LST_GROUP_ACCESS_ID_g = FAIL; -hid_t H5P_LST_DATATYPE_CREATE_ID_g = FAIL; -hid_t H5P_LST_DATATYPE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = FAIL; -hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = FAIL; -hid_t H5P_LST_OBJECT_COPY_ID_g = FAIL; -hid_t H5P_LST_LINK_CREATE_ID_g = FAIL; -hid_t H5P_LST_LINK_ACCESS_ID_g = FAIL; +hid_t H5P_LST_FILE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATASET_XFER_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_GROUP_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_GROUP_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_DATATYPE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_OBJECT_COPY_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_CREATE_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_LINK_ACCESS_ID_g = H5I_INVALID_HID; +hid_t H5P_LST_VOL_INITIALIZE_ID_g = H5I_INVALID_HID; /* Root property list class library initialization object */ const H5P_libclass_t H5P_CLS_ROOT[1] = {{ @@ -283,6 +286,26 @@ const H5P_libclass_t H5P_CLS_TACC[1] = {{ NULL /* Class close callback info */ }}; +/* VOL initialization property list class library initialization object */ +/* (move to proper source code file when used for real) */ +const H5P_libclass_t H5P_CLS_VINI[1] = {{ + "VOL initialization", /* Class name for debugging */ + H5P_TYPE_VOL_INITIALIZE, /* Class type */ + + &H5P_CLS_ROOT_g, /* Parent class */ + &H5P_CLS_VOL_INITIALIZE_g, /* Pointer to class */ + &H5P_CLS_VOL_INITIALIZE_ID_g, /* Pointer to class ID */ + &H5P_LST_VOL_INITIALIZE_ID_g, /* Pointer to default property list ID */ + NULL, /* Default property registration routine */ + + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + /* Library property list classes defined in other code modules */ /* (And not present in src/H5Pprivate.h) */ @@ -331,7 +354,8 @@ static H5P_libclass_t const * const init_class[] = { H5P_CLS_TACC, /* Datatype access */ H5P_CLS_ACRT, /* Attribute creation */ H5P_CLS_AACC, /* Attribute access */ - H5P_CLS_LCRT /* Link creation */ + H5P_CLS_LCRT, /* Link creation */ + H5P_CLS_VINI /* VOL initialization */ }; /* Declare a free list to manage the H5P_genclass_t struct */ @@ -525,7 +549,8 @@ H5P_term_package(void) H5P_LST_OBJECT_COPY_ID_g = H5P_LST_LINK_CREATE_ID_g = H5P_LST_LINK_ACCESS_ID_g = - H5P_LST_FILE_MOUNT_ID_g = (-1); + H5P_LST_VOL_INITIALIZE_ID_g = + H5P_LST_FILE_MOUNT_ID_g = H5I_INVALID_HID; } /* end if */ } /* end if */ @@ -552,6 +577,7 @@ H5P_term_package(void) H5P_CLS_OBJECT_COPY_g = H5P_CLS_LINK_CREATE_g = H5P_CLS_LINK_ACCESS_g = + H5P_CLS_VOL_INITIALIZE_g = H5P_CLS_FILE_MOUNT_g = NULL; H5P_CLS_ROOT_ID_g = @@ -571,7 +597,8 @@ H5P_term_package(void) H5P_CLS_OBJECT_COPY_ID_g = H5P_CLS_LINK_CREATE_ID_g = H5P_CLS_LINK_ACCESS_ID_g = - H5P_CLS_FILE_MOUNT_ID_g = (-1); + H5P_CLS_VOL_INITIALIZE_ID_g = + H5P_CLS_FILE_MOUNT_ID_g = H5I_INVALID_HID; } /* end if */ } /* end if */ @@ -5408,7 +5435,7 @@ H5P__new_plist_of_type(H5P_plist_type_t type) FUNC_ENTER_PACKAGE /* Sanity checks */ - HDcompile_assert(H5P_TYPE_ATTRIBUTE_ACCESS == (H5P_TYPE_MAX_TYPE - 1)); + HDcompile_assert(H5P_TYPE_VOL_INITIALIZE == (H5P_TYPE_MAX_TYPE - 1)); HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_LINK_ACCESS); /* Check arguments */ @@ -5487,6 +5514,10 @@ H5P__new_plist_of_type(H5P_plist_type_t type) class_id = H5P_CLS_LINK_ACCESS_ID_g; break; + case H5P_TYPE_VOL_INITIALIZE: + class_id = H5P_CLS_VOL_INITIALIZE_ID_g; + break; + case H5P_TYPE_USER: /* shut compiler warnings up */ case H5P_TYPE_ROOT: case H5P_TYPE_MAX_TYPE: diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 49f7a12..07910c3 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -78,6 +78,7 @@ typedef enum H5P_plist_type_t { H5P_TYPE_LINK_CREATE = 16, H5P_TYPE_LINK_ACCESS = 17, H5P_TYPE_ATTRIBUTE_ACCESS = 18, + H5P_TYPE_VOL_INITIALIZE = 19, H5P_TYPE_MAX_TYPE } H5P_plist_type_t; diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 90e6618..cad2071 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -68,6 +68,7 @@ #define H5P_OBJECT_COPY (H5OPEN H5P_CLS_OBJECT_COPY_ID_g) #define H5P_LINK_CREATE (H5OPEN H5P_CLS_LINK_CREATE_ID_g) #define H5P_LINK_ACCESS (H5OPEN H5P_CLS_LINK_ACCESS_ID_g) +#define H5P_VOL_INITIALIZE (H5OPEN H5P_CLS_VOL_INITIALIZE_ID_g) /* * The library's default property lists @@ -87,6 +88,7 @@ #define H5P_OBJECT_COPY_DEFAULT (H5OPEN H5P_LST_OBJECT_COPY_ID_g) #define H5P_LINK_CREATE_DEFAULT (H5OPEN H5P_LST_LINK_CREATE_ID_g) #define H5P_LINK_ACCESS_DEFAULT (H5OPEN H5P_LST_LINK_ACCESS_ID_g) +#define H5P_VOL_INITIALIZE_DEFAULT (H5OPEN H5P_LST_VOL_INITIALIZE_ID_g) /* Common creation order flags (for links in groups and attributes on objects) */ #define H5P_CRT_ORDER_TRACKED 0x0001 @@ -195,6 +197,7 @@ H5_DLLVAR hid_t H5P_CLS_ATTRIBUTE_ACCESS_ID_g; H5_DLLVAR hid_t H5P_CLS_OBJECT_COPY_ID_g; H5_DLLVAR hid_t H5P_CLS_LINK_CREATE_ID_g; H5_DLLVAR hid_t H5P_CLS_LINK_ACCESS_ID_g; +H5_DLLVAR hid_t H5P_CLS_VOL_INITIALIZE_ID_g; /* Default roperty list IDs */ /* (Internal to library, do not use! Use macros above) */ @@ -213,6 +216,7 @@ H5_DLLVAR hid_t H5P_LST_ATTRIBUTE_ACCESS_ID_g; H5_DLLVAR hid_t H5P_LST_OBJECT_COPY_ID_g; H5_DLLVAR hid_t H5P_LST_LINK_CREATE_ID_g; H5_DLLVAR hid_t H5P_LST_LINK_ACCESS_ID_g; +H5_DLLVAR hid_t H5P_LST_VOL_INITIALIZE_ID_g; /*********************/ /* Public Prototypes */ diff --git a/src/H5Shyper.c b/src/H5Shyper.c index c2cdf2b..63f457b 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -44,25 +44,13 @@ /* Macro for checking if two ranges overlap one another */ /* - * Three possible conditions for overlapping: - * 1. The lower bound of range #1 is between the lower and - * higher bounds of range #2. In other words, the low - * part of range #1 will at least overlap with range #2. - * 2. The higher bound of range #1 is between the lower and - * higher bounds of range #2. In other words, the upper - * part of range #1 will at least overlap with range #2. - * 3. Range #1 includes range #2, i.e. the lower bound - * is smaller than that of range #2 and the higher bound - * is larger than that of range #2. + * Check for the inverse of whether the ranges are disjoint. If they are + * disjoint, then the low bound of one of the ranges must be greater than the + * high bound of the other. */ /* (Assumes that low & high bounds are _inclusive_) */ #define H5S_RANGE_OVERLAP(L1, H1, L2, H2) \ - /* condition 1 */ \ - (((L1) >= (L2) && (L1) <= (H2)) || \ - /* condition 2 */ \ - ((H1) >= (L2) && (H1) <= (H2)) || \ - /* condition 3 */ \ - ((L1) <= (L2) && (H1) >= (H2))) + (!((L1) > (H2) || (L2) > (H1))) /* Flags for which hyperslab fragments to compute */ #define H5S_HYPER_COMPUTE_B_NOT_A 0x01 @@ -84,6 +72,18 @@ (curr_span) = saved_next_span; \ } while(0) +/* Macro to add "skipped" elements to projection during the execution of + * H5S__hyper_project_intersect() */ +#define H5S_HYPER_PROJ_INT_ADD_SKIP(UDATA, ADD, ERR) \ + do { \ + /* If there are any elements to add, we must add them \ + * to the projection first before adding skip */ \ + if((UDATA)->nelem > 0) \ + if(H5S__hyper_proj_int_build_proj(UDATA) < 0) \ + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, ERR, "can't add elements to projected selection") \ + (UDATA)->skip += (ADD); \ + } while(0) /* end H5S_HYPER_PROJ_INT_ADD_SKIP() */ + /******************/ /* Local Typedefs */ @@ -93,6 +93,28 @@ /* (Makes it easier to understand the alloc / free calls) */ typedef hsize_t hbounds_t; +/* Struct for holding persistent information during iteration for + * H5S__hyper_project_intersect() */ +typedef struct { + const H5S_hyper_span_t *ds_span[H5S_MAX_RANK]; /* Array of the current spans in the destination space in each dimension */ + hsize_t ds_low[H5S_MAX_RANK]; /* Array of current low bounds (of iteration) for each element in ds_span */ + H5S_hyper_span_info_t *ps_span_info[H5S_MAX_RANK]; /* Array of span info structs for projected space during iteration */ + uint32_t ps_clean_bitmap; /* Bitmap of whether the nth rank has a clean projected space since the last time it was set to 1 */ + unsigned ss_rank; /* Rank of source space */ + unsigned ds_rank; /* Rank of destination space */ + unsigned depth; /* Current depth of iterator in destination space */ + hsize_t skip; /* Number of elements to skip in projected space */ + hsize_t nelem; /* Number of elements to add to projected space (after skip) */ + uint64_t op_gen; /* Operation generation for counting elements */ +} H5S_hyper_project_intersect_ud_t; + +/* Assert that H5S_MAX_RANK is <= 32 so our trick with using a 32 bit bitmap + * (ps_clean_bitmap) works. If H5S_MAX_RANK increases either increase the size + * of ps_clean_bitmap or change the algorithm to use an array. */ +#if H5S_MAX_RANK > 32 +#error H5S_MAX_RANK too large for ps_clean_bitmap field in H5S_hyper_project_intersect_ud_t struct +#endif + /********************/ /* Local Prototypes */ @@ -119,6 +141,8 @@ static herr_t H5S__hyper_clip_spans(H5S_hyper_span_info_t *a_spans, unsigned ndims, H5S_hyper_span_info_t **a_not_b, H5S_hyper_span_info_t **a_and_b, H5S_hyper_span_info_t **b_not_a); static herr_t H5S__hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); +static hsize_t H5S__hyper_spans_nelem_helper(H5S_hyper_span_info_t *spans, + uint64_t op_gen); static hsize_t H5S__hyper_spans_nelem(H5S_hyper_span_info_t *spans); static herr_t H5S__hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); static H5S_hyper_span_info_t *H5S__hyper_make_spans(unsigned rank, @@ -147,6 +171,10 @@ static herr_t H5S__hyper_iter_get_seq_list_opt(H5S_sel_iter_t *iter, size_t maxs size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len); static herr_t H5S__hyper_iter_get_seq_list_single(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len); +static herr_t H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata); +static herr_t H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info, + const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth, + H5S_hyper_project_intersect_ud_t *udata); static void H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count, hsize_t *block, hsize_t clip_size); static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, @@ -10442,6 +10470,579 @@ done: /*-------------------------------------------------------------------------- NAME + H5S__hyper_proj_int_build_proj + PURPOSE + Secondary iteration routine for H5S__hyper_project_intersection + USAGE + herr_t H5S__hyper_proj_int_build_proj(udata) + H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Takes the skip and nelem amounts listed in udata and converts them to + span trees in the projected space, using the destination space. This + is a non-recursive algorithm by necessity, it saves the current state + of iteration in udata and resumes in the same location on subsequent + calls. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__hyper_proj_int_build_proj(H5S_hyper_project_intersect_ud_t *udata) { + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + HDassert(udata->nelem > 0); + + /* + * Skip over skipped elements + */ + if(udata->skip > 0) { + /* Work upwards, finishing each span tree before moving up */ + HDassert(udata->ds_span[udata->depth]); + do { + /* Check for lowest dimension */ + if(udata->ds_span[udata->depth]->down) { + if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) { + /* If we will run out of elements to skip in this span, + * advance to the first not fully skipped span and break + * out of this loop (start moving downwards) */ + if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts; + udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + } /* end if */ + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + + /* If we will run out of elements to skip in this span, + * skip the remainder of the skipped elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip; + udata->skip = 0; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + } /* end else */ + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + if(udata->ds_span[udata->depth]) + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + else if(udata->depth > 0) { + /* If present, append this span tree to the higher dimension's, + * and release ownership of it */ + if(udata->ps_span_info[udata->depth]) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1], + udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1], + udata->ds_low[udata->depth - 1], + udata->ps_span_info[udata->depth]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]); + udata->ps_span_info[udata->depth] = NULL; + } /* end if */ + + /* Ran out of spans, move up one dimension */ + udata->depth--; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth]++; + } /* end if */ + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection") + } while((udata->skip > 0) + || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high)); + + /* Work downwards until skip is 0 */ + HDassert(udata->ds_span[udata->depth]); + while(udata->skip > 0) { + HDassert(udata->ds_span[udata->depth]->down); + udata->depth++; + udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head; + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + if(udata->ds_span[udata->depth]->down) { + do { + /* If we will run out of elements to skip in this span, + * advance to the first not fully skipped span and + * continue down */ + if(udata->skip < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip / udata->ds_span[udata->depth]->down->u.nelmts; + udata->skip %= udata->ds_span[udata->depth]->down->u.nelmts; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->skip > 0); + } /* end if */ + else { + do { + /* If we will run out of elements to skip in this span, + * skip the remainder of the skipped elements */ + if(udata->skip < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + udata->ds_low[udata->depth] += udata->skip; + udata->skip = 0; + break; + } /* end if */ + + /* Skip over this entire span */ + udata->skip -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->skip > 0); + } /* end else */ + } /* end while */ + } /* end if */ + + /* + * Add requested number of elements to projected space + */ + /* Work upwards, adding all elements of each span tree until it can't fit + * all elements */ + HDassert(udata->ds_span[udata->depth]); + do { + /* Check for lowest dimension */ + if(udata->ds_span[udata->depth]->down) { + if(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high) { + /* If we will run out of elements to add in this span, add + * any complete spans, advance to the first not fully added + * span, and break out of this loop (start moving downwards) + */ + if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts; + udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts; + } /* end if */ + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_span[udata->depth]->high, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + } /* end if */ + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + + /* If we will run out of elements to add in this span, add the + * remainder of the elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem; + udata->nelem = 0; + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + } /* end else */ + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + if(udata->ds_span[udata->depth]) + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + else if(udata->depth > 0) { + /* Append this span tree to the higher dimension's, and release + * ownership of it */ + HDassert(udata->ps_span_info[udata->depth]); + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth - 1], + udata->ds_rank - udata->depth + 1, udata->ds_low[udata->depth - 1], + udata->ds_low[udata->depth - 1], + udata->ps_span_info[udata->depth]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[udata->depth]); + udata->ps_span_info[udata->depth] = NULL; + + /* Ran out of spans, move up one dimension */ + udata->depth--; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth]++; + } /* end if */ + else { + /* We have finished the entire destination span tree. If there are + * still elements to add, issue an error. */ + if(udata->nelem > 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "insufficient elements in destination selection") + break; + } /* end else */ + } while((udata->nelem > 0) + || (udata->ds_low[udata->depth] > udata->ds_span[udata->depth]->high)); + + /* Work downwards until nelem is 0 */ + HDassert(udata->ds_span[udata->depth] || (udata->nelem == 0)); + while(udata->nelem > 0) { + HDassert(udata->ds_span[udata->depth]->down); + udata->depth++; + udata->ds_span[udata->depth] = udata->ds_span[udata->depth - 1]->down->head; + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + if(udata->ds_span[udata->depth]->down) { + do { + /* If we will run out of elements to add in this span, add + * any complete spans, advance to the first not fully added + * span and continue down + */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < H5S__hyper_spans_nelem_helper(udata->ds_span[udata->depth]->down, udata->op_gen) + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(udata->nelem >= udata->ds_span[udata->depth]->down->u.nelmts) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_low[udata->depth] + (udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts) - 1, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem / udata->ds_span[udata->depth]->down->u.nelmts; + udata->nelem %= udata->ds_span[udata->depth]->down->u.nelmts; + } /* end if */ + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], + udata->ds_rank - udata->depth, udata->ds_low[udata->depth], + udata->ds_span[udata->depth]->high, + udata->ds_span[udata->depth]->down) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->down->u.nelmts + * (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1); + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->nelem > 0); + } /* end if */ + else { + HDassert(udata->ds_rank - udata->depth == 1); + do { + /* If we will run out of elements to add in this span, add + * the remainder of the elements and break out */ + HDassert(udata->ds_low[udata->depth] <= udata->ds_span[udata->depth]->high); + if(udata->nelem < (udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1)) { + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_low[udata->depth] + udata->nelem - 1, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->ds_low[udata->depth] += udata->nelem; + udata->nelem = 0; + break; + } /* end if */ + + /* Append span tree for entire span */ + if(H5S__hyper_append_span(&udata->ps_span_info[udata->depth], 1, + udata->ds_low[udata->depth], udata->ds_span[udata->depth]->high, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + udata->nelem -= udata->ds_span[udata->depth]->high - udata->ds_low[udata->depth] + 1; + + /* Advance to next span */ + udata->ds_span[udata->depth] = udata->ds_span[udata->depth]->next; + HDassert(udata->ds_span[udata->depth]); + udata->ds_low[udata->depth] = udata->ds_span[udata->depth]->low; + } while(udata->nelem > 0); + } /* end else */ + } /* end while */ + + HDassert(udata->skip == 0); + HDassert(udata->nelem == 0); + + /* Mark projected space as changed (for all ranks) */ + udata->ps_clean_bitmap = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__hyper_proj_int_build_proj() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__hyper_proj_int_iterate + PURPOSE + Main iteration routine for H5S__hyper_project_intersection + USAGE + herr_t H5S__hyper_proj_int_iterate(ss_span_info,sis_span_info,count,depth,udata) + const H5S_hyper_span_info_t *ss_span_info; IN: Span tree for source selection + const H5S_hyper_span_info_t *sis_span_info; IN: Span tree for source intersect selection + hsize_t count; IN: Number of times to compute the intersection of ss_span_info and sis_span_info + unsigned depth; IN: Depth of iteration (in terms of rank) + H5S_hyper_project_intersect_ud_t *udata; IN/OUT: Persistent shared data for iteration + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Computes the intersection of ss_span_info and sis_span_info and projects it + to the projected space (held in udata). It accomplishes this by iterating + over both spaces and computing the number of elements to skip (in + ss_span_info) and the number of elements to add (the intersection) in a + sequential fashion (similar to run length encoding). As necessary, this + function both recurses into lower dimensions and calls + H5S__hyper_proj_int_build_proj to convert the skip/nelem pairs to the + projected span tree. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__hyper_proj_int_iterate(const H5S_hyper_span_info_t *ss_span_info, + const H5S_hyper_span_info_t *sis_span_info, hsize_t count, unsigned depth, + H5S_hyper_project_intersect_ud_t *udata) +{ + const H5S_hyper_span_t *ss_span; /* Current span in source space */ + const H5S_hyper_span_t *sis_span; /* Current span in source intersect space */ + hsize_t ss_low; /* Current low bounds of source span */ + hsize_t sis_low; /* Current low bounds of source intersect span */ + hsize_t high; /* High bounds of current intersection */ + hsize_t low; /* Low bounds of current intersection */ + hsize_t old_skip; /* Value of udata->skip before main loop */ + hsize_t old_nelem; /* Value of udata->nelem before main loop */ + hbool_t check_intersect; /* Whether to check for intersecting elements */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Check for non-overlapping bounds */ + check_intersect = TRUE; + for(u = 0; u < (udata->ss_rank - depth); u++) + if(!H5S_RANGE_OVERLAP(ss_span_info->low_bounds[u], + ss_span_info->high_bounds[u], + sis_span_info->low_bounds[u], + sis_span_info->high_bounds[u])) { + check_intersect = FALSE; + break; + } /* end if */ + + /* Only enter main loop if there's something to do */ + if(check_intersect) { + /* Set ps_clean_bitmap */ + udata->ps_clean_bitmap |= (((uint32_t)1) << depth); + + /* Save old skip and nelem */ + old_skip = udata->skip; + old_nelem = udata->nelem; + + /* Intersect spaces once per count */ + for(u = 0; u < count; u++) { + ss_span = ss_span_info->head; + sis_span = sis_span_info->head; + HDassert(ss_span && sis_span); + ss_low = ss_span->low; + sis_low = sis_span->low; + + /* Main loop */ + do { + /* Check if spans overlap */ + if(H5S_RANGE_OVERLAP(ss_low, ss_span->high, + sis_low, sis_span->high)) { + high = MIN(ss_span->high, sis_span->high); + if(ss_span->down) { + /* Add skipped elements if there's a pre-gap */ + if(ss_low < sis_low) { + low = sis_low; + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (sis_low - ss_low), FAIL); + } /* end if */ + else + low = ss_low; + + /* Recurse into next dimension down */ + if(H5S__hyper_proj_int_iterate(ss_span->down, sis_span->down, high - low + 1, depth + 1, udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't iterate over source selections") + } /* end if */ + else { + HDassert(depth == udata->ss_rank - 1); + + /* Add skipped elements if there's a pre-gap */ + if(ss_low < sis_low) { + low = sis_low; + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, sis_low - ss_low, FAIL); + } /* end if */ + else + low = ss_low; + + /* Add overlapping elements */ + udata->nelem += high - low + 1; + } /* end else */ + + /* Advance spans */ + if(ss_span->high == sis_span->high) { + /* Advance both spans */ + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end if */ + else if(ss_span->high == high) { + /* Advance source span */ + HDassert(ss_span->high < sis_span->high); + sis_low = high + 1; + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + } /* end if */ + else { + /* Advance source intersect span */ + HDassert(ss_span->high > sis_span->high); + ss_low = high + 1; + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end else */ + } /* end if */ + else { + /* Advance spans */ + if(ss_span->high < sis_low) { + /* Add skipped elements */ + if(ss_span->down) + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL); + else + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL); + + /* Advance source span */ + ss_span = ss_span->next; + if(ss_span) + ss_low = ss_span->low; + } /* end if */ + else { + /* Advance source intersect span */ + HDassert(ss_low > sis_span->high); + sis_span = sis_span->next; + if(sis_span) + sis_low = sis_span->low; + } /* end else */ + } /* end else */ + } while(ss_span && sis_span); + + if(ss_span && !((depth == 0) && (u == count - 1))) { + /* Count remaining elements in ss_span_info */ + if(ss_span->down) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_low + 1), FAIL); + ss_span = ss_span->next; + while(ss_span) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper(ss_span->down, udata->op_gen) * (ss_span->high - ss_span->low + 1), FAIL); + ss_span = ss_span->next; + } /* end while */ + } /* end if */ + else { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_low + 1, FAIL); + ss_span = ss_span->next; + while(ss_span) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, ss_span->high - ss_span->low + 1, FAIL); + ss_span = ss_span->next; + } /* end while */ + } /* end else */ + } /* end if */ + + /* Check if the projected space was not changed since we started the + * first iteration of the loop, if so we do not need to continue + * looping and can just copy the result */ + if(udata->ps_clean_bitmap & (((uint32_t)1) << depth)) { + HDassert(u == 0); + if(udata->skip == old_skip) { + /* First case: algorithm added only elements */ + HDassert(udata->nelem >= old_nelem); + udata->nelem += (count - 1) * (udata->nelem - old_nelem); + } /* end if */ + else if(udata->nelem == 0) { + /* Second case: algorithm added only skip. In this case, + * nelem must be 0 since otherwise adding skip would have + * triggered a change in the projected space */ + HDassert(old_nelem == 0); + HDassert(udata->skip > old_skip); + udata->skip += (count - 1) * (udata->skip - old_skip); + } /* end if */ + else { + /* Third case: agorithm added skip and nelem (in that + * order). Add the same skip and nelem once for each item + * remaining in count. */ + hsize_t skip_add; + hsize_t nelem_add; + + HDassert(udata->nelem > 0); + HDassert(udata->skip > old_skip); + HDassert(old_nelem == 0); + + skip_add = udata->skip - old_skip; + nelem_add = udata->nelem - old_nelem; + for(u = 1; u < count; u++) { + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, skip_add, FAIL); + udata->nelem += nelem_add; + } /* end for */ + } /* end else */ + + /* End loop since we already took care of it */ + break; + } /* end if */ + } /* end for */ + } /* end if */ + else if(depth > 0) + /* Just count skipped elements */ + H5S_HYPER_PROJ_INT_ADD_SKIP(udata, H5S__hyper_spans_nelem_helper((H5S_hyper_span_info_t *)ss_span_info, udata->op_gen) * count, FAIL); /* Casting away const OK -NAF */ + + /* Clean up if we are done */ + if(depth == 0) { + /* Add remaining elements */ + if(udata->nelem > 0) + if(H5S__hyper_proj_int_build_proj(udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't add elements to projected selection") + + /* Append remaining span trees */ + for(u = udata->ds_rank - 1; u > 0; u--) + if(udata->ps_span_info[u]) { + if(H5S__hyper_append_span(&udata->ps_span_info[u - 1], + udata->ds_rank - u + 1, udata->ds_low[u - 1], + udata->ds_low[u - 1], + udata->ps_span_info[u]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + H5S__hyper_free_span_info(udata->ps_span_info[u]); + udata->ps_span_info[u] = NULL; + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__hyper_proj_int_iterate() */ + + +/*-------------------------------------------------------------------------- + NAME H5S__hyper_project_intersection PURPOSE Projects the intersection of of the selections of src_space and @@ -10461,7 +11062,9 @@ done: within the selection of dst_space. The result is placed in the selection of proj_space. Note src_space, dst_space, and src_intersect_space do not need to use hyperslab selections, but they cannot use point selections. - The result is always a hyperslab selection. + The result is always a hyperslab or none selection. Note also that + proj_space can share some span trees with dst_space, so proj_space + must not be subsequently modified if dst_space must be preserved. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES @@ -10471,43 +11074,11 @@ herr_t H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, const H5S_t *src_intersect_space, H5S_t *proj_space) { - hsize_t ss_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_space */ - size_t ss_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_space */ - size_t ss_nseq; /* Number of sequences for src_space */ - size_t ss_nelem; /* Number of elements for src_space */ - size_t ss_i = (size_t)0; /* Index into offset/length arrays for src_space */ - hbool_t advance_ss = FALSE; /* Whether to advance ss_i on the next iteration */ - H5S_sel_iter_t *ss_iter = NULL; /* Selection iterator for src_space */ - hbool_t ss_iter_init = FALSE; /* Whether ss_iter is initialized */ - hsize_t ss_sel_off = (hsize_t)0; /* Offset within src_space selection */ - hsize_t ds_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for dst_space */ - size_t ds_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for dst_space */ - size_t ds_nseq; /* Number of sequences for dst_space */ - size_t ds_nelem; /* Number of elements for dst_space */ - size_t ds_i = (size_t)0; /* Index into offset/length arrays for dst_space */ - H5S_sel_iter_t *ds_iter = NULL; /* Selection iterator for dst_space */ - hbool_t ds_iter_init = FALSE; /* Whether ds_iter is initialized */ - hsize_t ds_sel_off = (hsize_t)0; /* Offset within dst_space selection */ - hsize_t sis_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_intersect_space */ - size_t sis_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_intersect_space */ - size_t sis_nseq; /* Number of sequences for src_intersect_space */ - size_t sis_nelem; /* Number of elements for src_intersect_space */ - size_t sis_i = (size_t)0; /* Index into offset/length arrays for src_intersect_space */ - hbool_t advance_sis = FALSE; /* Whether to advance sis_i on the next iteration */ - H5S_sel_iter_t *sis_iter = NULL; /* Selection iterator for src_intersect_space */ - hbool_t sis_iter_init = FALSE; /* Whether sis_iter is initialized */ - hsize_t int_sel_off; /* Offset within intersected selections (ss/sis and ds/ps) */ - size_t int_len; /* Length of segment in intersected selections */ - hsize_t proj_off; /* Segment offset in proj_space */ - size_t proj_len; /* Segment length in proj_space */ - size_t proj_len_rem; /* Remaining length in proj_space for segment */ - hsize_t proj_down_dims[H5S_MAX_RANK]; /* "Down" dimensions in proj_space */ - H5S_hyper_span_info_t *curr_span_tree[H5S_MAX_RANK]; /* Current span tree being built (in each dimension) */ - hsize_t curr_span_up_dim[H5S_MAX_RANK]; /* "Up" dimensions for current span */ - unsigned proj_rank; /* Rank of proj_space */ - hsize_t low; /* Low value of span */ - size_t nelem; /* Number of elements returned for get_seq_list op */ - unsigned u; /* Local index variable */ + H5S_hyper_project_intersect_ud_t udata; /* User data for subroutines */ + const H5S_hyper_span_info_t *ss_span_info; + const H5S_hyper_span_info_t *ds_span_info; + H5S_hyper_span_info_t *ss_span_info_buf = NULL; + H5S_hyper_span_info_t *ds_span_info_buf = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -10521,280 +11092,88 @@ H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, /* Assert that src_space and src_intersect_space have same extent and there * are no point selections */ HDassert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space)); - HDassert(!HDmemcmp(src_space->extent.size, src_intersect_space->extent.size, - (size_t)H5S_GET_EXTENT_NDIMS(src_space) * sizeof(src_space->extent.size[0]))); + HDassert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space)); HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_POINTS); HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_POINTS); - HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) != H5S_SEL_POINTS); - - /* Initialize prev_space, curr_span_tree, and curr_span_up_dim */ - HDmemset(curr_span_tree, 0, sizeof(curr_span_tree)); - HDmemset(curr_span_up_dim, 0, sizeof(curr_span_up_dim)); + HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS); - /* Save rank of projected space */ - proj_rank = proj_space->extent.rank; - HDassert(proj_rank > 0); + /* Set up ss_span_info */ + if(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_HYPERSLABS) { + /* Make certain the selection has a span tree */ + if(NULL == src_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)src_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source hyperslab selection") - /* Get numbers of elements */ - ss_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_space); - ds_nelem = (size_t)H5S_GET_SELECT_NPOINTS(dst_space); - sis_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_intersect_space); - HDassert(ss_nelem == ds_nelem); - - /* Calculate proj_down_dims */ - if(H5VM_array_down(proj_rank, proj_space->extent.size, proj_down_dims) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value") - - /* Remove current selection from proj_space */ - if(H5S_SELECT_RELEASE(proj_space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - - /* If any selections are empty, skip to the end so "none" is selected */ - if((ss_nelem == 0) || (ds_nelem == 0) || (sis_nelem == 0)) - goto loop_end; - - /* Allocate space for the hyperslab selection information (note this sets - * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */ - if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info") - - /* Set selection type */ - proj_space->select.type = H5S_sel_hyper; - - /* Set unlim_dim */ - proj_space->select.sel_info.hslab->unlim_dim = -1; - - /* Allocate the source selection iterator */ - if(NULL == (ss_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source selection iterator") - - /* Initialize source space iterator */ - if(H5S_select_iter_init(ss_iter, src_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ss_iter_init = TRUE; - - /* Get sequence list for source space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - ss_nelem -= nelem; - HDassert(ss_nseq > 0); - - /* Allocate the destination selection iterator */ - if(NULL == (ds_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate destination selection iterator") - - /* Initialize destination space iterator */ - if(H5S_select_iter_init(ds_iter, dst_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ds_iter_init = TRUE; - - /* Get sequence list for destination space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - ds_nelem -= nelem; - HDassert(ds_nseq > 0); - - /* Allocate the source intersect space iterator */ - if(NULL == (sis_iter = H5FL_MALLOC(H5S_sel_iter_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate source intersect space iterator") - - /* Initialize source intersect space iterator */ - if(H5S_select_iter_init(sis_iter, src_intersect_space, (size_t)1, 0) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - sis_iter_init = TRUE; - - /* Get sequence list for source intersect space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - sis_nelem -= nelem; - HDassert(sis_nseq > 0); - - /* Loop until we run out of sequences in either the source or source - * intersect space */ - while(1) { - while(advance_ss || (ss_off[ss_i] + ss_len[ss_i] <= sis_off[sis_i])) { - /* Either we finished the current source sequence or the - * sequences do not intersect. Advance source space. */ - ss_sel_off += (hsize_t)ss_len[ss_i]; - if(++ss_i == ss_nseq) { - if(ss_nelem > 0) { - /* Try to grab more sequences from src_space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(ss_len[0] > 0); - - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= ss_nelem); - ss_nelem -= nelem; - - /* Reset source space index */ - ss_i = 0; - } /* end if */ - else - /* There are no more sequences in src_space, so we can exit - * the loop. Use goto instead of break so we exit the outer - * loop. */ - goto loop_end; - } /* end if */ + /* Simply point to existing span tree */ + ss_span_info = src_space->select.sel_info.hslab->span_lst; + } /* end if */ + else { + /* Create temporary span tree from all selection */ + HDassert(H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_ALL); - /* Reset advance_ss */ - advance_ss = FALSE; - } /* end while */ - if(advance_sis || (sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i])) { - do { - /* Either we finished the current source intersect sequence or - * the sequences do not intersect. Advance source intersect - * space. */ - if(++sis_i == sis_nseq) { - if(sis_nelem > 0) { - /* Try to grab more sequences from src_intersect_space - */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(sis_len[0] > 0); + if(NULL == (ss_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(src_space), + H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, src_space->extent.size))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL source space") + ss_span_info = ss_span_info_buf; + } /* end else */ - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= sis_nelem); - sis_nelem -= nelem; + /* Set up ds_span_info */ + if(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_HYPERSLABS) { + /* Make certain the selection has a span tree */ + if(NULL == dst_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)dst_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for dsetination hyperslab selection") - /* Reset source space index */ - sis_i = 0; - } /* end if */ - else - /* There are no more sequences in src_intersect_space, - * so we can exit the loop. Use goto instead of break - * so we exit the outer loop. */ - goto loop_end; - } /* end if */ - } while(sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i]); - - /* Reset advance_sis */ - advance_sis = FALSE; - } /* end if */ - else { - /* Sequences intersect, add intersection to projected space */ - /* Calculate intersection sequence in terms of offset within source - * selection and advance any sequences we complete */ - if(ss_off[ss_i] >= sis_off[sis_i]) - int_sel_off = ss_sel_off; - else - int_sel_off = sis_off[sis_i] - ss_off[ss_i] + ss_sel_off; - if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) <= (sis_off[sis_i] - + (hsize_t)sis_len[sis_i])) { - int_len = (size_t)((hsize_t)ss_len[ss_i] + ss_sel_off - int_sel_off); - advance_ss = TRUE; - } /* end if */ - else - int_len = (size_t)(sis_off[sis_i] + (hsize_t)sis_len[sis_i] - ss_off[ss_i] + ss_sel_off - int_sel_off); - if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) >= (sis_off[sis_i] - + (hsize_t)sis_len[sis_i])) - advance_sis = TRUE; - - /* Project intersection sequence to destination selection */ - while(int_len > (size_t)0) { - while(ds_sel_off + (hsize_t)ds_len[ds_i] <= int_sel_off) { - /* Intersection is not projected to this destination - * sequence, advance destination space */ - ds_sel_off += (hsize_t)ds_len[ds_i]; - if(++ds_i == ds_nseq) { - HDassert(ds_nelem > 0); - - /* Try to grab more sequences from dst_space */ - if(H5S_SELECT_ITER_GET_SEQ_LIST(ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") - HDassert(ds_len[0] > 0); - - /* Update ss_nelem */ - HDassert(nelem > 0); - HDassert(nelem <= ds_nelem); - ds_nelem -= nelem; - - /* Reset source space index */ - ds_i = 0; - } /* end if */ - } /* end while */ + /* Simply point to existing span tree */ + ds_span_info = dst_space->select.sel_info.hslab->span_lst; + } /* end if */ + else { + /* Create temporary span tree from all selection */ + HDassert(H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_ALL); - /* Add sequence to projected space */ - HDassert(ds_sel_off <= int_sel_off); - proj_off = ds_off[ds_i] + int_sel_off - ds_sel_off; - proj_len = proj_len_rem = (size_t)MIN(int_len, - (size_t)(ds_sel_off + (hsize_t)ds_len[ds_i] - int_sel_off)); - - /* Add to span tree */ - while(proj_len_rem > (size_t)0) { - hsize_t high; /* High value of span */ - size_t span_len; /* Length of span */ - - /* Append spans in higher dimensions if we're going ouside - * the plane of the span currently being built (i.e. it's - * finished being built) */ - /* Check for more than one full row (in every dim) and - * append multiple spans at once? -NAF */ - for(u = proj_rank - 1; ((u > 0) - && ((proj_off / proj_down_dims[u - 1]) - != curr_span_up_dim[u - 1])); u--) { - if(curr_span_tree[u]) { - /* Append complete lower dimension span tree to - * current dimension */ - low = curr_span_up_dim[u - 1] % proj_space->extent.size[u - 1]; - if(H5S__hyper_append_span(&curr_span_tree[u - 1], (proj_rank - u) + 1, low, low, curr_span_tree[u]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + if(NULL == (ds_span_info_buf = H5S__hyper_make_spans(H5S_GET_EXTENT_NDIMS(dst_space), + H5S_hyper_zeros_g, H5S_hyper_zeros_g, H5S_hyper_ones_g, dst_space->extent.size))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't create span tree for ALL destination space") + ds_span_info = ds_span_info_buf; + } /* end else */ - /* Reset lower dimension's span tree and previous - * span since we just committed it and will start - * over with a new one */ - H5S__hyper_free_span_info(curr_span_tree[u]); - curr_span_tree[u] = NULL; - } /* end if */ + /* Make certain the source intersect selection has a span tree */ + if(NULL == src_intersect_space->select.sel_info.hslab->span_lst) + if(H5S__hyper_generate_spans((H5S_t *)src_intersect_space) < 0) /* Casting away const OK -NAF */ + HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "can't construct span tree for source intersect hyperslab selection") - /* Update curr_span_up_dim */ - curr_span_up_dim[u - 1] = proj_off / proj_down_dims[u - 1]; - } /* end for */ + /* Initialize udata */ + HDmemset(&udata, 0, sizeof(udata)); + udata.ds_span[0] = ds_span_info->head; + udata.ds_low[0] = udata.ds_span[0]->low; + udata.ss_rank = H5S_GET_EXTENT_NDIMS(src_space); + udata.ds_rank = H5S_GET_EXTENT_NDIMS(dst_space); + udata.op_gen = H5S__hyper_get_op_gen(); - /* Compute bounds for new span in lowest dimension */ - low = proj_off % proj_space->extent.size[proj_rank - 1]; - span_len = MIN(proj_len_rem, - (size_t)(proj_space->extent.size[proj_rank - 1] - - low)); - HDassert(proj_len_rem >= span_len); - high = (low + (hsize_t)span_len) - (hsize_t)1; + /* Iterate over selections and build projected span tree */ + if(H5S__hyper_proj_int_iterate(ss_span_info, src_intersect_space->select.sel_info.hslab->span_lst, 1, 0, &udata) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "selection iteration failed") - /* Append span in lowest dimension */ - if(H5S__hyper_append_span(&curr_span_tree[proj_rank - 1], 1, low, high, NULL) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + /* Remove current selection from proj_space */ + if(H5S_SELECT_RELEASE(proj_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - /* Update remaining offset and length */ - proj_off += (hsize_t)span_len; - proj_len_rem -= span_len; - } /* end while */ + /* Check for elements in projected space */ + if(udata.ps_span_info[0]) { + /* Allocate space for the hyperslab selection information (note this sets + * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */ + if(NULL == (proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info") - /* Update intersection sequence */ - int_sel_off += (hsize_t)proj_len; - int_len -= proj_len; - } /* end while */ - } /* end else */ - } /* end while */ - -loop_end: - /* Add remaining spans to span tree */ - for(u = proj_rank - 1; u > 0; u--) - if(curr_span_tree[u]) { - /* Append remaining span tree to higher dimension */ - low = curr_span_up_dim[u - 1] % proj_space->extent.size[u - 1]; - if(H5S__hyper_append_span(&curr_span_tree[u - 1], (proj_rank - u) + 1, low, low, curr_span_tree[u]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span") + /* Set selection type */ + proj_space->select.type = H5S_sel_hyper; - /* Reset span tree */ - H5S__hyper_free_span_info(curr_span_tree[u]); - curr_span_tree[u] = NULL; - } /* end if */ + /* Set unlim_dim */ + proj_space->select.sel_info.hslab->unlim_dim = -1; - /* Add span tree to proj_space */ - if(curr_span_tree[0]) { - proj_space->select.sel_info.hslab->span_lst = curr_span_tree[0]; - curr_span_tree[0] = NULL; + /* Set span tree */ + proj_space->select.sel_info.hslab->span_lst = udata.ps_span_info[0]; + udata.ps_span_info[0] = NULL; /* Set the number of elements in current selection */ proj_space->select.num_elem = H5S__hyper_spans_nelem(proj_space->select.sel_info.hslab->span_lst); @@ -10810,36 +11189,40 @@ loop_end: HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") done: - /* Release source selection iterator */ - if(ss_iter_init && H5S_SELECT_ITER_RELEASE(ss_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(ss_iter) - ss_iter = H5FL_FREE(H5S_sel_iter_t, ss_iter); - - /* Release destination selection iterator */ - if(ds_iter_init && H5S_SELECT_ITER_RELEASE(ds_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(ds_iter) - ds_iter = H5FL_FREE(H5S_sel_iter_t, ds_iter); - - /* Release source intersect selection iterator */ - if(sis_iter_init && H5S_SELECT_ITER_RELEASE(sis_iter) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") - if(sis_iter) - sis_iter = H5FL_FREE(H5S_sel_iter_t, sis_iter); + /* Free ss_span_info_buf */ + if(ss_span_info_buf) { + H5S__hyper_free_span_info(ss_span_info_buf); + ss_span_info_buf = NULL; + } /* end if */ + + /* Free ds_span_info_buf */ + if(ds_span_info_buf) { + H5S__hyper_free_span_info(ds_span_info_buf); + ds_span_info_buf = NULL; + } /* end if */ /* Cleanup on error */ if(ret_value < 0) { - /* Remove current selection from proj_space */ - if(H5S_SELECT_RELEASE(proj_space) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") + unsigned u; /* Free span trees */ - for(u = 0; u < proj_rank; u++) - if(curr_span_tree[u]) - H5S__hyper_free_span_info(curr_span_tree[u]); + for(u = 0; u < udata.ds_rank; u++) + if(udata.ps_span_info[u]) { + H5S__hyper_free_span_info(udata.ps_span_info[u]); + udata.ps_span_info[u] = NULL; + } /* end if */ } /* end if */ +#ifndef NDEBUG + /* Verify there are no more span trees */ + { + unsigned u; + + for(u = 0; u < H5S_MAX_RANK; u++) + HDassert(!udata.ps_span_info[u]); + } /* end block */ +#endif /* NDEBUG */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S__hyper_project_intersection() */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 80b5ea1..6983c93 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -2374,10 +2374,11 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, if(H5S_select_copy(new_space, dst_space, FALSE) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection") } /* end if */ - /* If any of the spaces are "none", the projection must also be "none" */ - else if((src_intersect_space->select.type->type == H5S_SEL_NONE) - || (src_space->select.type->type == H5S_SEL_NONE) - || (dst_space->select.type->type == H5S_SEL_NONE)) { + /* If any of the selections contain no elements, the projection must be + * "none" */ + else if((H5S_GET_SELECT_NPOINTS(src_intersect_space) == 0) + || (H5S_GET_SELECT_NPOINTS(src_space) == 0) + || (H5S_GET_SELECT_NPOINTS(dst_space) == 0)) { /* Change to "none" selection */ if(H5S_select_none(new_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") @@ -2389,6 +2390,8 @@ H5S_select_project_intersection(const H5S_t *src_space, const H5S_t *dst_space, HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") else { HDassert(src_intersect_space->select.type->type == H5S_SEL_HYPERSLABS); + HDassert(src_space->select.type->type != H5S_SEL_NONE); + HDassert(dst_space->select.type->type != H5S_SEL_NONE); /* Intersecting space is hyperslab selection. Call the hyperslab * routine to project to another hyperslab selection. */ @@ -31,6 +31,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Iprivate.h" /* IDs */ +#include "H5Pprivate.h" /* Property lists */ #include "H5VLpkg.h" /* Virtual Object Layer */ /* VOL connectors */ @@ -101,6 +102,13 @@ H5VLregister_connector(const H5VL_class_t *cls, hid_t vipl_id) if (cls->wrap_cls.get_wrap_ctx && !cls->wrap_cls.free_wrap_ctx) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "VOL connector must provide free callback for object wrapping contexts when a get callback is provided") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector(cls, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") @@ -138,6 +146,13 @@ H5VLregister_connector_by_name(const char *name, hid_t vipl_id) if (0 == HDstrlen(name)) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "zero-length VOL connector name is disallowed") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector_by_name(name, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") @@ -173,6 +188,13 @@ H5VLregister_connector_by_value(H5VL_class_value_t value, hid_t vipl_id) if(value < 0) HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, H5I_INVALID_HID, "negative VOL connector value is disallowed") + /* Check VOL initialization property list */ + if(H5P_DEFAULT == vipl_id) + vipl_id = H5P_VOL_INITIALIZE_DEFAULT; + else + if(TRUE != H5P_isa_class(vipl_id, H5P_VOL_INITIALIZE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a VOL initialize property list") + /* Register connector */ if((ret_value = H5VL__register_connector_by_value(value, TRUE, vipl_id)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register VOL connector") diff --git a/src/H5trace.c b/src/H5trace.c index 851ec73..1125072 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -2714,6 +2714,9 @@ H5_trace(const double *returning, const char *func, const char *type, ...) case H5VL_FILE_GET_INTENT: HDfprintf(out, "H5VL_FILE_GET_INTENT"); break; + case H5VL_FILE_GET_FILENO: + HDfprintf(out, "H5VL_FILE_GET_FILENO"); + break; case H5VL_FILE_GET_NAME: HDfprintf(out, "H5VL_FILE_GET_NAME"); break; @@ -1409,7 +1409,7 @@ test_basic_io(unsigned config, hid_t fapl) int erbuf[10][26]; /* Expected read buffer */ int fill = -1; /* Fill value */ herr_t ret; /* Generic return value */ - int i, j; + int i, j, u, v; TESTING("basic virtual dataset I/O") @@ -3498,6 +3498,724 @@ test_basic_io(unsigned config, hid_t fapl) memspace = -1; + /* + * Test 8: For code coverage: Horizontal block virtual mappings, and file + * selection, grid memory selection + */ + /* Clear virtual layout in DCPL */ + if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0) + TEST_ERROR + + /* Create memory dataspace */ + if((memspace = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create virtual dataspaces */ + dims[0] = 8; + dims[1] = 15; + if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create source dataspace */ + dims[0] = 4; + if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Select all in source space (should not be necessary, but just to be sure) + */ + if(H5Sselect_all(srcspace[0]) < 0) + TEST_ERROR + + /* Select hyperslabs in virtual spaces */ + start[0] = 0; + start[1] = 0; + if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, dims, NULL) < 0) + TEST_ERROR + start[0] = 4; + if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, dims, NULL) < 0) + TEST_ERROR + + /* Add virtual layout mappings */ + if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0) + TEST_ERROR + if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0) + TEST_ERROR + + /* Reset dims */ + dims[0] = 10; + dims[1] = 26; + + /* Create virtual file */ + if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Create source file if requested */ + if(config & TEST_IO_DIFFERENT_FILE) { + if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + } + else { + srcfile[0] = vfile; + if(H5Iinc_ref(srcfile[0]) < 0) + TEST_ERROR + } + + /* Create source datasets */ + if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Create virtual dataset */ + if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Reset erbuf */ + HDmemset(erbuf[0], 0, sizeof(rbuf)); + + /* Populate write buffer */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j; + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + count[0] = 4; + count[1] = 15; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to first source dataset */ + if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + u = 0; + v = 0; + for(i = 2; i < 4; i++) + for(j = 0; j < 15; j++) { + erbuf[u][v] = buf[i][j]; + v += 2; + if(v >= 24) { + u += 2; + v = 0; + } + } + + /* Select hyperslab in memory */ + start[0] = 4; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to second source dataset */ + if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + for(i = 4; i < 6; i++) + for(j = 0; j < 15; j++) { + erbuf[u][v] = buf[i][j]; + v += 2; + if(v >= 24) { + u += 2; + v = 0; + } + } + + /* Close srcdsets and srcfile if config option specified */ + if(config & TEST_IO_CLOSE_SRC) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + + /* Reopen virtual dataset and file if config option specified */ + if(config & TEST_IO_REOPEN_VIRT) { + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0) + TEST_ERROR + } + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + stride[0] = 2; + stride[1] = 2; + count[0] = 5; + count[1] = 12; + block[0] = 1; + block[1] = 1; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, stride, count, block) < 0) + TEST_ERROR + + /* Select hyperslab in file */ + start[0] = 2; + start[1] = 0; + count[0] = 4; + count[1] = 15; + if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Read data through virtual dataset */ + HDmemset(rbuf[0], 0, sizeof(rbuf)); + if(H5Dread(vdset, H5T_NATIVE_INT, memspace, vspace[0], H5P_DEFAULT, rbuf[0]) < 0) + TEST_ERROR + + /* Verify read data */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + if(rbuf[i][j] != erbuf[i][j]) + TEST_ERROR + + /* Close */ + if(!(config & TEST_IO_CLOSE_SRC)) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if(H5Sclose(srcspace[0]) < 0) + TEST_ERROR + srcspace[0] = -1; + if(H5Sclose(vspace[0]) < 0) + TEST_ERROR + vspace[0] = -1; + if(H5Sclose(vspace[1]) < 0) + TEST_ERROR + vspace[1] = -1; + if(H5Sclose(memspace) < 0) + TEST_ERROR + memspace = -1; + + + /* + * Test 9: For code coverage: Horizontal block virtual mappings, and file + * selection, grid memory selection, 3 mappings, 3D memory space + */ + /* Clear virtual layout in DCPL */ + if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0) + TEST_ERROR + + /* Create memory dataspace */ + dims[1] = 13; + dims[2] = 2; + if((memspace = H5Screate_simple(3, dims, NULL)) < 0) + TEST_ERROR + + /* Create virtual dataspaces */ + dims[0] = 6; + dims[1] = 10; + if((vspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + if((vspace[1] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + if((vspace[2] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create source dataspace */ + dims[0] = 2; + if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Select all in source space (should not be necessary, but just to be sure) + */ + if(H5Sselect_all(srcspace[0]) < 0) + TEST_ERROR + + /* Select hyperslabs in virtual spaces */ + start[0] = 0; + start[1] = 0; + if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, dims, NULL) < 0) + TEST_ERROR + start[0] = 2; + if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, NULL, dims, NULL) < 0) + TEST_ERROR + start[0] = 4; + if(H5Sselect_hyperslab(vspace[2], H5S_SELECT_SET, start, NULL, dims, NULL) < 0) + TEST_ERROR + + /* Add virtual layout mappings */ + if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0) + TEST_ERROR + if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0) + TEST_ERROR + if(H5Pset_virtual(dcpl, vspace[2], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset3", srcspace[0]) < 0) + TEST_ERROR + + /* Reset dims */ + dims[0] = 10; + dims[1] = 26; + + /* Create virtual file */ + if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Create source file if requested */ + if(config & TEST_IO_DIFFERENT_FILE) { + if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + } + else { + srcfile[0] = vfile; + if(H5Iinc_ref(srcfile[0]) < 0) + TEST_ERROR + } + + /* Create source datasets */ + if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + if((srcdset[2] = H5Dcreate2(srcfile[0], "src_dset3", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Create virtual dataset */ + if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Reset erbuf */ + HDmemset(erbuf[0], 0, sizeof(rbuf)); + + /* Populate write buffer */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j; + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + start[2] = 0; + count[0] = 2; + count[1] = 5; + count[2] = 2; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to first source dataset */ + if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + u = 0; + v = 0; + for(i = 0; i < 2; i++) + for(j = 0; j < 10; j++) { + erbuf[u][v] = buf[i][j]; + if(++v == 6) + v += 2; + else if(v == 14) { + u += 2; + v = 0; + } + } + + /* Select hyperslab in memory */ + start[0] = 2; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to second source dataset */ + if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + for(i = 2; i < 4; i++) + for(j = 0; j < 10; j++) { + erbuf[u][v] = buf[i][j]; + if(++v == 6) + v += 2; + else if(v == 14) { + u += 2; + v = 0; + } + } + + /* Select hyperslab in memory */ + start[0] = 4; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to third source dataset */ + if(H5Dwrite(srcdset[2], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + for(i = 4; i < 6; i++) + for(j = 0; j < 10; j++) { + erbuf[u][v] = buf[i][j]; + if(++v == 6) + v += 2; + else if(v == 14) { + u += 2; + v = 0; + } + } + + /* Close srcdsets and srcfile if config option specified */ + if(config & TEST_IO_CLOSE_SRC) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Dclose(srcdset[2]) < 0) + TEST_ERROR + srcdset[2] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + + /* Reopen virtual dataset and file if config option specified */ + if(config & TEST_IO_REOPEN_VIRT) { + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0) + TEST_ERROR + } + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + start[2] = 0; + stride[0] = 2; + stride[1] = 4; + stride[2] = 1; + count[0] = 5; + count[1] = 2; + count[2] = 1; + block[0] = 1; + block[1] = 3; + block[2] = 2; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, stride, count, block) < 0) + TEST_ERROR + + /* Read data through virtual dataset */ + HDmemset(rbuf[0], 0, sizeof(rbuf)); + if(H5Dread(vdset, H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, rbuf[0]) < 0) + TEST_ERROR + + /* Verify read data */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + if(rbuf[i][j] != erbuf[i][j]) + TEST_ERROR + + /* Close */ + if(!(config & TEST_IO_CLOSE_SRC)) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Dclose(srcdset[2]) < 0) + TEST_ERROR + srcdset[2] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if(H5Sclose(srcspace[0]) < 0) + TEST_ERROR + srcspace[0] = -1; + if(H5Sclose(vspace[0]) < 0) + TEST_ERROR + vspace[0] = -1; + if(H5Sclose(vspace[1]) < 0) + TEST_ERROR + vspace[1] = -1; + if(H5Sclose(vspace[2]) < 0) + TEST_ERROR + vspace[2] = -1; + if(H5Sclose(memspace) < 0) + TEST_ERROR + memspace = -1; + + + /* + * Test 10: For code coverage: Vertical stripe virtual mappings, vertical + * block file selection, block memory selection, 3D VDS + */ + /* Clear virtual layout in DCPL */ + if(H5Pset_layout(dcpl, H5D_VIRTUAL) < 0) + TEST_ERROR + + /* Create memory dataspace */ + if((memspace = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Create virtual dataspaces */ + dims[0] = 10; + dims[1] = 9; + dims[2] = 6; + if((vspace[0] = H5Screate_simple(3, dims, NULL)) < 0) + TEST_ERROR + if((vspace[1] = H5Screate_simple(3, dims, NULL)) < 0) + TEST_ERROR + + /* Create source dataspace */ + dims[1] = 12; + if((srcspace[0] = H5Screate_simple(2, dims, NULL)) < 0) + TEST_ERROR + + /* Select all in source space (should not be necessary, but just to be sure) + */ + if(H5Sselect_all(srcspace[0]) < 0) + TEST_ERROR + + /* Select hyperslabs in virtual spaces */ + start[0] = 0; + start[1] = 0; + start[2] = 0; + count[0] = 1; + count[1] = 4; + count[2] = 3; + stride[0] = 1; + stride[1] = 2; + stride[2] = 2; + block[0] = 10; + block[1] = 1; + block[2] = 1; + if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, stride, count, block) < 0) + TEST_ERROR + start[2] = 1; + if(H5Sselect_hyperslab(vspace[1], H5S_SELECT_SET, start, stride, count, block) < 0) + TEST_ERROR + + /* Add virtual layout mappings */ + if(H5Pset_virtual(dcpl, vspace[0], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset1", srcspace[0]) < 0) + TEST_ERROR + if(H5Pset_virtual(dcpl, vspace[1], config & TEST_IO_DIFFERENT_FILE ? srcfilename_map : ".", "src_dset2", srcspace[0]) < 0) + TEST_ERROR + + /* Reset dims */ + dims[0] = 10; + dims[1] = 26; + + /* Create virtual file */ + if((vfile = H5Fcreate(vfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Create source file if requested */ + if(config & TEST_IO_DIFFERENT_FILE) { + if((srcfile[0] = H5Fcreate(srcfilename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + } + else { + srcfile[0] = vfile; + if(H5Iinc_ref(srcfile[0]) < 0) + TEST_ERROR + } + + /* Create source datasets */ + if((srcdset[0] = H5Dcreate2(srcfile[0], "src_dset1", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + if((srcdset[1] = H5Dcreate2(srcfile[0], "src_dset2", H5T_NATIVE_INT, srcspace[0], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Create virtual dataset */ + if((vdset = H5Dcreate2(vfile, "v_dset", H5T_NATIVE_INT, vspace[0], H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Initialize erbuf */ + HDmemset(erbuf[0], 0, sizeof(rbuf)); + for(i = 0; i < 10; i++) + for(j = 0; j < 24; j += 6) { + erbuf[i][j] = -1; + erbuf[i][j + 1] = -1; + } + + /* Populate write buffer */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + buf[i][j] = (i * (int)(sizeof(buf[0]) / sizeof(buf[0][0]))) + j; + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + count[0] = 10; + count[1] = 12; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to first source dataset */ + if(H5Dwrite(srcdset[0], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + u = 0; + v = 0; + for(i = 0; i < 10; i++) + for(j = 0; j < 8; j++) { + if(v == 0 || v == 12) + erbuf[u][v] = buf[i][j]; + v += 2; + if(!(v % 6)) + v += 6; + if(v >= 28) { + u++; + v = 0; + } + } + + /* Select hyperslab in memory */ + start[1] = 8; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Write data directly to second source dataset */ + if(H5Dwrite(srcdset[1], H5T_NATIVE_INT, memspace, H5S_ALL, H5P_DEFAULT, buf[0]) < 0) + TEST_ERROR + + /* Update erbuf */ + u = 0; + v = 1; + for(i = 0; i < 10; i++) + for(j = 8; j < 16; j++) { + if(v == 1 || v == 13) + erbuf[u][v] = buf[i][j]; + v += 2; + if(!((v - 1) % 6)) + v += 6; + if(v >= 28) { + u++; + v = 1; + } + } + + /* Close srcdsets and srcfile if config option specified */ + if(config & TEST_IO_CLOSE_SRC) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + + /* Reopen virtual dataset and file if config option specified */ + if(config & TEST_IO_REOPEN_VIRT) { + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if((vfile = H5Fopen(vfilename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + if((vdset = H5Dopen2(vfile, "v_dset", H5P_DEFAULT)) < 0) + TEST_ERROR + } + + /* Select hyperslab in memory */ + start[0] = 0; + start[1] = 0; + stride[0] = 1; + stride[1] = 6; + count[0] = 1; + count[1] = 4; + block[0] = 10; + block[1] = 2; + if(H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, stride, count, block) < 0) + TEST_ERROR + + /* Select hyperslab in file */ + start[0] = 0; + start[1] = 0; + start[2] = 0; + count[0] = 10; + count[1] = 4; + count[2] = 2; + if(H5Sselect_hyperslab(vspace[0], H5S_SELECT_SET, start, NULL, count, NULL) < 0) + TEST_ERROR + + /* Read data through virtual dataset */ + HDmemset(rbuf[0], 0, sizeof(rbuf)); + if(H5Dread(vdset, H5T_NATIVE_INT, memspace, vspace[0], H5P_DEFAULT, rbuf[0]) < 0) + TEST_ERROR + + /* Verify read data */ + for(i = 0; i < (int)(sizeof(buf) / sizeof(buf[0])); i++) + for(j = 0; j < (int)(sizeof(buf[0]) / sizeof(buf[0][0])); j++) + if(rbuf[i][j] != erbuf[i][j]) + TEST_ERROR + + /* Close */ + if(!(config & TEST_IO_CLOSE_SRC)) { + if(H5Dclose(srcdset[0]) < 0) + TEST_ERROR + srcdset[0] = -1; + if(H5Dclose(srcdset[1]) < 0) + TEST_ERROR + srcdset[1] = -1; + if(H5Fclose(srcfile[0]) < 0) + TEST_ERROR + srcfile[0] = -1; + } + if(H5Dclose(vdset) < 0) + TEST_ERROR + vdset = -1; + if(H5Fclose(vfile) < 0) + TEST_ERROR + vfile = -1; + if(H5Sclose(srcspace[0]) < 0) + TEST_ERROR + srcspace[0] = -1; + if(H5Sclose(vspace[0]) < 0) + TEST_ERROR + vspace[0] = -1; + if(H5Sclose(vspace[1]) < 0) + TEST_ERROR + vspace[1] = -1; + if(H5Sclose(memspace) < 0) + TEST_ERROR + memspace = -1; + + /* Close */ if(H5Pclose(dcpl) < 0) TEST_ERROR @@ -11,7 +11,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Purpose: Tests the virtual object layer (H5VL) + * Purpose: Tests the virtual object layer (H5VL) * * This is a minimal test to ensure VOL usage (setting a VOL, etc.) * works as expected. Actual VOL functionality is tested using @@ -149,6 +149,8 @@ static herr_t test_vol_registration(void) { hid_t native_id = H5I_INVALID_HID; + hid_t lapl_id = H5I_INVALID_HID; + hid_t vipl_id = H5I_INVALID_HID; herr_t ret = SUCCEED; htri_t is_registered = FAIL; hid_t vol_id = H5I_INVALID_HID; @@ -158,47 +160,66 @@ test_vol_registration(void) /* The test/fake VOL connector should not be registered at the start of the test */ if ((is_registered = H5VLis_connector_registered(FAKE_VOL_NAME)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; if (is_registered > 0) FAIL_PUTS_ERROR("VOL connector is inappropriately registered"); - /* Load a VOL interface */ - if ((vol_id = H5VLregister_connector(&fake_vol_g, H5P_DEFAULT)) < 0) - FAIL_STACK_ERROR; + /* Test registering a connector with an incorrect property list (SHOULD FAIL) */ + if ((lapl_id = H5Pcreate(H5P_LINK_ACCESS)) < 0) + TEST_ERROR; + H5E_BEGIN_TRY { + vol_id = H5VLregister_connector(&fake_vol_g, lapl_id); + } H5E_END_TRY; + if (H5I_INVALID_HID != vol_id) + FAIL_PUTS_ERROR("should not be able to register a connector with an incorrect property list"); + if (H5Pclose(lapl_id) < 0) + TEST_ERROR; + + /* Load a VOL interface + * The vipl_id does nothing without a VOL that needs it, but we do need to + * test creating a property list of that class and passing it along as a + * smoke check. + */ + if ((vipl_id = H5Pcreate(H5P_VOL_INITIALIZE)) < 0) + TEST_ERROR; + if ((vol_id = H5VLregister_connector(&fake_vol_g, vipl_id)) < 0) + TEST_ERROR; + if (H5Pclose(vipl_id) < 0) + TEST_ERROR; /* The test/fake VOL connector should be registered now */ if ((is_registered = H5VLis_connector_registered(FAKE_VOL_NAME)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; if (0 == is_registered) FAIL_PUTS_ERROR("VOL connector is un-registered"); /* Re-register a VOL connector */ if ((vol_id2 = H5VLregister_connector(&fake_vol_g, H5P_DEFAULT)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; /* The test/fake VOL connector should still be registered now */ if ((is_registered = H5VLis_connector_registered(FAKE_VOL_NAME)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; if (0 == is_registered) FAIL_PUTS_ERROR("VOL connector is un-registered"); /* Unregister the second test/fake VOL ID */ if (H5VLunregister_connector(vol_id2) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; /* The test/fake VOL connector should still be registered now */ if ((is_registered = H5VLis_connector_registered(FAKE_VOL_NAME)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; if (0 == is_registered) FAIL_PUTS_ERROR("VOL connector is un-registered"); /* Unregister the original test/fake VOL ID */ if (H5VLunregister_connector(vol_id) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; /* Try to unregister the native VOL connector (should fail) */ if (H5I_INVALID_HID == (native_id = H5VLget_connector_id(H5VL_NATIVE_NAME))) - FAIL_STACK_ERROR; + TEST_ERROR; H5E_BEGIN_TRY { ret = H5VLunregister_connector(native_id); } H5E_END_TRY; @@ -211,6 +232,8 @@ test_vol_registration(void) error: H5E_BEGIN_TRY { H5VLunregister_connector(vol_id); + H5Pclose(lapl_id); + H5Pclose(vipl_id); } H5E_END_TRY; return FAIL; @@ -235,7 +258,7 @@ test_native_vol_init(void) /* The native VOL connector should always be registered */ if ((is_registered = H5VLis_connector_registered(H5VL_NATIVE_NAME)) < 0) - FAIL_STACK_ERROR; + TEST_ERROR; if (0 == is_registered) FAIL_PUTS_ERROR("native VOL connector is un-registered"); @@ -293,7 +316,7 @@ test_basic_file_operation(const char *env_h5_drvr) if(H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI) < 0) TEST_ERROR; if(H5Pset_metadata_read_attempts(fapl_id, 9) < 0) - FAIL_STACK_ERROR + TEST_ERROR /* H5Fcreate */ if ((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0) |