From 15a79009266ab9f05deeac6131752fb91568501c Mon Sep 17 00:00:00 2001 From: Jerome Soumagne Date: Wed, 27 Apr 2016 15:33:32 -0500 Subject: Add support for metadata query in H5Q Refactor code between data/metadata query Store metadata plugin info in superblock Add dummy metadata plugin Tweak query and index tests --- src/CMakeLists.txt | 1 + src/H5D.c | 2 +- src/H5Dint.c | 17 +- src/H5Dprivate.h | 9 +- src/H5Fint.c | 274 +++++++++- src/H5Fpkg.h | 4 + src/H5Fprivate.h | 17 +- src/H5Fsuper.c | 15 + src/H5Q.c | 222 +++++++- src/H5X.c | 267 ++++++++-- src/H5Xmeta_dummy.c | 1439 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Xpkg.h | 5 + src/H5Xprivate.h | 10 +- src/H5Xpublic.h | 18 +- test/index.c | 72 +-- test/query.c | 247 ++++++++- 16 files changed, 2459 insertions(+), 160 deletions(-) create mode 100644 src/H5Xmeta_dummy.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 388ff28..4bf412c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -634,6 +634,7 @@ IDE_GENERATED_PROPERTIES ("H5WB" "${H5WB_HDRS}" "${H5WB_SRCS}" ) set (H5X_SRCS ${HDF5_SRC_DIR}/H5X.c ${HDF5_SRC_DIR}/H5Xdummy.c + ${HDF5_SRC_DIR}/H5Xmeta_dummy.c ${HDF5_SRC_DIR}/H5Pxapl.c ${HDF5_SRC_DIR}/H5Pxcpl.c ${HDF5_SRC_DIR}/H5Pxxpl.c diff --git a/src/H5D.c b/src/H5D.c index 715358a..5ff1e03 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -154,7 +154,7 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, dset->shared->dset_id = ret_value; /* Create index if told to */ - if(H5X_can_create(ret_value, dcpl_id) < 0) + if(H5X_can_create_data(ret_value, dcpl_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "Index can't be created on this dataset") done: diff --git a/src/H5Dint.c b/src/H5Dint.c index f84bdb7..7981ceb 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -3161,16 +3161,14 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D_set_index(H5D_t *dset, unsigned count, H5X_class_t **idx_class, - void **idx_handle, H5O_idxinfo_t *idx_info) +H5D_set_index(H5D_t *dset, H5X_class_t *idx_class, void *idx_handle, + H5O_idxinfo_t *idx_info) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(dset); - /* Do not support more than one index for now */ - HDassert(count <= 1); HDassert(idx_class); HDassert(idx_handle); HDassert(idx_info); @@ -3180,8 +3178,8 @@ H5D_set_index(H5D_t *dset, unsigned count, H5X_class_t **idx_class, HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update index header message"); /* Set user data for index */ - dset->shared->idx_class = *idx_class; - dset->shared->idx_handle = *idx_handle; + dset->shared->idx_class = idx_class; + dset->shared->idx_handle = idx_handle; if (NULL == H5O_msg_copy(H5O_IDXINFO_ID, idx_info, &dset->shared->idx_info)) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to update copy message"); @@ -3200,22 +3198,19 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D_get_index(H5D_t *dset, unsigned max_count, H5X_class_t **idx_class, - void **idx_handle, H5O_idxinfo_t **idx_info, unsigned *actual_count) +H5D_get_index(H5D_t *dset, H5X_class_t **idx_class, void **idx_handle, + H5O_idxinfo_t **idx_info) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(dset); - HDassert(max_count); /* Get user data for index */ if (idx_class) *idx_class = dset->shared->idx_class; if (idx_handle) *idx_handle = dset->shared->idx_handle; if (idx_info) *idx_info = &dset->shared->idx_info; - /* Just one index for now */ - if (actual_count) *actual_count = (dset->shared->idx_class) ? 1 : 0; FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_get_index() */ diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 121da08..34fa1fb 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -178,11 +178,10 @@ H5_DLL hid_t H5D_get_create_plist(H5D_t *dset); H5_DLL hid_t H5D_get_access_plist(H5D_t *dset); H5_DLL hid_t H5D_get_space(H5D_t *dset); H5_DLL hid_t H5D_get_type(H5D_t *dset); -H5_DLL herr_t H5D_set_index(H5D_t *dset, unsigned count, H5X_class_t **idx_class, - void **idx_handle, H5O_idxinfo_t *idx_info); -H5_DLL herr_t H5D_get_index(H5D_t *dset, unsigned max_count, - H5X_class_t **idx_class, void **idx_handle, H5O_idxinfo_t **idx_info, - unsigned *actual_count); +H5_DLL herr_t H5D_set_index(H5D_t *dset, H5X_class_t *idx_class, + void *idx_handle, H5O_idxinfo_t *idx_info); +H5_DLL herr_t H5D_get_index(H5D_t *dset, H5X_class_t **idx_class, + void **idx_handle, H5O_idxinfo_t **idx_info); H5_DLL herr_t H5D_remove_index(H5D_t *dset, unsigned plugin_id); H5_DLL herr_t H5D_get_index_size(H5D_t *dset, hsize_t *idx_size); H5_DLL H5S_t *H5D_query(H5D_t *dset, const H5S_t *file_space, const H5Q_t *query, diff --git a/src/H5Fint.c b/src/H5Fint.c index a5621b3..d07c26e 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -77,6 +77,8 @@ static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name);/* Declare a free list to manage the H5F_t struct */ +static herr_t H5F_open_index(H5F_t *file, hid_t xapl_id); +static herr_t H5F_close_index(H5F_t *file); /*********************/ /* Package Variables */ @@ -786,7 +788,12 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock") f->shared->sblock = NULL; } /* end if */ - + + /* Release index info */ + if (FAIL == H5O_msg_reset(H5O_IDXINFO_ID, &f->shared->idx_info)) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + /* Remove shared file struct from list of open files */ if(H5F_sfile_remove(f->shared) < 0) /* Push error, but keep going*/ @@ -1215,6 +1222,10 @@ H5F_close(H5F_t *f) HDassert(f); HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */ + /* Close index object if index is closed */ + if (f->shared->idx_handle && (FAIL == H5F_close_index(f))) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "cannot close index") + /* Perform checks for "semi" file close degree here, since closing the * file is not allowed if there are objects still open */ if(f->shared->fc_degree == H5F_CLOSE_SEMI) { @@ -2090,3 +2101,264 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__set_eoa() */ +/*------------------------------------------------------------------------- + * Function: H5F_set_index + * + * Purpose: Set index information. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_index(H5F_t *file, H5X_class_t *idx_class, void *idx_handle, + struct H5O_idxinfo_t *idx_info) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + HDassert(idx_class); + HDassert(idx_handle); + HDassert(idx_info); + + /* Write the index header message */ + if(H5F_super_ext_write_msg(file, H5AC_dxpl_id, idx_info, H5O_IDXINFO_ID, TRUE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_WRITEERROR, FAIL, "error in writing message to superblock extension") + + /* Set user data for index */ + file->shared->idx_class = idx_class; + file->shared->idx_handle = idx_handle; + if (NULL == H5O_msg_copy(H5O_IDXINFO_ID, idx_info, &file->shared->idx_info)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to update copy message"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_set_index() */ + +/*------------------------------------------------------------------------- + * Function: H5F_get_index + * + * Purpose: Get index information. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_index(H5F_t *file, H5X_class_t **idx_class, void **idx_handle, + struct H5O_idxinfo_t **idx_info) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(file); + + /* Get user data for index */ + if (idx_class) *idx_class = file->shared->idx_class; + if (idx_handle) *idx_handle = file->shared->idx_handle; + if (idx_info) *idx_info = &file->shared->idx_info; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_index() */ + +/*------------------------------------------------------------------------- + * Function: H5F_open_index + * + * Purpose: Open index. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_open_index(H5F_t *file, hid_t xapl_id) +{ + hid_t file_id; + H5X_class_t *idx_class; + void *idx_handle = NULL; + size_t metadata_size; + void *metadata; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + + file_id = file->file_id; + idx_class = file->shared->idx_class; + metadata_size = file->shared->idx_info.metadata_size; + metadata = file->shared->idx_info.metadata; + + if (NULL == H5I_object_verify(file_id, H5I_FILE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + if (NULL == metadata) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "no index metadata was found"); + if (NULL == idx_class->idx_class.metadata_class.open) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin open callback not defined"); + if (NULL == (idx_handle = idx_class->idx_class.metadata_class.open(file_id, xapl_id, metadata_size, metadata))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTOPENOBJ, FAIL, "cannot open index"); + + file->shared->idx_handle = idx_handle; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_open_index() */ + +/*------------------------------------------------------------------------- + * Function: H5F_close_index + * + * Purpose: Close index. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_close_index(H5F_t *file) +{ + H5X_class_t *idx_class; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + + idx_class = file->shared->idx_class; + if (NULL == (idx_class->idx_class.metadata_class.close)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin close callback not defined"); + if (FAIL == idx_class->idx_class.metadata_class.close(file->shared->idx_handle)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCLOSEOBJ, FAIL, "cannot close index"); + + file->shared->idx_handle = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_close_index() */ + +/*------------------------------------------------------------------------- + * Function: H5F_remove_index + * + * Purpose: Remove index. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_remove_index(H5F_t *file, unsigned H5_ATTR_UNUSED plugin_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + + /* First close index if opened */ + if (file->shared->idx_handle && (FAIL == H5F_close_index(file))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCLOSEOBJ, FAIL, "cannot close index"); + + /* Remove idx_handle from file */ + if(H5F_super_ext_remove_msg(file, H5AC_dxpl_id, H5O_IDXINFO_ID) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "error in removing message from superblock extension") + + if (FAIL == H5O_msg_reset(H5O_IDXINFO_ID, &file->shared->idx_info)) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to free index index"); + + file->shared->idx_class = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_remove_index() */ + +/*------------------------------------------------------------------------- + * Function: H5F_get_index_size + * + * Purpose: Get index index. + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_index_size(H5F_t *file, hsize_t *idx_size) +{ + H5X_class_t *idx_class = NULL; + hsize_t actual_size = 0; + hid_t xapl_id = H5P_INDEX_ACCESS_DEFAULT; /* TODO for now */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + HDassert(idx_size); + + idx_class = file->shared->idx_class; + if (!idx_class) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "index class not defined"); + if (NULL == (idx_class->idx_class.metadata_class.get_size)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin get size callback not defined"); + if (!file->shared->idx_handle && (FAIL == H5F_open_index(file, xapl_id))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTOPENOBJ, FAIL, "cannot open index"); + if (FAIL == idx_class->idx_class.metadata_class.get_size(file->shared->idx_handle, &actual_size)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "cannot get index size"); + + *idx_size = actual_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_index_size() */ + +/*------------------------------------------------------------------------- + * Function: H5F_query + * + * Purpose: Returns a set of object/attribute references that match + * the query. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_query(H5F_t *file, const struct H5Q_t *query, + size_t *ref_count, href_t *refs[], hid_t xapl_id, hid_t xxpl_id) +{ + H5X_class_t *idx_class; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file); + HDassert(query); + HDassert(ref_count); + HDassert(refs); + + idx_class = file->shared->idx_class; + + if (!idx_class) + HGOTO_DONE(SUCCEED); + + /* Index associated to file so use it */ + if (NULL == idx_class->idx_class.metadata_class.query) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin query callback not defined"); + + /* Open index if not opened yet */ + if (!file->shared->idx_handle && (FAIL == H5F_open_index(file, xapl_id))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTOPENOBJ, FAIL, "cannot open index"); + + /* Call query of index plugin */ + if (FAIL == idx_class->idx_class.metadata_class.query( + file->shared->idx_handle, query->query_id, xxpl_id, ref_count, refs)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCOMPARE, FAIL, "cannot query index"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_query */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 2255085..3e2d19b 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -293,6 +293,10 @@ struct H5F_file_t { /* Metadata accumulator information */ H5F_meta_accum_t accum; /* Metadata accumulator info */ + + void *idx_handle; /* Handle for the index */ + H5X_class_t *idx_class; /* Class for the index */ + struct H5O_idxinfo_t idx_info; /* Index information */ }; /* diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 658d123..cbe30fe 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -24,10 +24,11 @@ #include "H5Fpublic.h" /* Public headers needed by this file */ -#include "H5FDpublic.h" /* File drivers */ +#include "H5FDpublic.h" /* File drivers */ /* Private headers needed by this file */ -#include "H5VMprivate.h" /* Vectors and arrays */ +#include "H5VMprivate.h" /* Vectors and arrays */ +#include "H5Xprivate.h" /* Index */ /**************************/ @@ -555,6 +556,8 @@ struct H5UC_t; struct H5O_loc_t; struct H5HG_heap_t; struct H5P_genplist_t; +struct H5O_idxinfo_t; +struct H5Q_t; /* Forward declarations for anonymous H5F objects */ @@ -698,5 +701,15 @@ H5_DLL herr_t H5F_cwfs_remove_heap(H5F_file_t *shared, struct H5HG_heap_t *heap) /* Debugging functions */ H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth); +/* Index functions */ +H5_DLL herr_t H5F_set_index(H5F_t *f, H5X_class_t *idx_class, + void *idx_handle, struct H5O_idxinfo_t *idx_info); +H5_DLL herr_t H5F_get_index(H5F_t *f, H5X_class_t **idx_class, + void **idx_handle, struct H5O_idxinfo_t **idx_info); +H5_DLL herr_t H5F_remove_index(H5F_t *f, unsigned plugin_id); +H5_DLL herr_t H5F_get_index_size(H5F_t *f, hsize_t *idx_size); +H5_DLL herr_t H5F_query(H5F_t *file, const struct H5Q_t *query, + size_t *ref_count, href_t *refs[], hid_t xapl_id, hid_t xxpl_id); + #endif /* _H5Fprivate_H */ diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index c6b1c83..e9f5797 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -574,6 +574,21 @@ H5F__super_read(H5F_t *f, hid_t dxpl_id) f->shared->fs_addr[u] = fsinfo.fs_addr[u-1]; } /* end if */ + /* Check for the extension having a 'index info' message */ + if((status = H5O_msg_exists(&ext_loc, H5O_IDXINFO_ID, dxpl_id)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "can't check if message exists"); + if(status) { + H5O_idxinfo_t *idx_info; /* Pointer to dataset's info info */ + H5X_class_t *idx_class = NULL; + + idx_info = &f->shared->idx_info; + if(NULL == H5O_msg_read(&ext_loc, H5O_IDXINFO_ID, idx_info, dxpl_id)) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve message"); + if (NULL == (idx_class = H5X_registered(idx_info->plugin_id))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get index plugin class"); + f->shared->idx_class = idx_class; + } /* end if */ + /* Close superblock extension */ if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension") diff --git a/src/H5Q.c b/src/H5Q.c index d6331be..49079a8 100644 --- a/src/H5Q.c +++ b/src/H5Q.c @@ -180,6 +180,25 @@ struct { \ } while (0) #endif +#define H5R_FRIEND +#include "H5Rpkg.h" /* (Tmp) To re-use H5R__get_obj_name */ + +#define H5X_DUMMY_MAX_NAME_LEN (64 * 1024) +static void +printf_ref(href_t ref) +{ + char obj_name[H5X_DUMMY_MAX_NAME_LEN]; + + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, ref, obj_name, H5X_DUMMY_MAX_NAME_LEN); + if (H5Rget_type(ref) == H5R_EXT_ATTR) { + char attr_name[H5X_DUMMY_MAX_NAME_LEN]; + H5R__get_attr_name(NULL, ref, attr_name, H5X_DUMMY_MAX_NAME_LEN); + H5Q_LOG_DEBUG("Attribute reference: %s, %s", obj_name, attr_name); + } else { + H5Q_LOG_DEBUG("Object reference: %s", obj_name); + } +} + /******************/ /* Local Typedefs */ /******************/ @@ -240,6 +259,8 @@ static herr_t H5Q__apply_attr_name(const H5Q_t *query, hbool_t *result, static herr_t H5Q__apply_link_name(const H5Q_t *query, hbool_t *result, const char *name); +static herr_t H5Q__apply_index(hid_t loc_id, const H5Q_t *query, + H5Q_view_t *view, unsigned *result); static herr_t H5Q__apply_iterate(hid_t oid, const char *name, const H5O_info_t *oinfo, void *udata); static herr_t H5Q__apply_object(hid_t oid, const char *name, @@ -1880,15 +1901,16 @@ H5G_t * H5Q_apply(hid_t loc_id, const H5Q_t *query, unsigned *result, hid_t H5_ATTR_UNUSED vcpl_id) { - H5Q_apply_arg_t args; H5Q_view_t view = H5Q_VIEW_INITIALIZER(view); /* Resulting view */ H5G_t *ret_grp = NULL; /* New group created */ - H5G_t *ret_value = NULL; /* Return value */ H5P_genclass_t *pclass = NULL; unsigned flags; - hid_t fapl_id = FAIL; - H5F_t *new_file = NULL; + hid_t file_id = FAIL, fapl_id = FAIL; + H5F_t *file = NULL, *new_file = NULL; H5G_loc_t file_loc; + H5X_class_t *idx_class = NULL; + H5Q_type_t query_type; + H5G_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -1898,14 +1920,32 @@ H5Q_apply(hid_t loc_id, const H5Q_t *query, unsigned *result, /* First check and optimize query */ /* TODO */ - /* Create new view and init args */ - args.query = query; - args.result = result; - args.view = &view; + if (FAIL == (file_id = H5I_get_file_id(loc_id, FALSE))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, NULL, "can't get file ID from location"); + if (NULL == (file = H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a file"); + if (FAIL == H5F_get_index(file, &idx_class, NULL, NULL)) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get file index"); + if (FAIL == H5Q_get_type(query, &query_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, NULL, "unable to get query type"); + + /* Use metadata index if available instead of visiting all objects */ + /* TODO for now only use index if query is combined with metadata queries */ + if (idx_class && (query_type != H5Q_TYPE_DATA_ELEM)) { + if (FAIL == H5Q__apply_index(loc_id, query, &view, result)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCOMPARE, NULL, "unable to use metadata index"); + } else { + H5Q_apply_arg_t args; - if (FAIL == H5O_visit(loc_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE, H5Q__apply_iterate, - &args, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADITER, NULL, "object visitation failed"); + /* Create new view and init args */ + args.query = query; + args.result = result; + args.view = &view; + + if (FAIL == H5O_visit(loc_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE, H5Q__apply_iterate, + &args, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, NULL, "object visitation failed"); + } if (!H5Q_QUEUE_EMPTY(&view.reg_refs)) H5Q_LOG_DEBUG("Number of reg refs: %zu\n", view.reg_refs.n_elem); @@ -1979,6 +2019,166 @@ done: } /* end H5Q_apply() */ /*------------------------------------------------------------------------- + * Function: H5Q__apply_index + * + * Purpose: Private function for H5Q_apply. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q__apply_index(hid_t loc_id, const H5Q_t *query, H5Q_view_t *view, + unsigned *result) +{ + H5F_t *file = NULL; + hid_t xapl_id = H5P_INDEX_ACCESS_DEFAULT; + hid_t xxpl_id = H5P_INDEX_XFER_DEFAULT; + H5Q_type_t query_type; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if (NULL == (file = H5I_object_verify(loc_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "loc_id is restricted to dataset"); + + if (FAIL == H5Q_get_type(query, &query_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get query type"); + + /* TODO for now until we have wildcard support */ + if (query_type == H5Q_TYPE_DATA_ELEM) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unsupported query type"); + + /* Query is only of the same metadata type (may be combined) */ + if (query_type != H5Q_TYPE_MISC) { + size_t ref_count, i; + href_t *refs; + + if (FAIL == H5F_query(file, query, &ref_count, &refs, xapl_id, xxpl_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCOMPARE, FAIL, "cannot query index"); + for (i = 0; i < ref_count; i++) { + H5R_type_t ref_type = H5R_get_type(refs[i]); + + // printf_ref(idx_refs[i]); + *result |= (ref_type == H5R_EXT_ATTR) ? H5Q_REF_ATTR : H5Q_REF_OBJ; + if (FAIL == H5Q__view_append(view, ref_type, refs[i])) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + } + H5MM_free(refs); + } else { + /* Query is combined */ + H5Q_combine_op_t op_type; + + if (FAIL == H5Q_get_combine_op(query, &op_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get combine op"); + if (op_type == H5Q_COMBINE_AND) { + H5Q_t *query1, *query2; + H5Q_type_t query1_type, query2_type; + const H5Q_t *data_query, *metadata_query; + size_t ref_count, i; + href_t *refs; + + query1 = query->query.combine.l_query; + query2 = query->query.combine.r_query; + + if (FAIL == H5Q_get_type(query1, &query1_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get query type"); + if (FAIL == H5Q_get_type(query2, &query2_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get query type"); + + /* TODO clean that up */ + if (query1_type == H5Q_TYPE_DATA_ELEM) { + data_query = query1; + metadata_query = query2; + } else if (query2_type == H5Q_TYPE_DATA_ELEM) { + data_query = query2; + metadata_query = query1; + } else { + data_query = NULL; + metadata_query = query; + } + + /* Passing complex queries to plugins would be inefficient so we need to + * break queries down so that we only pass "AND combined" queries. This + * allows us to use a metadata index plugin on the metadata query part and + * a data index plugin on the data query part. + */ + if (FAIL == H5F_query(file, metadata_query, &ref_count, &refs, xapl_id, xxpl_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCOMPARE, FAIL, "cannot query index"); + for (i = 0; i < ref_count; i++) { + if (data_query) { + href_t ref; + hid_t obj_id = FAIL; + H5S_t *dataspace = NULL; + H5D_t *dataset = NULL; + char obj_name[64]; + +// H5I_type_t obj_type; +// if(H5R__get_obj_type(loc.oloc->file, H5AC_ind_dxpl_id, ref, obj_type) < 0) +// HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to determine object type") + if((obj_id = H5R__get_object(file, H5P_DATASET_ACCESS_DEFAULT, H5AC_ind_dxpl_id, refs[i], FALSE)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to get_object object") + + H5R__get_obj_name(file, H5P_DEFAULT, H5P_DEFAULT, refs[i], obj_name, 64); + + if (NULL == (dataset = (H5D_t *) H5I_object_verify(obj_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Query dataset */ + if (NULL == (dataspace = H5D_query(dataset, NULL, data_query, H5P_INDEX_ACCESS_DEFAULT, H5P_INDEX_XFER_DEFAULT))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't query dataset"); + + /* No element matched the query */ + if (H5S_SEL_NONE == H5S_get_select_type(dataspace)) + HGOTO_DONE(SUCCEED); + + *result = H5Q_REF_REG; + + /* Keep dataset region reference */ + if (NULL == (ref = H5R_create_ext_region(H5F_OPEN_NAME(file), obj_name, dataspace))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get buffer size for region reference"); + if (FAIL == H5Q__view_append(view, H5R_EXT_REGION, ref)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append region reference to view"); + + if (dataspace) H5S_close(dataspace); + if ((obj_id != FAIL) && (FAIL == H5I_dec_app_ref(obj_id))) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object") + H5Rdestroy(refs[i]); + } else { + H5R_type_t ref_type = H5R_get_type(refs[i]); + // printf_ref(idx_refs[i]); + *result |= (ref_type == H5R_EXT_ATTR) ? H5Q_REF_ATTR : H5Q_REF_OBJ; + if (FAIL == H5Q__view_append(view, ref_type, refs[i])) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + } + } + H5MM_free(refs); + + + /* Get data part of query */ + } else { + H5Q_view_t view1 = H5Q_VIEW_INITIALIZER(view1), view2 = H5Q_VIEW_INITIALIZER(view2); + unsigned result1 = 0, result2 = 0; + + if (FAIL == H5Q__apply_index(loc_id, query->query.combine.l_query, &view1, &result1)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query"); + if (FAIL == H5Q__apply_index(loc_id, query->query.combine.r_query, &view2, &result2)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query"); + + if (FAIL == H5Q__view_combine(op_type, &view1, &view2, result1, result2, + view, result)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTMERGE, FAIL, "unable to merge results"); + + if (result1) H5Q__view_free(&view1); + if (result2) H5Q__view_free(&view2); + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5Q__apply_index() */ + +/*------------------------------------------------------------------------- * Function: H5Q__apply_iterate * * Purpose: Private function for H5Q_apply. diff --git a/src/H5X.c b/src/H5X.c index f35e22f..18ec4cf 100644 --- a/src/H5X.c +++ b/src/H5X.c @@ -46,6 +46,11 @@ /* Local Prototypes */ /********************/ +static herr_t H5X_create_data(hid_t loc_id, H5X_class_t *idx_class, + hid_t xcpl_id, hid_t xapl_id); +static herr_t H5X_create_metadata(hid_t loc_id, H5X_class_t *idx_class, + hid_t xcpl_id, hid_t xapl_id); + /*********************/ /* Package Variables */ /*********************/ @@ -134,6 +139,8 @@ H5X__init_package(void) if (H5X_register(H5X_FASTBIT) < 0) HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register FastBit index plugin"); #endif + if (H5X_register(H5X_META_DUMMY) < 0) + HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register meta dummy index plugin"); done: FUNC_LEAVE_NOAPI(ret_value) @@ -380,7 +387,7 @@ done: } /* end H5X_unregister() */ /*------------------------------------------------------------------------- - * Function: H5X_can_create + * Function: H5X_can_create_data * * Purpose: * @@ -389,7 +396,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5X_can_create(hid_t dset_id, hid_t dcpl_id) +H5X_can_create_data(hid_t dset_id, hid_t dcpl_id) { hid_t xcpl_id = H5P_DEFAULT; herr_t ret_value = SUCCEED; /* Return value */ @@ -439,9 +446,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Xcreate(hid_t scope_id, unsigned plugin_id, hid_t xcpl_id) +H5Xcreate(hid_t loc_id, unsigned plugin_id, hid_t xcpl_id) { - H5D_t *dset = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -450,10 +456,10 @@ H5Xcreate(hid_t scope_id, unsigned plugin_id, hid_t xcpl_id) /* Check args */ if (plugin_id > H5X_PLUGIN_MAX) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid plugin identification number"); - if (NULL == (dset = (H5D_t *) H5I_object_verify(scope_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + if (FAIL == loc_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid loc ID"); - if (FAIL == H5X_create(scope_id, plugin_id, xcpl_id)) + if (FAIL == H5X_create(loc_id, plugin_id, xcpl_id)) HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "cannot create index"); done: @@ -470,21 +476,16 @@ done: *------------------------------------------------------------------------- */ herr_t -H5X_create(hid_t dset_id, unsigned plugin_id, hid_t xcpl_id) +H5X_create(hid_t loc_id, unsigned plugin_id, hid_t xcpl_id) { H5X_class_t *idx_class = NULL; - void *idx_handle = NULL; /* pointer to index object created */ - H5D_t *dset = NULL; hid_t xapl_id = H5P_INDEX_ACCESS_DEFAULT; /* TODO for now */ - size_t metadata_size; /* size of metadata created by plugin */ - void *metadata; /* metadata created by plugin that needs to be stored */ - H5O_idxinfo_t idx_info; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check args */ - HDassert(dset_id != FAIL); + HDassert(loc_id != FAIL); HDassert(plugin_id <= H5X_PLUGIN_MAX); /* Is the plugin already registered */ @@ -498,27 +499,114 @@ H5X_create(hid_t dset_id, unsigned plugin_id, hid_t xcpl_id) if (TRUE != H5P_isa_class(xcpl_id, H5P_INDEX_CREATE)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not index creation property list"); + if (idx_class->type == H5X_TYPE_DATA) { + if (FAIL == H5X_create_data(loc_id, idx_class, xcpl_id, xapl_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "cannot create data index"); + } + else if (idx_class->type == H5X_TYPE_METADATA) { + if (FAIL == H5X_create_metadata(loc_id, idx_class, xcpl_id, xapl_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "cannot create metadata index"); + } else + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "invalid index type"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_create() */ + +/*------------------------------------------------------------------------- + * Function: H5X_create_data + * + * Purpose: Create a new index in a container. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X_create_data(hid_t loc_id, H5X_class_t *idx_class, hid_t xcpl_id, + hid_t xapl_id) +{ + H5D_t *dset = NULL; + void *idx_handle = NULL; /* Pointer to index object created */ + size_t metadata_size; /* Size of metadata created by plugin */ + void *metadata; /* Metadata created by plugin that needs to be stored */ + H5O_idxinfo_t idx_info; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(idx_class); + HDassert(idx_class->type == H5X_TYPE_DATA); + /* Get dset object */ - if (NULL == (dset = (H5D_t *) H5I_object_verify(dset_id, H5I_DATASET))) + if (NULL == (dset = (H5D_t *) H5I_object_verify(loc_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); /* Call create of the plugin */ if (NULL == idx_class->idx_class.data_class.create) HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin create callback is not defined"); - if (NULL == (idx_handle = idx_class->idx_class.data_class.create(dset_id, xcpl_id, xapl_id, + if (NULL == (idx_handle = idx_class->idx_class.data_class.create(loc_id, xcpl_id, xapl_id, &metadata_size, &metadata))) HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "cannot create new plugin index"); /* Add idx_handle to dataset */ - idx_info.plugin_id = plugin_id; + idx_info.plugin_id = idx_class->id; idx_info.metadata_size = metadata_size; idx_info.metadata = metadata; - if (FAIL == H5D_set_index(dset, 1, &idx_class, &idx_handle, &idx_info)) + if (FAIL == H5D_set_index(dset, idx_class, idx_handle, &idx_info)) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "cannot set index"); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5X_create() */ +} /* end H5X_create_data() */ + +/*------------------------------------------------------------------------- + * Function: H5X_create_metadata + * + * Purpose: Create a new index in a container. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X_create_metadata(hid_t loc_id, H5X_class_t *idx_class, hid_t xcpl_id, + hid_t xapl_id) +{ + H5F_t *file = NULL; + void *idx_handle = NULL; /* Pointer to index object created */ + size_t metadata_size; /* Size of metadata created by plugin */ + void *metadata = NULL; /* Metadata created by plugin that needs to be stored */ + H5O_idxinfo_t idx_info; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(idx_class); + HDassert(idx_class->type == H5X_TYPE_METADATA); + + /* Get file object */ + if (NULL == (file = (H5F_t *) H5I_object_verify(loc_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + + /* Call create of the plugin */ + if (NULL == idx_class->idx_class.metadata_class.create) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin create callback is not defined"); + if (NULL == (idx_handle = idx_class->idx_class.metadata_class.create(loc_id, xcpl_id, xapl_id, + &metadata_size, &metadata))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "cannot create new plugin index"); + + /* Add idx_handle to dataset */ + idx_info.plugin_id = idx_class->id; + idx_info.metadata_size = metadata_size; + idx_info.metadata = metadata; + if (FAIL == H5F_set_index(file, idx_class, idx_handle, &idx_info)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "cannot set index"); + +done: + H5MM_free(metadata); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_create_metadata() */ /*------------------------------------------------------------------------- * Function: H5Xremove @@ -530,7 +618,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Xremove(hid_t scope_id, unsigned plugin_id) +H5Xremove(hid_t loc_id, unsigned plugin_id) { herr_t ret_value = SUCCEED; /* Return value */ @@ -540,11 +628,11 @@ H5Xremove(hid_t scope_id, unsigned plugin_id) /* Check args */ if (plugin_id > H5X_PLUGIN_MAX) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid plugin identification number"); - if (NULL == H5I_object_verify(scope_id, H5I_DATASET)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (FAIL == loc_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") /* Remove index from dataset */ - if (FAIL == H5X_remove(scope_id, plugin_id)) + if (FAIL == H5X_remove(loc_id, plugin_id)) HGOTO_ERROR(H5E_INDEX, H5E_CANTDELETE, FAIL, "unable to delete index") done: @@ -561,23 +649,45 @@ done: *------------------------------------------------------------------------- */ herr_t -H5X_remove(hid_t dset_id, unsigned plugin_id) +H5X_remove(hid_t loc_id, unsigned plugin_id) { - H5D_t *dset = NULL; + H5I_type_t loc_type; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check args */ - HDassert(dset_id != FAIL); + HDassert(loc_id != FAIL); HDassert(plugin_id <= H5X_PLUGIN_MAX); - if (NULL == (dset = (H5D_t *) H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (H5I_BADID == (loc_type = H5I_get_type(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid type") - /* Remove idx_handle from dataset */ - if (FAIL == H5D_remove_index(dset, plugin_id)) - HGOTO_ERROR(H5E_INDEX, H5E_CANTDELETE, FAIL, "unable to delete index") + switch (loc_type) { + case H5I_FILE: + { + H5F_t *file = NULL; + + if (NULL == (file = (H5F_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") + if (FAIL == H5F_remove_index(file, plugin_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTDELETE, FAIL, "unable to delete index") + } + break; + case H5I_DATASET: + { + H5D_t *dset = NULL; + + if (NULL == (dset = (H5D_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (FAIL == H5D_remove_index(dset, plugin_id)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTDELETE, FAIL, "unable to delete index") + } + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a supported type"); + break; + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -593,19 +703,19 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Xget_count(hid_t scope_id, hsize_t *idx_count) +H5Xget_count(hid_t loc_id, hsize_t *idx_count) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*h", scope_id, idx_count); - if (NULL == H5I_object_verify(scope_id, H5I_DATASET)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (FAIL == loc_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") if (!idx_count) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "idx_count is NULL"); - if (FAIL == H5X_get_count(scope_id, idx_count)) + if (FAIL == H5X_get_count(loc_id, idx_count)) HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "cannot get index count"); done: @@ -622,24 +732,47 @@ done: *------------------------------------------------------------------------- */ herr_t -H5X_get_count(hid_t dset_id, hsize_t *idx_count) +H5X_get_count(hid_t loc_id, hsize_t *idx_count) { - H5D_t *dset = NULL; - unsigned actual_count; + H5I_type_t loc_type; + H5X_class_t *idx_class = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT - HDassert(dset_id != H5I_BADID); + HDassert(loc_id != H5I_BADID); HDassert(idx_count); - if (NULL == (dset = (H5D_t *) H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (H5I_BADID == (loc_type = H5I_get_type(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid type") - if (FAIL == H5D_get_index(dset, 1, NULL, NULL, NULL, &actual_count)) - HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + switch (loc_type) { + case H5I_FILE: + { + H5F_t *file = NULL; + + if (NULL == (file = (H5F_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") + if (FAIL == H5F_get_index(file, &idx_class, NULL, NULL)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + } + break; + case H5I_DATASET: + { + H5D_t *dset = NULL; + + if (NULL == (dset = (H5D_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (FAIL == H5D_get_index(dset, &idx_class, NULL, NULL)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + } + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a supported type"); + break; + } - *idx_count = actual_count; + *idx_count = (idx_class) ? 1 : 0; done: FUNC_LEAVE_NOAPI(ret_value) @@ -655,17 +788,16 @@ done: *------------------------------------------------------------------------- */ hsize_t -H5Xget_size(hid_t scope_id) +H5Xget_size(hid_t loc_id) { hsize_t ret_value = 0; /* Return value */ FUNC_ENTER_API(0) H5TRACE1("h", "i", scope_id); - if (NULL == H5I_object_verify(scope_id, H5I_DATASET)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataset") - - if (FAIL == H5X_get_size(scope_id, &ret_value)) + if (FAIL == loc_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a location") + if (FAIL == H5X_get_size(loc_id, &ret_value)) HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, 0, "cannot get index storage size"); done: @@ -682,22 +814,45 @@ done: *------------------------------------------------------------------------- */ herr_t -H5X_get_size(hid_t dset_id, hsize_t *idx_size) +H5X_get_size(hid_t loc_id, hsize_t *idx_size) { - H5D_t *dset = NULL; + H5I_type_t loc_type; hsize_t actual_size = 0; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT - HDassert(dset_id != H5I_BADID); + HDassert(loc_id != H5I_BADID); HDassert(idx_size); - if (NULL == (dset = (H5D_t *) H5I_object_verify(dset_id, H5I_DATASET))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (H5I_BADID == (loc_type = H5I_get_type(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid type") - if (FAIL == H5D_get_index_size(dset, &actual_size)) - HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + switch (loc_type) { + case H5I_FILE: + { + H5F_t *file = NULL; + + if (NULL == (file = (H5F_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") + if (FAIL == H5F_get_index_size(file, &actual_size)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + } + break; + case H5I_DATASET: + { + H5D_t *dset = NULL; + + if (NULL == (dset = (H5D_t *) H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + if (FAIL == H5D_get_index_size(dset, &actual_size)) + HGOTO_ERROR(H5E_INDEX, H5E_BADVALUE, FAIL, "plugin is not registered"); + } + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a supported type"); + break; + } *idx_size = actual_size; diff --git a/src/H5Xmeta_dummy.c b/src/H5Xmeta_dummy.c new file mode 100644 index 0000000..5235522 --- /dev/null +++ b/src/H5Xmeta_dummy.c @@ -0,0 +1,1439 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Dummy index routines. + */ + +/****************/ +/* Module Setup */ +/****************/ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Xprivate.h" /* Index */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" +#include "H5Qprivate.h" +#include "H5Sprivate.h" +/* TODO using private headers but could use public ones */ + +//#define H5Q_FRIEND +//#include "H5Qpkg.h" /* To re-use H5Q_QUEUE */ + +#define H5R_FRIEND +#include "H5Rpkg.h" /* (Tmp) To re-use H5R__get_obj_name */ + +/****************/ +/* Local Macros */ +/****************/ +//#define H5X_DUMMY_DEBUG + +#ifdef H5X_DUMMY_DEBUG +#define H5X_DUMMY_LOG_DEBUG(...) do { \ + fprintf(stdout, " # %s(): ", __func__); \ + fprintf(stdout, __VA_ARGS__); \ + fprintf(stdout, "\n"); \ + fflush(stdout); \ + } while (0) +#else +#define H5X_DUMMY_LOG_DEBUG(...) do { \ + } while (0) +#endif + +/* + * Singly-linked Tail queue declarations. (from sys/queue.h) + */ +#define H5Q_QUEUE_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ + size_t n_elem; /* number of elements */ \ +} + +#define H5Q_QUEUE_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first, 0 } + +#define H5Q_QUEUE_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define H5Q_QUEUE_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ + (head)->n_elem = 0; \ +} while (/*CONSTCOND*/0) + +#define H5Q_QUEUE_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ + (head)->n_elem++; \ +} while (/*CONSTCOND*/0) + +#define H5Q_QUEUE_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->n_elem++; \ +} while (/*CONSTCOND*/0) + +#define H5Q_QUEUE_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) { \ + (head)->stqh_last = &(head)->stqh_first; \ + (head)->n_elem--; \ + } \ +} while (/*CONSTCOND*/0) + +#define H5Q_QUEUE_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + H5Q_QUEUE_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (curelm->field.stqe_next != (elm)) \ + curelm = curelm->field.stqe_next; \ + if ((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + (head)->n_elem--; \ + } \ +} while (/*CONSTCOND*/0) + +#define H5Q_QUEUE_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +#define H5Q_QUEUE_CONCAT(head1, head2) do { \ + if (!H5Q_QUEUE_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + (head1)->n_elem += (head2)->n_elem; \ + H5Q_QUEUE_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +/* + * Singly-linked Tail queue access methods. + */ +#define H5Q_QUEUE_EMPTY(head) ((head)->stqh_first == NULL) +#define H5Q_QUEUE_FIRST(head) ((head)->stqh_first) +#define H5Q_QUEUE_NEXT(elm, field) ((elm)->field.stqe_next) + +#define H5X_DUMMY_METADATA_TYPES 3 +#define H5X_DUMMY_MAX_NAME_LEN (64 * 1024) + +/******************/ +/* Local Typedefs */ +/******************/ + +typedef struct { + hid_t type; + void *value; +} H5X_dummy_elem_t; + +typedef struct H5X_dummy_entry_t H5X_dummy_entry_t; + +struct H5X_dummy_entry_t { + H5Q_type_t type; /* Query type */ + union { /* Key */ + H5X_dummy_elem_t elem; + char *name; + } key; + href_t ref; /* External reference */ + H5Q_QUEUE_ENTRY(H5X_dummy_entry_t) entry; +}; + +typedef H5Q_QUEUE_HEAD(H5X_dummy_head_t, H5X_dummy_entry_t) H5X_dummy_head_t; + +typedef struct { + H5X_dummy_head_t attr_values; + H5X_dummy_head_t attr_names; + H5X_dummy_head_t link_names; +} H5X_dummy_metadata_t; + +typedef struct { + const char *filename; + const char *loc_name; + H5X_dummy_metadata_t *metadata; +} H5X_dummy_index_attr_arg_t; + +typedef struct { + H5X_dummy_index_attr_arg_t *attr_args; + const char *attr_name; +} H5X_dummy_index_attr_elem_arg_t; + +typedef struct H5X_dummy_t { +// hid_t dataset_id; +// hid_t idx_anon_id; +// void *idx_token; +// size_t idx_token_size; + H5X_dummy_metadata_t metadata; +} H5X_dummy_t; + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5X__dummy_index(hid_t oid, const char *name, const H5O_info_t *oinfo, + void *udata); +static herr_t H5X__dummy_index_link_name(H5X_dummy_metadata_t *metadata, hid_t loc_id, + const char *name, const H5O_info_t *oinfo); +static herr_t H5X__dummy_index_attrs(H5X_dummy_metadata_t *metadata, hid_t loc_id, + const char *name); +static herr_t H5X__dummy_index_attr(hid_t loc_id, const char *attr_name, + const H5A_info_t H5_ATTR_UNUSED *ainfo, void *udata); +static herr_t H5X__dummy_index_attr_name(const char *attr_name, void *udata); +static herr_t H5X__dummy_index_attr_value(hid_t loc_id, const char *attr_name, + void *udata); +static herr_t H5X__dummy_index_attr_value_iterate(void *elem, hid_t type_id, + unsigned ndim, const hsize_t *point, void *udata); +static herr_t H5X__dummy_metadata_add(H5X_dummy_metadata_t *metadata, + href_t ref, H5Q_type_t type, ...); +static herr_t H5X__dummy_metadata_free(H5X_dummy_metadata_t *metadata); +static herr_t H5X__dummy_metadata_add_entry(H5X_dummy_head_t *head, + H5X_dummy_entry_t *entry); +static herr_t H5X__dummy_metadata_remove_entries(H5X_dummy_head_t *head); +static herr_t H5X__dummy_metadata_write(H5X_dummy_metadata_t *metadata, + hid_t loc_id, size_t *plugin_metadata_size, void **plugin_metadata); +static herr_t H5X__dummy_metadata_read(hid_t loc_id, + size_t plugin_metadata_size, void *plugin_metadata, + H5X_dummy_metadata_t *metadata); +static herr_t H5X__dummy_serialize_metadata(hid_t dset_ids[], void *buf, + size_t *buf_size); +static herr_t H5X__dummy_deserialize_metadata(hid_t file_id, void *buf, + size_t buf_size, hid_t *dset_ids[]); +static herr_t H5X__dummy_index_rebuild(H5X_dummy_metadata_t *metadata, + void *bufs[], size_t nelmts[], hid_t type_ids[]); +static herr_t H5X__dummy_metadata_query(H5X_dummy_metadata_t *metadata, + hid_t query_id, H5X_dummy_head_t *result); +static herr_t H5X__dummy_metadata_query_singleton(H5X_dummy_metadata_t *metadata, + hid_t query_id, H5X_dummy_head_t *result); +static herr_t H5X__dummy_metadata_query_combine(H5Q_combine_op_t combine_op, + H5X_dummy_head_t *result1, H5X_dummy_head_t *result2, + H5X_dummy_head_t *result); + +static void *H5X__dummy_create(hid_t loc_id, hid_t xcpl_id, hid_t xapl_id, + size_t *metadata_size, void **metadata); +static herr_t H5X__dummy_remove(hid_t loc_id, size_t metadata_size, + void *metadata); +static void *H5X__dummy_open(hid_t loc_id, hid_t xapl_id, size_t + metadata_size, void *metadata); +static herr_t H5X__dummy_close(void *idx_handle); +static herr_t H5X__dummy_insert_entry(void *idx_handle, hid_t obj_id, + H5Q_type_t key_type, H5Q_elem_t *key, hid_t xxpl_id); +static herr_t H5X__dummy_remove_entry(void *idx_handle, hid_t obj_id, + H5Q_type_t key_type, H5Q_elem_t *key, hid_t xxpl_id); +static herr_t H5X__dummy_query(void *idx_handle, hid_t query_id, hid_t xxpl_id, + size_t *ref_count, href_t *refs[]); + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Dummy index class */ +const H5X_class_t H5X_META_DUMMY[1] = {{ + H5X_CLASS_T_VERS, /* (From the H5Xpublic.h header file) */ + H5X_PLUGIN_META_DUMMY, /* (Or whatever number is assigned) */ + "dummy index plugin", /* Whatever name desired */ + H5X_TYPE_METADATA, /* This plugin operates on metadata */ + {{ + H5X__dummy_create, /* create */ + H5X__dummy_remove, /* remove */ + H5X__dummy_open, /* open */ + H5X__dummy_close, /* close */ + H5X__dummy_insert_entry, /* insert_entry */ + H5X__dummy_remove_entry, /* remove_entry */ + H5X__dummy_query, /* query */ + NULL /* get_size */ + }} +}}; + +static void +printf_ref(href_t ref) +{ + char obj_name[H5X_DUMMY_MAX_NAME_LEN]; + + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, ref, obj_name, H5X_DUMMY_MAX_NAME_LEN); + if (H5Rget_type(ref) == H5R_EXT_ATTR) { + char attr_name[H5X_DUMMY_MAX_NAME_LEN]; + H5R__get_attr_name(NULL, ref, attr_name, H5X_DUMMY_MAX_NAME_LEN); + H5X_DUMMY_LOG_DEBUG("Attribute reference: %s, %s", obj_name, attr_name); + } else { + H5X_DUMMY_LOG_DEBUG("Object reference: %s", obj_name); + } +} + +static herr_t +H5X__dummy_index(hid_t oid, const char *name, const H5O_info_t *oinfo, + void *udata) +{ + H5X_dummy_metadata_t *metadata = (H5X_dummy_metadata_t *) udata; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(name); + HDassert(oinfo); + HDassert(metadata); + + /* Index link names */ + if (FAIL == H5X__dummy_index_link_name(metadata, oid, name, oinfo)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTAPPEND, FAIL, "can't add link name"); + + /* Index attribute names/values */ + if (FAIL == H5X__dummy_index_attrs(metadata, oid, name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't apply data query to object"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index */ + +static herr_t +H5X__dummy_index_link_name(H5X_dummy_metadata_t *metadata, hid_t loc_id, + const char *name, const H5O_info_t *oinfo) +{ + href_t ref; + const char *link_name = NULL; + const char *trimmed_path = NULL; + char file_name[H5X_DUMMY_MAX_NAME_LEN]; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(metadata); + HDassert(name); + HDassert(oinfo); + + trimmed_path = HDstrrchr(name, '/'); + link_name = (trimmed_path) ? ++trimmed_path : name; + + if ((oinfo->type != H5O_TYPE_GROUP) && (oinfo->type != H5O_TYPE_DATASET)) + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized object type"); + + /* Get file name */ + if (H5Fget_name(loc_id, file_name, H5X_DUMMY_MAX_NAME_LEN) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file name"); + + /* Keep object reference */ + if (NULL == (ref = H5R_create_ext_object(file_name, name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create object reference"); + if (FAIL == H5X__dummy_metadata_add(metadata, ref, H5Q_TYPE_LINK_NAME, link_name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_link_name */ + +static herr_t +H5X__dummy_index_attrs(H5X_dummy_metadata_t *metadata, hid_t loc_id, + const char *name) +{ + H5X_dummy_index_attr_arg_t attr_args; + hid_t obj_id = FAIL; + char file_name[H5X_DUMMY_MAX_NAME_LEN]; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(metadata); + HDassert(name); + + /* Get file name */ + if (H5Fget_name(loc_id, file_name, H5X_DUMMY_MAX_NAME_LEN) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file name"); + + /* Build attribute operator info */ + attr_args.filename = file_name; + attr_args.loc_name = name; + attr_args.metadata = metadata; + + if (0 == HDstrcmp(name, ".")) { + obj_id = loc_id; + } else { + if (FAIL == (obj_id = H5Oopen(loc_id, name, H5P_DEFAULT))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't open object"); + } + + /* Iterate over attributes */ + if (FAIL == (ret_value = H5Aiterate(obj_id, H5_INDEX_NAME, H5_ITER_NATIVE, + NULL, H5X__dummy_index_attr, &attr_args))) + HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes"); + +done: + if ((obj_id != FAIL) && (obj_id != loc_id) && (FAIL == H5Oclose(obj_id))) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_attrs */ + +static herr_t +H5X__dummy_index_attr(hid_t loc_id, const char *attr_name, + const H5A_info_t H5_ATTR_UNUSED *ainfo, void *udata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(attr_name); + HDassert(udata); + + if (FAIL == H5X__dummy_index_attr_name(attr_name, udata)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't apply attr name query to object"); + + if (FAIL == H5X__dummy_index_attr_value(loc_id, attr_name, udata)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't apply attr name query to object"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_attr */ + +static herr_t +H5X__dummy_index_attr_name(const char *attr_name, void *udata) +{ + H5X_dummy_index_attr_arg_t *args = (H5X_dummy_index_attr_arg_t *) udata; + href_t ref; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(attr_name); + HDassert(args); + + /* Keep attribute reference */ + if (NULL == (ref = H5R_create_ext_attr(args->filename, args->loc_name, attr_name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get buffer size for attribute reference"); + if (FAIL == H5X__dummy_metadata_add(args->metadata, ref, H5Q_TYPE_ATTR_NAME, attr_name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_attr_name */ + +static herr_t +H5X__dummy_index_attr_value(hid_t loc_id, const char *attr_name, void *udata) +{ + H5X_dummy_index_attr_arg_t *args = (H5X_dummy_index_attr_arg_t *) udata; + void *buf = NULL; + size_t buf_size; + hid_t attr_id = FAIL; + hid_t type_id = FAIL; + hid_t space_id = FAIL; + size_t nelmts, elmt_size; + H5X_dummy_index_attr_elem_arg_t iter_args; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(attr_name); + HDassert(args); + + /* Open attribute */ + if (FAIL == (attr_id = H5Aopen(loc_id, attr_name, H5P_DEFAULT))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute"); + + /* Get attribute info */ + if (FAIL == (type_id = H5Aget_type(attr_id))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get attribute datatype"); + if (FAIL == (space_id = H5Aget_space(attr_id))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get attribute dataspace"); + if (0 == (nelmts = (size_t) H5Sget_select_npoints(space_id))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid number of elements"); + if (0 == (elmt_size = H5Tget_size(type_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid size of element"); + + /* Allocate buffer to hold data */ + buf_size = nelmts * elmt_size; + if (NULL == (buf = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_QUERY, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* Read data */ + if (FAIL == H5Aread(attr_id, type_id, buf)) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute"); + + iter_args.attr_args = args; + iter_args.attr_name = attr_name; + + /* Iterate over attribute elements to compare values */ + if (FAIL == H5Diterate(buf, type_id, space_id, H5X__dummy_index_attr_value_iterate, &iter_args)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "unable to compare attribute elements"); + +done: + H5MM_free(buf); + if (attr_id != FAIL) H5Aclose(attr_id); + if (type_id != FAIL) H5Tclose(type_id); + if (space_id != FAIL) H5Sclose(space_id); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_attr_value */ + +static herr_t +H5X__dummy_index_attr_value_iterate(void *elem, hid_t type_id, + unsigned H5_ATTR_UNUSED ndim, const hsize_t H5_ATTR_UNUSED *point, void *udata) +{ + H5X_dummy_index_attr_elem_arg_t *args = (H5X_dummy_index_attr_elem_arg_t *) udata; + href_t ref; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(elem); + HDassert(args); + + /* Keep attribute reference */ + if (NULL == (ref = H5R_create_ext_attr(args->attr_args->filename, args->attr_args->loc_name, args->attr_name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get buffer size for attribute reference"); + if (FAIL == H5X__dummy_metadata_add(args->attr_args->metadata, ref, H5Q_TYPE_ATTR_VALUE, type_id, elem)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_index_attr_value_iterate */ + +static herr_t +H5X__dummy_metadata_add(H5X_dummy_metadata_t *metadata, href_t ref, H5Q_type_t type, ...) +{ + va_list ap; + H5X_dummy_entry_t *entry; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(metadata); + HDassert(ref); + + va_start(ap, type); + + if (NULL == (entry = (H5X_dummy_entry_t *) H5MM_malloc(sizeof(H5X_dummy_entry_t)))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, FAIL, "can't allocate ref entry"); + entry->ref = ref; + entry->type = type; + + switch (type) { + case H5Q_TYPE_ATTR_VALUE: + { + hid_t datatype_id; + size_t datatype_size; + const void *value; + + /* Get arguments */ + datatype_id = va_arg(ap, hid_t); + value = va_arg(ap, const void *); + + HDassert(datatype_id != FAIL); + HDassert(value); + + if (FAIL == (entry->key.elem.type = H5Tget_native_type(datatype_id, H5T_DIR_DEFAULT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy attribute type"); + if (0 == (datatype_size = H5Tget_size(entry->key.elem.type))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid size"); + if (NULL == (entry->key.elem.value = H5MM_malloc(datatype_size))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, FAIL, "can't allocate value buffer"); + HDmemcpy(entry->key.elem.value, value, datatype_size); + H5Q_QUEUE_INSERT_TAIL(&metadata->attr_values, entry, entry); + } + break; + case H5Q_TYPE_ATTR_NAME: + { + const char *attr_name; + + /* Get arguments */ + attr_name = va_arg(ap, const char *); + + HDassert(attr_name); + + entry->key.name = H5MM_strdup(attr_name); + H5Q_QUEUE_INSERT_TAIL(&metadata->attr_names, entry, entry); + } + break; + case H5Q_TYPE_LINK_NAME: + { + const char *link_name; + + /* Get arguments */ + link_name = va_arg(ap, const char *); + + HDassert(link_name); + + entry->key.name = H5MM_strdup(link_name); + H5Q_QUEUE_INSERT_TAIL(&metadata->link_names, entry, entry); + } + break; + case H5Q_TYPE_MISC: + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type"); + break; + } + +done: + va_end(ap); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_add */ + +static herr_t +H5X__dummy_metadata_free(H5X_dummy_metadata_t *metadata) +{ + H5X_dummy_head_t *entries[H5X_DUMMY_METADATA_TYPES] = { &metadata->attr_names, + &metadata->attr_values, &metadata->link_names }; + herr_t ret_value = SUCCEED; /* Return value */ + int i; + + FUNC_ENTER_NOAPI_NOINIT + + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + while (!H5Q_QUEUE_EMPTY(entries[i])) { + H5X_dummy_entry_t *entry = H5Q_QUEUE_FIRST(entries[i]); + H5Q_QUEUE_REMOVE_HEAD(entries[i], entry); + + if (FAIL == H5Rdestroy(entry->ref)) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy reference"); + switch (entry->type) { + case H5Q_TYPE_ATTR_VALUE: + if (FAIL == H5Tclose(entry->key.elem.type)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); + entry->key.elem.value = H5MM_xfree(entry->key.elem.value); + break; + case H5Q_TYPE_ATTR_NAME: + case H5Q_TYPE_LINK_NAME: + entry->key.name = H5MM_xfree(entry->key.name); + break; + case H5Q_TYPE_MISC: + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type"); + break; + } + H5MM_free(entry); + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_free */ + +static herr_t +H5X__dummy_metadata_add_entry(H5X_dummy_head_t *head, H5X_dummy_entry_t *entry) +{ + H5X_dummy_entry_t *new_entry; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(head); + HDassert(entry); + + if (NULL == (new_entry = (H5X_dummy_entry_t *) H5MM_malloc(sizeof(H5X_dummy_entry_t)))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, FAIL, "can't allocate ref entry"); + HDmemcpy(new_entry, entry, sizeof(H5X_dummy_entry_t)); + H5Q_QUEUE_INSERT_TAIL(head, new_entry, entry); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_add_entry */ + +static herr_t +H5X__dummy_metadata_remove_entries(H5X_dummy_head_t *head) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(head); + + while (!H5Q_QUEUE_EMPTY(head)) { + H5X_dummy_entry_t *entry = H5Q_QUEUE_FIRST(head); + H5Q_QUEUE_REMOVE_HEAD(head, entry); + H5MM_free(entry); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_remove_entries */ + +static herr_t +H5X__dummy_metadata_write(H5X_dummy_metadata_t *metadata, hid_t file_id, + size_t *plugin_metadata_size, void **plugin_metadata) +{ + hid_t dset_ids[H5X_DUMMY_METADATA_TYPES] = {FAIL, FAIL, FAIL}; + hid_t mem_space_id = FAIL; + hid_t space_id = FAIL; + H5X_dummy_head_t *entries[H5X_DUMMY_METADATA_TYPES] = { &metadata->attr_names, + &metadata->attr_values, &metadata->link_names }; + hid_t type_ids[H5X_DUMMY_METADATA_TYPES] = { H5T_STD_REF_EXT_ATTR, + FAIL, H5T_STD_REF_EXT_OBJ }; + herr_t ret_value = SUCCEED; /* Return value */ + int i; + + FUNC_ENTER_NOAPI_NOINIT + + /* Iterate over reference types and write references if any */ + /* We only need to store attribute/object references and attribute values */ + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + H5X_dummy_entry_t *entry = NULL; + hsize_t n_elem = entries[i]->n_elem; + hsize_t start = 0; + + if (!n_elem) + continue; + + /* Create dataspace */ + if (FAIL == (space_id = H5Screate_simple(1, &n_elem, NULL))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + + /* Create the new dataset & get its ID */ + if (H5Q_QUEUE_FIRST(entries[i])->type == H5Q_TYPE_ATTR_VALUE) + type_ids[i] = H5Q_QUEUE_FIRST(entries[i])->key.elem.type; + if (FAIL == (dset_ids[i] = H5Dcreate_anon(file_id, type_ids[i], + space_id, H5P_DEFAULT, H5P_DEFAULT))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCREATE, FAIL, "can't create anonymous dataset"); + + /* Increment refcount so that anonymous dataset is persistent */ + if (FAIL == H5Oincr_refcount(dset_ids[i])) + HGOTO_ERROR(H5E_INDEX, H5E_CANTINC, FAIL, "can't increment dataset refcount"); + + /* Iterate over reference entries in view */ + H5Q_QUEUE_FOREACH(entry, entries[i], entry) { + hsize_t count = 1; + const void *buf = (entry->type == H5Q_TYPE_ATTR_VALUE) ? entry->key.elem.value : &entry->ref; + + if (FAIL == (mem_space_id = H5Screate_simple(1, &count, NULL))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + if (FAIL == H5Sselect_hyperslab(space_id, H5S_SELECT_SET, &start, NULL, &count, NULL)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") + if (FAIL == H5Dwrite(dset_ids[i], type_ids[i], mem_space_id, + space_id, H5P_DEFAULT, buf)) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write dataset"); + if (FAIL == H5Sclose(mem_space_id)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataspace"); + mem_space_id = FAIL; + + /* Increment reference position in file */ + start++; + } + if (FAIL == H5Sclose(space_id)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataspace"); + space_id = FAIL; + } + + /* Serialize metadata */ + if (FAIL == H5X__dummy_serialize_metadata(dset_ids, NULL, plugin_metadata_size)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get plugin metadata size"); + if (NULL == (*plugin_metadata = H5MM_malloc(*plugin_metadata_size))) + HGOTO_ERROR(H5E_INDEX, H5E_NOSPACE, FAIL, "can't allocate plugin metadata"); + if (FAIL == H5X__dummy_serialize_metadata(dset_ids, *plugin_metadata, plugin_metadata_size)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTENCODE, FAIL, "can't serialize plugin metadata"); + + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + if (FAIL == H5Dclose(dset_ids[i])) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataset"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_write */ + + +static herr_t +H5X__dummy_metadata_read(hid_t file_id, size_t plugin_metadata_size, + void *plugin_metadata, H5X_dummy_metadata_t *metadata) +{ + hid_t *dset_ids; + herr_t ret_value = SUCCEED; /* Return value */ + void *bufs[H5X_DUMMY_METADATA_TYPES]; + size_t nelmts[H5X_DUMMY_METADATA_TYPES]; + hid_t type_ids[H5X_DUMMY_METADATA_TYPES]; + int i; + + FUNC_ENTER_NOAPI_NOINIT + + /* Deserialize metadata and get anon dataset IDs */ + if (FAIL == H5X__dummy_deserialize_metadata(file_id, plugin_metadata, plugin_metadata_size, + &dset_ids)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTDECODE, FAIL, "can't deserialize plugin metadata"); + + /* Iterate over metadata index types */ + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + hid_t type_id = FAIL, space_id = FAIL; + size_t elmt_size; + + if (FAIL == (type_id = H5Dget_type(dset_ids[i]))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get datatype"); + if (FAIL == (space_id = H5Dget_space(dset_ids[i]))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get datatype"); + if (0 == (nelmts[i] = (size_t) H5Sget_select_npoints(space_id))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid number of elements"); + if (0 == (elmt_size = H5Tget_size(type_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid size of element"); + + /* Allocate buffer to hold data */ + if (NULL == (bufs[i] = H5MM_malloc(nelmts[i] * elmt_size))) + HGOTO_ERROR(H5E_INDEX, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* Read data from dataset */ + if (FAIL == H5Dread(dset_ids[i], type_id, H5S_ALL, space_id, + H5P_DEFAULT, bufs[i])) + HGOTO_ERROR(H5E_INDEX, H5E_READERROR, FAIL, "can't read index data"); + + if (FAIL == H5Sclose(space_id)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataspace"); + } + + /* Rebuild metadata index */ + if (FAIL == H5X__dummy_index_rebuild(metadata, bufs, nelmts, type_ids)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTINIT, FAIL, "unable to rebuild metadata index"); + + /* Close anon datasets */ + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + H5MM_free(bufs[i]); + if (FAIL == H5Tclose(type_ids[i])) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close datatype"); + if (FAIL == H5Dclose(dset_ids[i])) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to close dataset"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_read */ + +static herr_t +H5X__dummy_serialize_metadata(hid_t dset_ids[], void *buf, size_t *buf_size) +{ + uint8_t *p = buf; + size_t metadata_size = 3 * sizeof(haddr_t); + int i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + /* Encode metadata token info */ + if (p) { + H5O_info_t dset_info; + + /* Get addr info for dataset */ + if (FAIL == H5Oget_info(dset_ids[i], &dset_info)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get dataset info"); + + /* TODO use H5F_addr_encode instead */ + HDmemcpy(p, &dset_info.addr, sizeof(haddr_t)); + p += sizeof(haddr_t); + } + } + + if (buf_size) *buf_size = metadata_size; + + done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_serialize_metadata */ + +static herr_t +H5X__dummy_deserialize_metadata(hid_t file_id, void *buf, size_t buf_size, + hid_t *dset_ids[]) +{ + uint8_t *p = buf; + int i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(buf); + HDassert(buf_size); + HDassert(dset_ids); + + for (i = 0; i < H5X_DUMMY_METADATA_TYPES; i++) { + /* Decode index token info */ + if (FAIL == (*dset_ids[i] = H5Oopen_by_addr(file_id, *((haddr_t *) p)))) + HGOTO_ERROR(H5E_INDEX, H5E_CANTOPENOBJ, FAIL, "can't open anonymous dataset"); + p += sizeof(haddr_t); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5X__dummy_deserialize_metadata */ + +static herr_t +H5X__dummy_index_rebuild(H5X_dummy_metadata_t *metadata, void *bufs[], + size_t nelmts[], hid_t type_ids[]) +{ +// H5X_dummy_head_t *entries[H5X_DUMMY_METADATA_TYPES] = { &metadata->attr_names, +// &metadata->attr_values, &metadata->link_names }; +// href_t *link_refs; +// href_t *attr_refs; +// void **attr_values; +// hid_t attr_native_id; +// int i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(metadata); + HDassert(bufs); + HDassert(nelmts); + HDassert(type_ids); + +// attr_refs = bufs[0]; +// attr_values = bufs[1]; +// link_refs = bufs[2]; +// attr_native_id = H5Tget_native_type(type_ids[1], H5T_DIR_DEFAULT); +// +// for (i = 0; i < nelmts[0]; i++) { +// href_t ref; +// char attr_name[H5X_DUMMY_MAX_NAME_LEN]; +// char filename[H5X_DUMMY_MAX_NAME_LEN]; +// char pathname[H5X_DUMMY_MAX_NAME_LEN]; +// +// H5R__get_attr_name(NULL, attr_refs[i], attr_name, H5X_DUMMY_MAX_NAME_LEN); +// H5R__get_obj_name(NULL, attr_refs[i], pathname, H5X_DUMMY_MAX_NAME_LEN); +// H5Rget_file_name(attr_refs[i], attr_name, H5X_DUMMY_MAX_NAME_LEN); +// ref = H5R_create_ext_attr(filename, pathname, attr_name); +// if (FAIL == H5X__dummy_metadata_add(metadata, attr_refs[i], H5Q_TYPE_ATTR_NAME, attr_name)) +// HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); +// } + +//done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5X__dummy_index_rebuild */ + +/*------------------------------------------------------------------------- + * Function: H5X_dummy_create + * + * Purpose: This function creates a new instance of a dummy plugin index. + * + * Return: Success: Pointer to the new index + * Failure: NULL + * + *------------------------------------------------------------------------ + */ +static void * +H5X__dummy_create(hid_t loc_id, hid_t H5_ATTR_UNUSED xcpl_id, + hid_t H5_ATTR_UNUSED xapl_id, size_t *metadata_size, void **metadata) +{ + H5X_dummy_t *dummy = NULL; + hid_t file_id; + void *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + H5X_DUMMY_LOG_DEBUG("Calling H5X_dummy_create"); + + /* Create new dummy instance */ + if (NULL == (dummy = (H5X_dummy_t *) H5MM_malloc(sizeof(H5X_dummy_t)))) + HGOTO_ERROR(H5E_INDEX, H5E_NOSPACE, NULL, "can't allocate dummy struct"); + H5Q_QUEUE_INIT(&dummy->metadata.attr_names); + H5Q_QUEUE_INIT(&dummy->metadata.attr_values); + H5Q_QUEUE_INIT(&dummy->metadata.link_names); + + /* Get file ID */ + file_id = loc_id; /* TODO for now */ + + /* Visit file */ + if (FAIL == H5Ovisit(loc_id, H5_INDEX_NAME, H5_ITER_NATIVE, H5X__dummy_index, + &dummy->metadata)) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, NULL, "object visitation failed"); + + H5X_DUMMY_LOG_DEBUG("###########################"); + if (!H5Q_QUEUE_EMPTY(&dummy->metadata.attr_names)) + H5X_DUMMY_LOG_DEBUG("Indexed %zu attributes names", dummy->metadata.attr_names.n_elem); + if (!H5Q_QUEUE_EMPTY(&dummy->metadata.attr_values)) + H5X_DUMMY_LOG_DEBUG("Indexed %zu attributes values", dummy->metadata.attr_values.n_elem); + if (!H5Q_QUEUE_EMPTY(&dummy->metadata.link_names)) + H5X_DUMMY_LOG_DEBUG("Indexed %zu link names", dummy->metadata.link_names.n_elem); + H5X_dummy_entry_t *entry; + H5Q_QUEUE_FOREACH(entry, &dummy->metadata.attr_names, entry) { + H5X_DUMMY_LOG_DEBUG("Indexed attribute name: %s", (const char *) entry->key.name); + } + H5Q_QUEUE_FOREACH(entry, &dummy->metadata.attr_values, entry) { + H5X_DUMMY_LOG_DEBUG("Indexed attribute value: %d", *((int *) entry->key.elem.value)); + } + H5Q_QUEUE_FOREACH(entry, &dummy->metadata.link_names, entry) { + H5X_DUMMY_LOG_DEBUG("Indexed link name: %s", (const char *) entry->key.name); + } + H5X_DUMMY_LOG_DEBUG("###########################"); + + /* Write index metadata */ + if (FAIL == H5X__dummy_metadata_write(&dummy->metadata, file_id, metadata_size, metadata)) + HGOTO_ERROR(H5E_INDEX, H5E_WRITEERROR, NULL, "can't write metadata"); + + ret_value = dummy; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_dummy_create() */ + +/*------------------------------------------------------------------------- + * Function: H5X_dummy_remove + * + * Purpose: This function removes the dummy plugin index from the file. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X__dummy_remove(hid_t H5_ATTR_UNUSED file_id, size_t H5_ATTR_UNUSED metadata_size, + void H5_ATTR_UNUSED *metadata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + H5X_DUMMY_LOG_DEBUG("Calling H5X_dummy_remove"); + + /* TODO Does not do anything */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_dummy_remove() */ + +/*------------------------------------------------------------------------- + * Function: H5X_dummy_open + * + * Purpose: This function opens an already existing dummy index from a file. + * + * Return: Success: Pointer to the index + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static void * +H5X__dummy_open(hid_t loc_id, hid_t H5_ATTR_UNUSED xapl_id, size_t metadata_size, + void *metadata) +{ + hid_t file_id; + H5X_dummy_t *dummy = NULL; + void *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + H5X_DUMMY_LOG_DEBUG("Calling H5X_dummy_open"); + + if (!metadata_size) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL metadata size"); + if (!metadata) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL metadata"); + + if (NULL == (dummy = (H5X_dummy_t *) H5MM_malloc(sizeof(H5X_dummy_t)))) + HGOTO_ERROR(H5E_INDEX, H5E_NOSPACE, NULL, "can't allocate dummy struct"); + + /* Get file ID */ + file_id = loc_id; /* TODO for now */ + + if (FAIL == H5X__dummy_metadata_read(file_id, metadata_size, metadata, + &dummy->metadata)) + HGOTO_ERROR(H5E_INDEX, H5E_READERROR, NULL, "can't read metadata"); + + ret_value = dummy; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_dummy_open() */ + +/*------------------------------------------------------------------------- + * Function: H5X_dummy_close + * + * Purpose: This function closes a dummy index. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X__dummy_close(void *idx_handle) +{ + H5X_dummy_t *dummy = (H5X_dummy_t *) idx_handle; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + H5X_DUMMY_LOG_DEBUG("Calling H5X_dummy_close"); + + if (NULL == dummy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL index handle"); + + /* Free metadata */ + if (FAIL == H5X__dummy_metadata_free(&dummy->metadata)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTFREE, FAIL, "cannot free metadata"); + + H5MM_free(dummy); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_dummy_close() */ + +/*------------------------------------------------------------------------- + * Function: H5X__dummy_insert_entry + * + * Purpose: This function insert a new entry in the dummy plugin index. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X__dummy_insert_entry(void *idx_handle, hid_t obj_id, H5Q_type_t key_type, + H5Q_elem_t *key, hid_t H5_ATTR_UNUSED xxpl_id) +{ + H5X_dummy_t *dummy = (H5X_dummy_t *) idx_handle; + char file_name[H5X_DUMMY_MAX_NAME_LEN]; + char loc_name[H5X_DUMMY_MAX_NAME_LEN]; + href_t ref; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + H5X_DUMMY_LOG_DEBUG("Calling H5X__dummy_insert_entry"); + + if (NULL == dummy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL index handle"); + + if (H5Fget_name(obj_id, file_name, H5X_DUMMY_MAX_NAME_LEN) < 0) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get file name"); + if (H5Iget_name(obj_id, loc_name, H5X_DUMMY_MAX_NAME_LEN) < 0) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get location name"); + + switch (key_type) { + case H5Q_TYPE_ATTR_VALUE: + { + char attr_name[H5X_DUMMY_MAX_NAME_LEN]; + + if (H5Aget_name(obj_id, H5X_DUMMY_MAX_NAME_LEN, attr_name) < 0) + HGOTO_ERROR(H5E_INDEX, H5E_CANTGET, FAIL, "can't get attribute name"); + + /* Keep attribute reference */ + if (NULL == (ref = H5R_create_ext_attr(file_name, loc_name, attr_name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get buffer size for attribute reference"); + if (FAIL == H5X__dummy_metadata_add(&dummy->metadata, ref, H5Q_TYPE_ATTR_VALUE, key->value.type, key->value.value)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + } + break; + case H5Q_TYPE_ATTR_NAME: + { + /* Keep attribute reference */ + if (NULL == (ref = H5R_create_ext_attr(file_name, loc_name, key->name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get buffer size for attribute reference"); + if (FAIL == H5X__dummy_metadata_add(&dummy->metadata, ref, H5Q_TYPE_ATTR_NAME, key->name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + } + break; + case H5Q_TYPE_LINK_NAME: + { + /* Keep object reference */ + if (NULL == (ref = H5R_create_ext_object(file_name, loc_name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create object reference"); + if (FAIL == H5X__dummy_metadata_add(&dummy->metadata, ref, H5Q_TYPE_LINK_NAME, key->name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTAPPEND, FAIL, "can't append object reference to view"); + } + break; + case H5Q_TYPE_MISC: + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type"); + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_insert_entry() */ + +/*------------------------------------------------------------------------- + * Function: H5X__dummy_remove_entry + * + * Purpose: This function removes an entry from the dummy plugin index. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X__dummy_remove_entry(void H5_ATTR_UNUSED *idx_handle, hid_t H5_ATTR_UNUSED obj_id, + H5Q_type_t H5_ATTR_UNUSED key_type, H5Q_elem_t H5_ATTR_UNUSED *key, + hid_t H5_ATTR_UNUSED xxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + H5X_DUMMY_LOG_DEBUG("Calling H5X__dummy_remove_entry"); + + /* TODO Does not do anything */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_insert_entry() */ + +/*------------------------------------------------------------------------- + * Function: H5X_dummy_query + * + * Purpose: This function queries a dummy index. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5X__dummy_query(void *idx_handle, hid_t query_id, hid_t H5_ATTR_UNUSED xxpl_id, + size_t *ref_count, href_t *refs[]) +{ + H5X_dummy_t *dummy = (H5X_dummy_t *) idx_handle; + H5X_dummy_head_t query_result = H5Q_QUEUE_HEAD_INITIALIZER(query_result); + href_t *ref_buf = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + H5X_DUMMY_LOG_DEBUG("Calling H5X_dummy_query"); + + if (NULL == dummy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL index handle"); + + /* We assume here that the queries passed only operate on metadata */ + if (FAIL == H5X__dummy_metadata_query(&dummy->metadata, query_id, &query_result)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTCOMPARE, FAIL, "can't query metadata"); + +// H5X_DUMMY_LOG_DEBUG("###########################"); +// if (!H5Q_QUEUE_EMPTY(&query_result)) { +// H5X_dummy_entry_t *entry; +// H5X_DUMMY_LOG_DEBUG("Query returns %zu references", query_result.n_elem); +// H5Q_QUEUE_FOREACH(entry, &query_result, entry) +// printf_ref(entry->ref); +// } +// H5X_DUMMY_LOG_DEBUG("###########################"); + + /* Fill result */ + if (!H5Q_QUEUE_EMPTY(&query_result)) { + H5X_dummy_entry_t *entry; + int i = 0; + + if (NULL == (ref_buf = H5MM_malloc(sizeof(href_t) * query_result.n_elem))) + HGOTO_ERROR(H5E_QUERY, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + H5Q_QUEUE_FOREACH(entry, &query_result, entry) { + ref_buf[i] = H5Rcopy(entry->ref); + i++; + } + } + + *ref_count = query_result.n_elem; + *refs = ref_buf; + +done: + if (FAIL == H5X__dummy_metadata_remove_entries(&query_result)) + HDONE_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to remove entries"); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X_dummy_query() */ + +static herr_t +H5X__dummy_metadata_query(H5X_dummy_metadata_t *metadata, hid_t query_id, + H5X_dummy_head_t *result) +{ + H5Q_type_t query_type; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if (FAIL == H5Qget_type(query_id, &query_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get query type"); + + if (query_type != H5Q_TYPE_MISC) { + if (FAIL == H5X__dummy_metadata_query_singleton(metadata, query_id, result)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to compare query"); + } else { + H5Q_combine_op_t combine_op; + hid_t sub_query1_id, sub_query2_id; + H5X_dummy_head_t result1 = H5Q_QUEUE_HEAD_INITIALIZER(result1); + H5X_dummy_head_t result2 = H5Q_QUEUE_HEAD_INITIALIZER(result2); + + if (FAIL == H5Qget_combine_op(query_id, &combine_op)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get combine op"); + if (FAIL == H5Qget_components(query_id, &sub_query1_id, &sub_query2_id)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get components"); + + if (FAIL == H5X__dummy_metadata_query(metadata, sub_query1_id, &result1)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query"); + +// H5X_DUMMY_LOG_DEBUG("###########################"); +// if (!H5Q_QUEUE_EMPTY(&result1)) { +// H5X_dummy_entry_t *entry; +// H5X_DUMMY_LOG_DEBUG("Query returns %zu references", result1.n_elem); +// H5Q_QUEUE_FOREACH(entry, &result1, entry) +// printf_ref(entry->ref); +// } +// H5X_DUMMY_LOG_DEBUG("###########################"); + + if (FAIL == H5X__dummy_metadata_query(metadata, sub_query2_id, &result2)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query"); + +// H5X_DUMMY_LOG_DEBUG("###########################"); +// if (!H5Q_QUEUE_EMPTY(&result2)) { +// H5X_dummy_entry_t *entry; +// H5X_DUMMY_LOG_DEBUG("Query returns %zu references", result2.n_elem); +// H5Q_QUEUE_FOREACH(entry, &result2, entry) +// printf_ref(entry->ref); +// } +// H5X_DUMMY_LOG_DEBUG("###########################"); + + if (FAIL == H5X__dummy_metadata_query_combine(combine_op, &result1, &result2, result)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTMERGE, FAIL, "unable to merge results"); + +// H5X_DUMMY_LOG_DEBUG("###########################"); +// if (!H5Q_QUEUE_EMPTY(result)) { +// H5X_dummy_entry_t *entry; +// H5X_DUMMY_LOG_DEBUG("Query returns %zu references", result->n_elem); +// H5Q_QUEUE_FOREACH(entry, result, entry) +// printf_ref(entry->ref); +// } +// H5X_DUMMY_LOG_DEBUG("###########################"); + + if (FAIL == H5X__dummy_metadata_remove_entries(&result1)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to remove entries"); + if (FAIL == H5X__dummy_metadata_remove_entries(&result2)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to remove entries"); + if (FAIL == H5Qclose(sub_query1_id)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCLOSEOBJ, FAIL, "unable to close query"); + if (FAIL == H5Qclose(sub_query2_id)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCLOSEOBJ, FAIL, "unable to close query"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_query */ + +static herr_t +H5X__dummy_metadata_query_singleton(H5X_dummy_metadata_t *metadata, + hid_t query_id, H5X_dummy_head_t *result) +{ + H5X_dummy_entry_t *entry; + H5Q_type_t query_type; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if (FAIL == H5Qget_type(query_id, &query_type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTGET, FAIL, "unable to get query type"); + switch (query_type) { + case H5Q_TYPE_LINK_NAME: + H5Q_QUEUE_FOREACH(entry, &metadata->link_names, entry) { + hbool_t apply_result = FALSE; + if (FAIL == H5Qapply_atom(query_id, &apply_result, entry->key.name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't compare link name"); + if (!apply_result) continue; + +// H5X_DUMMY_LOG_DEBUG("Match link name: %s", (const char *) entry->key.name); + if (FAIL == H5X__dummy_metadata_add_entry(result, entry)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + break; + case H5Q_TYPE_ATTR_NAME: + H5Q_QUEUE_FOREACH(entry, &metadata->attr_names, entry) { + hbool_t apply_result = FALSE; + if (FAIL == H5Qapply_atom(query_id, &apply_result, entry->key.name)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't compare attribute name"); + if (!apply_result) continue; + +// H5X_DUMMY_LOG_DEBUG("Match attribute name: %s", (const char *) entry->key.name); + if (FAIL == H5X__dummy_metadata_add_entry(result, entry)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + break; + case H5Q_TYPE_ATTR_VALUE: + H5Q_QUEUE_FOREACH(entry, &metadata->attr_values, entry) { + hbool_t apply_result = FALSE; + if (FAIL == H5Qapply_atom(query_id, &apply_result, entry->key.elem.type, entry->key.elem.value)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "can't compare attribute values"); + if (!apply_result) continue; + +// H5X_DUMMY_LOG_DEBUG("Match attribute value: %d", *((int *) entry->key.elem.value)); + if (FAIL == H5X__dummy_metadata_add_entry(result, entry)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + break; + case H5Q_TYPE_DATA_ELEM: + case H5Q_TYPE_MISC: + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type"); + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_query_singleton */ + +static herr_t +H5X__dummy_metadata_query_combine(H5Q_combine_op_t combine_op, + H5X_dummy_head_t *result1, H5X_dummy_head_t *result2, H5X_dummy_head_t *result) +{ + H5X_dummy_entry_t *entry1; + H5X_dummy_entry_t *entry2; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if (combine_op == H5Q_COMBINE_AND) { + H5Q_QUEUE_FOREACH(entry1, result1, entry) { + H5R_type_t ref_type1 = H5Rget_type(entry1->ref); + H5Q_QUEUE_FOREACH(entry2, result2, entry) { + H5R_type_t ref_type2 = H5Rget_type(entry2->ref); + + if (H5Requal(entry1->ref, entry2->ref)) { + if (FAIL == H5X__dummy_metadata_add_entry(result, entry1)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + else if (ref_type1 == H5R_EXT_ATTR && ref_type2 == H5R_EXT_OBJECT) { + char obj_name1[H5X_DUMMY_MAX_NAME_LEN]; + char obj_name2[H5X_DUMMY_MAX_NAME_LEN]; + + /* Only combine if obj_names are equal */ + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, entry1->ref, + obj_name1, H5X_DUMMY_MAX_NAME_LEN); + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, entry2->ref, + obj_name2, H5X_DUMMY_MAX_NAME_LEN); + if (0 == HDstrcmp(obj_name1, obj_name2)) + if (FAIL == H5X__dummy_metadata_add_entry(result, entry2)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + else if (ref_type1 == H5R_EXT_OBJECT && ref_type2 == H5R_EXT_ATTR) { + char obj_name1[H5X_DUMMY_MAX_NAME_LEN]; + char obj_name2[H5X_DUMMY_MAX_NAME_LEN]; + + /* Only combine if obj_names are equal */ + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, entry1->ref, + obj_name1, H5X_DUMMY_MAX_NAME_LEN); + H5R__get_obj_name(NULL, H5P_DEFAULT, H5P_DEFAULT, entry2->ref, + obj_name2, H5X_DUMMY_MAX_NAME_LEN); + if (0 == HDstrcmp(obj_name1, obj_name2)) + if (FAIL == H5X__dummy_metadata_add_entry(result, entry1)) + HGOTO_ERROR(H5E_INDEX, H5E_CANTMERGE, FAIL, "unable to add result"); + } + } + } + } else if (combine_op == H5Q_COMBINE_OR) { + /* TODO might want to remove eventual duplicates */ + H5Q_QUEUE_CONCAT(result, result1); + H5Q_QUEUE_CONCAT(result, result2); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5X__dummy_metadata_query_combine */ diff --git a/src/H5Xpkg.h b/src/H5Xpkg.h index d647e6f..7cb9bf5 100644 --- a/src/H5Xpkg.h +++ b/src/H5Xpkg.h @@ -41,4 +41,9 @@ H5_DLLVAR const H5X_class_t H5X_ALACRITY[1]; H5_DLLVAR const H5X_class_t H5X_FASTBIT[1]; #endif +/* + * Dummy plugin meta + */ +H5_DLLVAR const H5X_class_t H5X_META_DUMMY[1]; + #endif /* _H5Xpkg_H */ diff --git a/src/H5Xprivate.h b/src/H5Xprivate.h index ad8966d..598ef6d 100644 --- a/src/H5Xprivate.h +++ b/src/H5Xprivate.h @@ -53,12 +53,12 @@ H5_DLL H5X_class_t *H5X_registered(unsigned plugin_id); H5_DLL herr_t H5X_register(const H5X_class_t *index_plugin); H5_DLL herr_t H5X_unregister(unsigned plugin_id); -H5_DLL herr_t H5X_create(hid_t dset_id, unsigned plugin_id, hid_t xcpl_id); -H5_DLL herr_t H5X_remove(hid_t dset_id, unsigned plugin_id); -H5_DLL herr_t H5X_can_create(hid_t dset_id, hid_t dcpl_id); +H5_DLL herr_t H5X_create(hid_t loc_id, unsigned plugin_id, hid_t xcpl_id); +H5_DLL herr_t H5X_remove(hid_t loc_id, unsigned plugin_id); +H5_DLL herr_t H5X_can_create_data(hid_t dset_id, hid_t dcpl_id); -H5_DLL herr_t H5X_get_count(hid_t dset_id, hsize_t *idx_count); +H5_DLL herr_t H5X_get_count(hid_t loc_id, hsize_t *idx_count); -H5_DLL herr_t H5X_get_size(hid_t dset_id, hsize_t *idx_size); +H5_DLL herr_t H5X_get_size(hid_t loc_id, hsize_t *idx_size); #endif /* _H5Xprivate_H */ diff --git a/src/H5Xpublic.h b/src/H5Xpublic.h index 28dad66..0636b05 100644 --- a/src/H5Xpublic.h +++ b/src/H5Xpublic.h @@ -32,16 +32,18 @@ #define H5X_CLASS_T_VERS (1) /* Plugin IDs */ -#define H5X_PLUGIN_ERROR (-1) /* no plugin */ -#define H5X_PLUGIN_NONE 0 /* reserved indefinitely */ -#define H5X_PLUGIN_DUMMY 1 /* dummy */ -#define H5X_PLUGIN_FASTBIT 2 /* fastbit */ -#define H5X_PLUGIN_ALACRITY 3 /* alacrity */ +#define H5X_PLUGIN_ERROR (-1) /* no plugin */ +#define H5X_PLUGIN_NONE 0 /* reserved indefinitely */ +#define H5X_PLUGIN_DUMMY 1 /* dummy */ +#define H5X_PLUGIN_FASTBIT 2 /* fastbit */ +#define H5X_PLUGIN_ALACRITY 3 /* alacrity */ -#define H5X_PLUGIN_RESERVED 64 /* plugin ids below this value reserved */ +#define H5X_PLUGIN_META_DUMMY 4 /* metadata dummy */ -#define H5X_PLUGIN_MAX 256 /* maximum plugin id */ -#define H5X_MAX_NPLUGINS 16 /* Maximum number of plugins allowed in a pipeline */ +#define H5X_PLUGIN_RESERVED 64 /* plugin ids below this value reserved */ + +#define H5X_PLUGIN_MAX 256 /* maximum plugin id */ +#define H5X_MAX_NPLUGINS 16 /* Maximum number of plugins allowed in a pipeline */ /*******************/ /* Public Typedefs */ diff --git a/test/index.c b/test/index.c index 3703c21..def99fb 100644 --- a/test/index.c +++ b/test/index.c @@ -28,6 +28,7 @@ const char *FILENAME[] = { #define DATASETNAME2 "dataset2" #define NTUPLES 256 +#define NLOOP 5 static herr_t write_dataset(hid_t file, const char *dataset_name, hsize_t ntuples, @@ -209,6 +210,8 @@ test_query(hid_t file_id, const char *dataset_name) float query_lb = 39.1f, query_ub = 42.6f; hid_t query = H5I_BADID, query1 = H5I_BADID, query2 = H5I_BADID; struct timeval t1, t2; + struct timeval t_total = {0, 0}; + int i; TESTING("index query"); @@ -228,37 +231,39 @@ test_query(hid_t file_id, const char *dataset_name) dataset = H5Dopen(file_id, dataset_name, H5P_DEFAULT); if (dataset < 0) FAIL_STACK_ERROR; - gettimeofday(&t1, NULL); - - if ((space = H5Dquery(dataset, H5S_ALL, query, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + for (i = 0; i < NLOOP; i++) { + HDgettimeofday(&t1, NULL); + if ((space = H5Dquery(dataset, H5S_ALL, query, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + HDgettimeofday(&t2, NULL); + + /* Bounds should be 40 and 42 */ + H5Sget_select_bounds(space, start_coord, end_coord); + + /* + { + hsize_t nelmts; + nelmts = (hsize_t) H5Sget_select_npoints(space); + printf("\n Created dataspace with %llu elements," + " bounds = [(%llu, %llu):(%llu, %llu)]\n", + nelmts, start_coord[0], start_coord[1], end_coord[0], end_coord[1]); + } + */ - gettimeofday(&t2, NULL); + if (start_coord[0] != 40) FAIL_STACK_ERROR; + // if (start_coord[1] != 0) FAIL_STACK_ERROR; + if (end_coord[0] != 42) FAIL_STACK_ERROR; + // if (end_coord[1] != 2) FAIL_STACK_ERROR; - /* Bounds should be 40 and 42 */ - H5Sget_select_bounds(space, start_coord, end_coord); + t_total.tv_sec += (t2.tv_sec - t1.tv_sec); + t_total.tv_usec += (t2.tv_usec - t1.tv_usec); - /* - { - hsize_t nelmts; - nelmts = (hsize_t) H5Sget_select_npoints(space); - printf("\n Created dataspace with %llu elements," - " bounds = [(%llu, %llu):(%llu, %llu)]\n", - nelmts, start_coord[0], start_coord[1], end_coord[0], end_coord[1]); + if (H5Sclose(space) < 0) FAIL_STACK_ERROR; } - */ - if (start_coord[0] != 40) FAIL_STACK_ERROR; - if (start_coord[1] != 0) FAIL_STACK_ERROR; - if (end_coord[0] != 42) FAIL_STACK_ERROR; - if (end_coord[1] != 2) FAIL_STACK_ERROR; + printf("Index query time: %lf ms\n", + ((float) t_total.tv_sec) * 1000.0f / NLOOP + + ((float) t_total.tv_usec) / (NLOOP * 1000.0f)); - /* - printf("\n Index query time: %lf ms\n", - ((float) (t2.tv_sec - t1.tv_sec)) * 1000.0f - + ((float) (t2.tv_usec - t1.tv_usec)) / 1000.0f); - */ - - if (H5Sclose(space) < 0) FAIL_STACK_ERROR; if (H5Dclose(dataset) < 0) FAIL_STACK_ERROR; if (H5Qclose(query) < 0) FAIL_STACK_ERROR; if (H5Qclose(query2) < 0) FAIL_STACK_ERROR; @@ -309,26 +314,21 @@ error: int main(int argc, char **argv) { - unsigned plugin; + unsigned plugin = H5X_PLUGIN_DUMMY; char filename[1024]; /* file name */ hsize_t ntuples = NTUPLES; - hsize_t ntuples_multiplier = 1; - hsize_t ncomponents = 3; + hsize_t ncomponents = 1; float *data; hid_t file = H5I_BADID, fapl = H5I_BADID; hsize_t i, j; // int incr_update; - if (argc < 2) { - printf("Usage: %s \n", argv[0]); - exit(0); + if (argc > 2) { + ntuples = (hsize_t) atoi(argv[1]); + plugin = (unsigned) atoi(argv[2]); + // incr_update = atoi(argv[3]); } - ntuples_multiplier = (hsize_t) atoi(argv[1]); - ntuples *= ntuples_multiplier; - plugin = (unsigned) atoi(argv[2]); -// incr_update = atoi(argv[3]); - /* Initialize the data. */ data = (float *) HDmalloc(sizeof(float) * ncomponents * ntuples); for (i = 0; i < ntuples; i++) { diff --git a/test/query.c b/test/query.c index 8bc4ddb..c75c2ec 100644 --- a/test/query.c +++ b/test/query.c @@ -25,6 +25,8 @@ const char *FILENAME[] = { "query1", "query2", "query3", + "query_meta_dummy", + "query_fastbit_meta_dummy", NULL }; @@ -32,6 +34,7 @@ const char *FILENAME[] = { #define NCOMPONENTS 1 #define MAX_NAME 64 #define MULTI_NFILES 3 +#define NLOOP 5 /* Create query */ static hid_t @@ -104,17 +107,17 @@ test_query_create_type(H5R_type_t type) /* Combine queries */ if (type == H5R_REGION) { - printf("Query ((17 < x < 22) AND (link='Pressure') AND (attr='SensorID') AND (attr=2)\n"); + printf("Query-> (17 < x < 22) AND ((link='Pressure') AND ((attr='SensorID') AND (attr=2)))\n"); if ((q8 = H5Qcombine(q6, H5Q_COMBINE_AND, q7)) < 0) FAIL_STACK_ERROR; if ((q9 = H5Qcombine(q3, H5Q_COMBINE_AND, q8)) < 0) FAIL_STACK_ERROR; } else if (type == H5R_OBJECT) { - printf("Query (link='Pressure') AND (attr='SensorID') AND (attr=2)\n"); + printf("Query-> (link='Pressure') AND (attr='SensorID') AND (attr=2)\n"); if ((q8 = H5Qcombine(q6, H5Q_COMBINE_AND, q7)) < 0) FAIL_STACK_ERROR; q9 = q8; } else if (type == H5R_ATTR) { - printf("Query (attr='SensorID') AND (attr=2)\n"); + printf("Query-> (attr='SensorID') AND (attr=2)\n"); q9 = q6; } @@ -289,7 +292,113 @@ error: /* Create file for view */ static herr_t -test_query_create_simple_file(const char *filename, hid_t fapl, unsigned idx_plugin) +test_query_create_simple_file2(const char *filename, hid_t fapl, unsigned n_objs, + unsigned meta_idx_plugin, unsigned data_idx_plugin) +{ + hid_t file = H5I_BADID; + hid_t aspace = H5I_BADID, dspace = H5I_BADID; + hid_t dcpl = H5P_DEFAULT; + hsize_t adim[1] = {1}; + hsize_t dims[2] = {NTUPLES, NCOMPONENTS}; + int rank = (NCOMPONENTS == 1) ? 1 : 2; + float *data = NULL; + unsigned int i, j, n; + + (void)meta_idx_plugin; /* TODO not used for now */ + + /* Initialize the data. */ + data = (float *) HDmalloc(sizeof(float) * NCOMPONENTS * NTUPLES); + for (i = 0; i < NTUPLES; i++) { + for (j = 0; j < NCOMPONENTS; j++) { + data[NCOMPONENTS * i + j] = (float) i; + } + } + + if ((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR; + + /* Create dataspace for datasets */ + if ((dspace = H5Screate_simple(rank, dims, NULL)) < 0) FAIL_STACK_ERROR; + if ((aspace = H5Screate_simple(1, adim, NULL)) < 0) FAIL_STACK_ERROR; + + if (data_idx_plugin && ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)) FAIL_STACK_ERROR; + if (data_idx_plugin && (H5Pset_index_plugin(dcpl, data_idx_plugin)) < 0) FAIL_STACK_ERROR; + + for (n = 1; n <= n_objs; n++) { + hid_t obj = H5I_BADID; + hid_t pres = H5I_BADID; + hid_t temp = H5I_BADID; + hid_t id_pres = H5I_BADID; + hid_t id_temp = H5I_BADID; + char obj_name[MAX_NAME]; + + printf("Writing object %d...\r", n); + + /* Create simple group and dataset */ + HDmemset(obj_name, '\0', MAX_NAME); + sprintf(obj_name, "Object%d", n); + if ((obj = H5Gcreate(file, obj_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR; + + /* Create some datasets and use index if told to */ + if ((pres = H5Dcreate(obj, "Pressure", H5T_NATIVE_FLOAT, dspace, H5P_DEFAULT, + dcpl, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + if ((temp = H5Dcreate(obj, "Temperature", H5T_NATIVE_FLOAT, dspace, H5P_DEFAULT, + dcpl, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + + /* Add attributes to datasets */ + if ((id_pres = H5Acreate(pres, "SensorID", H5T_NATIVE_INT, aspace, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR; + if ((id_temp = H5Acreate(temp, "SensorID", H5T_NATIVE_INT, aspace, H5P_DEFAULT, H5P_DEFAULT)) < 0) + FAIL_STACK_ERROR; + + if (H5Awrite(id_pres, H5T_NATIVE_INT, &n) < 0) FAIL_STACK_ERROR; + if (H5Awrite(id_temp, H5T_NATIVE_INT, &n) < 0) FAIL_STACK_ERROR; + + if (H5Aclose(id_pres) < 0) FAIL_STACK_ERROR; + if (H5Aclose(id_temp) < 0) FAIL_STACK_ERROR; + + /* Write data */ + if (H5Dwrite(pres, H5T_NATIVE_FLOAT, H5S_ALL, dspace, H5P_DEFAULT, data) < 0) + FAIL_STACK_ERROR; + if (H5Dwrite(temp, H5T_NATIVE_FLOAT, H5S_ALL, dspace, H5P_DEFAULT, data) < 0) + FAIL_STACK_ERROR; + + if (H5Dclose(pres) < 0) FAIL_STACK_ERROR; + if (H5Dclose(temp) < 0) FAIL_STACK_ERROR; + + if (H5Gclose(obj) < 0) FAIL_STACK_ERROR; + } + printf("\n Done \n"); + + if (data_idx_plugin && (H5Pclose(dcpl) < 0)) FAIL_STACK_ERROR; + + /* Close dataspaces */ + if (H5Sclose(aspace) < 0) FAIL_STACK_ERROR; + if (H5Sclose(dspace) < 0) FAIL_STACK_ERROR; + + /* Close file */ + if (H5Fclose(file) < 0) FAIL_STACK_ERROR; + + HDfree(data); + + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(dcpl); + H5Sclose(dspace); + H5Sclose(aspace); + H5Fclose(file); + HDfree(data); + } H5E_END_TRY; + return -1; +} + +/* Create file for view */ +static herr_t +test_query_create_simple_file(const char *filename, hid_t fapl, + unsigned meta_idx_plugin, unsigned data_idx_plugin) { hid_t file = H5I_BADID, obj1 = H5I_BADID, obj2 = H5I_BADID, obj3 = H5I_BADID; hid_t pres1 = H5I_BADID, pres2 = H5I_BADID, pres3 = H5I_BADID; @@ -328,8 +437,8 @@ test_query_create_simple_file(const char *filename, hid_t fapl, unsigned idx_plu if ((dspace = H5Screate_simple(rank, dims, NULL)) < 0) FAIL_STACK_ERROR; /* Create some datasets and use index if told to */ - if (idx_plugin && ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)) FAIL_STACK_ERROR; - if (idx_plugin && (H5Pset_index_plugin(dcpl, idx_plugin)) < 0) FAIL_STACK_ERROR; + if (data_idx_plugin && ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)) FAIL_STACK_ERROR; + if (data_idx_plugin && (H5Pset_index_plugin(dcpl, data_idx_plugin)) < 0) FAIL_STACK_ERROR; if ((pres1 = H5Dcreate(obj1, "Pressure", H5T_NATIVE_FLOAT, dspace, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; if ((temp1 = H5Dcreate(obj1, "Temperature", H5T_NATIVE_FLOAT, dspace, H5P_DEFAULT, @@ -342,7 +451,7 @@ test_query_create_simple_file(const char *filename, hid_t fapl, unsigned idx_plu dcpl, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; if ((temp3 = H5Dcreate(obj3, "Temperature", H5T_NATIVE_FLOAT, dspace, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; - if (idx_plugin && (H5Pclose(dcpl) < 0)) FAIL_STACK_ERROR; + if (data_idx_plugin && (H5Pclose(dcpl) < 0)) FAIL_STACK_ERROR; /* Add attributes to datasets */ if ((aspace = H5Screate_simple(1, adim, NULL)) < 0) FAIL_STACK_ERROR; @@ -460,7 +569,7 @@ test_query_read_selection(size_t file_count, const char *filenames[], if (0 == (n_refs = (size_t) H5Sget_select_npoints(ref_space))) FAIL_STACK_ERROR; printf("Found %zu reference(s)\n", n_refs); if (0 == (ref_size = H5Tget_size(ref_type))) FAIL_STACK_ERROR; - printf("Reference type size: %zu\n", ref_size); +// printf("Reference type size: %zu\n", ref_size); /* Allocate buffer to hold data */ ref_buf_size = n_refs * ref_size; @@ -559,22 +668,32 @@ error: } static herr_t -test_query_apply_view(const char *filename, hid_t fapl, unsigned idx_plugin) +test_query_apply_view(const char *filename, hid_t fapl, unsigned n_objs, + unsigned meta_idx_plugin, unsigned data_idx_plugin) { hid_t file = H5I_BADID; hid_t view = H5I_BADID; hid_t query = H5I_BADID; struct timeval t1, t2; + struct timeval t_total = {0, 0}; unsigned result = 0; + int i; printf(" ...\n---\n"); /* Create a simple file for testing queries */ printf("Creating test file \"%s\"\n", filename); - if ((test_query_create_simple_file(filename, fapl, idx_plugin)) < 0) FAIL_STACK_ERROR; + if ((test_query_create_simple_file2(filename, fapl, n_objs, meta_idx_plugin, + data_idx_plugin)) < 0) FAIL_STACK_ERROR; /* Open the file in read-only */ - if ((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) FAIL_STACK_ERROR; + if (meta_idx_plugin == H5X_PLUGIN_META_DUMMY) { + if ((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR; + /* Create metadata index */ + if (H5Xcreate(file, meta_idx_plugin, H5P_DEFAULT) < 0) FAIL_STACK_ERROR; + } else { + if ((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) FAIL_STACK_ERROR; + } printf("\nRegion query\n"); printf( "------------\n"); @@ -582,15 +701,21 @@ test_query_apply_view(const char *filename, hid_t fapl, unsigned idx_plugin) /* Test region query */ if ((query = test_query_create_type(H5R_REGION)) < 0) FAIL_STACK_ERROR; - HDgettimeofday(&t1, NULL); + for (i = 0; i < NLOOP; i++) { + HDgettimeofday(&t1, NULL); + if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + HDgettimeofday(&t2, NULL); - if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + t_total.tv_sec += (t2.tv_sec - t1.tv_sec); + t_total.tv_usec += (t2.tv_usec - t1.tv_usec); - HDgettimeofday(&t2, NULL); + if (i < (NLOOP - 1)) + if (H5Gclose(view) < 0) FAIL_STACK_ERROR; + } printf("View creation time on region: %lf ms\n", - ((float) (t2.tv_sec - t1.tv_sec)) * 1000.0f - + ((float) (t2.tv_usec - t1.tv_usec)) / 1000.0f); + ((float) t_total.tv_sec) * 1000.0f / NLOOP + + ((float) t_total.tv_usec) / (NLOOP * 1000.0f)); if (!(result & H5Q_REF_REG)) FAIL_STACK_ERROR; if (test_query_read_selection(1, &filename, &file, view, H5R_REGION) < 0) FAIL_STACK_ERROR; @@ -603,7 +728,24 @@ test_query_apply_view(const char *filename, hid_t fapl, unsigned idx_plugin) /* Test object query */ if ((query = test_query_create_type(H5R_OBJECT)) < 0) FAIL_STACK_ERROR; - if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + + t_total.tv_sec = 0; + t_total.tv_usec = 0; + for (i = 0; i < NLOOP; i++) { + HDgettimeofday(&t1, NULL); + if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + HDgettimeofday(&t2, NULL); + + t_total.tv_sec += (t2.tv_sec - t1.tv_sec); + t_total.tv_usec += (t2.tv_usec - t1.tv_usec); + + if (i < (NLOOP - 1)) + if (H5Gclose(view) < 0) FAIL_STACK_ERROR; + } + + printf("View creation time on object: %lf ms\n", + ((float) t_total.tv_sec) * 1000.0f / NLOOP + + ((float) t_total.tv_usec) / (NLOOP * 1000.0f)); if (!(result & H5Q_REF_OBJ)) FAIL_STACK_ERROR; if (test_query_read_selection(1, &filename, &file, view, H5R_OBJECT) < 0) FAIL_STACK_ERROR; @@ -616,7 +758,24 @@ test_query_apply_view(const char *filename, hid_t fapl, unsigned idx_plugin) /* Test attribute query */ if ((query = test_query_create_type(H5R_ATTR)) < 0) FAIL_STACK_ERROR; - if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + + t_total.tv_sec = 0; + t_total.tv_usec = 0; + for (i = 0; i < NLOOP; i++) { + HDgettimeofday(&t1, NULL); + if ((view = H5Qapply(file, query, &result, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR; + HDgettimeofday(&t2, NULL); + + t_total.tv_sec += (t2.tv_sec - t1.tv_sec); + t_total.tv_usec += (t2.tv_usec - t1.tv_usec); + + if (i < (NLOOP - 1)) + if (H5Gclose(view) < 0) FAIL_STACK_ERROR; + } + + printf("View creation time on attribute: %lf ms\n", + ((float) t_total.tv_sec) * 1000.0f / NLOOP + + ((float) t_total.tv_usec) / (NLOOP * 1000.0f)); if (!(result & H5Q_REF_ATTR)) FAIL_STACK_ERROR; if (test_query_read_selection(1, &filename, &file, view, H5R_ATTR) < 0) FAIL_STACK_ERROR; @@ -641,7 +800,8 @@ error: } static herr_t -test_query_apply_view_multi(const char *filenames[], hid_t fapl, unsigned idx_plugin) +test_query_apply_view_multi(const char *filenames[], hid_t fapl, + unsigned meta_idx_plugin, unsigned data_idx_plugin) { hid_t files[MULTI_NFILES] = {H5I_BADID, H5I_BADID, H5I_BADID}; hid_t view = H5I_BADID; @@ -655,7 +815,8 @@ test_query_apply_view_multi(const char *filenames[], hid_t fapl, unsigned idx_pl /* Create simple files for testing queries */ for (i = 0; i < MULTI_NFILES; i++) { printf("Creating test file \"%s\"\n", filenames[i]); - if ((test_query_create_simple_file(filenames[i], fapl, idx_plugin)) < 0) FAIL_STACK_ERROR; + if ((test_query_create_simple_file(filenames[i], fapl, meta_idx_plugin, + data_idx_plugin)) < 0) FAIL_STACK_ERROR; /* Open the file in read-only */ if ((files[i] = H5Fopen(filenames[i], H5F_ACC_RDONLY, fapl)) < 0) FAIL_STACK_ERROR; } @@ -727,15 +888,21 @@ error: } int -main(void) +main(int argc, char *argv[]) { char filename[MAX_NAME]; /* file name */ #ifdef H5_HAVE_FASTBIT char filename_fastbit[MAX_NAME]; + char filename_fastbit_meta_dummy[MAX_NAME]; #endif char **filename_multi = NULL; + char filename_meta_dummy[MAX_NAME]; hid_t query = H5I_BADID, fapl = H5I_BADID; int i; + unsigned n_objs = 3; + + if (argc > 1) + n_objs = (unsigned) atoi(argv[1]); /* Reset library */ h5_reset(); @@ -753,6 +920,11 @@ main(void) h5_fixname(FILENAME[2], fapl, filename_multi[0], MAX_NAME); h5_fixname(FILENAME[3], fapl, filename_multi[1], MAX_NAME); h5_fixname(FILENAME[4], fapl, filename_multi[2], MAX_NAME); + h5_fixname(FILENAME[5], fapl, filename_meta_dummy, sizeof(filename_meta_dummy)); +#ifdef H5_HAVE_FASTBIT + h5_fixname(FILENAME[6], fapl, filename_fastbit_meta_dummy, + sizeof(filename_fastbit_meta_dummy)); +#endif /* Check that no object is left open */ H5Pset_fclose_degree(fapl, H5F_CLOSE_SEMI); @@ -783,24 +955,51 @@ main(void) TESTING("query apply view (no index)"); - if (test_query_apply_view(filename, fapl, H5X_PLUGIN_NONE) < 0) FAIL_STACK_ERROR; + if (test_query_apply_view(filename, fapl, n_objs, H5X_PLUGIN_NONE, + H5X_PLUGIN_NONE) < 0) FAIL_STACK_ERROR; PASSED(); #ifdef H5_HAVE_FASTBIT TESTING("query apply view (FastBit index)"); - if (test_query_apply_view(filename_fastbit, fapl, H5X_PLUGIN_FASTBIT) < 0) FAIL_STACK_ERROR; + if (test_query_apply_view(filename_fastbit, fapl, n_objs, H5X_PLUGIN_NONE, + H5X_PLUGIN_FASTBIT) < 0) FAIL_STACK_ERROR; PASSED(); #endif TESTING("query apply view multiple (no index)"); - if (test_query_apply_view_multi(filename_multi, fapl, H5X_PLUGIN_NONE) < 0) FAIL_STACK_ERROR; + if (test_query_apply_view_multi(filename_multi, fapl, H5X_PLUGIN_NONE, + H5X_PLUGIN_NONE) < 0) FAIL_STACK_ERROR; PASSED(); + TESTING("query apply view (dummy metadata/no data index)"); + + /* Use latest format */ + if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR; + + if (test_query_apply_view(filename_meta_dummy, fapl, n_objs, + H5X_PLUGIN_META_DUMMY, H5X_PLUGIN_NONE) < 0) FAIL_STACK_ERROR; + + PASSED(); + +#ifdef H5_HAVE_FASTBIT + TESTING("query apply view (dummy metadata/FastBit index)"); + + /* Use latest format */ + if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR; + + if (test_query_apply_view(filename_fastbit_meta_dummy, fapl, n_objs, + H5X_PLUGIN_META_DUMMY, H5X_PLUGIN_FASTBIT) < 0) FAIL_STACK_ERROR; + + PASSED(); +#endif + /* Verify symbol table messages are cached */ if(h5_verify_cached_stabs(FILENAME, fapl) < 0) TEST_ERROR -- cgit v0.12