diff options
Diffstat (limited to 'src')
96 files changed, 45139 insertions, 205 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eb43b3d..0b64414 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -463,12 +463,17 @@ SET (H5P_SRCS ${HDF5_SRC_DIR}/H5Pfcpl.c ${HDF5_SRC_DIR}/H5Pfmpl.c ${HDF5_SRC_DIR}/H5Pgcpl.c + ${HDF5_SRC_DIR}/H5Pmcpl.c + ${HDF5_SRC_DIR}/H5Pmapl.c ${HDF5_SRC_DIR}/H5Pint.c ${HDF5_SRC_DIR}/H5Plapl.c ${HDF5_SRC_DIR}/H5Plcpl.c ${HDF5_SRC_DIR}/H5Pocpl.c ${HDF5_SRC_DIR}/H5Pocpypl.c ${HDF5_SRC_DIR}/H5Pstrcpl.c + ${HDF5_SRC_DIR}/H5Prcapl.c + ${HDF5_SRC_DIR}/H5Ptrspl.c + ${HDF5_SRC_DIR}/H5Ptrfpl.c ${HDF5_SRC_DIR}/H5Ptest.c ) @@ -487,6 +492,14 @@ SET (H5PL_HDRS ) IDE_GENERATED_PROPERTIES ("H5PL" "${H5PL_HDRS}" "${H5PL_SRCS}" ) +SET (H5Q_SRCS + ${HDF5_SRC_DIR}/H5Q.c +) + +SET (H5Q_HDRS + ${HDF5_SRC_DIR}/H5Qpublic.h +) +IDE_GENERATED_PROPERTIES ("H5Q" "${H5Q_HDRS}" "${H5Q_SRCS}" ) SET (H5R_SRCS ${HDF5_SRC_DIR}/H5R.c @@ -617,11 +630,56 @@ SET (H5VL_SRCS ${HDF5_SRC_DIR}/H5VLint.c ${HDF5_SRC_DIR}/H5VLnative.c ) + SET (H5VL_HDRS ${HDF5_SRC_DIR}/H5VLpublic.h ${HDF5_SRC_DIR}/H5VLpkg.h ${HDF5_SRC_DIR}/H5VLnative.h ) + +IF (HDF5_ENABLE_EFF) + SET (H5FF_SRCS + ${HDF5_SRC_DIR}/H5AS.c + ${HDF5_SRC_DIR}/H5FF.c + ${HDF5_SRC_DIR}/H5M.c + ${HDF5_SRC_DIR}/H5ES.c + ${HDF5_SRC_DIR}/H5RC.c + ${HDF5_SRC_DIR}/H5TR.c + ) + SET (H5FF_HDRS + ${HDF5_SRC_DIR}/H5ASpublic.h + ${HDF5_SRC_DIR}/H5FFpublic.h + ${HDF5_SRC_DIR}/H5Mpublic.h + ${HDF5_SRC_DIR}/H5ESpublic.h + ${HDF5_SRC_DIR}/H5RCpublic.h + ${HDF5_SRC_DIR}/H5TRpublic.h + ) + IDE_GENERATED_PROPERTIES ("H5FF" "${H5FF_HDRS}" "${H5FF_SRCS}" ) + SET (H5VL_SRCS + ${H5VL_SRCS} + ${HDF5_SRC_DIR}/H5VLiod.c + ${HDF5_SRC_DIR}/H5VLiod_common.c + ${HDF5_SRC_DIR}/H5VLiod_client.c + ${HDF5_SRC_DIR}/H5VLiod_server.c + ${HDF5_SRC_DIR}/H5VLiod_util.c + ${HDF5_SRC_DIR}/H5VLiod_file.c + ${HDF5_SRC_DIR}/H5VLiod_group.c + ${HDF5_SRC_DIR}/H5VLiod_dset.c + ${HDF5_SRC_DIR}/H5VLiod_dtype.c + ${HDF5_SRC_DIR}/H5VLiod_attr.c + ${HDF5_SRC_DIR}/H5VLiod_link.c + ${HDF5_SRC_DIR}/H5VLiod_obj.c + ${HDF5_SRC_DIR}/H5VLiod_map.c + ${HDF5_SRC_DIR}/H5VLiod_trans.c + ${HDF5_SRC_DIR}/H5VLiod_encdec.c + ${HDF5_SRC_DIR}/H5VLiod_analysis.c + ) + SET (H5VL_HDRS + ${H5VL_HDRS} + ${HDF5_SRC_DIR}/H5VLiod.h + ) +ENDIF (HDF5_ENABLE_EFF) + IDE_GENERATED_PROPERTIES ("H5VL" "${H5VL_HDRS}" "${H5VL_SRCS}" ) SET (H5WB_SRCS @@ -684,6 +742,7 @@ SET (common_SRCS ${H5O_SRCS} ${H5P_SRCS} ${H5PL_SRCS} + ${H5Q_SRCS} ${H5R_SRCS} ${H5UC_SRCS} ${H5RS_SRCS} @@ -698,6 +757,12 @@ SET (common_SRCS ${H5WB_SRCS} ${H5Z_SRCS} ) +IF (HDF5_ENABLE_EFF) + SET (common_SRCS + ${common_SRCS} + ${H5FF_SRCS} + ) +ENDIF (HDF5_ENABLE_EFF) SET (H5_PUBLIC_HEADERS ${H5_HDRS} @@ -725,6 +790,7 @@ SET (H5_PUBLIC_HEADERS ${H5O_HDRS} ${H5P_HDRS} ${H5PL_HDRS} + ${H5Q_HDRS} ${H5R_HDRS} ${H5S_HDRS} ${H5SM_HDRS} @@ -732,6 +798,12 @@ SET (H5_PUBLIC_HEADERS ${H5VL_HDRS} ${H5Z_HDRS} ) +IF (HDF5_ENABLE_EFF) + SET (H5_PUBLIC_HEADERS + ${H5_PUBLIC_HEADERS} + ${H5FF_HDRS} + ) +ENDIF (HDF5_ENABLE_EFF) SET (H5_PRIVATE_HEADERS @@ -765,6 +837,7 @@ SET (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5Oprivate.h ${HDF5_SRC_DIR}/H5Pprivate.h ${HDF5_SRC_DIR}/H5PLprivate.h + ${HDF5_SRC_DIR}/H5Qprivate.h ${HDF5_SRC_DIR}/H5UCprivate.h ${HDF5_SRC_DIR}/H5Rprivate.h ${HDF5_SRC_DIR}/H5RSprivate.h @@ -780,6 +853,13 @@ SET (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5Zprivate.h ${HDF5_SRC_DIR}/H5win32defs.h ) +IF (HDF5_ENABLE_EFF) + SET (H5_PRIVATE_HEADERS + ${H5_PRIVATE_HEADERS} + ${HDF5_SRC_DIR}/H5ASprivate.h + ${HDF5_SRC_DIR}/H5FFprivate.h + ) +ENDIF (HDF5_ENABLE_EFF) INCLUDE_DIRECTORIES (${HDF5_SOURCE_DIR}) INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR}) @@ -255,9 +255,19 @@ H5_term_library(void) pending += DOWN(D); pending += DOWN(L); pending += DOWN(G); +#ifdef H5_HAVE_EFF + pending += DOWN(M); +#endif /* H5_HAVE_EFF */ pending += DOWN(A); pending += DOWN(S); pending += DOWN(T); +#ifdef H5_HAVE_EFF + pending += DOWN(TR); + pending += DOWN(RC); +#endif /* H5_HAVE_EFF */ + pending += DOWN(ES); + pending += DOWN(Q); + /* Don't shut down the file code until objects in files are shut down */ if(pending == 0) pending += DOWN(F); @@ -809,3 +819,30 @@ H5close(void) FUNC_LEAVE_API_NOFS(SUCCEED) } /* end H5close() */ + +/*------------------------------------------------------------------------- + * Function: H5checksum + * + * Purpose: Generate a checksum for the data in Key. + * If the checksum is for a contiguous buffer, pass cs as NULL. + * if the checksum is for non contiguous buffer, intialize cs + * a,b,c,state to 0 and set the total_length to the size of the + * data. Then call H5checksum on every contiguous piece of the buffer + * with cs as the seed value from the previous H5checksum call. + * + * Programmer: Mohamad Chaarawi + * June 2013 + * + *------------------------------------------------------------------------- + */ +uint32_t H5checksum(const void *key, size_t length, H5_checksum_seed_t *cs) +{ + uint32_t ret_value; + + FUNC_ENTER_API(0) + + ret_value = H5_checksum_lookup4(key, length, cs); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5checksum */ @@ -223,7 +223,7 @@ H5A_term_interface(void) /* ARGSUSED */ hid_t H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, - hid_t acpl_id, hid_t UNUSED aapl_id) + hid_t acpl_id, hid_t aapl_id) { void *attr = NULL; /* attr token from VOL plugin */ void *obj = NULL; /* object token of loc_id */ @@ -365,7 +365,8 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") /* Create the attribute through the VOL */ - if(NULL == (attr = H5VL_attr_create(obj, loc_params, vol_plugin, attr_name, acpl_id, aapl_id, H5AC_dxpl_id, H5_EVENT_STACK_NULL))) + if(NULL == (attr = H5VL_attr_create(obj, loc_params, vol_plugin, attr_name, acpl_id, + aapl_id, H5AC_dxpl_id, H5_EVENT_STACK_NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create attribute") /* Get an atom for the attribute */ @@ -1729,6 +1730,7 @@ done: herr_t H5Aclose(hid_t attr_id) { + H5VL_t *vol_plugin = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -1738,6 +1740,13 @@ H5Aclose(hid_t attr_id) if(NULL == H5I_object_verify(attr_id, H5I_ATTR)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = H5_EVENT_STACK_NULL; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + /* Decrement references to that atom (and close it) */ if(H5I_dec_app_ref(attr_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "can't close attribute") @@ -1789,7 +1798,8 @@ H5Aexists(hid_t obj_id, const char *attr_name) loc_params.obj_type = H5I_get_type(obj_id); /* get the attribute info through the VOL */ - if(H5VL_attr_get(obj, vol_plugin, H5VL_ATTR_EXISTS, H5AC_dxpl_id, H5_EVENT_STACK_NULL, loc_params, attr_name, &ret_value) < 0) + if(H5VL_attr_get(obj, vol_plugin, H5VL_ATTR_EXISTS, H5AC_dxpl_id, H5_EVENT_STACK_NULL, + loc_params, attr_name, &ret_value) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get attribute info") done: @@ -1878,7 +1888,8 @@ H5A_close_attr(void *attr, H5VL_t *vol_plugin) FUNC_ENTER_NOAPI_NOINIT /* Close the attr through the VOL*/ - if((ret_value = H5VL_attr_close(attr, vol_plugin, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_attr_close(attr, vol_plugin, vol_plugin->close_dxpl_id, + vol_plugin->close_estack_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "unable to close attribute") done: diff --git a/src/H5AS.c b/src/H5AS.c new file mode 100644 index 0000000..3a94a78 --- /dev/null +++ b/src/H5AS.c @@ -0,0 +1,157 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: Analysis shipping for local enumeration of data on remote storage. + */ + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +//#define H5_INTERFACE_INIT_FUNC H5AS_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5ASprivate.h" /* Analysis shipping */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" +#include "H5ESprivate.h" /* Event Stacks */ + +#include "H5VLiod_client.h" + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5ASexecute + * + * Purpose: Execute the query on file_name/obj_name, run split_script + * on the query result, combine the results and run combine_script. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5ASexecute(const char *file_name, const char *obj_name, hid_t query_id, + const char *split_script, const char *combine_script, hid_t estack_id) +{ + H5Q_t *query; + herr_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "*s*si*s*si", file_name, obj_name, query_id, split_script, + combine_script, estack_id); + + /* Check argument and retrieve object */ + if(file_name == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL file name") + if(obj_name == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL object name") + /* + if(NULL == (query = (H5Q_t *)H5I_object_verify(query_id, H5I_QUERY))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + */ + + /* It is allowed to have split_script and combine_script to be NULL */ + + /* H5AS_execute */ + if((ret_value = H5AS_execute(file_name, obj_name, query_id, split_script, + combine_script, estack_id)) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTENCODE, FAIL, "can't start analysis" + "shipping execution") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ASexecute() */ + +/*------------------------------------------------------------------------- + * Function: H5AS_execute + * + * Purpose: Private routine for H5ASexecute. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5AS_execute(const char *file_name, const char *obj_name, hid_t query_id, + const char *split_script, const char *combine_script, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(file_name); + HDassert(obj_name); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if (NULL == (request = (H5_priv_request_t *) H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_analysis_execute(file_name, obj_name, query_id, + split_script, combine_script, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, + "can't start iod analysis shipping execution") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, + "failed to insert request in event stack"); + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5AS_execute */ diff --git a/src/H5ASprivate.h b/src/H5ASprivate.h new file mode 100644 index 0000000..203990e --- /dev/null +++ b/src/H5ASprivate.h @@ -0,0 +1,47 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5AS module + */ +#ifndef _H5ASprivate_H +#define _H5ASprivate_H + +/* Include package's public header */ +#include "H5ASpublic.h" + +/* Private headers needed by this file */ +#include "H5Qprivate.h" + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/******************************/ +/* Library Private Prototypes */ +/******************************/ + +H5_DLL herr_t H5AS_execute(const char *file_name, const char *dataset_name, + hid_t query_id, const char *split_script, const char *combine_script, + hid_t estack_id); + +#endif /* _H5ASprivate_H */ diff --git a/src/H5ASpublic.h b/src/H5ASpublic.h new file mode 100644 index 0000000..9cd8ffa --- /dev/null +++ b/src/H5ASpublic.h @@ -0,0 +1,57 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains public information about the H5AS analysis shipping + * module. It implements the functions specified in the "Data Analysis + * Extensions" section of the Fast Forward HDF design document. + * + * The functionality should be provided as part of the server-side VOL process, + * i.e. this file should + */ +#ifndef _H5ASpublic_H +#define _H5ASpublic_H + +/* Public headers needed by this file */ +#include "H5public.h" +#include "H5Ipublic.h" + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/***************************/ +/* Library Public Typedefs */ +/***************************/ + +/****************************/ +/* Library Public Variables */ +/****************************/ + +/*****************************/ +/* Library Public Prototypes */ +/*****************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Function prototypes */ +H5_DLL herr_t H5ASexecute(const char *file_name, const char *dataset_name, + hid_t query_id, const char *split_script, const char *combine_script, + hid_t estack_id); + +#ifdef __cplusplus +} +#endif +#endif /* _H5ASpublic_H */ @@ -394,6 +394,7 @@ done: herr_t H5Dclose(hid_t dset_id) { + H5VL_t *vol_plugin = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -403,6 +404,13 @@ H5Dclose(hid_t dset_id) if(H5I_DATASET != H5I_get_type(dset_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset ID") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = H5_EVENT_STACK_NULL; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + /* * Decrement the counter on the dataset. It will be freed if the count * reaches zero. @@ -1033,7 +1041,8 @@ H5Dset_extent(hid_t dset_id, const hsize_t size[]) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") /* set the extent through the VOL */ - if((ret_value = H5VL_dataset_set_extent(dset, vol_plugin, size, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_dataset_set_extent(dset, vol_plugin, size, H5AC_dxpl_id, + H5_EVENT_STACK_NULL)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extent of dataset") done: @@ -1063,7 +1072,8 @@ H5D_close_dataset(void *dset, H5VL_t *vol_plugin) FUNC_ENTER_NOAPI_NOINIT /* Close the dataset through the VOL*/ - if((ret_value = H5VL_dataset_close(dset, vol_plugin, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_dataset_close(dset, vol_plugin, vol_plugin->close_dxpl_id, + vol_plugin->close_estack_id)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to close dataset") done: diff --git a/src/H5Dselect.c b/src/H5Dselect.c index 38f8bc4..2b9b31f 100644 --- a/src/H5Dselect.c +++ b/src/H5Dselect.c @@ -311,4 +311,3 @@ H5D__select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__select_write() */ - diff --git a/src/H5ES.c b/src/H5ES.c new file mode 100644 index 0000000..1ab3b63 --- /dev/null +++ b/src/H5ES.c @@ -0,0 +1,1349 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.org> + * September, 2013 + * + * Purpose: Wrappers around existing HDF5 to support Exascale FastForward + * functionality. + * + */ + + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5ES_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5VLprivate.h" /* VOL plugins */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5ES_t struct */ +H5FL_DEFINE(H5ES_t); + +/* Dataspace ID class */ +static const H5I_class_t H5I_ES_CLS[1] = {{ + H5I_ES, /* ID class value */ + 0, /* Class flags */ + 2, /* # of reserved IDs for class */ + (H5I_free_t)H5ES_close, /* Callback routine for closing objects of this class */ + NULL /* Callback routine for closing auxilary objects of this class */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5ES_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_init() */ + + +/*-------------------------------------------------------------------------- +NAME + H5ES_init_interface -- Initialize interface-specific information +USAGE + herr_t H5ES_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5ES_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Initialize the atom group for the ES IDs */ + if(H5I_register_type(H5I_ES_CLS) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_init_interface() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ES_term_interface + PURPOSE + Terminate various H5ES objects + USAGE + void H5ES_term_interface() + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Release the atom group and any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5ES_term_interface(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + if((n = H5I_nmembers(H5I_ES))) { + H5I_clear_type(H5I_ES, FALSE, FALSE); + } /* end if */ + else { + /* Free data types */ + H5I_dec_type_ref(H5I_ES); + + /* Shut down interface */ + H5_interface_initialize_g = 0; + n = 1; /*H5I*/ + } /* end else */ + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* end H5ES_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5EScreate + * + * Purpose: Creates an Event Stack used to manage async requests + * + * Return: Success: The ID for a new event stack. + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5EScreate(void) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + hid_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE0("i",""); + + /* Allocate the event stack structure */ + if(NULL == (e_stack = H5FL_CALLOC(H5ES_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for event stack"); + + e_stack->head = e_stack->tail = NULL; + e_stack->size = 0; + + /* Get an atom for the event stack with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register(H5I_ES, e_stack, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize event stack handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScreate() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_insert + * + * Purpose: Inserts an async request into an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_insert(hid_t es_id, H5_priv_request_t *req) +{ + H5ES_t *e_stack = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments. */ + if(NULL == req) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "bad request"); + if(H5I_ES != H5I_get_type(es_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event stack ID") + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object(es_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + req->next = NULL; + req->prev = NULL; + + if(NULL == e_stack->head && NULL == e_stack->tail) { + e_stack->head = e_stack->tail = req; + } + else { + e_stack->head->prev = req; + req->next = e_stack->head; + e_stack->head = req; + } + e_stack->size ++; + e_stack->in_progress ++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESwait + * + * Purpose: Waits on an async request with the specified index in + * the Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESwait(hid_t es_id, size_t event_idx, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iz*Es", es_id, event_idx, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Wait request in the event stack */ + if(H5ES_wait(e_stack, event_idx, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait request into event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESwait() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_wait + * + * Purpose: Private routine for H5ESwait + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_wait(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(event_idx >= e_stack->size) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "index is out of range for event stack") + + cur = e_stack->head; + HDassert(NULL != cur); + + for(u=0 ; u<event_idx ; u++) { + cur = cur->next; + HDassert(NULL != cur); + } + + if(H5ES_STATUS_IN_PROGRESS == cur->status) { + /* wait on the request */ + if(H5VL_request_wait(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + + e_stack->in_progress --; + cur->status = status; + } + + *_status = cur->status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_wait() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESwait_all + * + * Purpose: Waits on all async requests in an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESwait_all(hid_t es_id, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Es", es_id, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Wait on all requests in the event stack */ + if(H5ES_wait_all(e_stack, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait request into event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESwait_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_wait_all + * + * Purpose: Private routine for H5ESwait_all + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_wait_all(H5ES_t *e_stack, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + size_t succeed_count = 0, fail_count = 0, cancel_count = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(e_stack->size == 0) { + HGOTO_DONE(SUCCEED); + } + + cur = e_stack->tail; + + for(u=0 ; u<e_stack->size ; u++) { + HDassert(NULL != cur); + + if(cur->status == H5ES_STATUS_IN_PROGRESS) { + /* wait on the request */ + if(H5VL_request_wait(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + e_stack->in_progress --; + cur->status = status; + } + else { + status = cur->status; + } + + switch(status) { + case H5ES_STATUS_SUCCEED: + succeed_count ++; + break; + case H5ES_STATUS_FAIL: + fail_count ++; + break; + case H5ES_STATUS_CANCEL: + cancel_count ++; + break; + case H5ES_STATUS_IN_PROGRESS: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "waiting on request returned invalid status"); + } + + cur = cur->prev; + } + + if(0 != e_stack->in_progress) { + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Failed to wait on all requests"); + } + + if(fail_count) + status = H5ES_STATUS_FAIL; + else if(cancel_count == e_stack->size) + status = H5ES_STATUS_CANCEL; + else if(succeed_count == e_stack->size || + succeed_count+cancel_count == e_stack->size) + status = H5ES_STATUS_SUCCEED; + + *_status = status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_wait_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5EStest + * + * Purpose: Tests on an async request with the specified index in + * the Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5EStest(hid_t es_id, size_t event_idx, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iz*Es", es_id, event_idx, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Test request in the event stack */ + if(H5ES_test(e_stack, event_idx, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request in event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EStest() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_test + * + * Purpose: Private routine for H5EStest + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_test(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(event_idx >= e_stack->size) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "index is out of range for event stack") + + cur = e_stack->head; + + for(u=0 ; u<event_idx ; u++) { + HDassert(NULL != cur); + cur = cur->next; + } + + if(H5ES_STATUS_IN_PROGRESS == cur->status) { + /* test on the request */ + if(H5VL_request_test(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + + cur->status = status; + + if(H5ES_STATUS_IN_PROGRESS != status) + e_stack->in_progress --; + } + + *_status = cur->status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_test() */ + + +/*------------------------------------------------------------------------- + * Function: H5EStest_all + * + * Purpose: Tests on all async requests in an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5EStest_all(hid_t es_id, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Es", es_id, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Test on all requests in the event stack */ + if(H5ES_test_all(e_stack, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request into event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EStest_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_test_all + * + * Purpose: Private routine for H5EStest_all + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_test_all(H5ES_t *e_stack, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + size_t succeed_count = 0, fail_count = 0, cancel_count = 0; + size_t in_progress_count = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(e_stack->size == 0) { + HGOTO_DONE(SUCCEED); + } + + cur = e_stack->tail; + + for(u=0 ; u<e_stack->size ; u++) { + HDassert(NULL != cur); + + if(cur->status == H5ES_STATUS_IN_PROGRESS) { + /* test on the request */ + if(H5VL_request_test(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + + if(status != H5ES_STATUS_IN_PROGRESS) { + cur->status = status; + e_stack->in_progress --; + } + } + else { + status = cur->status; + } + + switch(status) { + case H5ES_STATUS_SUCCEED: + succeed_count ++; + break; + case H5ES_STATUS_FAIL: + fail_count ++; + break; + case H5ES_STATUS_CANCEL: + cancel_count ++; + break; + case H5ES_STATUS_IN_PROGRESS: + in_progress_count ++; + break; + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "testing on request returned invalid status"); + } + + cur = cur->prev; + } + + HDassert(in_progress_count == e_stack->in_progress); + + if(in_progress_count) + status = H5ES_STATUS_IN_PROGRESS; + else if(fail_count) + status = H5ES_STATUS_FAIL; + else if(cancel_count == e_stack->size) + status = H5ES_STATUS_CANCEL; + else if(succeed_count == e_stack->size || + succeed_count+cancel_count == e_stack->size) + status = H5ES_STATUS_SUCCEED; + + *_status = status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_test_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5EScancel + * + * Purpose: Cancels on an async request with the specified index in + * the Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5EScancel(hid_t es_id, size_t event_idx, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iz*Es", es_id, event_idx, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Cancel request in the event stack */ + if(H5ES_cancel(e_stack, event_idx, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to cancel request in event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScancel() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_cancel + * + * Purpose: Private routine for H5EScancel + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_cancel(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(event_idx >= e_stack->size) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "index is out of range for event stack") + + cur = e_stack->head; + + for(u=0 ; u<event_idx ; u++) { + HDassert(NULL != cur); + cur = cur->next; + } + + if(cur->status == H5ES_STATUS_IN_PROGRESS) { + /* cancel on the request */ + if(H5VL_request_cancel(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to cancel request"); + + cur->status = status; + e_stack->in_progress --; + } + + *_status = cur->status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_cancel() */ + + +/*------------------------------------------------------------------------- + * Function: H5EScancel_all + * + * Purpose: Cancels on all async requests in an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5EScancel_all(hid_t es_id, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Es", es_id, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* Cancel on all requests in the event stack */ + if(H5ES_cancel_all(e_stack, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to cancel request into event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScancel_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_cancel_all + * + * Purpose: Private routine for H5EScancel_all + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_cancel_all(H5ES_t *e_stack, H5ES_status_t *_status) +{ + H5_priv_request_t *cur = NULL; + size_t u = 0; + size_t succeed_count = 0, fail_count = 0, cancel_count = 0; + H5ES_status_t status; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(e_stack->size == 0) { + HGOTO_DONE(SUCCEED); + } + + cur = e_stack->tail; + + for(u=0 ; u<e_stack->size ; u++) { + HDassert(NULL != cur); + + if(cur->status == H5ES_STATUS_IN_PROGRESS) { + /* cancel on the request */ + if(H5VL_request_cancel(&cur->req, cur->vol_plugin, &status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to cancel request"); + e_stack->in_progress --; + cur->status = status; + } + else { + status = cur->status; + } + + switch(status) { + case H5ES_STATUS_SUCCEED: + succeed_count ++; + break; + case H5ES_STATUS_FAIL: + fail_count ++; + break; + case H5ES_STATUS_CANCEL: + cancel_count ++; + break; + case H5ES_STATUS_IN_PROGRESS: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "canceling on request returned invalid status"); + } + + cur = cur->prev; + } + + if(0 != e_stack->in_progress) { + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Failed to wait on all requests"); + } + + if(fail_count) + status = H5ES_STATUS_FAIL; + else if(cancel_count == e_stack->size) + status = H5ES_STATUS_CANCEL; + else if(succeed_count == e_stack->size || + succeed_count+cancel_count == e_stack->size) + status = H5ES_STATUS_SUCCEED; + + *_status = status; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_cancel_all() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESget_count + * + * Purpose: Returns number of events in event stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESget_count(hid_t es_id, size_t *count) +{ + H5ES_t *e_stack = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*z", es_id, count); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + *count = e_stack->size; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESget_count() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESclear + * + * Purpose: Clear all events from the event stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESclear(hid_t es_id) +{ + H5ES_t *e_stack = NULL; + H5_priv_request_t *tail = NULL, *prev = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", es_id); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + if(e_stack->size == 0) { + HGOTO_DONE(SUCCEED); + } + + if(0 != e_stack->in_progress) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't clear stack with events in progress") + + while(e_stack->tail) { + /* Pop the last item and manage the stack accordingly */ + tail = e_stack->tail; + prev = tail->prev; + e_stack->tail = prev; + + if(NULL == e_stack->tail) + e_stack->head = e_stack->tail; + + /* free the request */ + HDassert(H5ES_STATUS_IN_PROGRESS != tail->status); + + tail->vol_plugin->nrefs --; + if (0 == tail->vol_plugin->nrefs) { + tail->vol_plugin->container_name = H5MM_xfree(tail->vol_plugin->container_name); + tail->vol_plugin = (H5VL_t *)H5MM_xfree(tail->vol_plugin); + } + tail->vol_plugin = NULL; + tail->req = NULL; + tail->next = NULL; + tail->prev = NULL; + tail = (H5_priv_request_t *)H5MM_xfree(tail); + + e_stack->size --; + } + + HDassert(0 == e_stack->size); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESclear() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESclose + * + * Purpose: Closes the specified event stack. The ID will no longer be + * valid for accessing the event stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESclose(hid_t es_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", es_id); + + /* Check args */ + if(NULL == H5I_object_verify(es_id,H5I_ES)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event stack") + + if(H5I_dec_app_ref(es_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESclose() */ + + +/*------------------------------------------------------------------------- + * Function: H5ES_close + * + * Purpose: Close an event stack object + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ES_close(H5ES_t *e_stack) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + e_stack = H5FL_FREE(H5ES_t, e_stack); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5ES_close() */ + +#if 0 + +/*------------------------------------------------------------------------- + * Function: H5EScreate + * + * Purpose: Creates an Event Stack used to manage async requests + * + * Return: Success: The ID for a new event stack. + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5EScreate(hid_t fapl_id) +{ + void *e_stack = NULL; /* event stack token */ + H5VL_class_t *vol_cls; /* VOL class attached to fapl_id */ + H5VL_t *vol_plugin = NULL; /* VOL plugin information from fapl */ + H5P_genplist_t *plist; /* Property list pointer */ + hid_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("i", "i", fapl_id); + + /* Check the file access property list */ + if(H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "can't find object for ID") + + if(H5P_get(plist, H5F_ACS_VOL_NAME, &vol_cls) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get vol plugin ID") + + /* Build the vol plugin struct */ + if(NULL == (*plugin = (H5VL_t *)H5MM_calloc(sizeof(H5VL_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + vol_plugin = *plugin; + vol_plugin->cls = vol_cls; + vol_plugin->nrefs = 1; + vol_plugin->container_name = NULL; + + /* Allocate the event stack structure */ + if(NULL == (e_stack = H5FL_CALLOC(H5ES_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for event stack"); + + e_stack->head = e_stack->tail = NULL; + e_stack->size = 0; + + /* Get an atom for the event stack with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register2(H5I_ES, e_stack, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize event stack handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5EScreate() */ + + +/*------------------------------------------------------------------------- + * Function: H5EScreate + * + * Purpose: Creates an Event Stack used to manage async requests + * + * Return: Success: The ID for a new event stack. + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +H5ES_t * +H5ES_create(H5VL_t **plugin, H5P_genplist_t *plist) +{ + H5ES_t *eq = NULL; /* Event Stack object */ + H5VL_class_t *vol_cls; /* VOL class attached to fapl_id */ + H5VL_t *vol_plugin = NULL; /* the public VOL struct */ + H5ES_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(H5P_get(plist, H5F_ACS_VOL_NAME, &vol_cls) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get vol plugin ID") + + /* Allocate the event stack structure */ + if(NULL == (eq = H5FL_CALLOC(H5ES_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for event stack"); + + eq->head = eq->tail = NULL; + eq->size = 0; + + /* Build the vol plugin struct */ + if(NULL == (*plugin = (H5VL_t *)H5MM_calloc(sizeof(H5VL_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + vol_plugin = *plugin; + vol_plugin->cls = vol_cls; + vol_plugin->nrefs = 1; + vol_plugin->container_name = NULL; + + ret_value = eq; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5ES_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESpop + * + * Purpose: retrieves the top async request from an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESpop(hid_t es_id, H5_request_t *req) +{ + H5ES_t *eq = NULL; /* event stack token */ + H5_priv_request_t *priv_req = NULL; /* internal request struct */ + H5_priv_request_t *head = NULL; + H5_priv_request_t *next = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*x", es_id, req); + + /* Check arguments. */ + if(H5I_ES != H5I_get_type(es_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event stack ID") + + /* get the eq object */ + if(NULL == (eq = (H5ES_t *)H5I_object(es_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier"); + + priv_req = eq->head; + + head = eq->head; + next = head->next; + + eq->head = next; + if(NULL == eq->head) + eq->tail = eq->head; + + eq->size --; + + *req = (H5_request_t) priv_req; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESpop() */ + + +/*------------------------------------------------------------------------- + * Function: H5ESwait + * + * Purpose: Waits on all async requests in an Event Stack. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5ESwait(hid_t es_id, size_t event_idx, H5ES_status_t *status) +{ + H5ES_t *e_stack = NULL; /* event stack token */ + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event stack should use */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iz*Es", es_id, event_idx, status); + + /* get the e_stack object */ + if(NULL == (e_stack = (H5ES_t *)H5I_object_verify(es_id, H5I_ES))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event stack identifier") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(es_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + /* Wait request in the event stack */ + if(H5ES_wait(e_stack, vol_plugin, event_idx, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait request into event stack") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5ESwait() */ + + +/*------------------------------------------------------------------------- + * Function: H5AOcancel + * + * Purpose: Cancel an asynchronous operation + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * May, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5AOcancel(H5_request_t req, H5ES_status_t *status) +{ + H5_priv_request_t *request = (H5_priv_request_t *)req; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "x*Es", req, status); + + if(H5VL_request_cancel(&request->req, request->vol_plugin, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to cancel request"); + + request->req = NULL; + request->vol_plugin = NULL; + request->next = NULL; + request = (H5_priv_request_t *)H5MM_xfree(request); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5AOcancel() */ + + +/*------------------------------------------------------------------------- + * Function: H5AOtest + * + * Purpose: Test for an asynchronous operation's completion + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5AOtest(H5_request_t req, H5ES_status_t *status) +{ + H5_priv_request_t *request = (H5_priv_request_t *)req; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "x*Es", req, status); + + if(H5VL_request_test(&request->req, request->vol_plugin, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + + if(*status != H5AO_PENDING) { + request->req = NULL; + request->vol_plugin = NULL; + request->next = NULL; + request = (H5_priv_request_t *)H5MM_xfree(request); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5AOtest() */ + + +/*------------------------------------------------------------------------- + * Function: H5AOwait + * + * Purpose: Wait for an asynchronous operation to complete + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5AOwait(H5_request_t req, H5ES_status_t *status) +{ + H5_priv_request_t *request = (H5_priv_request_t *)req; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "x*Es", req, status); + + if(H5VL_request_wait(&request->req, request->vol_plugin, status) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to test request"); + + request->req = NULL; + request->vol_plugin = NULL; + request->next = NULL; + request = (H5_priv_request_t *)H5MM_xfree(request); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5AOwait() */ + +#endif diff --git a/src/H5ESprivate.h b/src/H5ESprivate.h new file mode 100644 index 0000000..a1b8821 --- /dev/null +++ b/src/H5ESprivate.h @@ -0,0 +1,77 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5ES module + */ +#ifndef _H5ESprivate_H +#define _H5ESprivate_H + +/* Include package's public header */ +#include "H5ESpublic.h" + +/* Private headers needed by this file */ +#include "H5private.h" /* Generic Functions */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5VLprivate.h" /* VOL plugins */ + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* The private request structure */ +typedef struct H5_priv_request_t { + void *req; /* pointer to the request belonging to a VOL plugin */ + H5VL_t *vol_plugin; /* the vol plugin that owns this request */ + H5ES_status_t status; + struct H5_priv_request_t *prev; + struct H5_priv_request_t *next; +} H5_priv_request_t; + +/* The private request structure */ +typedef struct H5ES_t { + size_t size; /* number of events in the stack */ + size_t in_progress; /* number of events that the user did not call wait on */ + H5_priv_request_t *head; + H5_priv_request_t *tail; +} H5ES_t; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/******************************/ +/* Library Private Prototypes */ +/******************************/ + +herr_t H5ES_init(void); + +/* API wrappers */ +H5_DLL H5ES_t *H5ES_create(H5VL_t **plugin, H5P_genplist_t *plist); +H5_DLL herr_t H5ES_insert(hid_t es_id, H5_priv_request_t *req); +H5_DLL herr_t H5ES_wait(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_wait_all(H5ES_t *e_stack, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_test(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_test_all(H5ES_t *e_stack, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_cancel(H5ES_t *e_stack, size_t event_idx, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_cancel_all(H5ES_t *e_stack, H5ES_status_t *_status/*OUT*/); +H5_DLL herr_t H5ES_close(H5ES_t *e_stack); + +#endif /* _H5ESprivate_H */ diff --git a/src/H5ESpublic.h b/src/H5ESpublic.h new file mode 100644 index 0000000..a33a3d6 --- /dev/null +++ b/src/H5ESpublic.h @@ -0,0 +1,77 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5ES module. + */ +#ifndef _H5ESpublic_H +#define _H5ESpublic_H + +/* System headers needed by this file */ + +/* Public headers needed by this file */ +#include "H5public.h" +#include "H5Ipublic.h" + +/*****************/ +/* Public Macros */ +/*****************/ + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/* Asynchronous operation status */ +typedef enum H5ES_status_t { + H5ES_STATUS_IN_PROGRESS, /* Operation has not yet completed */ + H5ES_STATUS_SUCCEED, /* Operation has completed, successfully */ + H5ES_STATUS_FAIL, /* Operation has completed, but failed */ + H5ES_STATUS_CANCEL /* Operation has not completed and has been cancelled */ +} H5ES_status_t; + +/********************/ +/* Public Variables */ +/********************/ + + +#define H5_REQUEST_NULL NULL +#define H5_EVENT_STACK_NULL -1 + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************/ +/* Public Prototypes */ +/*********************/ + +H5_DLL hid_t H5EScreate(void); +H5_DLL herr_t H5ESget_count(hid_t es_id, size_t *count); + //H5_DLL herr_t H5ESget_event_info(hid_t es_id, size_t start_idx, size_t count, + //const char *ev_trace_str_arr[], H5ES_status_t ev_status_arr[], + //H5E_stack_id ev_err_stack_id_arr[]); +H5_DLL herr_t H5EStest(hid_t es_id, size_t event_idx, H5ES_status_t *status); +H5_DLL herr_t H5EStest_all(hid_t es_id, H5ES_status_t *status); +H5_DLL herr_t H5ESwait(hid_t es_id, size_t event_idx, H5ES_status_t *status); +H5_DLL herr_t H5ESwait_all(hid_t es_id, H5ES_status_t *status); +H5_DLL herr_t H5EScancel(hid_t es_id, size_t event_idx, H5ES_status_t *status); +H5_DLL herr_t H5EScancel_all(hid_t es_id, H5ES_status_t *status); +H5_DLL herr_t H5ESclear(hid_t es_id); +H5_DLL herr_t H5ESclose(hid_t es_id); + +#ifdef __cplusplus +} +#endif +#endif /* _H5ESpublic_H */ diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 4c4b4df..1f0d86a 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -40,6 +40,7 @@ hid_t H5E_ATTR_g = FAIL; /* Attribute */ hid_t H5E_IO_g = FAIL; /* Low-level I/O */ hid_t H5E_EFL_g = FAIL; /* External file list */ hid_t H5E_TST_g = FAIL; /* Ternary Search Trees */ +hid_t H5E_QUERY_g = FAIL; /* Query */ hid_t H5E_FSPACE_g = FAIL; /* Free Space Manager */ hid_t H5E_DATASET_g = FAIL; /* Dataset */ hid_t H5E_STORAGE_g = FAIL; /* Data storage */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 75c0b70..8a2c144 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -119,6 +119,11 @@ if((msg = H5E_create_msg(cls, H5E_MAJOR, "Ternary Search Trees"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_TST_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_QUERY_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MAJOR, "Query"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_QUERY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_FSPACE_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MAJOR, "Free Space Manager"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index 0e6def6..1bb55aa 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -69,6 +69,29 @@ typedef struct H5E_t H5E_t; HGOTO_DONE(ret_val) \ } +#define HGOTO_ERROR_IOD(iod_ret, ret_val, string) { \ + fprintf(stderr, "%s\n", string); \ + fprintf(stderr, "%d (%s).\n", iod_ret, strerror(-iod_ret)); \ + HGOTO_DONE(ret_val) \ +} + +#define HGOTO_ERROR_FF(ret_val, string) { \ + fprintf(stderr, "%s\n", string); \ + HGOTO_DONE(ret_val) \ +} + +#define HGOTO_ERROR2(maj, min, ret_val, string) { \ + fprintf(stderr, "%s\n", string); \ + err_occurred = TRUE; \ + err_occurred = err_occurred; /* Shut GCC warnings up! */ \ + HGOTO_DONE(ret_val) \ +} + +#define HDONE_ERROR2(maj, min, ret_val, string) { \ + fprintf(stderr, "%s\n", string); \ + ret_value = ret_val; \ +} + /* * HGOTO_ERROR_TAG macro, used like HGOTO_ERROR between H5_BEGIN_TAG and * H5_END_TAG statements. Resets the metadata tag before leaving the function. diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index e5ecd10..f0d4242 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -43,6 +43,7 @@ #define H5E_IO (H5OPEN H5E_IO_g) #define H5E_EFL (H5OPEN H5E_EFL_g) #define H5E_TST (H5OPEN H5E_TST_g) +#define H5E_QUERY (H5OPEN H5E_QUERY_g) #define H5E_FSPACE (H5OPEN H5E_FSPACE_g) #define H5E_DATASET (H5OPEN H5E_DATASET_g) #define H5E_STORAGE (H5OPEN H5E_STORAGE_g) @@ -77,6 +78,7 @@ H5_DLLVAR hid_t H5E_ATTR_g; /* Attribute */ H5_DLLVAR hid_t H5E_IO_g; /* Low-level I/O */ H5_DLLVAR hid_t H5E_EFL_g; /* External file list */ H5_DLLVAR hid_t H5E_TST_g; /* Ternary Search Trees */ +H5_DLLVAR hid_t H5E_QUERY_g; /* Query */ H5_DLLVAR hid_t H5E_FSPACE_g; /* Free Space Manager */ H5_DLLVAR hid_t H5E_DATASET_g; /* Dataset */ H5_DLLVAR hid_t H5E_STORAGE_g; /* Data storage */ diff --git a/src/H5Eterm.h b/src/H5Eterm.h index aecef3e..de0db21 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -41,6 +41,7 @@ H5E_ATTR_g= H5E_IO_g= H5E_EFL_g= H5E_TST_g= +H5E_QUERY_g= H5E_FSPACE_g= H5E_DATASET_g= H5E_STORAGE_g= @@ -626,7 +626,8 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") /* create a new file or truncate an existing file through the VOL */ - if(NULL == (file = H5VL_file_create(&vol_plugin, filename, flags, fcpl_id, fapl_id, H5AC_dxpl_id, H5_EVENT_STACK_NULL))) + if(NULL == (file = H5VL_file_create(&vol_plugin, filename, flags, fcpl_id, fapl_id, + H5AC_dxpl_id, H5_EVENT_STACK_NULL))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file") /* Get an atom for the file with the VOL information as the auxilary struct*/ @@ -789,6 +790,7 @@ done: herr_t H5Fclose(hid_t file_id) { + H5VL_t *vol_plugin = NULL; herr_t ret_value = SUCCEED; FUNC_ENTER_API(FAIL) @@ -798,6 +800,13 @@ H5Fclose(hid_t file_id) if(H5I_FILE != H5I_get_type(file_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = H5_EVENT_STACK_NULL; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + /* Decrement reference count on atom. When it reaches zero the file will be closed. */ if(H5I_dec_app_ref(file_id) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed") @@ -847,7 +856,8 @@ H5F_close_file(void *file, H5VL_t *vol_plugin) FUNC_ENTER_NOAPI_NOINIT /* Close the file through the VOL*/ - if((ret_value = H5VL_file_close(file, vol_plugin, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_file_close(file, vol_plugin, vol_plugin->close_dxpl_id, + vol_plugin->close_estack_id)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5FF.c b/src/H5FF.c new file mode 100644 index 0000000..c4875ed --- /dev/null +++ b/src/H5FF.c @@ -0,0 +1,4623 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol <koziol@hdfgroup.org> + * March, 2013 + * + * Purpose: Wrappers around existing HDF5 to support Exascale FastForward + * functionality. + * + */ + + +/****************/ +/* Module Setup */ +/****************/ + +#define H5A_PACKAGE /*suppress error about including H5Apkg */ +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5FF__init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Apkg.h" /* Attribute access */ +#include "H5Dpkg.h" /* Dataset access */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ +#include "H5Fpkg.h" /* File access */ +#include "H5FFprivate.h" /* FastForward wrappers */ +#include "H5Gpkg.h" /* Group access */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Tpkg.h" /* Datatype access */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod.h" /* IOD plugin - tmp */ +#include "H5VLiod_client.h" /* Client IOD - tmp */ + +#ifdef H5_HAVE_EFF +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +static herr_t +H5FF__init_interface(void) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_STATIC + + if(H5F_init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init file interface") + + if(H5G__init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init group interface") + + if(H5D_init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init dataset interface") + + if(H5A_init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init attribute interface") + + if(H5M_init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init map interface") + + if(H5RC_init() < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to init map interface") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FF__init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Fcreate_ff + * + * Purpose: Asynchronous wrapper around H5Fcreate(). + * + * Return: Success: The placeholder ID for a new file. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Fcreate_ff(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t estack_id) +{ + void *file = NULL; /* file token from VOL plugin */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "*sIuiii", filename, flags, fcpl_id, fapl_id, estack_id); + + /* Check/fix arguments */ + if(!filename || !*filename) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name") + /* In this routine, we only accept the following flags: + * H5F_ACC_EXCL, H5F_ACC_TRUNC and H5F_ACC_DEBUG + */ + if(flags & ~(H5F_ACC_EXCL | H5F_ACC_TRUNC | H5F_ACC_DEBUG)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags") + /* The H5F_ACC_EXCL and H5F_ACC_TRUNC flags are mutually exclusive */ + if((flags & H5F_ACC_EXCL) && (flags & H5F_ACC_TRUNC)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mutually exclusive flags for file creation") + + /* Check file creation property list */ + if(H5P_DEFAULT == fcpl_id) + fcpl_id = H5P_FILE_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(fcpl_id, H5P_FILE_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file create property list") + + /* Check the file access property list */ + if(H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") + + /* create a new file or truncate an existing file through the VOL */ + if(NULL == (file = H5VL_file_create(&vol_plugin, filename, flags, fcpl_id, fapl_id, + H5AC_dxpl_id, estack_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file") + + /* Get an atom for the file with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register2(H5I_FILE, file, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fcreate_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Fopen_ff + * + * Purpose: Asynchronous wrapper around H5Fopen(). + * + * Return: Success: The placeholder ID for a new file. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Fopen_ff(const char *filename, unsigned flags, hid_t fapl_id, + hid_t *rcxt_id, hid_t estack_id) +{ + void *file = NULL; /* file token from VOL plugin */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "*sIui*ii", filename, flags, fapl_id, rcxt_id, estack_id); + + /* Check/fix arguments. */ + if(!filename || !*filename) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name") + /* Reject undefined flags (~H5F_ACC_PUBLIC_FLAGS) and the H5F_ACC_TRUNC & H5F_ACC_EXCL flags */ + if((flags & ~H5F_ACC_PUBLIC_FLAGS) || + (flags & H5F_ACC_TRUNC) || (flags & H5F_ACC_EXCL)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") + if(H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") + + /* determine if we want to acquire the latest readable version + when the file is opened */ + if(rcxt_id) { + H5P_genplist_t *plist = NULL; /* Property list pointer */ + H5RC_t *rc = NULL; + + /* create a new read context object (if user requested it) */ + if(NULL == (rc = H5RC_create(file, IOD_TID_UNKNOWN))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create read context"); + /* Get an atom for the event queue with the VOL information as the auxilary struct */ + if((*rcxt_id = H5I_register(H5I_RC, rc, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize read context handle"); + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_ACQUIRE_RC_ID, rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rxct id") + } + + /* Open the file through the VOL layer */ + if(NULL == (file = H5VL_file_open(&vol_plugin, filename, flags, fapl_id, + H5AC_dxpl_id, estack_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file") + + if(rcxt_id) { + /* attach VOL information to the ID */ + if (H5I_register_aux(*rcxt_id, vol_plugin) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't attach vol info to ID") + } + + /* Get an atom for the file with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register2(H5I_FILE, file, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fopen_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Fclose_ff + * + * Purpose: This function closes the file specified by FILE_ID by + * flushing all data to storage, and terminating access to the + * file through FILE_ID. If objects (e.g., datasets, groups, + * etc.) are open in the file then the underlying storage is not + * closed until those objects are closed; however, all data for + * the file and the open objects is flushed. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fclose_ff(hid_t file_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", file_id, estack_id); + + /* Check/fix arguments. */ + if(H5I_FILE != H5I_get_type(file_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* Decrement reference count on atom. When it reaches zero the file will be closed. */ + if(H5I_dec_app_ref(file_id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fclose_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gcreate_ff + * + * Purpose: Asynchronous wrapper around H5Gcreate(). + * + * Return: Success: The placeholder ID for a group. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gcreate_ff(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, + hid_t trans_id, hid_t estack_id) +{ + void *grp = NULL; /* dset token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5VL_loc_params_t loc_params; + H5P_genplist_t *plist; /* Property list pointer */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("i", "i*siiiii", loc_id, name, lcpl_id, gcpl_id, gapl_id, trans_id, + estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Check group creation property list */ + if(H5P_DEFAULT == gcpl_id) + gcpl_id = H5P_GROUP_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(gcpl_id, H5P_GROUP_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group create property list") + + /* Check the group access property list */ + if(H5P_DEFAULT == gapl_id) + gapl_id = H5P_GROUP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(gapl_id, H5P_GROUP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(gcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + if(H5P_set(plist, H5VL_GRP_LCPL_ID, &lcpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for lcpl id") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the location object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Create the group through the VOL */ + if(NULL == (grp = H5VL_group_create(obj, loc_params, vol_plugin, name, gcpl_id, gapl_id, + dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group") + + /* Get an atom for the group */ + if((ret_value = H5I_register2(H5I_GROUP, grp, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize group handle") + +done: + if (ret_value < 0 && grp) + if(H5VL_group_close (grp, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group") + + FUNC_LEAVE_API(ret_value) +} /* end H5Gcreate_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gopen_ff + * + * Purpose: Asynchronous wrapper around H5Gopen(). + * + * Return: Success: The placeholder ID for a group. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gopen_ff(hid_t loc_id, const char *name, hid_t gapl_id, + hid_t rcxt_id, hid_t estack_id) +{ + void *grp = NULL; /* dset token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "i*siii", loc_id, name, gapl_id, rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Check the group access property list */ + if(H5P_DEFAULT == gapl_id) + gapl_id = H5P_GROUP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(gapl_id, H5P_GROUP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Create the group through the VOL */ + if(NULL == (grp = H5VL_group_open(obj, loc_params, vol_plugin, name, gapl_id, + dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group") + + /* Get an atom for the group */ + if((ret_value = H5I_register2(H5I_GROUP, grp, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gopen_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gclose_ff + * + * Purpose: Closes the specified group. The group ID will no longer be + * valid for accessing the group. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gclose_ff(hid_t group_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", group_id, estack_id); + + /* Check args */ + if(NULL == H5I_object_verify(group_id,H5I_GROUP)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(group_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* + * Decrement the counter on the group atom. It will be freed if the count + * reaches zero. + */ + if(H5I_dec_app_ref(group_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gclose_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dcreate_ff + * + * Purpose: Asynchronous wrapper around H5Dcreate(). + * + * Return: Success: The placeholder ID for a new dataset. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dcreate_ff(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, + hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id, hid_t trans_id, hid_t estack_id) +{ + void *dset = NULL; /* dset token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5VL_loc_params_t loc_params; + H5P_genplist_t *plist; /* Property list pointer */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE9("i", "i*siiiiiii", loc_id, name, type_id, space_id, lcpl_id, dcpl_id, + dapl_id, trans_id, estack_id); + + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Get correct property list */ + if(H5P_DEFAULT == dcpl_id) + dcpl_id = H5P_DATASET_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(dcpl_id, H5P_DATASET_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset create property list ID") + + /* Get correct property list */ + if(H5P_DEFAULT == dapl_id) + dapl_id = H5P_DATASET_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list") + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_DSET_TYPE_ID, &type_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for datatype id") + if(H5P_set(plist, H5VL_DSET_SPACE_ID, &space_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for space id") + if(H5P_set(plist, H5VL_DSET_LCPL_ID, &lcpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for lcpl id") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Create the dataset through the VOL */ + if(NULL == (dset = H5VL_dataset_create(obj, loc_params, vol_plugin, name, dcpl_id, dapl_id, + dxpl_id, estack_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset") + + /* Get an atom for the dataset */ + if((ret_value = H5I_register2(H5I_DATASET, dset, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && dset) + if(H5VL_dataset_close(dset, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + + FUNC_LEAVE_API(ret_value) +} /* end H5Dcreate_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dopen_ff + * + * Purpose: Asynchronous wrapper around H5Dopen(). + * + * Return: Success: The placeholder ID for a dataset. When + * the asynchronous operation completes, this + * ID will transparently be modified to be a + * "normal" ID. + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Dopen_ff(hid_t loc_id, const char *name, hid_t dapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *dset = NULL; /* dset token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "i*siii", loc_id, name, dapl_id, rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == dapl_id) + dapl_id = H5P_DATASET_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Create the dataset through the VOL */ + if(NULL == (dset = H5VL_dataset_open(obj, loc_params, vol_plugin, name, + dapl_id, dxpl_id, estack_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to open dataset") + + /* Get an atom for the dataset */ + if((ret_value = H5I_register2(H5I_DATASET, dset, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && dset) + if(H5VL_dataset_close (dset, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + + FUNC_LEAVE_API(ret_value) +} /* end H5Dopen_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dwrite_ff + * + * Purpose: Asynchronous wrapper around H5Dwrite(). + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dwrite_ff(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, const void *buf, + hid_t trans_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *dset; + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "iiiii*xii", dset_id, mem_type_id, mem_space_id, file_space_id, + dxpl_id, buf, trans_id, estack_id); + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (dset = (void *)H5I_object(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") + + /* Write the data through the VOL */ + if((ret_value = H5VL_dataset_write(dset, vol_plugin, mem_type_id, mem_space_id, + file_space_id, dxpl_id, buf, estack_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dwrite_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dread_ff + * + * Purpose: Asynchronous wrapper around H5Dread(). + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dread_ff(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, void *buf, + hid_t rcxt_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *dset; + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "iiiii*xii", dset_id, mem_type_id, mem_space_id, file_space_id, + dxpl_id, buf, rcxt_id, estack_id); + + if(mem_space_id < 0 || file_space_id < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if (H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (dset = (void *)H5I_object(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Read the data through the VOL */ + if((ret_value = H5VL_dataset_read(dset, vol_plugin, mem_type_id, mem_space_id, + file_space_id, dxpl_id, buf, estack_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dread_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dset_extent_ff + * + * Purpose: Modifies the dimensions of a dataset. + * Can change to a smaller dimension. + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dset_extent_ff(hid_t dset_id, const hsize_t size[], hid_t trans_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *dset; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*hii", dset_id, size, trans_id, estack_id); + + if(!size) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no size specified") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (dset = (void *)H5I_object(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") + + /* set the extent through the VOL */ + if((ret_value = H5VL_dataset_set_extent(dset, vol_plugin, size, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extent of dataset") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dset_extent_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dclose_ff + * + * Purpose: Closes access to a dataset (DATASET_ID) and releases + * resources used by it. It is illegal to subsequently use that + * same dataset ID in calls to other dataset functions. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dclose_ff(hid_t dset_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", dset_id, estack_id); + + /* Check/fix arguments. */ + if(H5I_DATASET != H5I_get_type(dset_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* + * Decrement the counter on the dataset. It will be freed if the count + * reaches zero. + * + * Pass in TRUE for the 3rd parameter to tell the function to remove + * dataset's ID even though the freeing function might fail. Please + * see the comments in H5I_dec_ref for details. (SLU - 2010/9/7) + */ + if(H5I_dec_app_ref_always_close(dset_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "can't decrement count on dataset ID") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dclose() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tcommit_ff + * + * Purpose: Save a transient datatype to a file and turn the type handle + * into a "named", immutable type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tcommit_ff(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, + hid_t tcpl_id, hid_t tapl_id, hid_t trans_id, hid_t estack_id) +{ + void *dt = NULL; + H5T_t *type = NULL; + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*siiiiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id, + trans_id, estack_id); + + /* Check arguments */ + if (H5Tcommitted(type_id)) + HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is already committed") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Get correct property list */ + if(H5P_DEFAULT == tcpl_id) + tcpl_id = H5P_DATATYPE_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(tcpl_id, H5P_DATATYPE_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype creation property list") + + /* Get correct property list */ + if(H5P_DEFAULT == tapl_id) + tapl_id = H5P_DATATYPE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(tapl_id, H5P_DATATYPE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype access property list") + + if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the object from the loc_id */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* commit the datatype through the VOL */ + if (NULL == (dt = H5VL_datatype_commit(obj, loc_params, vol_plugin, name, type_id, lcpl_id, + tcpl_id, tapl_id, dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to commit datatype") + + /* attach the vol object created using the commit call to the + library datatype structure */ + /* set the committed type object to the VOL pluging pointer in the H5T_t struct */ + type->vol_obj = dt; + + /* attach VOL information to the ID */ + if (H5I_register_aux(type_id, vol_plugin) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't attach vol info to ID") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tcommit_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Topen_ff + * + * Purpose: Opens a named datatype using a Datatype Access Property + * List. + * + * Return: Success: Object ID of the named datatype. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Topen_ff(hid_t loc_id, const char *name, hid_t tapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *vol_dt = NULL; /* datatype token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5T_t *dt = NULL; + H5VL_loc_params_t loc_params; + hid_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "i*siii", loc_id, name, tapl_id, rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == tapl_id) + tapl_id = H5P_DATATYPE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(tapl_id, H5P_DATATYPE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype access property list") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Create the datatype through the VOL */ + if(NULL == (vol_dt = H5VL_datatype_open(obj, loc_params, vol_plugin, name, tapl_id, + dxpl_id, H5_EVENT_STACK_NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open datatype"); + + /* Get an atom for the datatype */ + if ((ret_value = H5VL_create_datatype(vol_dt, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize datatype handle"); + + /* Get an atom for the datatype with the VOL information as the auxilary struct*/ + //if((ret_value = H5I_register2(H5I_DATATYPE, dt, vol_plugin, app_ref)) < 0) + //HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle") + +done: + if (ret_value < 0 && dt) + if(H5VL_datatype_close (dt, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release dataset") + FUNC_LEAVE_API(ret_value) +} /* end H5Topen_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tclose_ff + * + * Purpose: Frees a datatype and all associated memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tclose_ff(hid_t type_id, hid_t estack_id) +{ + H5T_t *dt; /* Pointer to datatype to close */ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", type_id, estack_id); + + /* Check args */ + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if(H5T_STATE_IMMUTABLE == dt->shared->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* When the reference count reaches zero the resources are freed */ + if(H5I_dec_app_ref(type_id) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tclose_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Acreate_ff + PURPOSE + Creates an attribute on an object + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +hid_t +H5Acreate_ff(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, + hid_t acpl_id, hid_t aapl_id, hid_t trans_id, hid_t estack_id) +{ + void *attr = NULL; /* attr token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("i", "i*siiiiii", loc_id, attr_name, type_id, space_id, acpl_id, + aapl_id, trans_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + + /* Get correct property list */ + if(H5P_DEFAULT == acpl_id) + acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(acpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_ATTR_TYPE_ID, &type_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for datatype id") + if(H5P_set(plist, H5VL_ATTR_SPACE_ID, &space_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for space id") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Create the attribute through the VOL */ + if(NULL == (attr = H5VL_attr_create(obj, loc_params, vol_plugin, attr_name, acpl_id, aapl_id, + dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create attribute") + + /* Get an atom for the attribute */ + if((ret_value = H5I_register2(H5I_ATTR, attr, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && attr) + if(H5VL_attr_close (attr, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Acreate_by_name_ff + PURPOSE + Creates an attribute on an object + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +hid_t +H5Acreate_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *attr = NULL; /* attr token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE10("i", "i*s*siiiiiii", loc_id, obj_name, attr_name, type_id, space_id, + acpl_id, aapl_id, lapl_id, trans_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + + /* Get correct property list */ + if(H5P_DEFAULT == acpl_id) + acpl_id = H5P_ATTRIBUTE_CREATE_DEFAULT; + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(acpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_ATTR_TYPE_ID, &type_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for datatype id") + if(H5P_set(plist, H5VL_ATTR_SPACE_ID, &space_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for space id") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.obj_type = H5I_get_type(loc_id); + loc_params.loc_data.loc_by_name.name = obj_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Create the attribute through the VOL */ + if(NULL == (attr = H5VL_attr_create(obj, loc_params, vol_plugin, attr_name, acpl_id, + aapl_id, dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create attribute") + + /* Get an atom for the attribute */ + if((ret_value = H5I_register2(H5I_ATTR, attr, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && attr) + if(H5VL_attr_close (attr, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + FUNC_LEAVE_API(ret_value) +} /* H5Acreate_by_name_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Aopen_ff + PURPOSE + Opens an attribute for an object by looking up the attribute name + RETURNS + ID of attribute on success, negative on failure +--------------------------------------------------------------------------*/ +hid_t +H5Aopen_ff(hid_t loc_id, const char *attr_name, hid_t aapl_id, + hid_t rcxt_id, hid_t estack_id) +{ + void *attr = NULL; /* attr token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "i*siii", loc_id, attr_name, aapl_id, rcxt_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Create the attribute through the VOL */ + if(NULL == (attr = H5VL_attr_open(obj, loc_params, vol_plugin, attr_name, aapl_id, dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open attribute") + + /* Get an atom for the attribute */ + if((ret_value = H5I_register2(H5I_ATTR, attr, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && attr) + if(H5VL_attr_close (attr, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + FUNC_LEAVE_API(ret_value) +} /* H5Aopen_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Aopen_by_name_ff + PURPOSE + Opens an attribute for an object by looking up the attribute name + RETURNS + ID of attribute on success, negative on failure +--------------------------------------------------------------------------*/ +hid_t +H5Aopen_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t aapl_id, hid_t lapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *attr = NULL; /* attr token from VOL plugin */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE7("i", "i*s*siiii", loc_id, obj_name, attr_name, aapl_id, lapl_id, + rcxt_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = obj_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Create the attribute through the VOL */ + if(NULL == (attr = H5VL_attr_open(obj, loc_params, vol_plugin, attr_name, aapl_id, dxpl_id, estack_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open attribute") + + /* Get an atom for the attribute */ + if((ret_value = H5I_register2(H5I_ATTR, attr, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + if (ret_value < 0 && attr) + if(H5VL_attr_close (attr, vol_plugin, H5AC_dxpl_id, estack_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") + FUNC_LEAVE_API(ret_value) +} /* H5Aopen_by_name_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Awrite_ff + PURPOSE + Write out data to an attribute + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +herr_t +H5Awrite_ff(hid_t attr_id, hid_t dtype_id, const void *buf, hid_t trans_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *attr; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "ii*xii", attr_id, dtype_id, buf, trans_id, estack_id); + + /* check arguments */ + if(NULL == buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (attr = (void *)H5I_object(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier") + + /* write the data through the VOL */ + if((ret_value = H5VL_attr_write(attr, vol_plugin, dtype_id, buf, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't read data") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Awrite_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Aread_ff + PURPOSE + Read in data from an attribute + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +herr_t +H5Aread_ff(hid_t attr_id, hid_t dtype_id, void *buf, hid_t rcxt_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *attr; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "ii*xii", attr_id, dtype_id, buf, rcxt_id, estack_id); + + /* check arguments */ + if(NULL == buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (attr = (void *)H5I_object(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier") + + /* Read the data through the VOL */ + if((ret_value = H5VL_attr_read(attr, vol_plugin, dtype_id, buf, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't read data") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aread_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Arename_ff + * + * Purpose: Rename an attribute + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Arename_ff(hid_t loc_id, const char *old_name, const char *new_name, + hid_t trans_id, hid_t estack_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "i*s*sii", loc_id, old_name, new_name, trans_id, estack_id); + + /* check arguments */ + if(!old_name || !new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil") + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + + /* Avoid thrashing things if the names are the same */ + if(HDstrcmp(old_name, new_name)) { + H5VL_t *vol_plugin; + void *obj; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* rename the attribute info through the VOL */ + if(H5VL_object_misc(obj, loc_params, vol_plugin, H5VL_ATTR_RENAME, dxpl_id, + estack_id, old_name, new_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") + } +done: + FUNC_LEAVE_API(ret_value) +} /* H5Arename_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Arename_by_name_ff + * + * Purpose: Rename an attribute + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Arename_by_name_ff(hid_t loc_id, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "i*s*s*siii", loc_id, obj_name, old_attr_name, new_attr_name, + lapl_id, trans_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") + if(!old_attr_name || !*old_attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no old attribute name") + if(!new_attr_name || !*new_attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new attribute name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* Avoid thrashing things if the names are the same */ + if(HDstrcmp(old_attr_name, new_attr_name)) { + H5VL_t *vol_plugin; + void *obj; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = obj_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* rename the attribute info through the VOL */ + if(H5VL_object_misc(obj, loc_params, vol_plugin, H5VL_ATTR_RENAME, dxpl_id, + estack_id, old_attr_name, new_attr_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Arename_by_name_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Adelete_ff + PURPOSE + Deletes an attribute from a location + RETURNS + Non-negative on success/Negative on failure +--------------------------------------------------------------------------*/ +herr_t +H5Adelete_ff(hid_t loc_id, const char *name, hid_t trans_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *obj; + H5VL_loc_params_t loc_params; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*sii", loc_id, name, trans_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + /* Open the attribute through the VOL */ + if(H5VL_attr_remove(obj, loc_params, vol_plugin, name, dxpl_id, estack_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Adelete_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Adelete_by_name_ff + PURPOSE + Deletes an attribute from a location + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + This function removes the named attribute from an object. +--------------------------------------------------------------------------*/ +herr_t +H5Adelete_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *obj; + H5VL_loc_params_t loc_params; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*s*siii", loc_id, obj_name, attr_name, lapl_id, trans_id, + estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = obj_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + /* Open the attribute through the VOL */ + if(H5VL_attr_remove(obj, loc_params, vol_plugin, attr_name, dxpl_id, estack_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Adelete_by_name_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Aexists_ff + * + * Purpose: Checks if an attribute with a given name exists on an opened + * object. + * + * Return: Success: Positive + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Aexists_ff(hid_t obj_id, const char *attr_name, hbool_t *ret, hid_t rcxt_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *obj; + H5VL_loc_params_t loc_params; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "i*s*bii", obj_id, attr_name, ret, rcxt_id, estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(obj_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (obj = (void *)H5VL_get_object(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(obj_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* get the attribute info through the VOL */ + if(H5VL_attr_get(obj, vol_plugin, H5VL_ATTR_EXISTS, dxpl_id, estack_id, + loc_params, attr_name, (htri_t *)ret) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get attribute info") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aexists_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Aexists_by_name_ff + * + * Purpose: Checks if an attribute with a given name exists on an object. + * + * Return: Success: Positive + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, November 1, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Aexists_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t lapl_id, hbool_t *ret, hid_t rcxt_id, hid_t estack_id) +{ + H5VL_t *vol_plugin; + void *obj; + H5VL_loc_params_t loc_params; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "i*s*si*bii", loc_id, obj_name, attr_name, lapl_id, ret, rcxt_id, + estack_id); + + /* check arguments */ + if(H5I_ATTR == H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") + if(!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name") + if(!attr_name || !*attr_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no attribute name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the dataset object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = obj_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* get the attribute info through the VOL */ + if(H5VL_attr_get(obj, vol_plugin, H5VL_ATTR_EXISTS, dxpl_id, estack_id, + loc_params, attr_name, (htri_t *)ret) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get attribute info") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aexists_by_name_ff() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Aclose_ff + PURPOSE + Close an attribute ID + RETURNS + Non-negative on success/Negative on failure + + DESCRIPTION + This function releases an attribute from use. Further use of the + attribute ID will result in undefined behavior. +--------------------------------------------------------------------------*/ +herr_t +H5Aclose_ff(hid_t attr_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", attr_id, estack_id); + + /* check arguments */ + if(NULL == H5I_object_verify(attr_id, H5I_ATTR)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(attr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* Decrement references to that atom (and close it) */ + if(H5I_dec_app_ref(attr_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "can't close attribute") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aclose_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lmove_ff + * + * Purpose: Renames an object within an HDF5 file and moves it to a new + * group. The original name SRC is unlinked from the group graph + * and then inserted with the new name DST (which can specify a + * new path for the object) as an atomic operation. The names + * are interpreted relative to SRC_LOC_ID and + * DST_LOC_ID, which are either file IDs or group ID. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lmove_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t lcpl_id, hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj1 = NULL; /* object token of src_id */ + H5VL_t *vol_plugin1; /* VOL plugin information */ + H5VL_loc_params_t loc_params1; + void *obj2 = NULL; /* object token of dst_id */ + H5VL_t *vol_plugin2; /* VOL plugin information */ + H5VL_loc_params_t loc_params2; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*si*siiii", src_loc_id, src_name, dst_loc_id, dst_name, + lcpl_id, lapl_id, trans_id, estack_id); + + /* Check arguments */ + if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC") + if(!src_name || !*src_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified") + if(!dst_name || !*dst_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified") + if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") + + /* Check the link create property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + /* Check the link access property list */ + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + + /* set location paramter for source object */ + loc_params1.type = H5VL_OBJECT_BY_NAME; + loc_params1.loc_data.loc_by_name.name = src_name; + loc_params1.loc_data.loc_by_name.plist_id = lapl_id; + loc_params1.obj_type = H5I_get_type(src_loc_id); + /* set location paramter for destination object */ + loc_params2.type = H5VL_OBJECT_BY_NAME; + loc_params2.loc_data.loc_by_name.name = dst_name; + loc_params2.loc_data.loc_by_name.plist_id = lapl_id; + loc_params2.obj_type = H5I_get_type(dst_loc_id); + + if(H5L_SAME_LOC != src_loc_id) { + /* get the file object */ + if(NULL == (obj1 = (void *)H5I_object(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin1 = (H5VL_t *)H5I_get_aux(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + if(H5L_SAME_LOC != dst_loc_id) { + /* get the file object */ + if(NULL == (obj2 = (void *)H5I_object(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin2 = (H5VL_t *)H5I_get_aux(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + /* Make sure that the VOL plugins are the same */ + if(H5L_SAME_LOC != dst_loc_id && H5L_SAME_LOC != src_loc_id) { + if (vol_plugin1->cls != vol_plugin2->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL plugins and can't be linked") + } + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* Move the link through the VOL */ + if((ret_value = H5VL_link_move(obj1, loc_params1, obj2, loc_params2, + (vol_plugin1!=NULL ? vol_plugin1 : vol_plugin2), + FALSE, lcpl_id, lapl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lmove_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lcopy_ff + * + * Purpose: Creates an identical copy of a link with the same creation + * time and target. The new link can have a different name + * and be in a different location than the original. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcopy_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t lcpl_id, hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj1 = NULL; /* object token of src_id */ + H5VL_t *vol_plugin1; /* VOL plugin information */ + H5VL_loc_params_t loc_params1; + void *obj2 = NULL; /* object token of dst_id */ + H5VL_t *vol_plugin2; /* VOL plugin information */ + H5VL_loc_params_t loc_params2; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*si*siiii", src_loc_id, src_name, dst_loc_id, dst_name, + lcpl_id, lapl_id, trans_id, estack_id); + + /* Check arguments */ + if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC") + if(!src_name || !*src_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified") + if(!dst_name || !*dst_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified") + if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") + + /* Check the link create property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + /* Check the link access property list */ + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + + /* set location paramter for source object */ + loc_params1.type = H5VL_OBJECT_BY_NAME; + loc_params1.loc_data.loc_by_name.name = src_name; + loc_params1.loc_data.loc_by_name.plist_id = lapl_id; + loc_params1.obj_type = H5I_get_type(src_loc_id); + /* set location paramter for destination object */ + loc_params2.type = H5VL_OBJECT_BY_NAME; + loc_params2.loc_data.loc_by_name.name = dst_name; + loc_params2.loc_data.loc_by_name.plist_id = lapl_id; + loc_params2.obj_type = H5I_get_type(dst_loc_id); + + if(H5L_SAME_LOC != src_loc_id) { + /* get the file object */ + if(NULL == (obj1 = (void *)H5I_object(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin1 = (H5VL_t *)H5I_get_aux(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + if(H5L_SAME_LOC != dst_loc_id) { + /* get the file object */ + if(NULL == (obj2 = (void *)H5I_object(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin2 = (H5VL_t *)H5I_get_aux(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + /* Make sure that the VOL plugins are the same */ + if(H5L_SAME_LOC != dst_loc_id && H5L_SAME_LOC != src_loc_id) { + if (vol_plugin1->cls != vol_plugin2->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL plugins and can't be linked") + } + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* Move the link through the VOL */ + if((ret_value = H5VL_link_move(obj1, loc_params1, obj2, loc_params2, + (vol_plugin1!=NULL ? vol_plugin1 : vol_plugin2), + TRUE, lcpl_id, lapl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lcopy_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lcreate_soft_ff + * + * Purpose: Creates a soft link from LINK_NAME to LINK_TARGET. + * + * LINK_TARGET can be anything and is interpreted at lookup + * time relative to the group which contains the final component + * of LINK_NAME. For instance, if LINK_TARGET is `./foo' and + * LINK_NAME is `./x/y/bar' and a request is made for `./x/y/bar' + * then the actual object looked up is `./x/y/./foo'. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_soft_ff(const char *link_target, hid_t link_loc_id, const char *link_name, + hid_t lcpl_id, hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5VL_loc_params_t loc_params; + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "*si*siiii", link_target, link_loc_id, link_name, lcpl_id, + lapl_id, trans_id, estack_id); + + /* Check arguments */ + if(link_loc_id == H5L_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location id should not be H5L_SAME_LOC") + if(!link_target || !*link_target) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no target specified") + if(!link_name || !*link_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified") + if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") + + /* Check the group access property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + /* Check the link access property list */ + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = link_name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(link_loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(link_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(link_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(lcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_LINK_TARGET_NAME, &link_target) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for target name") + + /* Create the link through the VOL */ + if((ret_value = H5VL_link_create(H5VL_LINK_CREATE_SOFT, obj, loc_params, vol_plugin, + lcpl_id, lapl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lcreate_soft_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lcreate_hard_ff + * + * Purpose: Creates a hard link from NEW_NAME to CUR_NAME. + * + * CUR_NAME must name an existing object. CUR_NAME and + * NEW_NAME are interpreted relative to CUR_LOC_ID and + * NEW_LOC_ID, which are either file IDs or group IDs. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_hard_ff(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, + const char *new_name, hid_t lcpl_id, hid_t lapl_id, + hid_t trans_id, hid_t estack_id) +{ + void *obj1 = NULL; /* object token of loc_id */ + void *obj2 = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin1 = NULL; /* VOL plugin information */ + H5VL_t *vol_plugin2 = NULL; /* VOL plugin information */ + H5VL_loc_params_t loc_params1; + H5VL_loc_params_t loc_params2; + H5P_genplist_t *plist; /* Property list pointer */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*si*siiii", cur_loc_id, cur_name, new_loc_id, new_name, + lcpl_id, lapl_id, trans_id, estack_id); + + /* Check arguments */ + if(cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC") + if(!cur_name || !*cur_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified") + if(!new_name || !*new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified") + if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") + + /* Check the link create property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + /* Check the link access property list */ + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + + loc_params1.type = H5VL_OBJECT_BY_NAME; + loc_params1.obj_type = H5I_get_type(cur_loc_id); + loc_params1.loc_data.loc_by_name.name = cur_name; + loc_params1.loc_data.loc_by_name.plist_id = lapl_id; + + loc_params2.type = H5VL_OBJECT_BY_NAME; + loc_params2.obj_type = H5I_get_type(new_loc_id); + loc_params2.loc_data.loc_by_name.name = new_name; + loc_params2.loc_data.loc_by_name.plist_id = lapl_id; + + if(H5L_SAME_LOC != cur_loc_id) { + /* get the file object */ + if(NULL == (obj1 = (void *)H5I_object(cur_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin1 = (H5VL_t *)H5I_get_aux(cur_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + if(H5L_SAME_LOC != new_loc_id) { + /* get the file object */ + if(NULL == (obj2 = (void *)H5I_object(new_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin2 = (H5VL_t *)H5I_get_aux(new_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + /* Make sure that the VOL plugins are the same */ + if(H5L_SAME_LOC != new_loc_id && H5L_SAME_LOC != cur_loc_id) { + if (vol_plugin1->cls != vol_plugin2->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL plugins and can't be linked") + } + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(lcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_LINK_TARGET, &obj1) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for target id") + if(H5P_set(plist, H5VL_LINK_TARGET_LOC_PARAMS, &loc_params1) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for target name") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* Create the link through the VOL */ + if((ret_value = H5VL_link_create(H5VL_LINK_CREATE_HARD, obj2, loc_params2, + (vol_plugin1!=NULL ? vol_plugin1 : vol_plugin2), + lcpl_id, lapl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lcreate_hard_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Ldelete_ff + * + * Purpose: Removes the specified NAME from the group graph and + * decrements the link count for the object to which NAME + * points. If the link count reaches zero then all file-space + * associated with the object will be reclaimed (but if the + * object is open, then the reclamation of the file space is + * delayed until all handles to the object are closed). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ldelete_ff(hid_t loc_id, const char *name, hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "i*siii", loc_id, name, lapl_id, trans_id, estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.obj_type = H5I_get_type(loc_id); + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Delete the link through the VOL */ + if((ret_value = H5VL_link_remove(obj, loc_params, vol_plugin, dxpl_id, + estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ldelete_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lexists_ff + * + * Purpose: Checks if a link of a given name exists in a group + * + * Return: Success: Positive + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lexists_ff(hid_t loc_id, const char *name, hid_t lapl_id, hbool_t *ret, + hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*si*bii", loc_id, name, lapl_id, ret, rcxt_id, estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.obj_type = H5I_get_type(loc_id); + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* check link existence through the VOL */ + if(H5VL_link_get(obj, loc_params, vol_plugin, H5VL_LINK_EXISTS, + dxpl_id, estack_id, (htri_t *)ret) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get link info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lexists_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lget_info_ff + * + * Purpose: Gets metadata for a link. + * + * Return: Success: Non-negative with information in LINFO + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lget_info_ff(hid_t loc_id, const char *name, H5L_ff_info_t *linfo , + hid_t lapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*s*xiii", loc_id, name, linfo, lapl_id, rcxt_id, estack_id); + + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.obj_type = H5I_get_type(loc_id); + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Get the link info through the VOL */ + if((ret_value = H5VL_link_get(obj, loc_params, vol_plugin, H5VL_LINK_GET_INFO, + dxpl_id, estack_id, linfo)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lget_info_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Lget_val_ff + * + * Purpose: Returns the link value of a link whose name is NAME. For + * symbolic links, this is the path to which the link points, + * including the null terminator. For user-defined links, it + * is the link buffer. + * + * At most SIZE bytes are copied to the BUF result buffer. + * + * Return: Success: Non-negative with the link value in BUF. + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lget_val_ff(hid_t loc_id, const char *name, void *buf, size_t size, + hid_t lapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "i*s*xziii", loc_id, name, buf, size, lapl_id, rcxt_id, estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.obj_type = H5I_get_type(loc_id); + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Get the link info through the VOL */ + if((ret_value = H5VL_link_get(obj, loc_params, vol_plugin, H5VL_LINK_GET_VAL, + dxpl_id, estack_id, buf, size)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get link value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lget_val_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oopen_ff + * + * Purpose: Opens an object within an HDF5 file. + * + * This function opens an object in the same way that H5Gopen2, + * H5Topen2, and H5Dopen2 do. However, H5Oopen doesn't require + * the type of object to be known beforehand. This can be + * useful in user-defined links, for instance, when only a + * path is known. + * + * The opened object should be closed again with H5Oclose + * or H5Gclose, H5Tclose, or H5Dclose. + * + * Return: Success: An open object identifier + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Oopen_ff(hid_t loc_id, const char *name, hid_t lapl_id, hid_t rcxt_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5I_type_t opened_type; + void *opened_obj = NULL; + H5VL_loc_params_t loc_params; + hid_t ret_value = FAIL; + + FUNC_ENTER_API(FAIL) + H5TRACE4("i", "i*sii", loc_id, name, lapl_id, rcxt_id); + + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Open the object through the VOL */ + if(NULL == (opened_obj = H5VL_object_open(obj, loc_params, vol_plugin, &opened_type, + dxpl_id, H5_EVENT_STACK_NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open object") + + if ((ret_value = H5VL_object_register(opened_obj, opened_type, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen_ff() */ + +/*------------------------------------------------------------------------- + * Function: H5Oget_token + * + * Purpose: This function retrieves a token representing an object in + * HDF5. This token can be used in H5Oopen_by_token(), to open the + * object in the same transaction it was created in. If the token + * buffer is NULL, the token size is returned in token_size. + * + * Return: Success: Non-negative with the link value in BUF. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_token(hid_t obj_id, void *token, size_t *token_size) +{ + H5VL_iod_object_t *obj = NULL; /* object token of loc_id */ + iod_obj_id_t iod_id, mdkv_id, attrkv_id; + H5O_type_t type; + uint8_t *buf_ptr = (uint8_t *)token; + size_t dt_size = 0, space_size = 0; + H5T_t *dt = NULL; + H5S_t *space = NULL; + size_t keytype_size = 0, valtype_size; + H5T_t *kt = NULL, *vt = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*x*z", obj_id, token, token_size); + + /* get the file object */ + if(NULL == (obj = (H5VL_iod_object_t *)H5VL_get_object(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier"); + + *token_size = sizeof(iod_obj_id_t)*3 + sizeof(H5O_type_t); + + switch(obj->obj_type) { + case H5I_GROUP: + iod_id = ((const H5VL_iod_group_t *)obj)->remote_group.iod_id; + mdkv_id = ((const H5VL_iod_group_t *)obj)->remote_group.mdkv_id; + attrkv_id = ((const H5VL_iod_group_t *)obj)->remote_group.attrkv_id; + type = H5O_TYPE_GROUP; + break; + case H5I_DATASET: + { + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)obj; + + iod_id = dset->remote_dset.iod_id; + mdkv_id = dset->remote_dset.mdkv_id; + attrkv_id = dset->remote_dset.attrkv_id; + type = H5O_TYPE_DATASET; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(dset->remote_dset.type_id, + H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a datatype") + if(NULL == (space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a dataspace") + + if(H5T_encode(dt, NULL, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + + if(H5S_encode(space, NULL, &space_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace") + + *token_size += dt_size + space_size + sizeof(size_t)*2; + + break; + } + case H5I_DATATYPE: + { + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)obj; + + iod_id = dtype->remote_dtype.iod_id; + mdkv_id = dtype->remote_dtype.mdkv_id; + attrkv_id = dtype->remote_dtype.attrkv_id; + type = H5O_TYPE_NAMED_DATATYPE; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(dtype->remote_dtype.type_id, + H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a datatype") + + if(H5T_encode(dt, NULL, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + + *token_size += dt_size + sizeof(size_t); + + break; + } + case H5I_MAP: + { + H5VL_iod_map_t *map = (H5VL_iod_map_t *)obj; + + iod_id = map->remote_map.iod_id; + mdkv_id = map->remote_map.mdkv_id; + attrkv_id = map->remote_map.attrkv_id; + type = H5O_TYPE_MAP; + + if(NULL == (kt = (H5T_t *)H5I_object_verify(map->remote_map.keytype_id, + H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a datatype") + + if(H5T_encode(kt, NULL, &keytype_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + + if(NULL == (vt = (H5T_t *)H5I_object_verify(map->remote_map.valtype_id, + H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a datatype") + + if(H5T_encode(vt, NULL, &valtype_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + + *token_size += keytype_size + valtype_size + sizeof(size_t)*2; + + break; + } + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "bad object"); + } + + if(token) { + HDmemcpy(buf_ptr, &iod_id, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(buf_ptr, &mdkv_id, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(buf_ptr, &attrkv_id, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(buf_ptr, &type, sizeof(H5O_type_t)); + buf_ptr += sizeof(H5O_type_t); + + switch(obj->obj_type) { + case H5I_GROUP: + break; + case H5I_DATASET: + HDmemcpy(buf_ptr, &dt_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5T_encode(dt, buf_ptr, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + buf_ptr += dt_size; + + HDmemcpy(buf_ptr, &space_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5S_encode(space, buf_ptr, &space_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace") + buf_ptr += space_size; + break; + case H5I_DATATYPE: + HDmemcpy(buf_ptr, &dt_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5T_encode(dt, buf_ptr, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + buf_ptr += dt_size; + break; + case H5I_MAP: + HDmemcpy(buf_ptr, &keytype_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5T_encode(kt, buf_ptr, &keytype_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + buf_ptr += keytype_size; + + HDmemcpy(buf_ptr, &valtype_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5T_encode(vt, buf_ptr, &valtype_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") + buf_ptr += valtype_size; + break; + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "bad object"); + } + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_token() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oopen_by_addr_ff + * + * Purpose: This function opens an object using its address within the + * HDF5 file, similar to an HDF5 hard link. The open object + * is identical to an object opened with H5Oopen() and should + * be closed with H5Oclose() or a type-specific closing + * function (such as H5Gclose() ). + * + * Return: Success: An open object identifier + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Oopen_by_token(const void *token, hid_t trans_id, hid_t estack_id) +{ + H5TR_t *tr = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + H5I_type_t opened_type; + void *opened_obj = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER_API(FAIL) + H5TRACE3("i", "*xii", token, trans_id, estack_id); + + if(NULL == token) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no token") + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(trans_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(NULL == (opened_obj = H5VL_iod_obj_open_token(token, tr, &opened_type, req))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open object"); + + if(request && *req) { + /* insert in stack */ + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + + vol_plugin->nrefs ++; + /* create hid_t for opened object */ + if ((ret_value = H5VL_object_register(opened_obj, opened_type, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize object handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oopen_by_addr_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Olink_ff + * + * Purpose: Creates a hard link from NEW_NAME to the object specified + * by OBJ_ID using properties defined in the Link Creation + * Property List LCPL. + * + * This function should be used to link objects that have just + * been created. + * + * NEW_NAME is interpreted relative to + * NEW_LOC_ID, which is either a file ID or a + * group ID. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Olink_ff(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, + hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj1 = NULL; /* object token of loc_id */ + void *obj2 = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin1 = NULL; /* VOL plugin information */ + H5VL_t *vol_plugin2 = NULL; /* VOL plugin information */ + H5VL_loc_params_t loc_params1; + H5VL_loc_params_t loc_params2; + H5P_genplist_t *plist; /* Property list pointer */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "ii*siiii", obj_id, new_loc_id, new_name, lcpl_id, lapl_id, + trans_id, estack_id); + + /* Check arguments */ + if(new_loc_id == H5L_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot use H5L_SAME_LOC when only one location is specified") + if(!new_name || !*new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") +/* Avoid compiler warning on 32-bit machines */ +#if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T + if(HDstrlen(new_name) > H5L_MAX_LINK_NAME_LEN) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "name too long") +#endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */ + if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list") + + /* Check the group access property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + + loc_params1.type = H5VL_OBJECT_BY_SELF; + loc_params1.obj_type = H5I_get_type(obj_id); + + loc_params2.type = H5VL_OBJECT_BY_NAME; + loc_params2.obj_type = H5I_get_type(new_loc_id); + loc_params2.loc_data.loc_by_name.name = new_name; + loc_params2.loc_data.loc_by_name.plist_id = lapl_id; + + if(H5L_SAME_LOC != obj_id) { + /* get the file object */ + if(NULL == (obj1 = (void *)H5VL_get_object(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin1 = (H5VL_t *)H5I_get_aux(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + if(H5L_SAME_LOC != new_loc_id) { + /* get the file object */ + if(NULL == (obj2 = (void *)H5VL_get_object(new_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin2 = (H5VL_t *)H5I_get_aux(new_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + } + /* Make sure that the VOL plugins are the same */ + if(H5L_SAME_LOC != new_loc_id && H5L_SAME_LOC != obj_id) { + if (vol_plugin1->cls != vol_plugin2->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL plugins and can't be linked") + } + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(lcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* set creation properties */ + if(H5P_set(plist, H5VL_LINK_TARGET, &obj1) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for target id") + if(H5P_set(plist, H5VL_LINK_TARGET_LOC_PARAMS, &loc_params1) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for target id") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* Create the link through the VOL */ + if((ret_value = H5VL_link_create(H5VL_LINK_CREATE_HARD, obj2, loc_params2, + (vol_plugin1!=NULL ? vol_plugin1 : vol_plugin2), + lcpl_id, lapl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create link") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Olink_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oexists_by_name_ff + * + * Purpose: Determine if a linked-to object exists + * + * Return: Success: TRUE/FALSE + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oexists_by_name_ff(hid_t loc_id, const char *name, hbool_t *ret, hid_t lapl_id, + hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*s*biii", loc_id, name, ret, lapl_id, rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* change the ref count through the VOL */ + if(H5VL_object_get(obj, loc_params, vol_plugin, H5VL_OBJECT_EXISTS, + dxpl_id, estack_id, (htri_t *)ret) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine if '%s' exists", name) + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oexists_by_name_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oset_comment_ff + * + * Purpose: Gives the specified object a comment. The COMMENT string + * should be a null terminated string. An object can have only + * one comment at a time. Passing NULL for the COMMENT argument + * will remove the comment property from the object. + * + * Note: Deprecated in favor of using attributes on objects + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oset_comment_ff(hid_t obj_id, const char *comment, hid_t trans_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*sii", obj_id, comment, trans_id, estack_id); + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(obj_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(obj_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* set comment on object through the VOL */ + if(H5VL_object_misc(obj, loc_params, vol_plugin, H5VL_OBJECT_SET_COMMENT, + dxpl_id, estack_id, comment) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to set comment value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oset_comment_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oset_comment_by_name_ff + * + * Purpose: Gives the specified object a comment. The COMMENT string + * should be a null terminated string. An object can have only + * one comment at a time. Passing NULL for the COMMENT argument + * will remove the comment property from the object. + * + * Note: Deprecated in favor of using attributes on objects + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oset_comment_by_name_ff(hid_t loc_id, const char *name, const char *comment, + hid_t lapl_id, hid_t trans_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*s*siii", loc_id, name, comment, lapl_id, trans_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* set comment on object through the VOL */ + if(H5VL_object_misc(obj, loc_params, vol_plugin, H5VL_OBJECT_SET_COMMENT, + dxpl_id, estack_id, comment) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to set comment value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oset_comment_by_name_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oget_comment_ff + * + * Purpose: Retrieve comment for an object. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_comment_ff(hid_t loc_id, char *comment, size_t bufsize, ssize_t *ret, + hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*sz*Zsii", loc_id, comment, bufsize, ret, rcxt_id, estack_id); + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + if(H5VL_object_get(obj, loc_params, vol_plugin, H5VL_OBJECT_GET_COMMENT, + dxpl_id, estack_id, comment, bufsize, ret) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get object comment") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_comment_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oget_comment_by_name_ff + * + * Purpose: Retrieve comment for an object. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_comment_by_name_ff(hid_t loc_id, const char *name, char *comment, size_t bufsize, + ssize_t *ret, hid_t lapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*s*sz*Zsiii", loc_id, name, comment, bufsize, ret, lapl_id, + rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + if(H5VL_object_get(obj, loc_params, vol_plugin, H5VL_OBJECT_GET_COMMENT, + dxpl_id, estack_id, comment, bufsize, ret) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get object info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_comment_by_name_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Ocopy_ff + * + * Purpose: Copy an object (group or dataset) to destination location + * within a file or cross files. PLIST_ID is a property list + * which is used to pass user options and properties to the + * copy. The name, dst_name, must not already be taken by some + * other object in the destination group. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Ocopy_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, + hid_t trans_id, hid_t estack_id) +{ + void *obj1 = NULL; /* object token of src_id */ + H5VL_t *vol_plugin1; /* VOL plugin information */ + H5VL_loc_params_t loc_params1; + void *obj2 = NULL; /* object token of dst_id */ + H5VL_t *vol_plugin2; /* VOL plugin information */ + H5VL_loc_params_t loc_params2; + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "i*si*siiii", src_loc_id, src_name, dst_loc_id, dst_name, + ocpypl_id, lcpl_id, trans_id, estack_id); + + /* Get correct property lists */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Get object copy property list */ + if(H5P_DEFAULT == ocpypl_id) + ocpypl_id = H5P_OBJECT_COPY_DEFAULT; + else + if(TRUE != H5P_isa_class(ocpypl_id, H5P_OBJECT_COPY)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object copy property list") + + /* get the object */ + if(NULL == (obj1 = (void *)H5I_object(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin1 = (H5VL_t *)H5I_get_aux(src_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src ID does not contain VOL information") + loc_params1.type = H5VL_OBJECT_BY_SELF; + loc_params1.obj_type = H5I_get_type(src_loc_id); + + /* get the object */ + if(NULL == (obj2 = (void *)H5I_object(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin2 = (H5VL_t *)H5I_get_aux(dst_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst ID does not contain VOL information") + loc_params2.type = H5VL_OBJECT_BY_SELF; + loc_params2.obj_type = H5I_get_type(dst_loc_id); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* Open the object through the VOL */ + if((ret_value = H5VL_object_copy(obj1, loc_params1, vol_plugin1, src_name, + obj2, loc_params2, vol_plugin2, dst_name, + ocpypl_id, lcpl_id, dxpl_id, estack_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to open object") +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ocopy_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oget_info_ff + * + * Purpose: Retrieve information about an object. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_info_ff(hid_t loc_id, H5O_ff_info_t *oinfo, hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*xii", loc_id, oinfo, rcxt_id, estack_id); + + /* Check args */ + if(!oinfo) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Get the group info through the VOL using the location token */ + if((ret_value = H5VL_object_get(obj, loc_params, vol_plugin, H5VL_OBJECT_GET_INFO, + dxpl_id, estack_id, oinfo)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_info_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oget_info_by_name_ff + * + * Purpose: Retrieve information about an object. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oget_info_by_name_ff(hid_t loc_id, const char *name, H5O_ff_info_t *oinfo, + hid_t lapl_id, hid_t rcxt_id, hid_t estack_id) +{ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + hid_t dxpl_id = H5P_DATASET_XFER_DEFAULT; /* transfer property list to pass to the VOL plugin */ + H5P_genplist_t *plist ; /* Property list pointer */ + H5VL_loc_params_t loc_params; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "i*s*xiii", loc_id, name, oinfo, lapl_id, rcxt_id, estack_id); + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(!oinfo) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct") + if(H5P_DEFAULT == lapl_id) + lapl_id = H5P_LINK_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID") + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = name; + loc_params.loc_data.loc_by_name.plist_id = lapl_id; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the file object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* Get the group info through the VOL using the location token */ + if((ret_value = H5VL_object_get(obj, loc_params, vol_plugin, H5VL_OBJECT_GET_INFO, + dxpl_id, estack_id, oinfo)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oget_info_by_name_ff() */ + + +/*------------------------------------------------------------------------- + * Function: H5Oclose_ff + * + * Purpose: Close an open file object. + * + * This is the companion to H5Oopen. It is used to close any + * open object in an HDF5 file (but not IDs are that not file + * objects, such as property lists and dataspaces). It has + * the same effect as calling H5Gclose, H5Dclose, or H5Tclose. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Oclose_ff(hid_t object_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", object_id, estack_id); + + /* Get the type of the object and close it in the correct way */ + switch(H5I_get_type(object_id)) { + case H5I_GROUP: + case H5I_DATATYPE: + case H5I_DATASET: + case H5I_MAP: + /* check ID */ + if(H5I_object(object_id) == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object"); + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(object_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + if(H5I_dec_app_ref(object_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object"); + break; + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, FAIL, "not a valid file object ID (dataset, group, or datatype)") + break; + } /* end switch */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Oclose_ff() */ + +herr_t +H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension, + hid_t memtype, const void *buf) +{ + hsize_t size[H5S_MAX_RANK]; + hsize_t start[H5S_MAX_RANK]; + hsize_t count[H5S_MAX_RANK]; + hsize_t stride[H5S_MAX_RANK]; + hsize_t block[H5S_MAX_RANK]; + hsize_t old_size=0; /* the size of the dimension to be extended */ + int ndims, i; /* number of dimensions in dataspace */ + hid_t space_id = FAIL; /* old File space */ + hid_t new_space_id = FAIL; /* new file space (after extension) */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts; /* number of elements in selection */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "iiIuzi*x", dset_id, dxpl_id, axis, extension, memtype, buf); + + /* check arguments */ + if(H5I_DATASET != H5I_get_type(dset_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* get the rank of this dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + if((int)axis >= ndims) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Invalid axis"); + + /* get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion sizes"); + + /* adjust the dimension size of the requested dimension, + but first record the old dimension size */ + old_size = size[axis]; + size[axis] += extension; + if(extension < old_size) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "extend size is smaller than current size of axis"); + + /* set the extent of the dataset to the new dimension */ + if(H5Dset_extent(dset_id, size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extent of dataset"); + + /* get the new dataspace of the dataset */ + if(FAIL == (new_space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* select a hyperslab corresponding to the append operation */ + for(i=0 ; i<ndims ; i++) { + start[i] = 0; + stride[i] = 1; + count[i] = size[i]; + block[i] = 1; + if(i == (int)axis) { + count[i] = extension; + start[i] = old_size; + } + } + if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + nelmts = H5Sget_select_npoints(new_space_id); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close new dataspace */ + if(new_space_id != FAIL && H5Sclose(new_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOappend */ + +herr_t +H5DOsequence(hid_t dset_id, hid_t dxpl_id, unsigned axis, hsize_t start_off, + size_t sequence, hid_t memtype, void *buf) +{ + hsize_t size[H5S_MAX_RANK]; + hsize_t start[H5S_MAX_RANK]; + hsize_t count[H5S_MAX_RANK]; + hsize_t stride[H5S_MAX_RANK]; + hsize_t block[H5S_MAX_RANK]; + int ndims, i; /* number of dimensions in dataspace */ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts; /* number of elements in selection */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE7("e", "iiIuhzi*x", dset_id, dxpl_id, axis, start_off, sequence, memtype, + buf); + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* get the rank of this dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + if((int)axis >= ndims) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Invalid axis"); + + /* get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion sizes"); + + /* select a hyperslab corresponding to the append operation */ + for(i=0 ; i<ndims ; i++) { + start[i] = 0; + stride[i] = 1; + count[i] = size[i]; + block[i] = 1; + if(i == (int)axis) { + count[i] = sequence; + start[i] = start_off; + } + } + if(FAIL == H5Sselect_hyperslab(space_id, H5S_SELECT_SET, start, stride, count, block)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + + nelmts = H5Sget_select_npoints(space_id); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Read the data */ + if(H5Dread(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOsequence */ + +herr_t H5DOset(hid_t dset_id, hid_t dxpl_id, const hsize_t coord[], + hid_t memtype, const void *buf) +{ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts = 1; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + if(FAIL == H5Sselect_elements(space_id, H5S_SELECT_SET, (size_t)nelmts, coord)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dwrite(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOset */ + +herr_t H5DOget(hid_t dset_id, hid_t dxpl_id, const hsize_t coord[], + hid_t memtype, void *buf) +{ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts = 1; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + if(FAIL == H5Sselect_elements(space_id, H5S_SELECT_SET, (size_t)nelmts, coord)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dread(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOget */ + + +herr_t H5DOappend_ff(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension, + hid_t memtype, const void *buf, hid_t trans_id, hid_t estack_id) +{ + hsize_t size[H5S_MAX_RANK]; + hsize_t start[H5S_MAX_RANK]; + hsize_t count[H5S_MAX_RANK]; + hsize_t stride[H5S_MAX_RANK]; + hsize_t block[H5S_MAX_RANK]; + hsize_t old_size=0; /* the size of the dimension to be extended */ + int ndims, i; /* number of dimensions in dataspace */ + hid_t space_id = FAIL; /* old File space */ + hid_t new_space_id = FAIL; /* new file space (after extension) */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts; /* number of elements in selection */ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* get the rank of this dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + if((int)axis >= ndims) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Invalid axis"); + + /* get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion sizes"); + + /* adjust the dimension size of the requested dimension, + but first record the old dimension size */ + old_size = size[axis]; + size[axis] += extension; + if(extension < old_size) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "extend size is smaller than current size of axis"); + + /* set the extent of the dataset to the new dimension */ + if(H5Dset_extent_ff(dset_id, size, trans_id, estack_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extent of dataset"); + + /* get the new dataspace of the dataset */ + if(FAIL == (new_space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* select a hyperslab corresponding to the append operation */ + for(i=0 ; i<ndims ; i++) { + start[i] = 0; + stride[i] = 1; + count[i] = size[i]; + block[i] = 1; + if(i == (int)axis) { + count[i] = extension; + start[i] = old_size; + } + } + if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + nelmts = H5Sget_select_npoints(new_space_id); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dwrite_ff(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf, trans_id, estack_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close new dataspace */ + if(new_space_id != FAIL && H5Sclose(new_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOappend_ff */ + +herr_t +H5DOsequence_ff(hid_t dset_id, hid_t dxpl_id, unsigned axis, hsize_t start_off, + size_t sequence, hid_t memtype, void *buf, hid_t rcxt_id, hid_t estack_id) +{ + hsize_t size[H5S_MAX_RANK]; + hsize_t start[H5S_MAX_RANK]; + hsize_t count[H5S_MAX_RANK]; + hsize_t stride[H5S_MAX_RANK]; + hsize_t block[H5S_MAX_RANK]; + int ndims, i; /* number of dimensions in dataspace */ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts; /* number of elements in selection */ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE9("e", "iiIuhzi*xii", dset_id, dxpl_id, axis, start_off, sequence, + memtype, buf, rcxt_id, estack_id); + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + /* get the rank of this dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + if((int)axis >= ndims) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Invalid axis"); + + /* get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion sizes"); + + /* select a hyperslab corresponding to the append operation */ + for(i=0 ; i<ndims ; i++) { + start[i] = 0; + stride[i] = 1; + count[i] = size[i]; + block[i] = 1; + if(i == (int)axis) { + count[i] = sequence; + start[i] = start_off; + } + } + if(FAIL == H5Sselect_hyperslab(space_id, H5S_SELECT_SET, start, stride, count, block)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + nelmts = H5Sget_select_npoints(space_id); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Read the data */ + if(H5Dread_ff(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf, rcxt_id, estack_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOsequence_ff */ + +herr_t H5DOset_ff(hid_t dset_id, hid_t dxpl_id, const hsize_t coord[], + hid_t memtype, const void *buf, hid_t trans_id, hid_t estack_id) +{ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts = 1; + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for trans_id") + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + if(FAIL == H5Sselect_elements(space_id, H5S_SELECT_SET, (size_t)nelmts, coord)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dwrite_ff(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf, trans_id, estack_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOset_ff */ + +herr_t H5DOget_ff(hid_t dset_id, hid_t dxpl_id, const hsize_t coord[], + hid_t memtype, void *buf, hid_t rcxt_id, hid_t estack_id) +{ + hid_t space_id = FAIL; /* old File space */ + hid_t mem_space_id = FAIL; /* memory space for data buffer */ + hsize_t nelmts = 1; + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + + /* check arguments */ + if(!dset_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + + /* store the transaction ID in the dxpl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + if(H5P_set(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rcxt_id") + + /* get the dataspace of the dataset */ + if(FAIL == (space_id = H5Dget_space(dset_id))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace"); + + if(FAIL == H5Sselect_elements(space_id, H5S_SELECT_SET, (size_t)nelmts, coord)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTSET, FAIL, "unable to set selection in dataspace"); + + /* create a memory space */ + mem_space_id = H5Screate_simple(1, &nelmts, NULL); + + /* Write the data */ + if(H5Dread_ff(dset_id, memtype, mem_space_id, space_id, dxpl_id, buf, rcxt_id, estack_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") +done: + + /* close old dataspace */ + if(space_id != FAIL && H5Sclose(space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + /* close memory dataspace */ + if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "unable to close dataspace") + + FUNC_LEAVE_API(ret_value) +}/* end H5DOget_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Dprefetch + * + * Purpose: Prefetched a Dataset from Central Storage to Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Dprefetch(hid_t dset_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t dapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *dset = NULL; /* pointer to dset object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (dset = (void *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == dapl_id) + dapl_id = H5P_DATASET_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_prefetch(dset, rcxt_id, replica_id, dapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't prefetch dataset") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Dprefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5Devict + * + * Purpose: Evicts a Dataset from Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Devict(hid_t dset_id, uint64_t c_version, hid_t dapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generated request pointer */ + void *dset = NULL; /* pointer to dset object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (dset = (void *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dset_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == dapl_id) + dapl_id = H5P_DATASET_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(dapl_id, H5P_DATASET_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_evict(dset, c_version, dapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't evict dataset") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Devict() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gprefetch + * + * Purpose: Prefetched a Group from Central Storage to Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Gprefetch(hid_t grp_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t gapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *grp = NULL; /* pointer to grp object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (grp = (void *)H5I_object_verify(grp_id, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(grp_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == gapl_id) + gapl_id = H5P_GROUP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(gapl_id, H5P_GROUP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_prefetch(grp, rcxt_id, replica_id, gapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't prefetch group") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gprefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gevict + * + * Purpose: Evicts a Group from Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Gevict(hid_t grp_id, uint64_t c_version, hid_t gapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generated request pointer */ + void *grp = NULL; /* pointer to grp object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (grp = (void *)H5I_object_verify(grp_id, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(grp_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == gapl_id) + gapl_id = H5P_GROUP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(gapl_id, H5P_GROUP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_evict(grp, c_version, gapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't evict group") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gevict() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tprefetch + * + * Purpose: Prefetched a Datatype from Central Storage to Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Tprefetch(hid_t dtype_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t tapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *dtype = NULL; /* pointer to dtype object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + H5T_t *type; /* Datatype object for ID */ + htri_t status; /* Generic status value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check arguments */ + if(NULL == (type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + /* Check if the datatype is committed */ + if((status = H5T_committed(type)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't check whether datatype is committed") + + if(FALSE == status) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't prefetch a non committed datatype"); + } + + /* Get correct property list */ + if(H5P_DEFAULT == tapl_id) + tapl_id = H5P_DATATYPE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(tapl_id, H5P_DATATYPE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype access property list") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dtype_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* get the named datatype object */ + if(NULL == (dtype = H5VL_get_object(dtype_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_prefetch(dtype, rcxt_id, replica_id, tapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't prefetch datatype") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tprefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tevict + * + * Purpose: Evicts a Datatype from Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Tevict(hid_t dtype_id, uint64_t c_version, hid_t tapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *dtype = NULL; /* pointer to dtype object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + H5T_t *type; /* Datatype object for ID */ + htri_t status; /* Generic status value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* Check arguments */ + if(NULL == (type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + /* Check if the datatype is committed */ + if((status = H5T_committed(type)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't check whether datatype is committed") + + if(FALSE == status) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't prefetch a non committed datatype"); + } + + /* Get correct property list */ + if(H5P_DEFAULT == tapl_id) + tapl_id = H5P_DATATYPE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(tapl_id, H5P_DATATYPE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype access property list") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(dtype_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* get the named datatype object */ + if(NULL == (dtype = H5VL_get_object(dtype_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_evict(dtype, c_version, tapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't evict datatype") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tevict() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5FFprivate.h b/src/H5FFprivate.h new file mode 100644 index 0000000..081ccca --- /dev/null +++ b/src/H5FFprivate.h @@ -0,0 +1,60 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5FF module + */ +#ifndef _H5FFprivate_H +#define _H5FFprivate_H + +/* Include package's public header */ +#include "H5FFpublic.h" + +/* Private headers needed by this file */ +#include "H5private.h" /* Generic Functions */ + + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/* DXPL property to store the transaction ID from the FF wrappers */ +#define H5VL_TRANS_ID "transaction_id" + +/* DXPL property to store the read context ID from the FF wrappers */ +#define H5VL_CONTEXT_ID "read_context_id" + +/* property to tell the VOL plugin to acquire a read context on the + container when the file is opened */ +#define H5VL_ACQUIRE_RC_ID "acquire_version" + +/* property to determine the scope of data integrity checks in the FF stack */ +#define H5VL_CS_BITFLAG_NAME "checksum_bitflag" + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/******************************/ +/* Library Private Prototypes */ +/******************************/ + +#endif /* _H5FFprivate_H */ + diff --git a/src/H5FFpublic.h b/src/H5FFpublic.h new file mode 100644 index 0000000..083409d --- /dev/null +++ b/src/H5FFpublic.h @@ -0,0 +1,226 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5FF module. + */ +#ifndef _H5FFpublic_H +#define _H5FFpublic_H + +/* System headers needed by this file */ + +/* Public headers needed by this file */ +#include "H5VLpublic.h" /* Public VOL header file */ + +/*****************/ +/* Public Macros */ +/*****************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef H5_HAVE_EFF + +typedef uint64_t haddr_ff_t; + +/*******************/ +/* Public Typedefs */ +/*******************/ + +typedef struct H5L_ff_info_t{ + H5L_type_t type; + H5T_cset_t cset; + union { + haddr_ff_t address; + size_t val_size; + } u; +} H5L_ff_info_t; + +typedef struct H5O_ff_info_t { + haddr_ff_t addr; /* Object address in file */ + H5O_type_t type; /* Basic object type */ + unsigned rc; /* Reference count of object */ + hsize_t num_attrs; /* # of attributes attached to object */ +} H5O_ff_info_t; + +/* Bitflag values to enable/disable checksuming in different layers */ +typedef enum H5FF_checksum_bitflag_t { + H5_CHECKSUM_NONE = 0x00, + H5_CHECKSUM_TRANSFER = 0x01, + H5_CHECKSUM_IOD = 0x02, + H5_CHECKSUM_MEMORY = 0x04, + H5_CHECKSUM_ALL = 0x07 +} H5FF_checksum_bitflag_t; + +/********************/ +/* Public Variables */ +/********************/ + +/*********************/ +/* Public Prototypes */ +/*********************/ + +/* API wrappers */ +H5_DLL hid_t H5Fcreate_ff(const char *filename, unsigned flags, hid_t fcpl, + hid_t fapl, hid_t estack_id); +H5_DLL hid_t H5Fopen_ff(const char *filename, unsigned flags, hid_t fapl_id, + hid_t *rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Fclose_ff(hid_t file_id, hid_t estack_id); + +H5_DLL hid_t H5Gcreate_ff(hid_t loc_id, const char *name, hid_t lcpl_id, + hid_t gcpl_id, hid_t gapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Gopen_ff(hid_t loc_id, const char *name, hid_t gapl_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Gclose_ff(hid_t group_id, hid_t estack_id); + +H5_DLL hid_t H5Dcreate_ff(hid_t loc_id, const char *name, hid_t type_id, + hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Dopen_ff(hid_t loc_id, const char *name, hid_t dapl_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Dwrite_ff(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, const void *buf, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Dread_ff(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, void *buf/*out*/, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Dset_extent_ff(hid_t dset_id, const hsize_t size[], hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Dclose_ff(hid_t dset_id, hid_t estack_id); + +H5_DLL herr_t H5Tcommit_ff(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id, + hid_t tcpl_id, hid_t tapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Topen_ff(hid_t loc_id, const char *name, hid_t tapl_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Tclose_ff(hid_t type_id, hid_t estack_id); + +H5_DLL hid_t H5Acreate_ff(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id, + hid_t acpl_id, hid_t aapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Acreate_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id, + hid_t lapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Aopen_ff(hid_t loc_id, const char *attr_name, hid_t aapl_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL hid_t H5Aopen_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t aapl_id, hid_t lapl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Awrite_ff(hid_t attr_id, hid_t dtype_id, const void *buf, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Aread_ff(hid_t attr_id, hid_t dtype_id, void *buf, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Arename_ff(hid_t loc_id, const char *old_name, const char *new_name, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Arename_by_name_ff(hid_t loc_id, const char *obj_name, const char *old_attr_name, + const char *new_attr_name, hid_t lapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Adelete_ff(hid_t loc_id, const char *name, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Adelete_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t lapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Aexists_by_name_ff(hid_t loc_id, const char *obj_name, const char *attr_name, + hid_t lapl_id, hbool_t *ret, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Aexists_ff(hid_t obj_id, const char *attr_name, hbool_t *ret, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Aclose_ff(hid_t attr_id, hid_t estack_id); + +H5_DLL herr_t H5Lmove_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t lcpl_id, hid_t lapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Lcopy_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t lcpl_id, hid_t lapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Lcreate_soft_ff(const char *link_target, hid_t link_loc_id, const char *link_name, + hid_t lcpl_id, hid_t lapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Lcreate_hard_ff(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, + const char *new_name, hid_t lcpl_id, hid_t lapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Ldelete_ff(hid_t loc_id, const char *name, hid_t lapl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Lexists_ff(hid_t loc_id, const char *name, hid_t lapl_id, hbool_t *ret, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Lget_info_ff(hid_t link_loc_id, const char *link_name, H5L_ff_info_t *link_buff, + hid_t lapl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Lget_val_ff(hid_t link_loc_id, const char *link_name, void *linkval_buff, + size_t size, hid_t lapl_id, hid_t rcxt_id, hid_t estack_id); + +H5_DLL hid_t H5Oopen_ff(hid_t loc_id, const char *name, hid_t lapl_id, + hid_t rcxt_id); +H5_DLL herr_t H5Oget_token(hid_t obj_id, void *token, size_t *token_size); +H5_DLL hid_t H5Oopen_by_token(const void *token, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Olink_ff(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id, + hid_t lapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Oexists_by_name_ff(hid_t loc_id, const char *name, hbool_t *ret, + hid_t lapl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Oset_comment_ff(hid_t obj_id, const char *comment, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Oset_comment_by_name_ff(hid_t loc_id, const char *name, const char *comment, + hid_t lapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Oget_comment_ff(hid_t loc_id, char *comment, size_t bufsize, ssize_t *ret, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Oget_comment_by_name_ff(hid_t loc_id, const char *name, char *comment, size_t bufsize, + ssize_t *ret, hid_t lapl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Ocopy_ff(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, + const char *dst_name, hid_t ocpypl_id, hid_t lcpl_id, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Oget_info_ff(hid_t object_id, H5O_ff_info_t *object_info, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Oget_info_by_name_ff(hid_t loc_id, const char *object_name, + H5O_ff_info_t *object_info, hid_t lapl_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Oclose_ff(hid_t object_id, hid_t estack_id); + +#if 0 +H5_DLL herr_t H5Aprefetch(hid_t attr_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t aapl_id, hid_t estack_id); +H5_DLL herr_t H5Aevict(hid_t attr_id, uint64_t c_version, hid_t aapl_id, hid_t estack_id); +#endif + +H5_DLL herr_t H5Gprefetch(hid_t grp_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t gapl_id, hid_t estack_id); +H5_DLL herr_t H5Tprefetch(hid_t type_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t tapl_id, hid_t estack_id); +H5_DLL herr_t H5Dprefetch(hid_t dset_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t dapl_id, hid_t estack_id); +H5_DLL herr_t H5Mprefetch(hid_t map_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t mapl_id, hid_t estack_id); + +H5_DLL herr_t H5Devict(hid_t dset_id, uint64_t c_version, hid_t dapl_id, hid_t estack_id); +H5_DLL herr_t H5Mevict(hid_t map_id, uint64_t c_version, hid_t mapl_id, hid_t estack_id); +H5_DLL herr_t H5Gevict(hid_t grp_id, uint64_t c_version, hid_t gapl_id, hid_t estack_id); +H5_DLL herr_t H5Tevict(hid_t type_id, uint64_t c_version, hid_t tapl_id, hid_t estack_id); + +/* New Routines for Dynamic Data Structures Use Case (ACG) */ +H5_DLL herr_t H5DOappend(hid_t dataset_id, hid_t dxpl_id, unsigned axis, size_t extension, + hid_t memtype, const void *buffer); +H5_DLL herr_t H5DOappend_ff(hid_t dataset_id, hid_t dxpl_id, unsigned axis, size_t extension, + hid_t memtype, const void *buffer, hid_t trans_id, + hid_t estack_id); +H5_DLL herr_t H5DOsequence(hid_t dataset_id, hid_t dxpl_id, unsigned axis, hsize_t start, + size_t sequence, hid_t memtype, void *buffer); +H5_DLL herr_t H5DOsequence_ff(hid_t dataset_id, hid_t dxpl_id, unsigned axis, hsize_t start, + size_t sequence, hid_t memtype, void *buffer, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5DOset(hid_t dataset_id, hid_t dxpl_id, const hsize_t coord[], + hid_t memtype, const void *buffer); +H5_DLL herr_t H5DOset_ff(hid_t dataset_id, hid_t dxpl_id, const hsize_t coord[],hid_t memtype, + const void *buffer, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5DOget(hid_t dataset_id, hid_t dxpl_id, const hsize_t coord[],hid_t memtype, void *buffer); +H5_DLL herr_t H5DOget_ff(hid_t dataset_id, hid_t dxpl_id, const hsize_t coord[],hid_t memtype, + void *buffer, hid_t rcxt_id, hid_t estack_id); + +#endif /* H5_HAVE_EFF */ + +#ifdef __cplusplus +} +#endif + +#endif /* _H5FFpublic_H */ + diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 556712f..d149306 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -36,7 +36,7 @@ /* Private headers needed by this file */ /* Macros for turning off free lists in the library */ -/*#define H5_NO_FREE_LISTS*/ +#define H5_NO_FREE_LISTS #if defined H5_NO_FREE_LISTS || defined H5_USING_MEMCHECKER #define H5_NO_REG_FREE_LISTS #define H5_NO_ARR_FREE_LISTS @@ -324,7 +324,8 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t g HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") /* Create the group through the VOL */ - if(NULL == (grp = H5VL_group_create(obj, loc_params, vol_plugin, name, gcpl_id, gapl_id, H5AC_dxpl_id, H5_EVENT_STACK_NULL))) + if(NULL == (grp = H5VL_group_create(obj, loc_params, vol_plugin, name, gcpl_id, gapl_id, + H5AC_dxpl_id, H5_EVENT_STACK_NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group") /* Get an atom for the group */ @@ -728,6 +729,7 @@ done: herr_t H5Gclose(hid_t group_id) { + H5VL_t *vol_plugin = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -737,6 +739,13 @@ H5Gclose(hid_t group_id) if(NULL == H5I_object_verify(group_id,H5I_GROUP)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(group_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = H5_EVENT_STACK_NULL; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + /* * Decrement the counter on the group atom. It will be freed if the count * reaches zero. @@ -776,7 +785,8 @@ H5G_close_group(void *grp, H5VL_t *vol_plugin) FUNC_ENTER_NOAPI_NOINIT /* Close the group through the VOL*/ - if((ret_value = H5VL_group_close(grp, vol_plugin, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_group_close(grp, vol_plugin, vol_plugin->close_dxpl_id, + vol_plugin->close_estack_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to close group") done: diff --git a/src/H5Gloc.c b/src/H5Gloc.c index 2a83f15..0239c92 100644 --- a/src/H5Gloc.c +++ b/src/H5Gloc.c @@ -180,7 +180,7 @@ H5G_loc_real(void *obj, H5I_type_t type, H5G_loc_t *loc) /* Get the actual datatype object if the VOL object is set */ if(NULL == (dt = (H5T_t *)H5T_get_named_type((const H5T_t *)obj))) dt = (H5T_t *) obj; - + if(NULL == (loc->oloc = H5T_oloc(dt))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of datatype") if(NULL == (loc->path = H5T_nameof(dt))) @@ -52,6 +52,7 @@ #include "H5SLprivate.h" /* Skip Lists */ #include "H5Tprivate.h" /* Datatypes */ #include "H5VLprivate.h" /* Virtual Object Layer */ +#include "H5VLiod_client.h" /* Client IOD helper */ #include "H5Fpkg.h" /* MSC- just a temp workaround FILES*/ @@ -2147,6 +2148,7 @@ H5Iiterate(H5I_type_t type, H5I_iterate_func_t op, void *op_data) herr_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) + H5TRACE3("e", "Itx*x", type, op, op_data); /* Set up udata struct */ int_udata.op = op; diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 4c3457c..325643a 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -89,5 +89,6 @@ H5_DLL herr_t H5I_dec_type_ref(H5I_type_t type); H5_DLL herr_t H5I_register_aux(hid_t id, void *aux_ptr); H5_DLL void *H5I_get_aux(hid_t id); H5_DLL hid_t H5I_get_id(void *object, H5I_type_t type); + #endif /* _H5Iprivate_H */ diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 0df96f1..309892c 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -38,6 +38,7 @@ typedef enum H5I_type_t { H5I_BADID = (-1), /*invalid Type */ H5I_FILE = 1, /*type ID for File objects */ H5I_GROUP, /*type ID for Group objects */ + H5I_MAP, /*type ID for MAP objects */ H5I_DATATYPE, /*type ID for Datatype objects */ H5I_DATASPACE, /*type ID for Dataspace objects */ H5I_DATASET, /*type ID for Dataset objects */ @@ -45,6 +46,11 @@ typedef enum H5I_type_t { H5I_REFERENCE, /*type ID for Reference objects */ H5I_VFL, /*type ID for virtual file layer */ H5I_VOL, /*type ID for virtual object layer */ + H5I_ES, /*type ID for Event Queue objects */ + H5I_RC, /*type ID for Read Context objects */ + H5I_TR, /*type ID for Transaction objects */ + H5I_QUERY, /*type ID for Query objects */ + H5I_VIEW, /*type ID for view objects */ H5I_GENPROP_CLS, /*type ID for generic property list classes */ H5I_GENPROP_LST, /*type ID for generic property lists */ H5I_ERROR_CLASS, /*type ID for error classes */ diff --git a/src/H5M.c b/src/H5M.c new file mode 100644 index 0000000..70f2d6c --- /dev/null +++ b/src/H5M.c @@ -0,0 +1,1073 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5M_init_interface + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Lprivate.h" /* Links */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod_client.h" /* IOD VOL plugin */ + +#ifdef H5_HAVE_EFF + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5M_close_map(void *map, H5VL_t *vol_plugin); + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +/* MAP ID class */ +static const H5I_class_t H5I_MAP_CLS[1] = {{ + H5I_MAP, /* ID class value */ + 0, /* Class flags */ + 0, /* # of reserved IDs for class */ + NULL, /* Callback routine for closing objects of this class */ + (H5I_free2_t)H5M_close_map /* Callback routine for closing auxilary objects of this class */ +}}; + + +/*------------------------------------------------------------------------- + * Function: H5M_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5M_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M_init() */ + + +/*-------------------------------------------------------------------------- +NAME + H5M_init_interface -- Initialize interface-specific information +USAGE + herr_t H5M_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5M_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Create attribute ID type. + */ + if(H5I_register_type(H5I_MAP_CLS) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M_init_interface() */ + + +/*-------------------------------------------------------------------------- + NAME + H5M_term_interface + PURPOSE + Terminate various H5M objects + USAGE + void H5M_term_interface() + RETURNS + DESCRIPTION + Release any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5M_term_interface(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + if((n = H5I_nmembers(H5I_MAP))>0) { + (void)H5I_clear_type(H5I_MAP, FALSE, FALSE); + } else { + (void)H5I_dec_type_ref(H5I_MAP); + H5_interface_initialize_g = 0; + n = 1; + } + } + FUNC_LEAVE_NOAPI(n) +} /* H5M_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Mcreate_ff + * + * Purpose: + * The H5Mcreate routine creates a new map object named name + * at the location given by loc_id. Map creation and access property + * lists (mcpl_id and mapl_id) modify the new map objectÕs behavior. + * All keys for the map are of keytype datatype and all values for the + * map are of valtype datatype. The H5Mcreate_ff routine is identical + * in functionality, but allows for asynchronous operation and + * inclusion in a transaction. Map IDs returned from this routine + * must be released with H5Mclose. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mcreate_ff(hid_t loc_id, const char *name, hid_t keytype, hid_t valtype, + hid_t lcpl_id, hid_t mcpl_id, hid_t mapl_id, hid_t trans_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + H5VL_loc_params_t loc_params; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE9("i", "i*siiiiiii", loc_id, name, keytype, valtype, lcpl_id, mcpl_id, + mapl_id, trans_id, estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Get correct property list */ + if(H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list") + + /* Check map creation property list */ + if(H5P_DEFAULT == mcpl_id) + mcpl_id = H5P_MAP_CREATE_DEFAULT; + else + if(TRUE != H5P_isa_class(mcpl_id, H5P_MAP_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group create property list") + + /* Check the group access property list */ + if(H5P_DEFAULT == mapl_id) + mapl_id = H5P_MAP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(mapl_id, H5P_MAP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object/file identifier") + /* get the plugin pointer */ + if(NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + if(vol_plugin->cls->value != IOD) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "only IOD plugin supports MAP objects") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* call the IOD specific private routine to create a map object */ + if(NULL == (map = H5VL_iod_map_create(obj, loc_params, name, keytype, valtype, + lcpl_id, mcpl_id, mapl_id, trans_id, req))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create map") + + /* increment the ref count on the VOL plugin */ + vol_plugin->nrefs ++; + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack") + } + + /* Get an atom for the map */ + if((ret_value = H5I_register2(H5I_MAP, map, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize map handle") + +done: + if (ret_value < 0 && map) + if(H5VL_iod_map_close (map, req) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release map") + FUNC_LEAVE_API(ret_value) +} /* end H5Mcreate_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mopen_ff + * + * Purpose: + * The H5Mopen routine opens an existing map object named + * name at the location given by loc_id. The map access property list + * (mapl_id) modifies the map objectÕs behavior. The H5Mopen_ff + * routine is identical in functionality, but allows for asynchronous + * operation and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Mopen_ff(hid_t loc_id, const char *name, hid_t mapl_id, hid_t rcxt_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + void *obj = NULL; /* object token of loc_id */ + H5VL_t *vol_plugin; /* VOL plugin information */ + H5VL_loc_params_t loc_params; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE5("i", "i*siii", loc_id, name, mapl_id, rcxt_id, estack_id); + + /* Check arguments */ + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Check the group access property list */ + if(H5P_DEFAULT == mapl_id) + mapl_id = H5P_MAP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(mapl_id, H5P_MAP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") + + loc_params.type = H5VL_OBJECT_BY_SELF; + loc_params.obj_type = H5I_get_type(loc_id); + + /* get the object */ + if(NULL == (obj = (void *)H5VL_get_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object/file identifier") + /* get the plugin pointer */ + if(NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(vol_plugin->cls->value != IOD) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "only IOD plugin supports MAP objects"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* call the IOD specific private routine to create a map object */ + if(NULL == (map = H5VL_iod_map_open(obj, loc_params, name, mapl_id, rcxt_id, req))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create map") + + /* increment the ref count on the VOL plugin */ + vol_plugin->nrefs ++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack") + } + + /* Get an atom for the map */ + if((ret_value = H5I_register2(H5I_MAP, map, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize map handle") + +done: + if (ret_value < 0 && map) + if(H5VL_iod_map_close (map, req) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release map") + FUNC_LEAVE_API(ret_value) +} /* end H5Mopen_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mset_ff + * + * Purpose: + * The H5Mset routine inserts or sets a key/value pair in a + * map object, given by map_id. The key (pointed to by key) is of + * type key_mem_type_id in memory and the value (pointed to by value) + * is of type value_mem_type_id in memory. The data transfer property + * list (dxpl_id) may modify the operationÕs behavior. The H5Mset_ff + * routine is identical in functionality, but allows for asynchronous + * operation and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mset_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + const void *value, hid_t dxpl_id, hid_t trans_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "ii*xi*xiii", map_id, key_mem_type_id, key, val_mem_type_id, + value, dxpl_id, trans_id, estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* Get the default map transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Set the data through the IOD VOL */ + if((ret_value = H5VL_iod_map_set(map, key_mem_type_id, key, val_mem_type_id, value, + dxpl_id, trans_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set map KV pair") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mset_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mget_ff + * + * Purpose: + * The H5Mget routine retrieves a value from a map object, + * given by map_id. The key value used to retrieve the value (pointed + * to by key) is of type key_mem_type_id in memory and the value + * (pointed to by value) is of type value_mem_type_id in memory. The + * data transfer property list (dxpl_id) may modify the operationÕs + * behavior. The H5Mget_ff routine is identical in functionality, but + * allows for asynchronous operation and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mget_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + void *value, hid_t dxpl_id, hid_t rcxt_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE8("e", "ii*xi*xiii", map_id, key_mem_type_id, key, val_mem_type_id, + value, dxpl_id, rcxt_id, estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id= H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_map_get(map, key_mem_type_id, key, val_mem_type_id, value, + dxpl_id, rcxt_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get map value") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mget_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mget_types_ff + * + * Purpose: + * The H5Mget_types routine retrieves the datatypes for the + * keys and values of a map, given by map_id. The key datatype is + * returned in key_type_id and the value datatype is returned in + * value_type_id. The H5Mget_types_ff routine is identical in + * functionality, but allows for asynchronous operation and inclusion + * in a transaction. Either (or both) of the datatype ID pointers may + * be NULL, if that datatype information is not desired. Any datatype + * IDs returned from this routine must be released with H5Tclose. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mget_types_ff(hid_t map_id, hid_t *key_type_id, hid_t *val_type_id, + hid_t rcxt_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "i*i*iii", map_id, key_type_id, val_type_id, rcxt_id, estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_map_get_types(map, key_type_id, val_type_id, rcxt_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get map value") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mget_types_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mget_count_ff + * + * Purpose: + * The H5Mget_count routine retrieves the number of key/value + * pairs in a map, given by map_id. The H5Mget_count_ff routine is + * identical in functionality, but allows for asynchronous operation + * and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mget_count_ff(hid_t map_id, hsize_t *count, hid_t rcxt_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*hii", map_id, count, rcxt_id, estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_map_get_count(map, count, rcxt_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get map value") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mget_count_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mexists_ff + * + * Purpose: + * The H5Mexists routine checks if a key exists in a map, + * given by map_id. The key value used (pointed to by key) is of type + * key_mem_type_id in memory and the status of the key in the map is + * returned in the exists pointerÕs value. The H5Mexists_ff routine is + * identical in functionality, but allows for asynchronous operation + * and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mexists_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, + hbool_t *exists, hid_t rcxt_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "ii*x*bii", map_id, key_mem_type_id, key, exists, rcxt_id, + estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_map_exists(map, key_mem_type_id, key, exists, rcxt_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get map value") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mexists_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Miterate_ff + * + * Purpose: + * The H5Miterate routine iterates over the key/value pairs + * in a map, given by map_id. The user-defined callback routine, given + * by callback_func, defined below, will be invoked for each key/value + * pair in the map: + * + * typedef int (*H5M_iterate_func_t)(const void *key, const void *value, void *context); + * + * Keys and values presented to the + * callback routine will be in key_mem_type_id and value_mem_type_id + * format, respectively. Additional information may be given to the + * callback routine with the context parameter, which is passed + * unmodified from the call to H5Miterate to the applicationÕs + * callback. The iteration callback routine should obey the same rules + * as other HDF5 iteration callbacks: return H5_ITER_ERROR for an error + * condition (which will stop iteration), H5_ITER_CONT for success + * (with continued iteration) and H5_ITER_STOP for success (but stop + * iteration). + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Miterate_ff(hid_t map_id, hid_t key_mem_type_id, hid_t value_mem_type_id, + H5M_iterate_func_t callback_func, void *context, hid_t rcxt_id) +{ + //void *map = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "iiix*xi", map_id, key_mem_type_id, value_mem_type_id, + callback_func, context, rcxt_id); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Miterate */ + + +/*------------------------------------------------------------------------- + * Function: H5Mdelete_ff + * + * Purpose: + * The H5Mdelete routine removes a key/value pair from a map, + * given by map_id. The key value used (pointed to by key) is of type + * key_mem_type_id in. The H5Mdelete_ff routine is identical in + * functionality, but allows for asynchronous operation and inclusion + * in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mdelete_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, + hid_t trans_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object created */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "ii*xii", map_id, key_mem_type_id, key, trans_id, estack_id); + + /* check arguments */ + if(!map_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* delete the key pair through the IOD VOL */ + if((ret_value = H5VL_iod_map_delete(map, key_mem_type_id, key, trans_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get map value") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mdelete_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5Mclose_ff + * + * Purpose: + * The H5Mclose routine terminates access to a map, given by + * map_id. The H5Mclose_ff routine is identical in functionality, but + * allows for asynchronous operation and inclusion in a transaction. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Mclose_ff(hid_t map_id, hid_t estack_id) +{ + H5VL_t *vol_plugin = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", map_id, estack_id); + + /* Check args */ + if(NULL == H5I_object_verify(map_id, H5I_MAP)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a map") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = estack_id; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + + /* + * Decrement the counter on the group atom. It will be freed if the count + * reaches zero. + */ + if(H5I_dec_app_ref(map_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close map") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mclose_ff */ + + +/*------------------------------------------------------------------------- + * Function: H5M_close_map + * + * Purpose: Called when the ref count reaches zero on the map_id + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5M_close_map(void *map, H5VL_t *vol_plugin) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(vol_plugin->close_estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Close the map through the VOL*/ + if(H5VL_iod_map_close(map, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to close map") + + if(request && *req) { + if(H5ES_insert(vol_plugin->close_estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + + vol_plugin->nrefs --; + if (0 == vol_plugin->nrefs) { + vol_plugin->container_name = (const char *)H5MM_xfree(vol_plugin->container_name); + vol_plugin = (H5VL_t *)H5MM_xfree(vol_plugin); + } +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5M_close_map() */ + + +/*------------------------------------------------------------------------- + * Function: H5Mprefetch + * + * Purpose: Prefetched a Map from Central Storage to Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Mprefetch(hid_t map_id, hid_t rcxt_id, hrpl_t *replica_id, + hid_t mapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *map = NULL; /* pointer to map object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == mapl_id) + mapl_id = H5P_MAP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(mapl_id, H5P_MAP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not map access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_prefetch(map, rcxt_id, replica_id, mapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't prefetch map") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mprefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5Mevict + * + * Purpose: Evicts a Map from Burst Buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +H5_DLL herr_t H5Mevict(hid_t map_id, uint64_t c_version, hid_t mapl_id, hid_t estack_id) +{ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generated request pointer */ + void *map = NULL; /* pointer to map object */ + H5VL_t *vol_plugin; /* VOL plugin information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + + /* get the map object */ + if(NULL == (map = (void *)H5I_object_verify(map_id, H5I_MAP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid map identifier") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(map_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == mapl_id) + mapl_id = H5P_MAP_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(mapl_id, H5P_MAP_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not map access property list") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* Get the data through the IOD VOL */ + if((ret_value = H5VL_iod_evict(map, c_version, mapl_id, req)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't evict map") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Mevict() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5Mpublic.h b/src/H5Mpublic.h new file mode 100644 index 0000000..4a8b8a2 --- /dev/null +++ b/src/H5Mpublic.h @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5M module. + */ +#ifndef _H5Mpublic_H +#define _H5Mpublic_H + +/* System headers needed by this file */ + +/* Public headers needed by this file */ +#include "H5public.h" +#include "H5Ipublic.h" + +/*****************/ +/* Public Macros */ +/*****************/ + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/********************/ +/* Public Variables */ +/********************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Typedef for H5Miterate() callbacks */ +typedef herr_t (*H5M_iterate_func_t)(const void *key, const void *value, void *context); + +/*********************/ +/* Public Prototypes */ +/*********************/ + +/* API wrappers */ +H5_DLL hid_t H5Mcreate_ff(hid_t loc_id, const char *name, hid_t keytype, hid_t valtype, hid_t lcpl_id, + hid_t mcpl_id, hid_t mapl_id, hid_t trans_id, hid_t estack_id); +H5_DLL hid_t H5Mopen_ff(hid_t loc_id, const char *name, hid_t mapl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Mset_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + const void *value, hid_t dxpl_id, hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Mget_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, hid_t val_mem_type_id, + void *value, hid_t dxpl_id, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Mget_types_ff(hid_t map_id, hid_t *key_type_id, hid_t *val_type_id, + hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Mget_count_ff(hid_t map_id, hsize_t *count, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Mexists_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, + hbool_t *exists, hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5Miterate_ff(hid_t map_id, hid_t key_mem_type_id, hid_t value_mem_type_id, + H5M_iterate_func_t callback_func, void *context, hid_t rcxt_id); +H5_DLL herr_t H5Mdelete_ff(hid_t map_id, hid_t key_mem_type_id, const void *key, + hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5Mclose_ff(hid_t map_id, hid_t estack_id); + +#ifdef __cplusplus +} +#endif +#endif /* _H5Mpublic_H */ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index a7d386a..d21aff8 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -85,6 +85,7 @@ typedef enum H5O_type_t { H5O_TYPE_GROUP, /* Object is a group */ H5O_TYPE_DATASET, /* Object is a dataset */ H5O_TYPE_NAMED_DATATYPE, /* Object is a named data type */ + H5O_TYPE_MAP, /* Object is a map */ H5O_TYPE_NTYPES /* Number of different object types (must be last!) */ } H5O_type_t; diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index acd48af..550badb 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -43,6 +43,9 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ #include "H5Tprivate.h" /* Datatypes */ +#ifdef H5_HAVE_EFF +#include "H5VLiod.h" /* IOD plugin */ +#endif #include "H5Zpkg.h" /* Data filters */ @@ -50,6 +53,14 @@ /* Local Macros */ /****************/ +#ifdef H5_HAVE_EFF +/* hint that access to dataset will be in an append only fashion */ +#define H5D_CRT_APPEND_ONLY_SIZE sizeof(hbool_t) +#define H5D_CRT_APPEND_ONLY_DEF FALSE +#define H5D_CRT_APPEND_ONLY_ENC H5P__encode_hbool_t +#define H5D_CRT_APPEND_ONLY_DEC H5P__decode_hbool_t +#endif + /* Define default layout information */ #define H5D_DEF_STORAGE_COMPACT_INIT {(hbool_t)FALSE, (size_t)0, NULL} #define H5D_DEF_STORAGE_CONTIG_INIT {HADDR_UNDEF, (hsize_t)0} @@ -170,6 +181,9 @@ H5FL_BLK_EXTERN(type_conv); /***************************/ /* Property value defaults */ +#ifdef H5_HAVE_EFF +static const hbool_t H5D_def_append_only_g = H5D_CRT_APPEND_ONLY_DEF; +#endif static const H5O_layout_t H5D_def_layout_g = H5D_CRT_LAYOUT_DEF; /* Default storage layout */ static const H5O_fill_t H5D_def_fill_g = H5D_CRT_FILL_VALUE_DEF; /* Default fill value */ static const unsigned H5D_def_alloc_time_state_g = H5D_CRT_ALLOC_TIME_STATE_DEF; /* Default allocation time state */ @@ -210,6 +224,14 @@ H5P__dcrt_reg_prop(H5P_genclass_t *pclass) FUNC_ENTER_STATIC +#ifdef H5_HAVE_EFF + if(H5P_register_real(pclass, H5D_CRT_APPEND_ONLY_NAME, H5D_CRT_APPEND_ONLY_SIZE, + &H5D_def_append_only_g, + NULL, NULL, NULL, H5D_CRT_APPEND_ONLY_ENC, H5D_CRT_APPEND_ONLY_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") +#endif + /* Register the storage layout property */ if(H5P_register_real(pclass, H5D_CRT_LAYOUT_NAME, H5D_CRT_LAYOUT_SIZE, &H5D_def_layout_g, NULL, NULL, NULL, H5D_CRT_LAYOUT_ENC, H5D_CRT_LAYOUT_DEC, diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c index b5d688b..aad2b0d 100644 --- a/src/H5Pdxpl.c +++ b/src/H5Pdxpl.c @@ -37,15 +37,40 @@ #include "H5ACprivate.h" /* Cache */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FFprivate.h" /* Fast Forward routines */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ +#include "H5VLiod.h" /* IOD plugin */ /****************/ /* Local Macros */ /****************/ +#ifdef H5_HAVE_EFF + +#define H5D_XFER_INJECT_CORRUPTION_SIZE sizeof(hbool_t) +#define H5D_XFER_INJECT_CORRUPTION_DEF FALSE +#define H5D_XFER_INJECT_CORRUPTION_ENC H5P__encode_hbool_t +#define H5D_XFER_INJECT_CORRUPTION_DEC H5P__decode_hbool_t + +#define H5D_XFER_CHECKSUM_SIZE sizeof(uint64_t) +#define H5D_XFER_CHECKSUM_DEF 0 +#define H5D_XFER_CHECKSUM_ENC H5P__encode_uint64_t +#define H5D_XFER_CHECKSUM_DEC H5P__decode_uint64_t + +/* definitions for checksum scope in FF stack */ +#define H5D_XFER_CHECKSUM_SCOPE_SIZE sizeof(uint32_t) +#define H5D_XFER_CHECKSUM_SCOPE_DEF 7 +#define H5D_XFER_CHECKSUM_SCOPE_ENC H5P__encode_uint32_t +#define H5D_XFER_CHECKSUM_SCOPE_DEC H5P__decode_uint32_t + +#define H5D_XFER_CHECKSUM_PTR_SIZE sizeof(uint64_t *) +#define H5D_XFER_CHECKSUM_PTR_DEF NULL + +#endif /* H5_HAVE_EFF */ + /* ======== Data transfer properties ======== */ /* Definitions for maximum temp buffer size property */ #define H5D_XFER_MAX_TEMP_BUF_SIZE sizeof(size_t) @@ -236,6 +261,13 @@ const H5P_libclass_t H5P_CLS_DXFR[1] = {{ /* Local Private Variables */ /***************************/ +#ifdef H5_HAVE_EFF +static const hbool_t H5D_def_inject_corruption_g = H5D_XFER_INJECT_CORRUPTION_DEF; +static const uint64_t H5D_def_checksum_g = H5D_XFER_CHECKSUM_DEF; +static const uint64_t *H5D_def_checksum_ptr_g = H5D_XFER_CHECKSUM_PTR_DEF; +static const uint32_t H5D_def_checksum_scope_g = H5D_XFER_CHECKSUM_SCOPE_DEF; +#endif /* H5_HAVE_EFF */ + /* Property value defaults */ static const size_t H5D_def_max_temp_buf_g = H5D_XFER_MAX_TEMP_BUF_DEF; /* Default value for maximum temp buffer size */ static const void *H5D_def_tconv_buf_g = H5D_XFER_TCONV_BUF_DEF; /* Default value for type conversion buffer */ @@ -284,10 +316,40 @@ static const size_t H5D_def_direct_chunk_datasize_g = H5D_XFER_DIRECT_CHUNK_WRIT static herr_t H5P__dxfr_reg_prop(H5P_genclass_t *pclass) { + hid_t trans_id = FAIL; + hid_t context_id = FAIL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC +#ifdef H5_HAVE_EFF + + if(H5P_register_real(pclass, H5D_XFER_INJECT_CORRUPTION_NAME, H5D_XFER_INJECT_CORRUPTION_SIZE, + &H5D_def_inject_corruption_g, + NULL, NULL, NULL, H5D_XFER_INJECT_CORRUPTION_ENC, H5D_XFER_INJECT_CORRUPTION_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + if(H5P_register_real(pclass, H5D_XFER_CHECKSUM_NAME, H5D_XFER_CHECKSUM_SIZE, + &H5D_def_checksum_g, + NULL, NULL, NULL, H5D_XFER_CHECKSUM_ENC, H5D_XFER_CHECKSUM_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + if(H5P_register_real(pclass, H5VL_CS_BITFLAG_NAME, H5D_XFER_CHECKSUM_SCOPE_SIZE, + &H5D_def_checksum_scope_g, + NULL, NULL, NULL, H5D_XFER_CHECKSUM_SCOPE_ENC, H5D_XFER_CHECKSUM_SCOPE_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + if(H5P_register_real(pclass, H5D_XFER_CHECKSUM_PTR_NAME, H5D_XFER_CHECKSUM_PTR_SIZE, + &H5D_def_checksum_ptr_g, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +#endif /* H5_HAVE_EFF */ + /* Register the max. temp buffer size property */ if(H5P_register_real(pclass, H5D_XFER_MAX_TEMP_BUF_NAME, H5D_XFER_MAX_TEMP_BUF_SIZE, &H5D_def_max_temp_buf_g, NULL, NULL, NULL, H5D_XFER_MAX_TEMP_BUF_ENC, H5D_XFER_MAX_TEMP_BUF_DEC, @@ -462,6 +524,16 @@ H5P__dxfr_reg_prop(H5P_genclass_t *pclass) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the transaction ID property*/ + if(H5P_register_real(pclass, H5VL_TRANS_ID, sizeof(hid_t), &trans_id, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the context ID property*/ + if(H5P_register_real(pclass, H5VL_CONTEXT_ID, sizeof(hid_t), &context_id, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P__dxfr_reg_prop() */ diff --git a/src/H5Pencdec.c b/src/H5Pencdec.c index 0c70c6c..a937feb 100644 --- a/src/H5Pencdec.c +++ b/src/H5Pencdec.c @@ -184,6 +184,78 @@ H5P__encode_hsize_t(const void *value, void **_pp, size_t *size) /*------------------------------------------------------------------------- + * Function: H5P__encode_uint32_t + * + * Purpose: Generic encoding callback routine for 'uint32_t' properties. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 07, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__encode_uint32_t(const void *value, void **_pp, size_t *size) +{ + uint8_t **pp = (uint8_t **)_pp; + + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity checks */ + HDassert(value); + HDassert(size); + + if(NULL != *pp) { + /* Encode the value */ + UINT32ENCODE(*pp, *(const uint32_t *)value); + } /* end if */ + + /* Set size needed for encoding */ + *size += sizeof(uint32_t); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__encode_uint32_t() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__encode_uint64_t + * + * Purpose: Generic encoding callback routine for 'uint64_t' properties. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 07, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__encode_uint64_t(const void *value, void **_pp, size_t *size) +{ + uint8_t **pp = (uint8_t **)_pp; + + FUNC_ENTER_PACKAGE_NOERR + + /* Sanity checks */ + HDassert(value); + HDassert(size); + + if(NULL != *pp) { + /* Encode the value */ + UINT64ENCODE(*pp, *(const uint64_t *)value); + } /* end if */ + + /* Set size needed for encoding */ + *size += sizeof(uint64_t); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5P__encode_uint64_t() */ + + +/*------------------------------------------------------------------------- * Function: H5P__encode_unsigned * * Purpose: Generic encoding callback routine for 'unsigned' properties. @@ -551,6 +623,74 @@ H5P__decode_hsize_t(const void **_pp, void *_value) /*------------------------------------------------------------------------- + * Function: H5P__decode_uint32_t + * + * Purpose: Generic encoding callback routine for 'uint32_t' properties. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 07, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__decode_uint32_t(const void **_pp, void *_value) +{ + uint32_t *value = (uint32_t *)_value; /* Property value to return */ + const uint8_t **pp = (const uint8_t **)_pp; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity checks */ + HDassert(pp); + HDassert(*pp); + HDassert(value); + + UINT32DECODE(*pp, *value) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__decode_uint32_t() */ + + +/*------------------------------------------------------------------------- + * Function: H5P__decode_uint64_t + * + * Purpose: Generic encoding callback routine for 'uint64_t' properties. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 07, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P__decode_uint64_t(const void **_pp, void *_value) +{ + uint64_t *value = (uint64_t *)_value; /* Property value to return */ + const uint8_t **pp = (const uint8_t **)_pp; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity checks */ + HDassert(pp); + HDassert(*pp); + HDassert(value); + + UINT64DECODE(*pp, *value) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__decode_uint64_t() */ + + +/*------------------------------------------------------------------------- * Function: H5P__decode_unsigned * * Purpose: Generic decoding callback routine for 'unsigned' properties. @@ -746,7 +886,7 @@ H5P__decode(const void *buf) /* Get the type of the property list */ type = (H5P_plist_type_t)*p++; - if(type <= H5P_TYPE_USER || type > H5P_TYPE_LINK_ACCESS) + if(type <= H5P_TYPE_USER || type > H5P_TYPE_TRANSACTION_FINISH) HGOTO_ERROR(H5E_PLIST, H5E_BADRANGE, FAIL, "bad type of encoded information: %u", (unsigned)type) /* Create new property list of the specified type */ diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index 59c0a2e..bc8d52d 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -36,7 +36,8 @@ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* Files */ +#include "H5Fprivate.h" /* Files */ +#include "H5FFprivate.h" /* FFwd wrappers */ #include "H5FDprivate.h" /* File drivers */ #include "H5VLprivate.h" /* VOL plugins */ #include "H5Iprivate.h" /* IDs */ @@ -58,6 +59,16 @@ /* Local Macros */ /****************/ +#ifdef H5_HAVE_EFF + +/* definitions for checksum scope in FF stack */ +#define H5F_ACS_CHECKSUM_SCOPE_SIZE sizeof(uint32_t) +#define H5F_ACS_CHECKSUM_SCOPE_DEF 7 +#define H5F_ACS_CHECKSUM_SCOPE_ENC H5P__encode_unsigned +#define H5F_ACS_CHECKSUM_SCOPE_DEC H5P__decode_unsigned + +#endif /* H5_HAVE_EFF */ + /* ========= File Access properties ============ */ /* Definitions for the initial metadata cache resize configuration */ #define H5F_ACS_META_CACHE_INIT_CONFIG_SIZE sizeof(H5AC_cache_config_t) @@ -258,6 +269,9 @@ static const hbool_t H5F_def_want_posix_fd_g = H5F_ACS_WANT_POSIX_FD_DEF; static const unsigned H5F_def_efc_size_g = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */ static const H5FD_file_image_info_t H5F_def_file_image_info_g = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */ +#ifdef H5_HAVE_EFF +static const uint32_t H5F_def_checksum_scope_g = H5F_ACS_CHECKSUM_SCOPE_DEF; +#endif /* H5_HAVE_EFF */ /*------------------------------------------------------------------------- @@ -277,6 +291,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) H5VL_class_t *vol_cls = H5F_ACS_VOL_DEF; /* Default VOL plugin */ void *vol_info = H5F_ACS_VOL_INFO_DEF; /* Default VOL plugin information*/ const hid_t def_driver_id = H5F_ACS_FILE_DRV_ID_DEF; /* Default VFL driver ID (initialized from a variable) */ + hid_t rcxt_id = FAIL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -419,6 +434,19 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, NULL, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the read context ID property*/ + if(H5P_register_real(pclass, H5VL_ACQUIRE_RC_ID, sizeof(hid_t), &rcxt_id, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +#ifdef H5_HAVE_EFF + if(H5P_register_real(pclass, H5VL_CS_BITFLAG_NAME, H5F_ACS_CHECKSUM_SCOPE_SIZE, + &H5F_def_checksum_scope_g, + NULL, NULL, NULL, H5F_ACS_CHECKSUM_SCOPE_ENC, H5F_ACS_CHECKSUM_SCOPE_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") +#endif /* H5_HAVE_EFF */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_facc_reg_prop() */ diff --git a/src/H5Pint.c b/src/H5Pint.c index 8837363..cccc5a4 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -43,6 +43,11 @@ /* Local Macros */ /****************/ +/* Async. I/O properties */ +#define H5P_ASYNC_FLAG_SIZE sizeof(hbool_t) +#define H5P_ASYNC_REQ_SIZE sizeof(void *) +#define H5P_ASYNC_REQ_DEF NULL + /******************/ /* Local Typedefs */ @@ -89,6 +94,9 @@ static H5P_genprop_t *H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type) static herr_t H5P_free_prop(H5P_genprop_t *prop); static int H5P_cmp_prop(const H5P_genprop_t *prop1, const H5P_genprop_t *prop2); +/* Property class callbacks */ +static herr_t H5P__root_reg_prop(H5P_genclass_t *pclass); + /*********************/ /* Package Variables */ @@ -108,13 +116,18 @@ hid_t H5P_CLS_DATASET_XFER_g = FAIL; hid_t H5P_CLS_FILE_MOUNT_g = FAIL; hid_t H5P_CLS_GROUP_CREATE_g = FAIL; hid_t H5P_CLS_GROUP_ACCESS_g = FAIL; +hid_t H5P_CLS_MAP_CREATE_g = FAIL; +hid_t H5P_CLS_MAP_ACCESS_g = FAIL; hid_t H5P_CLS_DATATYPE_CREATE_g = FAIL; hid_t H5P_CLS_DATATYPE_ACCESS_g = FAIL; hid_t H5P_CLS_ATTRIBUTE_CREATE_g = FAIL; hid_t H5P_CLS_OBJECT_COPY_g = FAIL; hid_t H5P_CLS_LINK_CREATE_g = FAIL; hid_t H5P_CLS_LINK_ACCESS_g = FAIL; -hid_t H5P_CLS_STRING_CREATE_g = FAIL; +hid_t H5P_CLS_STRING_CREATE_g = FAIL; +hid_t H5P_CLS_READ_CONTEXT_ACQUIRE_g = FAIL; +hid_t H5P_CLS_TRANSACTION_START_g = FAIL; +hid_t H5P_CLS_TRANSACTION_FINISH_g = FAIL; /* * Predefined property lists for each predefined class. These are initialized @@ -128,12 +141,17 @@ hid_t H5P_LST_DATASET_XFER_g = FAIL; hid_t H5P_LST_FILE_MOUNT_g = FAIL; hid_t H5P_LST_GROUP_CREATE_g = FAIL; hid_t H5P_LST_GROUP_ACCESS_g = FAIL; +hid_t H5P_LST_MAP_CREATE_g = FAIL; +hid_t H5P_LST_MAP_ACCESS_g = FAIL; hid_t H5P_LST_DATATYPE_CREATE_g = FAIL; hid_t H5P_LST_DATATYPE_ACCESS_g = FAIL; hid_t H5P_LST_ATTRIBUTE_CREATE_g = FAIL; hid_t H5P_LST_OBJECT_COPY_g = FAIL; hid_t H5P_LST_LINK_CREATE_g = FAIL; hid_t H5P_LST_LINK_ACCESS_g = FAIL; +hid_t H5P_LST_READ_CONTEXT_ACQUIRE_g = FAIL; +hid_t H5P_LST_TRANSACTION_START_g = FAIL; +hid_t H5P_LST_TRANSACTION_FINISH_g = FAIL; /* Root property list class library initialization object */ const H5P_libclass_t H5P_CLS_ROOT[1] = {{ @@ -142,7 +160,7 @@ const H5P_libclass_t H5P_CLS_ROOT[1] = {{ NULL, /* Parent class ID */ &H5P_CLS_ROOT_g, /* Pointer to class ID */ NULL, /* Pointer to default property list ID */ - NULL, /* Default property registration routine */ + H5P__root_reg_prop, /* Default property registration routine */ NULL, /* Class creation callback */ NULL, /* Class creation callback info */ NULL, /* Class copy callback */ @@ -202,12 +220,13 @@ const H5P_libclass_t H5P_CLS_TACC[1] = {{ NULL /* Class close callback info */ }}; - /* Library property list classes defined in other code modules */ H5_DLLVAR const H5P_libclass_t H5P_CLS_OCRT[1]; /* Object creation */ H5_DLLVAR const H5P_libclass_t H5P_CLS_STRCRT[1]; /* String create */ H5_DLLVAR const H5P_libclass_t H5P_CLS_LACC[1]; /* Link access */ H5_DLLVAR const H5P_libclass_t H5P_CLS_GCRT[1]; /* Group create */ +H5_DLLVAR const H5P_libclass_t H5P_CLS_MCRT[1]; /* Map create */ +H5_DLLVAR const H5P_libclass_t H5P_CLS_MACC[1]; /* Map access */ H5_DLLVAR const H5P_libclass_t H5P_CLS_OCPY[1]; /* Object copy */ H5_DLLVAR const H5P_libclass_t H5P_CLS_FCRT[1]; /* File creation */ H5_DLLVAR const H5P_libclass_t H5P_CLS_FACC[1]; /* File access */ @@ -217,7 +236,9 @@ H5_DLLVAR const H5P_libclass_t H5P_CLS_DXFR[1]; /* Data transfer */ H5_DLLVAR const H5P_libclass_t H5P_CLS_FMNT[1]; /* File mount */ H5_DLLVAR const H5P_libclass_t H5P_CLS_ACRT[1]; /* Attribute creation */ H5_DLLVAR const H5P_libclass_t H5P_CLS_LCRT[1]; /* Link creation */ - +H5_DLLVAR const H5P_libclass_t H5P_CLS_RCACC[1]; /* Read Context acquire */ +H5_DLLVAR const H5P_libclass_t H5P_CLS_TRSCC[1]; /* Transaction start */ +H5_DLLVAR const H5P_libclass_t H5P_CLS_TRFCC[1]; /* Transaction finish */ /*****************************/ /* Library Private Variables */ @@ -244,6 +265,8 @@ static H5P_libclass_t const * const init_class[] = { H5P_CLS_GCRT, /* Group create */ H5P_CLS_OCPY, /* Object copy */ H5P_CLS_GACC, /* Group access */ + H5P_CLS_MCRT, /* Map create */ + H5P_CLS_MACC, /* Map access */ H5P_CLS_FCRT, /* File creation */ H5P_CLS_FACC, /* File access */ H5P_CLS_DCRT, /* Dataset creation */ @@ -253,6 +276,9 @@ static H5P_libclass_t const * const init_class[] = { H5P_CLS_TCRT, /* Datatype creation */ H5P_CLS_TACC, /* Datatype access */ H5P_CLS_ACRT, /* Attribute creation */ + H5P_CLS_RCACC, /* Read Context acquire */ + H5P_CLS_TRSCC, /* Transaction start */ + H5P_CLS_TRFCC, /* Transaction finish */ H5P_CLS_LCRT /* Link creation */ }; @@ -283,6 +309,10 @@ static const H5I_class_t H5I_GENPROPLST_CLS[1] = {{ NULL /* Callback routine for closing auxilary objects of this class */ }}; +/* Property value defaults */ +static const hbool_t H5_def_async_flag_g = H5P_ASYNC_FLAG_DEF; /* Default async flag */ +static const void *H5_def_async_req_g = H5P_ASYNC_REQ_DEF; /* Default async request pointer */ + /*-------------------------------------------------------------------------- @@ -383,6 +413,42 @@ done: } /* end H5P_init() */ +/*------------------------------------------------------------------------- + * Function: H5P__root_reg_prop + * + * Purpose: Initialize the root property list class + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * March 20, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5P__root_reg_prop(H5P_genclass_t *pclass) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Register async. flag property */ + if(H5P_register_real(pclass, H5P_ASYNC_FLAG_NAME, H5P_ASYNC_FLAG_SIZE, &H5_def_async_flag_g, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register async. request property */ + if(H5P_register_real(pclass, H5P_ASYNC_REQ_NAME, H5P_ASYNC_REQ_SIZE, &H5_def_async_req_g, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__root_reg_prop() */ + + /*-------------------------------------------------------------------------- NAME H5P_init_interface -- Initialize interface-specific information @@ -526,12 +592,17 @@ H5P_term_interface(void) H5P_LST_DATASET_XFER_g = H5P_LST_GROUP_CREATE_g = H5P_LST_GROUP_ACCESS_g = + H5P_LST_MAP_CREATE_g = + H5P_LST_MAP_ACCESS_g = H5P_LST_DATATYPE_CREATE_g = H5P_LST_DATATYPE_ACCESS_g = H5P_LST_ATTRIBUTE_CREATE_g = H5P_LST_OBJECT_COPY_g = H5P_LST_LINK_CREATE_g = H5P_LST_LINK_ACCESS_g = + H5P_LST_READ_CONTEXT_ACQUIRE_g = + H5P_LST_TRANSACTION_START_g = + H5P_LST_TRANSACTION_FINISH_g = H5P_LST_FILE_MOUNT_g = (-1); } /* end if */ } /* end if */ @@ -551,6 +622,8 @@ H5P_term_interface(void) H5P_CLS_DATASET_XFER_g = H5P_CLS_GROUP_CREATE_g = H5P_CLS_GROUP_ACCESS_g = + H5P_CLS_MAP_CREATE_g = + H5P_CLS_MAP_ACCESS_g = H5P_CLS_DATATYPE_CREATE_g = H5P_CLS_DATATYPE_ACCESS_g = H5P_CLS_STRING_CREATE_g = @@ -558,6 +631,9 @@ H5P_term_interface(void) H5P_CLS_OBJECT_COPY_g = H5P_CLS_LINK_CREATE_g = H5P_CLS_LINK_ACCESS_g = + H5P_CLS_READ_CONTEXT_ACQUIRE_g = + H5P_CLS_TRANSACTION_START_g = + H5P_CLS_TRANSACTION_FINISH_g = H5P_CLS_FILE_MOUNT_g = (-1); } /* end if */ } /* end if */ @@ -5006,8 +5082,8 @@ H5P__new_plist_of_type(H5P_plist_type_t type) FUNC_ENTER_PACKAGE /* Sanity checks */ - HDcompile_assert(H5P_TYPE_LINK_ACCESS == (H5P_TYPE_MAX_TYPE - 1)); - HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_LINK_ACCESS); + HDcompile_assert(H5P_TYPE_TRANSACTION_FINISH == (H5P_TYPE_MAX_TYPE - 1)); + HDassert(type >= H5P_TYPE_USER && type <= H5P_TYPE_TRANSACTION_FINISH); /* Check arguments */ if(type == H5P_TYPE_USER) @@ -5053,6 +5129,14 @@ H5P__new_plist_of_type(H5P_plist_type_t type) class_id = H5P_CLS_GROUP_ACCESS_g; break; + case H5P_TYPE_MAP_CREATE: + class_id = H5P_CLS_MAP_CREATE_g; + break; + + case H5P_TYPE_MAP_ACCESS: + class_id = H5P_CLS_MAP_ACCESS_g; + break; + case H5P_TYPE_DATATYPE_CREATE: class_id = H5P_CLS_DATATYPE_CREATE_g; break; @@ -5081,6 +5165,18 @@ H5P__new_plist_of_type(H5P_plist_type_t type) class_id = H5P_CLS_LINK_ACCESS_g; break; + case H5P_TYPE_READ_CONTEXT_ACQUIRE: + class_id = H5P_CLS_READ_CONTEXT_ACQUIRE_g; + break; + + case H5P_TYPE_TRANSACTION_START: + class_id = H5P_CLS_TRANSACTION_START_g; + break; + + case H5P_TYPE_TRANSACTION_FINISH: + class_id = H5P_CLS_TRANSACTION_FINISH_g; + break; + case H5P_TYPE_USER: /* shut compiler warnings up */ case H5P_TYPE_ROOT: case H5P_TYPE_MAX_TYPE: diff --git a/src/H5Plapl.c b/src/H5Plapl.c index 676b574..618cfc9 100644 --- a/src/H5Plapl.c +++ b/src/H5Plapl.c @@ -38,13 +38,21 @@ #include "H5Lprivate.h" /* Links */ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ - +#include "H5VLiod.h" /* IOD plugin */ /****************/ /* Local Macros */ /****************/ /* ======== Link access properties ======== */ +#ifdef H5_HAVE_EFF +/* replica ID to use when accessing an object at IOD */ +#define H5O_ACS_REPLICA_ID_SIZE sizeof(hrpl_t) +#define H5O_ACS_REPLICA_ID_DEF 0 +#define H5O_ACS_REPLICA_ID_ENC H5P__encode_uint64_t +#define H5O_ACS_REPLICA_ID_DEC H5P__decode_uint64_t +#endif + /* Definitions for number of soft links to traverse */ #define H5L_ACS_NLINKS_SIZE sizeof(size_t) #define H5L_ACS_NLINKS_DEF H5L_NUM_LINKS /*max symlinks to follow per lookup */ @@ -151,7 +159,9 @@ static const char *H5L_def_elink_prefix_g = H5L_ACS_ELINK_PREFIX_DEF; /* Default static const hid_t H5L_def_fapl_id_g = H5L_ACS_ELINK_FAPL_DEF; /* Default fapl for external link access */ static const unsigned H5L_def_elink_flags_g = H5L_ACS_ELINK_FLAGS_DEF; /* Default file access flags for external link traversal */ static const H5L_elink_cb_t H5L_def_elink_cb_g = H5L_ACS_ELINK_CB_DEF; /* Default external link traversal callback */ - +#ifdef H5_HAVE_EFF +static const hrpl_t H5O_replica_id_g = H5O_ACS_REPLICA_ID_DEF; /* Default replica ID */ +#endif /*------------------------------------------------------------------------- @@ -177,6 +187,14 @@ H5P_lacc_reg_prop(H5P_genclass_t *pclass) FUNC_ENTER_NOAPI_NOINIT +#ifdef H5_HAVE_EFF + if(H5P_register_real(pclass, H5O_ACS_REPLICA_ID_NAME, H5O_ACS_REPLICA_ID_SIZE, + &H5O_replica_id_g, + NULL, NULL, NULL, H5O_ACS_REPLICA_ID_ENC, H5O_ACS_REPLICA_ID_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") +#endif + /* Register property for number of links traversed */ if(H5P_register_real(pclass, H5L_ACS_NLINKS_NAME, H5L_ACS_NLINKS_SIZE, &H5L_def_nlinks_g, NULL, NULL, NULL, H5L_ACS_NLINKS_ENC, H5L_ACS_NLINKS_DEC, diff --git a/src/H5Pmapl.c b/src/H5Pmapl.c new file mode 100644 index 0000000..6884ad8 --- /dev/null +++ b/src/H5Pmapl.c @@ -0,0 +1,118 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Pmapl.c + * January 27, 2014 + * Mohamad Chaarawi + * + * Purpose: Map access property list class routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ +#define H5P_PACKAGE /*suppress error about including H5Ppkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Ppkg.h" /* Property lists */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* ========= Map Access properties ============ */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Property class callbacks */ +static herr_t H5P__macc_reg_prop(H5P_genclass_t *pclass); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Map creation property list class library initialization object */ +const H5P_libclass_t H5P_CLS_MACC[1] = {{ + "map access", /* Class name for debugging */ + H5P_TYPE_MAP_ACCESS, /* Class type */ + &H5P_CLS_LINK_ACCESS_g, /* Parent class ID */ + &H5P_CLS_MAP_ACCESS_g, /* Pointer to class ID */ + &H5P_LST_MAP_ACCESS_g, /* Pointer to default property list ID */ + H5P__macc_reg_prop, /* Default property registration routine */ + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5P__macc_reg_prop + * + * Purpose: Initialize the map access property list class + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * January, 2014 + *------------------------------------------------------------------------- + */ +static herr_t +H5P__macc_reg_prop(H5P_genclass_t *pclass) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__macc_reg_prop() */ diff --git a/src/H5Pmcpl.c b/src/H5Pmcpl.c new file mode 100644 index 0000000..20ae66d --- /dev/null +++ b/src/H5Pmcpl.c @@ -0,0 +1,118 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Pmcpl.c + * January 27, 2014 + * Mohamad Chaarawi + * + * Purpose: Map creation property list class routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ +#define H5P_PACKAGE /*suppress error about including H5Ppkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Ppkg.h" /* Property lists */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* ========= Map Creation properties ============ */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Property class callbacks */ +static herr_t H5P__mcrt_reg_prop(H5P_genclass_t *pclass); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Map creation property list class library initialization object */ +const H5P_libclass_t H5P_CLS_MCRT[1] = {{ + "map create", /* Class name for debugging */ + H5P_TYPE_MAP_CREATE, /* Class type */ + &H5P_CLS_OBJECT_CREATE_g, /* Parent class ID */ + &H5P_CLS_MAP_CREATE_g, /* Pointer to class ID */ + &H5P_LST_MAP_CREATE_g, /* Pointer to default property list ID */ + H5P__mcrt_reg_prop, /* Default property registration routine */ + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5P__mcrt_reg_prop + * + * Purpose: Initialize the map creation property list class + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * January, 2014 + *------------------------------------------------------------------------- + */ +static herr_t +H5P__mcrt_reg_prop(H5P_genclass_t *pclass) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__mcrt_reg_prop() */ diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index df4ebb6..8d1d061 100644 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -49,6 +49,13 @@ /****************/ /* ========= Object Creation properties ============ */ +#ifdef H5_HAVE_EFF +/* hint for IOD to enable checksums on an object */ +#define H5O_CRT_ENABLE_CHECKSUM_SIZE sizeof(hbool_t) +#define H5O_CRT_ENABLE_CHECKSUM_DEF TRUE +#define H5O_CRT_ENABLE_CHECKSUM_ENC H5P__encode_hbool_t +#define H5O_CRT_ENABLE_CHECKSUM_DEC H5P__decode_hbool_t +#endif /* Definitions for the max. # of attributes to store compactly */ #define H5O_CRT_ATTR_MAX_COMPACT_SIZE sizeof(unsigned) #define H5O_CRT_ATTR_MAX_COMPACT_ENC H5P__encode_unsigned @@ -132,7 +139,9 @@ static const unsigned H5O_def_attr_max_compact_g = H5O_CRT_ATTR_MAX_COMPACT_DEF; static const unsigned H5O_def_attr_min_dense_g = H5O_CRT_ATTR_MIN_DENSE_DEF; /* Default min. dense attribute storage settings */ static const uint8_t H5O_def_ohdr_flags_g = H5O_CRT_OHDR_FLAGS_DEF; /* Default object header flag settings */ static const H5O_pline_t H5O_def_pline_g = H5O_CRT_PIPELINE_DEF; /* Default I/O pipeline setting */ - +#ifdef H5_HAVE_EFF +static const hbool_t H5O_def_enable_checksum_g = H5O_CRT_ENABLE_CHECKSUM_DEF; +#endif /*------------------------------------------------------------------------- @@ -154,6 +163,14 @@ H5P__ocrt_reg_prop(H5P_genclass_t *pclass) FUNC_ENTER_STATIC +#ifdef H5_HAVE_EFF + if(H5P_register_real(pclass, H5O_CRT_ENABLE_CHECKSUM_NAME, H5O_CRT_ENABLE_CHECKSUM_SIZE, + &H5O_def_enable_checksum_g, + NULL, NULL, NULL, H5O_CRT_ENABLE_CHECKSUM_ENC, H5O_CRT_ENABLE_CHECKSUM_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") +#endif + /* Register max. compact attribute storage property */ if(H5P_register_real(pclass, H5O_CRT_ATTR_MAX_COMPACT_NAME, H5O_CRT_ATTR_MAX_COMPACT_SIZE, &H5O_def_attr_max_compact_g, NULL, NULL, NULL, H5O_CRT_ATTR_MAX_COMPACT_ENC, H5O_CRT_ATTR_MAX_COMPACT_DEC, diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index 9d48c60..4bf3e66 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -211,12 +211,16 @@ H5_DLL herr_t H5P__encode_hsize_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__encode_size_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__encode_unsigned(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__encode_uint8_t(const void *value, void **_pp, size_t *size); +H5_DLL herr_t H5P__encode_uint32_t(const void *value, void **_pp, size_t *size); +H5_DLL herr_t H5P__encode_uint64_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__encode_hbool_t(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__encode_double(const void *value, void **_pp, size_t *size); H5_DLL herr_t H5P__decode_hsize_t(const void **_pp, void *value); H5_DLL herr_t H5P__decode_size_t(const void **_pp, void *value); H5_DLL herr_t H5P__decode_unsigned(const void **_pp, void *value); H5_DLL herr_t H5P__decode_uint8_t(const void **_pp, void *value); +H5_DLL herr_t H5P__decode_uint64_t(const void **_pp, void *value); +H5_DLL herr_t H5P__decode_uint32_t(const void **_pp, void *value); H5_DLL herr_t H5P__decode_hbool_t(const void **_pp, void *value); H5_DLL herr_t H5P__decode_double(const void **_pp, void *value); diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index 0c3b5aa..2d78d5c 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -35,6 +35,11 @@ /* ======== String creation property names ======== */ #define H5P_STRCRT_CHAR_ENCODING_NAME "character_encoding" /* Character set encoding for string */ +/* ======== Root property names ======== */ +#define H5P_ASYNC_FLAG_NAME "async flag" /* Async flag */ +#define H5P_ASYNC_FLAG_DEF FALSE +#define H5P_ASYNC_REQ_NAME "async request" /* Async request */ + /****************************/ /* Library Private Typedefs */ @@ -63,6 +68,11 @@ typedef enum H5P_plist_type_t { H5P_TYPE_OBJECT_COPY = 15, H5P_TYPE_LINK_CREATE = 16, H5P_TYPE_LINK_ACCESS = 17, + H5P_TYPE_MAP_CREATE = 18, + H5P_TYPE_MAP_ACCESS = 19, + H5P_TYPE_READ_CONTEXT_ACQUIRE = 20, + H5P_TYPE_TRANSACTION_START = 21, + H5P_TYPE_TRANSACTION_FINISH = 22, H5P_TYPE_MAX_TYPE } H5P_plist_type_t; diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 882b195..6ff9fca 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -62,6 +62,8 @@ #define H5P_FILE_MOUNT (H5OPEN H5P_CLS_FILE_MOUNT_g) #define H5P_GROUP_CREATE (H5OPEN H5P_CLS_GROUP_CREATE_g) #define H5P_GROUP_ACCESS (H5OPEN H5P_CLS_GROUP_ACCESS_g) +#define H5P_MAP_CREATE (H5OPEN H5P_CLS_MAP_CREATE_g) +#define H5P_MAP_ACCESS (H5OPEN H5P_CLS_MAP_ACCESS_g) #define H5P_DATATYPE_CREATE (H5OPEN H5P_CLS_DATATYPE_CREATE_g) #define H5P_DATATYPE_ACCESS (H5OPEN H5P_CLS_DATATYPE_ACCESS_g) #define H5P_STRING_CREATE (H5OPEN H5P_CLS_STRING_CREATE_g) @@ -69,6 +71,9 @@ #define H5P_OBJECT_COPY (H5OPEN H5P_CLS_OBJECT_COPY_g) #define H5P_LINK_CREATE (H5OPEN H5P_CLS_LINK_CREATE_g) #define H5P_LINK_ACCESS (H5OPEN H5P_CLS_LINK_ACCESS_g) +#define H5P_RC_ACQUIRE (H5OPEN H5P_CLS_READ_CONTEXT_ACQUIRE_g) +#define H5P_TR_START (H5OPEN H5P_CLS_TRANSACTION_START_g) +#define H5P_TR_FINISH (H5OPEN H5P_CLS_TRANSACTION_FINISH_g) /* * The library's default property lists @@ -81,12 +86,17 @@ #define H5P_FILE_MOUNT_DEFAULT (H5OPEN H5P_LST_FILE_MOUNT_g) #define H5P_GROUP_CREATE_DEFAULT (H5OPEN H5P_LST_GROUP_CREATE_g) #define H5P_GROUP_ACCESS_DEFAULT (H5OPEN H5P_LST_GROUP_ACCESS_g) +#define H5P_MAP_CREATE_DEFAULT (H5OPEN H5P_LST_MAP_CREATE_g) +#define H5P_MAP_ACCESS_DEFAULT (H5OPEN H5P_LST_MAP_ACCESS_g) #define H5P_DATATYPE_CREATE_DEFAULT (H5OPEN H5P_LST_DATATYPE_CREATE_g) #define H5P_DATATYPE_ACCESS_DEFAULT (H5OPEN H5P_LST_DATATYPE_ACCESS_g) #define H5P_ATTRIBUTE_CREATE_DEFAULT (H5OPEN H5P_LST_ATTRIBUTE_CREATE_g) #define H5P_OBJECT_COPY_DEFAULT (H5OPEN H5P_LST_OBJECT_COPY_g) #define H5P_LINK_CREATE_DEFAULT (H5OPEN H5P_LST_LINK_CREATE_g) #define H5P_LINK_ACCESS_DEFAULT (H5OPEN H5P_LST_LINK_ACCESS_g) +#define H5P_RC_ACQUIRE_DEFAULT (H5OPEN H5P_LST_READ_CONTEXT_ACQUIRE_g) +#define H5P_TR_START_DEFAULT (H5OPEN H5P_LST_TRANSACTION_START_g) +#define H5P_TR_FINISH_DEFAULT (H5OPEN H5P_LST_TRANSACTION_FINISH_g) /* Common creation order flags (for links in groups and attributes on objects) */ #define H5P_CRT_ORDER_TRACKED 0x0001 @@ -183,6 +193,8 @@ H5_DLLVAR hid_t H5P_CLS_DATASET_XFER_g; H5_DLLVAR hid_t H5P_CLS_FILE_MOUNT_g; H5_DLLVAR hid_t H5P_CLS_GROUP_CREATE_g; H5_DLLVAR hid_t H5P_CLS_GROUP_ACCESS_g; +H5_DLLVAR hid_t H5P_CLS_MAP_CREATE_g; +H5_DLLVAR hid_t H5P_CLS_MAP_ACCESS_g; H5_DLLVAR hid_t H5P_CLS_DATATYPE_CREATE_g; H5_DLLVAR hid_t H5P_CLS_DATATYPE_ACCESS_g; H5_DLLVAR hid_t H5P_CLS_STRING_CREATE_g; @@ -190,6 +202,9 @@ H5_DLLVAR hid_t H5P_CLS_ATTRIBUTE_CREATE_g; H5_DLLVAR hid_t H5P_CLS_OBJECT_COPY_g; H5_DLLVAR hid_t H5P_CLS_LINK_CREATE_g; H5_DLLVAR hid_t H5P_CLS_LINK_ACCESS_g; +H5_DLLVAR hid_t H5P_CLS_READ_CONTEXT_ACQUIRE_g; +H5_DLLVAR hid_t H5P_CLS_TRANSACTION_START_g; +H5_DLLVAR hid_t H5P_CLS_TRANSACTION_FINISH_g; /* Default roperty list IDs */ /* (Internal to library, do not use! Use macros above) */ @@ -201,12 +216,17 @@ H5_DLLVAR hid_t H5P_LST_DATASET_XFER_g; H5_DLLVAR hid_t H5P_LST_FILE_MOUNT_g; H5_DLLVAR hid_t H5P_LST_GROUP_CREATE_g; H5_DLLVAR hid_t H5P_LST_GROUP_ACCESS_g; +H5_DLLVAR hid_t H5P_LST_MAP_CREATE_g; +H5_DLLVAR hid_t H5P_LST_MAP_ACCESS_g; H5_DLLVAR hid_t H5P_LST_DATATYPE_CREATE_g; H5_DLLVAR hid_t H5P_LST_DATATYPE_ACCESS_g; H5_DLLVAR hid_t H5P_LST_ATTRIBUTE_CREATE_g; H5_DLLVAR hid_t H5P_LST_OBJECT_COPY_g; H5_DLLVAR hid_t H5P_LST_LINK_CREATE_g; H5_DLLVAR hid_t H5P_LST_LINK_ACCESS_g; +H5_DLLVAR hid_t H5P_LST_READ_CONTEXT_ACQUIRE_g; +H5_DLLVAR hid_t H5P_LST_TRANSACTION_START_g; +H5_DLLVAR hid_t H5P_LST_TRANSACTION_FINISH_g; /*********************/ /* Public Prototypes */ diff --git a/src/H5Prcapl.c b/src/H5Prcapl.c new file mode 100644 index 0000000..1e24e09 --- /dev/null +++ b/src/H5Prcapl.c @@ -0,0 +1,131 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Prcapl.c + * August 2013 + * Mohamad Chaarawi <chaarawi@hdfgroup.org> + * + * Purpose: Read Context Acquire property list class routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ +#define H5P_PACKAGE /*suppress error about including H5Ppkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Ppkg.h" /* Property lists */ +#include "H5RCprivate.h" /* Read Context */ + +/****************/ +/* Local Macros */ +/****************/ + +/* ========= Read Context properties ============ */ +/* Definitions for Container Version being Acquired */ +#define H5RC_ACQUIRE_CV_REQUEST_SIZE sizeof(H5RC_request_t) +#define H5RC_ACQUIRE_CV_REQUEST_DEF H5RC_EXACT +#define H5RC_ACQUIRE_CV_REQUEST_ENC H5P__encode_unsigned +#define H5RC_ACQUIRE_CV_REQUEST_DEC H5P__decode_unsigned + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Property class callbacks */ +static herr_t H5P__rcacc_reg_prop(H5P_genclass_t *pclass); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Read Context acquire property list class library initialization object */ +const H5P_libclass_t H5P_CLS_RCACC[1] = {{ + "read context acquire", /* Class name for debugging */ + H5P_TYPE_READ_CONTEXT_ACQUIRE, /* Class type */ + &H5P_CLS_ROOT_g, /* Parent class ID */ + &H5P_CLS_READ_CONTEXT_ACQUIRE_g, /* Pointer to class ID */ + &H5P_LST_READ_CONTEXT_ACQUIRE_g, /* Pointer to default property list ID */ + H5P__rcacc_reg_prop, /* Default property registration routine */ + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5P__rcacc_reg_prop + * + * Purpose: Register the read context acquire property list class's + * properties + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + *------------------------------------------------------------------------- + */ +static herr_t +H5P__rcacc_reg_prop(H5P_genclass_t *pclass) +{ + H5RC_request_t acquire_req = H5RC_ACQUIRE_CV_REQUEST_DEF; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Register the size of raw data chunk cache (elements) */ + if(H5P_register_real(pclass, H5RC_ACQUIRE_CV_REQUEST_NAME, H5RC_ACQUIRE_CV_REQUEST_SIZE, &acquire_req, + NULL, NULL, NULL, H5RC_ACQUIRE_CV_REQUEST_ENC, H5RC_ACQUIRE_CV_REQUEST_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__rcacc_reg_prop() */ diff --git a/src/H5Ptrfpl.c b/src/H5Ptrfpl.c new file mode 100644 index 0000000..3029ff1 --- /dev/null +++ b/src/H5Ptrfpl.c @@ -0,0 +1,132 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Ptrspl.c + * August 2013 + * Mohamad Chaarawi <chaarawi@hdfgroup.org> + * + * Purpose: Transaction Finish property list class routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ +#define H5P_PACKAGE /*suppress error about including H5Ppkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Ppkg.h" /* Property lists */ +#include "H5TRprivate.h" /* Transactions */ + +/****************/ +/* Local Macros */ +/****************/ + +/* ========= Read Context properties ============ */ +/* Definitions for Transaction being finished */ +#define H5TR_FINISH_ACQUIRE_SIZE sizeof(hbool_t) +#define H5TR_FINISH_ACQUIRE_DEF FALSE +#define H5TR_FINISH_ACQUIRE_ENC H5P__encode_hbool_t +#define H5TR_FINISH_ACQUIRE_DEC H5P__decode_hbool_t + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Property class callbacks */ +static herr_t H5P__trfcc_reg_prop(H5P_genclass_t *pclass); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Transaction finish property list class library initialization object */ +const H5P_libclass_t H5P_CLS_TRFCC[1] = {{ + "transaction finish", /* Class name for debugging */ + H5P_TYPE_TRANSACTION_FINISH, /* Class type */ + &H5P_CLS_ROOT_g, /* Parent class ID */ + &H5P_CLS_TRANSACTION_FINISH_g, /* Pointer to class ID */ + &H5P_LST_TRANSACTION_FINISH_g, /* Pointer to default property list ID */ + H5P__trfcc_reg_prop, /* Default property registration routine */ + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5P__trfcc_reg_prop + * + * Purpose: Register the transaction finish property list class's + * properties + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + *------------------------------------------------------------------------- + */ +static herr_t +H5P__trfcc_reg_prop(H5P_genclass_t *pclass) +{ + hbool_t acquire = H5TR_FINISH_ACQUIRE_DEF; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Register the size of raw data chunk cache (elements) */ + if(H5P_register_real(pclass, H5TR_FINISH_ACQUIRE_NAME, H5TR_FINISH_ACQUIRE_SIZE, &acquire, + NULL, NULL, NULL, H5TR_FINISH_ACQUIRE_ENC, H5TR_FINISH_ACQUIRE_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__trfcc_reg_prop() */ + diff --git a/src/H5Ptrspl.c b/src/H5Ptrspl.c new file mode 100644 index 0000000..c75c761 --- /dev/null +++ b/src/H5Ptrspl.c @@ -0,0 +1,131 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Ptrspl.c + * August 2013 + * Mohamad Chaarawi <chaarawi@hdfgroup.org> + * + * Purpose: Transaction Start property list class routines + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ +#define H5P_PACKAGE /*suppress error about including H5Ppkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Ppkg.h" /* Property lists */ +#include "H5TRprivate.h" /* Transactions */ + +/****************/ +/* Local Macros */ +/****************/ + +/* ========= Read Context properties ============ */ +/* Definitions for Transaction being started */ +#define H5TR_START_NUM_PEERS_SIZE sizeof(unsigned) +#define H5TR_START_NUM_PEERS_DEF 0 +#define H5TR_START_NUM_PEERS_ENC H5P__encode_unsigned +#define H5TR_START_NUM_PEERS_DEC H5P__decode_unsigned + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Property class callbacks */ +static herr_t H5P__trscc_reg_prop(H5P_genclass_t *pclass); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Transaction start property list class library initialization object */ +const H5P_libclass_t H5P_CLS_TRSCC[1] = {{ + "transaction start", /* Class name for debugging */ + H5P_TYPE_TRANSACTION_START, /* Class type */ + &H5P_CLS_ROOT_g, /* Parent class ID */ + &H5P_CLS_TRANSACTION_START_g, /* Pointer to class ID */ + &H5P_LST_TRANSACTION_START_g, /* Pointer to default property list ID */ + H5P__trscc_reg_prop, /* Default property registration routine */ + NULL, /* Class creation callback */ + NULL, /* Class creation callback info */ + NULL, /* Class copy callback */ + NULL, /* Class copy callback info */ + NULL, /* Class close callback */ + NULL /* Class close callback info */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5P__trscc_reg_prop + * + * Purpose: Register the transaction start property list class's + * properties + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + *------------------------------------------------------------------------- + */ +static herr_t +H5P__trscc_reg_prop(H5P_genclass_t *pclass) +{ + unsigned num_peers = H5TR_START_NUM_PEERS_DEF; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Register the size of raw data chunk cache (elements) */ + if(H5P_register_real(pclass, H5TR_START_NUM_PEERS_NAME, H5TR_START_NUM_PEERS_SIZE, &num_peers, + NULL, NULL, NULL, H5TR_START_NUM_PEERS_ENC, H5TR_START_NUM_PEERS_DEC, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P__trscc_reg_prop() */ diff --git a/src/H5Q.c b/src/H5Q.c new file mode 100644 index 0000000..1884dd4 --- /dev/null +++ b/src/H5Q.c @@ -0,0 +1,1220 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: Query routines. + */ + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5Q_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Qprivate.h" /* Query */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" + +/****************/ +/* Local Macros */ +/****************/ +#define H5Q_TYPE_SEQ \ + ((H5T_NATIVE_CHAR)(char))\ + ((H5T_NATIVE_SHORT)(short)) \ + ((H5T_NATIVE_INT)(int)) \ + ((H5T_NATIVE_LONG)(long)) \ + ((H5T_NATIVE_LLONG)(long long)) \ + ((H5T_NATIVE_FLOAT)(float)) \ + ((H5T_NATIVE_DOUBLE)(double)) + +#define H5Q_APPLY_MATCH_OP(result, op, x, y) \ + switch (op) { \ + case H5Q_MATCH_EQUAL: \ + result = (x == y); \ + break; \ + case H5Q_MATCH_NOT_EQUAL: \ + result = (x != y); \ + break; \ + case H5Q_MATCH_LESS_THAN: \ + result = (x < y); \ + break; \ + case H5Q_MATCH_GREATER_THAN: \ + result = (x > y); \ + break; \ + default: \ + break; \ + } + +#define H5Q_CMP_DATA_ELEM(result, op, type, x, y) \ +{ \ + type x_value; \ + type y_value; \ + x_value = *((type *) x); \ + y_value = *((type *) y); \ + \ + H5Q_APPLY_MATCH_OP(result, op, x_value, y_value) \ +} + +#define H5Q_CMP_TYPE(type1, type2, native_type) \ + (0 == H5T_cmp(type1, native_type, FALSE)) || \ + (0 == H5T_cmp(type2, native_type, FALSE)) + +/******************/ +/* Local Typedefs */ +/******************/ +typedef enum H5Q_match_type_t { /* The different kinds of native types we can match */ + H5Q_NATIVE_INT_MATCH_CHAR, + H5Q_NATIVE_INT_MATCH_SHORT, + H5Q_NATIVE_INT_MATCH_INT, + H5Q_NATIVE_INT_MATCH_LONG, + H5Q_NATIVE_INT_MATCH_LLONG, + H5Q_NATIVE_FLOAT_MATCH_FLOAT, + H5Q_NATIVE_FLOAT_MATCH_DOUBLE +} H5Q_match_type_t; + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5Q_apply_combine(H5Q_t *query, hbool_t *result, H5T_t *type, + const void *elem); +static herr_t H5Q_apply_select(H5Q_t *query, hbool_t *result, H5T_t *type, + const void *elem); +static herr_t H5Q_apply_data_elem(H5Q_t *query, hbool_t *result, H5T_t *type, + const void *elem); +static herr_t H5Q_apply_attr_name(H5Q_t *query, hbool_t *result, + const char *name); +static herr_t H5Q_apply_link_name(H5Q_t *query, hbool_t *result, + const char *name); + +static H5_inline void +H5Q_encode_memcpy(unsigned char **buf_ptr, size_t *nalloc, const void *data, + size_t data_size) +{ + if (*buf_ptr != NULL) { + HDmemcpy(*buf_ptr, data, data_size); + *buf_ptr += data_size; + } + *nalloc += data_size; +} + +static H5_inline void +H5Q_decode_memcpy(void *data, size_t data_size, const unsigned char **buf_ptr) +{ + if (*buf_ptr != NULL) { + HDmemcpy(data, *buf_ptr, data_size); + *buf_ptr += data_size; + } +} + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5Q_t struct */ +H5FL_DEFINE(H5Q_t); + +/* Query ID class */ +static const H5I_class_t H5I_QUERY_CLS[1] = {{ + H5I_QUERY, /* Class ID for the type */ + 0, /* Class behavior flags */ + 0, /* Number of reserved IDs for this type */ + (H5I_free_t)H5Q_close, /* Free function for object's of this type */ + NULL /* Free function for auxilary objects of this type */ +}}; + +/*------------------------------------------------------------------------- + * Function: H5Q_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5Q_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_init() */ + +/*-------------------------------------------------------------------------- +NAME + H5Q_init_interface -- Initialize interface-specific information +USAGE + herr_t H5Q_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5Q_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Initialize the atom group for the QUERY IDs */ + if (H5I_register_type(H5I_QUERY_CLS) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_init_interface() */ + +/*-------------------------------------------------------------------------- + NAME + H5Q_term_interface + PURPOSE + Terminate various H5Q objects + USAGE + void H5Q_term_interface() + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Release the atom group and any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5Q_term_interface(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if (H5_interface_initialize_g) { + if ((n = H5I_nmembers(H5I_QUERY))) { + H5I_clear_type(H5I_QUERY, FALSE, FALSE); + } /* end if */ + else { + /* Free data types */ + H5I_dec_type_ref(H5I_QUERY); + + /* Shut down interface */ + H5_interface_initialize_g = 0; + n = 1; /* H5I */ + } /* end else */ + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* end H5Q_term_interface() */ + +/*------------------------------------------------------------------------- + * Function: H5Qcreate + * + * Purpose: Create a new query object of query_type type, with match_op + * determining the query's match condition and additional parameters + * determined by the type of the query. + * + * Return: Success: The ID for a new query. + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +hid_t +H5Qcreate(H5Q_type_t query_type, H5Q_match_op_t match_op, ...) +{ + H5Q_t *query = NULL; + va_list ap; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE2("i", "QtQm", query_type, match_op); + + va_start(ap, match_op); + + switch (query_type) { + case H5Q_TYPE_DATA_ELEM: + { + H5T_t *datatype = NULL; + hid_t datatype_id; + const void *value; + + /* Get arguments */ + datatype_id = va_arg(ap, hid_t); + value = va_arg(ap, const void *); + + /* Get type */ + if (NULL == (datatype = (H5T_t *) H5I_object_verify(datatype_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type") + + /* Create a new query object */ + if (NULL == (query = H5Q_create(query_type, match_op, datatype, value))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCREATE, FAIL, "unable to create query") + } + break; + case H5Q_TYPE_ATTR_NAME: + { + const char *attr_name; + + /* Get arguments */ + attr_name = va_arg(ap, const char *); + + /* Create a new query object */ + if (NULL == (query = H5Q_create(query_type, match_op, attr_name))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCREATE, FAIL, "unable to create query") + } + break; + case H5Q_TYPE_LINK_NAME: + { + const char *link_name; + + /* Get arguments */ + link_name = va_arg(ap, const char *); + + /* Create a new query object */ + if (NULL == (query = H5Q_create(query_type, match_op, link_name))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCREATE, FAIL, "unable to create query") + } + break; + default: + { + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type") + } + break; + } + + va_end(ap); + + /* Register the new query object to get an ID for it */ + if ((ret_value = H5I_register(H5I_QUERY, query, TRUE)) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTREGISTER, FAIL, "can't register query handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Qcreate() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_create + * + * Purpose: Private function for H5Qcreate + * + * Return: Success: Pointer to the new query + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5Q_t * +H5Q_create(H5Q_type_t query_type, H5Q_match_op_t match_op, ...) +{ + H5Q_t *query = NULL; + va_list ap; + H5Q_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + va_start(ap, match_op); + + /* Allocate query struct */ + if (NULL == (query = H5FL_CALLOC(H5Q_t))) + HGOTO_ERROR(H5E_QUERY, H5E_NOSPACE, NULL, "can't allocate query structure") + + query->is_combined = FALSE; + query->ref_count = 1; + query->query.select.type = query_type; + query->query.select.match_op = match_op; + switch (query_type) { + case H5Q_TYPE_DATA_ELEM: + { + H5T_t *datatype = NULL; + H5T_t *native_datatype = NULL; + size_t datatype_size; + const void *value; + void *value_buf = NULL; + + datatype = va_arg(ap, H5T_t*); + value = va_arg(ap, const void *); + + /* Only use native type */ + if (NULL == (native_datatype = H5T_get_native_type(datatype, H5T_DIR_DEFAULT, NULL, NULL, NULL))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve native type") + query->query.select.elem.data_elem.type = native_datatype; + if (0 == (datatype_size = H5T_get_size(native_datatype))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid size") + query->query.select.elem.data_elem.type_size = datatype_size; + if (NULL == (value_buf = H5MM_malloc(datatype_size))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, NULL, + "can't allocate value buffer") + HDmemcpy(value_buf, value, datatype_size); + query->query.select.elem.data_elem.value = value_buf; + } + break; + case H5Q_TYPE_ATTR_NAME: + { + const char *attr_name; + + attr_name = va_arg(ap, const char *); + query->query.select.elem.attr_name.name = H5MM_strdup(attr_name); + } + break; + case H5Q_TYPE_LINK_NAME: + { + const char *link_name; + + link_name = va_arg(ap, const char *); + query->query.select.elem.link_name.name = H5MM_strdup(link_name); + } + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, NULL, "unsupported/unrecognized query type") + break; + } /* end switch */ + + va_end(ap); + + /* set return value */ + ret_value = query; + +done: + if (!ret_value && query) + query = H5FL_FREE(H5Q_t, query); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_create() */ + +/*------------------------------------------------------------------------- + * Function: H5Qclose + * + * Purpose: Close a query object. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Qclose(hid_t query_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", query_id); + + /* Check args */ + if (NULL == H5I_object_verify(query_id, H5I_QUERY)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + + if (H5I_dec_app_ref(query_id) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTDEC, FAIL, "unable to decrement ref count on query"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Qclose() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_close + * + * Purpose: Private function for H5Qclose. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Q_close(H5Q_t *query) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(query); + + query->ref_count--; + if (query->ref_count) HGOTO_DONE(SUCCEED) + + if (query->is_combined) { + if (FAIL == H5Q_close(query->query.combine.l_query)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to free query") + query->query.combine.l_query = NULL; + if (FAIL == H5Q_close(query->query.combine.r_query)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to free query") + query->query.combine.r_query = NULL; + } else { + switch (query->query.select.type) { + case H5Q_TYPE_DATA_ELEM: + if (FAIL == H5T_close(query->query.select.elem.data_elem.type)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTFREE, FAIL, "unable to free datatype"); + query->query.select.elem.data_elem.type = NULL; + H5MM_free(query->query.select.elem.data_elem.value); + query->query.select.elem.data_elem.value = NULL; + break; + case H5Q_TYPE_ATTR_NAME: + H5MM_free(query->query.select.elem.attr_name.name); + query->query.select.elem.attr_name.name = NULL; + break; + case H5Q_TYPE_LINK_NAME: + H5MM_free(query->query.select.elem.link_name.name); + query->query.select.elem.link_name.name = NULL; + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type") + break; + } + } + + /* Free the query struct */ + query = H5FL_FREE(H5Q_t, query); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_close() */ + +/*------------------------------------------------------------------------- + * Function: H5Qcombine + * + * Purpose: Combine query objects to create a new query object. + * + * Return: Success: The ID for a new combined query. + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +hid_t +H5Qcombine(hid_t query_id1, H5Q_combine_op_t combine_op, hid_t query_id2) +{ + H5Q_t *query = NULL, *query1 = NULL, *query2 = NULL; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE3("i", "iQci", query_id1, combine_op, query_id2); + + /* Check args and get the query objects */ + if(NULL == (query1 = (H5Q_t *) H5I_object_verify(query_id1, H5I_QUERY))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + if(NULL == (query2 = (H5Q_t *) H5I_object_verify(query_id2, H5I_QUERY))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + + /* Combine query objects */ + if (NULL == (query = H5Q_combine(query1, combine_op, query2))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCREATE, FAIL, "unable to combine query objects") + + /* Register the new query object to get an ID for it */ + if ((ret_value = H5I_register(H5I_QUERY, query, TRUE)) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTREGISTER, FAIL, "can't register query handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Qcombine() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_combine + * + * Purpose: Private function for H5Qcombine. + * + * Return: Success: Pointer to the new query + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5Q_t * +H5Q_combine(H5Q_t *query1, H5Q_combine_op_t combine_op, H5Q_t *query2) +{ + H5Q_t *query = NULL; + H5Q_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Allocate query struct */ + if (NULL == (query = H5FL_CALLOC(H5Q_t))) + HGOTO_ERROR(H5E_QUERY, H5E_NOSPACE, NULL, "can't allocate query structure") + + switch (combine_op) { + case H5Q_COMBINE_AND: + case H5Q_COMBINE_OR: + query->query.combine.op = combine_op; + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, NULL, "unsupported/unrecognized combine op") + break; + } + query->is_combined = TRUE; + query->ref_count = 1; + query->query.combine.l_query = query1; + query1->ref_count++; + query->query.combine.r_query = query2; + query2->ref_count++; + + /* set return value */ + ret_value = query; + +done: + if (!ret_value && query) + query = H5FL_FREE(H5Q_t, query); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_combine() */ + +/*------------------------------------------------------------------------- + * Function: H5Qapply + * + * Purpose: Apply a query to an element elem of type type_id. + * TODO modify prototype for attr/link name support + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Qapply(hid_t query_id, hbool_t *result, hid_t type_id, const void *elem) +{ + H5Q_t *query = NULL; + H5T_t *type = NULL, *native_type = NULL; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "i*bi*x", query_id, result, type_id, elem); + + /* Check args and get the query objects */ + if (!result) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL pointer for result") + if (NULL == (query = (H5Q_t *) H5I_object_verify(query_id, H5I_QUERY))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + if(NULL == (type = (H5T_t *) H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type") + + /* Only use native type */ + if (NULL == (native_type = H5T_get_native_type(type, H5T_DIR_DEFAULT, NULL, NULL, NULL))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot retrieve native type") + + /* Apply query */ + if (FAIL == (ret_value = H5Q_apply(query, result, native_type, elem))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query") + +done: + if (native_type) + H5T_close(native_type); + FUNC_LEAVE_API(ret_value) +} /* end H5Qapply() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_apply + * + * Purpose: Private function for H5Qapply. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Q_apply(H5Q_t *query, hbool_t *result, H5T_t *type, const void *elem) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(query); + HDassert(result); + + if (query->is_combined) { + if (FAIL == (ret_value = H5Q_apply_combine(query, result, type, elem))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query") + } else { + if (FAIL == (ret_value = H5Q_apply_select(query, result, type, elem))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_apply_combine + * + * Purpose: Private function for H5Qapply (combine query). + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q_apply_combine(H5Q_t *query, hbool_t *result, H5T_t *type, const void *elem) +{ + herr_t ret_value = SUCCEED; /* Return value */ + hbool_t result1, result2; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(query); + HDassert(query->is_combined == TRUE); + + if (FAIL == H5Q_apply(query->query.combine.l_query, &result1, type, elem)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query") + if (FAIL == H5Q_apply(query->query.combine.r_query, &result2, type, elem)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply query") + + switch (query->query.combine.op) { + case H5Q_COMBINE_AND: + *result = result1 && result2; + break; + case H5Q_COMBINE_OR: + *result = result1 || result2; + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized combine op") + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply_combine() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_apply_select + * + * Purpose: Private function for H5Qapply (select query). + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q_apply_select(H5Q_t *query, hbool_t *result, H5T_t *type, const void *elem) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(query); + HDassert(query->is_combined == FALSE); + + switch (query->query.select.type) { + case H5Q_TYPE_DATA_ELEM: + if (FAIL == (ret_value = H5Q_apply_data_elem(query, result, type, elem))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply data element query") + break; + case H5Q_TYPE_ATTR_NAME: + /* TODO pass non NULL string */ + if (FAIL == (ret_value = H5Q_apply_attr_name(query, result, NULL))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply attribute name query") + break; + case H5Q_TYPE_LINK_NAME: + /* TODO pass non NULL string */ + if (FAIL == (ret_value = H5Q_apply_link_name(query, result, NULL))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCOMPARE, FAIL, "unable to apply link name query") + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type") + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply_select() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_promote_type + * + * Purpose: Private function for H5Qapply (promote data element type + * so that data element and query element can be compared). + * + * Return: Success: Pointer to promoted native type + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +static H5T_t * +H5Q_promote_type(H5T_t *type1, H5T_t *type2, H5Q_match_type_t *match_type) +{ + H5T_t *ret_value; /* Return value */ + H5T_class_t type1_class, type2_class, promoted_type_class; + H5T_t *promoted_type; + + FUNC_ENTER_NOAPI_NOINIT + + /* Get class of types */ + if (H5T_NO_CLASS == (type1_class = H5T_get_class(type1, FALSE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class") + if (H5T_NO_CLASS == (type2_class = H5T_get_class(type2, FALSE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class") + + if ((type1_class == H5T_FLOAT) || (type2_class == H5T_FLOAT)) { + promoted_type_class = H5T_FLOAT; + } else { + promoted_type_class = H5T_INTEGER; + } + + switch (promoted_type_class) { + case H5T_INTEGER: + if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_LLONG_g))) { + *match_type = H5Q_NATIVE_INT_MATCH_LLONG; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_LLONG_g); + } else if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_LONG_g))) { + *match_type = H5Q_NATIVE_INT_MATCH_LONG; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_LONG_g); + } else if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_INT_g))) { + *match_type = H5Q_NATIVE_INT_MATCH_INT; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_INT_g); + } else if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_SHORT_g))) { + *match_type = H5Q_NATIVE_INT_MATCH_SHORT; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_SHORT_g); + } else if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g))) { + *match_type = H5Q_NATIVE_INT_MATCH_CHAR; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g); + } else { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid type") + } + break; + case H5T_FLOAT: + if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g))) { + *match_type = H5Q_NATIVE_FLOAT_MATCH_DOUBLE; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g); + } else if (H5Q_CMP_TYPE(type1, type2, (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g))) { + *match_type = H5Q_NATIVE_FLOAT_MATCH_FLOAT; + promoted_type = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g); + } else { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid type") + } + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class") + break; + } + + ret_value = promoted_type; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_promote_type() */ + + +/*------------------------------------------------------------------------- + * Function: H5Q_apply_data_elem + * + * Purpose: Private function for H5Qapply (data element). + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q_apply_data_elem(H5Q_t *query, hbool_t *result, H5T_t *type, const void *value) +{ + herr_t ret_value = SUCCEED; /* Return value */ + void *value_buf = NULL, *query_value_buf = NULL; + H5T_t *query_type, *promoted_type; + H5Q_match_type_t match_type; + size_t type_size, query_type_size, promoted_type_size; + hid_t type_id, query_type_id, promoted_type_id; + H5T_path_t *tpath; + H5Q_match_op_t query_op; + hbool_t query_result = FALSE; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(query); + HDassert(query->query.select.type == H5Q_TYPE_DATA_ELEM); + + /* Keep a copy of elem to work on */ + if (0 == (type_size = H5T_get_size(type))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid size") + + /* Keep a copy of the query value */ + query_type = query->query.select.elem.data_elem.type; + query_type_size = query->query.select.elem.data_elem.type_size; + query_op = query->query.select.match_op; + + /* Promote type to compare elements with query */ + promoted_type = H5Q_promote_type(type, query_type, &match_type); + if (0 == (promoted_type_size = H5T_get_size(promoted_type))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid size") + + /* Resize value and query value buf for convert + * (promoted_type_size is always bigger) */ + if (NULL == (value_buf = H5MM_malloc(promoted_type_size))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, FAIL, "can't allocate value buffer") + HDmemcpy(value_buf, value, type_size); + + if (NULL == (query_value_buf = H5MM_malloc(promoted_type_size))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, FAIL, "can't allocate value buffer") + HDmemcpy(query_value_buf, query->query.select.elem.data_elem.value, query_type_size); + + /* Create temporary IDs for H5T_convert */ + type_id = H5I_register(H5I_DATATYPE, type, FALSE); + query_type_id = H5I_register(H5I_DATATYPE, query_type, FALSE); + promoted_type_id = H5I_register(H5I_DATATYPE, promoted_type, FALSE); + + /* Find the conversion function */ + if (NULL == (tpath = H5T_path_find(type, promoted_type, NULL, NULL, H5P_LST_DATASET_XFER_g, FALSE))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTINIT, FAIL, "unable to find type info") + if (FAIL == (H5T_convert(tpath, type_id, promoted_type_id, 1, (size_t)0, (size_t)0, value_buf, NULL, H5P_LST_DATASET_XFER_g))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCONVERT, FAIL, "can't convert value") + + if (NULL == (tpath = H5T_path_find(query_type, promoted_type, NULL, NULL, H5P_LST_DATASET_XFER_g, FALSE))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTINIT, FAIL, "unable to find type info") + if (FAIL == (H5T_convert(tpath, query_type_id, promoted_type_id, 1, (size_t)0, (size_t)0, query_value_buf, NULL, H5P_LST_DATASET_XFER_g))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTCONVERT, FAIL, "can't convert query value") + + /* Could also use BOOST preprocessor for that but not really nice */ + switch (match_type) { + case H5Q_NATIVE_INT_MATCH_CHAR: + H5Q_CMP_DATA_ELEM(query_result, query_op, char, value_buf, query_value_buf); + break; + case H5Q_NATIVE_INT_MATCH_SHORT: + H5Q_CMP_DATA_ELEM(query_result, query_op, short, value_buf, query_value_buf); + break; + case H5Q_NATIVE_INT_MATCH_INT: + H5Q_CMP_DATA_ELEM(query_result, query_op, int, value_buf, query_value_buf); + break; + case H5Q_NATIVE_INT_MATCH_LONG: + H5Q_CMP_DATA_ELEM(query_result, query_op, long, value_buf, query_value_buf); + break; + case H5Q_NATIVE_INT_MATCH_LLONG: + H5Q_CMP_DATA_ELEM(query_result, query_op, long long, value_buf, query_value_buf); + break; + case H5Q_NATIVE_FLOAT_MATCH_FLOAT: + H5Q_CMP_DATA_ELEM(query_result, query_op, float, value_buf, query_value_buf); + break; + case H5Q_NATIVE_FLOAT_MATCH_DOUBLE: + H5Q_CMP_DATA_ELEM(query_result, query_op, double, value_buf, query_value_buf); + break; + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "unsupported/unrecognized datatype") + break; + } + + *result = query_result; + +done: + H5MM_free(value_buf); + H5MM_free(query_value_buf); + + /* Free temporary IDs */ + H5I_remove(type_id); + H5I_remove(query_type_id); + H5I_remove(promoted_type_id); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply_data_elem() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_apply_attr_name + * + * Purpose: Private function for H5Qapply (attribute name). + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q_apply_attr_name(H5Q_t *query, hbool_t *result, const char *name) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(query); + HDassert(query->query.select.type == H5Q_TYPE_ATTR_NAME); + + *result = (0 == HDstrcmp(name, query->query.select.elem.attr_name.name)); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply_attr_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_apply_link_name + * + * Purpose: Private function for H5Qapply (link name). + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +static herr_t +H5Q_apply_link_name(H5Q_t *query, hbool_t *result, const char *name) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(query); + HDassert(query->query.select.type == H5Q_TYPE_LINK_NAME); + + *result = (0 == HDstrcmp(name, query->query.select.elem.link_name.name)); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_apply_link_name() */ + +/*------------------------------------------------------------------------- + * Function: H5Qencode + * + * Purpose: Given a query ID, serialize the query into buf. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Qencode(hid_t query_id, void *buf, size_t *nalloc) +{ + H5Q_t *query; + herr_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*x*z", query_id, buf, nalloc); + + /* Check argument and retrieve object */ + if(NULL == (query = (H5Q_t *)H5I_object_verify(query_id, H5I_QUERY))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a query ID") + if(nalloc == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL pointer for buffer size") + + /* Encode the query */ + if((ret_value = H5Q_encode(query, (unsigned char *)buf, nalloc)) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTENCODE, FAIL, "can't encode query") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Qencode() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_encode + * + * Purpose: Private function for H5Qencode. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5Q_encode(H5Q_t *query, unsigned char *buf, size_t *nalloc) +{ + size_t buf_size = 0; + herr_t ret_value = SUCCEED; + unsigned char *buf_ptr = buf; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(query); + HDassert(nalloc); + + H5Q_encode_memcpy(&buf_ptr, &buf_size, &query->is_combined, sizeof(hbool_t)); + if (query->is_combined) { + size_t l_buf_size = 0, r_buf_size = 0; + + H5Q_encode_memcpy(&buf_ptr, &buf_size, &query->query.combine.op, sizeof(H5Q_combine_op_t)); + H5Q_encode(query->query.combine.l_query, buf_ptr, &l_buf_size); + buf_size += l_buf_size; + if (buf_ptr) buf_ptr += l_buf_size; + H5Q_encode(query->query.combine.r_query, buf_ptr, &r_buf_size); + buf_size += r_buf_size; + if (buf_ptr) buf_ptr += r_buf_size; + } else { + H5Q_encode_memcpy(&buf_ptr, &buf_size, &query->query.select.type, sizeof(H5Q_type_t)); + H5Q_encode_memcpy(&buf_ptr, &buf_size, &query->query.select.match_op, sizeof(H5Q_match_op_t)); + switch (query->query.select.type) { + case H5Q_TYPE_DATA_ELEM: + { + size_t type_id_nalloc = 0; + H5T_t *type = query->query.select.elem.data_elem.type; + size_t type_size = query->query.select.elem.data_elem.type_size; + void *value_buf = query->query.select.elem.data_elem.value; + + if (FAIL == H5T_encode(type, NULL, &type_id_nalloc)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTENCODE, FAIL, "can't get encoding size for datatype"); + H5Q_encode_memcpy(&buf_ptr, &buf_size, &type_id_nalloc, sizeof(size_t)); + if (FAIL == H5T_encode(type, buf_ptr, &type_id_nalloc)) + HGOTO_ERROR(H5E_QUERY, H5E_CANTENCODE, FAIL, "can't encode datatype"); + buf_size += type_id_nalloc; + if (buf_ptr) buf_ptr += type_id_nalloc; + H5Q_encode_memcpy(&buf_ptr, &buf_size, &type_size, sizeof(size_t)); + H5Q_encode_memcpy(&buf_ptr, &buf_size, value_buf, type_size); + } + break; + case H5Q_TYPE_ATTR_NAME: + { + size_t name_len = HDstrlen(query->query.select.elem.attr_name.name) + 1; + char *name = query->query.select.elem.attr_name.name; + + H5Q_encode_memcpy(&buf_ptr, &buf_size, &name_len, sizeof(size_t)); + H5Q_encode_memcpy(&buf_ptr, &buf_size, name, name_len); + } + break; + case H5Q_TYPE_LINK_NAME: + { + size_t name_len = HDstrlen(query->query.select.elem.link_name.name) + 1; + char *name = query->query.select.elem.attr_name.name; + + H5Q_encode_memcpy(&buf_ptr, &buf_size, &name_len, sizeof(size_t)); + H5Q_encode_memcpy(&buf_ptr, &buf_size, name, name_len); + } + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, FAIL, "unsupported/unrecognized query type") + break; + } + } + + *nalloc = buf_size; + +done: + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_encode() */ + +/*------------------------------------------------------------------------- + * Function: H5Qdecode + * + * Purpose: Deserialize the buffer and return a new query handle. + * + * Return: Success: query ID (non-negative) + * + * Failure: negative + *------------------------------------------------------------------------- + */ +hid_t +H5Qdecode(const void *buf) +{ + H5Q_t *query; + hid_t ret_value; /* Return value */ + const unsigned char *buf_ptr = (const unsigned char *) buf; + + FUNC_ENTER_API(FAIL) + H5TRACE1("i", "*x", buf); + + /* Check args */ + if(buf == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer") + + /* Create datatype by decoding buffer */ + if(NULL == (query = H5Q_decode(&buf_ptr))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTDECODE, FAIL, "can't decode object") + + /* Register the type and return the ID */ + if((ret_value = H5I_register(H5I_QUERY, query, TRUE)) < 0) + HGOTO_ERROR(H5E_QUERY, H5E_CANTREGISTER, FAIL, "unable to register query") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Qdecode() */ + +/*------------------------------------------------------------------------- + * Function: H5Q_decode + * + * Purpose: Private function for H5Qdecode. + * + * Return: Success: Pointer to the decoded query + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5Q_t * +H5Q_decode(const unsigned char **buf_ptr) +{ + H5Q_t *ret_value = NULL; + H5Q_t *query = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(*buf_ptr); + + /* Allocate query struct */ + if (NULL == (query = H5FL_CALLOC(H5Q_t))) + HGOTO_ERROR(H5E_QUERY, H5E_NOSPACE, NULL, "can't allocate query structure") + + /* Set ref count */ + query->ref_count = 1; + + H5Q_decode_memcpy(&query->is_combined, sizeof(hbool_t), buf_ptr); + if (query->is_combined) { + H5Q_decode_memcpy(&query->query.combine.op, sizeof(H5Q_combine_op_t), buf_ptr); + query->query.combine.l_query = H5Q_decode(buf_ptr); + query->query.combine.r_query = H5Q_decode(buf_ptr); + } else { + H5Q_decode_memcpy(&query->query.select.type, sizeof(H5Q_type_t), buf_ptr); + H5Q_decode_memcpy(&query->query.select.match_op, sizeof(H5Q_match_op_t), buf_ptr); + switch (query->query.select.type) { + case H5Q_TYPE_DATA_ELEM: + { + size_t type_id_nalloc = 0; + H5T_t *type; + size_t type_size; + void *value_buf; + + H5Q_decode_memcpy(&type_id_nalloc, sizeof(size_t), buf_ptr); + if (NULL == (type = H5T_decode(*buf_ptr))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode datatype"); + query->query.select.elem.data_elem.type = type; + *buf_ptr += type_id_nalloc; + + H5Q_decode_memcpy(&type_size, sizeof(size_t), buf_ptr); + query->query.select.elem.data_elem.type_size = type_size; + if (NULL == (value_buf = H5MM_malloc(type_size))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, NULL, "can't allocate value buffer") + H5Q_decode_memcpy(value_buf, type_size, buf_ptr); + query->query.select.elem.data_elem.value = value_buf; + } + break; + case H5Q_TYPE_ATTR_NAME: + { + size_t name_len; + char *name; + + H5Q_decode_memcpy(&name_len, sizeof(size_t), buf_ptr); + if (NULL == (name = H5MM_malloc(name_len))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, NULL, + "can't allocate value buffer") + H5Q_decode_memcpy(name, name_len, buf_ptr); + query->query.select.elem.attr_name.name = name; + } + break; + case H5Q_TYPE_LINK_NAME: + { + size_t name_len; + char *name; + + H5Q_decode_memcpy(&name_len, sizeof(size_t), buf_ptr); + if (NULL == (name = H5MM_malloc(name_len))) + HGOTO_ERROR(H5E_QUERY, H5E_CANTALLOC, NULL, + "can't allocate value buffer") + H5Q_decode_memcpy(name, name_len, buf_ptr); + query->query.select.elem.link_name.name = name; + } + break; + default: + HGOTO_ERROR(H5E_QUERY, H5E_BADTYPE, NULL, "unsupported/unrecognized query type") + break; + } + } + + ret_value = query; +done: + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5Q_decode() */ diff --git a/src/H5Qprivate.h b/src/H5Qprivate.h new file mode 100644 index 0000000..d9cc44e --- /dev/null +++ b/src/H5Qprivate.h @@ -0,0 +1,100 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5Q module + */ +#ifndef _H5Qprivate_H +#define _H5Qprivate_H + +/* Include package's public header */ +#include "H5Qpublic.h" + +/* Private headers needed by this file */ +#include "H5Tprivate.h" + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Data element */ +struct H5Q_data_elem { + H5T_t *type; /* type */ + size_t type_size; /* type size */ + void *value; /* value */ +}; + +/* Attribute name */ +struct H5Q_attr_name { + char *name; /* name */ +}; + +/* Link name */ +struct H5Q_link_name { + char *name; /* name */ +}; + +/* Query */ +typedef struct H5Q_t H5Q_t; + +/* Combine query */ +struct H5Q_combine { + H5Q_combine_op_t op; /* op */ + H5Q_t *l_query; /* left op query */ + H5Q_t *r_query; /* right op query */ +}; + +/* Select query */ +struct H5Q_select { + H5Q_type_t type; /* type */ + H5Q_match_op_t match_op; /* match op */ + union { + struct H5Q_data_elem data_elem; + struct H5Q_attr_name attr_name; + struct H5Q_link_name link_name; + } elem; +}; + +/* Query */ +struct H5Q_t { + unsigned ref_count; /* ref count */ + hbool_t is_combined; + union { + struct H5Q_select select; + struct H5Q_combine combine; + } query; +}; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/******************************/ +/* Library Private Prototypes */ +/******************************/ +H5_DLL herr_t H5Q_init(void); +H5_DLL H5Q_t *H5Q_create(H5Q_type_t query_type, H5Q_match_op_t match_op, ...); +H5_DLL herr_t H5Q_close(H5Q_t *query); +H5_DLL H5Q_t *H5Q_combine(H5Q_t *query1, H5Q_combine_op_t combine_op, H5Q_t *query2); +H5_DLL herr_t H5Q_apply(H5Q_t *query, hbool_t *result, H5T_t *type, const void *elem); + +H5_DLL herr_t H5Q_encode(H5Q_t *query, unsigned char *buf, size_t *nalloc); +H5_DLL H5Q_t *H5Q_decode(const unsigned char **buf); + +#endif /* _H5Qprivate_H */ diff --git a/src/H5Qpublic.h b/src/H5Qpublic.h new file mode 100644 index 0000000..f3dd48f --- /dev/null +++ b/src/H5Qpublic.h @@ -0,0 +1,83 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5Q module. + */ +#ifndef _H5Qpublic_H +#define _H5Qpublic_H + +/* Public headers needed by this file */ +#include "H5public.h" +#include "H5Ipublic.h" + +/*****************/ +/* Public Macros */ +/*****************/ + + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/* Query type */ +typedef enum H5Q_type_t { + H5Q_TYPE_DATA_ELEM, /* selects data elements */ + H5Q_TYPE_ATTR_NAME, /* selects attributes */ + H5Q_TYPE_LINK_NAME /* selects objects */ +} H5Q_type_t; + +/* Query match conditions */ +typedef enum H5Q_match_op_t { + H5Q_MATCH_EQUAL, /* equal */ + H5Q_MATCH_NOT_EQUAL, /* not equal */ + H5Q_MATCH_LESS_THAN, /* less than */ + H5Q_MATCH_GREATER_THAN /* greater than */ +} H5Q_match_op_t; + +/* Query combine operators */ +typedef enum H5Q_combine_op_t { + H5Q_COMBINE_AND, + H5Q_COMBINE_OR +} H5Q_combine_op_t; + +/********************/ +/* Public Variables */ +/********************/ + +/*********************/ +/* Public Prototypes */ +/*********************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Function prototypes */ +H5_DLL hid_t H5Qcreate(H5Q_type_t query_type, H5Q_match_op_t match_op, ...); +H5_DLL herr_t H5Qclose(hid_t query_id); +H5_DLL hid_t H5Qcombine(hid_t query_id1, H5Q_combine_op_t combine_op, hid_t query_id2); +H5_DLL herr_t H5Qapply(hid_t query_id, hbool_t *result, hid_t type_id, const void *elem); +/* or return dataspace and have + * hid_t H5Qapply(query_id, result, enum data_elem/link/attr, nelem, void*); + */ + +/* Encode / decode */ +H5_DLL herr_t H5Qencode(hid_t query_id, void *buf, size_t *nalloc); +H5_DLL hid_t H5Qdecode(const void *buf); + +#ifdef __cplusplus +} +#endif +#endif /* _H5Qpublic_H */ diff --git a/src/H5RC.c b/src/H5RC.c new file mode 100644 index 0000000..008e709 --- /dev/null +++ b/src/H5RC.c @@ -0,0 +1,732 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.org> + * August, 2013 + * + * Purpose: Read Context APIs to support Exascale FastForward + * functionality. + * + */ + + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5RC_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ +#include "H5RCprivate.h" /* Read Contexts */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod_client.h" /* IOD VOL plugin */ + +#ifdef H5_HAVE_EFF + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5RC_t struct */ +H5FL_DEFINE(H5RC_t); + +/* Dataspace ID class */ +static const H5I_class_t H5I_RC_CLS[1] = {{ + H5I_RC, /* ID class value */ + 0, /* Class flags */ + 2, /* # of reserved IDs for class */ + (H5I_free_t)H5RC_close, /* Callback routine for closing objects of this class */ + NULL /* Callback routine for closing auxilary objects of this class */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5RC_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RC_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RC_init() */ + + +/*-------------------------------------------------------------------------- +NAME + H5RC_init_interface -- Initialize interface-specific information +USAGE + herr_t H5RC_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5RC_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Initialize the atom group for the RC IDs */ + if(H5I_register_type(H5I_RC_CLS) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RC_init_interface() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RC_term_interface + PURPOSE + Terminate various H5RC objects + USAGE + void H5RC_term_interface() + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Release the atom group and any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5RC_term_interface(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + if((n = H5I_nmembers(H5I_RC))) { + H5I_clear_type(H5I_RC, FALSE, FALSE); + } /* end if */ + else { + /* Free data types */ + H5I_dec_type_ref(H5I_RC); + + /* Shut down interface */ + H5_interface_initialize_g = 0; + n = 1; /*H5I*/ + } /* end else */ + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* end H5RC_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_rcapl_version_request + * + * Purpose: Set the request type for acquring the container version, + * whether it has to be exactly the one requested (H5RC_EXACT), + * the lowest available greater than the one requested if it is + * not available (H5RC_NEXT), or the last one available ((H5RC_LAST). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_rcapl_version_request(hid_t rcapl_id, H5RC_request_t acquire_req) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iRc", rcapl_id, acquire_req); + + if(H5RC_LAST < acquire_req) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "Acquire request can be either H5RC_EXACT, H5RC_NEXT, or H5RC_LAST"); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(rcapl_id, H5P_RC_ACQUIRE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Set property */ + if(H5P_set(plist, H5RC_ACQUIRE_CV_REQUEST_NAME, &acquire_req) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set acquire request"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_rcapl_version_request() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_rcapl_version_request + * + * Purpose: Get the request type for acquring the container version, + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_rcapl_version_request(hid_t rcapl_id, H5RC_request_t *acquire_req) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Rc", rcapl_id, acquire_req); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(rcapl_id, H5P_RC_ACQUIRE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + if(acquire_req) { + /* Get property */ + if(H5P_get(plist, H5RC_ACQUIRE_CV_REQUEST_NAME, acquire_req) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get acquire request"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_rcapl_version_request() */ + + +/*------------------------------------------------------------------------- + * Function: H5RCcreate + * + * Purpose: Wraps an hid_t around a container version and a file ID. + * The user is responsible for making sure the container version + * is acquired. + * + * Return: Success: The ID for a new read context. + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5RCcreate(hid_t file_id, uint64_t c_version) +{ + void *file = NULL; + H5VL_t *vol_plugin = NULL; + H5RC_t *rc = NULL; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE2("i", "iIl", file_id, c_version); + + /* get the file object */ + if(NULL == (file = (void *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* create a new read context object */ + if(NULL == (rc = H5RC_create(file, c_version))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create read context") + + /* Get an atom for the event queue with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register2(H5I_RC, rc, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize read context handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5RCcreate() */ + + +/*------------------------------------------------------------------------- + * Function: H5RC_create + * + * Purpose: Private routine for H5RCcreate + * + * Return: Success: RC structure + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +H5RC_t * +H5RC_create(void *file, uint64_t c_version) +{ + H5RC_t *rc = NULL; + H5RC_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* allocate read context struct */ + if(NULL == (rc = H5FL_CALLOC(H5RC_t))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate read context structure") + + rc->file = (H5VL_iod_file_t *)file; + rc->c_version = c_version; + + rc->req_info.request = NULL; + rc->req_info.head = NULL; + rc->req_info.tail = NULL; + rc->req_info.num_req = 0; + + /* set return value */ + ret_value = rc; + +done: + if(!ret_value && rc) + rc = H5FL_FREE(H5RC_t, rc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RC_create() */ + +herr_t +H5RCget_version(hid_t rc_id, uint64_t *c_version) +{ + H5RC_t *rc = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Il", rc_id, c_version); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rc_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Read Context ID") + + *c_version = rc->c_version; + +done: + FUNC_LEAVE_API(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5RCacquire + * + * Purpose: Acquires a read context from a container for a container + * version c_version. The user can specify options to + * what container version to get if the one being asked for + * is not available. + * + * Return: Success: RC ID + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5RCacquire(hid_t file_id, uint64_t *c_version, + hid_t rcapl_id, hid_t estack_id) +{ + void *file = NULL; + H5VL_t *vol_plugin = NULL; + H5RC_t *rc = NULL; + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + hid_t rc_id = FAIL; + hid_t ret_value = FAIL; + + FUNC_ENTER_API(FAIL) + H5TRACE4("i", "i*Ilii", file_id, c_version, rcapl_id, estack_id); + + /* get the file object */ + if(NULL == (file = (void *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + /* Get correct property list */ + if(H5P_DEFAULT == rcapl_id) + rcapl_id = H5P_RC_ACQUIRE_DEFAULT; + else + if(TRUE != H5P_isa_class(rcapl_id, H5P_RC_ACQUIRE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not read context acquire property list") + + /* create a new read context object with the provided container + version. The container version associated with the RC object + might be changed if the version is not available for read. */ + if(NULL == (rc = H5RC_create(file, *c_version))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create read context") + /* Get an atom for the event queue with the VOL information as the auxilary struct*/ + if((rc_id = H5I_register2(H5I_RC, rc, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize read context handle") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_rc_acquire((H5VL_iod_file_t *)file, rc, c_version, rcapl_id, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a read context on container"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack") + } + + ret_value = rc_id; + +done: + if(ret_value < 0 && rc_id) { + if(H5I_dec_app_ref(rc_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close read context") + } + + FUNC_LEAVE_API(ret_value) +} /* end H5RCacquire() */ + + +/*------------------------------------------------------------------------- + * Function: H5RCrelease + * + * Purpose: Releases a previously acquired container version. Does not + * close the RC object (i.e. user has to call H5RCclose()). + * + * Return: Success: Non-Negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RCrelease(hid_t rc_id , hid_t estack_id) +{ + H5RC_t *rc = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", rc_id, estack_id); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rc_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Read Context ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(rc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_rc_release(rc, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a release on a read context on container"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5RCrelease() */ + + +/*------------------------------------------------------------------------- + * Function: H5RCpersist + * + * Purpose: Persists a previously acquired container version. + * + * Return: Success: Non-Negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RCpersist(hid_t rc_id , hid_t estack_id) +{ + H5RC_t *rc = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", rc_id, estack_id); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rc_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Read Context ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(rc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_rc_persist(rc, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a persist on a read context on container"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5RCpersist() */ + + +/*------------------------------------------------------------------------- + * Function: H5RCsnapshot + * + * Purpose: Creates a permanently visible snapshot of a container state. + * + * Return: Success: Non-Negative + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RCsnapshot(hid_t rc_id , const char *snapshot_name, hid_t estack_id) +{ + H5RC_t *rc = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*si", rc_id, snapshot_name, estack_id); + + /* Check arguments */ + if(!snapshot_name || !*snapshot_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid snapshot name") + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rc_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Read Context ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(rc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_rc_snapshot(rc, snapshot_name, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a snapshot on a read context on container"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5RCsnapshot() */ + + +/*------------------------------------------------------------------------- + * Function: H5RCclose + * + * Purpose: Closes the specified read context ID. The ID will no longer be + * valid for accessing the read context. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RCclose(hid_t rc_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", rc_id); + + /* Check args */ + if(NULL == H5I_object_verify(rc_id,H5I_RC)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an read context ID") + + if(H5I_dec_app_ref(rc_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close read context") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5RCclose() */ + + +/*------------------------------------------------------------------------- + * Function: H5RC_close + * + * Purpose: Closes the specified read context ID. The ID will no longer be + * valid for accessing the read context. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5RC_close(H5RC_t *rc) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(rc->req_info.num_req) { + H5VL_iod_request_t *cur_req = rc->req_info.head; + H5VL_iod_request_t *next_req = NULL; + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + while(cur_req) { + next_req = cur_req->trans_next; + + /* remove the current request from the linked list */ + prev = cur_req->trans_prev; + next = cur_req->trans_next; + if (prev) { + if (next) { + prev->trans_next = next; + next->trans_prev = prev; + } + else { + prev->trans_next = NULL; + rc->req_info.tail = prev; + } + } + else { + if (next) { + next->trans_prev = NULL; + rc->req_info.head = next; + } + else { + rc->req_info.head = NULL; + rc->req_info.tail = NULL; + } + } + + cur_req->trans_prev = NULL; + cur_req->trans_next = NULL; + + rc->req_info.num_req --; + + H5VL_iod_request_decr_rc(cur_req); + + cur_req = next_req; + } + HDassert(0 == rc->req_info.num_req); + } + + rc = H5FL_FREE(H5RC_t, rc); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5RC_close() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5RCprivate.h b/src/H5RCprivate.h new file mode 100644 index 0000000..a280ff9 --- /dev/null +++ b/src/H5RCprivate.h @@ -0,0 +1,70 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5RC module + */ +#ifndef _H5RCprivate_H +#define _H5RCprivate_H + +/* Include package's public header */ +#include "H5RCpublic.h" + +/* Private headers needed by this file */ +#include "H5private.h" /* Generic Functions */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5VLprivate.h" /* VOL plugins */ + +#ifdef H5_HAVE_EFF + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Request and Linked list info used in transactions and read contexts + to track dependencies. */ +typedef struct H5VL_iod_req_info_t { + struct H5VL_iod_request_t *request; + struct H5VL_iod_request_t *head; + struct H5VL_iod_request_t *tail; + size_t num_req; +} H5VL_iod_req_info_t; + +/* the client Read Context struct */ +typedef struct H5RC_t { + H5VL_iod_req_info_t req_info; /* must be first */ + struct H5VL_iod_file_t *file; + uint64_t c_version; +} H5RC_t; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/******************************/ +/* Library Private Prototypes */ +/******************************/ +herr_t H5RC_init(void); + +H5_DLL H5RC_t *H5RC_create(void *file, uint64_t c_version); +H5_DLL herr_t H5RC_close(H5RC_t *rcxt); + +#endif /* H5_HAVE_EFF */ + +#endif /* _H5RCprivate_H */ diff --git a/src/H5RCpublic.h b/src/H5RCpublic.h new file mode 100644 index 0000000..4fca5cb --- /dev/null +++ b/src/H5RCpublic.h @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5RC module. + */ +#ifndef _H5RCpublic_H +#define _H5RCpublic_H + +/* System headers needed by this file */ + +/* Public headers needed by this file */ + +/*****************/ +/* Public Macros */ +/*****************/ +#define H5RC_ACQUIRE_CV_REQUEST_NAME "acquire_request_name" + +/*******************/ +/* Public Typedefs */ +/*******************/ + +typedef enum H5RC_request_t{ + H5RC_EXACT, /* default */ + H5RC_PREV, + H5RC_NEXT, + H5RC_LAST +} H5RC_request_t; + +/********************/ +/* Public Variables */ +/********************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef H5_HAVE_EFF +/*********************/ +/* Public Prototypes */ +/*********************/ + +/* API wrappers */ +H5_DLL hid_t H5RCcreate(hid_t file_id, uint64_t container_version); +H5_DLL herr_t H5RCget_version(hid_t rcxt_id, uint64_t *c_version); +H5_DLL hid_t H5RCacquire(hid_t file_id, /*IN/OUT*/ uint64_t *container_version, + hid_t rcapl_id, hid_t estack_id); +H5_DLL herr_t H5RCrelease(hid_t rcxt_id , hid_t estack_id); +H5_DLL herr_t H5RCpersist(hid_t rcxt_id, hid_t estack_id); +H5_DLL herr_t H5RCsnapshot(hid_t rcxt_id, const char *snapshot_name, hid_t estack_id); +H5_DLL herr_t H5RCclose(hid_t rcxt_id); + +H5_DLL herr_t H5Pset_rcapl_version_request(hid_t rcapl_id, H5RC_request_t acquire_req); +H5_DLL herr_t H5Pget_rcapl_version_request(hid_t rcapl_id, H5RC_request_t *acquire_req); + +#endif /* H5_HAVE_EFF */ + +#ifdef __cplusplus +} +#endif +#endif /* _H5RCpublic_H */ @@ -55,8 +55,6 @@ static herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max); static htri_t H5S_is_simple(const H5S_t *sdim); -static herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc); -static H5S_t *H5S_decode(const unsigned char *buf); /*********************/ @@ -1502,7 +1500,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc) { size_t extent_size; /* Size of serialized dataspace extent */ @@ -1618,7 +1616,7 @@ done: * *------------------------------------------------------------------------- */ -static H5S_t* +H5S_t* H5S_decode(const unsigned char *buf) { H5S_t *ds; diff --git a/src/H5Shyper.c b/src/H5Shyper.c index c97c9b6..accc3a5 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -8856,3 +8856,79 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned UNUSED flags, H5S_sel_iter_t FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_hyper_get_seq_list() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_is_regular + PURPOSE + Check if hyperslab selection is a regular selection + RETURNS + TRUE/FALSE/FAIL +--------------------------------------------------------------------------*/ +htri_t +H5Sselect_is_regular(hid_t space_id) +{ + H5S_t *space; /* dataspace to modify */ + htri_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE1("t", "i", space_id); + + /* Check args and all the boring stuff. */ + if ((space = (H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)) == NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace") + + if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_HYPERSLABS) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "not a hyperslab selection") + + if(space->select.sel_info.hslab->diminfo_valid) + ret_value = TRUE; + else + ret_value = FALSE; + +done: + FUNC_LEAVE_API(ret_value) +} + + +/*-------------------------------------------------------------------------- + NAME + H5Sget_reg_hyperslab_params + PURPOSE + retrieve the start, stride, count, block arrays of a regular + hyperslab selection + RETURNS + TRUE/FALSE/FAIL +--------------------------------------------------------------------------*/ +herr_t +H5Sget_reg_hyperslab_params(hid_t space_id, hsize_t start[], hsize_t stride[], + hsize_t count[], hsize_t block[]) +{ + H5S_t *space = NULL; /* Dataspace to get selection of */ + const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ + unsigned ndims; /* Rank of the dataspace */ + unsigned u; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "i*h*h*h*h", space_id, start, stride, count, block); + + /* Check args */ + if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + if(!space->select.sel_info.hslab->diminfo_valid) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "not a regular hyperslab selection") + + diminfo = space->select.sel_info.hslab->opt_diminfo; + ndims = space->extent.rank; + + for(u=0 ; u<ndims; u++) { + start[u] = diminfo[u].start; + stride[u] = diminfo[u].stride; + count[u] = diminfo[u].count; + block[u] = diminfo[u].block; + } + +done: + FUNC_LEAVE_API(ret_value) +} diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 0e67af1..bee64a2 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -267,6 +267,14 @@ H5_DLL hsize_t H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter); H5_DLL herr_t H5S_select_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); H5_DLL herr_t H5S_select_iter_release(H5S_sel_iter_t *sel_iter); +H5_DLL herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc); +H5_DLL H5S_t *H5S_decode(const unsigned char *buf); + +H5_DLL herr_t H5S_get_offsets(const H5S_t *space, size_t elmt_size, size_t nelmts, + hsize_t **_off, size_t **_len, size_t *_num_entries); +H5_DLL uint64_t H5S_checksum(const void *buf, size_t elmt_size, size_t nelmts, + const H5S_t *space); + #ifdef H5_HAVE_PARALLEL /* Global vars whose value comes from environment variable */ /* (Defined in H5S.c) */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 6e87a65..f4f28f6 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -113,6 +113,13 @@ H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t _stride[], const hsize_t count[], const hsize_t _block[]); +H5_DLL htri_t H5Sselect_is_regular(hid_t space_id); +H5_DLL herr_t H5Sget_reg_hyperslab_params(hid_t space_id, + hsize_t start[], + hsize_t stride[], + hsize_t count[], + hsize_t block[]); + /* #define NEW_HYPERSLAB_API */ /* Note that these haven't been working for a while and were never * publicly released - QAK */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 44688b6..2400697 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -31,6 +31,9 @@ #include "H5Spkg.h" /* Dataspaces */ #include "H5VMprivate.h" /* Vector and array functions */ #include "H5WBprivate.h" /* Wrapped Buffers */ +#ifdef H5_HAVE_EFF +#include "mchecksum.h" /* Mercury Checksum library */ +#endif /* H5_HAVE_EFF */ /* Local functions */ #ifdef LATER @@ -2053,3 +2056,160 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5S_select_fill() */ + +/*------------------------------------------------------------------------- + * Function: H5S_get_offsets + * + * Purpose: Returns an offset/length pair array for a corresponding + * dataspace selecton. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_get_offsets(const H5S_t *space, size_t elmt_size, size_t nelmts, + hsize_t **_off, size_t **_len, size_t *_num_entries) +{ + H5S_sel_iter_t iter; /* Memory selection iteration info */ + hbool_t iter_init = 0; /* Memory selection iteration info has been initialized */ + size_t curr_seq; /* Current memory sequence to operate on */ + size_t nseq; /* Number of sequences generated in the file */ + hsize_t *off = NULL; + size_t *len = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (off = (hsize_t *)calloc(H5D_IO_VECTOR_SIZE, sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); + if(NULL == (len = (size_t *)calloc(H5D_IO_VECTOR_SIZE, sizeof(size_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); + + /* Check for only one element in selection */ + if(nelmts == 1) { + if(H5S_SELECT_OFFSET(space, off) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve memory selection offset"); + + /* Set up necessary information for I/O operation */ + nseq = 1; + *off *= elmt_size; + *len = elmt_size; + } /* end if */ + else { + size_t nelem; /* Number of elements used in sequences */ + size_t n = 2; + + /* Initialize iterator */ + if(H5S_select_iter_init(&iter, space, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + iter_init = 1; /* Memory selection iteration info has been initialized */ + + /* Initialize sequence counts */ + curr_seq = 0; + nseq = 0; + + /* Loop, until all bytes are processed */ + while(nelmts > 0) { + /* Get sequences for selection */ + if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, H5D_IO_VECTOR_SIZE, nelmts, &nseq, + &nelem, &off[curr_seq], &len[curr_seq]) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); + + /* check if more sequences are needed and extend the arrays if yes */ + nelmts -= nelem; + curr_seq += nseq; + + if(nelmts) { + HDassert(nseq == H5D_IO_VECTOR_SIZE); + if(NULL == (off = (hsize_t *)realloc(off, n * sizeof(hsize_t) * H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); + if(NULL == (len = (size_t *)realloc(len, n * sizeof(size_t) * H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); + } + n ++; + } /* end while */ + } /* end else */ + + *_off = off; + *_len = len; + *_num_entries = curr_seq; + +done: + /* Release memory selection iterator */ + if(iter_init) + if(H5S_SELECT_ITER_RELEASE(&iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_get_offsets() */ + +#ifdef H5_HAVE_EFF +uint64_t +H5S_checksum(const void *buf, size_t elmt_size, size_t nelmts, const H5S_t *space) +{ + H5S_sel_iter_t iter; /* Memory selection iteration info */ + hbool_t iter_init = 0; /* Memory selection iteration info has been initialized */ + hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */ + hsize_t *off = NULL; /* Pointer to sequence offsets in memory */ + size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */ + size_t *len = NULL; /* Pointer to sequence lengths in memory */ + size_t nseq; /* Number of sequences generated */ + size_t nelem; /* Number of elements used in sequences */ + size_t i; + const uint8_t *p = (const uint8_t *)buf; + const char *hash_method = "crc64"; + size_t hash_size; + mchecksum_object_t checksum; + uint64_t ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT + + len = _len; + off = _off; + + /* Initialize iterator */ + if(H5S_select_iter_init(&iter, space, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, 0, "unable to initialize selection iterator") + iter_init = 1; + + nseq = 0; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Loop, until all bytes are processed */ + while(nelmts > 0) { + /* Get sequences for selection */ + if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, H5D_IO_VECTOR_SIZE, nelmts, &nseq, + &nelem, off, len) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed"); + + for(i=0 ; i<nseq ; i++) { + mchecksum_update(checksum, p+off[i], len[i]); + } + nelmts -= nelem; + } /* end while */ + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &ret_value, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + +done: + /* Release memory selection iterator */ + if(iter_init) + if(H5S_SELECT_ITER_RELEASE(&iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, 0, "unable to release selection iterator") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_checksum */ +#endif /* H5_HAVE_EFF */ @@ -1750,6 +1750,7 @@ herr_t H5Tclose(hid_t type_id) { H5T_t *dt; /* Pointer to datatype to close */ + H5VL_t *vol_plugin = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -1761,6 +1762,15 @@ H5Tclose(hid_t type_id) if(H5T_STATE_IMMUTABLE == dt->shared->state) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype") + /* get the plugin pointer - + * if it exists, then we know that the datatype is committed, + * so we attach synchronous event q to it so it can pass through the VL layer. */ + if (NULL != (vol_plugin = (H5VL_t *)H5I_get_aux(type_id))) { + /* set the event queue and dxpl IDs to be passed on to the VOL layer */ + vol_plugin->close_estack_id = H5_EVENT_STACK_NULL; + vol_plugin->close_dxpl_id = H5AC_dxpl_id; + } + /* When the reference count reaches zero the resources are freed */ if(H5I_dec_app_ref(type_id) < 0) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id") diff --git a/src/H5TR.c b/src/H5TR.c new file mode 100644 index 0000000..8bdc8b5 --- /dev/null +++ b/src/H5TR.c @@ -0,0 +1,829 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.org> + * August, 2013 + * + * Purpose: Transaction APIs to support Exascale FastForward + * functionality. + * + */ + + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5TR_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5RCprivate.h" /* Read Contexts */ +#include "H5TRprivate.h" /* Transactions */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod_client.h" /* IOD VOL plugin */ + +#ifdef H5_HAVE_EFF + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5TR_t struct */ +H5FL_DEFINE(H5TR_t); + +/* Dataspace ID class */ +static const H5I_class_t H5I_TR_CLS[1] = {{ + H5I_TR, /* ID class value */ + 0, /* Class flags */ + 2, /* # of reserved IDs for class */ + (H5I_free_t)H5TR_close, /* Callback routine for closing objects of this class */ + NULL /* Callback routine for closing auxilary objects of this class */ +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5TR_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TR_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + /* FUNC_ENTER() does all the work */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5TR_init() */ + + +/*-------------------------------------------------------------------------- +NAME + H5TR_init_interface -- Initialize interface-specific information +USAGE + herr_t H5TR_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5TR_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Initialize the atom group for the TR IDs */ + if(H5I_register_type(H5I_TR_CLS) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5TR_init_interface() */ + + +/*-------------------------------------------------------------------------- + NAME + H5TR_term_interface + PURPOSE + Terminate various H5TR objects + USAGE + void H5TR_term_interface() + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Release the atom group and any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5TR_term_interface(void) +{ + int n = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + if((n = H5I_nmembers(H5I_TR))) { + H5I_clear_type(H5I_TR, FALSE, FALSE); + } /* end if */ + else { + /* Free data types */ + H5I_dec_type_ref(H5I_TR); + + /* Shut down interface */ + H5_interface_initialize_g = 0; + n = 1; /*H5I*/ + } /* end else */ + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* end H5TR_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_trspl_num_peers + * + * Purpose: Set the number of peers that will call H5TRstart for a + * transaction. If num_peers=0, the application has appointed a + * transaction leader to signal the start and finish of the + * transaction, and to coordinate with processes participating in the + * transaction regarding when they can begin updating and when their + * updates are done. When this is the case, only one process (the + * transaction leader) can call H5TRstart and H5TRfinish for the given + * transaction_num. This mode of operation is typical for + * tightly-coupled applications. If num_peers>0, the I/O stack (in + * particular, IOD) will track the status of the transaction. All + * num_peers processes participating in the transaction must call + * H5TRstart with the same values for num_peers and transaction_num. + * As each participating process is done with their updates in the + * transaction, they individually call H5TRfinish for this + * transaction_num. When all num_peers processes have called + * H5TRfinish for this transaction_num, the I/O stack detects that the + * transaction is finished and updates appear atomically when all + * lower-numbered transactions are finished, aborted, or skipped. + * This mode of operation is typical for loosely-coupled applications. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_trspl_num_peers(hid_t trspl_id, unsigned num_peers) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iIu", trspl_id, num_peers); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(trspl_id, H5P_TR_START))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Set property */ + if(H5P_set(plist, H5TR_START_NUM_PEERS_NAME, &num_peers) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set num peers in transaction"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_trspl_num_peers() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_trspl_num_peers + * + * Purpose: Get the number of peers that will call H5TRstart for a + * transaction. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_trspl_num_peers(hid_t trspl_id, unsigned *num_peers) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Iu", trspl_id, num_peers); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(trspl_id, H5P_TR_START))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Set property */ + if(H5P_get(plist, H5TR_START_NUM_PEERS_NAME, num_peers) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get num peers in transaction"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_trspl_num_peers() */ + + +/*------------------------------------------------------------------------- + * Function: H5TRcreate + * + * Purpose: Wraps an hid_t around a transaction number, a file ID, + * and a read context ID on that file that operations using + * the created transaction will read from. + * + * Return: Success: The ID for a new transaction. + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +hid_t +H5TRcreate(hid_t file_id, hid_t rc_id, uint64_t trans_num) +{ + void *file = NULL; + H5VL_t *vol_plugin = NULL; + H5TR_t *tr = NULL; + H5RC_t *rc = NULL; + hid_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE3("i", "iiIl", file_id, rc_id, trans_num); + + /* get the file object */ + if(NULL == (file = (void *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + /* get the Read Context object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rc_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a read context ID") + + /* create a new transaction object */ + if(NULL == (tr = H5TR_create(file, rc, trans_num))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create transaction object") + + /* Get an atom for the event queue with the VOL information as the auxilary struct*/ + if((ret_value = H5I_register2(H5I_TR, tr, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize transaction handle") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRcreate() */ + + +/*------------------------------------------------------------------------- + * Function: H5TR_create + * + * Purpose: Private version for H5TRcreate. + * + * Return: Success: Transaction struct. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +H5TR_t * +H5TR_create(void *file, H5RC_t *rc, uint64_t trans_num) +{ + H5TR_t *tr = NULL; + H5TR_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* allocate transaction struct */ + if(NULL == (tr = H5FL_CALLOC(H5TR_t))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate top transaction structure") + + tr->file = (H5VL_iod_file_t *)file; + tr->c_version = rc->c_version; + tr->trans_num = trans_num; + + tr->req_info.request = NULL; + tr->req_info.head = NULL; + tr->req_info.tail = NULL; + tr->req_info.num_req = 0; + + /* set return value */ + ret_value = tr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5TR_create() */ + +herr_t +H5TRget_trans_num(hid_t trans_id, uint64_t *trans_num) +{ + H5TR_t *tr = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Il", trans_id, trans_num); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a transaction ID") + + *trans_num = tr->trans_num; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5TRget_trans_num */ + +herr_t +H5TRget_version(hid_t trans_id, uint64_t *c_version) +{ + H5TR_t *tr = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Il", trans_id, c_version); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a transaction ID") + + *c_version = tr->c_version; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5TRget_version */ + + +/*------------------------------------------------------------------------- + * Function: H5TRstart + * + * Purpose: Starts a transaction that has been created with H5TRcreate. + * If the operation fails, the user is still reponsible to call + * H5TRclose() on the returned value to free resources. + * + * Return: Success: Non-Negative. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRstart(hid_t tr_id, hid_t trspl_id, hid_t estack_id) +{ + H5TR_t *tr = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iii", tr_id, trspl_id, estack_id); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(tr_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* Get correct property list */ + if(H5P_DEFAULT == trspl_id) + trspl_id = H5P_TR_START_DEFAULT; + else + if(TRUE != H5P_isa_class(trspl_id, H5P_TR_START)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not transaction start property list") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(tr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_tr_start(tr, trspl_id, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a transaction start"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRstart()*/ + + +/*------------------------------------------------------------------------- + * Function: H5TRfinish + * + * Purpose: Finishes/Commits a transaction. If rcxt_id is not NULL, + * create a read context from the finished transaction number. + * If the finish fails, the user is still reponsible to call + * H5RCclose() on the rcxt_id and H5TRclose() on the tr_id + * to free resources. + * + * Return: Success: Non-Negative. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRfinish(hid_t tr_id, hid_t trfpl_id, hid_t *rcxt_id, hid_t estack_id) +{ + H5TR_t *tr = NULL; + H5RC_t *rc = NULL; + hbool_t acquire = FALSE; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "ii*ii", tr_id, trfpl_id, rcxt_id, estack_id); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(tr_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* Get correct property list */ + if(H5P_DEFAULT == trfpl_id) + trfpl_id = H5P_TR_FINISH_DEFAULT; + else + if(TRUE != H5P_isa_class(trfpl_id, H5P_TR_FINISH)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not transaction finish property list") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(tr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + /* create a new read context object (if user requested it) with + the provided transaction number to finish */ + if(rcxt_id) { + acquire = TRUE; + + if(NULL == (rc = H5RC_create(tr->file, tr->trans_num))) + HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create read context"); + /* Get an atom for the event queue with the VOL information as the auxilary struct */ + if((*rcxt_id = H5I_register2(H5I_RC, rc, vol_plugin, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize read context handle"); + } + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_tr_finish(tr, acquire, trfpl_id, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a transaction finish"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRfinish()*/ + + +/*------------------------------------------------------------------------- + * Function: H5TRset_dependency + * + * Purpose: Set a depedency between two transactions. Transaction + * associated with tr_id is declaring a dependency on transaction + * numbered trans_num. trans_num must be < the transaction number + * tr_id is associated with. + * + * Return: Success: Non-Negative. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRset_dependency(hid_t tr_id, uint64_t trans_num, hid_t estack_id) +{ + H5TR_t *tr = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iIli", tr_id, trans_num, estack_id); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(tr_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(tr->trans_num <= trans_num) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "The dependent transaction must be higher than the one it depends on") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(tr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_tr_set_dependency(tr, trans_num, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a transaction set_dependency"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRset_dependency()*/ + + +/*------------------------------------------------------------------------- + * Function: H5TRskip + * + * Purpose: Skip a sequence of transaction numbers from the container. + * + * Return: Success: Non-Negative. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRskip(hid_t file_id, uint64_t start_trans_num, uint64_t count, hid_t estack_id) +{ + void *file = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE4("e", "iIlIli", file_id, start_trans_num, count, estack_id); + + /* get the file object */ + if(NULL == (file = (void *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_tr_skip((H5VL_iod_file_t *)file, start_trans_num, count, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a transaction skip"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRskip()*/ + + +/*------------------------------------------------------------------------- + * Function: H5TRabort + * + * Purpose: Aborts a transaction + * + * Return: Success: Non-Negative. + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRabort(hid_t tr_id, hid_t estack_id) +{ + H5TR_t *tr = NULL; + H5VL_t *vol_plugin = NULL; /* VOL plugin pointer this event queue should use */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event queue */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", tr_id, estack_id); + + /* get the plugin pointer */ + if (NULL == (vol_plugin = (H5VL_t *)H5I_get_aux(tr_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "ID does not contain VOL information"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(tr_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if(H5VL_iod_tr_abort(tr, req) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to request a transaction abort"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRabort()*/ + + +/*------------------------------------------------------------------------- + * Function: H5TRclose + * + * Purpose: Closes the specified transaction ID. The ID will no longer be + * valid for accessing the transaction. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TRclose(hid_t tr_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", tr_id); + + /* Check args */ + if(NULL == H5I_object_verify(tr_id, H5I_TR)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an transaction ID") + + if(H5I_dec_app_ref(tr_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close transaction") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5TRclose() */ + + +/*------------------------------------------------------------------------- + * Function: H5TR_close + * + * Purpose: Frees the transaction struct. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * August 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5TR_close(H5TR_t *tr) +{ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(tr->req_info.num_req) { + H5VL_iod_request_t *cur_req = tr->req_info.head; + H5VL_iod_request_t *next_req = NULL; + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + while(cur_req) { + next_req = cur_req->trans_next; + + /* remove the current request from the linked list */ + prev = cur_req->trans_prev; + next = cur_req->trans_next; + if (prev) { + if (next) { + prev->trans_next = next; + next->trans_prev = prev; + } + else { + prev->trans_next = NULL; + tr->req_info.tail = prev; + } + } + else { + if (next) { + next->trans_prev = NULL; + tr->req_info.head = next; + } + else { + tr->req_info.head = NULL; + tr->req_info.tail = NULL; + } + } + + cur_req->trans_prev = NULL; + cur_req->trans_next = NULL; + + tr->req_info.num_req --; + + H5VL_iod_request_decr_rc(cur_req); + + cur_req = next_req; + } + HDassert(0 == tr->req_info.num_req); + } + + tr = H5FL_FREE(H5TR_t, tr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5TR_close() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5TRprivate.h b/src/H5TRprivate.h new file mode 100644 index 0000000..70f5e5e --- /dev/null +++ b/src/H5TRprivate.h @@ -0,0 +1,59 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5TR module + */ +#ifndef _H5TRprivate_H +#define _H5TRprivate_H + +/* Include package's public header */ +#include "H5TRpublic.h" + +/* Private headers needed by this file */ +#include "H5RCprivate.h" /* Read Contexts */ + +/**************************/ +/* Library Private Macros */ +/**************************/ +#define H5TR_FINISH_ACQUIRE_NAME "acquire_after_finishing" + +#ifdef H5_HAVE_EFF + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* the transaction struct */ +typedef struct H5TR_t { + H5VL_iod_req_info_t req_info; /* must be first */ + struct H5VL_iod_file_t *file; + uint64_t c_version; + uint64_t trans_num; +} H5TR_t; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/******************************/ +/* Library Private Prototypes */ +/******************************/ +herr_t H5TR_init(void); + +H5_DLL H5TR_t *H5TR_create(void *file, H5RC_t *rc, uint64_t trans_num); +H5_DLL herr_t H5TR_close(H5TR_t *tr); + +#endif /* H5_HAVE_EFF */ +#endif /* _H5TRprivate_H */ diff --git a/src/H5TRpublic.h b/src/H5TRpublic.h new file mode 100644 index 0000000..c8ed982 --- /dev/null +++ b/src/H5TRpublic.h @@ -0,0 +1,71 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains function prototypes for each exported function in the + * H5TR module. + */ +#ifndef _H5TRpublic_H +#define _H5TRpublic_H + +/* System headers needed by this file */ + +/* Public headers needed by this file */ +#include "H5public.h" +#include "H5Ipublic.h" + +/*****************/ +/* Public Macros */ +/*****************/ +#define H5TR_START_NUM_PEERS_NAME "number_of_peers_name" + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/********************/ +/* Public Variables */ +/********************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef H5_HAVE_EFF + +/*********************/ +/* Public Prototypes */ +/*********************/ + +/* API wrappers */ +H5_DLL hid_t H5TRcreate(hid_t file_id, hid_t rc_id, uint64_t trans_num); +H5_DLL herr_t H5TRget_trans_num(hid_t trans_id, uint64_t *trans_num); +H5_DLL herr_t H5TRget_version(hid_t trans_id, uint64_t *c_version); +H5_DLL herr_t H5TRstart(hid_t trans_id, hid_t trspl_id, hid_t estack_id); +H5_DLL herr_t H5TRfinish(hid_t trans_id, hid_t trfpl_id, hid_t *rcntxt_id, hid_t estack_id); +H5_DLL herr_t H5TRskip(hid_t file_id, uint64_t start_trans_num, uint64_t count, hid_t estack_id); +H5_DLL herr_t H5TRset_dependency(hid_t trans_id, uint64_t trans_num, hid_t estack_id); +H5_DLL herr_t H5TRabort(hid_t trans_id, hid_t estack_id); +H5_DLL herr_t H5TRclose(hid_t trans_id); + +H5_DLL herr_t H5Pset_trspl_num_peers(hid_t trspl_id, unsigned num_peers); +H5_DLL herr_t H5Pget_trspl_num_peers(hid_t trspl_id, unsigned *num_peers); + +#endif /* H5_HAVE_EFF */ + +#ifdef __cplusplus +} +#endif +#endif /* _H5TRpublic_H */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index a483df7..9b1b1ae 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -1015,7 +1015,8 @@ H5T_close_datatype(void *type, H5VL_t *vol_plugin) /* Close the datatype through the VOL*/ if (NULL != dt->vol_obj) - if((ret_value = H5VL_datatype_close(dt->vol_obj, vol_plugin, H5AC_dxpl_id, H5_EVENT_STACK_NULL)) < 0) + if((ret_value = H5VL_datatype_close(dt->vol_obj, vol_plugin, + vol_plugin->close_dxpl_id, vol_plugin->close_estack_id)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype") done: diff --git a/src/H5Tnative.c b/src/H5Tnative.c index 1a97f39..2dee5f5 100644 --- a/src/H5Tnative.c +++ b/src/H5Tnative.c @@ -32,8 +32,6 @@ #include "H5Tpkg.h" /* Datatypes */ /* Static local functions */ -static H5T_t *H5T_get_native_type(H5T_t *dt, H5T_direction_t direction, - size_t *struct_align, size_t *offset, size_t *comp_size); static H5T_t *H5T_get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size); static H5T_t *H5T_get_native_float(size_t size, H5T_direction_t direction, @@ -147,7 +145,7 @@ done: * *------------------------------------------------------------------------- */ -static H5T_t * +H5T_t * H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) { H5T_t *dt; /* Datatype to make native */ diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 217a0d6..7bf21ef 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -166,5 +166,9 @@ H5_DLL int H5T_get_offset(const H5T_t *dt); /* Fixed-point functions */ H5_DLL H5T_sign_t H5T_get_sign(H5T_t const *dt); +/* Native type function */ +H5_DLL H5T_t *H5T_get_native_type(H5T_t *dt, H5T_direction_t direction, + size_t *struct_align, size_t *offset, size_t *comp_size); + #endif /* _H5Tprivate_H */ diff --git a/src/H5VLint.c b/src/H5VLint.c index 65250a1..b001cdf 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -39,6 +39,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ +#include "H5ESprivate.h" /* Event Stacks */ #include "H5Iprivate.h" /* IDs */ #include "H5Ipkg.h" /* IDs Package header */ #include "H5Lprivate.h" /* Links */ @@ -391,6 +392,11 @@ H5VL_object_register(void *obj, H5I_type_t obj_type, H5VL_t *vol_plugin, hbool_t HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize group handle") break; + case H5I_MAP: + if((ret_value = H5I_register2(obj_type, obj, vol_plugin, app_ref)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize map handle") + break; + case H5I_DATASET: if((ret_value = H5I_register2(obj_type, obj, vol_plugin, app_ref)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize dataset handle") @@ -407,6 +413,9 @@ H5VL_object_register(void *obj, H5I_type_t obj_type, H5VL_t *vol_plugin, hbool_t case H5I_REFERENCE: case H5I_VFL: case H5I_VOL: + case H5I_RC: + case H5I_TR: + case H5I_ES: case H5I_GENPROP_CLS: case H5I_GENPROP_LST: case H5I_ERROR_CLASS: @@ -475,8 +484,10 @@ done: */ void * H5VL_attr_create(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -485,12 +496,28 @@ H5VL_attr_create(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, co if(NULL == vol_plugin->cls->attr_cls.create) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `attr create' method") + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* call the corresponding VOL create callback */ if(NULL == (ret_value = (vol_plugin->cls->attr_cls.create) (obj, loc_params, name, acpl_id, - aapl_id, dxpl_id, H5_REQUEST_NULL))) + aapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "create failed") - vol_plugin->nrefs ++; + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_create() */ @@ -512,8 +539,10 @@ done: */ void * H5VL_attr_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t aapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t aapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -521,11 +550,30 @@ H5VL_attr_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, cons /* check if the type specific corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->attr_cls.open) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `attr open' method") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* call the corresponding VOL open callback */ - if(NULL == (ret_value = (vol_plugin->cls->attr_cls.open) (obj, loc_params, name, aapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->attr_cls.open) (obj, loc_params, name, aapl_id, + dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "attribute open failed") vol_plugin->nrefs ++; + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_open() */ @@ -546,17 +594,37 @@ done: *------------------------------------------------------------------------- */ herr_t H5VL_attr_read(void *attr, H5VL_t *vol_plugin, hid_t mem_type_id, void *buf, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) if(NULL == vol_plugin->cls->attr_cls.read) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `attr read' method") - if((ret_value = (vol_plugin->cls->attr_cls.read)(attr, mem_type_id, buf, dxpl_id, H5_REQUEST_NULL)) < 0) + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if((ret_value = (vol_plugin->cls->attr_cls.read)(attr, mem_type_id, buf, + dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "read failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_read() */ @@ -577,17 +645,37 @@ done: *------------------------------------------------------------------------- */ herr_t H5VL_attr_write(void *attr, H5VL_t *vol_plugin, hid_t mem_type_id, const void *buf, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) if(NULL == vol_plugin->cls->attr_cls.write) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `attr write' method") - if((ret_value = (vol_plugin->cls->attr_cls.write)(attr, mem_type_id, buf, dxpl_id, H5_REQUEST_NULL)) < 0) + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if((ret_value = (vol_plugin->cls->attr_cls.write)(attr, mem_type_id, buf, + dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "write failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_write() */ @@ -644,6 +732,8 @@ herr_t H5VL_attr_get(void *obj, H5VL_t *vol_plugin, H5VL_attr_get_t get_type, hid_t dxpl_id, hid_t estack_id, ...) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ va_list arguments; /* argument list passed from the API call */ herr_t ret_value = SUCCEED; @@ -651,26 +741,28 @@ H5VL_attr_get(void *obj, H5VL_t *vol_plugin, H5VL_attr_get_t get_type, if(NULL == vol_plugin->cls->attr_cls.get) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `attr get' method") + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + va_start (arguments, estack_id); - if((ret_value = (vol_plugin->cls->attr_cls.get)(obj, get_type, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->cls->attr_cls.get)(obj, get_type, dxpl_id, req, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed") va_end (arguments); -#if 0 - /* if the get_type is a named datatype, attach the vol info to it */ - if(H5VL_ATTR_GET_TYPE == get_type) { - hid_t *ret_id; - - va_start (arguments, estack_id); - ret_id = va_arg (arguments, hid_t *); - if(H5Tcommitted(*ret_id)) { - /* attach VOL information to the ID */ - if (H5I_register_aux(*ret_id, vol_plugin, (H5I_free_t)H5VL_close) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't attach vol info to ID") - } - va_end (arguments); + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); } -#endif + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_get() */ @@ -692,17 +784,36 @@ done: */ herr_t H5VL_attr_remove(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, - const char *attr_name, hid_t dxpl_id, hid_t UNUSED estack_id) + const char *attr_name, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) if(NULL == vol_plugin->cls->attr_cls.remove) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `attr remove' method") - if((ret_value = (vol_plugin->cls->attr_cls.remove)(obj, loc_params, attr_name, dxpl_id, H5_REQUEST_NULL)) < 0) + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if((ret_value = (vol_plugin->cls->attr_cls.remove)(obj, loc_params, attr_name, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTDELETE, FAIL, "remove failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_remove() */ @@ -723,22 +834,31 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_attr_close(void *attr, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_attr_close(void *attr, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) /* if the VOL class does not implement a specific attr close callback, try the object close */ - if(NULL == vol_plugin->cls->attr_cls.close){ + if(NULL == vol_plugin->cls->attr_cls.close) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `attr close' method") - /* - if(H5VL_object_close(id, dxpl_id, estack_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close object") - */ + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; } - else if((ret_value = (vol_plugin->cls->attr_cls.close)(attr, dxpl_id, H5_REQUEST_NULL)) < 0) + + if((ret_value = (vol_plugin->cls->attr_cls.close)(attr, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") vol_plugin->nrefs --; @@ -748,6 +868,11 @@ H5VL_attr_close(void *attr, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED esta vol_plugin = (H5VL_t *)H5MM_xfree(vol_plugin); } + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_attr_close() */ @@ -770,9 +895,11 @@ done: void * H5VL_datatype_commit(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { - void *ret_value = NULL; /* Return value */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -780,12 +907,28 @@ H5VL_datatype_commit(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin if(NULL == vol_plugin->cls->datatype_cls.commit) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `datatype commit' method") + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* call the corresponding VOL commit callback */ if(NULL == (ret_value = (vol_plugin->cls->datatype_cls.commit) - (obj, loc_params, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, H5_REQUEST_NULL))) + (obj, loc_params, name, type_id, lcpl_id, tcpl_id, tapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "commit failed") vol_plugin->nrefs ++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_datatype_commit() */ @@ -807,31 +950,40 @@ done: */ void * H5VL_datatype_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t tapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t tapl_id, hid_t dxpl_id, hid_t estack_id) { - void *ret_value = NULL; /* Return value */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) /* check if the type specific corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->datatype_cls.open) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "no datatype open callback"); -#if 0 - H5VL_loc_params_t loc_params; - loc_params.type = H5VL_OBJECT_BY_NAME; - loc_params.loc_data.loc_by_name.name = name; - loc_params.loc_data.loc_by_name.plist_id = tapl_id; + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } - /* Open the object class */ - if((ret_value = H5VL_object_open(id, loc_params, dxpl_id, estack_id)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to open object") -#endif /* call the corresponding VOL open callback */ - if(NULL == (ret_value = (vol_plugin->cls->datatype_cls.open)(obj, loc_params, name, tapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->datatype_cls.open)(obj, loc_params, name, tapl_id, + dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") vol_plugin->nrefs ++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_datatype_open() */ @@ -853,8 +1005,10 @@ done: */ ssize_t H5VL_datatype_get_binary(void *obj, H5VL_t *vol_plugin, unsigned char *buf, size_t size, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ ssize_t ret_value = FAIL; FUNC_ENTER_NOAPI(FAIL) @@ -862,10 +1016,27 @@ H5VL_datatype_get_binary(void *obj, H5VL_t *vol_plugin, unsigned char *buf, size /* check if the type specific corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->datatype_cls.get_binary) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "no datatype get_binary callback"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* call the corresponding VOL open callback */ - if((ret_value = (vol_plugin->cls->datatype_cls.get_binary)(obj, buf, size, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->datatype_cls.get_binary)(obj, buf, size, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "get binary failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_datatype_get_binary() */ @@ -921,8 +1092,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_datatype_close(void *dt, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_datatype_close(void *dt, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -931,8 +1104,19 @@ H5VL_datatype_close(void *dt, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED es if(NULL == vol_plugin->cls->datatype_cls.close) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `datatype close' method") + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* call the corresponding VOL close callback */ - if((ret_value = (vol_plugin->cls->datatype_cls.close)(dt, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->datatype_cls.close)(dt, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") vol_plugin->nrefs --; @@ -941,6 +1125,11 @@ H5VL_datatype_close(void *dt, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED es vol_plugin = (H5VL_t *)H5MM_xfree(vol_plugin); } + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_datatype_close() */ @@ -962,20 +1151,39 @@ done: */ void * H5VL_dataset_create(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL create callback exists */ if(NULL == vol_plugin->cls->dataset_cls.create) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `dataset create' method") /* call the corresponding VOL create callback */ - if(NULL == (ret_value = (vol_plugin->cls->dataset_cls.create)(obj, loc_params, name, dcpl_id, dapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->dataset_cls.create)(obj, loc_params, name, dcpl_id, + dapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "create failed") vol_plugin->nrefs ++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_dataset_create() */ @@ -997,12 +1205,25 @@ done: */ void * H5VL_dataset_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t dapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the type specific corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->dataset_cls.open) { ; @@ -1014,11 +1235,18 @@ H5VL_dataset_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, c } else { /* call the corresponding VOL open callback */ - if(NULL == (ret_value = (vol_plugin->cls->dataset_cls.open)(obj, loc_params, name, dapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->dataset_cls.open)(obj, loc_params, name, + dapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") vol_plugin->nrefs ++; } + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_dataset_open() */ @@ -1040,18 +1268,36 @@ done: */ herr_t H5VL_dataset_read(void *dset, H5VL_t *vol_plugin, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t plist_id, void *buf, hid_t UNUSED estack_id) + hid_t file_space_id, hid_t plist_id, void *buf, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->dataset_cls.read) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `dataset read' method") if((ret_value = (vol_plugin->cls->dataset_cls.read) - (dset, mem_type_id, mem_space_id, file_space_id, plist_id, buf, H5_REQUEST_NULL)) < 0) + (dset, mem_type_id, mem_space_id, file_space_id, plist_id, buf, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "read failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_dataset_read() */ @@ -1073,18 +1319,36 @@ done: */ herr_t H5VL_dataset_write(void *dset, H5VL_t *vol_plugin, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t plist_id, const void *buf, hid_t UNUSED estack_id) + hid_t file_space_id, hid_t plist_id, const void *buf, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->dataset_cls.write) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `dataset write' method") if((ret_value = (vol_plugin->cls->dataset_cls.write) - (dset, mem_type_id, mem_space_id, file_space_id, plist_id, buf, H5_REQUEST_NULL)) < 0) + (dset, mem_type_id, mem_space_id, file_space_id, plist_id, buf, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "write failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_dataset_write() */ @@ -1106,17 +1370,35 @@ done: */ herr_t H5VL_dataset_set_extent(void *dset, H5VL_t *vol_plugin, const hsize_t size[], - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->dataset_cls.set_extent) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `dataset set_extent' method") - if((ret_value = (vol_plugin->cls->dataset_cls.set_extent)(dset, size, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->dataset_cls.set_extent)(dset, size, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "set_extent failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_dataset_set_extent() */ @@ -1149,7 +1431,8 @@ H5VL_dataset_get(void *dset, H5VL_t *vol_plugin, H5VL_dataset_get_t get_type, HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `dataset get' method") va_start (arguments, estack_id); - if((ret_value = (vol_plugin->cls->dataset_cls.get)(dset, get_type, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->cls->dataset_cls.get)(dset, get_type, dxpl_id, + H5_REQUEST_NULL, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed") va_end (arguments); @@ -1190,24 +1473,30 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_dataset_close(void *dset, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_dataset_close(void *dset, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT - /* if the VOL class does not implement a specific dataset close - callback, try the object close */ - if(NULL == vol_plugin->cls->dataset_cls.close){ - ; -#if 0 - if(H5VL_object_close(id, dxpl_id, dxpl_id, estack_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close object") -#endif + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; } - else { - if((ret_value = (vol_plugin->cls->dataset_cls.close)(dset, dxpl_id, H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") + if((ret_value = (vol_plugin->cls->dataset_cls.close)(dset, dxpl_id, req)) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); } vol_plugin->nrefs --; @@ -1236,38 +1525,56 @@ done: *------------------------------------------------------------------------- */ void * -H5VL_file_create(H5VL_t **plugin, const char *name, unsigned flags, hid_t fcpl_id, - hid_t fapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_file_create(H5VL_t **plugin, const char *filename, unsigned flags, hid_t fcpl_id, + hid_t fapl_id, hid_t dxpl_id, hid_t estack_id) { H5P_genplist_t *plist; /* Property list pointer */ H5VL_class_t *vol_cls; /* VOL class attached to fapl_id */ H5VL_t *vol_plugin = NULL; /* the public VOL struct */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) /* get the VOL info from the fapl */ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); if(H5P_get(plist, H5F_ACS_VOL_NAME, &vol_cls) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get vol plugin ID") - - /* check if the corresponding VOL create callback exists */ - if(NULL == vol_cls->file_cls.create) - HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `file create' method") - /* call the corresponding VOL create callback */ - if(NULL == (ret_value = (vol_cls->file_cls.create)(name, flags, fcpl_id, fapl_id, dxpl_id, H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "create failed") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get vol plugin ID"); /* Build the vol plugin struct */ if(NULL == (*plugin = (H5VL_t *)H5MM_calloc(sizeof(H5VL_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - vol_plugin = *plugin; vol_plugin->cls = vol_cls; vol_plugin->nrefs = 1; - if((vol_plugin->container_name = H5MM_xstrdup(name)) == NULL) - HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,NULL,"memory allocation failed") + if((vol_plugin->container_name = H5MM_xstrdup(filename)) == NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,NULL,"memory allocation failed"); + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* check if the corresponding VOL create callback exists */ + if(NULL == vol_cls->file_cls.create) + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `file create' method") + /* call the corresponding VOL create callback */ + if(NULL == (ret_value = (vol_cls->file_cls.create)(filename, flags, fcpl_id, fapl_id, + dxpl_id, req))) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "create failed"); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -1289,12 +1596,14 @@ done: *------------------------------------------------------------------------- */ void * -H5VL_file_open(H5VL_t **plugin, const char *name, unsigned flags, hid_t fapl_id, - hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_file_open(H5VL_t **plugin, const char *filename, unsigned flags, hid_t fapl_id, + hid_t dxpl_id, hid_t estack_id) { H5P_genplist_t *plist; /* Property list pointer */ H5VL_class_t *vol_cls; /* VOL class attached to fapl_id */ H5VL_t *vol_plugin = NULL; /* the public VOL struct */ + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -1305,23 +1614,39 @@ H5VL_file_open(H5VL_t **plugin, const char *name, unsigned flags, hid_t fapl_id, if(H5P_get(plist, H5F_ACS_VOL_NAME, &vol_cls) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get vol plugin ID") - /* check if the corresponding VOL create callback exists */ - if(NULL == vol_cls->file_cls.open) - HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `file open' method") - /* call the corresponding VOL create callback */ - if(NULL == (ret_value = (vol_cls->file_cls.open)(name, flags, fapl_id, dxpl_id, H5_REQUEST_NULL))) - HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") - /* Build the vol plugin struct */ if(NULL == (*plugin = (H5VL_t *)H5MM_calloc(sizeof(H5VL_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - vol_plugin = *plugin; vol_plugin->cls = vol_cls; vol_plugin->nrefs = 1; - if((vol_plugin->container_name = H5MM_xstrdup(name)) == NULL) + if((vol_plugin->container_name = H5MM_xstrdup(filename)) == NULL) HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,NULL,"memory allocation failed") + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + /* check if the corresponding VOL create callback exists */ + if(NULL == vol_cls->file_cls.open) + HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `file open' method") + /* call the corresponding VOL create callback */ + if(NULL == (ret_value = (vol_cls->file_cls.open)(filename, flags, fapl_id, + dxpl_id, req))) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_file_open() */ @@ -1343,17 +1668,36 @@ done: */ herr_t H5VL_file_flush(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, H5F_scope_t scope, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->file_cls.flush) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `file flush' method") - if((ret_value = (vol_plugin->cls->file_cls.flush)(obj, loc_params, scope, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->file_cls.flush)(obj, loc_params, scope, + dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTFLUSH, FAIL, "flush failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_file_flush() */ @@ -1508,17 +1852,35 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_file_close(void *file, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_file_close(void *file, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT + + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } if(NULL == vol_plugin->cls->file_cls.close) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `file close' method") - if((ret_value = (vol_plugin->cls->file_cls.close)(file, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->file_cls.close)(file, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTCLOSEFILE, FAIL, "close failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + vol_plugin->nrefs --; if (0 == vol_plugin->nrefs) { vol_plugin->container_name = (const char *)H5MM_xfree(vol_plugin->container_name); @@ -1546,20 +1908,39 @@ done: */ void * H5VL_group_create(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(NULL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL create callback exists */ if(NULL == vol_plugin->cls->group_cls.create) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `group create' method") /* call the corresponding VOL create callback */ - if(NULL == (ret_value = (vol_plugin->cls->group_cls.create)(obj, loc_params, name, gcpl_id, gapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->group_cls.create)(obj, loc_params, name, gcpl_id, + gapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "create failed") vol_plugin->nrefs ++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_group_create() */ @@ -1581,12 +1962,25 @@ done: */ void * H5VL_group_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, const char *name, - hid_t gapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t gapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the type specific corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->group_cls.open) { ; @@ -1598,10 +1992,17 @@ H5VL_group_open(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, con } else { /* call the corresponding VOL open callback */ - if(NULL == (ret_value = (vol_plugin->cls->group_cls.open)(obj, loc_params, name, gapl_id, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->group_cls.open)(obj, loc_params, name, + gapl_id, dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") vol_plugin->nrefs ++; } + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_group_open() */ @@ -1657,25 +2058,32 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_group_close(void *grp, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_group_close(void *grp, H5VL_t *vol_plugin, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT - /* if the VOL class does not implement a specific group close - callback, try the object close */ - if(NULL == vol_plugin->cls->group_cls.close) { - ; -#if 0 - if(H5VL_object_close(id, dxpl_id, estack_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close object") -#endif + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + + if((ret_value = (vol_plugin->cls->group_cls.close)(grp, dxpl_id, req)) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); } - else { - if((ret_value = (vol_plugin->cls->group_cls.close)(grp, dxpl_id, H5_REQUEST_NULL)) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") - } vol_plugin->nrefs --; if (0 == vol_plugin->nrefs) { @@ -1702,20 +2110,38 @@ done: */ herr_t H5VL_link_create(H5VL_link_create_type_t create_type, void *obj, H5VL_loc_params_t loc_params, - H5VL_t *vol_plugin, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + H5VL_t *vol_plugin, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL create callback exists */ if(NULL == vol_plugin->cls->link_cls.create) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `link create' method") /* call the corresponding VOL create callback */ if((ret_value = (vol_plugin->cls->link_cls.create) - (create_type, obj, loc_params, lcpl_id, lapl_id, dxpl_id, H5_REQUEST_NULL)) < 0) + (create_type, obj, loc_params, lcpl_id, lapl_id, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "link create failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_link_create() */ @@ -1736,20 +2162,38 @@ done: herr_t H5VL_link_move(void *src_obj, H5VL_loc_params_t loc_params1, void *dst_obj, H5VL_loc_params_t loc_params2, H5VL_t *vol_plugin, hbool_t copy_flag, - hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL move callback exists */ if(NULL == vol_plugin->cls->link_cls.move) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `link move' method") /* call the corresponding VOL move callback */ if((ret_value = (vol_plugin->cls->link_cls.move) - (src_obj, loc_params1, dst_obj, loc_params2, copy_flag, lcpl_id, lapl_id, dxpl_id, H5_REQUEST_NULL)) < 0) + (src_obj, loc_params1, dst_obj, loc_params2, copy_flag, lcpl_id, lapl_id, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "link move failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_link_move() */ @@ -1771,18 +2215,36 @@ done: herr_t H5VL_link_iterate(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, hbool_t recursive, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, - H5L_iterate_t op, void *op_data, hid_t dxpl_id, hid_t UNUSED estack_id) + H5L_iterate_t op, void *op_data, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->link_cls.iterate) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `link iterate' method") if((ret_value = (vol_plugin->cls->link_cls.iterate)(obj, loc_params, recursive, idx_type, - order, idx, op, op_data, dxpl_id, H5_REQUEST_NULL)) < 0) + order, idx, op, op_data, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, FAIL, "iteration failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_link_iterate() */ @@ -1806,18 +2268,36 @@ herr_t H5VL_link_get(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, H5VL_link_get_t get_type, hid_t dxpl_id, hid_t estack_id, ...) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ va_list arguments; /* argument list passed from the API call */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->link_cls.get) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `link get' method") va_start (arguments, estack_id); - if((ret_value = (vol_plugin->cls->link_cls.get)(obj, loc_params, get_type, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->cls->link_cls.get)(obj, loc_params, get_type, dxpl_id, req, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed") va_end (arguments); + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_link_get() */ @@ -1837,19 +2317,37 @@ done: */ herr_t H5VL_link_remove(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL remove callback exists */ if(NULL == vol_plugin->cls->link_cls.remove) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `link remove' method") /* call the corresponding VOL remove callback */ - if((ret_value = (vol_plugin->cls->link_cls.remove)(obj, loc_params, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->link_cls.remove)(obj, loc_params, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "link remove failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_link_remove() */ @@ -1871,20 +2369,39 @@ done: */ void * H5VL_object_open(void *obj, H5VL_loc_params_t params, H5VL_t *vol_plugin, H5I_type_t *opened_type, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + /* check if the corresponding VOL open callback exists */ if(NULL == vol_plugin->cls->object_cls.open) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "vol plugin has no `object open' method") /* call the corresponding VOL open callback */ - if(NULL == (ret_value = (vol_plugin->cls->object_cls.open)(obj, params, opened_type, dxpl_id, H5_REQUEST_NULL))) + if(NULL == (ret_value = (vol_plugin->cls->object_cls.open)(obj, params, opened_type, + dxpl_id, req))) HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "open failed") vol_plugin->nrefs++; + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, NULL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_open() */ @@ -1906,22 +2423,41 @@ done: herr_t H5VL_object_copy(void *src_obj, H5VL_loc_params_t loc_params1, H5VL_t *vol_plugin1, const char *src_name, void *dst_obj, H5VL_loc_params_t loc_params2, H5VL_t *vol_plugin2, const char *dst_name, - hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin1; + } + /* check if both objects are associated with the same VOL plugin */ if(vol_plugin1->cls != vol_plugin2->cls) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "Objects are accessed through different VOL plugins and can't be copied") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "Objects are accessed through different VOL plugins and can't be copied") if(NULL == vol_plugin1->cls->object_cls.copy) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object copy' method") if((ret_value = (vol_plugin1->cls->object_cls.copy) - (src_obj, loc_params1, src_name, dst_obj, loc_params2, dst_name, ocpypl_id, lcpl_id, dxpl_id, H5_REQUEST_NULL)) < 0) + (src_obj, loc_params1, src_name, dst_obj, loc_params2, dst_name, + ocpypl_id, lcpl_id, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "copy failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_copy() */ @@ -1942,19 +2478,37 @@ done: */ herr_t H5VL_object_visit(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op, - void *op_data, hid_t dxpl_id, hid_t UNUSED estack_id) + void *op_data, hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->object_cls.visit) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object visit' method") if((ret_value = (vol_plugin->cls->object_cls.visit)(obj, loc_params, idx_type, order, op, - op_data, dxpl_id, H5_REQUEST_NULL)) < 0) + op_data, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_BADITER, FAIL, "object visitation failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_visit() */ @@ -1992,7 +2546,7 @@ H5VL_object_lookup(hid_t id, H5VL_loc_type_t lookup_type, void **location, HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object lookup' method") va_start (arguments, estack_id); - if((ret_value = (vol_plugin->object_cls.lookup)(id, lookup_type, location, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->object_cls.lookup)(id, lookup_type, location, dxpl_id, req, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "lookup of object location failed") va_end (arguments); done: @@ -2014,7 +2568,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5VL_object_free_loc(hid_t id, void *location, hid_t dxpl_id, hid_t UNUSED estack_id) +H5VL_object_free_loc(hid_t id, void *location, hid_t dxpl_id, hid_t estack_id) { H5VL_class_t *vol_plugin; /* VOL structure attached to id */ herr_t ret_value = SUCCEED; @@ -2027,7 +2581,7 @@ H5VL_object_free_loc(hid_t id, void *location, hid_t dxpl_id, hid_t UNUSED estac if(NULL == vol_plugin->object_cls.free_loc) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object free_loc' method") - if((ret_value = (vol_plugin->object_cls.free_loc)(location, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->object_cls.free_loc)(location, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "freeing location token of object location failed") done: @@ -2054,18 +2608,38 @@ herr_t H5VL_object_get(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, H5VL_object_get_t get_type, hid_t dxpl_id, hid_t estack_id, ...) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ va_list arguments; /* argument list passed from the API call */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->object_cls.get) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object get' method") va_start (arguments, estack_id); - if((ret_value = (vol_plugin->cls->object_cls.get)(obj, loc_params, get_type, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->cls->object_cls.get)(obj, loc_params, get_type, + dxpl_id, req, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "get failed") va_end (arguments); + + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_get() */ @@ -2088,19 +2662,38 @@ herr_t H5VL_object_misc(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, H5VL_object_misc_t misc_type, hid_t dxpl_id, hid_t estack_id, ...) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ va_list arguments; /* argument list passed from the API call */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->object_cls.misc) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object misc' method") va_start (arguments, estack_id); - if((ret_value = (vol_plugin->cls->object_cls.misc)(obj, loc_params, misc_type, dxpl_id, H5_REQUEST_NULL, arguments)) < 0) + if((ret_value = (vol_plugin->cls->object_cls.misc)(obj, loc_params, misc_type, + dxpl_id, req, arguments)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "misc failed") va_end (arguments); + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_misc() */ @@ -2122,17 +2715,35 @@ done: */ herr_t H5VL_object_close(void *obj, H5VL_loc_params_t loc_params, H5VL_t *vol_plugin, - hid_t dxpl_id, hid_t UNUSED estack_id) + hid_t dxpl_id, hid_t estack_id) { + H5_priv_request_t *request = NULL; /* private request struct inserted in event stack */ + void **req = NULL; /* pointer to plugin generate requests (Stays NULL if plugin does not support async */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(FAIL) + if(estack_id != H5_EVENT_STACK_NULL) { + /* create the private request */ + if(NULL == (request = (H5_priv_request_t *)H5MM_calloc(sizeof(H5_priv_request_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + request->req = NULL; + req = &request->req; + request->next = NULL; + request->vol_plugin = vol_plugin; + vol_plugin->nrefs ++; + } + if(NULL == vol_plugin->cls->object_cls.close) HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "vol plugin has no `object close' method") - if((ret_value = (vol_plugin->cls->object_cls.close)(obj, loc_params, dxpl_id, H5_REQUEST_NULL)) < 0) + if((ret_value = (vol_plugin->cls->object_cls.close)(obj, loc_params, dxpl_id, req)) < 0) HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "close failed") + if(request && *req) { + if(H5ES_insert(estack_id, request) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "failed to insert request in event stack"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5VL_object_close() */ diff --git a/src/H5VLiod.c b/src/H5VLiod.c new file mode 100644 index 0000000..7308184 --- /dev/null +++ b/src/H5VLiod.c @@ -0,0 +1,9251 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * February, 2012 + * + * Purpose: The IOD VOL plugin where access is forwarded to the IOD library + * by the function shipper. + */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5VL_iod_init_interface + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FDprivate.h" /* file drivers */ +#include "H5FFprivate.h" /* Fast Forward */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspaces */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod.h" /* Iod VOL plugin */ +#include "H5VLiod_client.h" /* Client IOD helper */ + +#ifdef H5_HAVE_EFF + +#define H5VL_IOD_MAX_ADDR_NAME 256 + +/* function shipper IDs for different routines */ +static hg_id_t H5VL_EFF_INIT_ID; +static hg_id_t H5VL_EFF_FINALIZE_ID; +static hg_id_t H5VL_ANALYSIS_EXECUTE_ID; +static hg_id_t H5VL_FILE_CREATE_ID; +static hg_id_t H5VL_FILE_OPEN_ID; +static hg_id_t H5VL_FILE_CLOSE_ID; +static hg_id_t H5VL_ATTR_CREATE_ID; +static hg_id_t H5VL_ATTR_OPEN_ID; +static hg_id_t H5VL_ATTR_READ_ID; +static hg_id_t H5VL_ATTR_WRITE_ID; +static hg_id_t H5VL_ATTR_EXISTS_ID; +static hg_id_t H5VL_ATTR_ITERATE_ID; +static hg_id_t H5VL_ATTR_RENAME_ID; +static hg_id_t H5VL_ATTR_REMOVE_ID; +static hg_id_t H5VL_ATTR_CLOSE_ID; +static hg_id_t H5VL_GROUP_CREATE_ID; +static hg_id_t H5VL_GROUP_OPEN_ID; +static hg_id_t H5VL_GROUP_CLOSE_ID; +static hg_id_t H5VL_MAP_CREATE_ID; +static hg_id_t H5VL_MAP_OPEN_ID; +static hg_id_t H5VL_MAP_SET_ID; +static hg_id_t H5VL_MAP_GET_ID; +static hg_id_t H5VL_MAP_GET_COUNT_ID; +static hg_id_t H5VL_MAP_EXISTS_ID; +static hg_id_t H5VL_MAP_ITERATE_ID; +static hg_id_t H5VL_MAP_DELETE_ID; +static hg_id_t H5VL_MAP_CLOSE_ID; +static hg_id_t H5VL_DSET_CREATE_ID; +static hg_id_t H5VL_DSET_OPEN_ID; +static hg_id_t H5VL_DSET_READ_ID; +static hg_id_t H5VL_DSET_GET_VL_SIZE_ID; +static hg_id_t H5VL_DSET_WRITE_ID; +static hg_id_t H5VL_DSET_SET_EXTENT_ID; +static hg_id_t H5VL_DSET_CLOSE_ID; +static hg_id_t H5VL_DTYPE_COMMIT_ID; +static hg_id_t H5VL_DTYPE_OPEN_ID; +static hg_id_t H5VL_DTYPE_CLOSE_ID; +static hg_id_t H5VL_LINK_CREATE_ID; +static hg_id_t H5VL_LINK_MOVE_ID; +static hg_id_t H5VL_LINK_ITERATE_ID; +static hg_id_t H5VL_LINK_EXISTS_ID; +static hg_id_t H5VL_LINK_GET_INFO_ID; +static hg_id_t H5VL_LINK_GET_VAL_ID; +static hg_id_t H5VL_LINK_REMOVE_ID; +static hg_id_t H5VL_OBJECT_OPEN_BY_TOKEN_ID; +static hg_id_t H5VL_OBJECT_OPEN_ID; +static hg_id_t H5VL_OBJECT_COPY_ID; +static hg_id_t H5VL_OBJECT_EXISTS_ID; +static hg_id_t H5VL_OBJECT_VISIT_ID; +static hg_id_t H5VL_OBJECT_SET_COMMENT_ID; +static hg_id_t H5VL_OBJECT_GET_COMMENT_ID; +static hg_id_t H5VL_OBJECT_GET_INFO_ID; +static hg_id_t H5VL_RC_ACQUIRE_ID; +static hg_id_t H5VL_RC_RELEASE_ID; +static hg_id_t H5VL_RC_PERSIST_ID; +static hg_id_t H5VL_RC_SNAPSHOT_ID; +static hg_id_t H5VL_TR_START_ID; +static hg_id_t H5VL_TR_FINISH_ID; +static hg_id_t H5VL_TR_SET_DEPEND_ID; +static hg_id_t H5VL_TR_SKIP_ID; +static hg_id_t H5VL_TR_ABORT_ID; +static hg_id_t H5VL_PREFETCH_ID; +static hg_id_t H5VL_EVICT_ID; +static hg_id_t H5VL_CANCEL_OP_ID; + + +/* global AXE list struct */ +typedef struct H5VL_iod_axe_list_t { + H5VL_iod_request_t *head; + H5VL_iod_request_t *tail; + AXE_task_t last_released_task; +} H5VL_iod_axe_list_t; + +static na_addr_t PEER; +static na_class_t *network_class = NULL; + +static AXE_task_t g_axe_id; +static H5VL_iod_axe_list_t axe_list; + +/* Prototypes */ +static void *H5VL_iod_fapl_copy(const void *_old_fa); +static herr_t H5VL_iod_fapl_free(void *_fa); + +/* Atrribute callbacks */ +static void *H5VL_iod_attribute_create(void *obj, H5VL_loc_params_t loc_params, const char *attr_name, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); +static void *H5VL_iod_attribute_open(void *obj, H5VL_loc_params_t loc_params, const char *attr_name, hid_t aapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_attribute_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_attribute_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_attribute_get(void *obj, H5VL_attr_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_attribute_remove(void *obj, H5VL_loc_params_t loc_params, const char *attr_name, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_attribute_close(void *attr, hid_t dxpl_id, void **req); + +/* Datatype callbacks */ +static void *H5VL_iod_datatype_commit(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id, void **req); +static void *H5VL_iod_datatype_open(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t tapl_id, hid_t dxpl_id, void **req); +static ssize_t H5VL_iod_datatype_get_binary(void *obj, unsigned char *buf, size_t size, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_datatype_get(void *obj, H5VL_datatype_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_datatype_close(void *dt, hid_t dxpl_id, void **req); + +/* Dataset callbacks */ +static void *H5VL_iod_dataset_create(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req); +static void *H5VL_iod_dataset_open(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t dapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, void *buf, void **req); +static herr_t H5VL_iod_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, const void *buf, void **req); +static herr_t H5VL_iod_dataset_set_extent(void *dset, const hsize_t size[], hid_t dxpl_id, void **req); +static herr_t H5VL_iod_dataset_get(void *dset, H5VL_dataset_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_dataset_close(void *dset, hid_t dxpl_id, void **req); + +/* File callbacks */ +static void *H5VL_iod_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id, void **req); +static void *H5VL_iod_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_file_get(void *file, H5VL_file_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_file_close(void *file, hid_t dxpl_id, void **req); + +/* Group callbacks */ +static void *H5VL_iod_group_create(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id, void **req); +static void *H5VL_iod_group_open(void *obj, H5VL_loc_params_t loc_params, const char *name, hid_t gapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_group_get(void *obj, H5VL_group_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_group_close(void *grp, hid_t dxpl_id, void **req); + +/* Link callbacks */ +static herr_t H5VL_iod_link_create(H5VL_link_create_type_t create_type, void *obj, + H5VL_loc_params_t loc_params, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_link_move(void *src_obj, H5VL_loc_params_t loc_params1, + void *dst_obj, H5VL_loc_params_t loc_params2, + hbool_t copy_flag, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_link_iterate(void *obj, H5VL_loc_params_t loc_params, hbool_t recursive, + H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, + H5L_iterate_t op, void *op_data, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_link_get(void *obj, H5VL_loc_params_t loc_params, H5VL_link_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_link_remove(void *obj, H5VL_loc_params_t loc_params, hid_t dxpl_id, void **req); + +/* Object callbacks */ +static void *H5VL_iod_object_open(void *obj, H5VL_loc_params_t loc_params, H5I_type_t *opened_type, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_object_copy(void *src_obj, H5VL_loc_params_t loc_params1, const char *src_name, + void *dst_obj, H5VL_loc_params_t loc_params2, const char *dst_name, + hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_object_visit(void *obj, H5VL_loc_params_t loc_params, H5_index_t idx_type, + H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t dxpl_id, void **req); +static herr_t H5VL_iod_object_get(void *obj, H5VL_loc_params_t loc_params, H5VL_object_get_t get_type, hid_t dxpl_id, void **req, va_list arguments); +static herr_t H5VL_iod_object_misc(void *obj, H5VL_loc_params_t loc_params, H5VL_object_misc_t misc_type, hid_t dxpl_id, void **req, va_list arguments); + +static herr_t H5VL_iod_cancel(void **req, H5ES_status_t *status); +static herr_t H5VL_iod_test(void **req, H5ES_status_t *status); +static herr_t H5VL_iod_wait(void **req, H5ES_status_t *status); + +/* IOD-specific file access properties */ +typedef struct H5VL_iod_fapl_t { + MPI_Comm comm; /*communicator */ + MPI_Info info; /*file information */ +} H5VL_iod_fapl_t; + +H5FL_DEFINE(H5VL_iod_file_t); +H5FL_DEFINE(H5VL_iod_attr_t); +H5FL_DEFINE(H5VL_iod_group_t); +H5FL_DEFINE(H5VL_iod_map_t); +H5FL_DEFINE(H5VL_iod_dset_t); +H5FL_DEFINE(H5VL_iod_dtype_t); + +static H5VL_class_t H5VL_iod_g = { + IOD, + "iod", /* name */ + NULL, /* initialize */ + NULL, /* terminate */ + sizeof(H5VL_iod_fapl_t), /*fapl_size */ + H5VL_iod_fapl_copy, /*fapl_copy */ + H5VL_iod_fapl_free, /*fapl_free */ + { /* attribute_cls */ + H5VL_iod_attribute_create, /* create */ + H5VL_iod_attribute_open, /* open */ + H5VL_iod_attribute_read, /* read */ + H5VL_iod_attribute_write, /* write */ + NULL,//H5VL_iod_attr_iterate, /* iterate */ + H5VL_iod_attribute_get, /* get */ + H5VL_iod_attribute_remove, /* remove */ + H5VL_iod_attribute_close /* close */ + }, + { /* datatype_cls */ + H5VL_iod_datatype_commit, /* commit */ + H5VL_iod_datatype_open, /* open */ + H5VL_iod_datatype_get_binary, /* get_size */ + H5VL_iod_datatype_get, /* get */ + H5VL_iod_datatype_close /* close */ + }, + { /* dataset_cls */ + H5VL_iod_dataset_create, /* create */ + H5VL_iod_dataset_open, /* open */ + H5VL_iod_dataset_read, /* read */ + H5VL_iod_dataset_write, /* write */ + H5VL_iod_dataset_set_extent, /* set extent */ + H5VL_iod_dataset_get, /* get */ + H5VL_iod_dataset_close /* close */ + }, + { /* file_cls */ + H5VL_iod_file_create, /* create */ + H5VL_iod_file_open, /* open */ + NULL, /* flush */ + H5VL_iod_file_get, /* get */ + NULL, /* misc */ + NULL, /* optional */ + H5VL_iod_file_close /* close */ + }, + { /* group_cls */ + H5VL_iod_group_create, /* create */ + H5VL_iod_group_open, /* open */ + H5VL_iod_group_get, /* get */ + H5VL_iod_group_close /* close */ + }, + { /* link_cls */ + H5VL_iod_link_create, /* create */ + H5VL_iod_link_move, /* move */ + H5VL_iod_link_iterate, /* iterate */ + H5VL_iod_link_get, /* get */ + H5VL_iod_link_remove /* remove */ + }, + { /* object_cls */ + H5VL_iod_object_open, /* open */ + H5VL_iod_object_copy, /* copy */ + H5VL_iod_object_visit, /* visit */ + H5VL_iod_object_get, /* get */ + H5VL_iod_object_misc, /* misc */ + NULL, /* optional */ + NULL /* close */ + }, + { + H5VL_iod_cancel, + H5VL_iod_test, + H5VL_iod_wait + } +}; + + +/*-------------------------------------------------------------------------- +NAME + H5VL_iod_init_interface -- Initialize interface-specific information +USAGE + herr_t H5VL_iod_init_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5VL_iod_init currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5VL_iod_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5VL_iod_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_init + * + * Purpose: Initialize this vol plugin by registering the driver with the + * library. + * + * Return: Success: The ID for the iod plugin. + * Failure: Negative. + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +H5VL_class_t * +H5VL_iod_init(void) +{ + H5VL_class_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Set return value */ + ret_value = &H5VL_iod_g; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_request_remove_from_axe_list + * + * Purpose: Utility routine to remove a node from the global list of + * AXE tasks. + * + * Return: Success: Positive + * Failure: Negative. + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_request_remove_from_axe_list(H5VL_iod_request_t *request) +{ + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(request); + + prev = request->global_prev; + next = request->global_next; + + if (prev) { + if (next) { + prev->global_next = next; + next->global_prev = prev; + } + else { + prev->global_next = NULL; + axe_list.tail = prev; + } + } + else { + if (next) { + next->global_prev = NULL; + axe_list.head = next; + } + else { + axe_list.head = NULL; + axe_list.tail = NULL; + } + } + + request->global_prev = NULL; + request->global_next = NULL; + + H5VL_iod_request_decr_rc(request); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL__iod_request_remove_from_axe_list() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_request_add_to_axe_list + * + * Purpose: Utility routine to add a node to the global list of AXE + * tasks. This routine also checks which tasks have completed + * and can be freed by the VOL callback that is calling this + * routine, and updates the last_released_task global variable + * accordingly. + * + * Return: Success: Positive + * Failure: Negative. + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_request_add_to_axe_list(H5VL_iod_request_t *request) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(request); + + if (axe_list.tail) { + axe_list.tail->global_next = request; + request->global_prev = axe_list.tail; + axe_list.tail = request; + } + else { + axe_list.head = request; + axe_list.tail = request; + request->global_prev = NULL; + } + + request->global_next = NULL; + request->ref_count ++; + + /* process axe_list */ + while(axe_list.head && /* If there is a head request */ + /* and the only reference is from this global axe list OR + from the axe list and the file list */ + (axe_list.head->ref_count == 1 || (axe_list.head->ref_count == 2 && request->req != NULL)) && + /* and the request has completed */ + H5VL_IOD_COMPLETED == axe_list.head->state) { + + /* add the axe IDs to the ones to free. */ + axe_list.last_released_task = axe_list.head->axe_id; + + /* remove head from axe list */ + H5VL__iod_request_remove_from_axe_list(axe_list.head); + } + + FUNC_LEAVE_NOAPI(SUCCEED) +}/* end H5VL__iod_request_add_to_axe_list() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_create_and_forward + * + * Purpose: Utility routine to create a mercury request and a + * VOL IOD request and ship the op to the server. + * + * Return: Success: Positive + * Failure: Negative. + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__iod_create_and_forward(hg_id_t op_id, H5RQ_type_t op_type, + H5VL_iod_object_t *request_obj, htri_t track, + size_t num_parents, H5VL_iod_request_t **parent_reqs, + H5VL_iod_req_info_t *req_info, + void *input, void *output, void *data, void **req) +{ + hg_request_t *hg_req = NULL; + H5VL_iod_request_t *request = NULL; + hbool_t do_async = (req == NULL) ? FALSE : TRUE; /* Whether we're performing async. I/O */ + axe_t *axe_info = (axe_t *) input; + AXE_task_t *parent_axe_ids = NULL; + unsigned u; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get a function shipper request */ + if(NULL == (hg_req = (hg_request_t *)H5MM_malloc(sizeof(hg_request_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate a HG request"); + + /* Get async request for operation */ + if(NULL == (request = (H5VL_iod_request_t *)H5MM_malloc(sizeof(H5VL_iod_request_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate IOD VOL request struct"); + + /* get axe ID for operation */ + axe_info->axe_id = g_axe_id ++; + + /* Set up request */ + HDmemset(request, 0, sizeof(*request)); + request->type = op_type; + request->data = data; + request->req = hg_req; + request->ref_count = 1; + request->obj = request_obj; + request->axe_id = axe_info->axe_id; + request->file_next = request->file_prev = NULL; + request->global_next = request->global_prev = NULL; + + if(do_async) + request->trans_info = req_info; + + /* add request to container's linked list */ + if(HG_ANALYSIS_EXECUTE != op_type) + H5VL_iod_request_add(request_obj->file, request); + + /* update the parent information in the request */ + request->num_parents = num_parents; + request->parent_reqs = parent_reqs; + + if(num_parents) { + if(NULL == (parent_axe_ids = (AXE_task_t *)H5MM_malloc(sizeof(AXE_task_t) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent axe IDs"); + + for(u=0 ; u<num_parents ; u++) + parent_axe_ids[u] = parent_reqs[u]->axe_id; + } + + axe_info->num_parents = num_parents; + axe_info->parent_axe_ids = parent_axe_ids; + + axe_info->start_range = axe_list.last_released_task + 1; + /* add request to global axe's linked list */ + H5VL__iod_request_add_to_axe_list(request); + axe_info->count = axe_list.last_released_task - axe_info->start_range + 1; + +#if H5VL_IOD_DEBUG + printf("Operation %"PRIu64" Dependencies: ", request->axe_id); + for(u=0 ; u<num_parents ; u++) + printf("%"PRIu64" ", axe_info->parent_axe_ids[u]); + printf("\n"); + + if(axe_info->count) { + printf("Operation %"PRIu64" will finish tasks %"PRIu64" through %"PRIu64"\n", + request->axe_id, axe_info->start_range, + axe_info->start_range+axe_info->count-1); + } +#endif + + /* forward the call to the ION */ + if(HG_Forward(PEER, op_id, input, output, hg_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + + /* Store/wait on request */ + if(do_async) { + *req = request; + + /* Track request */ + if(track) + request_obj->request = request; + } /* end if */ + else { + if(track) + request_obj->request = NULL; + + if(HG_ANALYSIS_EXECUTE == op_type) { + int ret; + hg_status_t status; + + /* test the operation status */ + ret = HG_Wait(*((hg_request_t *)request->req), HG_MAX_IDLE_TIME, &status); + if(HG_FAIL == ret) { + fprintf(stderr, "failed to wait on request\n"); + request->status = H5ES_STATUS_FAIL; + request->state = H5VL_IOD_COMPLETED; + } + else { + if(status) { + request->status = H5ES_STATUS_SUCCEED; + request->state = H5VL_IOD_COMPLETED; + } + } + } + else { + /* Synchronously wait on the request */ + if(H5VL_iod_request_wait(request_obj->file, request) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on HG request"); + } + + /* Since the operation is synchronous, return FAIL if the status failed */ + if(H5ES_STATUS_FAIL == request->status) { + ret_value = FAIL; + } + + request->req = H5MM_xfree(request->req); + H5VL_iod_request_decr_rc(request); + } /* end else */ + +done: + parent_axe_ids = (AXE_task_t *)H5MM_xfree(parent_axe_ids); + FUNC_LEAVE_NOAPI(ret_value) +}/* end H5VL__iod_create_and_forward() */ + + +/*------------------------------------------------------------------------- + * Function: EFF_init + * + * Purpose: initialize to the EFF stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +EFF_init(MPI_Comm comm, MPI_Info UNUSED info) +{ + //char mpi_port_name[MPI_MAX_PORT_NAME]; + int tag = 123456; + hg_request_t hg_req; + int num_procs, my_rank; + na_addr_t ion_target; + double axe_seed; + char addr_name[H5VL_IOD_MAX_ADDR_NAME]; + herr_t ret_value = SUCCEED; + + MPI_Comm_size(comm, &num_procs); + MPI_Comm_rank(comm, &my_rank); + + /* generate global variables to create and track axe_ids for every + operation. Each process owns a portion of the ID space and uses + that space incrementally. */ + axe_seed = (pow(2.0,64.0) - 1) / num_procs; + g_axe_id = (AXE_task_t)(axe_seed * my_rank + 1); + + axe_list.last_released_task = g_axe_id - 1; + axe_list.head = NULL; + axe_list.tail = NULL; + + /* MSC - This is a temporary solution for connecting to the server + using mercury */ + /* Only rank 0 reads file */ + if (my_rank == 0) { + int count, line=0, num_ions; + FILE *config; + char config_addr_name[H5VL_IOD_MAX_ADDR_NAME]; + + config = fopen("port.cfg", "r"); + + fscanf(config, "%d\n", &num_ions); + +#if H5VL_IOD_DEBUG + printf("Found %d servers\n", num_ions); +#endif + + /* read a line */ + if(fgets(config_addr_name, H5VL_IOD_MAX_ADDR_NAME, config) != NULL) { + strncpy(addr_name, config_addr_name, H5VL_IOD_MAX_ADDR_NAME); + count = 1; + while(num_procs > line + (count*num_ions)) { + MPI_Send(config_addr_name, H5VL_IOD_MAX_ADDR_NAME, MPI_BYTE, + line + (count*num_ions), tag, comm); + count ++; + } + line++; + } + + while (fgets(config_addr_name, H5VL_IOD_MAX_ADDR_NAME, config) != NULL) { + count = 0; + while(num_procs > line + (count*num_ions)) { + MPI_Send(config_addr_name, H5VL_IOD_MAX_ADDR_NAME, MPI_BYTE, + line + (count*num_ions), tag, comm); + count ++; + } + line ++; + } + fclose(config); + } + else { + MPI_Recv(addr_name, H5VL_IOD_MAX_ADDR_NAME, MPI_BYTE, + 0, tag, comm, MPI_STATUS_IGNORE); + } + +#if H5VL_IOD_DEBUG + printf("CN %d Connecting to ION %s\n", my_rank, addr_name); +#endif + + /* initialize Mercury stuff */ + network_class = NA_MPI_Init(NULL, 0); + + if (HG_SUCCESS != HG_Init(network_class)) { + fprintf(stderr, "Failed to initialize Mercury\n"); + return FAIL; + } + if (NA_SUCCESS != NA_Addr_lookup_wait(network_class, addr_name, &ion_target)) { + fprintf(stderr, "Server lookup failed\n"); + return FAIL; + } + + PEER = ion_target; + + /* Register function and encoding/decoding functions */ + H5VL_EFF_INIT_ID = MERCURY_REGISTER("eff_init", eff_init_in_t, ret_t); + H5VL_EFF_FINALIZE_ID = MERCURY_REGISTER("eff_finalize", ret_t, ret_t); + + H5VL_ANALYSIS_EXECUTE_ID = MERCURY_REGISTER("analysis_execute", + analysis_execute_in_t, + analysis_execute_out_t); + + H5VL_FILE_CREATE_ID = MERCURY_REGISTER("file_create", file_create_in_t, file_create_out_t); + H5VL_FILE_OPEN_ID = MERCURY_REGISTER("file_open", file_open_in_t, file_open_out_t); + H5VL_FILE_CLOSE_ID = MERCURY_REGISTER("file_close", file_close_in_t, ret_t); + + H5VL_ATTR_CREATE_ID = MERCURY_REGISTER("attr_create", attr_create_in_t, attr_create_out_t); + H5VL_ATTR_OPEN_ID = MERCURY_REGISTER("attr_open", attr_open_in_t, attr_open_out_t); + H5VL_ATTR_READ_ID = MERCURY_REGISTER("attr_read", attr_io_in_t, ret_t); + H5VL_ATTR_WRITE_ID = MERCURY_REGISTER("attr_write", attr_io_in_t, ret_t); + H5VL_ATTR_EXISTS_ID = MERCURY_REGISTER("attr_exists", attr_op_in_t, htri_t); + H5VL_ATTR_ITERATE_ID = MERCURY_REGISTER("attr_iterate", attr_op_in_t, ret_t); + H5VL_ATTR_RENAME_ID = MERCURY_REGISTER("attr_rename", attr_rename_in_t, ret_t); + H5VL_ATTR_REMOVE_ID = MERCURY_REGISTER("attr_remove", attr_op_in_t, ret_t); + H5VL_ATTR_CLOSE_ID = MERCURY_REGISTER("attr_close", attr_close_in_t, ret_t); + + H5VL_GROUP_CREATE_ID = MERCURY_REGISTER("group_create", group_create_in_t, group_create_out_t); + H5VL_GROUP_OPEN_ID = MERCURY_REGISTER("group_open", group_open_in_t, group_open_out_t); + H5VL_GROUP_CLOSE_ID = MERCURY_REGISTER("group_close", group_close_in_t, ret_t); + + H5VL_MAP_CREATE_ID = MERCURY_REGISTER("map_create", map_create_in_t, map_create_out_t); + H5VL_MAP_OPEN_ID = MERCURY_REGISTER("map_open", map_open_in_t, map_open_out_t); + H5VL_MAP_SET_ID = MERCURY_REGISTER("map_set", map_set_in_t, ret_t); + H5VL_MAP_GET_ID = MERCURY_REGISTER("map_get", map_get_in_t, map_get_out_t); + H5VL_MAP_GET_COUNT_ID = MERCURY_REGISTER("map_get_count", map_get_count_in_t, int64_t); + H5VL_MAP_ITERATE_ID = MERCURY_REGISTER("map_iterate", map_op_in_t, ret_t); + H5VL_MAP_EXISTS_ID = MERCURY_REGISTER("map_exists", map_op_in_t, hbool_t); + H5VL_MAP_DELETE_ID = MERCURY_REGISTER("map_delete", map_op_in_t, ret_t); + H5VL_MAP_CLOSE_ID = MERCURY_REGISTER("map_close", map_close_in_t, ret_t); + + H5VL_DSET_CREATE_ID = MERCURY_REGISTER("dset_create", dset_create_in_t, dset_create_out_t); + H5VL_DSET_OPEN_ID = MERCURY_REGISTER("dset_open", dset_open_in_t, dset_open_out_t); + H5VL_DSET_READ_ID = MERCURY_REGISTER("dset_read", dset_io_in_t, dset_read_out_t); + H5VL_DSET_GET_VL_SIZE_ID = MERCURY_REGISTER("dset_get_vl_size", dset_io_in_t, dset_read_out_t); + H5VL_DSET_WRITE_ID = MERCURY_REGISTER("dset_write", dset_io_in_t, ret_t); + H5VL_DSET_SET_EXTENT_ID = MERCURY_REGISTER("dset_set_extent", + dset_set_extent_in_t, ret_t); + H5VL_DSET_CLOSE_ID = MERCURY_REGISTER("dset_close", dset_close_in_t, ret_t); + + H5VL_DTYPE_COMMIT_ID = MERCURY_REGISTER("dtype_commit", dtype_commit_in_t, dtype_commit_out_t); + H5VL_DTYPE_OPEN_ID = MERCURY_REGISTER("dtype_open", dtype_open_in_t, dtype_open_out_t); + H5VL_DTYPE_CLOSE_ID = MERCURY_REGISTER("dtype_close", dtype_close_in_t, ret_t); + + H5VL_LINK_CREATE_ID = MERCURY_REGISTER("link_create", link_create_in_t, ret_t); + H5VL_LINK_MOVE_ID = MERCURY_REGISTER("link_move", link_move_in_t, ret_t); + H5VL_LINK_EXISTS_ID = MERCURY_REGISTER("link_exists", link_op_in_t, htri_t); + H5VL_LINK_GET_INFO_ID = MERCURY_REGISTER("link_get_info", link_op_in_t, linfo_t); + H5VL_LINK_GET_VAL_ID = MERCURY_REGISTER("link_get_val", link_get_val_in_t, + link_get_val_out_t); + H5VL_LINK_ITERATE_ID = MERCURY_REGISTER("link_iterate", link_op_in_t, ret_t); + H5VL_LINK_REMOVE_ID = MERCURY_REGISTER("link_remove", link_op_in_t, ret_t); + + H5VL_OBJECT_OPEN_BY_TOKEN_ID = MERCURY_REGISTER("object_open_by_token", + object_token_in_t, iod_handles_t); + H5VL_OBJECT_OPEN_ID = MERCURY_REGISTER("object_open", object_op_in_t, object_open_out_t); + H5VL_OBJECT_COPY_ID = MERCURY_REGISTER("object_copy", object_copy_in_t, ret_t); + H5VL_OBJECT_EXISTS_ID = MERCURY_REGISTER("object_exists", object_op_in_t, htri_t); + H5VL_OBJECT_VISIT_ID = MERCURY_REGISTER("object_visit", object_op_in_t, ret_t); + H5VL_OBJECT_SET_COMMENT_ID = MERCURY_REGISTER("set_comment", object_set_comment_in_t, ret_t); + H5VL_OBJECT_GET_COMMENT_ID = MERCURY_REGISTER("get_comment", object_get_comment_in_t, + object_get_comment_out_t); + H5VL_OBJECT_GET_INFO_ID = MERCURY_REGISTER("object_get_info", object_op_in_t, oinfo_t); + + H5VL_RC_ACQUIRE_ID = MERCURY_REGISTER("read_context_acquire", + rc_acquire_in_t, rc_acquire_out_t); + H5VL_RC_RELEASE_ID = MERCURY_REGISTER("read_context_release", rc_release_in_t, ret_t); + H5VL_RC_PERSIST_ID = MERCURY_REGISTER("read_context_persist", rc_persist_in_t, ret_t); + H5VL_RC_SNAPSHOT_ID = MERCURY_REGISTER("read_context_snapshot", rc_snapshot_in_t, ret_t); + + H5VL_TR_START_ID = MERCURY_REGISTER("transaction_start", tr_start_in_t, ret_t); + H5VL_TR_FINISH_ID = MERCURY_REGISTER("transaction_finish", tr_finish_in_t, ret_t); + H5VL_TR_SET_DEPEND_ID = MERCURY_REGISTER("transaction_set_depend",tr_set_depend_in_t, ret_t); + H5VL_TR_SKIP_ID = MERCURY_REGISTER("transaction_skip", tr_skip_in_t, ret_t); + H5VL_TR_ABORT_ID = MERCURY_REGISTER("transaction_abort",tr_abort_in_t, ret_t); + + H5VL_PREFETCH_ID = MERCURY_REGISTER("prefetch", prefetch_in_t, hrpl_t); + H5VL_EVICT_ID = MERCURY_REGISTER("evict", evict_in_t, ret_t); + + H5VL_CANCEL_OP_ID = MERCURY_REGISTER("cancel_op", uint64_t, uint8_t); + + /* forward the init call to the ION and wait for its completion */ + if(HG_SUCCESS != HG_Forward(PEER, H5VL_EFF_INIT_ID, &num_procs, &ret_value, &hg_req)) { + fprintf(stderr, "Failed to initialize Stack\n"); + return FAIL; + } + + /* Wait for it to compete */ + HG_Wait(hg_req, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE); + + /* Free Mercury request */ + if(HG_Request_free(hg_req) != HG_SUCCESS) + return FAIL; + + return ret_value; +} /* end EFF_init() */ + + +/*------------------------------------------------------------------------- + * Function: EFF_finalize + * + * Purpose: shutdown the EFF stack + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +EFF_finalize(void) +{ + hg_request_t hg_req; + herr_t ret_value = SUCCEED; + + H5VL_iod_request_t *cur_req = axe_list.head; + + /* process axe_list */ + while(cur_req) { + H5VL_iod_request_t *next_req = NULL; + + next_req = cur_req->global_next; + + HDassert(H5VL_IOD_COMPLETED == cur_req->state); + HDassert(cur_req->ref_count == 1); + + /* add the axe IDs to the ones to free. */ + axe_list.last_released_task = cur_req->axe_id; + + /* remove head from axe list */ + H5VL__iod_request_remove_from_axe_list(cur_req); + + cur_req = next_req; + } + + /* forward the finalize call to the ION and wait for it to complete */ + if(HG_Forward(PEER, H5VL_EFF_FINALIZE_ID, &ret_value, &ret_value, &hg_req) < 0) + return FAIL; + + HG_Wait(hg_req, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE); + + /* Free Mercury request */ + if(HG_Request_free(hg_req) != HG_SUCCESS) + return FAIL; + + /* Free addr id */ + if (NA_SUCCESS != NA_Addr_free(network_class, PEER)) + return FAIL; + + /* Finalize interface */ + //if (HG_SUCCESS != HG_Bulk_finalize()) + //return FAIL; + + if (HG_SUCCESS != HG_Finalize()) + return FAIL; + + if(NA_SUCCESS != NA_Finalize(network_class)) + return FAIL; + + return ret_value; +} /* end EFF_finalize() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_fapl_iod + * + * Purpose: Modify the file access property list to use the H5VL_IOD + * plugin defined in this source file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_fapl_iod(hid_t fapl_id, MPI_Comm comm, MPI_Info info) +{ + H5VL_iod_fapl_t fa; + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "iMcMi", fapl_id, comm, info); + + if(fapl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + + if(MPI_COMM_NULL == comm) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid communicator") + + /* Initialize driver specific properties */ + fa.comm = comm; + fa.info = info; + + ret_value = H5P_set_vol(plist, &H5VL_iod_g, &fa); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_fapl_iod() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_fapl_copy + * + * Purpose: Copies the iod-specific file access properties. + * + * Return: Success: Ptr to a new property list + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_fapl_copy(const void *_old_fa) +{ + const H5VL_iod_fapl_t *old_fa = (const H5VL_iod_fapl_t*)_old_fa; + H5VL_iod_fapl_t *new_fa = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (new_fa = (H5VL_iod_fapl_t *)H5MM_malloc(sizeof(H5VL_iod_fapl_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* Copy the general information */ + /* HDmemcpy(new_fa, old_fa, sizeof(H5VL_iod_fapl_t)); */ + + /* Duplicate communicator and Info object. */ + if(FAIL == H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info, &new_fa->comm, &new_fa->info)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed"); + + ret_value = new_fa; + +done: + if (NULL == ret_value){ + /* cleanup */ + if (new_fa) + H5MM_xfree(new_fa); + } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_fapl_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_fapl_free + * + * Purpose: Frees the iod-specific file access properties. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * July 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_fapl_free(void *_fa) +{ + herr_t ret_value = SUCCEED; + H5VL_iod_fapl_t *fa = (H5VL_iod_fapl_t*)_fa; + + FUNC_ENTER_NOAPI_NOINIT + + assert(fa); + + /* Free the internal communicator and INFO object */ + assert(MPI_COMM_NULL!=fa->comm); + if(H5FD_mpi_comm_info_free(&fa->comm, &fa->info) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "Communicator/Info free failed"); + /* free the struct */ + H5MM_xfree(fa); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_fapl_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_ocpl_enable_checksum + * + * Purpose: Set a boolean flag on the object creation property list + * to indicate to the VOL plugin to enable checksum on the + * object to be created. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * January, 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_ocpl_enable_checksum(hid_t ocpl_id, hbool_t flag) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ib", ocpl_id, flag); + + if(ocpl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(ocpl_id, H5P_OBJECT_CREATE))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a ocpl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5O_CRT_ENABLE_CHECKSUM_NAME, &flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_ocpl_enable_checksum() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_ocpl_enable_checksum + * + * Purpose: Retrieve a boolean flag on the object creation property + * list that indicates whether checksuming on this object + * is enabled or not. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * January, 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_ocpl_enable_checksum(hid_t ocpl_id, hbool_t *flag/*out*/) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", ocpl_id, flag); + + if(NULL == (plist = H5P_object_verify(ocpl_id, H5P_OBJECT_CREATE))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a ocpl") + + /* Get the transfer mode */ + if(flag) + if(H5P_get(plist, H5O_CRT_ENABLE_CHECKSUM_NAME, flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_ocpl_enable_checksum() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_lapl_replica_id + * + * Purpose: Set the replica ID to be used when accessing an object + * using this access plist. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February, 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_lapl_replica_id(hid_t lapl_id, hrpl_t replica_id) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iRp", lapl_id, replica_id); + + if(lapl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a lapl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5O_ACS_REPLICA_ID_NAME, &replica_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_lapl_replica_id() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_lapl_replica_id + * + * Purpose: Retrieve the replica ID from this access plist. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * February, 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_lapl_replica_id(hid_t lapl_id, hrpl_t *replica_id/*out*/) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", lapl_id, replica_id); + + if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a lapl") + + /* Get the transfer mode */ + if(replica_id) + if(H5P_get(plist, H5O_ACS_REPLICA_ID_NAME, replica_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_lapl_replica_id() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_dxpl_checksum + * + * Purpose: Modify the dataset transfer property list to set a + * checksum value for the data to be transfered. + * This is used with write operations. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_dxpl_checksum(hid_t dxpl_id, uint64_t cs) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iIl", dxpl_id, cs); + + if(dxpl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5D_XFER_CHECKSUM_NAME, &cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set checksum value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_dxpl_checksum() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_dxpl_checksum + * + * Purpose: Retrieve the checksum value that was set using + * H5Pset_dxpl_checksum. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_dxpl_checksum(hid_t dxpl_id, uint64_t *cs/*out*/) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", dxpl_id, cs); + + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Get the transfer mode */ + if(cs) + if(H5P_get(plist, H5D_XFER_CHECKSUM_NAME, cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_dxpl_checksum() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_dxpl_checksum_ptr + * + * Purpose: Set a pointer to tell the library where to insert the + * checksum that is received from a remote location. + * This is used with read operations. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_dxpl_checksum_ptr(hid_t dxpl_id, uint64_t *cs) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Il", dxpl_id, cs); + + if(dxpl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5D_XFER_CHECKSUM_PTR_NAME, &cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set checksum_ptr value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_dxpl_checksum_ptr() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_dxpl_checksum_ptr + * + * Purpose: Retrieve the checksum pointer value that was set using + * H5Pset_dxpl_checksum_ptr. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_dxpl_checksum_ptr(hid_t dxpl_id, uint64_t **cs/*out*/) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", dxpl_id, cs); + + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Get the transfer mode */ + if(cs) + if(H5P_get(plist, H5D_XFER_CHECKSUM_PTR_NAME, *cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum_ptr value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_dxpl_checksum_ptr() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_metadata_integrity_scope + * + * Purpose: Set the scope of checksum generation and verification for + * metadata in the FF stack. This is a file access property so the + * property is set on a particular container. Changing the property + * would require closing the file and reopening it. Possible values + * for this property are: + * H5_CHECKSUM_NONE = No metadata checksuming and verification + is done at any part of the stack. + * H5_CHECKSUM_TRANSFER = Metadata is verified after being transfered + through Mercury. + * H5_CHECKSUM_IOD = Metadata is checksumed and the checksum is + given to IOD when written, and verified when read. + * H5_CHECKSUM_MEMORY = Metadata is verified when moved in memory + (Not currently supported). + * H5_CHECKSUM_ALL = Metadata is checksumed and verified on all levels. + * + * Note that the property value is a bitflag so any combination can be + * set for individual values using OR operation. + * + * Return: Non-negative + * on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_metadata_integrity_scope(hid_t fapl_id, uint32_t scope) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iIu", fapl_id, scope); + + if(scope > H5_CHECKSUM_ALL) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid scope for Data Integrity"); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Set property */ + if(H5P_set(plist, H5VL_CS_BITFLAG_NAME, &scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data integrity scope"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_metadata_integrity_scope() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_metadata_integrity_scope + * + * Purpose: Get the current bit flag indicating the data integrity scope. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_metadata_integrity_scope(hid_t fapl_id, uint32_t *scope) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Iu", fapl_id, scope); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + if(scope) { + /* Get property */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_metadata_integrity_scope() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_rawdata_integrity_scope + * + * Purpose: Set the scope of checksum generation and verification for + * rawdata in the FF stack. This is a data transfer property so the + * property is set on a particular I/O operation (H5Dread/write, + * H5Mset/get, etc ...). Possible values for this property are: + * H5_CHECKSUM_NONE = No checksuming and verification + is done at any part of the stack. + * H5_CHECKSUM_TRANSFER = Data is verified after being transfered + through Mercury. + * H5_CHECKSUM_IOD = Data is checksumed and the checksum is + given to IOD when written, and verified when read. + * H5_CHECKSUM_MEMORY = Data is verified when moved in memory + * H5_CHECKSUM_ALL = Data is checksumed and verified on all levels. + * + * Note that the property value is a bitflag so any combination can be + * set for individual values using OR operation. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_rawdata_integrity_scope(hid_t dxpl_id, uint32_t scope) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "iIu", dxpl_id, scope); + + if(scope > H5_CHECKSUM_ALL) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid scope for Data Integrity"); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Set property */ + if(H5P_set(plist, H5VL_CS_BITFLAG_NAME, &scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data integrity scope"); + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_rawdata_integrity_scope() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_rawdata_integrity_scope + * + * Purpose: Get the current bit flag indicating the data integrity scope. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_rawdata_integrity_scope(hid_t dxpl_id, uint32_t *scope) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Iu", dxpl_id, scope); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + if(scope) { + /* Get property */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + } + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_rawdata_integrity_scope() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_dxpl_inject_corruption + * + * Purpose: Temporary routine to set a boolean flag that tells the + * library to inject corruption in the stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_dxpl_inject_corruption(hid_t dxpl_id, hbool_t flag) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ib", dxpl_id, flag); + + if(dxpl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5D_XFER_INJECT_CORRUPTION_NAME, &flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_dxpl_inject_corruption() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_dxpl_inject_corruption + * + * Purpose: Temporary routine to retrieve the boolean flag that tells the + * library to inject corruption in the stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_dxpl_inject_corruption(hid_t dxpl_id, hbool_t *flag/*out*/) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", dxpl_id, flag); + + if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl") + + /* Get the transfer mode */ + if(flag) + if(H5P_get(plist, H5D_XFER_INJECT_CORRUPTION_NAME, flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_dxpl_inject_corruption() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_dcpl_append_only + * + * Purpose: Set a boolean flag on the dataset creation property list + * to indicate to the VOL plugin that access to this dataset + * will always be in an append/sequence only manner. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_dcpl_append_only(hid_t dcpl_id, hbool_t flag) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ib", dcpl_id, flag); + + if(dcpl_id == H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list") + + /* Check arguments */ + if(NULL == (plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dcpl") + + /* Set the transfer mode */ + if(H5P_set(plist, H5D_CRT_APPEND_ONLY_NAME, &flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_dcpl_append_only() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_dcpl_append_only + * + * Purpose: Retrieve a boolean flag on the dataset creation property list + * that indicates whether access to this dataset + * will always be in an append/sequence only manner. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_dcpl_append_only(hid_t dcpl_id, hbool_t *flag/*out*/) +{ + H5P_genplist_t *plist = NULL; /* Property list pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ix", dcpl_id, flag); + + if(NULL == (plist = H5P_object_verify(dcpl_id, H5P_DATASET_CREATE))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dcpl") + + /* Get the transfer mode */ + if(flag) + if(H5P_get(plist, H5D_CRT_APPEND_ONLY_NAME, flag) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_dcpl_append_only() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_analysis_execute + * + * Purpose: Creates a file as a iod HDF5 file. + * + * Return: Success: the file id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_analysis_execute(const char *file_name, const char *obj_name, + hid_t query_id, const char *split_script, const char *combine_script, + void **req) +{ + analysis_execute_in_t input; + analysis_execute_out_t *output; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* set the input structure for the HG encode routine */ + input.file_name = file_name; + input.obj_name = obj_name; + input.query_id = query_id; + input.split_script = split_script; + input.combine_script = combine_script; + +#if H5VL_IOD_DEBUG + printf("Analysis Execute on file %s Object %s\n", + input.file_name, input.obj_name); +#endif + + if(NULL == (output = (analysis_execute_out_t *)H5MM_malloc(sizeof(analysis_execute_out_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate analysis output struct"); + + if(H5VL__iod_create_and_forward(H5VL_ANALYSIS_EXECUTE_ID, HG_ANALYSIS_EXECUTE, + NULL, 0, 0, NULL, + NULL, &input, output, output, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship file create"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_analysis_execute() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_file_create + * + * Purpose: Creates a file as a iod HDF5 file. + * + * Return: Success: the file id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, + hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_fapl_t *fa = NULL; + H5P_genplist_t *plist = NULL; /* Property list pointer */ + H5VL_iod_file_t *file = NULL; + file_create_in_t input; + uint32_t cs_scope; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Adjust bit flags by turning on the creation bit and making sure that + * the EXCL or TRUNC bit is set. All newly-created files are opened for + * reading and writing. + */ + if(0==(flags & (H5F_ACC_EXCL|H5F_ACC_TRUNC))) + flags |= H5F_ACC_EXCL; /*default*/ + flags |= H5F_ACC_RDWR | H5F_ACC_CREAT; + + /* obtain the process rank from the communicator attached to the fapl ID */ + if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") + if(NULL == (fa = (H5VL_iod_fapl_t *)H5P_get_vol_info(plist))) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't get IOD info struct") + + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get scope for data integrity checks"); + + /* allocate the file object that is returned to the user */ + if(NULL == (file = H5FL_CALLOC(H5VL_iod_file_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate IOD file struct"); + file->remote_file.root_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + file->remote_file.root_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + file->remote_file.root_id = IOD_OBJ_INVALID; + file->remote_file.c_version = 0; + + MPI_Comm_rank(fa->comm, &file->my_rank); + MPI_Comm_size(fa->comm, &file->num_procs); + + if(0 == file->my_rank) { + file->remote_file.kv_oid_index = 4; + file->remote_file.array_oid_index = 0; + file->remote_file.blob_oid_index = 0; + } + else { + file->remote_file.kv_oid_index = 0; + file->remote_file.array_oid_index = 0; + file->remote_file.blob_oid_index = 0; + } + + /* Duplicate communicator and Info object. */ + if(FAIL == H5FD_mpi_comm_info_dup(fa->comm, fa->info, &file->comm, &file->info)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed"); + + /* Generate an IOD ID for the root group to be created */ + H5VL_iod_gen_obj_id(0, file->num_procs, (uint64_t)0, IOD_OBJ_KV, &input.root_id); + file->remote_file.root_id = input.root_id; + + /* Generate an IOD ID for the root group MDKV to be created */ + H5VL_iod_gen_obj_id(0, file->num_procs, (uint64_t)1, IOD_OBJ_KV, &input.mdkv_id); + file->remote_file.mdkv_id = input.mdkv_id; + + /* Generate an IOD ID for the root group ATTR KV to be created */ + H5VL_iod_gen_obj_id(0, file->num_procs, (uint64_t)2, IOD_OBJ_KV, &input.attrkv_id); + file->remote_file.attrkv_id = input.attrkv_id; + + /* Generate an IOD ID for the OID index array to be created */ + H5VL_iod_gen_obj_id(0, file->num_procs, (uint64_t)3, IOD_OBJ_KV, &input.oidkv_id); + file->remote_file.oidkv_id = input.oidkv_id; + + /* set the input structure for the HG encode routine */ + input.name = name; + input.num_peers = (uint32_t)file->num_procs; + input.flags = flags; + input.fcpl_id = fcpl_id; + input.fapl_id = fapl_id; + + /* create the file object that is passed to the API layer */ + file->file_name = HDstrdup(name); + file->flags = flags; + file->md_integrity_scope = cs_scope; + if((file->remote_file.fcpl_id = H5Pcopy(fcpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy fcpl"); + if((file->fapl_id = H5Pcopy(fapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy fapl"); + file->nopen_objs = 1; + file->num_req = 0; + + /* initialize head and tail of the container's linked list of requests */ + file->request_list_head = NULL; + file->request_list_tail = NULL; + + file->common.obj_type = H5I_FILE; + /* The name of the location is the root's object name "\" */ + file->common.obj_name = HDstrdup("/"); + file->common.obj_name[1] = '\0'; + file->common.file = file; + +#if H5VL_IOD_DEBUG + printf("File Create %s IOD ROOT ID %"PRIu64", axe id %"PRIu64"\n", + name, input.root_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_FILE_CREATE_ID, HG_FILE_CREATE, + (H5VL_iod_object_t *)file, 1, 0, NULL, + NULL, &input, &file->remote_file, file, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship file create"); + + ret_value = (void *)file; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(file->file_name) { + HDfree(file->file_name); + file->file_name = NULL; + } + if(file->common.obj_name) { + HDfree(file->common.obj_name); + file->common.obj_name = NULL; + } + if(file->common.comment) { + HDfree(file->common.comment); + file->common.comment = NULL; + } + if(file->comm || file->info) + if(H5FD_mpi_comm_info_free(&file->comm, &file->info) < 0) + HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "Communicator/Info free failed") + if(file->fapl_id != FAIL && H5I_dec_ref(file->fapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(file->remote_file.fcpl_id != FAIL && + H5I_dec_ref(file->remote_file.fcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(file != NULL) { + file = H5FL_FREE(H5VL_iod_file_t, file); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_file_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_file_open + * + * Purpose: Opens a file as a iod HDF5 file. + * + * Return: Success: file id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_file_open(const char *name, unsigned flags, hid_t fapl_id, + hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_fapl_t *fa; + H5P_genplist_t *plist = NULL; /* Property list pointer */ + H5VL_iod_file_t *file = NULL; + file_open_in_t input; + hid_t rcxt_id; + uint32_t cs_scope; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* obtain the process rank from the communicator attached to the fapl ID */ + if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") + if(NULL == (fa = (H5VL_iod_fapl_t *)H5P_get_vol_info(plist))) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't get IOD info struct") + + /* determine if we want to acquire the latest readable version + when the file is opened */ + if(H5P_get(plist, H5VL_ACQUIRE_RC_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't set property value for rxct id") + + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get scope for data integrity checks"); + + if(FAIL != rcxt_id) { + input.acquire = TRUE; + } + else { + input.acquire = FALSE; + } + + /* allocate the file object that is returned to the user */ + if(NULL == (file = H5FL_CALLOC(H5VL_iod_file_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate IOD file struct"); + + file->remote_file.coh.cookie = IOD_OH_UNDEFINED; + file->remote_file.root_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + file->remote_file.root_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + file->remote_file.root_id = IOD_OBJ_INVALID; + file->remote_file.mdkv_id = IOD_OBJ_INVALID; + file->remote_file.attrkv_id = IOD_OBJ_INVALID; + file->remote_file.oidkv_id = IOD_OBJ_INVALID; + file->remote_file.fcpl_id = -1; + file->remote_file.c_version = IOD_TID_UNKNOWN; + file->remote_file.kv_oid_index = 0; + file->remote_file.array_oid_index = 0; + file->remote_file.blob_oid_index = 0; + + /* set input paramters in struct to give to the function shipper */ + input.name = name; + input.flags = flags; + input.fapl_id = fapl_id; + + /* create the file object that is passed to the API layer */ + MPI_Comm_rank(fa->comm, &file->my_rank); + MPI_Comm_size(fa->comm, &file->num_procs); + /* Duplicate communicator and Info object. */ + if(FAIL == H5FD_mpi_comm_info_dup(fa->comm, fa->info, &file->comm, &file->info)) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed"); + + file->file_name = HDstrdup(name); + file->flags = flags; + file->md_integrity_scope = cs_scope; + if((file->fapl_id = H5Pcopy(fapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy fapl"); + file->nopen_objs = 1; + file->num_req = 0; + + /* initialize head and tail of the container's linked list */ + file->request_list_head = NULL; + file->request_list_tail = NULL; + + file->common.obj_type = H5I_FILE; + /* The name of the location is the root's object name "\" */ + file->common.obj_name = HDstrdup("/"); + file->common.obj_name[1] = '\0'; + file->common.file = file; + +#if H5VL_IOD_DEBUG + printf("File Open %s axe id %"PRIu64"\n", name, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_FILE_OPEN_ID, HG_FILE_OPEN, + (H5VL_iod_object_t *)file, 1, 0, NULL, + NULL, &input, &file->remote_file, file, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship file open"); + + ret_value = (void *)file; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(file->file_name) { + HDfree(file->file_name); + file->file_name = NULL; + } + if(file->common.obj_name) { + HDfree(file->common.obj_name); + file->common.obj_name = NULL; + } + if(file->common.comment) { + HDfree(file->common.comment); + file->common.comment = NULL; + } + if(file->comm || file->info) + if(H5FD_mpi_comm_info_free(&file->comm, &file->info) < 0) + HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "Communicator/Info free failed") + + if(file->fapl_id != FAIL && H5I_dec_ref(file->fapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(file->remote_file.fcpl_id != FAIL && + H5I_dec_ref(file->remote_file.fcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(file != NULL) { + file = H5FL_FREE(H5VL_iod_file_t, file); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_file_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_file_get + * + * Purpose: Gets certain data about a file + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_file_get(void *_obj, H5VL_file_get_t get_type, hid_t UNUSED dxpl_id, + void UNUSED **req, va_list arguments) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + H5VL_iod_file_t *file = obj->file; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + switch (get_type) { + /* H5Fget_access_plist */ + case H5VL_FILE_GET_FAPL: + { + H5VL_iod_fapl_t fa, *old_fa; + H5P_genplist_t *new_plist, *old_plist; + hid_t *plist_id = va_arg (arguments, hid_t *); + + /* Retrieve the file's access property list */ + if((*plist_id = H5Pcopy(file->fapl_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file access property list") + + if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(*plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(file->fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + + if(NULL == (old_fa = (H5VL_iod_fapl_t *)H5P_get_vol_info(old_plist))) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get vol info"); + fa.comm = old_fa->comm; + fa.info = old_fa->info; + + ret_value = H5P_set_vol(new_plist, &H5VL_iod_g, &fa); + + break; + } + /* H5Fget_create_plist */ + case H5VL_FILE_GET_FCPL: + { + hid_t *plist_id = va_arg (arguments, hid_t *); + + /* Retrieve the file's access property list */ + if((*plist_id = H5Pcopy(file->remote_file.fcpl_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file creation property list") + + break; + } + /* H5Fget_intent */ + case H5VL_FILE_GET_INTENT: + { + unsigned *ret = va_arg (arguments, unsigned *); + + if(file->flags & H5F_ACC_RDWR) + *ret = H5F_ACC_RDWR; + else + *ret = H5F_ACC_RDONLY; + break; + } + /* H5Fget_name */ + case H5VL_FILE_GET_NAME: + { + H5I_type_t UNUSED type = va_arg (arguments, H5I_type_t); + size_t size = va_arg (arguments, size_t); + char *name = va_arg (arguments, char *); + ssize_t *ret = va_arg (arguments, ssize_t *); + size_t len; + + len = HDstrlen(file->file_name); + + if(name) { + HDstrncpy(name, file->file_name, MIN(len + 1,size)); + if(len >= size) + name[size-1]='\0'; + } /* end if */ + + /* Set the return value for the API call */ + *ret = (ssize_t)len; + break; + } + /* H5I_get_file_id */ + case H5VL_OBJECT_GET_FILE: + { + + H5I_type_t UNUSED type = va_arg (arguments, H5I_type_t); + void **ret = va_arg (arguments, void **); + + *ret = (void*)file; + break; + } + /* H5Fget_obj_count */ + case H5VL_FILE_GET_OBJ_COUNT: + { + //unsigned types = va_arg (arguments, unsigned); + //ssize_t *ret = va_arg (arguments, ssize_t *); + //break; + } + /* H5Fget_obj_ids */ + case H5VL_FILE_GET_OBJ_IDS: + { + //unsigned types = va_arg (arguments, unsigned); + //size_t max_objs = va_arg (arguments, size_t); + //hid_t *oid_list = va_arg (arguments, hid_t *); + //ssize_t *ret = va_arg (arguments, ssize_t *); + //break; + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_file_get() */ + +#if 0 + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_file_misc + * + * Purpose: Perform an operation + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_file_misc(void *obj, H5VL_file_misc_t misc_type, hid_t dxpl_id, + void **req, va_list arguments) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + switch (misc_type) { + /* H5Fis_accessible */ + case H5VL_FILE_IS_ACCESSIBLE: + { + hid_t fapl_id = va_arg (arguments, hid_t); + const char *name = va_arg (arguments, const char *); + htri_t *ret = va_arg (arguments, htri_t *); + H5VL_iod_file_t *file = NULL; +#if 0 + /* attempt to open the file through the MDS plugin */ + if(NULL == (file = (H5VL_iod_file_t *)H5VL_iod_file_open(name, H5F_ACC_RDONLY, fapl_id, + H5_REQUEST_NULL))) + *ret = FALSE; + else + *ret = TRUE; + + /* close the file if it was succesfully opened */ + if(file && H5VL_iod_file_close((void*)file, H5_REQUEST_NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close file"); + break; +#endif + } + /* H5Fmount */ + case H5VL_FILE_MOUNT: + { + H5I_type_t type = va_arg (arguments, H5I_type_t); + const char *name = va_arg (arguments, const char *); + H5VL_iod_file_t *child = va_arg (arguments, H5VL_iod_file_t *); + hid_t plist_id = va_arg (arguments, hid_t); + } + /* H5Fmount */ + case H5VL_FILE_UNMOUNT: + { + H5I_type_t type = va_arg (arguments, H5I_type_t); + const char *name = va_arg (arguments, const char *); + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "MDS Plugin does not support this operation type") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_file_misc() */ +#endif + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_file_close + * + * Purpose: Closes a file. + * + * Return: Success: 0 + * Failure: -1, file not closed. + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_file_close(void *_file, hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_file_t *file = (H5VL_iod_file_t *)_file; + file_close_in_t input; + int *status = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_all(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + /* allocate an integer to receive the return value if the file close succeeded or not */ + status = (int *)malloc(sizeof(int)); + + /* determine the max indexes for the KV, Array, and BLOB IDs used + up by all the processes */ + if(file->flags != H5F_ACC_RDONLY) { + uint64_t input_indexes[3] = {file->remote_file.kv_oid_index, + file->remote_file.array_oid_index, + file->remote_file.blob_oid_index}; + uint64_t object_indexes[3]; + + if(MPI_SUCCESS != MPI_Reduce(input_indexes, object_indexes, 3, + MPI_UINT64_T, MPI_MAX, 0, file->comm)) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't determine max value of object indexes for ID generation"); + + if(0 == file->my_rank) { + input.max_kv_index = object_indexes[0]; + input.max_array_index = object_indexes[1]; + input.max_blob_index = object_indexes[2]; + } + else { + input.max_kv_index = 0; + input.max_array_index = 0; + input.max_blob_index = 0; + } + } + else { + input.max_kv_index = 0; + input.max_array_index = 0; + input.max_blob_index = 0; + } + + input.coh = file->remote_file.coh; + input.root_oh = file->remote_file.root_oh; + input.root_id = file->remote_file.root_id; + input.cs_scope = file->md_integrity_scope; + + if(file->num_req) { + H5VL_iod_request_t *cur_req = file->request_list_head; + + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * file->num_req))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + + while(cur_req) { + if(cur_req->state == H5VL_IOD_PENDING) { + parent_reqs[num_parents] = cur_req; + cur_req->ref_count ++; + num_parents ++; + } + cur_req = cur_req->file_next; + } + } + +#if H5VL_IOD_DEBUG + printf("File Close Root ID %"PRIu64" axe id %"PRIu64"\n", input.root_id, g_axe_id); +#endif + + /* + * All ranks must wait for rank 0 to go close the file and write + * out the metadata before going on an closing the file. Rank 0 + * calls the barrier on request completion in + * H5VLiod_client.c. + + * (This is an IOD limitation.) + */ + if(0 != file->my_rank) + MPI_Barrier (file->comm); + + if(H5VL__iod_create_and_forward(H5VL_FILE_CLOSE_ID, HG_FILE_CLOSE, + (H5VL_iod_object_t *)file, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship file close"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_file_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_group_create + * + * Purpose: Creates a group inside a iod h5 file. + * + * Return: Success: group + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_group_create(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, hid_t gcpl_id, + hid_t gapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the group */ + H5VL_iod_group_t *grp = NULL; /* the group object that is created and passed to the user */ + group_create_in_t input; + hid_t lcpl_id; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5P_genplist_t *plist = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Get the group creation plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(gcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + /* get creation properties */ + if(H5P_get(plist, H5VL_GRP_LCPL_ID, &lcpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for lcpl id"); + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the group object that is returned to the user */ + if(NULL == (grp = H5FL_CALLOC(H5VL_iod_group_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + grp->remote_group.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + grp->remote_group.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + + /* Generate IOD IDs for the group to be created */ + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.grp_id); + grp->remote_group.iod_id = input.grp_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.mdkv_id); + grp->remote_group.mdkv_id = input.mdkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.attrkv_id); + grp->remote_group.attrkv_id = input.attrkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.gcpl_id = gcpl_id; + input.gapl_id = gapl_id; + input.lcpl_id = lcpl_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + /* setup the local group struct */ + /* store the entire path of the group locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (grp->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(grp->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(grp->common.obj_name+obj_name_len, name, name_len); + grp->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* copy property lists */ + if((grp->remote_group.gcpl_id = H5Pcopy(gcpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy gcpl"); + if((grp->gapl_id = H5Pcopy(gapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy gapl"); + /* set common object parameters */ + grp->common.obj_type = H5I_GROUP; + grp->common.file = obj->file; + grp->common.file->nopen_objs ++; + +#if H5VL_IOD_DEBUG + printf("Group Create %s, IOD ID %"PRIu64", axe id %"PRIu64"\n", + name, input.grp_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_GROUP_CREATE_ID, HG_GROUP_CREATE, + (H5VL_iod_object_t *)grp, 1, + num_parents, parent_reqs, (H5VL_iod_req_info_t *)tr, + &input, &grp->remote_group, grp, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship group create"); + + ret_value = (void *)grp; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(grp->common.obj_name) { + HDfree(grp->common.obj_name); + grp->common.obj_name = NULL; + } + if(grp->common.comment) { + HDfree(grp->common.comment); + grp->common.comment = NULL; + } + if(grp->gapl_id != FAIL && H5I_dec_ref(grp->gapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp->remote_group.gcpl_id != FAIL && + H5I_dec_ref(grp->remote_group.gcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp) + grp = H5FL_FREE(H5VL_iod_group_t, grp); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_group_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_group_open + * + * Purpose: Opens a group inside a iod h5 file. + * + * Return: Success: group id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_group_open(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t gapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the group */ + H5VL_iod_group_t *grp = NULL; /* the group object that is created and passed to the user */ + group_open_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the group object that is returned to the user */ + if(NULL == (grp = H5FL_CALLOC(H5VL_iod_group_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + grp->remote_group.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + grp->remote_group.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + grp->remote_group.iod_id = IOD_OBJ_INVALID; + grp->remote_group.mdkv_id = IOD_OBJ_INVALID; + grp->remote_group.attrkv_id = IOD_OBJ_INVALID; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.gapl_id = gapl_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Group Open %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + name, input.loc_id, g_axe_id); +#endif + + /* setup the local group struct */ + /* store the entire path of the group locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (grp->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(grp->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(grp->common.obj_name+obj_name_len, name, name_len); + grp->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* copy property lists */ + if((grp->gapl_id = H5Pcopy(gapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy gapl"); + /* set common object parameters */ + grp->common.obj_type = H5I_GROUP; + grp->common.file = obj->file; + grp->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_GROUP_OPEN_ID, HG_GROUP_OPEN, + (H5VL_iod_object_t *)grp, 1, + num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, + &input, &grp->remote_group, grp, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship group open"); + + ret_value = (void *)grp; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(grp->common.obj_name) { + HDfree(grp->common.obj_name); + grp->common.obj_name = NULL; + } + if(grp->common.comment) { + HDfree(grp->common.comment); + grp->common.comment = NULL; + } + if(grp->gapl_id != FAIL && H5I_dec_ref(grp->gapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp->remote_group.gcpl_id != FAIL && + H5I_dec_ref(grp->remote_group.gcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp) + grp = H5FL_FREE(H5VL_iod_group_t, grp); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_group_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_group_get + * + * Purpose: Gets certain data about a group + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_group_get(void *_grp, H5VL_group_get_t get_type, hid_t UNUSED dxpl_id, + void UNUSED **req, va_list arguments) +{ + H5VL_iod_group_t *grp = (H5VL_iod_group_t *)_grp; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + switch (get_type) { + /* H5Gget_create_plist */ + case H5VL_GROUP_GET_GCPL: + { + hid_t *plist_id = va_arg (arguments, hid_t *); + + /* Retrieve the file's access property list */ + if((*plist_id = H5Pcopy(grp->remote_group.gcpl_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group create property list") + break; + } + /* H5Gget_info */ + case H5VL_GROUP_GET_INFO: + { + //H5VL_loc_params_t loc_params = va_arg (arguments, H5VL_loc_params_t); + //H5G_info_t *ginfo = va_arg (arguments, H5G_info_t *); + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from group") + } +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_group_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_group_close + * + * Purpose: Closes a group. + * + * Return: Success: 0 + * Failure: -1, group not closed. + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_group_close(void *_grp, hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_group_t *grp = (H5VL_iod_group_t *)_grp; + group_close_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(grp->common.file, grp) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(IOD_OH_UNDEFINED == grp->remote_group.iod_oh.rd_oh.cookie) { + /* Synchronously wait on the request attached to the group */ + if(H5VL_iod_request_wait(grp->common.file, grp->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on group request"); + grp->common.request = NULL; + } + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)grp, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)grp, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parent requests"); + } + + input.iod_oh = grp->remote_group.iod_oh; + input.iod_id = grp->remote_group.iod_id; + + /* allocate an integer to receive the return value if the group close succeeded or not */ + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Group Close IOD ID %"PRIu64", axe id %"PRIu64"\n", + input.iod_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_GROUP_CLOSE_ID, HG_GROUP_CLOSE, + (H5VL_iod_object_t *)grp, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship group close"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_group_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_create + * + * Purpose: Sends a request to the IOD to create a dataset + * + * Return: Success: dataset object. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_dataset_create(void *_obj, H5VL_loc_params_t UNUSED loc_params, + const char *name, hid_t dcpl_id, + hid_t dapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the dataset */ + H5VL_iod_dset_t *dset = NULL; /* the dataset object that is created and passed to the user */ + dset_create_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5VL_iod_request_t **parent_reqs = NULL; + H5P_genplist_t *plist = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + hid_t type_id, space_id, lcpl_id; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Get the dcpl plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + + /* get datatype, dataspace, and lcpl IDs that were added in the dcpl at the API layer */ + if(H5P_get(plist, H5VL_DSET_TYPE_ID, &type_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for datatype id"); + if(H5P_get(plist, H5VL_DSET_SPACE_ID, &space_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for space id"); + if(H5P_get(plist, H5VL_DSET_LCPL_ID, &lcpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for lcpl id"); + + /* Check that no values other than the first dimension in MAX dims + is H5S_UNLIMITED. */ + { + H5S_t *ds = NULL; + int ndims, i; + hsize_t max_dims[H5S_MAX_RANK]; + + if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a dataspace") + + ndims = (int)H5S_GET_EXTENT_NDIMS(ds); + H5S_get_simple_extent_dims(ds, NULL, max_dims); + + for(i=1; i<ndims; i++) { + if(max_dims[i] == H5S_UNLIMITED) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "only first dimension can be H5S_UNLIMITED."); + } + } + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a Transaction ID") + + /* Retrieve the parent AXE id by traversing the path where the + dataset should be created. */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the dataset object that is returned to the user */ + if(NULL == (dset = H5FL_CALLOC(H5VL_iod_dset_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dset->remote_dset.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_id = IOD_OBJ_INVALID; + + /* Generate IOD IDs for the dset to be created */ + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.array_oid_index, + IOD_OBJ_ARRAY, &input.dset_id); + dset->remote_dset.iod_id = input.dset_id; + /* increment the index of ARRAY objects created on the container */ + obj->file->remote_file.array_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.mdkv_id); + dset->remote_dset.mdkv_id = input.mdkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.attrkv_id); + dset->remote_dset.attrkv_id = input.attrkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.dcpl_id = dcpl_id; + input.dapl_id = dapl_id; + input.lcpl_id = lcpl_id; + input.type_id = type_id; + input.space_id = space_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (dset->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dset->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dset->common.obj_name+obj_name_len, name, name_len); + dset->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* copy property lists, dtype, and dspace*/ + if((dset->remote_dset.dcpl_id = H5Pcopy(dcpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dcpl"); + if((dset->dapl_id = H5Pcopy(dapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dapl"); + if((dset->remote_dset.type_id = H5Tcopy(type_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dtype"); + if((dset->remote_dset.space_id = H5Scopy(space_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dspace"); + + /* set common object parameters */ + dset->common.obj_type = H5I_DATASET; + dset->common.file = obj->file; + dset->common.file->nopen_objs ++; + +#if H5VL_IOD_DEBUG + printf("Dataset Create %s IOD ID %"PRIu64", axe id %"PRIu64"\n", + name, input.dset_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_DSET_CREATE_ID, HG_DSET_CREATE, + (H5VL_iod_object_t *)dset, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, &dset->remote_dset, dset, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship dataset create"); + + ret_value = (void *)dset; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(dset->common.obj_name) { + HDfree(dset->common.obj_name); + dset->common.obj_name = NULL; + } + if(dset->common.comment) { + HDfree(dset->common.comment); + dset->common.comment = NULL; + } + if(dset->remote_dset.type_id != FAIL && H5I_dec_ref(dset->remote_dset.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dset->remote_dset.space_id != FAIL && H5I_dec_ref(dset->remote_dset.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(dset->remote_dset.dcpl_id != FAIL && H5I_dec_ref(dset->remote_dset.dcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset->dapl_id != FAIL && H5I_dec_ref(dset->dapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset) + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_open + * + * Purpose: Sends a request to the IOD to open a dataset + * + * Return: Success: dataset object. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_dataset_open(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t dapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the dataset */ + H5VL_iod_dset_t *dset = NULL; /* the dataset object that is created and passed to the user */ + dset_open_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for rcxt_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* Retrieve the parent AXE id by traversing the path where the + dataset should be opened. */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the dataset object that is returned to the user */ + if(NULL == (dset = H5FL_CALLOC(H5VL_iod_dset_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dset->remote_dset.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_id = IOD_OBJ_INVALID; + dset->remote_dset.mdkv_id = IOD_OBJ_INVALID; + dset->remote_dset.attrkv_id = IOD_OBJ_INVALID; + dset->remote_dset.dcpl_id = -1; + dset->remote_dset.type_id = -1; + dset->remote_dset.space_id = -1; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.dapl_id = dapl_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (dset->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dset->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dset->common.obj_name+obj_name_len, name, name_len); + dset->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((dset->dapl_id = H5Pcopy(dapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dapl"); + + /* set common object parameters */ + dset->common.obj_type = H5I_DATASET; + dset->common.file = obj->file; + dset->common.file->nopen_objs ++; + +#if H5VL_IOD_DEBUG + printf("Dataset Open %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + name, input.loc_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_DSET_OPEN_ID, HG_DSET_OPEN, + (H5VL_iod_object_t *)dset, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, &dset->remote_dset, dset, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship dataset open"); + + ret_value = (void *)dset; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + if(dset->common.obj_name) { + HDfree(dset->common.obj_name); + dset->common.obj_name = NULL; + } + if(dset->common.comment) { + HDfree(dset->common.comment); + dset->common.comment = NULL; + } + if(dset->remote_dset.type_id != FAIL && H5I_dec_ref(dset->remote_dset.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dset->remote_dset.space_id != FAIL && H5I_dec_ref(dset->remote_dset.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(dset->remote_dset.dcpl_id != FAIL && H5I_dec_ref(dset->remote_dset.dcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset->dapl_id != FAIL && H5I_dec_ref(dset->dapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset) + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_read + * + * Purpose: Reads raw data from a dataset into a buffer. + * + * Return: Success: 0 + * Failure: -1, data not read. + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, void *buf, void **req) +{ + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; + dset_io_in_t input; + H5P_genplist_t *plist = NULL; + hg_bulk_t *bulk_handle = NULL; + H5S_t *mem_space = NULL; + H5S_t *file_space = NULL; + char fake_char; + size_t type_size; /* size of mem type */ + hssize_t nelmts; /* num elements in mem dataspace */ + H5VL_iod_read_info_t *info = NULL; + H5VL_iod_read_status_t *status = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + H5VL_iod_type_info_t *type_info = NULL; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the dataset that is not present locally, wait */ + if(-1 == dset->remote_dset.dcpl_id || + -1 == dset->remote_dset.type_id || + -1 == dset->remote_dset.space_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dset->common.file, dset->common.request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + dset->common.request = NULL; + } + + /* check arguments */ + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = (H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + /* Check for valid selection */ + if(H5S_SELECT_VALID(mem_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + else { + if(NULL == (mem_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + if(H5S_select_all(mem_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } + + if(H5S_ALL != file_space_id) { + if(NULL == (file_space = (H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + /* Check for valid selection */ + if(H5S_SELECT_VALID(file_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + else { + if(NULL == (file_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + if(H5S_select_all(file_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } + + if(!buf && (NULL == file_space || H5S_GET_SELECT_NPOINTS(file_space) != 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); + + if(!buf) + buf = &fake_char; + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + + /* At the IOD server, the array object is actually created with + MAX dims, not current dims. So here we need to range check the + filespace against the current dimensions of the dataset to make + sure that the I/O happens in the current range and not the + extensible one. */ + { + H5S_t *dset_space; + hsize_t dset_dims[H5S_MAX_RANK], io_dims[H5S_MAX_RANK]; + int dset_ndims, io_ndims, i; + + if(NULL == (dset_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + dset_ndims = (int)H5S_GET_EXTENT_NDIMS(dset_space); + io_ndims = (int)H5S_GET_EXTENT_NDIMS(file_space); + + if(dset_ndims < io_ndims) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection not within dataset's dataspace"); + + H5S_get_simple_extent_dims(dset_space, dset_dims, NULL); + H5S_get_simple_extent_dims(file_space, io_dims, NULL); + + for(i=0 ; i<io_ndims ; i++) { + if(dset_dims[i] < io_dims[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection Out of range"); + } + } + + /* get the memory type size */ + { + H5T_t *dt = NULL; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + + type_size = H5T_GET_SIZE(dt); + } + + /* get the number of elements selcted in dataspace */ + nelmts = H5S_GET_SELECT_NPOINTS(mem_space); + + /* allocate a bulk data transfer handle */ + if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + + if(NULL == (type_info = (H5VL_iod_type_info_t *)H5MM_malloc(sizeof(H5VL_iod_type_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate type info struct"); + + /* Get type info */ + if(H5VL_iod_get_type_info(mem_type_id, type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + /* Check if there are any vlen types. If so, guess number of vl + * lengths, allocate array, and register with bulk buffer. Otherwise, + * register data buffer. */ + if(type_info->vls) { + /* For now, just guess one segment for each vl in top level */ + vl_lengths_size = 8 * (size_t)nelmts * type_info->num_vls; + + /* Allocate vl_lengths */ + if(NULL == (vl_lengths = (char *)HDmalloc(vl_lengths_size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate vlen lengths buffer"); + + /* Register vl_lengths buffer */ + HG_Bulk_handle_create(vl_lengths, vl_lengths_size, HG_BULK_READWRITE, bulk_handle); + } /* end if */ + else { + /* for non vlen data, create the bulk handle to recieve the data in */ + if(H5VL_iod_pre_read(mem_type_id, mem_space, buf, nelmts, bulk_handle) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't generate read parameters"); + } + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)dset, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure for reading data */ + input.coh = dset->common.file->remote_file.coh; + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; + input.bulk_handle = *bulk_handle; + input.vl_len_bulk_handle = HG_BULK_NULL; + input.checksum = 0; + input.dxpl_id = dxpl_id; + if(H5S_ALL == file_space_id) + input.space_id = dset->remote_dset.space_id; + else + input.space_id = file_space_id; + input.dset_type_id = dset->remote_dset.type_id; + input.mem_type_id = mem_type_id; + input.trans_num = 0; + input.rcxt_num = rc->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + input.axe_id = g_axe_id; + + /* allocate structure to receive status of read operation + (contains return value, checksum, and buffer size) */ + if(NULL == (status = (H5VL_iod_read_status_t *)H5MM_malloc(sizeof(H5VL_iod_read_status_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate Read status struct"); + + /* setup info struct for I/O request. + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_read_info_t *)H5MM_calloc(sizeof(H5VL_iod_read_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); + + info->status = status; + info->bulk_handle = bulk_handle; + info->type_info = type_info; + info->vl_lengths = vl_lengths; + info->vl_lengths_size = vl_lengths_size; + info->buf_ptr = buf; + info->nelmts = nelmts; + info->type_size = type_size; + info->cs_ptr = NULL; + info->axe_id = g_axe_id; + + /* store a copy of the dataspace selection to be able to calculate the checksum later */ + if(NULL == (info->space = H5S_copy(mem_space, FALSE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace"); + /* store the pointer to the buffer where the checksum needs to be placed */ + if(H5P_get(plist, H5D_XFER_CHECKSUM_PTR_NAME, &info->cs_ptr) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum pointer value"); + /* store the raw data integrity scope */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &info->raw_cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum pointer value"); + + /* If the read is of VL data, then we need the read parameters to + perform the actual read when the wait is called (i.e. when we + retrieve the buffer size) */ + if(type_info->vls) { + if((info->file_space_id = H5Scopy(input.space_id)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace"); + if((info->mem_type_id = H5Tcopy(mem_type_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype"); + if((info->dxpl_id = H5P_copy_plist((H5P_genplist_t *)plist, TRUE)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy dxpl"); + + info->ion_target = PEER; + info->read_id = H5VL_DSET_READ_ID; + } + +#if H5VL_IOD_DEBUG + if(!type_info->vls) + printf("Dataset Read, axe id %"PRIu64"\n", g_axe_id); + else + printf("Dataset GET size, axe id %"PRIu64"\n", g_axe_id + 1); +#endif + + /* forward the call to the IONs */ + if(!type_info->vls) { + if(H5VL__iod_create_and_forward(H5VL_DSET_READ_ID, HG_DSET_READ, + (H5VL_iod_object_t *)dset, 0, + num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, + &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset read"); + } + else { + /* allocate an axe_id for the read operation to follow */ + g_axe_id ++; + + if(H5VL__iod_create_and_forward(H5VL_DSET_GET_VL_SIZE_ID, HG_DSET_GET_VL_SIZE, + (H5VL_iod_object_t *)dset, 0, + num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, + &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset get VL size"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_write + * + * Purpose: Writes raw data from a buffer into a dataset. + * + * Return: Success: 0 + * Failure: -1, dataset not writed. + * + * Programmer: Mohamad Chaarawi + * October, 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t dxpl_id, const void *buf, void **req) +{ + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; + dset_io_in_t input; + H5P_genplist_t *plist = NULL; + hg_bulk_t *bulk_handle = NULL; + hg_bulk_t *vl_len_bulk_handle = NULL; + hg_bulk_segment_t *vl_segments = NULL; + char *vl_lengths = NULL; + H5S_t *mem_space = NULL; + H5S_t *file_space = NULL; + char fake_char; + int *status = NULL; + H5VL_iod_write_info_t *info; /* info struct used to manage I/O parameters once the operation completes*/ + uint64_t internal_cs = 0; /* internal checksum calculated in this function */ + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + uint64_t user_cs, vl_len_cs; + uint32_t raw_cs_scope = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the dataset that is not present locally, wait */ + if(-1 == dset->remote_dset.dcpl_id || + -1 == dset->remote_dset.type_id || + -1 == dset->remote_dset.space_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dset->common.file, dset->common.request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + dset->common.request = NULL; + } + + /* check arguments */ + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = (H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + /* Check for valid selection */ + if(H5S_SELECT_VALID(mem_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + else { + if(NULL == (mem_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + if(H5S_select_all(mem_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } + + if(H5S_ALL != file_space_id) { + if(NULL == (file_space = (H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + /* Check for valid selection */ + if(H5S_SELECT_VALID(file_space) != TRUE) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + else { + if(NULL == (file_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + if(H5S_select_all(file_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } + + if(!buf && (NULL == file_space || H5S_GET_SELECT_NPOINTS(file_space) != 0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); + + if(!buf) + buf = &fake_char; + + /* At the IOD server, the array object is actually created with + MAX dims, not current dims. So here we need to range check the + filespace against the current dimensions of the dataset to make + sure that the I/O happens in the current range and not the + extensible one. */ + { + H5S_t *dset_space; + hsize_t dset_dims[H5S_MAX_RANK], io_dims[H5S_MAX_RANK]; + int dset_ndims, io_ndims, i; + + if(NULL == (dset_space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + dset_ndims = (int)H5S_GET_EXTENT_NDIMS(dset_space); + io_ndims = (int)H5S_GET_EXTENT_NDIMS(file_space); + + if(dset_ndims < io_ndims) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection not within dataset's dataspace"); + + H5S_get_simple_extent_dims(dset_space, dset_dims, NULL); + H5S_get_simple_extent_dims(file_space, io_dims, NULL); + + for(i=0 ; i<io_ndims ; i++) { + if(dset_dims[i] < io_dims[i]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection Out of range"); + } + } + + /* get the plist pointer */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* get the TR object */ + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* get the data integrity scope */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &raw_cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* allocate a bulk data transfer handle */ + if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + if(NULL == (vl_len_bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + + if(raw_cs_scope) { + /* compute checksum and create bulk handle */ + if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, &internal_cs, &vl_len_cs, + bulk_handle, vl_len_bulk_handle, &vl_segments, &vl_lengths) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't generate write parameters"); + } + else { +#if H5VL_IOD_DEBUG + printf("NO DATA INTEGRITY CHECKS ON RAW DATA WRITTEN\n"); +#endif + /* compute checksum and create bulk handle */ + if(H5VL_iod_pre_write(mem_type_id, mem_space, buf, NULL, NULL, bulk_handle, + vl_len_bulk_handle, &vl_segments, &vl_lengths) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't generate write parameters"); + internal_cs = 0; + } + + /* Verify the checksum value if the dxpl contains a user defined checksum */ + if(H5P_get(plist, H5D_XFER_CHECKSUM_NAME, &user_cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum value"); + + if((raw_cs_scope & H5_CHECKSUM_MEMORY) && user_cs && + user_cs != internal_cs) { + fprintf(stderr, "Errrr.. In memory Data corruption. expecting %016lX, got %016lX\n", + user_cs, internal_cs); + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "Checksum verification failed"); + } + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)dset, (H5VL_iod_req_info_t *)tr, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = dset->common.file->remote_file.coh; + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; + input.bulk_handle = *bulk_handle; + input.vl_len_bulk_handle = *vl_len_bulk_handle; + input.checksum = internal_cs; + input.dxpl_id = dxpl_id; + if(H5S_ALL == file_space_id) + input.space_id = dset->remote_dset.space_id; + else + input.space_id = file_space_id; + input.dset_type_id = dset->remote_dset.type_id; + input.mem_type_id = mem_type_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + input.axe_id = g_axe_id; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Dataset Write, axe id %"PRIu64"\n", g_axe_id); +#endif + + /* setup info struct for I/O request + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_write_info_t *)H5MM_calloc(sizeof(H5VL_iod_write_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); + info->status = status; + info->bulk_handle = bulk_handle; + info->vl_len_bulk_handle = vl_len_bulk_handle; + info->vl_lengths = vl_lengths; + info->vl_segments = vl_segments; + + if(H5VL__iod_create_and_forward(H5VL_DSET_WRITE_ID, HG_DSET_WRITE, + (H5VL_iod_object_t *)dset, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset write"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_set_extent + * + * Purpose: Set Extent of dataset + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * October, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_dataset_set_extent(void *_dset, const hsize_t size[], + hid_t dxpl_id, void **req) +{ + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; + dset_set_extent_in_t input; + int *status = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5P_genplist_t *plist = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the dataset that is not present locally, wait */ + if(-1 == dset->remote_dset.space_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dset->common.file, dset->common.request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + dset->common.request = NULL; + } + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dset, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dset, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parent requests"); + } + + /* Fill input structure */ + input.coh = dset->common.file->remote_file.coh; + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; + input.dims.rank = H5Sget_simple_extent_ndims(dset->remote_dset.space_id); + input.dims.size = size; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Dataset Set Extent, axe id %"PRIu64"\n", g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_DSET_SET_EXTENT_ID, HG_DSET_SET_EXTENT, + (H5VL_iod_object_t *)dset, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset set_extent"); + + /* modify the local dataspace of the dataset */ + { + H5S_t *space; /* Dataset's dataspace */ + + if(NULL == (space = (H5S_t *)H5I_object_verify(dset->remote_dset.space_id, + H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + + /* Modify the size of the data space */ + if(H5S_set_extent(space, size) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space"); + } +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_set_extent() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_get + * + * Purpose: Gets certain information about a dataset + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_dataset_get(void *_dset, H5VL_dataset_get_t get_type, + hid_t UNUSED dxpl_id, + void UNUSED **req, va_list arguments) +{ + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(-1 == dset->remote_dset.dcpl_id || + -1 == dset->remote_dset.type_id || + -1 == dset->remote_dset.space_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dset->common.file, dset->common.request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + dset->common.request = NULL; + } + + switch (get_type) { + case H5VL_DATASET_GET_DCPL: + { + hid_t *plist_id = va_arg (arguments, hid_t *); + + /* Retrieve the file's access property list */ + if((*plist_id = H5Pcopy(dset->remote_dset.dcpl_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get dset creation property list") + + break; + } + case H5VL_DATASET_GET_DAPL: + { + hid_t *plist_id = va_arg (arguments, hid_t *); + + /* Retrieve the file's access property list */ + if((*plist_id = H5Pcopy(dset->dapl_id)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get dset access property list") + + break; + } + case H5VL_DATASET_GET_SPACE: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + + if((*ret_id = H5Scopy(dset->remote_dset.space_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get dataspace ID of dataset"); + break; + } + case H5VL_DATASET_GET_SPACE_STATUS: + { + H5D_space_status_t *allocation = va_arg (arguments, H5D_space_status_t *); + + *allocation = H5D_SPACE_STATUS_NOT_ALLOCATED; + break; + } + case H5VL_DATASET_GET_TYPE: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + + if((*ret_id = H5Tcopy(dset->remote_dset.type_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of dataset") + } + case H5VL_DATASET_GET_STORAGE_SIZE: + case H5VL_DATASET_GET_OFFSET: + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from dataset") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_dataset_close + * + * Purpose: Closes a dataset. + * + * Return: Success: 0 + * Failure: -1, dataset not closed. + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_dataset_close(void *_dset, hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)_dset; + dset_close_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(-1 == dset->remote_dset.dcpl_id || + -1 == dset->remote_dset.type_id || + -1 == dset->remote_dset.space_id || + IOD_OH_UNDEFINED == dset->remote_dset.iod_oh.rd_oh.cookie) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dset->common.file, dset->common.request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait dset request"); + dset->common.request = NULL; + } + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(dset->common.file, dset) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dset, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dset, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parent requests"); + } + + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Dataset Close IOD ID %"PRIu64", axe id %"PRIu64"\n", + input.iod_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_DSET_CLOSE_ID, HG_DSET_CLOSE, + (H5VL_iod_object_t *)dset, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship dataset close"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_dataset_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_datatype_commit + * + * Purpose: Commits a datatype inside the container. + * + * Return: Success: datatype + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_datatype_commit(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t type_id, hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, + hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the datatype */ + H5VL_iod_dtype_t *dtype = NULL; /* the datatype object that is created and passed to the user */ + dtype_commit_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the datatype object that is returned to the user */ + if(NULL == (dtype = H5FL_CALLOC(H5VL_iod_dtype_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dtype->remote_dtype.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_id = IOD_OBJ_INVALID; + + /* Generate IOD IDs for the group to be created */ + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.blob_oid_index, + IOD_OBJ_BLOB, &input.dtype_id); + dtype->remote_dtype.iod_id = input.dtype_id; + /* increment the index of BLOB objects created on the container */ + obj->file->remote_file.blob_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.mdkv_id); + dtype->remote_dtype.mdkv_id = input.mdkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.attrkv_id); + dtype->remote_dtype.attrkv_id = input.attrkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.tcpl_id = tcpl_id; + input.tapl_id = tapl_id; + input.lcpl_id = lcpl_id; + input.type_id = type_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Datatype Commit %s IOD ID %"PRIu64", axe id %"PRIu64"\n", + name, input.dtype_id, g_axe_id); +#endif + + /* setup the local datatype struct */ + /* store the entire path of the datatype locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (dtype->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dtype->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dtype->common.obj_name+obj_name_len, name, name_len); + dtype->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* store a copy of the datatype parameters*/ + if((dtype->remote_dtype.tcpl_id = H5Pcopy(tcpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dcpl"); + if((dtype->tapl_id = H5Pcopy(tapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dapl"); + if((dtype->remote_dtype.type_id = H5Tcopy(type_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dtype"); + + /* set common object parameters */ + dtype->common.obj_type = H5I_DATATYPE; + dtype->common.file = obj->file; + dtype->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_DTYPE_COMMIT_ID, HG_DTYPE_COMMIT, + (H5VL_iod_object_t *)dtype, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, &dtype->remote_dtype, dtype, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship datatype commit"); + + ret_value = (void *)dtype; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free dtype components */ + if(dtype->common.obj_name) { + HDfree(dtype->common.obj_name); + dtype->common.obj_name = NULL; + } + if(dtype->common.comment) { + HDfree(dtype->common.comment); + dtype->common.comment = NULL; + } + if(dtype->remote_dtype.tcpl_id != FAIL && H5I_dec_ref(dtype->remote_dtype.tcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->tapl_id != FAIL && H5I_dec_ref(dtype->tapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->remote_dtype.type_id != FAIL && H5I_dec_ref(dtype->remote_dtype.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dtype) + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_datatype_commit() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_datatype_open + * + * Purpose: Opens a named datatype. + * + * Return: Success: datatype id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_datatype_open(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t tapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the datatype */ + H5VL_iod_dtype_t *dtype = NULL; /* the datatype object that is created and passed to the user */ + dtype_open_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the datatype object that is returned to the user */ + if(NULL == (dtype = H5FL_CALLOC(H5VL_iod_dtype_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dtype->remote_dtype.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_id = IOD_OBJ_INVALID; + dtype->remote_dtype.mdkv_id = IOD_OBJ_INVALID; + dtype->remote_dtype.attrkv_id = IOD_OBJ_INVALID; + dtype->remote_dtype.tcpl_id = -1; + dtype->remote_dtype.type_id = -1; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.tapl_id = tapl_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Datatype Open %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + name, input.loc_id, g_axe_id); +#endif + + /* setup the local datatype struct */ + /* store the entire path of the datatype locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (dtype->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dtype->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dtype->common.obj_name+obj_name_len, name, name_len); + dtype->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((dtype->tapl_id = H5Pcopy(tapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy tapl"); + + /* set common object parameters */ + dtype->common.obj_type = H5I_DATATYPE; + dtype->common.file = obj->file; + dtype->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_DTYPE_OPEN_ID, HG_DTYPE_OPEN, + (H5VL_iod_object_t *)dtype, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, &dtype->remote_dtype, dtype, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship datatype open"); + + ret_value = (void *)dtype; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free dtype components */ + if(dtype->common.obj_name) { + HDfree(dtype->common.obj_name); + dtype->common.obj_name = NULL; + } + if(dtype->common.comment) { + HDfree(dtype->common.comment); + dtype->common.comment = NULL; + } + if(dtype->remote_dtype.tcpl_id != FAIL && H5I_dec_ref(dtype->remote_dtype.tcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->tapl_id != FAIL && H5I_dec_ref(dtype->tapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->remote_dtype.type_id != FAIL && H5I_dec_ref(dtype->remote_dtype.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dtype) + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_datatype_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_datatype_get_binary + * + * Purpose: gets size required to encode the datatype + * + * Return: Success: datatype id. + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +static ssize_t +H5VL_iod_datatype_get_binary(void *obj, unsigned char *buf, size_t size, + hid_t UNUSED dxpl_id, void UNUSED **req) +{ + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)obj; + size_t nalloc = size; + ssize_t ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + if(H5Tencode(dtype->remote_dtype.type_id, buf, &nalloc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't determine serialized length of datatype") + + ret_value = (ssize_t) nalloc; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_datatype_get_binary() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_datatype_get + * + * Purpose: Gets certain information about a datatype + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * June, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_datatype_get(void UNUSED *obj, H5VL_datatype_get_t get_type, + hid_t UNUSED dxpl_id, void UNUSED **req, va_list UNUSED arguments) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + switch (get_type) { + /* H5Tget_create_plist */ + case H5VL_DATATYPE_GET_TCPL: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + H5P_genplist_t *tcpl_plist = NULL; /* New datatype creation property list */ + hid_t tcpl_id; + + /* Copy the default datatype creation property list */ + if(NULL == (tcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATATYPE_CREATE_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default creation property list") + if((tcpl_id = H5P_copy_plist(tcpl_plist, TRUE)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to copy the creation property list") + + *ret_id = tcpl_id; + break; + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from datatype") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_datatype_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_datatype_close + * + * Purpose: Closes an datatype. + * + * Return: Success: 0 + * Failure: -1, datatype not closed. + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_datatype_close(void *obj, hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)obj; + dtype_close_in_t input; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + int *status = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(dtype->common.file, dtype) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(IOD_OH_UNDEFINED == dtype->remote_dtype.iod_oh.rd_oh.cookie) { + /* Synchronously wait on the request attached to the dtype */ + if(H5VL_iod_request_wait(dtype->common.file, dtype->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on dtype request"); + dtype->common.request = NULL; + } + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dtype, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)dtype, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parent requests"); + } + + input.iod_oh = dtype->remote_dtype.iod_oh; + input.iod_id = dtype->remote_dtype.iod_id; + +#if H5VL_IOD_DEBUG + printf("Datatype Close IOD ID %"PRIu64", axe id %"PRIu64"\n", input.iod_id, g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_DTYPE_CLOSE_ID, HG_DTYPE_CLOSE, + (H5VL_iod_object_t *)dtype, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship datatype open"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_datatype_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_create + * + * Purpose: Sends a request to the IOD to create a attribute + * + * Return: Success: attribute object. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_attribute_create(void *_obj, H5VL_loc_params_t loc_params, const char *attr_name, + hid_t acpl_id, hid_t UNUSED aapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the attribute */ + H5VL_iod_attr_t *attr = NULL; /* the attribute object that is created and passed to the user */ + attr_create_in_t input; + H5P_genplist_t *plist = NULL; + iod_obj_id_t iod_id, attrkv_id; + iod_handles_t iod_oh; + const char *path; /* path on where the traversal starts relative to the location object specified */ + char *loc_name = NULL; + hid_t type_id, space_id; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* Get the acpl plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(acpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + + /* get datatype, dataspace, and lcpl IDs that were added in the acpl at the API layer */ + if(H5P_get(plist, H5VL_ATTR_TYPE_ID, &type_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for datatype id"); + if(H5P_get(plist, H5VL_ATTR_SPACE_ID, &space_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for space id"); + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the attribute object that is returned to the user */ + if(NULL == (attr = H5FL_CALLOC(H5VL_iod_attr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + attr->remote_attr.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + attr->remote_attr.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + + /* Generate IOD IDs for the attr to be created */ + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.array_oid_index, + IOD_OBJ_ARRAY, &input.attr_id); + attr->remote_attr.iod_id = input.attr_id; + /* increment the index of ARRAY objects created on the container */ + obj->file->remote_file.array_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.mdkv_id); + attr->remote_attr.mdkv_id = input.mdkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_attrkv_id = attrkv_id; + input.loc_oh = iod_oh; + input.path = loc_name; + input.attr_name = attr_name; + input.type_id = type_id; + input.space_id = space_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + /* setup the local attribute struct */ + /* store the entire path of the attribute locally */ + if(loc_params.type == H5VL_OBJECT_BY_SELF) { + path = NULL; + attr->loc_name = HDstrdup(obj->obj_name); + } + else if (loc_params.type == H5VL_OBJECT_BY_NAME && + (NULL != obj->obj_name)) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len; + + path = loc_params.loc_data.loc_by_name.name; + name_len = HDstrlen(path); + + if (NULL == (attr->loc_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(attr->loc_name, obj->obj_name, obj_name_len); + HDmemcpy(attr->loc_name+obj_name_len, path, name_len); + attr->loc_name[obj_name_len+name_len] = '\0'; + } + + /* store the name of the attribute locally */ + attr->common.obj_name = strdup(attr_name); + +#if H5VL_IOD_DEBUG + printf("Attribute Create %s IOD ID %"PRIu64", axe id %"PRIu64"\n", + attr_name, input.attr_id, g_axe_id); +#endif + + /* copy dtype, and dspace */ + if((attr->remote_attr.type_id = H5Tcopy(type_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dtype"); + if((attr->remote_attr.space_id = H5Scopy(space_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dspace"); + + /* set common object parameters */ + attr->common.obj_type = H5I_ATTR; + attr->common.file = obj->file; + attr->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_ATTR_CREATE_ID, HG_ATTR_CREATE, + (H5VL_iod_object_t *)attr, 1, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, &attr->remote_attr, + attr, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship attribute create"); + + ret_value = (void *)attr; + +done: + if(loc_name) + HDfree(loc_name); + + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free attr components */ + if(attr->common.obj_name) { + HDfree(attr->common.obj_name); + attr->common.obj_name = NULL; + } + if(attr->common.comment) { + HDfree(attr->common.comment); + attr->common.comment = NULL; + } + if(attr->loc_name) { + HDfree(attr->loc_name); + attr->loc_name = NULL; + } + if(attr->remote_attr.type_id != FAIL && H5I_dec_ref(attr->remote_attr.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(attr->remote_attr.space_id != FAIL && H5I_dec_ref(attr->remote_attr.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(attr) + attr = H5FL_FREE(H5VL_iod_attr_t, attr); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_open + * + * Purpose: Sends a request to the IOD to open a attribute + * + * Return: Success: attribute object. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_attribute_open(void *_obj, H5VL_loc_params_t loc_params, const char *attr_name, + hid_t UNUSED aapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the attribute */ + H5VL_iod_attr_t *attr = NULL; /* the attribute object that is created and passed to the user */ + attr_open_in_t input; + const char *path; /* path on where the traversal starts relative to the location object specified */ + char *loc_name = NULL; + iod_obj_id_t iod_id, attrkv_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the attribute object that is returned to the user */ + if(NULL == (attr = H5FL_CALLOC(H5VL_iod_attr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + attr->remote_attr.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + attr->remote_attr.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + attr->remote_attr.iod_id = IOD_OBJ_INVALID; + attr->remote_attr.mdkv_id = IOD_OBJ_INVALID; + attr->remote_attr.type_id = -1; + attr->remote_attr.space_id = -1; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_attrkv_id = attrkv_id; + input.loc_oh = iod_oh; + input.path = loc_name; + input.attr_name = attr_name; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Attribute Open %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + attr_name, input.loc_id, g_axe_id); +#endif + + /* setup the local attribute struct */ + + /* store the entire path of the attribute locally */ + if(loc_params.type == H5VL_OBJECT_BY_SELF) { + path = NULL; + attr->loc_name = HDstrdup(obj->obj_name); + } + else if (loc_params.type == H5VL_OBJECT_BY_NAME && + NULL != obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len; + + path = loc_params.loc_data.loc_by_name.name; + name_len = HDstrlen(path); + + if (NULL == (attr->loc_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(attr->loc_name, obj->obj_name, obj_name_len); + HDmemcpy(attr->loc_name+obj_name_len, path, name_len); + attr->loc_name[obj_name_len+name_len] = '\0'; + } + + /* store the name of the attribute locally */ + attr->common.obj_name = strdup(attr_name); + + /* set common object parameters */ + attr->common.obj_type = H5I_ATTR; + attr->common.file = obj->file; + attr->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_ATTR_OPEN_ID, HG_ATTR_OPEN, + (H5VL_iod_object_t *)attr, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, &attr->remote_attr, attr, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship attribute open"); + + ret_value = (void *)attr; + +done: + if(loc_name) + HDfree(loc_name); + + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free attr components */ + if(attr->common.obj_name) { + HDfree(attr->common.obj_name); + attr->common.obj_name = NULL; + } + if(attr->common.comment) { + HDfree(attr->common.comment); + attr->common.comment = NULL; + } + if(attr->loc_name) { + HDfree(attr->loc_name); + attr->loc_name = NULL; + } + if(attr->remote_attr.type_id != FAIL && H5I_dec_ref(attr->remote_attr.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(attr->remote_attr.space_id != FAIL && H5I_dec_ref(attr->remote_attr.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(attr) + attr = H5FL_FREE(H5VL_iod_attr_t, attr); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_read + * + * Purpose: Reads raw data from a attribute into a buffer. + * + * Return: Success: 0 + * Failure: -1, data not read. + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_attribute_read(void *_attr, hid_t type_id, void *buf, hid_t dxpl_id, void **req) +{ + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)_attr; + attr_io_in_t input; + hg_bulk_t *bulk_handle = NULL; + int *status = NULL; + size_t size; + H5VL_iod_attr_io_info_t *info = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5P_genplist_t *plist = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + + if(-1 == attr->remote_attr.space_id) { + HDassert(attr->common.request); + /* Synchronously wait on the request attached to the attribute */ + if(H5VL_iod_request_wait(attr->common.file, attr->common.request) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't wait on HG request"); + attr->common.request = NULL; + } + + /* MSC - VLEN datatypes for attributes are not supported for now. */ + { + H5T_class_t dt_class; + H5T_t *dt = NULL; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + dt_class = H5T_get_class(dt, FALSE); + if(H5T_VLEN == dt_class || (H5T_STRING == dt_class && H5T_is_variable_str(dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "VLEN datatypes for attributes not supported"); + } + + /* calculate the size of the buffer needed */ + { + hsize_t nelmts; + size_t elmt_size; + + nelmts = (hsize_t)H5Sget_simple_extent_npoints(attr->remote_attr.space_id); + elmt_size = H5Tget_size(type_id); + + size = elmt_size * nelmts; + } + + /* allocate a bulk data transfer handle */ + if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, size, HG_BULK_READWRITE, bulk_handle)) + HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)attr, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = attr->common.file->remote_file.coh; + input.iod_oh = attr->remote_attr.iod_oh; + input.iod_id = attr->remote_attr.iod_id; + input.mdkv_id = attr->remote_attr.mdkv_id; + input.bulk_handle = *bulk_handle; + input.type_id = type_id; + input.space_id = attr->remote_attr.space_id; + input.rcxt_num = rc->c_version; + input.cs_scope = attr->common.file->md_integrity_scope; + input.trans_num = 0; + + /* allocate structure to receive status of read operation (contains return value and checksum */ + status = (int *)malloc(sizeof(int)); + + /* setup info struct for I/O request. + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_attr_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_attr_io_info_t)))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a request"); + info->status = status; + info->bulk_handle = bulk_handle; + +#if H5VL_IOD_DEBUG + printf("Attribute Read IOD ID %"PRIu64", axe id %"PRIu64"\n", + input.iod_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_ATTR_READ_ID, HG_ATTR_READ, + (H5VL_iod_object_t *)attr, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute read"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_write + * + * Purpose: Writes raw data from a buffer into a attribute. + * + * Return: Success: 0 + * Failure: -1, attribute not writed. + * + * Programmer: Mohamad Chaarawi + * October, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_attribute_write(void *_attr, hid_t type_id, const void *buf, hid_t dxpl_id, void **req) +{ + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)_attr; + attr_io_in_t input; + H5P_genplist_t *plist = NULL; + hg_bulk_t *bulk_handle = NULL; + int *status = NULL; + size_t size; + uint64_t internal_cs; /* internal checksum calculated in this function */ + H5VL_iod_attr_io_info_t *info; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(-1 == attr->remote_attr.space_id) { + /* Synchronously wait on the request attached to the attribute */ + if(H5VL_iod_request_wait(attr->common.file, attr->common.request) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't wait on HG request"); + attr->common.request = NULL; + } + + /* MSC - VLEN datatypes for attributes are not supported for now. */ + { + H5T_class_t dt_class; + H5T_t *dt = NULL; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + dt_class = H5T_get_class(dt, FALSE); + if(H5T_VLEN == dt_class || (H5T_STRING == dt_class && H5T_is_variable_str(dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "VLEN datatypes for attributes not supported"); + } + + /* calculate the size of the buffer needed */ + { + hsize_t nelmts; + size_t elmt_size; + + nelmts = (hsize_t)H5Sget_simple_extent_npoints(attr->remote_attr.space_id); + elmt_size = H5Tget_size(type_id); + + size = elmt_size * nelmts; + } + + /* calculate a checksum for the data */ + internal_cs = H5_checksum_crc64(buf, size); + + /* allocate a bulk data transfer handle */ + if(NULL == (bulk_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a bulk data transfer handle"); + + /* Register memory */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, size, HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't create Bulk Data Handle"); + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)attr, (H5VL_iod_req_info_t *)tr, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = attr->common.file->remote_file.coh; + input.iod_oh = attr->remote_attr.iod_oh; + input.iod_id = attr->remote_attr.iod_id; + input.mdkv_id = attr->remote_attr.mdkv_id; + input.bulk_handle = *bulk_handle; + input.type_id = type_id; + input.space_id = attr->remote_attr.space_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.checksum = internal_cs; + input.cs_scope = attr->common.file->md_integrity_scope; + + status = (int *)malloc(sizeof(int)); + + /* setup info struct for I/O request + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_attr_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_attr_io_info_t)))) + HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't allocate a request"); + info->status = status; + info->bulk_handle = bulk_handle; + +#if H5VL_IOD_DEBUG + printf("Attribute Write IOD ID %"PRIu64", axe id %"PRIu64"\n", + input.iod_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_ATTR_WRITE_ID, HG_ATTR_WRITE, + (H5VL_iod_object_t *)attr, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute write"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_remove + * + * Purpose: Set Extent of attribute + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * October, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_attribute_remove(void *_obj, H5VL_loc_params_t loc_params, const char *attr_name, + hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the attribute */ + attr_op_in_t input; + iod_obj_id_t iod_id, attrkv_id; + iod_handles_t iod_oh; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5P_genplist_t *plist = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + int *status = NULL; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.cs_scope = obj->file->md_integrity_scope; + input.loc_id = iod_id; + input.loc_attrkv_id = attrkv_id; + input.loc_oh = iod_oh; + input.path = loc_name; + input.attr_name = attr_name; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Attribute Remove loc %s name %s, axe id %"PRIu64"\n", + loc_name, attr_name, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_ATTR_REMOVE_ID, HG_ATTR_REMOVE, + (H5VL_iod_object_t *)obj, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute remove"); + +done: + if(loc_name) { + HDfree(loc_name); + loc_name = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_get + * + * Purpose: Gets certain information about a attribute + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_attribute_get(void *_obj, H5VL_attr_get_t get_type, hid_t dxpl_id, + void **req, va_list arguments) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location of operation */ + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + + switch (get_type) { + /* H5Aget_space */ + case H5VL_ATTR_GET_SPACE: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + + if(-1 == attr->remote_attr.space_id) { + /* Synchronously wait on the request attached to the attribute */ + if(H5VL_iod_request_wait(attr->common.file, attr->common.request) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't wait on HG request"); + attr->common.request = NULL; + } + + if((*ret_id = H5Scopy(attr->remote_attr.space_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get dataspace ID of attribute") + break; + } + /* H5Aget_type */ + case H5VL_ATTR_GET_TYPE: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + + if(-1 == attr->remote_attr.type_id) { + /* Synchronously wait on the request attached to the attribute */ + if(H5VL_iod_request_wait(attr->common.file, attr->common.request) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't wait on HG request"); + attr->common.request = NULL; + } + + if((*ret_id = H5Tcopy(attr->remote_attr.type_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of attribute") + break; + } + /* H5Aget_create_plist */ + case H5VL_ATTR_GET_ACPL: + { + hid_t *ret_id = va_arg (arguments, hid_t *); + //H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + + /* Retrieve the file's access property list */ + if((*ret_id = H5Pcopy(H5P_ATTRIBUTE_CREATE_DEFAULT)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get attr creation property list"); + break; + } + /* H5Aget_name */ + case H5VL_ATTR_GET_NAME: + { + H5VL_loc_params_t loc_params = va_arg (arguments, H5VL_loc_params_t); + size_t buf_size = va_arg (arguments, size_t); + char *buf = va_arg (arguments, char *); + ssize_t *ret_val = va_arg (arguments, ssize_t *); + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) { + size_t copy_len, nbytes; + + nbytes = HDstrlen(attr->common.obj_name); + HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/ + + /* compute the string length which will fit into the user's buffer */ + copy_len = MIN(buf_size - 1, nbytes); + + /* Copy all/some of the name */ + if(buf && copy_len > 0) { + HDmemcpy(buf, attr->common.obj_name, copy_len); + + /* Terminate the string */ + buf[copy_len]='\0'; + } /* end if */ + *ret_val = (ssize_t)nbytes; + } + else if(H5VL_OBJECT_BY_IDX == loc_params.type) { + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get name of attr"); + } + break; + } + /* H5Aexists/exists_by_name */ + case H5VL_ATTR_EXISTS: + { + H5VL_loc_params_t loc_params = va_arg (arguments, H5VL_loc_params_t); + char *attr_name = va_arg (arguments, char *); + htri_t *ret = va_arg (arguments, htri_t *); + attr_op_in_t input; + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &input.loc_attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, &input.loc_attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.attr_name = attr_name; + input.path = loc_name; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.trans_num = 0; + +#if H5VL_IOD_DEBUG + printf("Attribute Exists loc %s name %s, axe id %"PRIu64"\n", + loc_name, attr_name, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_ATTR_EXISTS_ID, HG_ATTR_EXISTS, + obj, 1, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, + ret, ret, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute exists"); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Aget_info */ + case H5VL_ATTR_GET_INFO: + { +#if 0 + H5VL_loc_params_t loc_params = va_arg (arguments, H5VL_loc_params_t); + H5A_info_t *ainfo = va_arg (arguments, H5A_info_t *); + + if(H5VL_OBJECT_BY_SELF == loc_params.type) { + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get attr info") + } + else if(H5VL_OBJECT_BY_NAME == loc_params.type) { + char *attr_name = va_arg (arguments, char *); + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get attr info") + } + else if(H5VL_OBJECT_BY_IDX == loc_params.type) { + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get attr info") + } + else + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get attr info") +#endif + break; + } + case H5VL_ATTR_GET_STORAGE_SIZE: + { + //hsize_t *ret = va_arg (arguments, hsize_t *); + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get attr storage size"); + break; + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from attr") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_attribute_close + * + * Purpose: Closes a attribute. + * + * Return: Success: 0 + * Failure: -1, attribute not closed. + * + * Programmer: Mohamad Chaarawi + * March, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_attribute_close(void *_attr, hid_t UNUSED dxpl_id, void **req) +{ + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)_attr; + attr_close_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(-1 == attr->remote_attr.type_id || + -1 == attr->remote_attr.space_id || + IOD_OH_UNDEFINED == attr->remote_attr.iod_oh.rd_oh.cookie) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(attr->common.file, attr->common.request) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't wait on HG request"); + attr->common.request = NULL; + } + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(attr->common.file, attr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)attr, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)attr, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parent requests"); + } + + status = (int *)malloc(sizeof(int)); + + input.iod_oh = attr->remote_attr.iod_oh; + input.iod_id = attr->remote_attr.iod_id; + +#if H5VL_IOD_DEBUG + printf("Attribute Close IOD ID %"PRIu64", axe id %"PRIu64"\n", input.iod_id, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_ATTR_CLOSE_ID, HG_ATTR_CLOSE, + (H5VL_iod_object_t *)attr, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute close"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_attribute_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_link_create + * + * Purpose: Creates an hard/soft/UD/external links. + * For now, only Hard and Soft Links are Supported. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_link_create(H5VL_link_create_type_t create_type, void *_obj, H5VL_loc_params_t loc_params, + hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object */ + link_create_in_t input; + int *status = NULL; + H5P_genplist_t *plist = NULL; /* Property list pointer */ + char *link_value = NULL; /* Value of soft link */ + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + hid_t trans_id; + H5TR_t *tr = NULL; + char *loc_name = NULL, *target_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* Get the plist structure */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(lcpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 3))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + status = (int *)malloc(sizeof(int)); + + switch (create_type) { + case H5VL_LINK_CREATE_HARD: + { + H5VL_iod_object_t *target_obj = NULL; + H5VL_loc_params_t target_params; + + if(H5P_get(plist, H5VL_LINK_TARGET, &target_obj) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for current location"); + if(H5P_get(plist, H5VL_LINK_TARGET_LOC_PARAMS, &target_params) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for current name"); + + /* object is H5L_SAME_LOC */ + if(NULL == obj && target_obj) { + obj = target_obj; + } + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* Retrieve the parent info by traversing the path where the + link should be created. */ + + /* object is H5L_SAME_LOC */ + if(NULL == target_obj && obj) { + target_obj = obj; + } + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(target_obj, NULL, + &parent_reqs[num_parents], &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(target_obj, &input.target_loc_id, + &input.target_loc_oh, &input.target_mdkv_id, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.target_loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(target_obj->file, target_obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + target_obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(target_obj, &input.target_loc_id, + &input.target_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == target_params.type) + target_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == target_params.type) + target_name = strdup(target_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.create_type = H5VL_LINK_CREATE_HARD; + if(obj) + input.coh = obj->file->remote_file.coh; + else + input.coh = target_obj->file->remote_file.coh; + + input.target_name = target_name; + input.loc_name = loc_name; + input.lcpl_id = lcpl_id; + input.lapl_id = lapl_id; + link_value = strdup("\0"); + input.link_value = link_value; + +#if H5VL_IOD_DEBUG + printf("Link Create Hard axe id %"PRIu64"\n", g_axe_id); +#endif + break; + } + case H5VL_LINK_CREATE_SOFT: + { + H5VL_iod_object_t *target_obj = NULL; + H5VL_loc_params_t target_params; + + if(H5P_get(plist, H5VL_LINK_TARGET_NAME, &target_name) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for targe name"); + + target_params.type = H5VL_OBJECT_BY_NAME; + target_params.loc_data.loc_by_name.name = target_name; + target_params.loc_data.loc_by_name.plist_id = lapl_id; + + if('/' == *target_name) { + /* The target location object is the file root */ + target_obj = (H5VL_iod_object_t *)obj->file; + } + else { + target_obj = obj; + } + + link_value = strdup(target_name); + + /* Retrieve the parent info by traversing the path where the + link should be created from. */ + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(target_obj, NULL, + &parent_reqs[num_parents], &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(target_obj, &input.target_loc_id, + &input.target_loc_oh, &input.target_mdkv_id, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.target_loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(target_obj->file, target_obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + target_obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(target_obj, &input.target_loc_id, + &input.target_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + /* set the input structure for the HG encode routine */ + input.create_type = H5VL_LINK_CREATE_SOFT; + input.coh = obj->file->remote_file.coh; + input.loc_name = loc_name; + input.target_name = target_name; + input.lcpl_id = lcpl_id; + input.lapl_id = lapl_id; + input.link_value = link_value; + +#if H5VL_IOD_DEBUG + printf("Link Create Soft axe id %"PRIu64"\n", g_axe_id); +#endif + break; + } + /* MSC - not supported now */ + case H5VL_LINK_CREATE_UD: + { + H5L_type_t link_type; + void *udata; + size_t udata_size; + + if(H5P_get(plist, H5VL_LINK_TYPE, &link_type) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for link type"); + if(H5P_get(plist, H5VL_LINK_UDATA, &udata) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for udata"); + if(H5P_get(plist, H5VL_LINK_UDATA_SIZE, &udata_size) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for udata size"); + } + default: + HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "invalid link creation call") + } + + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + if(H5VL__iod_create_and_forward(H5VL_LINK_CREATE_ID, HG_LINK_CREATE, + obj, 1, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link create"); + +done: + if(link_value) + HDfree(link_value); + if(loc_name) + HDfree(loc_name); + if(H5VL_LINK_CREATE_HARD == create_type && target_name) + HDfree(target_name); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_link_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_link_move + * + * Purpose: Renames an object within an HDF5 file and moves it to a new + * group. The original name SRC is unlinked from the group graph + * and then inserted with the new name DST (which can specify a + * new path for the object) as an atomic operation. The names + * are interpreted relative to SRC_LOC_ID and + * DST_LOC_ID, which are either file IDs or group ID. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_link_move(void *_src_obj, H5VL_loc_params_t loc_params1, + void *_dst_obj, H5VL_loc_params_t loc_params2, + hbool_t copy_flag, hid_t lcpl_id, hid_t lapl_id, + hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *src_obj = (H5VL_iod_object_t *)_src_obj; + H5VL_iod_object_t *dst_obj = (H5VL_iod_object_t *)_dst_obj; + link_move_in_t input; + int *status = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + H5P_genplist_t *plist = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + char *src_name = NULL, *dst_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 3))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(src_obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(src_obj, &input.src_loc_id, &input.src_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.src_loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(src_obj->file, src_obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + src_obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(src_obj, &input.src_loc_id, + &input.src_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params1.type) + src_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params1.type) + src_name = strdup(loc_params1.loc_data.loc_by_name.name); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(dst_obj, NULL, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(dst_obj, &input.dst_loc_id, &input.dst_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.dst_loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(dst_obj->file, dst_obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + dst_obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(dst_obj, &input.dst_loc_id, + &input.dst_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params2.type) + dst_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params2.type) + dst_name = strdup(loc_params2.loc_data.loc_by_name.name); + + /* if the object, to be moved is open locally, then update its + link information */ + if(!copy_flag && 0 == strcmp(src_name, ".")) { + char *link_name = NULL; + + /* generate the entire path of the new link */ + { + size_t obj_name_len = HDstrlen(dst_obj->obj_name); + size_t name_len = HDstrlen(loc_params2.loc_data.loc_by_name.name); + + if (NULL == (link_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate"); + HDmemcpy(link_name, dst_obj->obj_name, obj_name_len); + HDmemcpy(link_name+obj_name_len, loc_params2.loc_data.loc_by_name.name, name_len); + link_name[obj_name_len+name_len] = '\0'; + } + //H5VL_iod_update_link(dst_obj, loc_params2, link_name); + free(link_name); + } + + /* set the input structure for the HG encode routine */ + input.coh = src_obj->file->remote_file.coh; + input.copy_flag = copy_flag; + input.src_loc_name = src_name; + input.dst_loc_name = dst_name; + input.lcpl_id = lcpl_id; + input.lapl_id = lapl_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = src_obj->file->md_integrity_scope; + + status = (herr_t *)malloc(sizeof(herr_t)); + + if(H5VL__iod_create_and_forward(H5VL_LINK_MOVE_ID, HG_LINK_MOVE, dst_obj, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, + status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link move"); + +done: + if(src_name) + free(src_name); + if(dst_name) + free(dst_name); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_link_move() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_link_iterate + * + * Purpose: Iterates through links in a group + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t H5VL_iod_link_iterate(void UNUSED *_obj, H5VL_loc_params_t UNUSED loc_params, + hbool_t UNUSED recursive, + H5_index_t UNUSED idx_type, H5_iter_order_t UNUSED order, + hsize_t UNUSED *idx, + H5L_iterate_t UNUSED op, void UNUSED *op_data, + hid_t UNUSED dxpl_id, void UNUSED **req) +{ + //H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + //herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_link_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_link_get + * + * Purpose: Gets certain data about a link + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_link_get(void *_obj, H5VL_loc_params_t loc_params, H5VL_link_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + hid_t rcxt_id; + H5RC_t *rc = NULL; + H5P_genplist_t *plist = NULL; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + switch (get_type) { + /* H5Lexists */ + case H5VL_LINK_EXISTS: + { + link_op_in_t input; + htri_t *ret = va_arg (arguments, htri_t *); + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.trans_num = 0; + input.path = loc_name; + +#if H5VL_IOD_DEBUG + printf("Link Exists axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_LINK_EXISTS_ID, HG_LINK_EXISTS, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, ret, ret, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link exists"); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Lget_info/H5Lget_info_by_idx */ + case H5VL_LINK_GET_INFO: + { + H5L_ff_info_t *linfo = va_arg (arguments, H5L_ff_info_t *); + link_op_in_t input; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.trans_num = 0; + input.path = loc_name; + +#if H5VL_IOD_DEBUG + printf("Link get info axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_LINK_GET_INFO_ID, HG_LINK_GET_INFO, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, linfo, linfo, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link get_info"); + + if(loc_name) + HDfree(loc_name); + + break; + } + /* H5Lget_val/H5Lget_val_by_idx */ + case H5VL_LINK_GET_VAL: + { + void *buf = va_arg (arguments, void *); + size_t size = va_arg (arguments, size_t); + link_get_val_in_t input; + link_get_val_out_t *result; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.length = size; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.path = loc_name; + + if(NULL == (result = (link_get_val_out_t *)malloc + (sizeof(link_get_val_out_t)))) { + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate get val return struct"); + } + + result->value.val_size = input.length; + result->value.val = buf; + +#if H5VL_IOD_DEBUG + printf("Link get val axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_LINK_GET_VAL_ID, HG_LINK_GET_VAL, obj, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, result, result, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link get_val"); + + if(loc_name) + HDfree(loc_name); + + break; + } + /* H5Lget_name_by_idx */ + case H5VL_LINK_GET_NAME: + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from link") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_link_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_link_remove + * + * Purpose: Removes the specified NAME from the group graph and + * decrements the link count for the object to which NAME + * points. If the link count reaches zero then all file-space + * associated with the object will be reclaimed (but if the + * object is open, then the reclamation of the file space is + * delayed until all handles to the object are closed). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_link_remove(void *_obj, H5VL_loc_params_t loc_params, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + link_op_in_t input; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5P_genplist_t *plist = NULL; + int *status = NULL; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.path = loc_name; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Link Remove axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, loc_name, input.loc_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_LINK_REMOVE_ID, HG_LINK_REMOVE, obj, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship link remove"); + +done: + if(loc_name) + HDfree(loc_name); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_link_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_obj_open_token + * + * Purpose: Opens a object inside IOD file using it IOD ID + * + * Return: Success: object id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void * +H5VL_iod_obj_open_token(const void *token, H5TR_t *tr, H5I_type_t *opened_type, void **req) +{ + object_token_in_t input; + const uint8_t *buf_ptr = (const uint8_t *)token; + H5O_type_t obj_type; + iod_obj_id_t iod_id, mdkv_id, attrkv_id; + H5VL_iod_dset_t *dset = NULL; /* the dataset object that is created and passed to the user */ + H5VL_iod_dtype_t *dtype = NULL; /* the datatype object that is created and passed to the user */ + H5VL_iod_group_t *grp = NULL; /* the group object that is created and passed to the user */ + H5VL_iod_map_t *map = NULL; /* the map object that is created and passed to the user */ + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + HDmemcpy(&iod_id, buf_ptr, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(&mdkv_id, buf_ptr, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(&attrkv_id, buf_ptr, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(&obj_type, buf_ptr, sizeof(H5O_type_t)); + buf_ptr += sizeof(H5O_type_t); + + switch(obj_type) { + case H5O_TYPE_DATASET: + /* allocate the dataset object that is returned to the user */ + if(NULL == (dset = H5FL_CALLOC(H5VL_iod_dset_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dset->remote_dset.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dset->remote_dset.iod_id = iod_id; + dset->remote_dset.mdkv_id = mdkv_id; + dset->remote_dset.attrkv_id = attrkv_id; + + dset->dapl_id = H5Pcopy(H5P_DATASET_ACCESS_DEFAULT); + dset->remote_dset.dcpl_id = H5Pcopy(H5P_DATASET_CREATE_DEFAULT); + + /* decode dtype */ + { + H5T_t *dt = NULL; + size_t dt_size; + + HDmemcpy(&dt_size, buf_ptr, sizeof(size_t)); + buf_ptr += sizeof(size_t); + /* Create datatype by decoding buffer */ + if(NULL == (dt = H5T_decode((const unsigned char *)buf_ptr))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object"); + /* Register the type */ + if((dset->remote_dset.type_id = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register data type"); + buf_ptr += dt_size; + } + + /* decode dspace */ + { + H5S_t *ds; + size_t space_size; + + HDmemcpy(&space_size, buf_ptr, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if((ds = H5S_decode((const unsigned char *)buf_ptr)) == NULL) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode object"); + /* Register the type */ + if((dset->remote_dset.space_id = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, NULL, "unable to register dataspace"); + buf_ptr += space_size; + } + + input.coh = tr->file->remote_file.coh; + input.iod_id = iod_id; + input.trans_num = tr->trans_num; + + /* set common object parameters */ + dset->common.obj_type = H5I_DATASET; + dset->common.file = tr->file; + dset->common.file->nopen_objs ++; + dset->common.obj_name = NULL; + +#if H5VL_IOD_DEBUG + printf("Dataset open by token %"PRIu64": ID %"PRIu64"\n", + g_axe_id, input.iod_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_OPEN_BY_TOKEN_ID, HG_OBJECT_OPEN_BY_TOKEN, + (H5VL_iod_object_t *)dset, 1, 0, NULL, + (H5VL_iod_req_info_t *)tr, &input, + &dset->remote_dset.iod_oh, dset, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship dataset open_by_token"); + + ret_value = (void *)dset; + *opened_type = H5I_DATASET; + break; + case H5O_TYPE_NAMED_DATATYPE: + /* allocate the datatype object that is returned to the user */ + if(NULL == (dtype = H5FL_CALLOC(H5VL_iod_dtype_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dtype->remote_dtype.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + dtype->remote_dtype.iod_id = iod_id; + dtype->remote_dtype.mdkv_id = mdkv_id; + dtype->remote_dtype.attrkv_id = attrkv_id; + + dtype->tapl_id = H5Pcopy(H5P_DATATYPE_ACCESS_DEFAULT); + dtype->remote_dtype.tcpl_id = H5Pcopy(H5P_DATATYPE_CREATE_DEFAULT); + + /* decode dtype */ + { + H5T_t *dt = NULL; + size_t dt_size; + + HDmemcpy(&dt_size, buf_ptr, sizeof(size_t)); + buf_ptr += sizeof(size_t); + /* Create datatype by decoding buffer */ + if(NULL == (dt = H5T_decode((const unsigned char *)buf_ptr))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object"); + /* Register the type */ + if((dtype->remote_dtype.type_id = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register data type"); + buf_ptr += dt_size; + } + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.iod_id = iod_id; + input.trans_num = tr->trans_num; + + /* set common object parameters */ + dtype->common.obj_type = H5I_DATATYPE; + dtype->common.file = tr->file; + dtype->common.file->nopen_objs ++; + dtype->common.obj_name = NULL; + +#if H5VL_IOD_DEBUG + printf("Named Datatype open by token %"PRIu64": ID %"PRIu64"\n", + g_axe_id, input.iod_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_OPEN_BY_TOKEN_ID, HG_OBJECT_OPEN_BY_TOKEN, + (H5VL_iod_object_t *)dtype, 1, 0, NULL, + (H5VL_iod_req_info_t *)tr, &input, + &dtype->remote_dtype.iod_oh, dtype, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship datatype open_by_token"); + + ret_value = (void *)dtype; + *opened_type = H5I_DATATYPE; + break; + case H5O_TYPE_GROUP: + /* allocate the dataset object that is returned to the user */ + if(NULL == (grp = H5FL_CALLOC(H5VL_iod_group_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + grp->remote_group.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + grp->remote_group.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + grp->remote_group.iod_id = iod_id; + grp->remote_group.mdkv_id = mdkv_id; + grp->remote_group.attrkv_id = attrkv_id; + + grp->remote_group.gcpl_id = H5Pcopy(H5P_GROUP_CREATE_DEFAULT); + grp->gapl_id = H5Pcopy(H5P_GROUP_ACCESS_DEFAULT); + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.iod_id = iod_id; + input.trans_num = tr->trans_num; + + /* set common object parameters */ + grp->common.obj_type = H5I_GROUP; + grp->common.file = tr->file; + grp->common.file->nopen_objs ++; + grp->common.obj_name = NULL; + +#if H5VL_IOD_DEBUG + printf("Group open by token %"PRIu64": ID %"PRIu64"\n", + g_axe_id, input.iod_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_OPEN_BY_TOKEN_ID, HG_OBJECT_OPEN_BY_TOKEN, + (H5VL_iod_object_t *)grp, 1, 0, NULL, + (H5VL_iod_req_info_t *)tr, &input, + &grp->remote_group.iod_oh, grp, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship group open_by_token"); + + ret_value = (void *)grp; + *opened_type = H5I_GROUP; + break; + case H5O_TYPE_MAP: + /* allocate the dataset object that is returned to the user */ + if(NULL == (map = H5FL_CALLOC(H5VL_iod_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + map->remote_map.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_id = iod_id; + map->remote_map.mdkv_id = mdkv_id; + map->remote_map.attrkv_id = attrkv_id; + + map->remote_map.mcpl_id = H5Pcopy(H5P_MAP_CREATE_DEFAULT); + map->mapl_id = H5Pcopy(H5P_MAP_ACCESS_DEFAULT); + + /* decode key_type */ + { + H5T_t *dt = NULL; + size_t dt_size; + + HDmemcpy(&dt_size, buf_ptr, sizeof(size_t)); + buf_ptr += sizeof(size_t); + /* Create datatype by decoding buffer */ + if(NULL == (dt = H5T_decode((const unsigned char *)buf_ptr))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object"); + /* Register the type */ + if((map->remote_map.keytype_id = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register data type"); + buf_ptr += dt_size; + } + /* decode val_type */ + { + H5T_t *dt = NULL; + size_t dt_size; + + HDmemcpy(&dt_size, buf_ptr, sizeof(size_t)); + buf_ptr += sizeof(size_t); + /* Create datatype by decoding buffer */ + if(NULL == (dt = H5T_decode((const unsigned char *)buf_ptr))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object"); + /* Register the type */ + if((map->remote_map.valtype_id = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register data type"); + buf_ptr += dt_size; + } + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.iod_id = iod_id; + input.trans_num = tr->trans_num; + + /* set common object parameters */ + map->common.obj_type = H5I_MAP; + map->common.file = tr->file; + map->common.file->nopen_objs ++; + map->common.obj_name = NULL; + +#if H5VL_IOD_DEBUG + printf("Map open by token %"PRIu64": ID %"PRIu64"\n", + g_axe_id, input.iod_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_OPEN_BY_TOKEN_ID, HG_OBJECT_OPEN_BY_TOKEN, + (H5VL_iod_object_t *)map, 1, 0, NULL, + (H5VL_iod_req_info_t *)tr, &input, + &map->remote_map, map, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship map open"); + + ret_value = (void *)map; + *opened_type = H5I_MAP; + break; + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, NULL, "not a valid file object (dataset, map, group, or datatype)"); + } + +done: + if(NULL == ret_value) { + switch(obj_type) { + case H5O_TYPE_DATASET: + if(dset->common.obj_name) { + HDfree(dset->common.obj_name); + dset->common.obj_name = NULL; + } + if(dset->common.comment) { + HDfree(dset->common.comment); + dset->common.comment = NULL; + } + if(dset->remote_dset.type_id != FAIL && H5I_dec_ref(dset->remote_dset.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dset->remote_dset.space_id != FAIL && H5I_dec_ref(dset->remote_dset.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(dset->remote_dset.dcpl_id != FAIL && H5I_dec_ref(dset->remote_dset.dcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset->dapl_id != FAIL && H5I_dec_ref(dset->dapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset) + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + break; + case H5O_TYPE_NAMED_DATATYPE: + /* free dtype components */ + if(dtype->common.obj_name) { + HDfree(dtype->common.obj_name); + dtype->common.obj_name = NULL; + } + if(dtype->common.comment) { + HDfree(dtype->common.comment); + dtype->common.comment = NULL; + } + if(dtype->remote_dtype.tcpl_id != FAIL && H5I_dec_ref(dtype->remote_dtype.tcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->tapl_id != FAIL && H5I_dec_ref(dtype->tapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->remote_dtype.type_id != FAIL && H5I_dec_ref(dtype->remote_dtype.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dtype) + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + break; + case H5O_TYPE_GROUP: + if(grp->common.obj_name) { + HDfree(grp->common.obj_name); + grp->common.obj_name = NULL; + } + if(grp->common.comment) { + HDfree(grp->common.comment); + grp->common.comment = NULL; + } + if(grp->gapl_id != FAIL && H5I_dec_ref(grp->gapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp->remote_group.gcpl_id != FAIL && + H5I_dec_ref(grp->remote_group.gcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp) + grp = H5FL_FREE(H5VL_iod_group_t, grp); + break; + case H5O_TYPE_MAP: + /* free map components */ + if(map->common.obj_name) { + HDfree(map->common.obj_name); + map->common.obj_name = NULL; + } + if(map->common.comment) { + HDfree(map->common.comment); + map->common.comment = NULL; + } + if(map->remote_map.keytype_id != FAIL && H5I_dec_ref(map->remote_map.keytype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map->remote_map.valtype_id != FAIL && H5I_dec_ref(map->remote_map.valtype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map) + map = H5FL_FREE(H5VL_iod_map_t, map); + break; + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "not a valid object type"); + } /* end switch */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +}/* end H5VL_iod_obj_open_token() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_object_open + * + * Purpose: Opens a object inside IOD file. + * + * Return: Success: object id. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * November, 2012 + * + *------------------------------------------------------------------------- + */ +static void * +H5VL_iod_object_open(void *_obj, H5VL_loc_params_t loc_params, + H5I_type_t *opened_type, hid_t dxpl_id, void UNUSED **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to open the group */ + H5P_genplist_t *plist = NULL; + hid_t rcxt_id; + H5RC_t *rc = NULL; + size_t num_parents = 0; + char *loc_name = NULL; + object_op_in_t input; + H5VL_iod_remote_object_t remote_obj; /* generic remote object structure */ + H5VL_iod_dset_t *dset = NULL; /* the dataset object that is created and passed to the user */ + H5VL_iod_dtype_t *dtype = NULL; /* the datatype object that is created and passed to the user */ + H5VL_iod_group_t *grp = NULL; /* the group object that is created and passed to the user */ + H5VL_iod_map_t *map = NULL; /* the map object that is created and passed to the user */ + H5VL_iod_request_t **parent_reqs = NULL; + void *ret_value; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, &input.loc_mdkv_id, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == input.loc_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &input.loc_id, &input.loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_name = loc_name; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + /* H5Oopen has to be synchronous */ + if(H5VL__iod_create_and_forward(H5VL_OBJECT_OPEN_ID, HG_OBJECT_OPEN, + obj, 1, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, + &remote_obj, &remote_obj, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship object open"); + + *opened_type = remote_obj.obj_type; + + if(loc_name) + HDfree(loc_name); + + switch(remote_obj.obj_type) { + case H5I_DATASET: + /* allocate the dataset object that is returned to the user */ + if(NULL == (dset = H5FL_CALLOC(H5VL_iod_dset_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dset->remote_dset.iod_oh.rd_oh.cookie = remote_obj.iod_oh.rd_oh.cookie; + dset->remote_dset.iod_oh.wr_oh.cookie = remote_obj.iod_oh.wr_oh.cookie; + dset->remote_dset.iod_id = remote_obj.iod_id; + dset->remote_dset.mdkv_id = remote_obj.mdkv_id; + dset->remote_dset.attrkv_id = remote_obj.attrkv_id; + dset->remote_dset.dcpl_id = remote_obj.cpl_id; + dset->remote_dset.type_id = remote_obj.id1; + dset->remote_dset.space_id = remote_obj.id2; + + if(dset->remote_dset.dcpl_id == H5P_DEFAULT){ + dset->remote_dset.dcpl_id = H5Pcopy(H5P_DATASET_CREATE_DEFAULT); + } + + HDassert(dset->remote_dset.dcpl_id); + HDassert(dset->remote_dset.type_id); + HDassert(dset->remote_dset.space_id); + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(loc_params.loc_data.loc_by_name.name); + + if (NULL == (dset->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dset->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dset->common.obj_name+obj_name_len, + loc_params.loc_data.loc_by_name.name, name_len); + dset->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((dset->dapl_id = H5Pcopy(H5P_DATASET_CREATE_DEFAULT)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dapl"); + + /* set common object parameters */ + dset->common.obj_type = H5I_DATASET; + dset->common.file = obj->file; + dset->common.file->nopen_objs ++; + + ret_value = (void *)dset; + break; + case H5I_DATATYPE: + /* allocate the dataset object that is returned to the user */ + if(NULL == (dtype = H5FL_CALLOC(H5VL_iod_dtype_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + dtype->remote_dtype.iod_oh.rd_oh.cookie = remote_obj.iod_oh.rd_oh.cookie; + dtype->remote_dtype.iod_oh.wr_oh.cookie = remote_obj.iod_oh.wr_oh.cookie; + dtype->remote_dtype.iod_id = remote_obj.iod_id; + dtype->remote_dtype.mdkv_id = remote_obj.mdkv_id; + dtype->remote_dtype.attrkv_id = remote_obj.attrkv_id; + dtype->remote_dtype.tcpl_id = remote_obj.cpl_id; + dtype->remote_dtype.type_id = remote_obj.id1; + + if(dtype->remote_dtype.tcpl_id == H5P_DEFAULT){ + dtype->remote_dtype.tcpl_id = H5Pcopy(H5P_DATATYPE_CREATE_DEFAULT); + } + + HDassert(dtype->remote_dtype.tcpl_id); + HDassert(dtype->remote_dtype.type_id); + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(loc_params.loc_data.loc_by_name.name); + + if (NULL == (dtype->common.obj_name = (char *)HDmalloc + (obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(dtype->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(dtype->common.obj_name+obj_name_len, + loc_params.loc_data.loc_by_name.name, name_len); + dtype->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((dtype->tapl_id = H5Pcopy(H5P_DATATYPE_CREATE_DEFAULT)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dapl"); + + /* set common object parameters */ + dtype->common.obj_type = H5I_DATATYPE; + dtype->common.file = obj->file; + dtype->common.file->nopen_objs ++; + + ret_value = (void *)dtype; + break; + case H5I_GROUP: + /* allocate the dataset object that is returned to the user */ + if(NULL == (grp = H5FL_CALLOC(H5VL_iod_group_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + grp->remote_group.iod_oh.rd_oh.cookie = remote_obj.iod_oh.rd_oh.cookie; + grp->remote_group.iod_oh.wr_oh.cookie = remote_obj.iod_oh.wr_oh.cookie; + grp->remote_group.iod_id = remote_obj.iod_id; + grp->remote_group.mdkv_id = remote_obj.mdkv_id; + grp->remote_group.attrkv_id = remote_obj.attrkv_id; + grp->remote_group.gcpl_id = remote_obj.cpl_id; + + if(grp->remote_group.gcpl_id == H5P_DEFAULT){ + grp->remote_group.gcpl_id = H5Pcopy(H5P_GROUP_CREATE_DEFAULT); + } + + HDassert(grp->remote_group.gcpl_id); + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(loc_params.loc_data.loc_by_name.name); + + if (NULL == (grp->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(grp->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(grp->common.obj_name+obj_name_len, + loc_params.loc_data.loc_by_name.name, name_len); + grp->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((grp->gapl_id = H5Pcopy(H5P_GROUP_CREATE_DEFAULT)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy gapl"); + + /* set common object parameters */ + grp->common.obj_type = H5I_GROUP; + grp->common.file = obj->file; + grp->common.file->nopen_objs ++; + + ret_value = (void *)grp; + break; + case H5I_MAP: + /* allocate the dataset object that is returned to the user */ + if(NULL == (map = H5FL_CALLOC(H5VL_iod_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + map->remote_map.iod_oh.rd_oh.cookie = remote_obj.iod_oh.rd_oh.cookie; + map->remote_map.iod_oh.wr_oh.cookie = remote_obj.iod_oh.wr_oh.cookie; + map->remote_map.iod_id = remote_obj.iod_id; + map->remote_map.mdkv_id = remote_obj.mdkv_id; + map->remote_map.attrkv_id = remote_obj.attrkv_id; + map->remote_map.mcpl_id = remote_obj.cpl_id; + map->remote_map.keytype_id = remote_obj.id1; + map->remote_map.valtype_id = remote_obj.id2; + + if(map->remote_map.mcpl_id == H5P_DEFAULT){ + map->remote_map.mcpl_id = H5Pcopy(H5P_MAP_CREATE_DEFAULT); + } + + /* setup the local dataset struct */ + /* store the entire path of the dataset locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(loc_params.loc_data.loc_by_name.name); + + if (NULL == (map->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(map->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(map->common.obj_name+obj_name_len, + loc_params.loc_data.loc_by_name.name, name_len); + map->common.obj_name[obj_name_len+name_len] = '\0'; + } + + if((map->mapl_id = H5Pcopy(H5P_MAP_ACCESS_DEFAULT)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy mapl"); + + /* set common object parameters */ + map->common.obj_type = H5I_MAP; + map->common.file = obj->file; + map->common.file->nopen_objs ++; + + ret_value = (void *)map; + break; + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_VIEW: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, NULL, "not a valid file object (dataset, map, group, or datatype)") + break; + } + +done: + if(NULL == ret_value) { + switch(remote_obj.obj_type) { + case H5I_DATASET: + if(dset->common.obj_name) { + HDfree(dset->common.obj_name); + dset->common.obj_name = NULL; + } + if(dset->common.comment) { + HDfree(dset->common.comment); + dset->common.comment = NULL; + } + if(dset->remote_dset.type_id != FAIL && H5I_dec_ref(dset->remote_dset.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dset->remote_dset.space_id != FAIL && H5I_dec_ref(dset->remote_dset.space_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dspace"); + if(dset->remote_dset.dcpl_id != FAIL && H5I_dec_ref(dset->remote_dset.dcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset->dapl_id != FAIL && H5I_dec_ref(dset->dapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dset) + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + break; + case H5I_DATATYPE: + /* free dtype components */ + if(dtype->common.obj_name) { + HDfree(dtype->common.obj_name); + dtype->common.obj_name = NULL; + } + if(dtype->common.comment) { + HDfree(dtype->common.comment); + dtype->common.comment = NULL; + } + if(dtype->remote_dtype.tcpl_id != FAIL && H5I_dec_ref(dtype->remote_dtype.tcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->tapl_id != FAIL && H5I_dec_ref(dtype->tapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(dtype->remote_dtype.type_id != FAIL && H5I_dec_ref(dtype->remote_dtype.type_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(dtype) + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + break; + case H5I_GROUP: + if(grp->common.obj_name) { + HDfree(grp->common.obj_name); + grp->common.obj_name = NULL; + } + if(grp->common.comment) { + HDfree(grp->common.comment); + grp->common.comment = NULL; + } + if(grp->gapl_id != FAIL && H5I_dec_ref(grp->gapl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp->remote_group.gcpl_id != FAIL && + H5I_dec_ref(grp->remote_group.gcpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close plist"); + if(grp) + grp = H5FL_FREE(H5VL_iod_group_t, grp); + break; + case H5I_MAP: + /* free map components */ + if(map->common.obj_name) { + HDfree(map->common.obj_name); + map->common.obj_name = NULL; + } + if(map->common.comment) { + HDfree(map->common.comment); + map->common.comment = NULL; + } + if(map->remote_map.keytype_id != FAIL && H5I_dec_ref(map->remote_map.keytype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map->remote_map.valtype_id != FAIL && H5I_dec_ref(map->remote_map.valtype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map) + map = H5FL_FREE(H5VL_iod_map_t, map); + break; + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_VIEW: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "not a valid object type"); + } /* end switch */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_object_open */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_object_copy + * + * Purpose: Copys a object through the IOD plugin. + * + * Return: Success: postive. + * Failure: NULL + * + * Programmer: Mohamad Chaarawi + * November, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_object_copy(void *_src_obj, H5VL_loc_params_t UNUSED loc_params1, const char *src_name, + void *_dst_obj, H5VL_loc_params_t UNUSED loc_params2, const char *dst_name, + hid_t ocpypl_id, hid_t lcpl_id, hid_t dxpl_id, void **req) +{ + H5VL_iod_object_t *src_obj = (H5VL_iod_object_t *)_src_obj; + H5VL_iod_object_t *dst_obj = (H5VL_iod_object_t *)_dst_obj; + object_copy_in_t input; + int *status = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + H5P_genplist_t *plist = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 3))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(src_obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(src_obj, &input.src_loc_id, &input.src_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(dst_obj, NULL, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(dst_obj, &input.dst_loc_id, &input.dst_loc_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* set the input structure for the HG encode routine */ + input.coh = src_obj->file->remote_file.coh; + input.src_loc_name = src_name; + input.dst_loc_name = dst_name; + input.lcpl_id = lcpl_id; + input.ocpypl_id = ocpypl_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = src_obj->file->md_integrity_scope; + + status = (herr_t *)malloc(sizeof(herr_t)); + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_COPY_ID, HG_OBJECT_COPY, + (H5VL_iod_object_t *)dst_obj, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship object copy"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_object_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_object_visit + * + * Purpose: Iterates through all objects linked to an object + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * November, 2012 + * + *------------------------------------------------------------------------- + */ +static herr_t H5VL_iod_object_visit(void UNUSED *_obj, H5VL_loc_params_t UNUSED loc_params, + H5_index_t UNUSED idx_type, + H5_iter_order_t UNUSED order, H5O_iterate_t UNUSED op, + void UNUSED *op_data, + hid_t UNUSED dxpl_id, void UNUSED **req) +{ + //H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + //herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_object_visit() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_object_misc + * + * Purpose: Perform a plugin specific operation for an object + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * November, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_object_misc(void *_obj, H5VL_loc_params_t loc_params, H5VL_object_misc_t misc_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + iod_obj_id_t iod_id, mdkv_id, attrkv_id; + iod_handles_t iod_oh; + int *status = NULL; + size_t num_parents = 0; + hid_t trans_id; + H5TR_t *tr = NULL; + H5P_genplist_t *plist = NULL; + H5VL_iod_request_t **parent_reqs = NULL; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the transaction ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_TRANS_ID, &trans_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, &mdkv_id, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, &mdkv_id, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + switch (misc_type) { + /* H5Arename/rename_by_name */ + case H5VL_ATTR_RENAME: + { + const char *old_name = va_arg (arguments, const char *); + const char *new_name = va_arg (arguments, const char *); + attr_rename_in_t input; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.old_attr_name = old_name; + input.new_attr_name = new_name; + input.loc_id = iod_id; + input.loc_attrkv_id = attrkv_id; + input.loc_oh = iod_oh; + input.path = loc_name; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Attribute Rename %s to %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + old_name, new_name, input.loc_id, g_axe_id); +#endif + + status = (herr_t *)malloc(sizeof(herr_t)); + + if(H5VL__iod_create_and_forward(H5VL_ATTR_RENAME_ID, HG_ATTR_RENAME, + obj, 1, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship attribute rename"); + + if(loc_name) + HDfree(loc_name); + + break; + } + /* H5Oset_comment */ + case H5VL_OBJECT_SET_COMMENT: + { + const char *comment = va_arg (arguments, char *); + object_set_comment_in_t input; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.comment = comment; + input.loc_id = iod_id; + input.loc_mdkv_id = mdkv_id; + input.loc_oh = iod_oh; + input.path = loc_name; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + + status = (herr_t *)malloc(sizeof(herr_t)); + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_SET_COMMENT_ID, HG_OBJECT_SET_COMMENT, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship object set_comment"); + + /* store the comment locally if the object is open */ + if(loc_params.type == H5VL_OBJECT_BY_SELF) + obj->comment = HDstrdup(comment); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Oincr_refcount / H5Odecr_refcount */ + case H5VL_OBJECT_CHANGE_REF_COUNT: + { + //int update_ref = va_arg (arguments, int); + } + case H5VL_REF_CREATE: + { + /* + void *ref = va_arg (arguments, void *); + const char *name = va_arg (arguments, char *); + H5R_type_t ref_type = va_arg (arguments, H5R_type_t); + hid_t space_id = va_arg (arguments, hid_t); + size_t ref_size = 0; + + if(ref_type == H5R_DATASET_REGION) + ref_size = sizeof(hdset_reg_ref_t); + else if (ref_type == H5R_OBJECT) + ref_size = sizeof(hobj_ref_t); + */ + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't recognize this operation type") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_object_misc() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_object_get + * + * Purpose: Gets certain data about a file + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Mohamad Chaarawi + * November, 2012 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_object_get(void *_obj, H5VL_loc_params_t loc_params, H5VL_object_get_t get_type, + hid_t dxpl_id, void **req, va_list arguments) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + size_t num_parents = 0; + hid_t rcxt_id; + H5RC_t *rc = NULL; + H5P_genplist_t *plist = NULL; + iod_obj_id_t iod_id, mdkv_id, attrkv_id; + iod_handles_t iod_oh; + H5VL_iod_request_t **parent_reqs = NULL; + char *loc_name = NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, &mdkv_id, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, &mdkv_id, &attrkv_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to resolve current location group info"); + } + + switch (get_type) { + /* H5Oexists_by_name */ + case H5VL_OBJECT_EXISTS: + { + htri_t *ret = va_arg (arguments, htri_t *); + object_op_in_t input; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_mdkv_id = mdkv_id; + input.loc_oh = iod_oh; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.loc_name = loc_name; + +#if H5VL_IOD_DEBUG + printf("Object Exists axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, input.loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_EXISTS_ID, HG_OBJECT_EXISTS, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, ret, ret, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship object exists"); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Oget_comment / H5Oget_comment_by_name */ + case H5VL_OBJECT_GET_COMMENT: + { + char *comment = va_arg (arguments, char *); + size_t size = va_arg (arguments, size_t); + ssize_t *ret = va_arg (arguments, ssize_t *); + object_get_comment_in_t input; + object_get_comment_out_t *result = NULL; + size_t len; + + /* If the comment is present locally, get it and return */ + if(loc_params.type == H5VL_OBJECT_BY_SELF && obj->comment) { + len = HDstrlen(obj->comment); + + if(comment) { + HDstrncpy(comment, obj->comment, MIN(len + 1,size)); + if(len >= size) + comment[size-1]='\0'; + } /* end if */ + + /* Set the return value for the API call */ + *ret = (ssize_t)len; + break; + } + + /* Otherwise Go to the server */ + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = HDstrdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = HDstrdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.loc_mdkv_id = mdkv_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.path = loc_name; + if(comment) + input.length = size; + else + input.length = 0; + + if(NULL == (result = (object_get_comment_out_t *)malloc + (sizeof(object_get_comment_out_t)))) { + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate get comment return struct"); + } + + result->name.size = input.length; + result->name.value_size = ret; + result->name.value = comment; + +#if H5VL_IOD_DEBUG + printf("Object Get Comment axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_GET_COMMENT_ID, HG_OBJECT_GET_COMMENT, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, result, result, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship object get_comment"); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Oget_info / H5Oget_info_by_name / H5Oget_info_by_idx */ + case H5VL_OBJECT_GET_INFO: + { + H5O_ff_info_t *oinfo = va_arg (arguments, H5O_ff_info_t *); + object_op_in_t input; + + if(H5VL_OBJECT_BY_SELF == loc_params.type) + loc_name = strdup("."); + else if(H5VL_OBJECT_BY_NAME == loc_params.type) + loc_name = strdup(loc_params.loc_data.loc_by_name.name); + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.loc_mdkv_id = mdkv_id; + input.loc_attrkv_id = attrkv_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.loc_name = loc_name; + +#if H5VL_IOD_DEBUG + printf("Object get_info axe %"PRIu64": %s ID %"PRIu64"\n", + g_axe_id, input.loc_name, input.loc_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_OBJECT_GET_INFO_ID, HG_OBJECT_GET_INFO, + obj, 0, num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, oinfo, oinfo, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship object get_info"); + + if(loc_name) + HDfree(loc_name); + break; + } + /* H5Rget_region */ + case H5VL_REF_GET_REGION: + { + //hid_t *ret = va_arg (arguments, hid_t *); + //H5R_type_t ref_type = va_arg (arguments, H5R_type_t); + //void *ref = va_arg (arguments, void *); + //H5S_t *space = NULL; /* Dataspace object */ + } + /* H5Rget_obj_type2 */ + case H5VL_REF_GET_TYPE: + { + //H5O_type_t *obj_type = va_arg (arguments, H5O_type_t *); + //H5R_type_t ref_type = va_arg (arguments, H5R_type_t); + //const void *ref = va_arg (arguments, const void *); + } + /* H5Rget_name */ + case H5VL_REF_GET_NAME: + { + //ssize_t *ret = va_arg (arguments, ssize_t *); + //char *name = va_arg (arguments, char *); + //size_t size = va_arg (arguments, size_t); + //H5R_type_t ref_type = va_arg (arguments, H5R_type_t); + //void *ref = va_arg (arguments, void *); + } + default: + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from object") + } +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_object_get() */ + +void * +H5VL_iod_map_create(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t keytype, hid_t valtype, hid_t lcpl_id, hid_t mcpl_id, + hid_t mapl_id, hid_t trans_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the group */ + H5VL_iod_map_t *map = NULL; /* the map object that is created and passed to the user */ + map_create_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5VL_iod_request_t **parent_reqs = NULL; + size_t num_parents = 0; + H5TR_t *tr = NULL; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a Transaction ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the map object that is returned to the user */ + if(NULL == (map = H5FL_CALLOC(H5VL_iod_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + map->remote_map.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_id = IOD_OBJ_INVALID; + map->remote_map.mcpl_id = -1; + + /* Generate IOD IDs for the map to be created */ + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.map_id); + map->remote_map.iod_id = input.map_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.mdkv_id); + map->remote_map.mdkv_id = input.mdkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + H5VL_iod_gen_obj_id(obj->file->my_rank, obj->file->num_procs, + obj->file->remote_file.kv_oid_index, + IOD_OBJ_KV, &input.attrkv_id); + map->remote_map.attrkv_id = input.attrkv_id; + /* increment the index of KV objects created on the container */ + obj->file->remote_file.kv_oid_index ++; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.keytype_id = keytype; + input.valtype_id = valtype; + input.mcpl_id = mcpl_id; + input.mapl_id = mapl_id; + input.lcpl_id = lcpl_id; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Map Create %s, IOD ID %"PRIu64", axe id %"PRIu64"\n", + name, input.map_id, g_axe_id); +#endif + + /* setup the local map struct */ + /* store the entire path of the map locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (map->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(map->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(map->common.obj_name+obj_name_len, name, name_len); + map->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* copy property lists */ + if((map->remote_map.mcpl_id = H5Pcopy(mcpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy mcpl"); + if((map->mapl_id = H5Pcopy(mapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy mapl"); + if((map->remote_map.keytype_id = H5Tcopy(keytype)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dtype"); + if((map->remote_map.valtype_id = H5Tcopy(valtype)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy dtype"); + + /* set common object parameters */ + map->common.obj_type = H5I_MAP; + map->common.file = obj->file; + map->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_MAP_CREATE_ID, HG_MAP_CREATE, + (H5VL_iod_object_t *)map, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, &map->remote_map, map, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship map create"); + + ret_value = (void *)map; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free map components */ + if(map->common.obj_name) { + HDfree(map->common.obj_name); + map->common.obj_name = NULL; + } + if(map->common.comment) { + HDfree(map->common.comment); + map->common.comment = NULL; + } + if(map->remote_map.keytype_id != FAIL && H5I_dec_ref(map->remote_map.keytype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map->remote_map.valtype_id != FAIL && H5I_dec_ref(map->remote_map.valtype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map) + map = H5FL_FREE(H5VL_iod_map_t, map); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_create() */ + +void * +H5VL_iod_map_open(void *_obj, H5VL_loc_params_t UNUSED loc_params, const char *name, + hid_t mapl_id, hid_t rcxt_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; /* location object to create the group */ + H5VL_iod_map_t *map = NULL; /* the map object that is created and passed to the user */ + map_open_in_t input; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + H5VL_iod_request_t **parent_reqs = NULL; + H5RC_t *rc = NULL; + size_t num_parents = 0; + void *ret_value = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a READ CONTEXT ID") + + /* allocate parent request array */ + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(obj, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to retrieve parent requests"); + + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + + /* MSC - If location object not opened yet, wait for it. */ + if(IOD_OBJ_INVALID == iod_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't wait on HG request"); + obj->request = NULL; + /* retrieve IOD info of location object */ + if(H5VL_iod_get_loc_info(obj, &iod_id, &iod_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "Failed to resolve current location group info"); + } + + /* allocate the map object that is returned to the user */ + if(NULL == (map = H5FL_CALLOC(H5VL_iod_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate object struct"); + + map->remote_map.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + map->remote_map.iod_id = IOD_OBJ_INVALID; + map->remote_map.mdkv_id = IOD_OBJ_INVALID; + map->remote_map.attrkv_id = IOD_OBJ_INVALID; + map->remote_map.keytype_id = -1; + map->remote_map.valtype_id = -1; + + /* set the input structure for the HG encode routine */ + input.coh = obj->file->remote_file.coh; + input.loc_id = iod_id; + input.loc_oh = iod_oh; + input.name = name; + input.mapl_id = mapl_id; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("Map Open %s LOC ID %"PRIu64", axe id %"PRIu64"\n", + name, input.loc_id, g_axe_id); +#endif + + /* setup the local map struct */ + /* store the entire path of the map locally */ + if(obj->obj_name) { + size_t obj_name_len = HDstrlen(obj->obj_name); + size_t name_len = HDstrlen(name); + + if (NULL == (map->common.obj_name = (char *)HDmalloc(obj_name_len + name_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate"); + HDmemcpy(map->common.obj_name, obj->obj_name, obj_name_len); + HDmemcpy(map->common.obj_name+obj_name_len, name, name_len); + map->common.obj_name[obj_name_len+name_len] = '\0'; + } + + /* copy property lists */ + if((map->mapl_id = H5Pcopy(mapl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "failed to copy mapl"); + + /* set common object parameters */ + map->common.obj_type = H5I_MAP; + map->common.file = obj->file; + map->common.file->nopen_objs ++; + + if(H5VL__iod_create_and_forward(H5VL_MAP_OPEN_ID, HG_MAP_OPEN, (H5VL_iod_object_t *)map, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, &map->remote_map, map, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "failed to create and ship map open"); + + ret_value = (void *)map; + +done: + /* If the operation is synchronous and it failed at the server, or + it failed locally, then cleanup and return fail */ + if(NULL == ret_value) { + /* free map components */ + if(map->common.obj_name) { + HDfree(map->common.obj_name); + map->common.obj_name = NULL; + } + if(map->common.comment) { + HDfree(map->common.comment); + map->common.comment = NULL; + } + if(map->remote_map.keytype_id != FAIL && H5I_dec_ref(map->remote_map.keytype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map->remote_map.valtype_id != FAIL && H5I_dec_ref(map->remote_map.valtype_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "failed to close dtype"); + if(map) + map = H5FL_FREE(H5VL_iod_map_t, map); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_open() */ + +herr_t +H5VL_iod_map_set(void *_map, hid_t key_mem_type_id, const void *key, + hid_t val_mem_type_id, const void *value, hid_t dxpl_id, + hid_t trans_id, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_set_in_t input; + size_t key_size, val_size; + int *status = NULL; + H5P_genplist_t *plist = NULL; + size_t num_parents = 0; + H5TR_t *tr = NULL; + hg_bulk_t *value_handle = NULL; + uint64_t key_cs, value_cs, user_cs; + uint32_t raw_cs_scope; + H5VL_iod_request_t **parent_reqs = NULL; + H5T_class_t val_type_class; + H5VL_iod_map_set_info_t *info = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the dataset that is not present locally, wait */ + if(-1 == map->remote_map.keytype_id || + -1 == map->remote_map.valtype_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(map->common.file, map->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on HG request"); + map->common.request = NULL; + } + + /* get the key size and checksum from the provided key datatype & buffer */ + if(H5VL_iod_map_get_size(key_mem_type_id, key, &key_cs, &key_size, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get key size"); + + /* get the plist pointer */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* get the data integrity scope */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &raw_cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + if(raw_cs_scope) { + /* get the value size and checksum from the provided value datatype & buffer */ + if(H5VL_iod_map_get_size(val_mem_type_id, value, &value_cs, + &val_size, &val_type_class) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get value size"); + } + else { +#if H5VL_IOD_DEBUG + printf("NO DATA INTEGRITY CHECKS ON RAW DATA WRITTEN\n"); +#endif + /* get the value size and checksum from the provided value datatype & buffer */ + if(H5VL_iod_map_get_size(val_mem_type_id, value, NULL, + &val_size, &val_type_class) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get value size"); + } + + /* Verify the checksum value if the dxpl contains a user defined checksum */ + if(H5P_get(plist, H5D_XFER_CHECKSUM_NAME, &user_cs) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum value"); + + if((raw_cs_scope & H5_CHECKSUM_MEMORY) && user_cs && + user_cs != value_cs) { + fprintf(stderr, "Errrr.. In memory Data corruption. expecting %"PRIu64", got %"PRIu64"\n", + user_cs, value_cs); + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "Checksum verification failed"); + } + + /* allocate a bulk data transfer handle */ + if(NULL == (value_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a bulk data transfer handle"); + + /* Register memory */ + if(H5T_VLEN == val_type_class) { + /* if this is a VL type buffer, set the buffer pointer to the + actual data (the p pointer) */ + if(HG_SUCCESS != HG_Bulk_handle_create(((const hvl_t *)value)->p, val_size, + HG_BULK_READ_ONLY, value_handle)) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't create Bulk Data Handle"); + } + else { + if(HG_SUCCESS != HG_Bulk_handle_create(value, val_size, HG_BULK_READ_ONLY, value_handle)) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't create Bulk Data Handle"); + } + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)map, (H5VL_iod_req_info_t *)tr, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = map->common.file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.dxpl_id = dxpl_id; + input.key_maptype_id = map->remote_map.keytype_id; + input.key_memtype_id = key_mem_type_id; + input.key.buf_size = key_size; + input.key.buf = key; + input.val_maptype_id = map->remote_map.valtype_id; + input.val_memtype_id = val_mem_type_id; + input.val_handle = *value_handle; + input.val_checksum = value_cs; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = map->common.file->md_integrity_scope; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("MAP set, value size %zu, axe id %"PRIu64"\n", val_size, g_axe_id); +#endif + + /* setup info struct for I/O request + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_map_set_info_t *)H5MM_calloc(sizeof(H5VL_iod_map_set_info_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate a request"); + + info->status = status; + info->value_handle = value_handle; + + if(H5VL__iod_create_and_forward(H5VL_MAP_SET_ID, HG_MAP_SET, + (H5VL_iod_object_t *)map, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map set"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_set() */ + +herr_t +H5VL_iod_map_get(void *_map, hid_t key_mem_type_id, const void *key, + hid_t val_mem_type_id, void *value, + hid_t dxpl_id, hid_t rcxt_id, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_get_in_t input; + H5P_genplist_t *plist = NULL; + map_get_out_t *output = NULL; + H5VL_iod_map_io_info_t *info = NULL; + size_t key_size, val_size; + hg_bulk_t *value_handle = NULL; + hg_bulk_t dummy_handle; + uint64_t key_cs = 0; + H5RC_t *rc = NULL; + size_t num_parents = 0; + hbool_t val_is_vl; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the map that is not present locally, wait */ + if(-1 == map->remote_map.keytype_id || + -1 == map->remote_map.valtype_id) { + /* Synchronously wait on the request attached to the map */ + if(H5VL_iod_request_wait(map->common.file, map->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on HG request"); + map->common.request = NULL; + } + + /* get the key size and checksum from the provided key datatype & buffer */ + if(H5VL_iod_map_get_size(key_mem_type_id, key, &key_cs, &key_size, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get key size"); + + /* get information about the datatype of the value. Get the values + size if it is not VL. val_size will be 0 if it is VL */ + if(H5VL_iod_map_dtype_info(val_mem_type_id, &val_is_vl, &val_size) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get key size"); + + /* allocate a bulk data transfer handle */ + if(NULL == (value_handle = (hg_bulk_t *)H5MM_malloc(sizeof(hg_bulk_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate a buld data transfer handle"); + + /* If the val type is not VL, then we know the size and we can + create the bulk handle */ + if(!val_is_vl) { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(value, val_size, + HG_BULK_READWRITE, value_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + } + else { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(value, (size_t)1, + HG_BULK_READWRITE, &dummy_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + } + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)map, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = map->common.file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.dxpl_id = dxpl_id; + input.key_memtype_id = key_mem_type_id; + input.key_maptype_id = map->remote_map.keytype_id; + input.val_memtype_id = val_mem_type_id; + input.val_maptype_id = map->remote_map.valtype_id; + input.key.buf_size = key_size; + input.key.buf = key; + input.val_is_vl = val_is_vl; + input.val_size = val_size; + input.rcxt_num = rc->c_version; + if(!val_is_vl) + input.val_handle = *value_handle; + else { + input.val_handle = dummy_handle; + } + input.cs_scope = map->common.file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("MAP Get, axe id %"PRIu64"\n", g_axe_id); +#endif + + /* get the plist pointer */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + if(NULL == (output = (map_get_out_t *)H5MM_calloc(sizeof(map_get_out_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate map get output struct"); + + /* setup info struct for I/O request. + This is to manage the I/O operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_map_io_info_t *)H5MM_calloc(sizeof(H5VL_iod_map_io_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); + + /* capture the parameters required to submit a get request again + if the value type is VL, since the first Get is to retrieve the + value size */ + info->val_ptr = value; + info->read_buf = NULL; + info->value_handle = value_handle; + + info->val_is_vl = val_is_vl; + + /* store the pointer to the buffer where the checksum needs to be placed */ + if(H5P_get(plist, H5D_XFER_CHECKSUM_PTR_NAME, &info->val_cs_ptr) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum pointer value"); + /* store the raw data integrity scope */ + if(H5P_get(plist, H5VL_CS_BITFLAG_NAME, &info->raw_cs_scope) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get checksum pointer value"); + + /* The value size expected to be received. If VL data, this will + be 0, because the first call would be to get the value size */ + info->val_size = val_size; + info->rcxt_id = rcxt_id; + info->key.buf_size = key_size; + info->key.buf = key; + info->output = output; + if(val_is_vl) { + if((info->val_mem_type_id = H5Tcopy(val_mem_type_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype"); + if((info->key_mem_type_id = H5Tcopy(key_mem_type_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype"); + if((info->dxpl_id = H5P_copy_plist((H5P_genplist_t *)plist, TRUE)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy dxpl"); + + info->peer = PEER; + info->map_get_id = H5VL_MAP_GET_ID; + } + + if(H5VL__iod_create_and_forward(H5VL_MAP_GET_ID, HG_MAP_GET, + (H5VL_iod_object_t *)map, 0, + num_parents, parent_reqs, (H5VL_iod_req_info_t *)rc, + &input, output, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map get"); + + if(val_is_vl && (HG_SUCCESS != HG_Bulk_handle_free(dummy_handle))) { + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "failed to free dummy handle created"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_get() */ + +herr_t +H5VL_iod_map_get_types(void *_map, hid_t *key_type_id, hid_t *val_type_id, + hid_t UNUSED rcxt_id, void UNUSED **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If there is information needed about the dataset that is not present locally, wait */ + if(-1 == map->remote_map.keytype_id || + -1 == map->remote_map.valtype_id) { + /* Synchronously wait on the request attached to the dataset */ + if(H5VL_iod_request_wait(map->common.file, map->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on HG request"); + map->common.request = NULL; + } + + if((*key_type_id = H5Tcopy(map->remote_map.keytype_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of map key") + + if((*val_type_id = H5Tcopy(map->remote_map.valtype_id)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get datatype ID of map val") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_get_types() */ + +herr_t +H5VL_iod_map_get_count(void *_map, hsize_t *count, hid_t rcxt_id, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_get_count_in_t input; + H5RC_t *rc = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)map, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = map->common.file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.rcxt_num = rc->c_version; + input.cs_scope = map->common.file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("MAP Get count, axe id %"PRIu64"\n", g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_MAP_GET_COUNT_ID, HG_MAP_GET_COUNT, + (H5VL_iod_object_t *)map, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, count, count, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map get_count"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_get_count() */ + +herr_t +H5VL_iod_map_exists(void *_map, hid_t key_mem_type_id, const void *key, + hbool_t *exists, hid_t rcxt_id, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_op_in_t input; + size_t key_size; + H5RC_t *rc = NULL; + size_t num_parents = 0; + uint64_t key_cs = 0; + H5VL_iod_request_t **parent_reqs = NULL; + H5VL_iod_exists_info_t *info = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(H5VL_iod_map_get_size(key_mem_type_id, key, &key_cs, &key_size, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get key size"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID") + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)map, (H5VL_iod_req_info_t *)rc, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = map->common.file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.key_maptype_id = map->remote_map.keytype_id; + input.key_memtype_id = key_mem_type_id; + input.key.buf_size = key_size; + input.key.buf = key; + input.rcxt_num = rc->c_version; + input.cs_scope = map->common.file->md_integrity_scope; + input.trans_num = 0; + +#if H5VL_IOD_DEBUG + printf("MAP EXISTS, axe id %"PRIu64"\n", g_axe_id); +#endif + + /* setup info struct for exists request. + This is to manage the exists operation once the wait is called. */ + if(NULL == (info = (H5VL_iod_exists_info_t *)H5MM_calloc(sizeof(H5VL_iod_exists_info_t)))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request"); + + info->user_bool = exists; + + if(H5VL__iod_create_and_forward(H5VL_MAP_EXISTS_ID, HG_MAP_EXISTS, + (H5VL_iod_object_t *)map, 0, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)rc, &input, + &info->server_ret, info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map exists"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_exists() */ + +herr_t +H5VL_iod_map_iterate(void UNUSED *map, hid_t UNUSED key_mem_type_id, hid_t UNUSED value_mem_type_id, + H5M_iterate_func_t UNUSED callback_func, void UNUSED *context) +{ + //herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_map_iterate() */ + +herr_t +H5VL_iod_map_delete(void *_map, hid_t key_mem_type_id, const void *key, + hid_t trans_id, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_op_in_t input; + size_t key_size; + int *status = NULL; + size_t num_parents = 0; + H5TR_t *tr = NULL; + uint64_t key_cs = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(H5VL_iod_map_get_size(key_mem_type_id, key, &key_cs, &key_size, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get key size"); + + /* get the TR object */ + if(NULL == (tr = (H5TR_t *)H5I_object_verify(trans_id, H5I_TR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Transaction ID") + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *) * 2))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests((H5VL_iod_object_t *)map, (H5VL_iod_req_info_t *)tr, + parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* Fill input structure */ + input.coh = map->common.file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.key_maptype_id = map->remote_map.keytype_id; + input.key_memtype_id = key_mem_type_id; + input.key.buf_size = key_size; + input.key.buf = key; + input.trans_num = tr->trans_num; + input.rcxt_num = tr->c_version; + input.cs_scope = map->common.file->md_integrity_scope; + +#if H5VL_IOD_DEBUG + printf("MAP DELETE, axe id %"PRIu64"\n", g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_MAP_DELETE_ID, HG_MAP_DELETE, + (H5VL_iod_object_t *)map, 1, + num_parents, parent_reqs, + (H5VL_iod_req_info_t *)tr, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map delete"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_delete() */ + +herr_t H5VL_iod_map_close(void *_map, void **req) +{ + H5VL_iod_map_t *map = (H5VL_iod_map_t *)_map; + map_close_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(map->common.file, map) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(IOD_OH_UNDEFINED == map->remote_map.iod_oh.rd_oh.cookie) { + /* Synchronously wait on the request attached to the map */ + if(H5VL_iod_request_wait(map->common.file, map->common.request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on map request"); + map->common.request = NULL; + } + + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)map, &num_parents, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get num requests"); + + if(num_parents) { + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * num_parents))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + if(H5VL_iod_get_obj_requests((H5VL_iod_object_t *)map, &num_parents, + parent_reqs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get parents requests"); + } + + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + +#if H5VL_IOD_DEBUG + printf("Map Close IOD ID %"PRIu64", axe id %"PRIu64"\n", input.iod_id, g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_MAP_CLOSE_ID, HG_MAP_CLOSE, + (H5VL_iod_object_t *)map, 1, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map close"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_rc_acquire + * + * Purpose: Forwards an acquire for a read context to IOD. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_rc_acquire(H5VL_iod_file_t *file, H5RC_t *rc, uint64_t *c_version, + hid_t rcapl_id, void **req) +{ + rc_acquire_in_t input; + H5VL_iod_rc_info_t *rc_info = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* set the input structure for the HG encode routine */ + input.coh = file->remote_file.coh; + input.c_version = *c_version; + input.rcapl_id = rcapl_id; + + /* setup the info structure for updating the RC on completion */ + if(NULL == (rc_info = (H5VL_iod_rc_info_t *)H5MM_calloc(sizeof(H5VL_iod_rc_info_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate RC info struct"); + + rc_info->read_cxt = rc; + rc_info->c_version_ptr = c_version; + +#if H5VL_IOD_DEBUG + printf("Read Context Acquire, version %"PRIu64", axe id %"PRIu64"\n", + input.c_version, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_RC_ACQUIRE_ID, HG_RC_ACQUIRE, + (H5VL_iod_object_t *)file, 0, 0, NULL, + NULL, &input, &rc_info->result, rc_info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + + if(NULL != req) { + H5VL_iod_request_t *request = (H5VL_iod_request_t *)(*req); + + rc->req_info.request = request; + //request->ref_count ++; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_rc_acquire() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_rc_release + * + * Purpose: Forwards a release on an acquired read context to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_rc_release(H5RC_t *rc, void **req) +{ + rc_release_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * (rc->req_info.num_req + 1)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + + /* retrieve start request */ + if(H5VL_iod_get_parent_requests(NULL, (H5VL_iod_req_info_t *)rc, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + if(rc->req_info.num_req) { + H5VL_iod_request_t *cur_req = rc->req_info.head; + H5VL_iod_request_t *next_req = NULL; + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + while(cur_req) { + /* add a dependency if the current request in the list is pending */ + if(cur_req->state == H5VL_IOD_PENDING) { + /* If this call is not asynchronous, wait on a dependent request */ + if(NULL == req) { + if(H5VL_iod_request_wait(rc->file, cur_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on request"); + } + /* Otherwise, add a dependency */ + else { + parent_reqs[num_parents] = cur_req; + cur_req->ref_count ++; + num_parents ++; + } + } + + next_req = cur_req->trans_next; + + /* remove the current request from the linked list */ + prev = cur_req->trans_prev; + next = cur_req->trans_next; + if (prev) { + if (next) { + prev->trans_next = next; + next->trans_prev = prev; + } + else { + prev->trans_next = NULL; + rc->req_info.tail = prev; + } + } + else { + if (next) { + next->trans_prev = NULL; + rc->req_info.head = next; + } + else { + rc->req_info.head = NULL; + rc->req_info.tail = NULL; + } + } + + cur_req->trans_prev = NULL; + cur_req->trans_next = NULL; + + rc->req_info.num_req --; + + H5VL_iod_request_decr_rc(cur_req); + + cur_req = next_req; + } + HDassert(0 == rc->req_info.num_req); + } + + /* set the input structure for the HG encode routine */ + input.coh = rc->file->remote_file.coh; + input.c_version = rc->c_version; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Read Context Release, version %"PRIu64", axe id %"PRIu64"\n", + input.c_version, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_RC_RELEASE_ID, HG_RC_RELEASE, + (H5VL_iod_object_t *)rc->file, 0, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + + //if(NULL != rc->req_info.request) { + //H5VL_iod_request_decr_rc(rc->req_info.request); + //} + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_rc_release() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_rc_persist + * + * Purpose: Forwards an persist on an acquired read context to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_rc_persist(H5RC_t *rc, void **req) +{ + rc_persist_in_t input; + int *status = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(!(rc->file->flags & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Can't persist a container opened for Read only") + + /* set the input structure for the HG encode routine */ + input.coh = rc->file->remote_file.coh; + input.c_version = rc->c_version; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Read Context Persist, version %"PRIu64", axe id %"PRIu64"\n", + input.c_version, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_RC_PERSIST_ID, HG_RC_PERSIST, + (H5VL_iod_object_t *)rc->file, 0, 0, NULL, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_rc_persist() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_rc_snapshot + * + * Purpose: Forwards an snapshot on an acquired read context to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_rc_snapshot(H5RC_t *rc, const char *snapshot_name, void **req) +{ + rc_snapshot_in_t input; + int *status = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* set the input structure for the HG encode routine */ + input.coh = rc->file->remote_file.coh; + input.c_version = rc->c_version; + input.snapshot_name = snapshot_name; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Read Context Snapshot, version %"PRIu64", axe id %"PRIu64"\n", + input.c_version, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_RC_SNAPSHOT_ID, HG_RC_SNAPSHOT, + (H5VL_iod_object_t *)rc->file, 0, 0, NULL, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_rc_snapshot() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_tr_start + * + * Purpose: Forwards a transaction start call to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_tr_start(H5TR_t *tr, hid_t trspl_id, void **req) +{ + tr_start_in_t input; + H5VL_iod_tr_info_t *tr_info = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.trans_num = tr->trans_num; + input.trspl_id = trspl_id; + +#if H5VL_IOD_DEBUG + printf("Transaction start, number %"PRIu64", axe id %"PRIu64"\n", + input.trans_num, g_axe_id); +#endif + + /* setup the info structure for updating the transaction on completion */ + if(NULL == (tr_info = (H5VL_iod_tr_info_t *)H5MM_calloc(sizeof(H5VL_iod_tr_info_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate TR info struct"); + + tr_info->tr = tr; + + if(H5VL__iod_create_and_forward(H5VL_TR_START_ID, HG_TR_START, + (H5VL_iod_object_t *)tr->file, 0, 0, NULL, + NULL, &input, &tr_info->result, tr_info, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + + if(NULL != req) { + H5VL_iod_request_t *request = (H5VL_iod_request_t *)(*req); + + tr->req_info.request = request; + //request->ref_count ++; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_tr_start() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_tr_finish + * + * Purpose: Forwards a transaction finish call to IOD. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_tr_finish(H5TR_t *tr, hbool_t acquire, hid_t trfpl_id, void **req) +{ + tr_finish_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (parent_reqs = (H5VL_iod_request_t **)H5MM_malloc + (sizeof(H5VL_iod_request_t *) * (tr->req_info.num_req + 1)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array of parent reqs"); + + /* retrieve start request */ + if(H5VL_iod_get_parent_requests(NULL, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + if(tr->req_info.num_req) { + H5VL_iod_request_t *cur_req = tr->req_info.head; + H5VL_iod_request_t *next_req = NULL; + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + while(cur_req) { + /* add a dependency if the current request in the list is pending */ + if(cur_req->state == H5VL_IOD_PENDING) { + /* If this call is not asynchronous, wait on a dependent request */ + if(NULL == req) { + if(H5VL_iod_request_wait(tr->file, cur_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on request"); + } + /* Otherwise, add a dependency */ + else { + parent_reqs[num_parents] = cur_req; + cur_req->ref_count ++; + num_parents ++; + } + } + + next_req = cur_req->trans_next; + + /* remove the current request from the linked list */ + prev = cur_req->trans_prev; + next = cur_req->trans_next; + if (prev) { + if (next) { + prev->trans_next = next; + next->trans_prev = prev; + } + else { + prev->trans_next = NULL; + tr->req_info.tail = prev; + } + } + else { + if (next) { + next->trans_prev = NULL; + tr->req_info.head = next; + } + else { + tr->req_info.head = NULL; + tr->req_info.tail = NULL; + } + } + + cur_req->trans_prev = NULL; + cur_req->trans_next = NULL; + + tr->req_info.num_req --; + + H5VL_iod_request_decr_rc(cur_req); + + cur_req = next_req; + } + HDassert(0 == tr->req_info.num_req); + } + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.cs_scope = tr->file->md_integrity_scope; + input.trans_num = tr->trans_num; + input.trfpl_id = trfpl_id; + input.acquire = acquire; + input.client_rank = (uint32_t)tr->file->my_rank; + input.oidkv_id = (iod_obj_id_t)(tr->file->num_procs * 3); + input.kv_oid_index = tr->file->remote_file.kv_oid_index; + input.array_oid_index = tr->file->remote_file.array_oid_index; + input.blob_oid_index = tr->file->remote_file.blob_oid_index; + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Transaction Finish, %"PRIu64", axe id %"PRIu64"\n", + input.trans_num, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_TR_FINISH_ID, HG_TR_FINISH, + (H5VL_iod_object_t *)tr->file, 0, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + + //if(NULL != tr->req_info.request) { + //H5VL_iod_request_decr_rc(tr->req_info.request); + //} + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_tr_finish() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_tr_set_dependency + * + * Purpose: Forwards a transaction set dependency to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_tr_set_dependency(H5TR_t *tr, uint64_t trans_num, void **req) +{ + tr_set_depend_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(NULL, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.child_trans_num = tr->trans_num; + input.parent_trans_num = trans_num; + +#if H5VL_IOD_DEBUG + printf("Transaction Set Dependency, %"PRIu64" on %"PRIu64" axe id %"PRIu64"\n", + input.child_trans_num, input.parent_trans_num, g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_TR_SET_DEPEND_ID, HG_TR_SET_DEPEND, + (H5VL_iod_object_t *)tr->file, 0, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_tr_set_dependency() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_tr_skip + * + * Purpose: Forwards a transaction skip to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_tr_skip(H5VL_iod_file_t *file, uint64_t start_trans_num, uint64_t count, void **req) +{ + tr_skip_in_t input; + int *status = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* set the input structure for the HG encode routine */ + input.coh = file->remote_file.coh; + input.start_trans_num = start_trans_num; + input.count = count; + +#if H5VL_IOD_DEBUG + printf("Transaction Skip, tr %"PRIu64" count %"PRIu64",, axe id %"PRIu64"\n", + input.start_trans_num, input.count, g_axe_id); +#endif + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_TR_SKIP_ID, HG_TR_SKIP, + (H5VL_iod_object_t *)file, 0, 0, NULL, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_tr_skip() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_tr_abort + * + * Purpose: Forwards a transaction abort to IOD + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * September 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_tr_abort(H5TR_t *tr, void **req) +{ + tr_abort_in_t input; + int *status = NULL; + size_t num_parents = 0; + H5VL_iod_request_t **parent_reqs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (parent_reqs = (H5VL_iod_request_t **) + H5MM_malloc(sizeof(H5VL_iod_request_t *)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate parent req element"); + + /* retrieve parent requests */ + if(H5VL_iod_get_parent_requests(NULL, (H5VL_iod_req_info_t *)tr, parent_reqs, &num_parents) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to retrieve parent requests"); + + /* set the input structure for the HG encode routine */ + input.coh = tr->file->remote_file.coh; + input.trans_num = tr->trans_num; + + /* remove all nodes from the transaction linked list */ + if(tr->req_info.num_req) { + H5VL_iod_request_t *cur_req = tr->req_info.head; + H5VL_iod_request_t *next_req = NULL; + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + + while(cur_req) { + next_req = cur_req->trans_next; + + prev = cur_req->trans_prev; + next = cur_req->trans_next; + if (prev) { + if (next) { + prev->trans_next = next; + next->trans_prev = prev; + } + else { + prev->trans_next = NULL; + tr->req_info.tail = prev; + } + } + else { + if (next) { + next->trans_prev = NULL; + tr->req_info.head = next; + } + else { + tr->req_info.head = NULL; + tr->req_info.tail = NULL; + } + } + + cur_req->trans_prev = NULL; + cur_req->trans_next = NULL; + + tr->req_info.num_req --; + + H5VL_iod_request_decr_rc(cur_req); + + cur_req = next_req; + } + HDassert(0 == tr->req_info.num_req); + } + + status = (int *)malloc(sizeof(int)); + +#if H5VL_IOD_DEBUG + printf("Transaction Abort, tr %"PRIu64", axe id %"PRIu64"\n", + input.trans_num, g_axe_id); +#endif + + if(H5VL__iod_create_and_forward(H5VL_TR_ABORT_ID, HG_TR_ABORT, + (H5VL_iod_object_t *)tr->file, 0, + num_parents, parent_reqs, + NULL, &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_tr_abort() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_prefetch + * + * Purpose: prefetched an object from BB to Central storage and returns + * a replica ID for access to the prefetched object. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_prefetch(void *_obj, hid_t rcxt_id, hrpl_t *replica_id, hid_t apl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + prefetch_in_t input; + H5RC_t *rc = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(obj->file, obj) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(obj->request && H5VL_IOD_PENDING == obj->request->state) { + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait for request") + } + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + input.coh = obj->file->remote_file.coh; + input.rcxt_num = rc->c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.apl_id = apl_id; + input.obj_type = obj->obj_type; + + switch(obj->obj_type) { + case H5I_DATASET: + { + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)obj; + input.iod_id = dset->remote_dset.iod_id; + input.iod_oh = dset->remote_dset.iod_oh; + break; + } + case H5I_DATATYPE: + { + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)obj; + input.iod_id = dtype->remote_dtype.iod_id; + input.iod_oh = dtype->remote_dtype.iod_oh; + break; + } + case H5I_GROUP: + { + H5VL_iod_group_t *group = (H5VL_iod_group_t *)obj; + input.iod_id = group->remote_group.iod_id; + input.iod_oh = group->remote_group.iod_oh; + break; + } + case H5I_MAP: + { + H5VL_iod_map_t *map = (H5VL_iod_map_t *)obj; + input.iod_id = map->remote_map.iod_id; + input.iod_oh = map->remote_map.iod_oh; + break; + } + case H5I_ATTR: + { + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + input.iod_id = attr->remote_attr.iod_id; + input.iod_oh = attr->remote_attr.iod_oh; + break; + } + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_VIEW: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "not a valid object to prefetch"); + } + + if(H5VL__iod_create_and_forward(H5VL_PREFETCH_ID, HG_PREFETCH, + obj, 1, 0, NULL, NULL, + &input, replica_id, replica_id, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_prefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_evict + * + * Purpose: evicts an object from BB. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_evict(void *_obj, uint64_t c_version, hid_t apl_id, void **req) +{ + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)_obj; + evict_in_t input; + H5P_genplist_t *plist = NULL; /* Property list pointer */ + int *status = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If this call is not asynchronous, complete and remove all + requests that are associated with this object from the List */ + if(NULL == req) { + if(H5VL_iod_request_wait_some(obj->file, obj) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't wait on all object requests"); + } + + if(obj->request && H5VL_IOD_PENDING == obj->request->state) { + if(H5VL_iod_request_wait(obj->file, obj->request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait for request") + } + + if(NULL == (plist = H5P_object_verify(apl_id, H5P_LINK_ACCESS))) + HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not an access plist"); + if(H5P_get(plist, H5O_ACS_REPLICA_ID_NAME, &input.replica_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value"); + + input.coh = obj->file->remote_file.coh; + input.rcxt_num = c_version; + input.cs_scope = obj->file->md_integrity_scope; + input.apl_id = apl_id; + + switch(obj->obj_type) { + case H5I_DATASET: + { + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)obj; + input.iod_id = dset->remote_dset.iod_id; + input.iod_oh = dset->remote_dset.iod_oh; + break; + } + case H5I_DATATYPE: + { + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)obj; + input.iod_id = dtype->remote_dtype.iod_id; + input.iod_oh = dtype->remote_dtype.iod_oh; + break; + } + case H5I_GROUP: + { + H5VL_iod_group_t *group = (H5VL_iod_group_t *)obj; + input.iod_id = group->remote_group.iod_id; + input.iod_oh = group->remote_group.iod_oh; + break; + } + case H5I_MAP: + { + H5VL_iod_map_t *map = (H5VL_iod_map_t *)obj; + input.iod_id = map->remote_map.iod_id; + input.iod_oh = map->remote_map.iod_oh; + break; + } + case H5I_ATTR: + { + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)obj; + input.iod_id = attr->remote_attr.iod_id; + input.iod_oh = attr->remote_attr.iod_oh; + break; + } + case H5I_UNINIT: + case H5I_BADID: + case H5I_FILE: + case H5I_DATASPACE: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_VIEW: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "not a valid object to evict"); + } + + status = (int *)malloc(sizeof(int)); + + if(H5VL__iod_create_and_forward(H5VL_EVICT_ID, HG_EVICT, + obj, 1, 0, NULL, NULL, + &input, status, status, req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship VOL op"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_evict() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cancel + * + * Purpose: Cancel an asynchronous operation + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Mohamad Chaarawi + * April 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_cancel(void **req, H5ES_status_t *status) +{ + H5VL_iod_request_t *request = *((H5VL_iod_request_t **)req); + hg_status_t hg_status; + int ret; + H5VL_iod_state_t state; + hg_request_t hg_req; /* Local function shipper request, for sync. operations */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* request has completed already, can not cancel */ + if(request->state == H5VL_IOD_COMPLETED) { + /* Call the completion function to check return values and free resources */ + if(H5VL_iod_request_complete(request->obj->file, request) < 0) + fprintf(stderr, "Operation Failed!\n"); + + *status = request->status; + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + + /* forward the cancel call to the IONs */ + if(HG_Forward(PEER, H5VL_CANCEL_OP_ID, &request->axe_id, &state, &hg_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship attribute write"); + + /* Wait on the cancel request to return */ + ret = HG_Wait(hg_req, HG_MAX_IDLE_TIME, &hg_status); + + /* If the actual wait Fails, then the status of the cancel + operation is unknown */ + if(HG_FAIL == ret) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to wait on cancel request") + else { + if(hg_status) { + /* If the operation to be canceled has already completed, + mark it so and complete it locally */ + if(state == H5VL_IOD_COMPLETED) { + if(H5VL_IOD_PENDING == request->state) { + if(H5VL_iod_request_wait(request->obj->file, request) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait for request"); + } + + *status = request->status; + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + + /* if the status returned is cancelled, then cancel it + locally too */ + else if (state == H5VL_IOD_CANCELLED) { + request->status = H5ES_STATUS_CANCEL; + request->state = H5VL_IOD_CANCELLED; + if(H5VL_iod_request_cancel(request->obj->file, request) < 0) + fprintf(stderr, "Operation Failed!\n"); + + *status = request->status; + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + } + else + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "Cancel Operation taking too long. Aborting"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_cancel() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_test + * + * Purpose: Test for an asynchronous operation's completion + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_test(void **req, H5ES_status_t *status) +{ + H5VL_iod_request_t *request = *((H5VL_iod_request_t **)req); + hg_status_t hg_status; + int ret; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Test completion of the request if is still pending */ + if(H5VL_IOD_PENDING == request->state) { + ret = HG_Wait(*((hg_request_t *)request->req), 0, &hg_status); + if(HG_FAIL == ret) { + fprintf(stderr, "failed to wait on request\n"); + request->status = H5ES_STATUS_FAIL; + request->state = H5VL_IOD_COMPLETED; + + /* remove the request from the file linked list */ + H5VL_iod_request_delete(request->obj->file, request); + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + else { + if(hg_status) { + request->status = H5ES_STATUS_SUCCEED; + request->state = H5VL_IOD_COMPLETED; + + /* Call the completion function to check return values and free resources */ + if(H5VL_iod_request_complete(request->obj->file, request) < 0) + fprintf(stderr, "Operation Failed!\n"); + + *status = request->status; + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + /* request has not finished, set return status appropriately */ + else + *status = request->status; + } + } + else { + *status = request->status; + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_test() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_wait + * + * Purpose: Wait for an asynchronous operation to complete + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, March 20, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL_iod_wait(void **req, H5ES_status_t *status) +{ + H5VL_iod_request_t *request = *((H5VL_iod_request_t **)req); + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* Wait on completion of the request if it was not completed */ + if(H5VL_IOD_PENDING == request->state) { + if(H5VL_iod_request_wait(request->obj->file, request) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to wait for request") + } + + *status = request->status; + + /* free the mercury request */ + request->req = H5MM_xfree(request->req); + + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_wait() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod.h b/src/H5VLiod.h new file mode 100644 index 0000000..c29d234 --- /dev/null +++ b/src/H5VLiod.h @@ -0,0 +1,83 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * January, 2012 + * + * Purpose: The public header file for the IOD VOL plugin. + */ +#ifndef H5VLiod_H +#define H5VLiod_H + +#ifdef H5_HAVE_EFF + +#include "axe.h" +#include "iod_api.h" +#include "iod_types.h" +#include "mercury.h" +#include "mercury_handler.h" +#include "mercury_macros.h" +#include "mercury_proc_string.h" +#include "na_mpi.h" + +#define H5VL_IOD (H5VL_iod_init()) +#else +#define H5VL_IOD (-1) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef H5_HAVE_EFF + +#define H5D_XFER_INJECT_CORRUPTION_NAME "inject_corruption" +#define H5D_XFER_CHECKSUM_NAME "checksum" +#define H5D_XFER_CHECKSUM_PTR_NAME "checksum_ptr" +#define H5D_CRT_APPEND_ONLY_NAME "append_only" +#define H5O_CRT_ENABLE_CHECKSUM_NAME "enable_obj_checksum" +#define H5O_ACS_REPLICA_ID_NAME "replica_id" + +H5_DLL H5VL_class_t *H5VL_iod_init(void); +H5_DLL herr_t H5Pset_fapl_iod(hid_t fapl_id, MPI_Comm comm, MPI_Info info); +H5_DLL herr_t EFF_start_server(MPI_Comm comm, MPI_Info info); +H5_DLL herr_t EFF_init(MPI_Comm comm, MPI_Info info); +H5_DLL herr_t EFF_finalize(void); + +H5_DLL herr_t H5Pset_lapl_replica_id(hid_t lapl_id, hrpl_t replica_id); +H5_DLL herr_t H5Pget_lapl_replica_id(hid_t lapl_id, hrpl_t *replica_id); +H5_DLL herr_t H5Pset_ocpl_enable_checksum(hid_t ocpl_id, hbool_t flag); +H5_DLL herr_t H5Pget_ocpl_enable_checksum(hid_t ocpl_id, hbool_t *flag); +H5_DLL herr_t H5Pset_dxpl_checksum(hid_t dxpl_id, uint64_t value); +H5_DLL herr_t H5Pget_dxpl_checksum(hid_t dxpl_id, uint64_t *value); +H5_DLL herr_t H5Pset_dxpl_checksum_ptr(hid_t dxpl_id, uint64_t *value); +H5_DLL herr_t H5Pget_dxpl_checksum_ptr(hid_t dxpl_id, uint64_t **value); +H5_DLL herr_t H5Pset_metadata_integrity_scope(hid_t fapl_id, uint32_t scope); +H5_DLL herr_t H5Pget_metadata_integrity_scope(hid_t fapl_id, uint32_t *scope); +H5_DLL herr_t H5Pset_rawdata_integrity_scope(hid_t dxpl_id, uint32_t scope); +H5_DLL herr_t H5Pget_rawdata_integrity_scope(hid_t dxpl_id, uint32_t *scope); +H5_DLL herr_t H5Pset_dxpl_inject_corruption(hid_t dxpl_id, hbool_t flag); +H5_DLL herr_t H5Pget_dxpl_inject_corruption(hid_t dxpl_id, hbool_t *flag); +H5_DLL herr_t H5Pset_dcpl_append_only(hid_t dcpl_id, hbool_t flag); +H5_DLL herr_t H5Pget_dcpl_append_only(hid_t dcpl_id, hbool_t *flag); + +#endif /* H5_HAVE_EFF */ + +#ifdef __cplusplus +} +#endif + +#endif /* _H5VLiod_H */ diff --git a/src/H5VLiod_analysis.c b/src/H5VLiod_analysis.c new file mode 100644 index 0000000..a40f64d --- /dev/null +++ b/src/H5VLiod_analysis.c @@ -0,0 +1,1307 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Routines to support Analysis Shipping. + */ + +#include "H5VLiod_server.h" + +#include "H5Qpublic.h" + +#ifdef H5_HAVE_PYTHON +#include <Python.h> +#include <numpy/ndarrayobject.h> +#endif + +#ifdef H5_HAVE_EFF + +/* User data for dataspace iteration to query elements. */ +typedef struct { + size_t num_elmts; + hid_t query_id; + hid_t space_query; +} H5VL__iod_get_query_data_t; + +/* do not change order */ +typedef struct { + analysis_farm_out_t farm_out; + void *data; +} H5VLiod_farm_data_t; + +#ifdef H5_HAVE_PYTHON + +static hbool_t numpy_initialized = FALSE; +static void H5VL__iod_numpy_init(void); + +static PyObject *H5VL__iod_load_script(const char *script, const char *func_name); + +static herr_t H5VL__iod_translate_h5_type(hid_t data_type_id, + enum NPY_TYPES *npy_type); + +static herr_t H5VL__iod_translate_numpy_type(enum NPY_TYPES npy_type, + hid_t *data_type_id, size_t *data_type_size); + +static PyObject *H5VL__iod_create_numpy_array(size_t num_elmts, hid_t data_type_id, + void *data); + +static herr_t H5VL__iod_extract_numpy_array(PyObject *numpy_array, void **data, + size_t *num_elmts, hid_t *data_type_id); + +/* TODO define as static but leave it like this for testing */ +herr_t H5VL__iod_split(const char *split_script, void *data, + size_t num_elmts, hid_t data_type_id, void **split_data, + size_t *split_num_elmts, hid_t *split_data_type_id); + +herr_t H5VL__iod_combine(const char *combine_script, + void **split_data, size_t *split_num_elmts, + size_t num_targets, hid_t data_type_id, + void **combine_data, size_t *combine_num_elmts, + hid_t *combine_data_type_id); + +#endif + +static herr_t H5VL__iod_farm_split(iod_handle_t coh, iod_obj_id_t obj_id, iod_trans_id_t rtid, + hid_t space_id, coords_t coords, iod_size_t num_cells, + hid_t type_id, hid_t query_id, + const char *split_script, void **split_data, + size_t *split_num_elmts, hid_t *split_type_id); + +static hid_t H5VL__iod_get_space_layout(coords_t coords, iod_size_t num_cells, hid_t space_id); + +static herr_t H5VL__iod_get_query_data_cb(void *elem, hid_t type_id, unsigned ndim, + const hsize_t *point, void *_udata); + +static herr_t H5VL__iod_get_query_data(iod_handle_t coh, iod_obj_id_t dset_id, + iod_trans_id_t rtid, hid_t query_id, + hid_t space_id, hid_t type_id, + size_t *num_elmts, void **data); + +static herr_t H5VL__iod_read_selection(iod_handle_t coh, iod_obj_id_t obj_id, + iod_trans_id_t rtid, hid_t space_id, + hid_t type_id, void *buf); + +#ifdef H5_HAVE_PYTHON + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_numpy_init + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static void +H5VL__iod_numpy_init(void) +{ + /* Needed for numpy stuff */ + /* Note: This function must be called in the initialization section of a + * module that will make use of the C-API. It imports the module where the + * function-pointer table is stored and points the correct variable to it. + * If, however, the extension module involves multiple files where the C-API + * is needed then some additional steps must be taken. */ + import_array(); + numpy_initialized = TRUE; +} /* end H5VL__iod_numpy_init() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_load_script + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static PyObject * +H5VL__iod_load_script(const char *script, const char *func_name) +{ + PyObject *po_func = NULL, *ret_value = NULL; /* Return value */ + PyObject *po_main = NULL, *po_main_dict = NULL, *po_rstring = NULL; + /* for reference in case we need it + PyObject *main = PyImport_AddModule("__main__"); + PyObject *dlfl = PyImport_AddModule("dlfl"); + PyObject* main_dict = PyModule_GetDict( main ); + PyObject* dlfl_dict = PyModule_GetDict( dlfl ); + */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Get reference to main */ + if(NULL == (po_main = PyImport_AddModule("__main__"))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, NULL, "can't get reference to main module"); + + if(NULL == (po_main_dict = PyModule_GetDict(po_main))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, NULL, "can't get dictionary from main module"); + + /* Load script */ + if(NULL == (po_rstring = PyRun_String(script, Py_file_input, po_main_dict, po_main_dict))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, NULL, "can't load script into main module"); + + /* Get reference to function name */ + if(NULL == (po_func = PyObject_GetAttrString(po_main, func_name))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, NULL, "can't get reference to function"); + + ret_value = po_func; + +done: + Py_DECREF(po_rstring); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_load_script() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_translate_h5_type + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_translate_h5_type(hid_t data_type_id, enum NPY_TYPES *npy_type) +{ + herr_t ret_value = SUCCEED; /* Return value */ + enum NPY_TYPES translated_type; + hid_t native_datatype_id; + + FUNC_ENTER_NOAPI_NOINIT + + if((native_datatype_id = H5Tget_native_type(data_type_id, H5T_DIR_DEFAULT)) < 0) + HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot retrieve native type"); + + if(H5Tequal(native_datatype_id, H5T_NATIVE_LLONG_g)) + translated_type = NPY_LONGLONG; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_LONG_g)) + translated_type = NPY_LONG; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_INT_g)) + translated_type = NPY_INT; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_SHORT_g)) + translated_type = NPY_SHORT; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_SCHAR_g)) + translated_type = NPY_BYTE; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_DOUBLE_g)) + translated_type = NPY_DOUBLE; + else if(H5Tequal(native_datatype_id, H5T_NATIVE_FLOAT_g)) + translated_type = NPY_FLOAT; + else + HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid type") + + if(FAIL == H5Tclose(native_datatype_id)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); + + *npy_type = translated_type; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_translate_h5_type() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_translate_numpy_type + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_translate_numpy_type(enum NPY_TYPES npy_type, hid_t *data_type_id, + size_t *data_type_size) +{ + herr_t ret_value = SUCCEED; /* Return value */ + hid_t translated_type_id; + size_t translated_type_size; + + FUNC_ENTER_NOAPI_NOINIT + + switch (npy_type) { + case NPY_LONGLONG: + translated_type_id = H5T_NATIVE_LLONG_g; + break; + case NPY_LONG: + translated_type_id = H5T_NATIVE_LONG_g; + break; + case NPY_INT: + translated_type_id = H5T_NATIVE_INT_g; + break; + case NPY_SHORT: + translated_type_id = H5T_NATIVE_SHORT_g; + break; + case NPY_BYTE: + translated_type_id = H5T_NATIVE_SCHAR_g; + break; + case NPY_DOUBLE: + translated_type_id = H5T_NATIVE_DOUBLE_g; + break; + case NPY_FLOAT: + translated_type_id = H5T_NATIVE_FLOAT_g; + break; + default: + HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid type") + break; + } + + if (0 == (translated_type_size = H5Tget_size(translated_type_id))) + HGOTO_ERROR2(H5E_ARGS, H5E_BADTYPE, FAIL, "not a valid size") + + *data_type_id = translated_type_id; + *data_type_size = translated_type_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_translate_numpy_type() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_create_numpy_array + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static PyObject * +H5VL__iod_create_numpy_array(size_t num_elmts, hid_t data_type_id, void *data) +{ + PyObject *ret_value = NULL; /* Return value */ + npy_intp dim[1] = {(npy_intp) num_elmts}; + enum NPY_TYPES npy_type; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(data); + + /* Convert data_type to numpy type */ + if(FAIL == H5VL__iod_translate_h5_type(data_type_id, &npy_type)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTCONVERT, NULL, "unable to translate datatype to NPY type"); + + ret_value = PyArray_SimpleNewFromData(1, dim, npy_type, data); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_create_numpy_array() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_extract_numpy_array + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_extract_numpy_array(PyObject *numpy_array, void **data, + size_t *num_elmts, hid_t *data_type_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + void *numpy_data = NULL, *extracted_data = NULL; + hid_t extracted_datatype_id; + npy_intp *numpy_dims; + int numpy_datatype; + size_t numpy_num_elmts, extracted_datatype_size; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(numpy_array); + HDassert(data); + HDassert(num_elmts); + HDassert(data_type_id); + + /* Input array should be 1D */ + if(PyArray_NDIM(numpy_array) > 1) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "was expecting 1-dimensional array") + + if(NULL == (numpy_data = PyArray_DATA(numpy_array))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get data from numpy array") + + if(NULL == (numpy_dims = PyArray_DIMS(numpy_array))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get dimensions from numpy array") + numpy_num_elmts = (size_t) numpy_dims[0]; + + if(0 == (numpy_datatype = PyArray_TYPE(numpy_array))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get type from numpy array") + + /* Translate NPY type to hid_t */ + if(FAIL == H5VL__iod_translate_numpy_type(numpy_datatype, &extracted_datatype_id, + &extracted_datatype_size)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCONVERT, FAIL, "can't translate NPY type") + + /* Copy data from NPY array */ + if(NULL == (extracted_data = H5MM_malloc(numpy_num_elmts * extracted_datatype_size))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTALLOC, FAIL, "can't allocate extracted data") + HDmemcpy(extracted_data, numpy_data, numpy_num_elmts * extracted_datatype_size); + + *data = extracted_data; + *num_elmts = numpy_num_elmts; + *data_type_id = extracted_datatype_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5VL__iod_extract_numpy_array */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_split + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__iod_split(const char *split_script, void *data, size_t num_elmts, + hid_t data_type_id, void **split_data, size_t *split_num_elmts, + hid_t *split_data_type_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + PyObject *po_func = NULL, *po_numpy_array = NULL, *po_args_tup = NULL; + PyObject *po_numpy_array_split = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + if(!numpy_initialized) H5VL__iod_numpy_init(); + + /* Create numpy array */ + if(NULL == (po_numpy_array = H5VL__iod_create_numpy_array(num_elmts, data_type_id, data))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create numpy array from data") + + /* Load script */ + if(NULL == (po_func = H5VL__iod_load_script(split_script, "split"))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't load split script") + + /* Check whether split is defined as function in given script */ + if(0 == PyCallable_Check(po_func)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't find split function") + + /* Get the input to function */ + if(NULL == (po_args_tup = PyTuple_Pack(1, po_numpy_array))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't set input to split function") + + /* Invoke the split function */ + if(NULL == (po_numpy_array_split = PyObject_CallObject(po_func, po_args_tup))) + HGOTO_ERROR2(H5E_SYM, H5E_BADVALUE, FAIL, "returned NULL python object") + + /* Extract data from numpy array */ + if(FAIL == H5VL__iod_extract_numpy_array(po_numpy_array_split, split_data, + split_num_elmts, split_data_type_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCREATE, FAIL, "can't extract data from numpy array") + +done: + /* Cleanup */ + Py_XDECREF(po_func); + Py_XDECREF(po_args_tup); + Py_XDECREF(po_numpy_array); + Py_XDECREF(po_numpy_array_split); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_split() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_combine + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__iod_combine(const char *combine_script, void **split_data, size_t *split_num_elmts, + size_t num_targets, hid_t data_type_id, void **combine_data, + size_t *combine_num_elmts, hid_t *combine_data_type_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + PyObject *po_func = NULL, *po_numpy_arrays = NULL, *po_args_tup = NULL; + PyObject *po_numpy_array_combine = NULL; + size_t i; + + FUNC_ENTER_NOAPI_NOINIT + + if(!numpy_initialized) H5VL__iod_numpy_init(); + + /* Create numpy arrays */ + if(NULL == (po_numpy_arrays = PyList_New((Py_ssize_t) num_targets))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create list of arrays") + for(i = 0; i < num_targets; i++) { + PyObject *po_numpy_array = NULL; + int py_ret = 0; + + if(NULL == (po_numpy_array = + H5VL__iod_create_numpy_array(split_num_elmts[i], + data_type_id, + split_data[i]))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create numpy array from data") + + if(0 != (py_ret = PyList_SetItem(po_numpy_arrays, (Py_ssize_t) i, po_numpy_array))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't set item to array list") + } + + /* Load script */ + if(NULL == (po_func = H5VL__iod_load_script(combine_script, "combine"))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't load combine script") + + /* Check whether split is defined as function in given script */ + if(0 == PyCallable_Check(po_func)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't find combine function") + + /* Get the input to function */ + if(NULL == (po_args_tup = PyTuple_Pack(1, po_numpy_arrays))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTLOAD, FAIL, "can't set input to combine function") + + /* Invoke the split function */ + if(NULL == (po_numpy_array_combine = PyObject_CallObject(po_func, po_args_tup))) + HGOTO_ERROR2(H5E_SYM, H5E_BADVALUE, FAIL, "returned NULL python object") + + /* Extract data from numpy array */ + if(FAIL == H5VL__iod_extract_numpy_array(po_numpy_array_combine, combine_data, + combine_num_elmts, combine_data_type_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTCREATE, FAIL, "can't extract data from numpy array") + +done: + /* Cleanup */ + Py_XDECREF(po_func); + Py_XDECREF(po_args_tup); + for(i = 0; i < num_targets; i++) { + Py_XDECREF(po_numpy_arrays + i); + } + Py_XDECREF(po_numpy_array_combine); + + FUNC_LEAVE_NOAPI(ret_value) +} + +#endif /* H5_HAVE_PYTHON */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_request_container_open + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_request_container_open(const char *file_name, iod_handle_t **cohs) +{ + herr_t ret_value = SUCCEED; /* Return value */ + hg_request_t *hg_reqs = NULL; + iod_handle_t *temp_cohs = NULL; + int i; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (hg_reqs = (hg_request_t *)malloc(sizeof(hg_request_t) * (unsigned int) num_ions_g))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate HG requests"); + + if(NULL == (temp_cohs = (iod_handle_t *)malloc(sizeof(iod_handle_t) * (unsigned int) num_ions_g))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate container handles"); + + /* forward a call to every ION to open the container */ + for(i = 1; i < num_ions_g; i++) { + if(HG_Forward(server_addr_g[i], H5VL_EFF_OPEN_CONTAINER, &file_name, + &temp_cohs[i], &hg_reqs[i]) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + } + + /* open the container */ + printf("(%d) Calling iod_container_open on %s\n", my_rank_g, file_name); + if(iod_container_open(file_name, NULL, IOD_CONT_R, &temp_cohs[0], NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open file"); + + for(i = 1; i < num_ions_g; i++) { + if(HG_Wait(hg_reqs[i], HG_MAX_IDLE_TIME, HG_STATUS_IGNORE) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "HG_Wait Failed"); + + /* Free Mercury request */ + if(HG_Request_free(hg_reqs[i]) != HG_SUCCESS) + HGOTO_ERROR2(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + } + free(hg_reqs); + + *cohs = temp_cohs; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_request_container_open */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_request_container_close + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_request_container_close(iod_handle_t *cohs) +{ + herr_t ret_value = SUCCEED; /* Return value */ + hg_request_t *hg_reqs = NULL; + int i; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (hg_reqs = (hg_request_t *)malloc(sizeof(hg_request_t) * (unsigned int) num_ions_g))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate HG requests"); + + /* forward a call to every ION to close the container */ + for(i = 1; i < num_ions_g; i++) { + if(HG_Forward(server_addr_g[i], H5VL_EFF_CLOSE_CONTAINER, &cohs[i], + &ret_value, &hg_reqs[i]) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + } + + /* close the container */ + if(iod_container_close(cohs[0], NULL, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTDEC, FAIL, "can't close container"); + + for(i = 1; i < num_ions_g; i++) { + if(HG_Wait(hg_reqs[i], HG_MAX_IDLE_TIME, HG_STATUS_IGNORE) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "HG_Wait Failed"); + + /* Free Mercury request */ + if(HG_Request_free(hg_reqs[i]) != HG_SUCCESS) + HGOTO_ERROR2(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + } + free(hg_reqs); + free(cohs); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_request_container_close */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_farm_work + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_farm_work(iod_obj_map_t *obj_map, iod_handle_t *cohs, + iod_obj_id_t obj_id, iod_trans_id_t rtid, + hid_t space_id, hid_t type_id, hid_t query_id, + const char *split_script, const char *combine_script) +{ + herr_t ret_value = SUCCEED; /* Return value */ + void **split_data; + size_t *split_num_elmts; + void *combine_data; + size_t combine_num_elmts; + hid_t split_type_id = FAIL, combine_type_id = FAIL; + hg_request_t *hg_reqs = NULL; + unsigned int i; + unsigned int num_targets = obj_map->u_map.array_map.n_range; + analysis_farm_in_t farm_input; + analysis_farm_out_t *farm_output = NULL; + + FUNC_ENTER_NOAPI_NOINIT + + /* function shipper requests */ + if(NULL == (hg_reqs = (hg_request_t *) malloc(sizeof(hg_request_t) * num_targets))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate HG requests"); + + if(NULL == (farm_output = (analysis_farm_out_t *) malloc(sizeof(analysis_farm_out_t) * num_targets))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate HG requests"); + + if(NULL == (split_data = (void **) malloc(sizeof(void *) * num_targets))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array for split data"); + + if(NULL == (split_num_elmts = (size_t *) malloc(sizeof(size_t) * num_targets))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array for num elmts"); + + farm_input.obj_id = obj_id; + farm_input.rtid = rtid; + farm_input.space_id = space_id; + farm_input.type_id = type_id; + farm_input.query_id = query_id; + farm_input.split_script = split_script; + + for (i = 0; i < obj_map->u_map.array_map.n_range; i++) { + unsigned int j; + unsigned int server_idx = 0; + farm_input.num_cells = obj_map->u_map.array_map.array_range[i].n_cell; + farm_input.coords.rank = H5Sget_simple_extent_ndims(space_id); + farm_input.coords.start_cell = obj_map->u_map.array_map.array_range[i].start_cell; + farm_input.coords.end_cell = obj_map->u_map.array_map.array_range[i].end_cell; + + for (j = 0; j < (unsigned int) num_ions_g; j++) { + if (0 == strcmp(obj_map->u_map.array_map.array_range[i].loc, + server_loc_g[j])) { + server_idx = j; + printf("(%d) Server %d owns this object\n", my_rank_g, server_idx); + break; + } + } + + farm_input.server_idx = server_idx; + farm_input.coh = cohs[server_idx]; + + /* forward the call to the target server */ + if (server_idx == 0) { + hg_reqs[i] = HG_REQUEST_NULL; + /* Do a local split */ + if(FAIL == H5VL__iod_farm_split(cohs[0], obj_id, rtid, space_id, + farm_input.coords, farm_input.num_cells, type_id, query_id, split_script, + &split_data[i], &split_num_elmts[i], &split_type_id)) + HGOTO_ERROR2(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't split in farmed job"); + } else { + if(HG_Forward(server_addr_g[server_idx], + H5VL_EFF_ANALYSIS_FARM, &farm_input, &farm_output[i], + &hg_reqs[i]) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + } + } + + for (i = 0; i < num_targets; i++) { + if (hg_reqs[i] == HG_REQUEST_NULL) { + /* No request / was local */ + } else { + analysis_transfer_in_t transfer_input; + analysis_transfer_out_t transfer_output; + hg_bulk_t bulk_handle; + size_t split_data_size; + unsigned int server_idx; + + /* Wait for the farmed work to complete */ + if(HG_Wait(hg_reqs[i], HG_MAX_IDLE_TIME, HG_STATUS_IGNORE) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "HG_Wait Failed"); + + /* Get split type ID and num_elemts (all the arrays should have the same native type id) */ + server_idx = farm_output[i].server_idx; + split_type_id = farm_output[i].type_id; + split_num_elmts[i] = farm_output[i].num_elmts; + split_data_size = split_num_elmts[i] * H5Tget_size(split_type_id); +// printf("Getting %d elements of size %zu from server %zu\n", +// split_num_elmts[i], H5Tget_size(split_type_id), server_idx); + + if(NULL == (split_data[i] = malloc(split_data_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate farm buffer"); + + HG_Bulk_handle_create(split_data[i], split_data_size, + HG_BULK_READWRITE, &bulk_handle); + + transfer_input.axe_id = farm_output[i].axe_id; + transfer_input.bulk_handle = bulk_handle; + + /* forward a free call to the target server */ + if(HG_Forward(server_addr_g[server_idx], H5VL_EFF_ANALYSIS_FARM_TRANSFER, + &transfer_input, &transfer_output, &hg_reqs[i]) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + + /* Wait for the farmed work to complete */ + if(HG_Wait(hg_reqs[i], HG_MAX_IDLE_TIME, HG_STATUS_IGNORE) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "HG_Wait Failed"); + + /* Free bulk handle */ + HG_Bulk_handle_free(bulk_handle); + + /* Free Mercury request */ + if(HG_Request_free(hg_reqs[i]) != HG_SUCCESS) + HGOTO_ERROR2(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + } + } + + if(hg_reqs) + free(hg_reqs); + if(farm_output) + free(farm_output); + + printf("(%d) Applying combine on data\n", my_rank_g); +#ifdef H5_HAVE_PYTHON + if (H5VL__iod_combine(combine_script, split_data, split_num_elmts, + num_targets, split_type_id, &combine_data, + &combine_num_elmts, &combine_type_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't combine split data"); +#endif + + /* free farm data */ + if (split_data) { + for (i = 0; i < num_targets; i++) { + free(split_data[i]); + } + free(split_data); + } + free(split_num_elmts); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_farm_work */ + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_execute_cb + * + * Purpose: Retrieves layout of object + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_analysis_execute_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + analysis_execute_in_t *input = (analysis_execute_in_t *)op_data->input; + analysis_execute_out_t output; + const char *file_name = input->file_name; + const char *obj_name = input->obj_name; + hid_t query_id = input->query_id; + const char *split_script = input->split_script; + const char *combine_script = input->combine_script; + hid_t space_id = FAIL, type_id = FAIL; + iod_cont_trans_stat_t *tids = NULL; + iod_trans_id_t rtid; + iod_handle_t *cohs; /* the container handle */ + iod_handles_t root_handle; /* root handle */ + iod_obj_id_t obj_id; /* The ID of the object */ + iod_handles_t obj_oh; /* object handle */ + iod_handle_t mdkv_oh; + scratch_pad sp; + iod_obj_map_t *obj_map = NULL; + unsigned int i; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* ****************** TEMP THING (as IOD requires collective container open) */ + + if(FAIL == H5VL__iod_request_container_open(file_name, &cohs)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't request container open"); + + /* ***************** END TEMP THING */ + + if(iod_query_cont_trans_stat(cohs[0], &tids, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get container tids status"); + + rtid = tids->latest_rdable; + + if(iod_free_cont_trans_stat(cohs[0], tids) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free container transaction status object"); + + if(iod_trans_start(cohs[0], &rtid, NULL, 0, IOD_TRANS_R, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't start transaction"); + + root_handle.rd_oh.cookie = IOD_OH_UNDEFINED; + root_handle.wr_oh.cookie = IOD_OH_UNDEFINED; + + /* Traverse Path to retrieve object ID, and open object */ + if(H5VL_iod_server_open_path(cohs[0], ROOT_ID, root_handle, obj_name, + rtid, 7, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + printf("(%d) coh %"PRIu64" objoh %"PRIu64" objid %"PRIx64" rtid %"PRIu64"\n", + my_rank_g, cohs[0].cookie, obj_oh.rd_oh.cookie, obj_id, rtid); + + printf("Calling iod_obj_query_map\n"); + ret = iod_obj_query_map(obj_oh.rd_oh, rtid, &obj_map, NULL); + if (ret != 0) { + printf("iod_obj_query_map failed, ret: %d (%s).\n", ret, strerror(-ret)); + assert(0); + } + + printf("(%d) %-10d\n", my_rank_g, obj_map->u_map.array_map.n_range); + for (i = 0; i < obj_map->u_map.array_map.n_range; i++) { + printf("(%d) range: %d, start: %zu %zu, " + "end: %zu %zu, n_cell: %zu, " + "loc: %s\n", my_rank_g, i, + obj_map->u_map.array_map.array_range[i].start_cell[0], + obj_map->u_map.array_map.array_range[i].start_cell[1], + obj_map->u_map.array_map.array_range[i].end_cell[0], + obj_map->u_map.array_map.array_range[i].end_cell[1], + obj_map->u_map.array_map.array_range[i].n_cell, + obj_map->u_map.array_map.array_range[i].loc); + } + + /* get scratch pad */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, (char *) &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + /* retrieve datatype and dataspace */ + /* MSC - This applies only to DATASETS for Q6 */ + + /* open the metadata scratch pad */ + if (iod_obj_open_read(cohs[0], sp[0], rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_OBJ_DATATYPE, + NULL, NULL, &type_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, + H5VL_IOD_KEY_OBJ_DATASPACE, + NULL, NULL, &space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + /*******************************************/ + /* Farm work */ + if(FAIL == H5VL__iod_farm_work(obj_map, cohs, obj_id, rtid, space_id, type_id, + query_id, split_script, combine_script)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't farm work"); + + /********************************************/ + + iod_obj_free_map(obj_oh.rd_oh, obj_map); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + /* close object */ + if(iod_obj_close(obj_oh.rd_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + + if(iod_trans_finish(cohs[0], rtid, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't finish transaction 0"); + + /* ****************** TEMP THING (as IOD requires collective container open) */ + + printf("Closing container\n"); + if(FAIL == H5VL__iod_request_container_close(cohs)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't request container close"); + + /* ***************** END TEMP THING */ + + printf("Analysis DONE\n"); + /* set output, and return to AS client */ + output.ret = ret_value; + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + if(space_id) + H5Sclose(space_id); + if(type_id) + H5Tclose(type_id); + + input = (analysis_execute_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_analysis_execute_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_farm_split + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_farm_split(iod_handle_t coh, iod_obj_id_t obj_id, iod_trans_id_t rtid, + hid_t space_id, coords_t coords, iod_size_t num_cells, + hid_t type_id, hid_t query_id, + const char *split_script, void **split_data, + size_t *split_num_elmts, hid_t *split_type_id) +{ + void *data = NULL; + size_t num_elmts; + herr_t ret_value = SUCCEED; + hid_t space_layout; + + FUNC_ENTER_NOAPI_NOINIT + + if(FAIL == (space_layout = H5VL__iod_get_space_layout(coords, num_cells, space_id))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't generate local dataspace selection"); + + if(H5VL__iod_get_query_data(coh, obj_id, rtid, query_id, space_layout, + type_id, &num_elmts, &data) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read local data"); + + printf("(%d) Applying split on data\n", my_rank_g); + /* Apply split python script on data from query */ +#ifdef H5_HAVE_PYTHON + if(FAIL == H5VL__iod_split(split_script, data, num_elmts, type_id, + split_data, split_num_elmts, split_type_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANAPPLY, FAIL, "can't apply split script to data"); +#endif + + /* Free the data after split operation */ + H5MM_free(data); + data = NULL; + +done: + if(space_layout) + H5Sclose(space_layout); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_farm_work */ + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_farm_cb + * + * Purpose: Retrieves layout of object + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_analysis_farm_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + analysis_farm_in_t *input = (analysis_farm_in_t *)op_data->input; + H5VLiod_farm_data_t *output = NULL; + iod_handle_t coh = input->coh; + hid_t query_id = input->query_id; + hid_t space_id = input->space_id; + hid_t type_id = input->type_id; + iod_trans_id_t rtid = input->rtid; + iod_obj_id_t obj_id = input->obj_id; /* The ID of the object */ + coords_t coords = input->coords; + const char *split_script = input->split_script; + iod_size_t num_cells = input->num_cells; + void *split_data = NULL; + size_t split_num_elmts; + hid_t split_type_id; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(FAIL == H5VL__iod_farm_split(coh, obj_id, rtid, space_id, coords, num_cells, + type_id, query_id, split_script, + &split_data, &split_num_elmts, &split_type_id)) + HGOTO_ERROR2(H5E_ATTR, H5E_WRITEERROR, FAIL, "can't split in farmed job"); + + /* allocate output struct */ + if(NULL == (output = (H5VLiod_farm_data_t *)H5MM_malloc(sizeof(H5VLiod_farm_data_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, FAIL, "No Space"); + + /* set output, and return to master */ + output->farm_out.ret = ret_value; + output->farm_out.axe_id = op_data->axe_id; + output->farm_out.server_idx = input->server_idx; + output->farm_out.num_elmts = split_num_elmts; + output->farm_out.type_id = split_type_id; + output->data = split_data; + op_data->output = output; + + HG_Handler_start_output(op_data->hg_handle, &output->farm_out); + +done: + input = (analysis_farm_in_t *)H5MM_xfree(input); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_analysis_farm_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_farm_transfer_cb + * + * Purpose: Frees the output from the split operation + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_analysis_transfer_cb(AXE_engine_t axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + analysis_transfer_in_t *input = (analysis_transfer_in_t *)op_data->input; + op_data_t *farm_op_data = NULL; + void *farm_op_data_ptr = NULL; + H5VLiod_farm_data_t *farm_output = NULL; + herr_t ret_value = SUCCEED; + hg_bulk_t bulk_block_handle; + size_t data_size; + hg_bulk_request_t bulk_request; + na_addr_t source = HG_Handler_get_addr(op_data->hg_handle); + + FUNC_ENTER_NOAPI_NOINIT + + if(AXE_SUCCEED != AXEget_op_data(axe_engine, input->axe_id, &farm_op_data_ptr)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to get farm op_data"); + + farm_op_data = (op_data_t *)farm_op_data_ptr; + farm_output = (H5VLiod_farm_data_t *)farm_op_data->output; + + data_size = HG_Bulk_handle_get_size(input->bulk_handle); + printf("(%d) Transferring split data back to master\n", my_rank_g); + + HG_Bulk_handle_create(farm_output->data, data_size, HG_BULK_READ_ONLY, + &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(source, + input->bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* free the bds block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + + free(farm_output->data); + farm_op_data = (op_data_t *)H5MM_xfree(farm_op_data); + +done: + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (analysis_transfer_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_analysis_farm_cb() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_get_space_layout + * + * Purpose: Generates a dataspace from the IOD layout for a particular + * ION or OST. The dataspace returned must be closed with H5Sclose(). + * + * Return: Success: space id + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static hid_t +H5VL__iod_get_space_layout(coords_t coords, iod_size_t num_cells, hid_t space_id) +{ + int ndims, i; + hsize_t start[H5S_MAX_RANK]; + hsize_t block[H5S_MAX_RANK]; + hsize_t count[H5S_MAX_RANK]; + + hid_t space_layout = FAIL, ret_value = FAIL; + + FUNC_ENTER_NOAPI_NOINIT + + /* retrieve number of dimensions and dimensions. */ + ndims = H5Sget_simple_extent_ndims(space_id); + + /* copy the original dataspace and reset selection to NONE */ + if(FAIL == (space_layout = H5Scopy(space_id))) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace"); + + for(i=0 ; i<ndims ; i++) { + start[i] = coords.start_cell[i]; + block[i] = (coords.end_cell[i] - coords.start_cell[i]) + 1; + count[i] = 1; + } + + if(H5Sselect_hyperslab(space_layout, H5S_SELECT_SET, start, NULL, count, block)) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to add point to selection"); + + ret_value = space_layout; + +done: + if(ret_value < 0) { + if(FAIL != space_layout && H5Sclose(space_layout) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_get_space_layout() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_get_query_data_cb + * + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_get_query_data_cb(void *elem, hid_t type_id, unsigned ndim, + const hsize_t *point, void *_udata) +{ + H5VL__iod_get_query_data_t *udata = (H5VL__iod_get_query_data_t *)_udata; + hbool_t result; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(ndim == 1); + + /* Apply the query */ + if(H5Qapply(udata->query_id, &result, type_id, elem) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "unable to apply query to data element"); + + /* If element satisfies query, add it to the selection */ + if (result) { + /* TODO remove that after demo */ + printf("(%d) Element |%d| matches query\n", my_rank_g, *((int *) elem)); + udata->num_elmts ++; + if(H5Sselect_elements(udata->space_query, H5S_SELECT_APPEND, 1, point)) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to add point to selection") + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_get_query_data_cb */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_get_query_data + * + * Purpose: Generates a dataspace from the query specified. The dataspace + * returned must be closed with H5Sclose(). + * + * Return: Success: space id + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_get_query_data(iod_handle_t coh, iod_obj_id_t dset_id, + iod_trans_id_t rtid, hid_t query_id, + hid_t space_id, hid_t type_id, + size_t *num_elmts, void **data) +{ + hsize_t dims[1]; + size_t nelmts; + size_t elmt_size=0, buf_size=0; + H5VL__iod_get_query_data_t udata; + void *buf = NULL; + hid_t space_query = FAIL, mem_space = FAIL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + nelmts = (size_t) H5Sget_select_npoints(space_id); + elmt_size = H5Tget_size(type_id); + buf_size = nelmts * elmt_size; + + /* allocate buffer to hold data */ + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* read the data local on the ION specified in the layout selection */ + if(H5VL__iod_read_selection(coh, dset_id, rtid, space_id, type_id, buf) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read local data"); + + dims[0] = (hsize_t)nelmts; + /* create a 1-D selection to describe the data read in memory */ + if(FAIL == (mem_space = H5Screate_simple(1, dims, NULL))) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); + + if(FAIL == (space_query = H5Scopy(mem_space))) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace"); + + udata.query_id = query_id; + udata.space_query = space_query; + udata.num_elmts = 0; + + /* iterate over every element and apply the query on it. If the + query is not satisfied, then remove it from the query selection */ + if(H5Diterate(buf, type_id, mem_space, H5VL__iod_get_query_data_cb, &udata) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to compute buffer size"); + + if(udata.num_elmts) { + buf_size = udata.num_elmts * elmt_size; + + /* allocate buffer to hold data */ + if(NULL == (*data = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate data buffer"); + + if(H5Dgather(space_query, buf, type_id, buf_size, *data, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_IO, H5E_CANTCOPY, FAIL, "gather failed") + } + + *num_elmts = udata.num_elmts; + +done: + if(space_query && H5Sclose(space_query) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + if(mem_space && H5Sclose(mem_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + if(buf != NULL) + free(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_get_query_data() */ + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_read_selection + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_read_selection(iod_handle_t coh, iod_obj_id_t obj_id, + iod_trans_id_t rtid, hid_t space_id, + hid_t type_id, void *buf) +{ + iod_handle_t obj_oh; + size_t buf_size=0; + size_t elmt_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the array object */ + if (iod_obj_open_read(coh, obj_id, rtid, NULL, &obj_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open array object fo read"); + + /* read the data selection from IOD. */ + /* MSC - will need to do it in pieces, not it one shot. */ + elmt_size = H5Tget_size(type_id); + if(H5VL__iod_server_final_io(obj_oh, space_id, elmt_size, FALSE, + buf, buf_size, (uint64_t)0, 0, rtid) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + +done: + if(obj_oh.cookie != IOD_OH_UNDEFINED && + iod_obj_close(obj_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_read_selection() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_attr.c b/src/H5VLiod_attr.c new file mode 100644 index 0000000..4c4979e --- /dev/null +++ b/src/H5VLiod_attr.c @@ -0,0 +1,1260 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side attribute routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_create_cb + * + * Purpose: Creates a attr as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_create_in_t *input = (attr_create_in_t *)op_data->input; + attr_create_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t loc_attrkv_id = input->loc_attrkv_id; /* The ID of the attribute KV of the location object*/ + iod_obj_id_t attr_id = input->attr_id; /* The ID of the attribute that needs to be created */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV to be created */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t attr_oh, obj_oh; /* object handles */ + iod_handle_t attr_kv_oh, mdkv_oh; + iod_obj_id_t obj_id; + const char *loc_name = input->path; /* path to start hierarchy traversal */ + const char *attr_name = input->attr_name; /* attribute's name */ + iod_array_struct_t array; /* IOD array structure for attribute's creation */ + iod_size_t *max_dims; /* MAX dims for IOD */ + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_size_t array_dims[H5S_MAX_RANK], current_dims[H5S_MAX_RANK]; + iod_hint_list_t *obj_create_hint = NULL; + hbool_t opened_locally = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute create %s at %"PRIu64" with ID %"PRIx64" %"PRIx64"\n", + attr_name, loc_handle.wr_oh.cookie, attr_id, loc_attrkv_id); +#endif + + attr_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + attr_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + mdkv_oh.cookie = IOD_OH_UNDEFINED; + attr_kv_oh.cookie = IOD_OH_UNDEFINED; + + if(cs_scope & H5_CHECKSUM_IOD) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + if(loc_handle.rd_oh.cookie == IOD_OH_UNDEFINED) { + /* Try and open the starting location */ + if (iod_obj_open_read(coh, loc_id, wtid, NULL, &loc_handle.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open start location"); + opened_locally = TRUE; + } + + /* Open the object where the attribute needs to be created. */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, loc_name, rtid, + cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* Set the IOD array creation parameters */ + array.cell_size = (uint32_t)H5Tget_size(input->type_id); + array.num_dims = (uint32_t)H5Sget_simple_extent_ndims(input->space_id); + + /* Handle Scalar Dataspaces (set rank and current dims size to 1) */ + if(0 == array.num_dims) { + array.num_dims = 1; + array.firstdim_max = 1; + current_dims[0] = 1; + } + else { + if(H5Sget_simple_extent_dims(input->space_id, current_dims, array_dims) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get dimentions' sizes"); + array.firstdim_max = array_dims[0]; + } + + array.current_dims = current_dims; + array.chunk_dims = NULL; + + /* create the attribute */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_ARRAY, NULL, + &array, &attr_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Attribute"); + + if (iod_obj_open_read(coh, attr_id, wtid, NULL, &attr_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open attribute"); + if (iod_obj_open_write(coh, attr_id, wtid, NULL, &attr_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open attribute"); + + /* create the metadata KV object for the attribute */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, NULL, NULL, &mdkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = IOD_OBJ_INVALID; + sp[2] = IOD_OBJ_INVALID; + sp[3] = IOD_OBJ_INVALID; + + /* set scratch pad in attribute */ + if(cs_scope & H5_CHECKSUM_IOD) { + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + if (iod_obj_set_scratch(attr_oh.wr_oh, wtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + else { + if (iod_obj_set_scratch(attr_oh.wr_oh, wtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + + /* Open Metadata KV object for write */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create scratch pad"); + + /* insert object type metadata */ + if(H5VL_iod_insert_object_type(mdkv_oh, wtid, H5I_ATTR, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* MSC - need to check size of datatype if it fits in + entry otherwise create a BLOB */ + + /* insert datatype metadata */ + if(H5VL_iod_insert_datatype(mdkv_oh, wtid, input->type_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert dataspace metadata */ + if(H5VL_iod_insert_dataspace(mdkv_oh, wtid, input->space_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* if the starting location is not the last component, need to + read the attrkv_id of the last object where attribute needs + to be created */ + if(loc_id != obj_id || loc_attrkv_id == IOD_OBJ_INVALID) { + /* get scratch pad of the parent */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the attribute KV in scratch pad */ + if (iod_obj_open_write(coh, sp[1], wtid, NULL /*hints*/, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the attribute KV */ + if (iod_obj_open_write(coh, loc_attrkv_id, wtid, NULL /*hints*/, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + /* insert new attribute in scratch pad of current object */ + if(H5VL_iod_insert_new_link(attr_kv_oh, wtid, attr_name, + H5L_TYPE_HARD, &attr_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + output.iod_oh.rd_oh.cookie = attr_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = attr_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr create, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + + /* close parent group if it is not the location we started the + traversal into */ + if(TRUE == opened_locally || loc_handle.rd_oh.cookie != obj_oh.rd_oh.cookie) { + iod_obj_close(obj_oh.rd_oh, NULL, NULL); + } + + iod_obj_close(mdkv_oh, NULL, NULL); + iod_obj_close(attr_kv_oh, NULL, NULL); + + /* return an UNDEFINED oh to the client if the operation failed */ + if(ret_value < 0) { + fprintf(stderr, "Failed Attribute Create\n"); + + if(attr_oh.rd_oh.cookie != IOD_OH_UNDEFINED && + iod_obj_close(attr_oh.rd_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if(attr_oh.wr_oh.cookie != IOD_OH_UNDEFINED && + iod_obj_close(attr_oh.wr_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + if(obj_create_hint) { + free(obj_create_hint); + obj_create_hint = NULL; + } + +#if 0 + /* close the Metadata KV object */ + if(mdkv_oh.cookie != IOD_OH_UNDEFINED && + iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* close the Attribute KV object */ + if(attr_kv_oh.cookie != IOD_OH_UNDEFINED && + iod_obj_close(attr_kv_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); +#endif + + input = (attr_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_open_cb + * + * Purpose: Opens a attribute as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_open_in_t *input = (attr_open_in_t *)op_data->input; + attr_open_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start traversal */ + iod_obj_id_t loc_id = input->loc_id; /* location ID */ + iod_obj_id_t loc_attrkv_id = input->loc_attrkv_id; /* The ID of the attribute KV of the location object*/ + const char *loc_name = input->path; /* current path to start traversal */ + const char *attr_name = input->attr_name; /* attribute's name to open */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t attr_oh, obj_oh; + iod_handle_t attr_kv_oh, mdkv_oh; + iod_obj_id_t obj_id; + iod_obj_id_t attr_id; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + H5VL_iod_link_t iod_link; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute open %s at %s (OH %"PRIu64" ID %"PRIx64")\n", + attr_name, loc_name, loc_handle.rd_oh.cookie, loc_id); +#endif + + /* Open the object where the attribute needs to be opened. */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Attribute is on object (OH %"PRIu64" ID %"PRIx64")\n", + obj_oh.rd_oh.cookie, obj_id); +#endif + + /* if the starting location is not the last component, need to + read the attrkv_id of the last object where attribute needs + to be created */ + if(loc_id != obj_id || loc_attrkv_id == IOD_OBJ_INVALID) { + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* if attribute KV does not exist, return error*/ + if(IOD_OBJ_INVALID == sp[1]) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "Object has no attributes"); + + /* open the attribute KV in scratch pad */ + if (iod_obj_open_read(coh, sp[1], rtid, NULL /*hints*/, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the attribute KV */ + if (iod_obj_open_read(coh, loc_attrkv_id, rtid, NULL /*hints*/, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + /* get attribute ID */ + if(H5VL_iod_get_metadata(attr_kv_oh, rtid, H5VL_IOD_LINK, + attr_name, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve Attribute ID from parent KV store"); + + HDassert(iod_link.link_type == H5L_TYPE_HARD); + attr_id = iod_link.u.iod_id; + + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != obj_oh.rd_oh.cookie) { + iod_obj_close(obj_oh.rd_oh, NULL, NULL); + } + /* close the attribute KV holder */ + iod_obj_close(attr_kv_oh, NULL, NULL); + + /* open the attribute */ + if (iod_obj_open_read(coh, attr_id, rtid, NULL /*hints*/, &attr_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + if (iod_obj_open_write(coh, attr_id, rtid, NULL /*hints*/, &attr_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + /* get scratch pad of the attribute */ + if(iod_obj_get_scratch(attr_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad of the attribute */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_OBJ_DATATYPE, + cs_scope, NULL, &output.type_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, + H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &output.space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + output.iod_id = attr_id; + output.mdkv_id = sp[0]; + output.iod_oh.rd_oh.cookie = attr_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = attr_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.space_id = FAIL; + output.type_id = FAIL; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (attr_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_read_cb + * + * Purpose: Reads from IOD into the function shipper BDS handle. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_read_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_io_in_t *input = (attr_io_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handle_t iod_oh = input->iod_oh.rd_oh; /* attribute's object handle */ + iod_obj_id_t iod_id = input->iod_id; /* attribute's ID */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV */ + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + //hid_t type_id = input->type_id; /* datatype ID of data */ + hid_t space_id = input->space_id; /* dataspace of attribute */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handle_t mdkv_oh; + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + iod_mem_desc_t *mem_desc = NULL; /* memory descriptor used for reading array */ + iod_array_iodesc_t file_desc; /* file descriptor used to read array */ + iod_hyperslab_t hslabs; /* IOD hyperslab generated from HDF5 filespace */ + size_t size; /* size of outgoing bulk data */ + void *buf; /* buffer to hold outgoing data */ + iod_checksum_t iod_cs = 0, attr_cs = 0; + int ndims; /* dataset's rank/number of dimensions */ + hssize_t num_descriptors = 0; /* number of IOD file descriptors needed to describe filespace selection */ + na_addr_t dest = HG_Handler_get_addr(op_data->hg_handle); /* destination address to push data to */ + hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the attribute here or if it was already open */ + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the attribute if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, iod_id, rtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Attribute Read on OH %"PRIu64" OID %"PRIx64"\n", + iod_oh.cookie, iod_id); +#endif + + size = HG_Bulk_handle_get_size(bulk_handle); + + if(NULL == (buf = malloc(size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* Get dataspace if it is not available */ + if(H5I_UNINIT == space_id) { + /* open the metadata scratch pad of the attribute */ + if (iod_obj_open_read(coh, mdkv_id, rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, + H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + + /* set the memory descriptor */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = buf; + mem_desc->frag[0].len = (iod_size_t)size; + + num_descriptors = 1; + + /* get the rank of the dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + /* handle scalar dataspace */ + if(0 == ndims) { + ndims = 1; + + hslabs.start = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.stride = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.block = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.count = (iod_size_t *)malloc(sizeof(iod_size_t)); + + num_descriptors = 1; + hslabs.start[0] = 0; + hslabs.count[0] = 1; + hslabs.block[0] = 1; + hslabs.stride[0] = 1; + } + else { + hslabs.start = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.stride = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.block = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.count = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + + /* generate the descriptor */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, &hslabs) < 0) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + } + + /* set the file descriptor */ + file_desc = hslabs; + + /* read from array object */ + if(cs_scope & H5_CHECKSUM_IOD) { + ret = iod_array_read(iod_oh, rtid, NULL, mem_desc, &file_desc, + &iod_cs, NULL); + if(ret < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + } + + attr_cs = H5_checksum_crc64(buf, size); + + if(attr_cs != iod_cs) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data corruption detected when reading attribute"); + } + else { + ret = iod_array_read(iod_oh, rtid, NULL, mem_desc, &file_desc, NULL, NULL); + if(ret < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + } + } + + /* Create a new block handle to write the data */ + HG_Bulk_handle_create(buf, size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't start Mercury Bulk Data write"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Failed to wait on Mercury Bulk data write"); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr read, sending response to client\n"); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + + input = (attr_io_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + free(buf); + + /* free allocated descriptors */ + free(hslabs.start); + free(hslabs.stride); + free(hslabs.block); + free(hslabs.count); + if(mem_desc) + free(mem_desc); + + /* close the attribute if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_read_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_write_cb + * + * Purpose: Writes from IOD into the function shipper BDS handle. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_write_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_io_in_t *input = (attr_io_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handle_t iod_oh = input->iod_oh.wr_oh; /* attribute's object handle */ + iod_obj_id_t iod_id = input->iod_id; /* attribute's ID */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV */ + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + //hid_t type_id = input->type_id; /* datatype ID of data */ + hid_t space_id = input->space_id; /* dataspace of attribute */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handle_t mdkv_oh; + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + iod_mem_desc_t *mem_desc; /* memory descriptor used for writing array */ + iod_array_iodesc_t file_desc; /* file descriptor used to write array */ + iod_hyperslab_t hslabs; /* IOD hyperslab generated from HDF5 filespace */ + size_t size; /* size of outgoing bulk data */ + void *buf; /* buffer to hold outgoing data */ + int ndims; /* dataset's rank/number of dimensions */ + iod_checksum_t attr_cs = 0; + hssize_t num_descriptors = 0; /* number of IOD file descriptors needed to describe filespace selection*/ + na_addr_t source = HG_Handler_get_addr(op_data->hg_handle); /* source address to pull data from */ + hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the attribute here or if it was already opened */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the attribute if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, wtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Attribute Write on OH %"PRIu64" OID %"PRIx64"\n", + iod_oh.cookie, iod_id); +#endif + + /* Read bulk data here and wait for the data to be here */ + size = HG_Bulk_handle_get_size(bulk_handle); + if(NULL == (buf = malloc(size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + HG_Bulk_handle_create(buf, size, HG_BULK_READWRITE, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* free the bds block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + +#if H5VL_IOD_DEBUG + { + int i; + int *buf_ptr = (int *)buf; + + fprintf(stderr, "AWRITE Received a buffer of size %zu with values: ", size); + for(i=0;i<60;++i) + fprintf(stderr, "%d ", buf_ptr[i]); + fprintf(stderr, "\n"); + } +#endif + + /* Get dataspace if it is not available */ + if(H5I_UNINIT == space_id) { + /* open the metadata scratch pad of the attribute */ + if (iod_obj_open_read(coh, mdkv_id, wtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + + /* set the memory descriptor */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = buf; + mem_desc->frag[0].len = (iod_size_t)size; + + num_descriptors = 1; + + /* get the rank of the dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + /* handle scalar dataspace */ + if(0 == ndims) { + ndims = 1; + + hslabs.start = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.stride = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.block = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs.count = (iod_size_t *)malloc(sizeof(iod_size_t)); + + num_descriptors = 1; + hslabs.start[0] = 0; + hslabs.count[0] = 1; + hslabs.block[0] = 1; + hslabs.stride[0] = 1; + } + else { + hslabs.start = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.stride = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.block = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs.count = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + + /* generate the descriptor */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, &hslabs) < 0) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + } + + /* set the file descriptor */ + file_desc = hslabs; + + if(cs_scope & H5_CHECKSUM_IOD) { + attr_cs = H5_checksum_crc64(buf, size); + /* write from array object */ + if(iod_array_write(iod_oh, wtid, NULL, mem_desc, &file_desc, &attr_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write to array object"); + } + else { + /* write from array object */ + if(iod_array_write(iod_oh, wtid, NULL, mem_desc, &file_desc, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write to array object"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr write, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + + input = (attr_io_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + free(buf); + + /* free allocated descriptors */ + free(hslabs.start); + free(hslabs.stride); + free(hslabs.block); + free(hslabs.count); + if(mem_desc) + free(mem_desc); + + /* close the attribute if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_write_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_exists_cb + * + * Purpose: Checks if an attribute exists on object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_exists_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_op_in_t *input = (attr_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; /* current object handle accessed */ + iod_handle_t attr_kv_oh; /* KV handle holding attributes for object */ + iod_obj_id_t obj_id; + const char *loc_name = input->path; /* path to start hierarchy traversal */ + const char *attr_name = input->attr_name; /* attribute's name */ + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_size_t kv_size = 0; + htri_t ret = -1; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute Exists %s/%s on CV %d\n", loc_name, attr_name, (int)rtid); +#endif + + /* Open the object where the attribute needs to be checked. */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, loc_name, rtid, + cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if(loc_id != obj_id || IOD_OBJ_INVALID == input->loc_attrkv_id) { + /* get scratch pad of the parent */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* if attribute KV does not exist, return false*/ + if(IOD_OBJ_INVALID == sp[1]) { + ret = FALSE; + HGOTO_DONE(SUCCEED); + } + + /* open the attribute KV in scratch pad */ + if (iod_obj_open_read(coh, sp[1], rtid, NULL, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the attribute KV */ + if (iod_obj_open_read(coh, input->loc_attrkv_id, rtid, NULL, &attr_kv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != obj_oh.rd_oh.cookie) { + iod_obj_close(obj_oh.rd_oh, NULL, NULL); + } + + /* get attribute ID */ + if(iod_kv_get_value(attr_kv_oh, rtid, attr_name, (iod_size_t)strlen(attr_name), + NULL, &kv_size, NULL, NULL) < 0) { + ret = FALSE; + } + else { + ret = TRUE; + } + + iod_obj_close(attr_kv_oh, NULL, NULL); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr exists, sending %d to client\n", ret); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret); + + input = (attr_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_exists_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_rename_cb + * + * Purpose: Renames iod HDF5 attribute. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_rename_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_rename_in_t *input = (attr_rename_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_handles_t obj_oh; /* current object handle accessed */ + iod_handles_t attr_kv_oh; /* KV handle holding attributes for object */ + iod_obj_id_t obj_id, attr_id; + const char *loc_name = input->path; /* path to start hierarchy traversal */ + const char *old_name = input->old_attr_name; + const char *new_name = input->new_attr_name; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_kv_params_t kvs; /* KV lists for objects - used to unlink attribute object */ + iod_kv_t kv; /* KV entry */ + H5VL_iod_link_t iod_link; + scratch_pad sp; + iod_ret_t ret; + iod_checksum_t cs; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute Rename %s to %s\n", old_name, new_name); +#endif + + /* Open the object where the attribute needs to be checked. */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if(loc_id != obj_id || IOD_OBJ_INVALID == input->loc_attrkv_id) { + /* get scratch pad of the parent */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* if attribute KV does not exist, return error*/ + if(IOD_OBJ_INVALID == sp[1]) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "Object has no attributes"); + + /* open the attribute KV in scratch pad */ + if (iod_obj_open_read(coh, sp[1], wtid, NULL /*hints*/, &attr_kv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, sp[1], wtid, NULL /*hints*/, &attr_kv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the attribute KV */ + if (iod_obj_open_read(coh, input->loc_attrkv_id, wtid, NULL /*hints*/, &attr_kv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, input->loc_attrkv_id, wtid, NULL /*hints*/, &attr_kv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != obj_oh.rd_oh.cookie) { + iod_obj_close(obj_oh.rd_oh, NULL, NULL); + } + + /* get attribute ID */ + if(H5VL_iod_get_metadata(attr_kv_oh.rd_oh, rtid, H5VL_IOD_LINK, + old_name, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve Attribute ID from parent KV store"); + + HDassert(iod_link.link_type == H5L_TYPE_HARD); + attr_id = iod_link.u.iod_id; + + /* remove attribute with old name */ + kv.key = (void *)old_name; + kv.key_len = strlen(old_name); + kvs.kv = &kv; + kvs.cs = NULL; + kvs.ret = &ret; + if(iod_kv_unlink_keys(attr_kv_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); + + /* insert attribute with new name */ + if(H5VL_iod_insert_new_link(attr_kv_oh.wr_oh, wtid, new_name, + H5L_TYPE_HARD, &attr_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close the Attribute KV object */ + if(iod_obj_close(attr_kv_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTFREE, FAIL, "can't close object"); + if(iod_obj_close(attr_kv_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTFREE, FAIL, "can't close object"); + +done: + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr rename, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (attr_rename_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_rename_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_remove_cb + * + * Purpose: Removes iod HDF5 attribute. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_remove_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_op_in_t *input = (attr_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_handles_t obj_oh; /* current object handle accessed */ + iod_handles_t attr_kv_oh; /* KV handle holding attributes for object */ + iod_handle_t attr_oh; + iod_obj_id_t obj_id, attr_id; + const char *loc_name = input->path; /* path to start hierarchy traversal */ + const char *attr_name = input->attr_name; /* attribute's name */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_kv_params_t kvs; + iod_kv_t kv; + H5VL_iod_link_t iod_link; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_ret_t ret; + iod_checksum_t cs; + int step = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute Remove %s\n", attr_name); +#endif + + /* Open the object where the attribute needs to be removed. */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, loc_name, rtid, + cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if(loc_id != obj_id) { + /* get scratch pad of the parent */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* if attribute KV does not exist, return error*/ + if(IOD_OBJ_INVALID == sp[1]) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "Object has no attributes"); + + /* open the attribute KV in scratch pad */ + if (iod_obj_open_read(coh, sp[1], wtid, NULL /*hints*/, &attr_kv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, sp[1], wtid, NULL /*hints*/, &attr_kv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the attribute KV */ + if (iod_obj_open_read(coh, input->loc_attrkv_id, wtid, NULL /*hints*/, &attr_kv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, input->loc_attrkv_id, wtid, NULL /*hints*/, &attr_kv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + step ++; + + /* get attribute ID */ + if(H5VL_iod_get_metadata(attr_kv_oh.rd_oh, rtid, H5VL_IOD_LINK, + attr_name, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve Attribute ID from parent KV store"); + + HDassert(iod_link.link_type == H5L_TYPE_HARD); + attr_id = iod_link.u.iod_id; + + /* remove metadata KV of attribute */ + /* open the attribute */ + if (iod_obj_open_read(coh, attr_id, wtid, NULL /*hints*/, &attr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + step ++; + + /* get scratch pad of the attribute */ + if(iod_obj_get_scratch(attr_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + /* close the attribute oh */ + iod_obj_close(attr_oh, NULL, NULL); + + step --; + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + ret = iod_obj_unlink(coh, sp[0], wtid, NULL); + if(ret < 0) { + fprintf(stderr, "ret %d error %s\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink MDKV of attribute object"); + } + + /* remove attribute */ + kv.key = (void *)attr_name; + kv.key_len = strlen(attr_name); + kvs.kv = &kv; + kvs.cs = NULL; + kvs.ret = &ret; + if(iod_kv_unlink_keys(attr_kv_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); + + /* close the Attribute KV object */ + iod_obj_close(attr_kv_oh.rd_oh, NULL, NULL); + iod_obj_close(attr_kv_oh.wr_oh, NULL, NULL); + + step --; + + ret = iod_obj_unlink(coh, attr_id, wtid, NULL); + if(ret != 0) { + fprintf(stderr, "ret %d error %s\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink object"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr remove, sending response to client\n"); +#endif + + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != obj_oh.rd_oh.cookie) { + iod_obj_close(obj_oh.rd_oh, NULL, NULL); + } + + if(step == 2) { + /* close the attribute oh */ + iod_obj_close(attr_oh, NULL, NULL); + step --; + } + if(step == 1) { + /* close the Attribute KV object */ + iod_obj_close(attr_kv_oh.rd_oh, NULL, NULL); + iod_obj_close(attr_kv_oh.wr_oh, NULL, NULL); + step --; + } + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (attr_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_remove_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_close_cb + * + * Purpose: Closes iod HDF5 attribute. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_attr_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + attr_close_in_t *input = (attr_close_in_t *)op_data->input; + iod_handles_t iod_oh = input->iod_oh; /* iod handle to close */ + //iod_obj_id_t iod_id = input->iod_id; /* iod id of object to close */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start attribute Close %"PRIu64" %"PRIu64"\n", + iod_oh.rd_oh.cookie, iod_oh.wr_oh.cookie); +#endif + + if((iod_obj_close(iod_oh.rd_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if((iod_obj_close(iod_oh.wr_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with attr close, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (attr_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_attr_close_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_client.c b/src/H5VLiod_client.c new file mode 100644 index 0000000..1940816 --- /dev/null +++ b/src/H5VLiod_client.c @@ -0,0 +1,3015 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.org> + * + * Purpose: IOD plugin client code + */ + +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Dpkg.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspaces */ +#include "H5VLprivate.h" /* VOL plugins */ +#include "H5VLiod.h" /* Iod VOL plugin */ +#include "H5VLiod_common.h" +#include "H5VLiod_client.h" +#include "H5WBprivate.h" /* Wrapped Buffers */ + +#ifdef H5_HAVE_EFF + +H5FL_EXTERN(H5VL_iod_file_t); +H5FL_EXTERN(H5VL_iod_attr_t); +H5FL_EXTERN(H5VL_iod_group_t); +H5FL_EXTERN(H5VL_iod_dset_t); +H5FL_EXTERN(H5VL_iod_dtype_t); + +/* H5Diterate op-data for VL traversal */ +typedef struct { + size_t buf_size; + uint8_t *buf_ptr; + void **off; + size_t *len; + int curr_seq; + size_t *str_len; /* used only for VL strings */ +} H5VL_iod_pre_write_t; + +static herr_t H5VL__iod_vl_map_get_finalize(size_t buf_size, void *read_buf, void *user_buf, + hid_t mem_type_id); + +herr_t +H5VL_iod_request_decr_rc(H5VL_iod_request_t *request) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + request->ref_count --; + + if(0 == request->ref_count) { + //request->parent_reqs = (H5VL_iod_request_t **)H5MM_xfree(request->parent_reqs); + request = (H5VL_iod_request_t *)H5MM_xfree(request); + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_add + * + * Purpose: Adds a request pointer to the Doubly linked list on the + * file. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_add(H5VL_iod_file_t *file, H5VL_iod_request_t *request) +{ + H5VL_iod_req_info_t *req_info = request->trans_info; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(request); + + if (file->request_list_tail) { + file->request_list_tail->file_next = request; + request->file_prev = file->request_list_tail; + file->request_list_tail = request; + } + else { + file->request_list_head = request; + file->request_list_tail = request; + request->file_prev = NULL; + } + request->file_next = NULL; + file->num_req ++; + + if(req_info) { + if (req_info->tail) { + req_info->tail->trans_next = request; + request->trans_prev = req_info->tail; + req_info->tail = request; + } + else { + req_info->head = request; + req_info->tail = request; + request->trans_prev = NULL; + } + request->trans_next = NULL; + req_info->num_req ++; + + request->ref_count ++; + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_delete + * + * Purpose: Removes a request pointer from the Doubly linked list on the + * file. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_delete(H5VL_iod_file_t *file, H5VL_iod_request_t *request) +{ + H5VL_iod_request_t *prev; + H5VL_iod_request_t *next; + unsigned u; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(request); + + /* decrement ref count on parent requests */ + for(u=0 ; u<request->num_parents ; u++) { + /* Decrement ref count on request */ + H5VL_iod_request_decr_rc(request->parent_reqs[u]); + } + + request->parent_reqs = (H5VL_iod_request_t **)H5MM_xfree(request->parent_reqs); + + /* remove the request from the container link list */ + prev = request->file_prev; + next = request->file_next; + if (prev) { + if (next) { + prev->file_next = next; + next->file_prev = prev; + } + else { + prev->file_next = NULL; + file->request_list_tail = prev; + } + } + else { + if (next) { + next->file_prev = NULL; + file->request_list_head = next; + } + else { + file->request_list_head = NULL; + file->request_list_tail = NULL; + } + } + + if(request == request->obj->request) + request->obj->request = NULL; + request->file_prev = NULL; + request->file_next = NULL; + + file->num_req --; + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_wait + * + * Purpose: + * Waits for a particular request to complete. This will test + * the request completion using Mercury's test routine. If the + * request is still pending we test for completion of other requests in + * the file's linked list to try and keep making progress. Once the + * original requests completes, we remove it from the linked list + * and return. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_wait(H5VL_iod_file_t *file, H5VL_iod_request_t *request) +{ + H5VL_iod_request_t *cur_req = file->request_list_head; + int ret; + hg_status_t status; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(request); + HDassert(request->req); + + /* Loop to complete the request while poking through other requests on the + container to avoid deadlock. */ + while(1) { + HDassert(request->state == H5VL_IOD_PENDING); + /* test the operation status */ + ret = HG_Wait(*((hg_request_t *)request->req), 0, &status); + if(HG_FAIL == ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to wait on request\n"); + request->status = H5ES_STATUS_FAIL; + request->state = H5VL_IOD_COMPLETED; + H5VL_iod_request_delete(file, request); + break; + } + else { + if(status) { + request->status = H5ES_STATUS_SUCCEED; + request->state = H5VL_IOD_COMPLETED; + } + } + + /* if it has not completed, go through the list of requests on the container to + test progress */ + if(!status) { + H5VL_iod_request_t *tmp_req = NULL; + + if(cur_req) { + if(HG_FILE_CLOSE != cur_req->type && cur_req->req != request->req) { + hg_status_t tmp_status; + + tmp_req = cur_req->file_next; + + HDassert(cur_req->state == H5VL_IOD_PENDING); + ret = HG_Wait(*((hg_request_t *)cur_req->req), 0, &tmp_status); + if(HG_FAIL == ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to wait on request\n"); + cur_req->status = H5ES_STATUS_FAIL; + cur_req->state = H5VL_IOD_COMPLETED; + H5VL_iod_request_delete(file, cur_req); + } + else { + if(tmp_status) { + cur_req->status = H5ES_STATUS_SUCCEED; + cur_req->state = H5VL_IOD_COMPLETED; + if(H5VL_iod_request_complete(file, cur_req) < 0) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Operation %"PRIu64" Failed!\n", cur_req->axe_id); + } + } + } + } + /* next time, test the next request in the list */ + cur_req = tmp_req; + } + } + /* request complete, remove it from list & break */ + else { + if(H5VL_iod_request_complete(file, request) < 0) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Operation %"PRIu64" Failed!\n", request->axe_id); + } + break; + } + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_wait */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_wait_all + * + * Purpose: Wait and complete all the requests in the linked list. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_wait_all(H5VL_iod_file_t *file) +{ + H5VL_iod_request_t *cur_req = file->request_list_head; + hg_status_t status; + int ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Loop to complete all requests */ + while(cur_req) { + H5VL_iod_request_t *tmp_req = NULL; + + tmp_req = cur_req->file_next; + + HDassert(cur_req->state == H5VL_IOD_PENDING); + ret = HG_Wait(*((hg_request_t *)cur_req->req), HG_MAX_IDLE_TIME, &status); + if(HG_FAIL == ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to wait on request\n"); + cur_req->status = H5ES_STATUS_FAIL; + cur_req->state = H5VL_IOD_COMPLETED; + } + else { + if(!status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Wait timeout reached\n"); + cur_req->status = H5ES_STATUS_FAIL; + cur_req->state = H5VL_IOD_COMPLETED; + H5VL_iod_request_delete(file, cur_req); + goto done; + } + else { + cur_req->status = H5ES_STATUS_SUCCEED; + cur_req->state = H5VL_IOD_COMPLETED; + } + } + + if(H5VL_iod_request_complete(file, cur_req) < 0) + HERROR(H5E_FUNC, H5E_CANTINIT, "Operation %"PRIu64" Failed!\n", cur_req->axe_id); + + cur_req = tmp_req; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_request_wait_all */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_wait_some + * + * Purpose: Wait for some requests on the linked list, particularly + * the ones that are tracked with a particular object. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_wait_some(H5VL_iod_file_t *file, const void *object) +{ + H5VL_iod_request_t *cur_req = file->request_list_head; + hg_status_t status; + int ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Loop to complete some requests */ + while(cur_req) { + H5VL_iod_request_t *tmp_req; + + tmp_req = cur_req->file_next; + + /* If the request is pending on the object we want, complete it */ + if(cur_req->obj == object && + cur_req->state == H5VL_IOD_PENDING) { + ret = HG_Wait(*((hg_request_t *)cur_req->req), HG_MAX_IDLE_TIME, + &status); + if(HG_FAIL == ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to wait on request\n"); + cur_req->status = H5ES_STATUS_FAIL; + cur_req->state = H5VL_IOD_COMPLETED; + H5VL_iod_request_delete(file, cur_req); + } + else { + if(!status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Wait timeout reached\n"); + cur_req->status = H5ES_STATUS_FAIL; + cur_req->state = H5VL_IOD_COMPLETED; + H5VL_iod_request_delete(file, cur_req); + } + else { + cur_req->status = H5ES_STATUS_SUCCEED; + cur_req->state = H5VL_IOD_COMPLETED; + if(H5VL_iod_request_complete(file, cur_req) < 0) + HERROR(H5E_FUNC, H5E_CANTINIT, "Operation %"PRIu64" Failed!\n", cur_req->axe_id); + } + } + } + cur_req = tmp_req; + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_request_wait_some */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_complete + * + * Purpose: Completion calls for every type of request. This checks + * the return status from the server, and frees memory + * allocated by this request. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(req->state == H5VL_IOD_COMPLETED); + + switch(req->type) { + case HG_ANALYSIS_EXECUTE: + { + analysis_execute_out_t *output = (analysis_execute_out_t *)req->data; + + if(SUCCEED != output->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Analysis Execute failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + free(output); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_FILE_CREATE: + if(IOD_OH_UNDEFINED == req->obj->file->remote_file.coh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to create file\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + MPI_Barrier (file->comm); + H5VL_iod_request_delete(file, req); + break; + case HG_FILE_OPEN: + if(IOD_OH_UNDEFINED == req->obj->file->remote_file.coh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open file\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + H5P_genplist_t *plist = NULL; /* Property list pointer */ + hid_t rcxt_id; + + if(NULL == (plist = H5P_object_verify(file->fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") + + /* determine if we want to update the latest readable version + when the file is opened */ + if(H5P_get(plist, H5VL_ACQUIRE_RC_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set property value for rxct id"); + + if(FAIL != rcxt_id) { + H5RC_t *rc = NULL; + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + rc->c_version = file->remote_file.c_version; + rc->file = file; + } + + /* increment ref count on ID generated by Mercury encoding callback */ + if(H5I_inc_ref(req->obj->file->remote_file.fcpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + + H5VL_iod_request_delete(file, req); + break; + case HG_ATTR_CREATE: + { + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)req->obj; + + if(IOD_OH_UNDEFINED == attr->remote_attr.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to create Attribute\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_OPEN: + { + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)req->obj; + + if(IOD_OH_UNDEFINED == attr->remote_attr.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Attribute\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(attr->remote_attr.type_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(attr->remote_attr.space_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + H5VL_iod_request_delete(file, req); + break; + } + case HG_GROUP_CREATE: + { + H5VL_iod_group_t *group = (H5VL_iod_group_t *)req->obj; + + if(IOD_OH_UNDEFINED == group->remote_group.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to create Group\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_GROUP_OPEN: + { + H5VL_iod_group_t *group = (H5VL_iod_group_t *)req->obj; + + if(IOD_OH_UNDEFINED == group->remote_group.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Group\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(group->remote_group.gcpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_CREATE: + { + H5VL_iod_map_t *map = (H5VL_iod_map_t *)req->obj; + + if(IOD_OH_UNDEFINED == map->remote_map.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to create Map\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_OPEN: + { + H5VL_iod_map_t *map = (H5VL_iod_map_t *)req->obj; + + if(IOD_OH_UNDEFINED == map->remote_map.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Map\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(map->remote_map.mcpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(map->remote_map.keytype_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(map->remote_map.valtype_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_CREATE: + { + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + if(IOD_OH_UNDEFINED == dset->remote_dset.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to create Dataset\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_OPEN: + { + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + if(IOD_OH_UNDEFINED == dset->remote_dset.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Dataset\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(dset->remote_dset.dcpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(dset->remote_dset.type_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(dset->remote_dset.space_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_DTYPE_COMMIT: + { + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)req->obj; + + if(IOD_OH_UNDEFINED == dtype->remote_dtype.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to commit Datatype\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_DTYPE_OPEN: + { + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)req->obj; + + if(IOD_OH_UNDEFINED == dtype->remote_dtype.iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Datatype\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(dtype->remote_dtype.tcpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(H5I_inc_ref(dtype->remote_dtype.type_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_WRITE: + { + H5VL_iod_write_info_t *info = (H5VL_iod_write_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free dataset bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(*info->vl_len_bulk_handle != HG_BULK_NULL && + HG_SUCCESS != HG_Bulk_handle_free(*info->vl_len_bulk_handle)) { + fprintf(stderr, "failed to free dataset bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(SUCCEED != *((int *)info->status)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrr! Dataset Write Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(info->vl_segments) { + free(info->vl_segments); + info->vl_segments = NULL; + } + if(info->vl_lengths) { + free(info->vl_lengths); + info->vl_lengths = NULL; + } + + free(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info->vl_len_bulk_handle = (hg_bulk_t *)H5MM_xfree(info->vl_len_bulk_handle); + info = (H5VL_iod_write_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_READ: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + H5VL_iod_read_status_t *read_status = (H5VL_iod_read_status_t *)info->status; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free dataset bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + if(SUCCEED != read_status->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + uint32_t raw_cs_scope = info->raw_cs_scope; + + if(raw_cs_scope) { + uint64_t internal_cs = 0; + + /* calculate a checksum for the data recieved */ + internal_cs = H5S_checksum(info->buf_ptr, info->type_size, + (size_t)info->nelmts, info->space); + + /* verify data integrity */ + if((raw_cs_scope & H5_CHECKSUM_TRANSFER) && + internal_cs != read_status->cs) { + HERROR(H5E_FUNC, H5E_CANTINIT, + "Errrrr! Dataset Read integrity failure (expecting %"PRIu64" got %"PRIu64").\n", + read_status->cs, internal_cs); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } +#if H5VL_IOD_DEBUG + if(!raw_cs_scope & H5_CHECKSUM_TRANSFER) { + printf("NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA READ\n"); + } +#endif + + /* If the app gave us a buffer to store the checksum, then put it there */ + if(info->cs_ptr) + *info->cs_ptr = internal_cs; + } + } + + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + read_status = (H5VL_iod_read_status_t *)H5MM_xfree(read_status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_GET_VL_SIZE: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + H5VL_iod_read_status_t *status = (H5VL_iod_read_status_t *)info->status; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle) || + SUCCEED != status->ret) { + + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrrr! Dataset Read Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + + if(H5Sclose(info->file_space_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(H5Tclose(info->mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + status = (H5VL_iod_read_status_t *)H5MM_xfree(status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); + } + else { + dset_io_in_t input; + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + hid_t rcxt_id; + H5RC_t *rc; + H5P_genplist_t *plist = NULL; + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + hg_request_t hg_req; + hg_status_t hg_status; + + /* MSC - Need to fix this to allow for nested VLs */ + HDassert(info->vl_lengths_size == status->buf_size); + + /* Create segments from vl lengths */ + if(H5VL_iod_create_segments_recv((char *)info->buf_ptr, info->type_info, + (size_t)info->nelmts, &segments, &num_segments, + info->vl_lengths, info->vl_lengths_size, + NULL, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create segments for bulk data transfer"); + HDassert(segments); + + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READWRITE, + info->bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data handle"); + + /* get the context ID */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(info->dxpl_id))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + if(H5P_get(plist, H5VL_CONTEXT_ID, &rcxt_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for trans_id"); + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + /* Fill input structure for reading data */ + input.coh = file->remote_file.coh; + input.iod_oh = dset->remote_dset.iod_oh; + input.iod_id = dset->remote_dset.iod_id; + input.mdkv_id = dset->remote_dset.mdkv_id; + input.bulk_handle = *info->bulk_handle; + input.vl_len_bulk_handle = HG_BULK_NULL; + input.checksum = 0; + input.dxpl_id = info->dxpl_id; + input.space_id = info->file_space_id; + input.mem_type_id = info->mem_type_id; + input.dset_type_id = dset->remote_dset.type_id; + input.rcxt_num = rc->c_version; + input.cs_scope = dset->common.file->md_integrity_scope; + input.trans_num = 0; + input.axe_id = info->axe_id + 1; + input.axe_info.axe_id = info->axe_id; + input.axe_info.start_range = 0; + input.axe_info.count = 0; + input.axe_info.num_parents = 0; + input.axe_info.parent_axe_ids = NULL; + + /* forward the call to the ION */ + if(HG_Forward(info->ion_target, info->read_id, &input, info->status, &hg_req) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to ship operation"); + + if(HG_FAIL == HG_Wait(hg_req, HG_MAX_IDLE_TIME, &hg_status)) { + fprintf(stderr, "failed to wait on request\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + HG_Request_free(hg_req); + HG_Bulk_handle_free(*info->bulk_handle); + + if(segments) { + free(segments); + segments = NULL; + } + } + + if(info->vl_lengths) { + HDfree(info->vl_lengths); + info->vl_lengths = NULL; + } + if(H5Sclose(info->file_space_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(H5Tclose(info->mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + status = (H5VL_iod_read_status_t *)H5MM_xfree(status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_WRITE: + case HG_ATTR_READ: + { + H5VL_iod_attr_io_info_t *info = (H5VL_iod_attr_io_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free attribute bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + if(SUCCEED != *((int *)info->status)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Attribute I/O Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + HDfree(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_attr_io_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_SET: + { + H5VL_iod_map_set_info_t *info = (H5VL_iod_map_set_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->value_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free Map Value bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(SUCCEED != *((int *)info->status)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Errrr! MAP set Failure Reported from Server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(info->status); + info->status = NULL; + info->value_handle = (hg_bulk_t *)H5MM_xfree(info->value_handle); + info = (H5VL_iod_map_set_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_DELETE: + { + int *status = (int *)req->data; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "MAP delete failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_GET: + { + H5VL_iod_map_io_info_t *info = (H5VL_iod_map_io_info_t *)req->data; + map_get_out_t *output = info->output; + + if(SUCCEED != output->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "MAP get failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + + /* free stuff associated with request */ + info->value_handle = (hg_bulk_t *)H5MM_xfree(info->value_handle); + if(H5Tclose(info->val_mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Tclose(info->key_mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + + free(info->output); + info->output = NULL; + info = (H5VL_iod_map_io_info_t *)H5MM_xfree(info); + req->data = NULL; + + /* remove request from file list */ + H5VL_iod_request_delete(file, req); + break; + } + else { + /* If the data is not VL, then just free resources and + remove the request */ + if(!info->val_is_vl) { + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->value_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free value bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + uint64_t internal_cs = 0; + uint32_t raw_cs_scope = info->raw_cs_scope; + + /* calculate a checksum for the data recieved */ + internal_cs = H5_checksum_crc64(info->val_ptr, info->val_size); + + /* verify data integrity */ + if((raw_cs_scope & H5_CHECKSUM_TRANSFER) && + internal_cs != output->val_cs) { + HERROR(H5E_FUNC, H5E_CANTINIT, + "Errrrr! MAP Get integrity failure (expecting %"PRIu64" got %"PRIu64").\n", + output->val_cs, internal_cs); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } +#if H5VL_IOD_DEBUG + if(!raw_cs_scope & H5_CHECKSUM_TRANSFER) { + printf("NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA READ\n"); + } +#endif + /* If the app gave us a buffer to store the checksum, then put it there */ + if(info->val_cs_ptr) + *info->val_cs_ptr = internal_cs; + } + + free(info->output); + info->output = NULL; + info->value_handle = (hg_bulk_t *)H5MM_xfree(info->value_handle); + info = (H5VL_iod_map_io_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + else { + /* If this is the second roundtrip with the VL + data, scatter it in the user buffer */ + if(info->val_size && output->val_size) { + HDassert(info->val_size == output->val_size); + + /* scatter the data into the user's buffer */ + if(H5VL__iod_vl_map_get_finalize(output->val_size, + info->read_buf, + (void *)info->val_ptr, + info->val_mem_type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to store VL data in user buffer"); + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + /* if the data is VL, then we need to submit another + get operation this time to get the actual data */ + else { + void *value_buf = NULL; + H5VL_iod_map_t *map = (H5VL_iod_map_t *)req->obj; + map_get_in_t input; + H5RC_t *rc = NULL; + H5VL_iod_map_io_info_t vl_read_info; + + /* get the RC object */ + if(NULL == (rc = (H5RC_t *)H5I_object_verify(info->rcxt_id, H5I_RC))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a READ CONTEXT ID"); + + if(NULL == (value_buf = (void *)HDmalloc(output->val_size))) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate VL recieve buffer"); + + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(value_buf, output->val_size, + HG_BULK_READWRITE, info->value_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + + /* Fill input structure */ + input.coh = file->remote_file.coh; + input.iod_oh = map->remote_map.iod_oh; + input.iod_id = map->remote_map.iod_id; + input.dxpl_id = info->dxpl_id; + input.key_memtype_id = info->key_mem_type_id; + input.key_maptype_id = map->remote_map.keytype_id; + input.val_memtype_id = info->val_mem_type_id; + input.val_maptype_id = map->remote_map.valtype_id; + input.key.buf_size = info->key.buf_size; + input.key.buf = info->key.buf; + input.val_is_vl = TRUE; + input.val_size = output->val_size; + input.val_handle = *info->value_handle; + input.rcxt_num = rc->c_version; + input.cs_scope = map->common.file->md_integrity_scope; + + vl_read_info.output = output; + vl_read_info.value_handle = info->value_handle; + vl_read_info.val_is_vl = TRUE; + vl_read_info.val_ptr = info->val_ptr; + vl_read_info.val_mem_type_id = info->val_mem_type_id; + vl_read_info.val_size = input.val_size; + vl_read_info.read_buf = value_buf; + + /* remove request from file list */ + H5VL_iod_request_delete(file, req); + + if(H5VL__iod_create_and_forward(info->map_get_id, HG_MAP_GET, + (H5VL_iod_object_t *)map, 0, + 0, NULL, (H5VL_iod_req_info_t *)rc, + &input, output, &vl_read_info, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to create and ship map get"); + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->value_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free value bulk handle\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + /* free stuff associated with request */ + info->value_handle = (hg_bulk_t *)H5MM_xfree(info->value_handle); + HDfree(value_buf); + if(H5Tclose(info->val_mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Tclose(info->key_mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + + free(info->output); + info->output = NULL; + info = (H5VL_iod_map_io_info_t *)H5MM_xfree(info); + req->data = NULL; + break; + } + } + } + } + case HG_MAP_GET_COUNT: + { + hsize_t *count = (hsize_t *)req->data; + + if(*count == IOD_COUNT_UNDEFINED) { + HERROR(H5E_FUNC, H5E_CANTINIT, "MAP get_count failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_EXISTS: + { + H5VL_iod_exists_info_t *info = (H5VL_iod_exists_info_t *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + if(info->server_ret < 0) { + HERROR(H5E_FUNC, H5E_CANTINIT, "MAP exists failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else if (0 == info->server_ret) + *info->user_bool = FALSE; + else + *info->user_bool = TRUE; + + req->data = NULL; + obj->request = NULL; + info = (H5VL_iod_exists_info_t *)H5MM_xfree(info); + H5VL_iod_request_delete(file, req); + break; + } + case HG_FILE_CLOSE: + { + int *status = (int *)req->data; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "FILE close failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + if(0 == file->my_rank) + MPI_Barrier (file->comm); + + free(status); + req->data = NULL; + file->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free everything */ + free(file->file_name); + free(file->common.obj_name); + if(H5FD_mpi_comm_info_free(&file->comm, &file->info) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "Communicator/Info free failed"); + if(file->common.comment) + HDfree(file->common.comment); + if(file->fapl_id != H5P_FILE_ACCESS_DEFAULT && H5Pclose(file->fapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(file->remote_file.fcpl_id != H5P_FILE_CREATE_DEFAULT && + H5Pclose(file->remote_file.fcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + file = H5FL_FREE(H5VL_iod_file_t, file); + break; + } + case HG_ATTR_RENAME: + { + int *status = (int *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "ATTR rename failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + obj->request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_REMOVE: + { + int *status = (int *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "ATTR remove failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + obj->request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_EXISTS: + case HG_LINK_EXISTS: + case HG_OBJECT_EXISTS: + { + htri_t *ret = (htri_t *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + if(*ret < 0) { + HERROR(H5E_FUNC, H5E_CANTINIT, "EXIST OP failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + obj->request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "ATTR close failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + attr->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free attr components */ + if(attr->common.obj_name) + free(attr->common.obj_name); + if(attr->loc_name) + free(attr->loc_name); + if(attr->common.comment) + HDfree(attr->common.comment); + if(H5Tclose(attr->remote_attr.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(H5Sclose(attr->remote_attr.space_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dspace"); + attr = H5FL_FREE(H5VL_iod_attr_t, attr); + break; + } + case HG_GROUP_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_group_t *grp = (H5VL_iod_group_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "GROUP CLOSE failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + grp->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free group components */ + if(grp->common.obj_name) + free(grp->common.obj_name); + if(grp->common.comment) + HDfree(grp->common.comment); + if(grp->gapl_id != H5P_GROUP_ACCESS_DEFAULT && H5Pclose(grp->gapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(grp->remote_group.gcpl_id != H5P_GROUP_CREATE_DEFAULT && + H5Pclose(grp->remote_group.gcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + grp = H5FL_FREE(H5VL_iod_group_t, grp); + break; + } + case HG_DSET_SET_EXTENT: + { + int *status = (int *)req->data; + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "DATASET set extent failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + dset->common.request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "DATASET %s CLOSE failed at the server\n", + dset->common.obj_name); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + /* free dset components */ + if(dset->common.obj_name) + free(dset->common.obj_name); + if(dset->common.comment) + HDfree(dset->common.comment); + if(H5Tclose(dset->remote_dset.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(H5Sclose(dset->remote_dset.space_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dspace"); + if(dset->remote_dset.dcpl_id != H5P_DATASET_CREATE_DEFAULT) { + if(H5Pclose(dset->remote_dset.dcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + } + if(dset->dapl_id != H5P_DATASET_ACCESS_DEFAULT) { + if(H5Pclose(dset->dapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + } + + free(status); + req->data = NULL; + dset->common.request = NULL; + H5VL_iod_request_delete(file, req); + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + break; + } + case HG_MAP_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_map_t *map = (H5VL_iod_map_t *)req->obj; + + if(H5VL_iod_request_wait_some(map->common.file, map) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't wait on all object requests"); + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "MAP close failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + map->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free map components */ + if(map->common.obj_name) + free(map->common.obj_name); + if(map->common.comment) + HDfree(map->common.comment); + if(H5Tclose(map->remote_map.keytype_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(H5Tclose(map->remote_map.valtype_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + map = H5FL_FREE(H5VL_iod_map_t, map); + break; + } + case HG_DTYPE_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)req->obj; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "datatype close failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + dtype->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free dtype components */ + if(dtype->common.obj_name) + free(dtype->common.obj_name); + if(dtype->common.comment) + HDfree(dtype->common.comment); + if(dtype->remote_dtype.tcpl_id != H5P_DATATYPE_CREATE_DEFAULT && + H5Pclose(dtype->remote_dtype.tcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(dtype->tapl_id != H5P_DATATYPE_ACCESS_DEFAULT && + H5Pclose(dtype->tapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(H5Tclose(dtype->remote_dtype.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + break; + } + case HG_LINK_CREATE: + case HG_LINK_MOVE: + case HG_LINK_REMOVE: + case HG_OBJECT_SET_COMMENT: + case HG_OBJECT_COPY: + { + int *status = (int *)req->data; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Link operation failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_LINK_GET_INFO: + { + H5L_ff_info_t *linfo = (H5L_ff_info_t *)req->data; + + if(linfo->type == H5L_TYPE_ERROR) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Link get_info failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_OBJECT_GET_INFO: + { + H5O_ff_info_t *oinfo = (H5O_ff_info_t *)req->data; + + if(oinfo->type == H5O_TYPE_UNKNOWN) { + HERROR(H5E_FUNC, H5E_CANTINIT, "OBJECT get_info failed at the server\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_LINK_GET_VAL: + { + link_get_val_out_t *result = (link_get_val_out_t *)req->data; + + if(SUCCEED != result->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "get comment failed\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + /* Free Mercury request */ + if(HG_Request_free(*((hg_request_t *)req->req)) != HG_SUCCESS) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + + free(result); + req->data = NULL; + H5VL_iod_request_delete(file, req); + HGOTO_DONE(ret_value); + //break; + } + case HG_OBJECT_OPEN_BY_TOKEN: + { + iod_handles_t *oh = (iod_handles_t *)req->data; + + if(IOD_OH_UNDEFINED == (*oh).rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to Open object by token\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_OBJECT_OPEN: + { + H5VL_iod_remote_object_t *obj = (H5VL_iod_remote_object_t *)req->data; + + if(IOD_OH_UNDEFINED == obj->iod_oh.rd_oh.cookie) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to open Object\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + else { + /* increment ref count on IDs generated by Mercury encoding callback */ + if(H5I_inc_ref(obj->cpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + if(FAIL != obj->id1) { + if(H5I_inc_ref(obj->id1, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + if(FAIL != obj->id2) { + if(H5I_inc_ref(obj->id2, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count"); + } + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_OBJECT_GET_COMMENT: + { + object_get_comment_out_t *result = (object_get_comment_out_t *)req->data; + + if(SUCCEED != result->ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "get comment failed\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + /* Free Mercury request */ + if(HG_Request_free(*((hg_request_t *)req->req)) != HG_SUCCESS) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + + free(result); + H5VL_iod_request_delete(file, req); + HGOTO_DONE(ret_value); + //break; + } + case HG_RC_ACQUIRE: + { + H5VL_iod_rc_info_t *rc_info = (H5VL_iod_rc_info_t *)req->data; + + if(SUCCEED != rc_info->result.ret) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Failed to Acquire Read Context %"PRIu64"\n", *(rc_info->c_version_ptr)); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + rc_info->read_cxt->c_version = rc_info->result.c_version; + *rc_info->c_version_ptr = rc_info->result.c_version; + rc_info->read_cxt->req_info.request = NULL; + rc_info = (H5VL_iod_rc_info_t *)H5MM_xfree(rc_info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_RC_RELEASE: + case HG_RC_PERSIST: + case HG_RC_SNAPSHOT: + { + int *status = (int *)req->data; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Failed to Read Context OP\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_TR_START: + { + H5VL_iod_tr_info_t *tr_info = (H5VL_iod_tr_info_t *)req->data; + + if(SUCCEED != tr_info->result) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Failed to start transaction %"PRIu64"\n", tr_info->tr->trans_num); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + tr_info->tr->req_info.request = NULL; + tr_info = (H5VL_iod_tr_info_t *)H5MM_xfree(tr_info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_TR_FINISH: + case HG_TR_SET_DEPEND: + case HG_TR_SKIP: + case HG_TR_ABORT: + case HG_EVICT: + { + int *status = (int *)req->data; + + if(SUCCEED != *status) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Failed transaction OP\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_PREFETCH: + { + hrpl_t *replica_id = (hrpl_t *)req->data; + + if(0 == *replica_id) { + HERROR(H5E_FUNC, H5E_CANTINIT, "Failed transaction OP\n"); + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + } + + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_LINK_ITERATE: + case HG_OBJECT_VISIT: + case HG_MAP_ITERATE: + default: + req->status = H5ES_STATUS_FAIL; + req->state = H5VL_IOD_COMPLETED; + req->data = NULL; + H5VL_iod_request_delete(file, req); + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Request Type not supported"); + } + + /* Free Mercury request */ + if(HG_Request_free(*((hg_request_t *)req->req)) != HG_SUCCESS) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_request_complete */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_request_cancel + * + * Purpose: Cancels a particular request by freeing memory + * associated with it. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_request_cancel(H5VL_iod_file_t *file, H5VL_iod_request_t *req) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(req->state == H5VL_IOD_CANCELLED); + + switch(req->type) { + case HG_ANALYSIS_EXECUTE: + { + analysis_execute_out_t *output = (analysis_execute_out_t *)req->data; + + free(output); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_WRITE: + { + H5VL_iod_write_info_t *info = (H5VL_iod_write_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + fprintf(stderr, "failed to free bulk handle\n"); + } + + if(info->vl_segments) { + HDfree(info->vl_segments); + info->vl_segments = NULL; + } + if(info->vl_lengths) { + HDfree(info->vl_lengths); + info->vl_lengths = NULL; + } + + HDfree(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info->vl_len_bulk_handle = (hg_bulk_t *)H5MM_xfree(info->vl_len_bulk_handle); + info = (H5VL_iod_write_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_GET_VL_SIZE: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + + if(H5Sclose(info->file_space_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + if(H5Tclose(info->mem_type_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype"); + if(H5Pclose(info->dxpl_id) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTRELEASE, FAIL, "unable to release plist"); + } + case HG_DSET_READ: + { + H5VL_iod_read_info_t *info = (H5VL_iod_read_info_t *)req->data; + + /* Free memory handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(*info->bulk_handle)) { + HERROR(H5E_FUNC, H5E_CANTINIT, "failed to free bulk handle\n"); + } + + H5VL_iod_type_info_reset(info->type_info); + info->type_info = (H5VL_iod_type_info_t *)H5MM_xfree(info->type_info); + if(info->space && H5S_close(info->space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + info->status = (H5VL_iod_read_status_t *)H5MM_xfree(info->status); + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_read_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_WRITE: + case HG_ATTR_READ: + { + H5VL_iod_attr_io_info_t *info = (H5VL_iod_attr_io_info_t *)req->data; + + HDfree(info->status); + info->status = NULL; + info->bulk_handle = (hg_bulk_t *)H5MM_xfree(info->bulk_handle); + info = (H5VL_iod_attr_io_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_FILE_CREATE: + case HG_FILE_OPEN: + case HG_FILE_CLOSE: + { + int *status = (int *)req->data; + + free(status); + req->data = NULL; + file->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free everything */ + free(file->file_name); + free(file->common.obj_name); + if(H5FD_mpi_comm_info_free(&file->comm, &file->info) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "Communicator/Info free failed"); + if(file->common.comment) + HDfree(file->common.comment); + if(file->fapl_id != H5P_FILE_ACCESS_DEFAULT && H5Pclose(file->fapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(file->remote_file.fcpl_id != 0 && + file->remote_file.fcpl_id != H5P_FILE_CREATE_DEFAULT && + H5Pclose(file->remote_file.fcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + file = H5FL_FREE(H5VL_iod_file_t, file); + break; + } + case HG_ATTR_REMOVE: + case HG_ATTR_RENAME: + { + int *status = (int *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + free(status); + req->data = NULL; + obj->request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_EXISTS: + { + H5VL_iod_exists_info_t *info = (H5VL_iod_exists_info_t *)req->data; + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + req->data = NULL; + obj->request = NULL; + info = (H5VL_iod_exists_info_t *)H5MM_xfree(info); + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_EXISTS: + case HG_LINK_EXISTS: + case HG_OBJECT_EXISTS: + case HG_MAP_GET_COUNT: + { + H5VL_iod_object_t *obj = (H5VL_iod_object_t *)req->obj; + + req->data = NULL; + obj->request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_ATTR_CREATE: + case HG_ATTR_OPEN: + case HG_ATTR_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_attr_t *attr = (H5VL_iod_attr_t *)req->obj; + + free(status); + req->data = NULL; + attr->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free attr components */ + if(attr->common.obj_name) + free(attr->common.obj_name); + if(attr->loc_name) + free(attr->loc_name); + if(attr->common.comment) + HDfree(attr->common.comment); + if(attr->remote_attr.type_id != 0 && + H5Tclose(attr->remote_attr.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(attr->remote_attr.space_id != 0 && + H5Sclose(attr->remote_attr.space_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dspace"); + attr = H5FL_FREE(H5VL_iod_attr_t, attr); + break; + } + case HG_GROUP_CREATE: + case HG_GROUP_OPEN: + case HG_GROUP_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_group_t *grp = (H5VL_iod_group_t *)req->obj; + + free(status); + req->data = NULL; + grp->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free group components */ + if(grp->common.obj_name) + free(grp->common.obj_name); + if(grp->common.comment) + HDfree(grp->common.comment); + if(grp->gapl_id != H5P_GROUP_ACCESS_DEFAULT && H5Pclose(grp->gapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(grp->remote_group.gcpl_id != 0 && + grp->remote_group.gcpl_id != H5P_GROUP_CREATE_DEFAULT && + H5Pclose(grp->remote_group.gcpl_id) < 0) { + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + } + grp = H5FL_FREE(H5VL_iod_group_t, grp); + break; + } + case HG_DSET_SET_EXTENT: + { + int *status = (int *)req->data; + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + free(status); + req->data = NULL; + dset->common.request = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_DSET_CREATE: + case HG_DSET_OPEN: + case HG_DSET_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_dset_t *dset = (H5VL_iod_dset_t *)req->obj; + + free(status); + req->data = NULL; + dset->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free dset components */ + if(dset->common.obj_name) + free(dset->common.obj_name); + if(dset->common.comment) + HDfree(dset->common.comment); + if(dset->remote_dset.dcpl_id != 0 && + dset->remote_dset.dcpl_id != H5P_DATASET_CREATE_DEFAULT && + H5Pclose(dset->remote_dset.dcpl_id) < 0) { + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + } + if(dset->dapl_id != H5P_DATASET_ACCESS_DEFAULT && + H5Pclose(dset->dapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(dset->remote_dset.type_id != 0 && + H5Tclose(dset->remote_dset.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(dset->remote_dset.space_id != 0 && + H5Sclose(dset->remote_dset.space_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dspace"); + dset = H5FL_FREE(H5VL_iod_dset_t, dset); + break; + } + case HG_MAP_CREATE: + case HG_MAP_OPEN: + case HG_MAP_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_map_t *map = (H5VL_iod_map_t *)req->obj; + + free(status); + req->data = NULL; + map->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free map components */ + if(map->common.obj_name) + free(map->common.obj_name); + if(map->common.comment) + HDfree(map->common.comment); + if(H5Tclose(map->remote_map.keytype_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + if(H5Tclose(map->remote_map.valtype_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + map = H5FL_FREE(H5VL_iod_map_t, map); + break; + } + case HG_DTYPE_COMMIT: + case HG_DTYPE_OPEN: + case HG_DTYPE_CLOSE: + { + int *status = (int *)req->data; + H5VL_iod_dtype_t *dtype = (H5VL_iod_dtype_t *)req->obj; + + free(status); + req->data = NULL; + dtype->common.request = NULL; + H5VL_iod_request_delete(file, req); + + /* free dtype components */ + if(dtype->common.obj_name) + free(dtype->common.obj_name); + if(dtype->common.comment) + HDfree(dtype->common.comment); + if(dtype->remote_dtype.tcpl_id != 0 && + dtype->remote_dtype.tcpl_id != H5P_DATATYPE_CREATE_DEFAULT && + H5Pclose(dtype->remote_dtype.tcpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(dtype->tapl_id != H5P_DATATYPE_ACCESS_DEFAULT && + H5Pclose(dtype->tapl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close plist"); + if(dtype->remote_dtype.type_id != 0 && + H5Tclose(dtype->remote_dtype.type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "failed to close dtype"); + dtype = H5FL_FREE(H5VL_iod_dtype_t, dtype); + break; + } + + case HG_MAP_GET: + { + map_get_out_t *output = (map_get_out_t *)req->data; + + free(output); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_SET: + { + H5VL_iod_map_set_info_t *info = (H5VL_iod_map_set_info_t *)req->data; + + free(info->status); + info->status = NULL; + info->value_handle = (hg_bulk_t *)H5MM_xfree(info->value_handle); + info = (H5VL_iod_map_set_info_t *)H5MM_xfree(info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_MAP_DELETE: + case HG_LINK_CREATE: + case HG_LINK_MOVE: + case HG_LINK_REMOVE: + case HG_OBJECT_SET_COMMENT: + case HG_OBJECT_COPY: + { + int *status = (int *)req->data; + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_OBJECT_GET_COMMENT: + { + object_get_comment_out_t *result = (object_get_comment_out_t *)req->data; + + free(result); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_OBJECT_OPEN_BY_TOKEN: + case HG_OBJECT_OPEN: + case HG_LINK_GET_INFO: + case HG_OBJECT_GET_INFO: + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + case HG_LINK_GET_VAL: + { + link_get_val_out_t *result = (link_get_val_out_t *)req->data; + + free(result); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_RC_ACQUIRE: + { + H5VL_iod_rc_info_t *rc_info = (H5VL_iod_rc_info_t *)req->data; + + rc_info = (H5VL_iod_rc_info_t *)H5MM_xfree(rc_info); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_RC_RELEASE: + case HG_RC_PERSIST: + case HG_RC_SNAPSHOT: + case HG_TR_START: + case HG_TR_FINISH: + case HG_TR_SET_DEPEND: + case HG_TR_SKIP: + case HG_TR_ABORT: + case HG_EVICT: + { + int *status = (int *)req->data; + + free(status); + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + } + case HG_PREFETCH: + req->data = NULL; + H5VL_iod_request_delete(file, req); + break; + case HG_LINK_ITERATE: + case HG_OBJECT_VISIT: + case HG_MAP_ITERATE: + default: + H5VL_iod_request_delete(file, req); + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Request Type not supported"); + } + + /* Free Mercury request */ + if(HG_Request_free(*((hg_request_t *)req->req)) != HG_SUCCESS) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "Can't Free Mercury Request"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_request_cancel */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_obj_requests + * + * Purpose: returns the number of requests that are associated + * with a particular object. If the parent array is not NULL, + * the request pointers are stored. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_get_obj_requests(H5VL_iod_object_t *obj, /*IN/OUT*/ size_t *count, + /*OUT*/ H5VL_iod_request_t **parent_reqs) +{ + H5VL_iod_file_t *file = obj->file; + H5VL_iod_request_t *cur_req = file->request_list_head; + size_t size = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + while(cur_req) { + /* If the request is pending on the object we want, add its axe_id */ + if(cur_req->obj == obj) { + if(cur_req->status == H5ES_STATUS_IN_PROGRESS) { + if(NULL != parent_reqs) { + parent_reqs[size] = cur_req; + cur_req->ref_count ++; + } + size ++; + } + } + cur_req = cur_req->file_next; + } + + *count = size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_get_obj_requests */ + +herr_t +H5VL_iod_get_loc_info(H5VL_iod_object_t *obj, iod_obj_id_t *iod_id, + iod_handles_t *iod_oh, iod_obj_id_t *mdkv_id, + iod_obj_id_t *attrkv_id) +{ + iod_obj_id_t id, md, at; + iod_handles_t oh; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + switch(obj->obj_type) { + case H5I_FILE: + oh = obj->file->remote_file.root_oh; + id = obj->file->remote_file.root_id; + md = obj->file->remote_file.mdkv_id; + at = obj->file->remote_file.attrkv_id; + break; + case H5I_GROUP: + oh = ((const H5VL_iod_group_t *)obj)->remote_group.iod_oh; + id = ((const H5VL_iod_group_t *)obj)->remote_group.iod_id; + md = ((const H5VL_iod_group_t *)obj)->remote_group.mdkv_id; + at = ((const H5VL_iod_group_t *)obj)->remote_group.attrkv_id; + break; + case H5I_DATASET: + oh = ((const H5VL_iod_dset_t *)obj)->remote_dset.iod_oh; + id = ((const H5VL_iod_dset_t *)obj)->remote_dset.iod_id; + md = ((const H5VL_iod_dset_t *)obj)->remote_dset.mdkv_id; + at = ((const H5VL_iod_dset_t *)obj)->remote_dset.attrkv_id; + break; + case H5I_DATATYPE: + oh = ((const H5VL_iod_dtype_t *)obj)->remote_dtype.iod_oh; + id = ((const H5VL_iod_dtype_t *)obj)->remote_dtype.iod_id; + md = ((const H5VL_iod_dtype_t *)obj)->remote_dtype.mdkv_id; + at = ((const H5VL_iod_dtype_t *)obj)->remote_dtype.attrkv_id; + break; + case H5I_MAP: + oh = ((const H5VL_iod_map_t *)obj)->remote_map.iod_oh; + id = ((const H5VL_iod_map_t *)obj)->remote_map.iod_id; + md = ((const H5VL_iod_map_t *)obj)->remote_map.mdkv_id; + at = ((const H5VL_iod_map_t *)obj)->remote_map.attrkv_id; + break; + case H5I_UNINIT: + case H5I_BADID: + case H5I_DATASPACE: + case H5I_ATTR: + case H5I_REFERENCE: + case H5I_VFL: + case H5I_VOL: + case H5I_ES: + case H5I_RC: + case H5I_TR: + case H5I_QUERY: + case H5I_VIEW: + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + case H5I_NTYPES: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "bad location object"); + } + + if(iod_id) + *iod_id = id; + if(iod_oh) + *iod_oh = oh; + if(mdkv_id) + *mdkv_id = md; + if(attrkv_id) + *attrkv_id = at; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_get_loc_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_parent_requests + * + * Purpose: Returns the parent requests associated with an object + * and transaction. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_get_parent_requests(H5VL_iod_object_t *obj, H5VL_iod_req_info_t *req_info, + H5VL_iod_request_t **parent_reqs, size_t *num_parents) +{ + size_t count = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(obj && obj->request && obj->request->status == H5ES_STATUS_IN_PROGRESS) { + parent_reqs[count] = obj->request; + obj->request->ref_count ++; + count ++; + } + + if(req_info && + req_info->request && + req_info->request->status == H5ES_STATUS_IN_PROGRESS) { + parent_reqs[count] = req_info->request; + req_info->request->ref_count ++; + count ++; + } + + *num_parents += count; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5VL_iod_get_parent_requests */ + +herr_t +H5VL_iod_gen_obj_id(int myrank, int nranks, uint64_t cur_index, + iod_obj_type_t type, uint64_t *id) +{ + herr_t ret_value = SUCCEED; + uint64_t tmp_id; + + FUNC_ENTER_NOAPI_NOINIT + + /* determine first the rank of the object with the first 60 bits + (IOD owns 60,61,62,63). */ + tmp_id = (uint32_t)myrank + ((uint32_t)nranks * cur_index); + + /* toggle the object type bits */ + switch(type) { + case IOD_OBJ_ARRAY: + IOD_OBJID_SETTYPE(tmp_id, IOD_OBJ_ARRAY) + break; + case IOD_OBJ_KV: + IOD_OBJID_SETTYPE(tmp_id, IOD_OBJ_KV) + break; + case IOD_OBJ_BLOB: + /* This is for HDF5 committed datatypes and not for VLEN BLOBs */ + tmp_id &= ~(((uint64_t)0x1) << 59); + IOD_OBJID_SETTYPE(tmp_id, IOD_OBJ_BLOB) + break; + case IOD_OBJ_ANY: + case IOD_OBJ_INVALID: + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "bad object type"); + } + + /* toggle the owner bit */ + IOD_OBJID_SETOWNER_APP(tmp_id) + + *id = tmp_id; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_gen_obj_id */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_pre_write + * + * Depending on the type, this routine generates all the necessary + * parameters for forwarding a write call to IOD. It sets up the + * Mercury Bulk handle and checksums the data. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_pre_write(hid_t type_id, H5S_t *space, const void *buf, + /*out*/uint64_t *_checksum, + /*out*/uint64_t *_vlen_checksum, + /*out*/hg_bulk_t *bulk_handle, + /*out*/hg_bulk_t *vl_len_bulk_handle, + /*out*/hg_bulk_segment_t **_vl_segments, + /*out*/char **_vl_lengths) +{ + hsize_t buf_size = 0; + uint64_t checksum = 0; + size_t nelmts; + H5VL_iod_type_info_t type_info; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* Get type info */ + if(H5VL_iod_get_type_info(type_id, &type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + nelmts = (size_t)H5S_GET_SELECT_NPOINTS(space); + + if(type_info.vls) { + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; + + HDassert(_vl_segments); + HDassert(_vl_lengths); + + /* Create segments and vl lengths */ + if(H5VL_iod_create_segments_send((char *)buf, &type_info, nelmts, &segments, &num_segments, + &vl_lengths, &vl_lengths_size, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create segments for bulk data transfer"); + HDassert(segments); + HDassert(vl_lengths); + + /* Register vl lengths */ + if(HG_SUCCESS != HG_Bulk_handle_create(vl_lengths, vl_lengths_size, + HG_BULK_READ_ONLY, vl_len_bulk_handle)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data Handle for vlen lengths"); + + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data handle"); + + if(_checksum) + checksum = H5_checksum_crc64_segments(segments, num_segments); + if(_vlen_checksum) + *_vlen_checksum = H5_checksum_crc64(vl_lengths, vl_lengths_size); + + *_vl_segments = segments; + *_vl_lengths = vl_lengths; + } + else { + H5T_t *dt = NULL; + size_t type_size; + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + *vl_len_bulk_handle = HG_BULK_NULL; + type_size = H5T_get_size(dt); + + buf_size = type_size * nelmts; + + if(_checksum) { + checksum = H5S_checksum(buf, type_size, nelmts, space); + } + + /* If the memory selection is contiguous, create simple HG Bulk Handle */ + if(H5S_select_is_contiguous(space)) { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, (size_t)buf_size, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + } + + /* if the memory selection is non-contiguous, create a segmented selection */ + else { + hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ + size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ + size_t count = 0; /* number of offset/length entries in selection */ + size_t i; + hg_bulk_segment_t *bulk_segments = NULL; + uint8_t *start_offset = (uint8_t *) buf; + + /* generate the offsets/lengths pair arrays from the memory dataspace selection */ + if(H5S_get_offsets(space, type_size, nelmts, &off, &len, &count) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); + + /* Register memory with segmented HG handle */ + bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); + for (i = 0; i < count ; i++) { + bulk_segments[i].address = (void *)(start_offset + off[i]); + bulk_segments[i].size = len[i]; + } + + /* create Bulk handle */ + if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, + HG_BULK_READ_ONLY, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + + /* cleanup */ + if(count) { + free(bulk_segments); + bulk_segments = NULL; + free(len); + len = NULL; + free(off); + off = NULL; + } + } + } + + if(_checksum) { + *_checksum = checksum; + } + + H5VL_iod_type_info_reset(&type_info); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_pre_write */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_pre_read + * + * Depending on the type, this routine generates all the necessary + * parameters for forwarding a write call to IOD. It sets up the + * Mercury Bulk handle and checksums the data. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_pre_read(hid_t type_id, H5S_t *space, const void *buf, hssize_t nelmts, + /*out*/hg_bulk_t *bulk_handle) +{ + size_t buf_size = 0; + H5T_t *dt = NULL; + size_t type_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + type_size = H5T_get_size(dt); + buf_size = type_size * (size_t)nelmts; + + /* If the memory selection is contiguous, create simple HG Bulk Handle */ + if(H5S_select_is_contiguous(space)) { + /* Register memory with bulk_handle */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, buf_size, + HG_BULK_READWRITE, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + } + + /* if the memory selection is non-contiguous, create a segmented selection */ + else { + hsize_t *off = NULL; /* array that contains the memory addresses of the memory selection */ + size_t *len = NULL; /* array that contains the length of a contiguous block at each address */ + size_t count = 0; /* number of offset/length entries in selection */ + size_t i; + hg_bulk_segment_t *bulk_segments = NULL; + uint8_t *start_offset = (uint8_t *) buf; + + /* generate the offsets/lengths pair arrays from the memory dataspace selection */ + if(H5S_get_offsets(space, type_size, (size_t)nelmts, &off, &len, &count) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't retrieve offets/lengths of memory space"); + + /* Register memory with segmented HG handle */ + bulk_segments = (hg_bulk_segment_t *)malloc(count * sizeof(hg_bulk_segment_t)); + for (i = 0; i < count ; i++) { + bulk_segments[i].address = (void *)(start_offset + off[i]); + bulk_segments[i].size = len[i]; + } + + /* create Bulk handle */ + if (HG_SUCCESS != HG_Bulk_handle_create_segments(bulk_segments, count, + HG_BULK_READWRITE, bulk_handle)) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't create Bulk Data Handle"); + + /* cleanup */ + if(count) { + free(bulk_segments); + bulk_segments = NULL; + free(len); + len = NULL; + free(off); + off = NULL; + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_pre_read */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_vl_map_get_finalize + * + * Finalize the data read by deserializing it into the user's buffer. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_vl_map_get_finalize(size_t buf_size, void *read_buf, + void *user_buf, hid_t mem_type_id) +{ + H5T_t *mem_dt = NULL; + H5T_t *super = NULL; + size_t super_size; + H5T_class_t dt_class; + uint8_t *buf_ptr = (uint8_t *)read_buf; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (mem_dt = (H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + if(NULL == (super = H5T_get_super(mem_dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); + + super_size = H5T_get_size(super); + dt_class = H5T_get_class(mem_dt, FALSE); + +#if 0 + { + size_t seq_len = buf_size, u; + + if(H5T_STRING == dt_class) + fprintf(stderr, "String Length %zu: %s\n", buf_size, (char *)read_buf); + else if(H5T_VLEN == dt_class) { + int *ptr = (int *)buf_ptr; + fprintf(stderr, "Sequence Count %zu: ", buf_size/sizeof(int)); + for(u=0 ; u<buf_size/sizeof(int) ; ++u) + fprintf(stderr, "%d ", ptr[u]); + fprintf(stderr, "\n"); + } + } +#endif + + if(H5T_VLEN == dt_class) { + hvl_t *vl = (hvl_t *)user_buf; + + vl->len = buf_size/super_size; + vl->p = malloc(buf_size); + HDmemcpy(vl->p, buf_ptr, buf_size); + buf_ptr += buf_size; + } + else if(H5T_STRING == dt_class) { + char **buf = (char **)user_buf; + + //elmt_size = *((size_t *)buf_ptr); + //buf_ptr += sizeof(size_t); + + *buf = HDstrdup((char *)buf_ptr); + //buf_ptr += elmt_size; + } + +done: + if(super && H5T_close(super) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't close super type") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_vl_map_get_finalize */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_map_get_size + * + * Purpose: Retrieves the size of a Key or Value binary + * buffer given its datatype and buffer contents. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_map_get_size(hid_t type_id, const void *buf, + /*out*/uint64_t *checksum, + /*out*/size_t *size, /*out*/H5T_class_t *ret_class) +{ + size_t buf_size = 0; + H5T_t *dt = NULL; + H5T_class_t dt_class; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + dt_class = H5T_get_class(dt, FALSE); + + switch(dt_class) { + case H5T_STRING: + /* If this is a variable length string, get the size using strlen(). */ + if(H5T_is_variable_str(dt)) { + buf_size = HDstrlen((const char*)buf) + 1; + + /* compute checksum */ + *checksum = H5_checksum_crc64(buf, buf_size); + break; + } + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + case H5T_NO_CLASS: + case H5T_REFERENCE: + case H5T_NCLASSES: + case H5T_COMPOUND: + /* Data is not variable length, so use H5Tget_size() */ + /* MSC - This is not correct. Compound/Array can contian + VL datatypes, but for now we don't support that. Need + to check for that too */ + buf_size = H5T_get_size(dt); + + /* compute checksum */ + *checksum = H5_checksum_crc64(buf, buf_size); + break; + + /* If this is a variable length datatype, iterate over it */ + case H5T_VLEN: + { + H5T_t *super = NULL; + const hvl_t *vl; + + vl = (const hvl_t *)buf; + + if(NULL == (super = H5T_get_super(dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid super type of VL type"); + + buf_size = H5T_get_size(super) * vl->len; + + /* compute checksum */ + *checksum = H5_checksum_crc64(vl->p, buf_size); + H5T_close(super); + break; + } + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); + } + *size = buf_size; + if(ret_class) + *ret_class = dt_class; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_get_size */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_map_dtype_info + * + * Purpose: Retrieves information about the datatype of Map Key or + * value datatype, whether it's VL or not. If it is not VL + * return the size. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_map_dtype_info(hid_t type_id, /*out*/ hbool_t *is_vl, /*out*/size_t *size) +{ + size_t buf_size = 0; + H5T_t *dt = NULL; + H5T_class_t dt_class; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype") + + dt_class = H5T_get_class(dt, FALSE); + + switch(dt_class) { + case H5T_STRING: + /* If this is a variable length string, get the size using strlen(). */ + if(H5T_is_variable_str(dt)) { + *is_vl = TRUE; + break; + } + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + case H5T_NO_CLASS: + case H5T_REFERENCE: + case H5T_NCLASSES: + case H5T_COMPOUND: + /* Data is not variable length, so use H5Tget_size() */ + /* MSC - This is not correct. Compound/Array can contian + VL datatypes, but for now we don't support that. Need + to check for that too */ + buf_size = H5T_get_size(dt); + *is_vl = FALSE; + break; + + /* If this is a variable length datatype, iterate over it */ + case H5T_VLEN: + *is_vl = TRUE; + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); + } + + if(size) + *size = buf_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_map_get_size */ + +#if 0 +static herr_t +H5VL_generate_axe_ids(int myrank, int nranks, uint64_t *start_id) +{ + uint64_t seed; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + seed = (pow(2,64) - 1) / nranks; + *start_id = seed * my_rank; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +static herr_t +H5VL_iod_get_axe_id(int myrank, int nranks, int cur_index, uint64_t *id) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_parent_info + * + * Purpose: This routine traverses the path in name, or in loc_params + * if the path is specified there, to determine the components + * of the path that are present locally in the ID space. + * Once a component in the path is not found, the routine + * breaks at that point and stores the remaining path in new_name. + * This is where the traversal can begin at the server. + * The IOD ID, OH, and axe_id belonging to the last object + * present are returned too. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_get_parent_info(H5VL_iod_object_t *obj, H5VL_loc_params_t loc_params, + const char *name, /*OUT*/iod_obj_id_t *iod_id, + /*OUT*/iod_handle_t *iod_oh, /*OUT*/H5VL_iod_request_t **parent_req, + /*OUT*/char **new_name, /*OUT*/H5VL_iod_object_t **last_obj) +{ + iod_obj_id_t cur_id; + iod_handle_t cur_oh; + size_t cur_size; /* current size of the path traversed so far */ + char *cur_name; /* full path to object that is currently being looked for */ + H5VL_iod_object_t *cur_obj = obj; /* current object in the traversal loop */ + H5VL_iod_object_t *next_obj = NULL; /* the next object to traverse */ + const char *path; /* specified path for the object to traverse to */ + H5WB_t *wb = NULL; /* Wrapped buffer for temporary buffer */ + char comp_buf[1024]; /* Temporary buffer for path components */ + char *comp; /* Pointer to buffer for path components */ + size_t nchars; /* component name length */ + H5VL_iod_file_t *file = obj->file; /* pointer to file where the search happens */ + hbool_t last_comp = FALSE; /* Flag to indicate that a component is the last component in the name */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(loc_params.type == H5VL_OBJECT_BY_SELF) + path = name; + else if (loc_params.type == H5VL_OBJECT_BY_NAME) + path = loc_params.loc_data.loc_by_name.name; + + if (NULL == (cur_name = (char *)malloc(HDstrlen(obj->obj_name) + HDstrlen(path) + 2))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate"); + + HDstrcpy(cur_name, obj->obj_name); + cur_size = HDstrlen(obj->obj_name); + + if(obj->obj_type != H5I_FILE) { + HDstrcat(cur_name, "/"); + cur_size += 1; + } + + /* Wrap the local buffer for serialized header info */ + if(NULL == (wb = H5WB_wrap(comp_buf, sizeof(comp_buf)))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") + /* Get a pointer to a buffer that's large enough */ + if(NULL == (comp = (char *)H5WB_actual(wb, (HDstrlen(path) + 1)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Traverse the path */ + while((path = H5G__component(path, &nchars)) && *path) { + const char *s; /* Temporary string pointer */ + + /* + * Copy the component name into a null-terminated buffer so + * we can pass it down to the other symbol table functions. + */ + HDmemcpy(comp, path, nchars); + comp[nchars] = '\0'; + + /* + * The special name `.' is a no-op. + */ + if('.' == comp[0] && !comp[1]) { + path += nchars; + continue; + } /* end if */ + + /* Check if this is the last component of the name */ + if(!((s = H5G__component(path + nchars, NULL)) && *s)) + last_comp = TRUE; + + HDstrcat(cur_name, comp); + cur_size += nchars; + cur_name[cur_size] = '\0'; + + if(NULL == (next_obj = (const H5VL_iod_object_t *)H5I_search_name(file, cur_name, H5I_GROUP))) { + if(last_comp) { + if(NULL == (next_obj = (const H5VL_iod_object_t *)H5I_search_name + (file, cur_name, H5I_DATASET)) + && NULL == (next_obj = (H5VL_iod_object_t *)H5I_search_name + (file, cur_name, H5I_DATATYPE)) + && NULL == (next_obj = (H5VL_iod_object_t *)H5I_search_name + (file, cur_name, H5I_MAP))) + break; + } + else { + break; + } + } + +#if H5VL_IOD_DEBUG + printf("Found %s Locally\n", comp); +#endif + + /* Advance to next component in string */ + path += nchars; + HDstrcat(cur_name, "/"); + cur_size += 1; + cur_obj = next_obj; + } + + switch(cur_obj->obj_type) { + case H5I_FILE: + cur_oh = cur_obj->file->remote_file.root_oh; + cur_id = cur_obj->file->remote_file.root_id; + break; + case H5I_GROUP: + cur_oh = ((const H5VL_iod_group_t *)cur_obj)->remote_group.iod_oh; + cur_id = ((const H5VL_iod_group_t *)cur_obj)->remote_group.iod_id; + break; + case H5I_DATASET: + cur_oh = ((const H5VL_iod_dset_t *)cur_obj)->remote_dset.iod_oh; + cur_id = ((const H5VL_iod_dset_t *)cur_obj)->remote_dset.iod_id; + break; + case H5I_DATATYPE: + cur_oh = ((const H5VL_iod_dtype_t *)cur_obj)->remote_dtype.iod_oh; + cur_id = ((const H5VL_iod_dtype_t *)cur_obj)->remote_dtype.iod_id; + break; + case H5I_MAP: + cur_oh = ((const H5VL_iod_map_t *)cur_obj)->remote_map.iod_oh; + cur_id = ((const H5VL_iod_map_t *)cur_obj)->remote_map.iod_id; + break; + default: + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "bad location object"); + } + + if(cur_obj->request && cur_obj->request->status == H5ES_STATUS_IN_PROGRESS) { + *parent_req = cur_obj->request; + cur_obj->request->ref_count ++; + } + else { + *parent_req = NULL; + HDassert(cur_oh.cookie != IOD_OH_UNDEFINED); + } + + *iod_id = cur_id; + *iod_oh = cur_oh; + + if(*path) + *new_name = strdup(path); + else + *new_name = strdup("."); + + if(last_obj) + *last_obj = cur_obj; + +done: + free(cur_name); + /* Release temporary component buffer */ + if(wb && H5WB_unwrap(wb) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't release wrapped buffer") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_get_parent_info */ + + +/*------------------------------------------------------------------------- + * Function: H5I_search_name + * + * Purpose: return pointer to object with given full path name + * + * Return: Success: pointer to object + * Failure: NULL (not found) + * + * Programmer: Mohamad Chaarawi + * March 2013 + * + *------------------------------------------------------------------------- + */ +const void * +H5I_search_name(void *_file, char *name, H5I_type_t type) +{ + H5I_id_type_t *type_ptr; /*ptr to the type */ + const void *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(NULL) + + type_ptr = H5I_id_type_list_g[type]; + if(type_ptr == NULL || type_ptr->count <= 0) + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type") + + /* Only iterate through hash table if there are IDs in group */ + if(type_ptr->ids > 0) { + H5I_id_info_t *id_ptr; /*ptr to the new ID */ + unsigned i; /*counter */ + + /* Start at the beginning of the array */ + for(i = 0; i < type_ptr->cls->hash_size; i++) { + id_ptr = type_ptr->id_list[i]; + while(id_ptr) { + H5VL_iod_file_t *file = (H5VL_iod_file_t *)_file; + + switch(type) { + case H5I_GROUP: + { + const H5VL_iod_group_t *grp = (const H5VL_iod_group_t *)id_ptr->obj_ptr; + + if (file == grp->common.file && + 0 == strcmp(grp->common.obj_name, name)) { + ret_value = id_ptr->obj_ptr; + HGOTO_DONE(id_ptr->obj_ptr); + } + break; + } + case H5I_DATASET: + { + const H5VL_iod_dset_t *dset = (const H5VL_iod_dset_t *)id_ptr->obj_ptr; + + if (file == dset->common.file && + 0 == strcmp(dset->common.obj_name, name)) { + ret_value = id_ptr->obj_ptr; + HGOTO_DONE(id_ptr->obj_ptr); + } + break; + } + case H5I_MAP: + { + const H5VL_iod_map_t *map = (const H5VL_iod_map_t *)id_ptr->obj_ptr; + + if (file == map->common.file && + 0 == strcmp(map->common.obj_name, name)) { + ret_value = id_ptr->obj_ptr; + HGOTO_DONE(id_ptr->obj_ptr); + } + break; + } + case H5I_DATATYPE: + { + const H5T_t *dt = (const H5T_t *)id_ptr->obj_ptr; + + if(H5T_committed(dt)) { + const H5VL_iod_dtype_t *dtype ; + + dtype = (const H5VL_iod_dtype_t *)H5T_get_named_type(dt); + + if (file == dtype->common.file && + 0 == strcmp(dtype->common.obj_name, name)) { + ret_value = id_ptr->obj_ptr; + HGOTO_DONE(id_ptr->obj_ptr); + } + } + break; + } + default: + HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type") + } + id_ptr = id_ptr->next; + } /* end while */ + } /* end for */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_search_name() */ + +#endif + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_client.h b/src/H5VLiod_client.h new file mode 100644 index 0000000..4de6041 --- /dev/null +++ b/src/H5VLiod_client.h @@ -0,0 +1,450 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5VL iod client module + */ +#ifndef _H5VLiod_client_H +#define _H5VLiod_client_H + +#include "H5FFprivate.h" /* FastForward wrappers */ +#include "H5Mpublic.h" +#include "H5Sprivate.h" +#include "H5RCprivate.h" /* Read contexts */ +#include "H5TRprivate.h" /* Transactions */ +#include "H5VLiod_common.h" + +#ifdef H5_HAVE_EFF + +/* forward declaration of file struct */ +struct H5VL_iod_file_t; +/* forward declaration of object struct */ +struct H5VL_iod_object_t; + +/* enum for types of requests */ +typedef enum H5RQ_type_t { + HG_ANALYSIS_EXECUTE, + HG_FILE_CREATE, + HG_FILE_OPEN, + HG_FILE_CLOSE, + HG_ATTR_CREATE, + HG_ATTR_OPEN, + HG_ATTR_READ, + HG_ATTR_WRITE, + HG_ATTR_EXISTS, + HG_ATTR_RENAME, + HG_ATTR_REMOVE, + HG_ATTR_CLOSE, + HG_GROUP_CREATE, + HG_GROUP_OPEN, + HG_GROUP_CLOSE, + HG_DSET_CREATE, + HG_DSET_OPEN, + HG_DSET_READ, + HG_DSET_WRITE, + HG_DSET_GET_VL_SIZE, + HG_DSET_SET_EXTENT, + HG_DSET_CLOSE, + HG_DTYPE_COMMIT, + HG_DTYPE_OPEN, + HG_DTYPE_CLOSE, + HG_LINK_CREATE, + HG_LINK_MOVE, + HG_LINK_ITERATE, + HG_LINK_EXISTS, + HG_LINK_GET_INFO, + HG_LINK_GET_VAL, + HG_LINK_REMOVE, + HG_MAP_CREATE, + HG_MAP_OPEN, + HG_MAP_SET, + HG_MAP_GET, + HG_MAP_GET_COUNT, + HG_MAP_EXISTS, + HG_MAP_ITERATE, + HG_MAP_DELETE, + HG_MAP_CLOSE, + HG_OBJECT_OPEN_BY_TOKEN, + HG_OBJECT_OPEN, + HG_OBJECT_COPY, + HG_OBJECT_VISIT, + HG_OBJECT_EXISTS, + HG_OBJECT_SET_COMMENT, + HG_OBJECT_GET_COMMENT, + HG_OBJECT_GET_INFO, + HG_RC_ACQUIRE, + HG_RC_RELEASE, + HG_RC_PERSIST, + HG_RC_SNAPSHOT, + HG_TR_START, + HG_TR_FINISH, + HG_TR_SET_DEPEND, + HG_TR_SKIP, + HG_TR_ABORT, + HG_PREFETCH, + HG_EVICT +} H5RQ_type_t; + +/* the client IOD VOL request struct */ +typedef struct H5VL_iod_request_t { + H5RQ_type_t type; /* The operation type of this request */ + void *data; /* data associated with request (usually used at completion time) */ + void *req; /* the request pointer correponding to the Mercury request */ + struct H5VL_iod_object_t *obj; /* The object pointer that this request is associated with */ + H5VL_iod_state_t state; /* current internal state of the request */ + H5ES_status_t status; /* external status given to use of request */ + uint64_t axe_id; /* The AXE ID this request was assigned */ + unsigned ref_count; /* reference count to know when this request can be freed. */ + H5VL_iod_req_info_t *trans_info; /* pointer to transaction or read context struct for this request */ + + size_t num_parents; /* Number of parents this request has (in AXE) */ + struct H5VL_iod_request_t **parent_reqs; /* an array of the parent request pointers */ + + /* Linked list pointers for the container this request was generated. */ + struct H5VL_iod_request_t *file_prev; + struct H5VL_iod_request_t *file_next; + + /* Linked list pointers for all IOD VOL requests in the library */ + struct H5VL_iod_request_t *global_prev; + struct H5VL_iod_request_t *global_next; + + /* Linked list pointers for the transaction this request belong to */ + struct H5VL_iod_request_t *trans_prev; + struct H5VL_iod_request_t *trans_next; +} H5VL_iod_request_t; + +/* struct that contains the information about the IOD container */ +typedef struct H5VL_iod_remote_file_t { + /* Do NOT change the order of the parameters */ + iod_handle_t coh; + iod_handles_t root_oh; + uint64_t kv_oid_index; + uint64_t array_oid_index; + uint64_t blob_oid_index; + iod_obj_id_t root_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + iod_obj_id_t oidkv_id; + uint64_t c_version; + hid_t fcpl_id; +} H5VL_iod_remote_file_t; + +/* struct that contains the information about the IOD attr */ +typedef struct H5VL_iod_remote_attr_t { + /* Do NOT change the order of the parameters */ + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + hid_t type_id; + hid_t space_id; +} H5VL_iod_remote_attr_t; + +/* struct that contains the information about the IOD group */ +typedef struct H5VL_iod_remote_group_t { + /* Do NOT change the order of the parameters */ + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + hid_t gcpl_id; +} H5VL_iod_remote_group_t; + +/* struct that contains the information about the IOD map */ +typedef struct H5VL_iod_remote_map_t { + /* Do NOT change the order of the parameters */ + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + hid_t keytype_id; + hid_t valtype_id; + hid_t mcpl_id; +} H5VL_iod_remote_map_t; + +/* struct that contains the information about the IOD dset */ +typedef struct H5VL_iod_remote_dset_t { + /* Do NOT change the order of the parameters */ + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + hid_t dcpl_id; + hid_t type_id; + hid_t space_id; +} H5VL_iod_remote_dset_t; + +/* struct that contains the information about the IOD dtype */ +typedef struct H5VL_iod_remote_dtype_t { + /* Do NOT change the order of the parameters */ + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + hid_t tcpl_id; + hid_t type_id; +} H5VL_iod_remote_dtype_t; + +/* struct that contains the information about a generic IOD object */ +typedef struct H5VL_iod_remote_object_t { + /* Do NOT change the order of the parameters */ + H5I_type_t obj_type; + iod_handles_t iod_oh; + iod_obj_id_t iod_id; + iod_obj_id_t mdkv_id; + iod_obj_id_t attrkv_id; + hid_t cpl_id; + hid_t id1; + hid_t id2; +} H5VL_iod_remote_object_t; + +/* a common strcut between all client side objects */ +typedef struct H5VL_iod_object_t { + H5I_type_t obj_type; + char *obj_name; + char *comment; + H5VL_iod_request_t *request; + struct H5VL_iod_file_t *file; +} H5VL_iod_object_t; + +/* the client side file struct */ +typedef struct H5VL_iod_file_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_file_t remote_file; + char *file_name; + unsigned flags; + uint32_t md_integrity_scope; + hid_t fapl_id; + MPI_Comm comm; + MPI_Info info; + int my_rank; + int num_procs; + size_t num_req; + unsigned nopen_objs; + H5VL_iod_request_t *request_list_head; + H5VL_iod_request_t *request_list_tail; +} H5VL_iod_file_t; + +/* the client side attribute struct */ +typedef struct H5VL_iod_attr_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_attr_t remote_attr; + char *loc_name; +} H5VL_iod_attr_t; + +/* the client side group struct */ +typedef struct H5VL_iod_group_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_group_t remote_group; + hid_t gapl_id; +} H5VL_iod_group_t; + +/* the client side map struct */ +typedef struct H5VL_iod_map_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_map_t remote_map; + hid_t mapl_id; +} H5VL_iod_map_t; + +/* the client side dataset struct */ +typedef struct H5VL_iod_dset_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_dset_t remote_dset; + hid_t dapl_id; +} H5VL_iod_dset_t; + +/* the client side datatype struct */ +typedef struct H5VL_iod_dtype_t { + H5VL_iod_object_t common; /* must be first */ + H5VL_iod_remote_dtype_t remote_dtype; + hid_t tapl_id; +} H5VL_iod_dtype_t; + +/* information about an attr IO request */ +typedef struct H5VL_iod_attr_io_info_t { + int *status; + hg_bulk_t *bulk_handle; +} H5VL_iod_attr_io_info_t; + +/* information about a dataset write request */ +typedef struct H5VL_iod_write_info_t { + void *status; + hg_bulk_t *bulk_handle; + hg_bulk_t *vl_len_bulk_handle; + hg_bulk_segment_t *vl_segments; + char *vl_lengths; +} H5VL_iod_write_info_t; + +/* status of a read operation after it completes */ +typedef struct H5VL_iod_read_status_t { + int ret; + uint64_t cs; + size_t buf_size; +} H5VL_iod_read_status_t; + +/* information about a dataset read request */ +typedef struct H5VL_iod_read_info_t { + void *status; + hg_bulk_t *bulk_handle; + void *buf_ptr; + char *vl_lengths; + size_t vl_lengths_size; + H5VL_iod_type_info_t *type_info; + hssize_t nelmts; + size_t type_size; + struct H5S_t *space; + uint64_t *cs_ptr; + uint32_t raw_cs_scope; + hid_t file_space_id; + hid_t mem_type_id; + hid_t dxpl_id; + uint64_t axe_id; + na_addr_t ion_target; + hg_id_t read_id; +} H5VL_iod_read_info_t; + +typedef struct H5VL_iod_map_set_info_t { + void *status; + hg_bulk_t *value_handle; +} H5VL_iod_map_set_info_t; + +/* information about a map get request */ +typedef struct H5VL_iod_map_io_info_t { + /* read & write params */ + map_get_out_t *output; /* this must be first */ + void *val_ptr; + void *read_buf; + hg_bulk_t *value_handle; + size_t val_size; + uint32_t raw_cs_scope; + uint64_t *val_cs_ptr; + hid_t val_mem_type_id; + hid_t key_mem_type_id; + hid_t dxpl_id; + hbool_t val_is_vl; + hid_t rcxt_id; + binary_buf_t key; + na_addr_t peer; + hg_id_t map_get_id; +} H5VL_iod_map_io_info_t; + +/* information about a read context acquire request*/ +typedef struct H5VL_iod_rc_info_t { + rc_acquire_out_t result; + H5RC_t *read_cxt; + uint64_t *c_version_ptr; +} H5VL_iod_rc_info_t; + +/* information about a transaction start request*/ +typedef struct H5VL_iod_tr_info_t { + int result; + H5TR_t *tr; +} H5VL_iod_tr_info_t; + +/* information about an exists request*/ +typedef struct H5VL_iod_exists_info_t { + hbool_t *user_bool; /* pointer to the user provided hbool_t */ + htri_t server_ret; /* the return value from the server */ +} H5VL_iod_exists_info_t; + +H5_DLL herr_t H5VL_iod_request_delete(H5VL_iod_file_t *file, H5VL_iod_request_t *request); +H5_DLL herr_t H5VL_iod_request_add(H5VL_iod_file_t *file, H5VL_iod_request_t *request); +H5_DLL herr_t H5VL_iod_request_wait(H5VL_iod_file_t *file, H5VL_iod_request_t *request); +H5_DLL herr_t H5VL_iod_request_wait_all(H5VL_iod_file_t *file); +H5_DLL herr_t H5VL_iod_request_wait_some(H5VL_iod_file_t *file, const void *object); +H5_DLL herr_t H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req); +H5_DLL herr_t H5VL_iod_request_cancel(H5VL_iod_file_t *file, H5VL_iod_request_t *req); +H5_DLL herr_t H5VL_iod_request_decr_rc(H5VL_iod_request_t *request); + +H5_DLL herr_t H5VL_iod_get_parent_requests(H5VL_iod_object_t *obj, H5VL_iod_req_info_t *req_info, + H5VL_iod_request_t **parent_reqs, size_t *num_parents); +H5_DLL herr_t H5VL_iod_get_loc_info(H5VL_iod_object_t *obj, iod_obj_id_t *iod_id, + iod_handles_t *iod_oh, iod_obj_id_t *mdkv_oh, + iod_obj_id_t *attrkv_oh); +H5_DLL herr_t H5VL_iod_get_obj_requests(H5VL_iod_object_t *obj, /*IN/OUT*/ size_t *count, + /*OUT*/ H5VL_iod_request_t **parent_reqs); +H5_DLL herr_t H5VL__iod_create_and_forward(hg_id_t op_id, H5RQ_type_t op_type, + H5VL_iod_object_t *request_obj, htri_t track, + size_t num_parents, H5VL_iod_request_t **parent_reqs, + H5VL_iod_req_info_t *req_info, + void *input, void *output, void *data, void **req); + +H5_DLL herr_t H5VL_iod_map_dtype_info(hid_t type_id, /*out*/ hbool_t *is_vl, /*out*/size_t *size); +H5_DLL herr_t H5VL_iod_map_get_size(hid_t type_id, const void *buf, + /*out*/uint64_t *checksum, + /*out*/size_t *size, /*out*/H5T_class_t *dt_class); +H5_DLL herr_t H5VL_iod_gen_obj_id(int myrank, int nranks, uint64_t cur_index, + iod_obj_type_t type, uint64_t *id); +H5_DLL herr_t H5VL_iod_pre_write(hid_t type_id, H5S_t *space, const void *buf, + /*out*/uint64_t *_checksum, + /*out*/uint64_t *_vlen_checksum, + /*out*/hg_bulk_t *bulk_handle, + /*out*/hg_bulk_t *vl_len_bulk_handle, + /*out*/hg_bulk_segment_t **_vl_segments, + /*out*/char **_vl_lengths); +H5_DLL herr_t H5VL_iod_pre_read(hid_t type_id, struct H5S_t *space, const void *buf, + hssize_t nelmts, /*out*/hg_bulk_t *bulk_handle); + +/* private routines for map objects */ +H5_DLL herr_t H5M_init(void); +H5_DLL void *H5VL_iod_map_create(void *obj, H5VL_loc_params_t loc_params, const char *name, + hid_t keytype, hid_t valtype, hid_t lcpl_id, hid_t mcpl_id, + hid_t mapl_id, hid_t trans_id, void **req); +H5_DLL void *H5VL_iod_map_open(void *obj, H5VL_loc_params_t loc_params, + const char *name, hid_t mapl_id, hid_t rcxt_id, void **req); +H5_DLL herr_t H5VL_iod_map_set(void *map, hid_t key_mem_type_id, const void *key, + hid_t val_mem_type_id, const void *value, hid_t dxpl_id, + hid_t trans_id, void **req); +H5_DLL herr_t H5VL_iod_map_get(void *map, hid_t key_mem_type_id, const void *key, + hid_t val_mem_type_id, void *value, hid_t dxpl_id, + hid_t rcxt_id, void **req); +H5_DLL herr_t H5VL_iod_map_get_types(void *map, hid_t *key_type_id, hid_t *val_type_id, + hid_t rcxt_id, void **req); +H5_DLL herr_t H5VL_iod_map_get_count(void *map, hsize_t *count, hid_t rcxt_id, void **req); +H5_DLL herr_t H5VL_iod_map_exists(void *map, hid_t key_mem_type_id, const void *key, + hbool_t *exists, hid_t rcxt_id, void **req); +H5_DLL herr_t H5VL_iod_map_iterate(void *map, hid_t key_mem_type_id, hid_t value_mem_type_id, + H5M_iterate_func_t callback_func, void *context); +H5_DLL herr_t H5VL_iod_map_delete(void *map, hid_t key_mem_type_id, const void *key, + hid_t trans_id, void **req); +H5_DLL herr_t H5VL_iod_map_close(void *map, void **req); + +H5_DLL void * H5VL_iod_obj_open_token(const void *token, H5TR_t *tr, + H5I_type_t *opened_type, void **req); + +/* private routines for RC */ +H5_DLL herr_t H5VL_iod_rc_acquire(H5VL_iod_file_t *file, H5RC_t *rc, + uint64_t *c_version, hid_t rcapl_id, void **req); +H5_DLL herr_t H5VL_iod_rc_release(H5RC_t *rc, void **req); +H5_DLL herr_t H5VL_iod_rc_persist(H5RC_t *rc, void **req); +H5_DLL herr_t H5VL_iod_rc_snapshot(H5RC_t *rc, const char *snapshot_name, void **req); + +/* private routines for TR */ +H5_DLL herr_t H5VL_iod_tr_start(H5TR_t *tr, hid_t trspl_id, void **req); +H5_DLL herr_t H5VL_iod_tr_finish(H5TR_t *tr, hbool_t acquire, hid_t trfpl_id, void **req); +H5_DLL herr_t H5VL_iod_tr_set_dependency(H5TR_t *tr, uint64_t trans_num, void **req); +H5_DLL herr_t H5VL_iod_tr_skip(H5VL_iod_file_t *file, uint64_t start_trans_num, + uint64_t count, void **req); +H5_DLL herr_t H5VL_iod_tr_abort(H5TR_t *tr, void **req); + +H5_DLL herr_t H5VL_iod_prefetch(void *obj, hid_t rcxt_id, hrpl_t *replica_id, + hid_t apl_id, void **req); +H5_DLL herr_t H5VL_iod_evict(void *obj, uint64_t c_version, hid_t apl_id, void **req); + +H5_DLL herr_t H5VL_iod_analysis_execute(const char *file_name, const char *obj_name, + hid_t query_id, const char *split_script, const char *combine_script, + void **req); + +#endif /* H5_HAVE_EFF */ +#endif /* _H5VLiod_client_H */ diff --git a/src/H5VLiod_common.c b/src/H5VLiod_common.c new file mode 100644 index 0000000..9047613 --- /dev/null +++ b/src/H5VLiod_common.c @@ -0,0 +1,1020 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of h5netvol. The full h5netvol copyright notice, * + * including terms governing use, modification, and redistribution, is * + * contained in the file COPYING at the root of the source code distribution * + * tree. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include "H5VLiod_common.h" +#ifdef H5_HAVE_EFF +#include <mchecksum.h> /* Mercury Checksum library */ +#endif /* H5_HAVE_EFF */ + +/* + * Local typedefs + */ +/* Structure for a compound member type */ +typedef struct H5VL_iod_cmpd_info_t { + size_t offset; + hid_t type_id; +} H5VL_iod_cmpd_info_t; + +/* Macros for error handling */ +#define SUCCEED 0 +#define FAIL -1 +#define PRINT_ERROR(MSG) \ +do { \ + fprintf(stderr, "ERROR at %s:%d in %s()...\n%s\n", __FILE__, __LINE__, __FUNCTION__,MSG); \ +} while(0) +#define ERROR(MSG) \ +do { \ + PRINT_ERROR(MSG); \ + goto error; \ +} while(0) + +#define TRUE 1 +#define FALSE 0 + +/* Macros to encode and decode a uint64_t */ +# define UINT64ENCODE(p, n) \ + do { \ + uint64_t _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t*)(p); \ +\ + for (_i = 0; _i < sizeof(uint64_t); _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + for (/*void*/; _i < 8; _i++) \ + *_p++ = 0; \ + } while(0) + +# define UINT64DECODE(p, n) \ + do { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + size_t _i; \ + uint8_t *_p = (uint8_t*)(p); \ +\ + n = 0; \ + (_p) += 8; \ + for (_i = 0; _i < sizeof(uint64_t); _i++) \ + n = (n << 8) | *(--_p); \ + } while(0) + +/* + * Local functions + */ +static int H5VL_iod_cmpd_qsort_cb(const void *_memb1, const void *_memb2); +static int H5VL_iod_get_type_info_helper(hid_t type_id, + H5VL_iod_type_info_t *type_info, size_t offset, size_t *vls_nalloc); +static int H5VL_iod_cs_send_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char **vl_lengths, size_t *vl_lengths_nused, + size_t *vl_lengths_nalloc, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc); +static int H5VL_iod_cs_recv_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char *vl_lengths, size_t *vl_lengths_loc, + size_t vl_lengths_nused, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc); + + +/* + * Local macros + */ +#define H5VL_IOD_ARR_ADD(TYPE, ARR, NUSED, NALLOC, DEF_ALLOC) \ + do { \ + size_t _tmp_nalloc; \ + TYPE *_tmp_arr; \ +\ + assert((NALLOC) >= (NUSED)); \ +\ + if((NALLOC) == (NUSED)) { \ + _tmp_nalloc = (NALLOC) ? (NALLOC) * 2 : (DEF_ALLOC); \ +\ + if(NULL == (_tmp_arr = (TYPE *)realloc(ARR, _tmp_nalloc * sizeof(TYPE)))) \ + ERROR("failed to reallocate array"); \ + (ARR) = _tmp_arr; \ + (NALLOC) = _tmp_nalloc; \ + } /* end if */ \ + } while(0) + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cmpd_qsort_cb + * + * Purpose: qsort callback for sorting compound type members by + * offset. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cmpd_qsort_cb(const void *_memb1, const void *_memb2) +{ + const H5VL_iod_cmpd_info_t *memb1 = (const H5VL_iod_cmpd_info_t *)_memb1; + const H5VL_iod_cmpd_info_t *memb2 = (const H5VL_iod_cmpd_info_t *)_memb2; + + if(memb1->offset < memb2->offset) + return -1; + else if(memb1->offset > memb2->offset) + return 1; + else + return 0; +} /* end H5VL_iod_cmpd_qsort_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_type_info_helper + * + * Purpose: Recursively searches for variable-length datatypes in the + * provided type, filling in the fields in type_info. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 18, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_get_type_info_helper(hid_t type_id, H5VL_iod_type_info_t *type_info, + size_t offset, size_t *vls_nalloc) +{ + hid_t super_type = -1; + hsize_t *dims = NULL; + size_t num_cmpd_membs = 0; + H5VL_iod_cmpd_info_t *cmpd_membs = NULL; + H5T_class_t type_class; + int i; + + assert(type_info); + assert(vls_nalloc); + + /* Get type class */ + if(H5T_NO_CLASS == (type_class = H5Tget_class(type_id))) + ERROR("failed to get datatype class"); + + /* Take different actions depending on class */ + switch(type_class) { + case H5T_COMPOUND: + { + int nmemb; + + /* Get number of members */ + if((nmemb = H5Tget_nmembers(type_id)) < 0) + ERROR("failed to get number of compound datatype members"); + + /* Allocate array of members */ + if(NULL == (cmpd_membs = (H5VL_iod_cmpd_info_t *)malloc((size_t)nmemb * sizeof(H5VL_iod_cmpd_info_t)))) + ERROR("failed ot allocate array of compound type members"); + + /* Get offset and type for all members */ + for(i = 0; i < nmemb; i++) { + cmpd_membs[i].offset = H5Tget_member_offset(type_id, (unsigned)i); + + if((cmpd_membs[i].type_id = H5Tget_member_type(type_id, (unsigned)i)) < 0) + ERROR("failed to get compound datatype member type"); + num_cmpd_membs++; + } /* end for */ + + /* Sort members by offset */ + qsort(cmpd_membs, num_cmpd_membs, sizeof(cmpd_membs[0]), H5VL_iod_cmpd_qsort_cb); + + /* Get info for all members */ + for(i = 0; i < nmemb; i++) + if(H5VL_iod_get_type_info_helper(cmpd_membs[i].type_id, type_info, offset + cmpd_membs[i].offset, vls_nalloc) < 0) + ERROR("failed to get compound datatype member type info"); + + /* Free cmpd_membs. Run in opposite order so if a failure + * occurs the error code doesn't try to free types twice */ + for(i = nmemb - 1; i >= 0; i--) { + num_cmpd_membs--; + if(H5Tclose(cmpd_membs[i].type_id) < 0) + ERROR("failed to close compound member type"); + } /* end for */ + free(cmpd_membs); + cmpd_membs = NULL; + + break; + } /* end block */ + + case H5T_ARRAY: + { + int ndims; + size_t array_nelem = 1; + size_t orig_num_vls = type_info->num_vls; + size_t elem_num_vls; + size_t super_type_size; + size_t i_size, j_size; + + /* Get array element type */ + if((super_type = H5Tget_super(type_id)) < 0) + ERROR("failed to get array datatype element type"); + + /* Get type info for element type (effectively only for the + * first element) */ + if(H5VL_iod_get_type_info_helper(super_type, type_info, offset, vls_nalloc) < 0) + ERROR("failed to get array datatype element type info"); + + /* If the element type contains any vlens, we must copy the vlen + * info for each element in the array */ + if(type_info->num_vls != orig_num_vls) { + assert(type_info->num_vls > orig_num_vls); + + /* Get number of dimensions in array */ + if((ndims = H5Tget_array_ndims(type_id)) < 0) + ERROR("failed to get array datatype number of dimensions"); + + /* Allocate array of dimensions */ + if(NULL == (dims = (hsize_t *)malloc((size_t)ndims * sizeof(hsize_t)))) + ERROR("failed to allocate array of dimensions"); + + /* Get array dimensions */ + if(H5Tget_array_dims2(type_id, dims) < 0) + ERROR("failed to get array datatype dimensions"); + + /* Calculate total number of elements */ + for(i = 0; i < ndims; i++) + array_nelem *= (size_t)dims[i]; + + /* Get size of element type */ + if(0 == (super_type_size = H5Tget_size(super_type))) + ERROR("failed to get array element type size"); + + /* Replicate all vls added during recursion into element + * type for each element in the array. Increment ref count + * on base types instead of copying. */ + elem_num_vls = type_info->num_vls; + for(i_size = 1; i_size < array_nelem; i_size++) + for(j_size = orig_num_vls; j_size < elem_num_vls; + j_size++) { + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + type_info->vls[type_info->num_vls].offset = type_info->vls[j_size].offset + (i_size * super_type_size); + type_info->vls[type_info->num_vls].base_type = type_info->vls[j_size].base_type; + if(type_info->vls[type_info->num_vls].base_type) + type_info->vls[type_info->num_vls].base_type->rc++; + type_info->num_vls++; + } /* end for */ + + free(dims); + dims = NULL; + } /* end if */ + + if(H5Tclose(super_type) < 0) + ERROR("failed to close array datatype element type"); + super_type = -1; + + break; + } /* end block */ + + case H5T_VLEN: + /* Add vlen to vls array */ + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + /* Get vlen base type */ + if((super_type = H5Tget_super(type_id)) < 0) + ERROR("failed to get vlen datatype base type"); + + /* Set vlen offset in type */ + type_info->vls[type_info->num_vls].offset = offset; + + /* Allocate type info for base type */ + if(NULL == (type_info->vls[type_info->num_vls].base_type = (H5VL_iod_type_info_t *)malloc(sizeof(H5VL_iod_type_info_t)))) + ERROR("failed to allocate vlen datatype base type info"); + type_info->num_vls++; + + /* Get type info for base type */ + if(H5VL_iod_get_type_info(super_type, type_info->vls[type_info->num_vls - 1].base_type) < 0) + ERROR("failed to get vlen datatype base type info"); + + if(H5Tclose(super_type) < 0) + ERROR("failed to close vlen datatype base type"); + super_type = -1; + + break; + + case H5T_STRING: + { + htri_t is_variable_str; + + /* Check if this string is variable length */ + if((is_variable_str = H5Tis_variable_str(type_id)) < 0) + ERROR("failed to determine if type is variable string"); + + if(is_variable_str) { + /* Add variable-length string to vls array. Set base_type + * to NULL. */ + H5VL_IOD_ARR_ADD(H5VL_iod_vl_info_t, type_info->vls, type_info->num_vls, *vls_nalloc, 8); + + type_info->vls[type_info->num_vls].offset = offset; + type_info->vls[type_info->num_vls].base_type = NULL; + type_info->num_vls++; + + break; + } /* end if */ + + /* Fall through if not variable string */ + } /* end block */ + + default: + /* Nothing to do currently */ + break; + } /* end switch */ + + return(SUCCEED); + +error: + if(super_type >= 0) + if(H5Tclose(super_type) < 0) + PRINT_ERROR("failed to close super type"); + if(dims) + free(dims); + if(cmpd_membs) { + for(i = 0; i < (int)num_cmpd_membs; i++) + if(H5Tclose(cmpd_membs[i].type_id) < 0) + PRINT_ERROR("failed to close compound member type"); + free(cmpd_membs); + } /* end if */ + + return(FAIL); +} /* end H5VL_iod_get_type_info_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_type_info + * + * Purpose: Builds the type_info struct given type_id. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 18, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_get_type_info(hid_t type_id, H5VL_iod_type_info_t *type_info) +{ + htri_t found_class; + + /* Initialize struct first, so a call to reset() won't cause problems if + * something in this function fails */ + type_info->num_fl_spans = 0; + type_info->fl_spans = NULL; + type_info->num_vls = 0; + type_info->vls = NULL; + type_info->rc = 1; + if(0 == (type_info->size = H5Tget_size(type_id))) + ERROR("H5Tget_size failed"); + + /* Check for a vl or string type */ + if((found_class = H5Tdetect_class(type_id, H5T_VLEN)) < 0) + ERROR("failed to search for vlen type class"); + if(!found_class) + if((found_class = H5Tdetect_class(type_id, H5T_STRING)) < 0) + ERROR("failed to search for string type class"); + + /* Only need to investigate further if the type contains a vlen or string */ + if(found_class) { + size_t vls_nalloc = 0; + + if(H5VL_iod_get_type_info_helper(type_id, type_info, 0, &vls_nalloc) < 0) + ERROR("failed to type info"); + } /* end if */ + + /* If any vlens were found, build fixed-length span info */ + if(type_info->num_vls) { + size_t cur_fl_offset = 0; + size_t fl_spans_nalloc = 0; + size_t i; + + /* Iterate over all vlens */ + for(i = 0; i < type_info->num_vls; i++) { + /* Check if this vlen left a fixed-length gap before it */ + assert(type_info->vls[i].offset >= cur_fl_offset); + if(type_info->vls[i].offset > cur_fl_offset) { + /* Create fixed-length span before vl */ + H5VL_IOD_ARR_ADD(H5VL_iod_fl_span_t, type_info->fl_spans, type_info->num_fl_spans, fl_spans_nalloc, 2); + + type_info->fl_spans[type_info->num_fl_spans].offset = cur_fl_offset; + type_info->fl_spans[type_info->num_fl_spans].size = type_info->vls[i].offset - cur_fl_offset; + type_info->num_fl_spans++; + } /* end if */ + + /* Update cur_fl_offset */ + cur_fl_offset = type_info->vls[i].offset + (type_info->vls[i].base_type ? sizeof(hvl_t) : sizeof(char *)); + } /* end for */ + + /* Add span at end */ + assert(type_info->size >= cur_fl_offset); + if(type_info->size > cur_fl_offset) { + H5VL_IOD_ARR_ADD(H5VL_iod_fl_span_t, type_info->fl_spans, type_info->num_fl_spans, fl_spans_nalloc, 2); + + type_info->fl_spans[type_info->num_fl_spans].offset = cur_fl_offset; + type_info->fl_spans[type_info->num_fl_spans].size = type_info->size - cur_fl_offset; + type_info->num_fl_spans++; + } /* end if */ + } /* end if */ + + return(SUCCEED); + +error: + H5VL_iod_type_info_reset(type_info); + + return(FAIL); +} /* end H5VL_iod_get_type_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_type_info_reset + * + * Purpose: Frees all fields fields in type_info, and anything + * referenced by those fields. Does not free type_info. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_type_info_reset(H5VL_iod_type_info_t *type_info) +{ + size_t i; + + /* Free fl spans */ + if(type_info->fl_spans) { + free(type_info->fl_spans); + type_info->fl_spans = NULL; + } /* end if */ + type_info->num_fl_spans = 0; + + /* Free vls */ + if(type_info->vls) { + /* Recurse into each vl's base type, and free the base type if its rc + * reaches 0 */ + for(i = 0; i < type_info->num_vls; i++) + if(type_info->vls[i].base_type + && (--type_info->vls[i].base_type->rc == 0)) { + H5VL_iod_type_info_reset(type_info->vls[i].base_type); + free(type_info->vls[i].base_type); + } /* end if */ + + free(type_info->vls); + type_info->vls = NULL; + } /* end if */ + type_info->num_vls = 0; + + return; +} /* end H5VL_iod_type_info_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cs_send_helper + * + * Purpose: Recursively builds the segments array and array of + * variable-length data lengths given buf, type_info and + * nelem. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cs_send_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char **vl_lengths, size_t *vl_lengths_nused, + size_t *vl_lengths_nalloc, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc) +{ + _Bool wrapped = FALSE; + _Bool wrappable; + size_t span_size; + size_t i; + size_t j; + + assert(nelem > 0); + + if(type_info->vls) { + /* Add segments for fixed-length spans */ + if(type_info->num_fl_spans > 0) { + assert(type_info->fl_spans); + + /* Check if we can combine the last span in each element with the first + * span in the next */ + wrappable = ((type_info->fl_spans[type_info->num_fl_spans - 1].offset + + type_info->fl_spans[type_info->num_fl_spans - 1].size) + == type_info->size) && (type_info->fl_spans[0].offset == 0); + + assert(!(wrappable && (type_info->num_fl_spans == 1))); + + /* Iterate over spans */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_fl_spans; j++) + if(wrapped) + wrapped = FALSE; + else { + /* Add fixed-length segment to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + /* Check if we can wrap this segment */ + if((j == (type_info->num_fl_spans - 1)) && wrappable + && (i != (nelem - 1))) { + span_size = type_info->fl_spans[0].size + type_info->fl_spans[j].size; + wrapped = TRUE; + } /* end if */ + else + span_size = type_info->fl_spans[j].size; + + /* Add segment */ + (*segments)[*num_segments].address = (hg_ptr_t)(buf + (i * type_info->size) + type_info->fl_spans[j].offset); + (*segments)[*num_segments].size = span_size; + (*num_segments)++; + } /* end else */ + } /* end if */ + + /* Analyze vlens */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_vls; j++) + if(type_info->vls[j].base_type) { + /* Standard vlen */ + hvl_t vl = *(hvl_t *)(buf + (i * type_info->size) + type_info->vls[j].offset); + + /* Add vl segment length to vl_lengths array */ + H5VL_IOD_ARR_ADD(char, *vl_lengths, *vl_lengths_nused, *vl_lengths_nalloc, 256); + assert(*vl_lengths_nused + 8 <= *vl_lengths_nalloc); + + UINT64ENCODE(&(*vl_lengths)[*vl_lengths_nused], (uint64_t)vl.len); + *vl_lengths_nused += 8; + + /* Handle vlen array if present */ + if(vl.len > 0) { + /* Add vlen buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl.p; + (*free_list_len)++; + } /* end if */ + + /* Recurse into vlen data */ + if(H5VL_iod_cs_send_helper((char *)vl.p, type_info->vls[j].base_type, vl.len, segments, num_segments, segments_nalloc, vl_lengths, vl_lengths_nused, vl_lengths_nalloc, free_list, free_list_len, free_list_nalloc) < 0) + ERROR("failed to build segments"); + } /* end if */ + } /* end if */ + else { + /* Vlen string */ + char *vl_s = *(char **)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_s_len; + + /* Get size */ + if(vl_s) + vl_s_len = (uint64_t)strlen(vl_s) + 1; + else + vl_s_len = 0; + + /* Add vl string length to vl_lengths array. Include null + * terminator in length to distinguish between NULL pointer + * (len = 0) and null string (len = 1) */ + H5VL_IOD_ARR_ADD(char, *vl_lengths, *vl_lengths_nused, *vl_lengths_nalloc, 256); + assert(*vl_lengths_nused + 8 <= *vl_lengths_nalloc); + + UINT64ENCODE(&(*vl_lengths)[*vl_lengths_nused], vl_s_len); + *vl_lengths_nused += 8; + + /* Handle the vl string buffer if present */ + if(vl_s_len > 0) { + /* Add vl string buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl_s; + (*free_list_len)++; + } /* end if */ + + /* Add vl string length to segments array, if length is + * greater than 1 (including null terminator). Do not + * include null terminator in segment length so it is not + * transmitted. */ + if(vl_s_len > 1) { + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)vl_s; + (*segments)[*num_segments].size = vl_s_len - 1; + (*num_segments)++; + } /* end if */ + } /* end if */ + } /* end else */ + } /* end if */ + else { + /* No vlens, just add entire buffer to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)buf; + (*segments)[*num_segments].size = nelem * type_info->size; + (*num_segments)++; + } /* end else */ + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_cs_send_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_create_segments_send + * + * Purpose: Builds the segments array and array of variable-length + * data lengths given buf, type_info and nelem. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_create_segments_send(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char **vl_lengths, size_t *vl_lengths_size, void ***free_list, + size_t *free_list_len) +{ + size_t segments_nalloc = 0; + size_t vl_lengths_nalloc = 0; + size_t free_list_nalloc = 0; + + assert(buf); + assert(type_info); + assert(type_info->vls); + assert(nelem > 0); + assert(segments); + assert(!*segments); + assert(num_segments); + assert(*num_segments == 0); + assert(vl_lengths); + assert(!*vl_lengths); + assert(vl_lengths_size); + assert(*vl_lengths_size == 0); + assert(!free_list == !free_list_len); + assert(!free_list || !*free_list); + assert(!free_list_len || (*free_list_len == 0)); + + /* Call the real (recursive) function */ + if(H5VL_iod_cs_send_helper(buf, type_info, nelem, segments, num_segments, &segments_nalloc, vl_lengths, vl_lengths_size, &vl_lengths_nalloc, free_list, free_list_len, &free_list_nalloc) < 0) + ERROR("failed to build segments"); + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_create_segments_send() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_cs_recv_helper + * + * Purpose: Recursively builds the segments array, allocates buffers + * for variable-length data, and writes vlen pointers given + * (empty) buf, type_info, nelem, and the vl_lengths array. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +static int +H5VL_iod_cs_recv_helper(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + size_t *segments_nalloc, char *vl_lengths, size_t *vl_lengths_loc, + size_t vl_lengths_size, void ***free_list, size_t *free_list_len, + size_t *free_list_nalloc) +{ + _Bool wrapped = FALSE; + _Bool wrappable; + size_t span_size; + size_t i; + size_t j; + + assert(nelem > 0); + + if(type_info->vls) { + /* Add segments for fixed-length spans */ + if(type_info->num_fl_spans > 0) { + assert(type_info->fl_spans); + + /* Check if we can combine the last span in each element with the first + * span in the next */ + wrappable = ((type_info->fl_spans[type_info->num_fl_spans - 1].offset + + type_info->fl_spans[type_info->num_fl_spans - 1].size) + == type_info->size) && (type_info->fl_spans[0].offset == 0); + + assert(!(wrappable && (type_info->num_fl_spans == 1))); + + /* Iterate over spans */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_fl_spans; j++) + if(wrapped) + wrapped = FALSE; + else { + /* Add fixed-length segment to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + /* Check if we can wrap this segment */ + if((j == (type_info->num_fl_spans - 1)) && wrappable + && (i != (nelem - 1))) { + span_size = type_info->fl_spans[0].size + type_info->fl_spans[j].size; + wrapped = TRUE; + } /* end if */ + else + span_size = type_info->fl_spans[j].size; + + /* Add segment */ + (*segments)[*num_segments].address = (hg_ptr_t)(buf + (i * type_info->size) + type_info->fl_spans[j].offset); + (*segments)[*num_segments].size = span_size; + (*num_segments)++; + } /* end else */ + } /* end if */ + + /* Analyze vlens */ + for(i = 0; i < nelem; i++) + for(j = 0; j < type_info->num_vls; j++) + if(type_info->vls[j].base_type) { + /* Standard vlen */ + hvl_t *vl = (hvl_t *)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_length; + + /* Retrieve vl segment length from vl_lengths array */ + if(*vl_lengths_loc + 8 > vl_lengths_size) + ERROR("vl_lengths array is too short"); + UINT64DECODE(&vl_lengths[*vl_lengths_loc], vl_length); + *vl_lengths_loc += 8; + vl->len = (size_t)vl_length; + + if(vl_length == 0) + vl->p = NULL; + else { + /* Allocate buffer for vlen data */ + if(NULL == (vl->p = malloc(vl_length * type_info->vls[j].base_type->size))) + ERROR("failed to allocate vlen buffer"); + + /* Add malloc'ed buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = vl->p; + (*free_list_len)++; + } /* end if */ + + /* Recurse into vlen data */ + if(H5VL_iod_cs_recv_helper(vl->p, type_info->vls[j].base_type, (size_t)vl_length, segments, num_segments, segments_nalloc, vl_lengths, vl_lengths_loc, vl_lengths_size, free_list, free_list_len, free_list_nalloc) < 0) + ERROR("failed to build segments"); + } /* end if */ + } /* end if */ + else { + /* Vlen string */ + char **vl_s = (char **)(buf + (i * type_info->size) + type_info->vls[j].offset); + uint64_t vl_s_len; + + /* Retrieve vl string length from vl_lengths array */ + if(*vl_lengths_loc + 8 > vl_lengths_size) + ERROR("vl_lengths array is too short"); + UINT64DECODE(&vl_lengths[*vl_lengths_loc], vl_s_len); + *vl_lengths_loc += 8; + + if(vl_s_len == 0) + *vl_s = NULL; + else { + /* Allocate buffer for vlen string data */ + if(NULL == (*vl_s = malloc((size_t)vl_s_len))) + ERROR("failed to allocate vlen string buffer"); + + /* Add malloc'ed buffer to free list, if present */ + if(free_list) { + H5VL_IOD_ARR_ADD(void *, *free_list, *free_list_len, *free_list_nalloc, 64); + + (*free_list)[*free_list_len] = *vl_s; + (*free_list_len)++; + } /* end if */ + + /* Add vl string to segments array, if length is greater + * than 1 (including null terminator) */ + if(vl_s_len > 1) { + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)*vl_s; + (*segments)[*num_segments].size = (size_t)vl_s_len - 1; + (*num_segments)++; + } /* end if */ + + /* Add null terminator */ + (*vl_s)[vl_s_len - 1] = '\0'; + } /* end if */ + } /* end else */ + } /* end if */ + else { + /* No vlens, just add entire buffer to segments array */ + H5VL_IOD_ARR_ADD(hg_bulk_segment_t, *segments, *num_segments, *segments_nalloc, 256); + + (*segments)[*num_segments].address = (hg_ptr_t)buf; + (*segments)[*num_segments].size = nelem * type_info->size; + (*num_segments)++; + } /* end else */ + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_cs_recv_helper() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_create_segments_recv + * + * Purpose: Builds the segments array, allocates buffers for + * variable-length data, and writes vlen pointers given + * (empty) buf, type_info, nelem, and the vl_lengths array. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Neil Fortner + * Nov 19, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_create_segments_recv(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char *vl_lengths, size_t vl_lengths_size, void ***free_list, + size_t *free_list_len) +{ + size_t segments_nalloc = 0; + size_t vl_lengths_loc = 0; + size_t free_list_nalloc = 0; + + assert(buf); + assert(type_info); + assert(type_info->vls); + assert(nelem > 0); + assert(segments); + assert(!*segments); + assert(num_segments); + assert(*num_segments == 0); + assert(vl_lengths); + assert(vl_lengths_size > 0); + assert(!free_list == !free_list_len); + assert(!free_list || !*free_list); + assert(!free_list_len || (*free_list_len == 0)); + + /* Call the real (recursive) function */ + if(H5VL_iod_cs_recv_helper(buf, type_info, nelem, segments, num_segments, &segments_nalloc, vl_lengths, &vl_lengths_loc, vl_lengths_size, free_list, free_list_len, &free_list_nalloc) < 0) + ERROR("failed to build segments"); + + return(SUCCEED); + +error: + return(FAIL); +} /* end H5VL_iod_create_segments_recv() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_free_list_free + * + * Purpose: Frees all pointers on the provided free list and then + * frees the free list itself + * + * Return: void + * + * Programmer: Neil Fortner + * Dec 5, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_free_list_free(void **free_list, size_t free_list_len) +{ + size_t i; + + for(i = 0; i < free_list_len; i++) + free(free_list[i]); + free(free_list); +} /* end H5VL_iod_free_list_free() */ + +#ifdef H5_HAVE_EFF +uint64_t +H5_checksum_crc64(const void *buf, size_t buf_size) +{ + const char *hash_method = "crc64"; + size_t hash_size; + mchecksum_object_t checksum; + uint64_t ret_value = 0; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + mchecksum_update(checksum, buf, buf_size); + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &ret_value, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return ret_value; +} + +uint64_t +H5_checksum_crc64_segments(hg_bulk_segment_t *segments, size_t count) +{ + const char *hash_method = "crc64"; + size_t hash_size; + size_t i; + mchecksum_object_t checksum; + uint64_t ret_value; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + for (i = 0; i < count; i++) { + mchecksum_update(checksum, segments[i].address, segments[i].size); + } + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &ret_value, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return ret_value; +} + +uint64_t +H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count) +{ + const char *hash_method = "crc64"; + size_t hash_size; + size_t i; + mchecksum_object_t checksum; + uint64_t ret_value; + + /* Initialize checksum */ + mchecksum_init(hash_method, &checksum); + + /* Update checksum */ + for (i = 0; i < count; i++) { + mchecksum_update(checksum, buf[i], buf_size[i]); + } + + /* Get size of checksum */ + hash_size = mchecksum_get_size(checksum); + + assert(hash_size == sizeof(uint64_t)); + + /* get checksum value */ + mchecksum_get(checksum, &ret_value, hash_size, 1); + + /* Destroy checksum */ + mchecksum_destroy(checksum); + + return ret_value; +} +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_common.h b/src/H5VLiod_common.h new file mode 100644 index 0000000..fa73306 --- /dev/null +++ b/src/H5VLiod_common.h @@ -0,0 +1,731 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5VL module + */ +#ifndef _H5VLiod_common_H +#define _H5VLiod_common_H + +#include "H5public.h" +#include "H5FFpublic.h" +#include "H5VLpublic.h" +#include "H5VLiod.h" /* Iod VOL plugin */ + +#ifdef H5_HAVE_EFF + +#define NA_UNDEFINED NULL +#define IOD_OH_UNDEFINED ((uint64_t)0)//(pow(2.0,64.0) - 1) +#define IOD_ID_UNDEFINED ((uint64_t)(-1))//(pow(2.0,64.0) - 1) +#define IOD_COUNT_UNDEFINED ((uint64_t)(-1))//(pow(2.0,64.0) - 1) +#define H5VL_IOD_DEBUG 1 + +/* Structure for a span of fixed-length data in a type */ + typedef struct H5VL_iod_fl_span_t { + size_t offset; /* Offset of start of span in type */ + size_t size; /* Size of span */ +} H5VL_iod_fl_span_t; + +/* Structure for a variable-length type in a type */ +typedef struct H5VL_iod_vl_info_t { + size_t offset; /* Offset of vlen in type */ + struct H5VL_iod_type_info_t *base_type; /* Type info for vlen base type. Set to NULL if this vlen is a vl string. */ +} H5VL_iod_vl_info_t; + +/* Structure containing information about a type to use during I/O */ +typedef struct H5VL_iod_type_info_t { + size_t size; /* Size of one element of this type */ + size_t num_fl_spans; /* Size of fl_spans array */ + H5VL_iod_fl_span_t *fl_spans; /* Array of spans of fixed-length data in type */ + size_t num_vls; /* Size of vls array */ + H5VL_iod_vl_info_t *vls; /* Array of variable-length types in type */ + size_t rc; /* Number of references to this struct */ +} H5VL_iod_type_info_t; + +typedef enum H5VL_iod_state_t { + H5VL_IOD_PENDING, + H5VL_IOD_COMPLETED, + H5VL_IOD_CANCELLED +} H5VL_iod_state_t; + +typedef struct dims_t { + int rank; + hsize_t *size; +} dims_t; + +typedef struct coords_t { + int rank; + uint64_t *start_cell; + uint64_t *end_cell; +} coords_t; + +typedef struct name_t { + size_t size; + ssize_t *value_size; + char *value; +} name_t; + +typedef struct binary_buf_t { + size_t buf_size; + void *buf; +} binary_buf_t; + +typedef struct value_t { + size_t val_size; + void *val; +} value_t; + +typedef struct axe_t { + AXE_task_t axe_id; + AXE_task_t start_range; + size_t count; + size_t num_parents; + AXE_task_t *parent_axe_ids; +} axe_t; + +typedef struct iod_handles_t { + iod_handle_t rd_oh; + iod_handle_t wr_oh; +} iod_handles_t; + +#endif /* H5_HAVE_EFF */ + +H5_DLL int H5VL_iod_get_type_info(hid_t type_id, H5VL_iod_type_info_t *type_info); +H5_DLL void H5VL_iod_type_info_reset(H5VL_iod_type_info_t *type_info); +H5_DLL int H5VL_iod_create_segments_send(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char **vl_lengths, size_t *vl_lengths_nused, void ***free_list, + size_t *free_list_len); +H5_DLL int H5VL_iod_create_segments_recv(char *buf, H5VL_iod_type_info_t *type_info, + size_t nelem, hg_bulk_segment_t **segments, size_t *num_segments, + char *vl_lengths, size_t vl_lengths_nused, void ***free_list, + size_t *free_list_len); +H5_DLL void H5VL_iod_free_list_free(void **free_list, size_t free_list_len); + +#ifdef H5_HAVE_EFF + +H5_DLL uint64_t H5_checksum_crc64(const void *buf, size_t buf_size); +H5_DLL uint64_t H5_checksum_crc64_segments(hg_bulk_segment_t *segments, size_t count); +H5_DLL uint64_t H5_checksum_crc64_fragments(void **buf, size_t *buf_size, size_t count); + +H5_DLL int hg_proc_ret_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_axe_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_size_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_hid_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_htri_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_hbool_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_iod_obj_id_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_iod_handle_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_iod_handles_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_dims_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_axe_ids_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_name_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_value_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_binary_buf_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_linfo_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_oinfo_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_coords_t(hg_proc_t proc, void *data); +H5_DLL int hg_proc_hrpl_t(hg_proc_t proc, void *data); + +MERCURY_GEN_PROC(analysis_execute_in_t, + ((axe_t)(axe_info)) + ((hid_t)(query_id)) + ((hg_const_string_t)(file_name)) + ((hg_const_string_t)(obj_name)) + ((hg_const_string_t)(split_script)) + ((hg_const_string_t)(combine_script))) +MERCURY_GEN_PROC(analysis_execute_out_t, ((int32_t)(ret))) +MERCURY_GEN_PROC(analysis_farm_in_t, + ((iod_handle_t)(coh)) + ((hid_t)(query_id)) + ((hid_t)(space_id)) + ((hid_t)(type_id)) + ((uint64_t)(rtid)) + ((iod_obj_id_t)(obj_id)) + ((size_t)(num_cells)) + ((coords_t)(coords)) + ((uint32_t)(server_idx)) + ((hg_const_string_t)(split_script))) +MERCURY_GEN_PROC(analysis_farm_out_t, + ((int32_t)(ret)) + ((uint64_t)(axe_id)) + ((uint32_t)(server_idx)) + ((hg_bulk_t)(bulk_handle)) + ((hid_t)(type_id)) + ((size_t)(num_elmts))) +MERCURY_GEN_PROC(analysis_transfer_in_t, + ((hg_bulk_t)(bulk_handle)) + ((uint64_t)(axe_id)) + ) +MERCURY_GEN_PROC(analysis_transfer_out_t, + ((int32_t)(ret)) + ) + +MERCURY_GEN_PROC(eff_init_in_t, + ((uint32_t)(proc_num))) + +MERCURY_GEN_PROC(file_create_in_t, + ((axe_t)(axe_info)) + ((hg_const_string_t)(name)) + ((uint32_t)(flags)) + ((iod_obj_id_t)(root_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((iod_obj_id_t)(oidkv_id)) + ((uint32_t)(num_peers)) + ((hid_t)(fapl_id)) + ((hid_t)(fcpl_id))) +MERCURY_GEN_PROC(file_create_out_t, + ((iod_handle_t)(coh)) + ((iod_handles_t)(root_oh))) +MERCURY_GEN_PROC(file_open_in_t, + ((axe_t)(axe_info)) + ((hg_const_string_t)(name)) + ((uint32_t)(flags)) + ((hbool_t)(acquire)) + ((hid_t)(fapl_id))) +MERCURY_GEN_PROC(file_open_out_t, + ((iod_handle_t)(coh)) + ((iod_handles_t)(root_oh)) + ((uint64_t)(kv_oid_index)) + ((uint64_t)(array_oid_index)) + ((uint64_t)(blob_oid_index)) + ((iod_obj_id_t)(root_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((iod_obj_id_t)(oidkv_id)) + ((uint64_t)(c_version)) + ((hid_t)(fcpl_id))) +MERCURY_GEN_PROC(file_close_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(root_oh)) + ((iod_obj_id_t)(root_id)) + ((iod_obj_id_t)(max_kv_index)) + ((iod_obj_id_t)(max_array_index)) + ((iod_obj_id_t)(max_blob_index))) + +MERCURY_GEN_PROC(attr_create_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_attrkv_id)) + ((iod_obj_id_t)(attr_id)) + ((iod_obj_id_t)(mdkv_id)) + ((hg_const_string_t)(path)) + ((hg_const_string_t)(attr_name)) + ((hid_t)(type_id)) + ((hid_t)(space_id))) +MERCURY_GEN_PROC(attr_create_out_t, + ((iod_handles_t)(iod_oh))) +MERCURY_GEN_PROC(attr_open_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_attrkv_id)) + ((hg_const_string_t)(path)) + ((hg_const_string_t)(attr_name))) +MERCURY_GEN_PROC(attr_open_out_t, + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((hid_t)(type_id)) + ((hid_t)(space_id))) +MERCURY_GEN_PROC(attr_op_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_attrkv_id)) + ((hg_const_string_t)(path)) + ((hg_const_string_t)(attr_name))) +MERCURY_GEN_PROC(attr_rename_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_attrkv_id)) + ((hg_const_string_t)(path)) + ((hg_const_string_t)(old_attr_name)) + ((hg_const_string_t)(new_attr_name))) +MERCURY_GEN_PROC(attr_io_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((uint64_t)(checksum)) + ((hid_t)(space_id)) + ((hid_t)(type_id)) + ((hg_bulk_t)(bulk_handle))) +MERCURY_GEN_PROC(attr_close_in_t, + ((axe_t)(axe_info)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +MERCURY_GEN_PROC(group_create_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(grp_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hg_const_string_t)(name)) + ((hid_t)(gapl_id)) + ((hid_t)(gcpl_id)) + ((hid_t)(lcpl_id))) +MERCURY_GEN_PROC(group_create_out_t, + ((iod_handles_t)(iod_oh))) +MERCURY_GEN_PROC(group_open_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(name)) + ((hid_t)(gapl_id))) +MERCURY_GEN_PROC(group_open_out_t, + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hid_t)(gcpl_id))) +MERCURY_GEN_PROC(group_close_in_t, + ((axe_t)(axe_info)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +MERCURY_GEN_PROC(map_create_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(map_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hg_const_string_t)(name)) + ((hid_t)(keytype_id)) + ((hid_t)(valtype_id)) + ((hid_t)(mapl_id)) + ((hid_t)(mcpl_id)) + ((hid_t)(lcpl_id))) +MERCURY_GEN_PROC(map_create_out_t, + ((iod_handles_t)(iod_oh))) +MERCURY_GEN_PROC(map_open_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(name)) + ((hid_t)(mapl_id))) +MERCURY_GEN_PROC(map_open_out_t, + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hid_t)(keytype_id)) + ((hid_t)(valtype_id)) + ((hid_t)(mcpl_id))) +MERCURY_GEN_PROC(map_set_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((hid_t)(key_maptype_id)) + ((hid_t)(key_memtype_id)) + ((binary_buf_t)(key)) + ((hid_t)(val_maptype_id)) + ((hid_t)(val_memtype_id)) + ((uint64_t)(val_checksum)) + ((hg_bulk_t)(val_handle)) + ((hid_t)(dxpl_id))) +MERCURY_GEN_PROC(map_get_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((hid_t)(key_maptype_id)) + ((hid_t)(key_memtype_id)) + ((binary_buf_t)(key)) + ((hid_t)(val_maptype_id)) + ((hid_t)(val_memtype_id)) + ((hbool_t)(val_is_vl)) + ((hg_bulk_t)(val_handle)) + ((size_t)(val_size)) + ((hid_t)(dxpl_id))) +MERCURY_GEN_PROC(map_get_out_t, + ((int32_t)(ret)) + ((size_t)(val_size)) + ((uint64_t)(val_cs))) +MERCURY_GEN_PROC(map_get_count_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) +MERCURY_GEN_PROC(map_op_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((hid_t)(key_maptype_id)) + ((hid_t)(key_memtype_id)) + ((binary_buf_t)(key))) +MERCURY_GEN_PROC(map_close_in_t, + ((axe_t)(axe_info)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +MERCURY_GEN_PROC(dset_create_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(dset_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hg_const_string_t)(name)) + ((hid_t)(dapl_id)) + ((hid_t)(dcpl_id)) + ((hid_t)(lcpl_id)) + ((hid_t)(type_id)) + ((hid_t)(space_id))) +MERCURY_GEN_PROC(dset_create_out_t, + ((iod_handles_t)(iod_oh))) +MERCURY_GEN_PROC(dset_open_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(name)) + ((hid_t)(dapl_id))) +MERCURY_GEN_PROC(dset_open_out_t, + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hid_t)(dcpl_id)) + ((hid_t)(type_id)) + ((hid_t)(space_id))) +MERCURY_GEN_PROC(dset_set_extent_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((dims_t)(dims))) +MERCURY_GEN_PROC(dset_io_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((hid_t)(dset_type_id)) + ((hid_t)(mem_type_id)) + ((hid_t)(space_id)) + ((hid_t)(dxpl_id)) + ((uint64_t)(checksum)) + ((hg_bulk_t)(bulk_handle)) + ((hg_bulk_t)(vl_len_bulk_handle)) + ((uint64_t)(axe_id))) +MERCURY_GEN_PROC(dset_read_out_t, + ((int32_t)(ret)) + ((uint64_t)(cs)) + ((size_t)(buf_size))) +MERCURY_GEN_PROC(dset_close_in_t, + ((axe_t)(axe_info)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +MERCURY_GEN_PROC(dtype_commit_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(dtype_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hg_const_string_t)(name)) + ((hid_t)(tapl_id)) + ((hid_t)(tcpl_id)) + ((hid_t)(lcpl_id)) + ((hid_t)(type_id))) +MERCURY_GEN_PROC(dtype_commit_out_t, + ((iod_handles_t)(iod_oh))) +MERCURY_GEN_PROC(dtype_open_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(name)) + ((hid_t)(tapl_id))) +MERCURY_GEN_PROC(dtype_open_out_t, + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hid_t)(tcpl_id)) + ((hid_t)(type_id))) +MERCURY_GEN_PROC(dtype_close_in_t, + ((axe_t)(axe_info)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +MERCURY_GEN_PROC(link_create_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((int8_t)(create_type)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(loc_name)) + ((iod_handles_t)(target_loc_oh)) + ((iod_obj_id_t)(target_loc_id)) + ((iod_obj_id_t)(target_mdkv_id)) + ((hg_const_string_t)(target_name)) + ((hg_const_string_t)(link_value)) + ((hid_t)(lapl_id)) + ((hid_t)(lcpl_id))) +MERCURY_GEN_PROC(link_move_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((hbool_t)(copy_flag)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(src_loc_oh)) + ((iod_obj_id_t)(src_loc_id)) + ((hg_const_string_t)(src_loc_name)) + ((iod_handles_t)(dst_loc_oh)) + ((iod_obj_id_t)(dst_loc_id)) + ((hg_const_string_t)(dst_loc_name)) + ((hid_t)(lapl_id)) + ((hid_t)(lcpl_id))) +MERCURY_GEN_PROC(link_op_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(path))) +MERCURY_GEN_PROC(link_get_val_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((hg_const_string_t)(path)) + ((uint64_t)(length))) +MERCURY_GEN_PROC(link_get_val_out_t, + ((int32_t)(ret)) + ((value_t)(value))) + +MERCURY_GEN_PROC(object_token_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((iod_handle_t)(coh)) + ((iod_obj_id_t)(iod_id)) + ((uint64_t)(trans_num))) +MERCURY_GEN_PROC(object_op_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_mdkv_id)) + ((iod_obj_id_t)(loc_attrkv_id)) + ((hg_const_string_t)(loc_name))) +MERCURY_GEN_PROC(object_open_out_t, + ((int32_t)(obj_type)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id)) + ((iod_obj_id_t)(mdkv_id)) + ((iod_obj_id_t)(attrkv_id)) + ((hid_t)(cpl_id)) + ((hid_t)(id1)) + ((hid_t)(id2))) +MERCURY_GEN_PROC(object_copy_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(src_loc_oh)) + ((iod_obj_id_t)(src_loc_id)) + ((hg_const_string_t)(src_loc_name)) + ((iod_handles_t)(dst_loc_oh)) + ((iod_obj_id_t)(dst_loc_id)) + ((hg_const_string_t)(dst_loc_name)) + ((hid_t)(ocpypl_id)) + ((hid_t)(lcpl_id))) +MERCURY_GEN_PROC(object_set_comment_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((uint64_t)(trans_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_mdkv_id)) + ((hg_const_string_t)(path)) + ((hg_const_string_t)(comment))) +MERCURY_GEN_PROC(object_get_comment_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((iod_handle_t)(coh)) + ((iod_handles_t)(loc_oh)) + ((iod_obj_id_t)(loc_id)) + ((iod_obj_id_t)(loc_mdkv_id)) + ((hg_const_string_t)(path)) + ((uint64_t)(length))) +MERCURY_GEN_PROC(object_get_comment_out_t, + ((int32_t)(ret)) + ((name_t)(name))) + +MERCURY_GEN_PROC(rc_acquire_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(c_version)) + ((hid_t)(rcapl_id))) +MERCURY_GEN_PROC(rc_acquire_out_t, + ((int32_t)(ret)) + ((uint64_t)(c_version))) +MERCURY_GEN_PROC(rc_release_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(c_version))) +MERCURY_GEN_PROC(rc_persist_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(c_version))) +MERCURY_GEN_PROC(rc_snapshot_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((hg_const_string_t)(snapshot_name)) + ((uint64_t)(c_version))) + +MERCURY_GEN_PROC(tr_start_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(trans_num)) + ((hid_t)(trspl_id))) +MERCURY_GEN_PROC(tr_finish_in_t, + ((axe_t)(axe_info)) + ((uint32_t)(cs_scope)) + ((iod_handle_t)(coh)) + ((uint64_t)(trans_num)) + ((hbool_t)(acquire)) + ((uint32_t)(client_rank)) + ((iod_obj_id_t)(oidkv_id)) + ((iod_obj_id_t)(kv_oid_index)) + ((iod_obj_id_t)(array_oid_index)) + ((iod_obj_id_t)(blob_oid_index)) + ((hid_t)(trfpl_id))) +MERCURY_GEN_PROC(tr_set_depend_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(child_trans_num)) + ((uint64_t)(parent_trans_num))) +MERCURY_GEN_PROC(tr_skip_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(start_trans_num)) + ((uint64_t)(count))) +MERCURY_GEN_PROC(tr_abort_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint64_t)(trans_num))) + +MERCURY_GEN_PROC(prefetch_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((hid_t)(apl_id)) + ((int32_t)(obj_type)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) +MERCURY_GEN_PROC(evict_in_t, + ((axe_t)(axe_info)) + ((iod_handle_t)(coh)) + ((uint32_t)(cs_scope)) + ((uint64_t)(rcxt_num)) + ((hrpl_t)(replica_id)) + ((hid_t)(apl_id)) + ((int32_t)(obj_type)) + ((iod_handles_t)(iod_oh)) + ((iod_obj_id_t)(iod_id))) + +#endif /* H5_HAVE_EFF */ +#endif /* _H5VLiod_common_H */ diff --git a/src/H5VLiod_dset.c b/src/H5VLiod_dset.c new file mode 100644 index 0000000..4b37995 --- /dev/null +++ b/src/H5VLiod_dset.c @@ -0,0 +1,1833 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ +#include "H5Dpkg.h" /* Datasets */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Gprivate.h" /* IDs */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side dataset routines. + */ + +/* User data for VL traverssal */ +typedef struct { + iod_handle_t coh; + iod_obj_id_t iod_id; + iod_handles_t iod_oh; + hid_t space_id; + uint8_t *buf_ptr; + size_t buf_size; + size_t nelmts; + size_t cur_seg; + hg_bulk_segment_t *segments; + iod_trans_id_t wtid; + iod_trans_id_t rtid; +} H5VL_iod_server_vl_write_t; + +static herr_t +H5VL__iod_server_vl_data_write(iod_handle_t coh, iod_obj_id_t iod_id, iod_handles_t iod_oh, + hid_t space_id, hid_t mem_type_id, hid_t dset_type_id, + H5VL_iod_type_info_t type_info, size_t nelmts, + size_t num_segments, hg_bulk_segment_t *segments, + hid_t dxpl_id, iod_trans_id_t wtid, iod_trans_id_t rtid, + na_addr_t source, hg_bulk_t bulk_handle, uint32_t cs_scope); + +static herr_t +H5VL__iod_server_vl_data_read(iod_handle_t coh, AXE_engine_t axe_engine, AXE_task_t axe_id, + size_t nelmts, void *buf, + hid_t dxpl_id, iod_trans_id_t rtid); + +static herr_t +H5VL__iod_server_vl_data_write_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, + const hsize_t *point, void *_udata); + +static iod_obj_id_t +H5VL__iod_get_vl_blob_oid(iod_obj_id_t dset_id, hid_t space_id, const hsize_t *point) +{ + hsize_t dims[H5S_MAX_RANK]; + uint64_t cur; + int ndims, i; + iod_obj_id_t blob_id = 0; + + ndims = H5Sget_simple_extent_dims(space_id, dims, NULL); + + /* set the BLOB ID algorithmically from the coordinate */ + cur = 1; + for(i=0 ; i<ndims ; i++) { + blob_id += cur*point[i]; + cur *= dims[i]; + } + + /* copy the last 20 bits of the dataset ID into bits 58->38 of the BLOB ID */ + for(i=0 ; i<20 ; i++) { + (dset_id & (((uint64_t)0x1) << i)) ? + (blob_id |= (((uint64_t)0x1) << (38+i+1))) : + (blob_id &= ~(((uint64_t)0x1) << (38+i+1))); + } + + /* set the BLOB for dset elements ID */ + blob_id |= (((uint64_t)0x1) << 59); + + /* Set IOD bit parameters for the BLOB ID */ + IOD_OBJID_SETTYPE(blob_id, IOD_OBJ_BLOB); + IOD_OBJID_SETOWNER_APP(blob_id); + + return blob_id; +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_create_cb + * + * Purpose: Creates a dset as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_create_in_t *input = (dset_create_in_t *)op_data->input; + dset_create_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t dset_id = input->dset_id; /* The ID of the dataset that needs to be created */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV to be created */ + iod_obj_id_t attrkv_id = input->attrkv_id; /* The ID of the attirbute KV to be created */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + hid_t space_id = input->space_id; + hid_t dcpl_id; + iod_handles_t dset_oh, cur_oh; + iod_handle_t mdkv_oh; + iod_obj_id_t cur_id; + const char *name = input->name; /* name of dset including path to create */ + char *last_comp; /* the name of the dataset obtained from the last component in the path */ + iod_array_struct_t array; /* IOD array struct describing the dataset's dimensions */ + scratch_pad sp; + iod_ret_t ret = 0; + int step = 0; + hbool_t enable_checksum = FALSE; + H5T_class_t dt_class; + iod_hint_list_t *obj_create_hint = NULL; + iod_size_t array_dims[H5S_MAX_RANK], current_dims[H5S_MAX_RANK]; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset create %s at %"PRIu64"\n", name, loc_handle.wr_oh.cookie); +#endif + + if(H5P_DEFAULT == input->dcpl_id) + input->dcpl_id = H5Pcopy(H5P_DATASET_CREATE_DEFAULT); + dcpl_id = input->dcpl_id; + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_ocpl_enable_checksum(dcpl_id, &enable_checksum) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* the traversal will retrieve the location where the dataset needs + to be created. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_handle, name, wtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Creating Dataset ID %"PRIx64" ",dset_id); + fprintf(stderr, "at (OH %"PRIu64" ID %"PRIx64") ", cur_oh.wr_oh.cookie, cur_id); + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) + fprintf(stderr, "with Data integrity ENABLED\n"); + else + fprintf(stderr, "with Data integrity DISABLED\n"); +#endif + + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + dt_class = H5Tget_class(input->type_id); + /* Set the IOD array creation parameters */ + if(dt_class == H5T_VLEN || + (dt_class == H5T_STRING && H5Tis_variable_str(input->type_id)) ) + array.cell_size = sizeof(iod_obj_id_t) + sizeof(iod_size_t); + else + array.cell_size = (uint32_t)H5Tget_size(input->type_id); + + array.num_dims = (uint32_t)H5Sget_simple_extent_ndims(space_id); + + /* Handle Scalar Dataspaces (set rank and current dims size to 1) */ + if(0 == array.num_dims) { + array.num_dims = 1; + array.firstdim_max = 1; + current_dims[0] = 1; + array.current_dims = current_dims; + } + else { + if(H5Sget_simple_extent_dims(space_id, current_dims, array_dims) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get dimentions' sizes"); + + if(H5S_UNLIMITED == array_dims[0]) { + array_dims[0] = current_dims[0]; + array.firstdim_max = IOD_DIMLEN_UNLIMITED; + } + else { + array.firstdim_max = array_dims[0]; + } + + array.current_dims = current_dims; + } + + /* MSC - Add chunking support */ + array.chunk_dims = NULL; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "now creating the dataset %s cellsize %d num dimensions %d\n", + last_comp, array.cell_size, array.num_dims); +#endif + + /* create the dataset */ + ret = iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_ARRAY, NULL, + &array, &dset_id, NULL); + if(ret != 0) { + fprintf(stderr, "ret: %d error: %s\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Array object"); + } + + if (iod_obj_open_write(coh, dset_id, wtid, NULL, &dset_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Dataset for Write"); + if (iod_obj_open_read(coh, dset_id, wtid, NULL, &dset_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Dataset for Read"); + + step ++; + + /* create the attribute KV object for the dataset */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, NULL, NULL, &attrkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create attribute KV object"); + + /* create the metadata KV object for the dataset */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, NULL, NULL, &mdkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = attrkv_id; + sp[2] = IOD_OBJ_INVALID; + sp[3] = IOD_OBJ_INVALID; + + /* set scratch pad in dataset */ + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t sp_cs = 0; + + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + + if (iod_obj_set_scratch(dset_oh.wr_oh, wtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + else { + if (iod_obj_set_scratch(dset_oh.wr_oh, wtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + + /* Open Metadata KV object for write */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create scratch pad"); + + step ++; + + /* insert plist metadata */ + if(H5VL_iod_insert_plist(mdkv_oh, wtid, dcpl_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh, wtid, (uint64_t)1, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert object type metadata */ + if(H5VL_iod_insert_object_type(mdkv_oh, wtid, H5I_DATASET, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* MSC - need to check size of datatype if it fits in + entry otherwise create a BLOB*/ + + /* insert datatype metadata */ + if(H5VL_iod_insert_datatype(mdkv_oh, wtid, input->type_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert dataspace metadata */ + if(H5VL_iod_insert_dataspace(mdkv_oh, wtid, space_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close the Metadata KV object */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + step --; + + /* add link in parent group to current object */ + if(H5VL_iod_insert_new_link(cur_oh.wr_oh, wtid, last_comp, + H5L_TYPE_HARD, &dset_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + + output.iod_oh.rd_oh.cookie = dset_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = dset_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset create, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(loc_handle.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + /* return an UNDEFINED oh to the client if the operation failed */ + if(ret_value < 0) { + fprintf(stderr, "failed to create Dataset\n"); + + if(step == 2) { + iod_obj_close(mdkv_oh, NULL, NULL); + step --; + } + if(step == 1) { + iod_obj_close(dset_oh.rd_oh, NULL, NULL); + iod_obj_close(dset_oh.wr_oh, NULL, NULL); + } + + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + if(obj_create_hint) { + free(obj_create_hint); + obj_create_hint = NULL; + } + + last_comp = (char *)H5MM_xfree(last_comp); + input = (dset_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_open_cb + * + * Purpose: Opens a dataset as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_open_in_t *input = (dset_open_in_t *)op_data->input; + dset_open_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + const char *name = input->name; /* name of dset including path to open */ + iod_obj_id_t dset_id; /* ID of the dataset to open */ + iod_handles_t dset_oh; + iod_handle_t mdkv_oh; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset open %s at (OH %"PRIu64" ID %"PRIx64")\n", + name, loc_handle.rd_oh.cookie, loc_id); +#endif + + /* Traverse Path and open dset */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, name, rtid, + cs_scope, &dset_id, &dset_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* open a write handle on the ID. */ + if (iod_obj_open_write(coh, dset_id, rtid, NULL, &dset_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current dset"); + + /* get scratch pad of the dataset */ + if(iod_obj_get_scratch(dset_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.dcpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dcpl"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, H5VL_IOD_KEY_OBJ_DATATYPE, + cs_scope, NULL, &output.type_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &output.space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + output.iod_id = dset_id; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + output.iod_oh.rd_oh.cookie = dset_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = dset_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + fprintf(stderr, "DSET open FAILED\n"); + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.space_id = FAIL; + output.type_id = FAIL; + output.dcpl_id = FAIL; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (dset_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_read_cb + * + * Purpose: Reads from IOD into the function shipper BDS handle. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_read_cb(AXE_engine_t axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_io_in_t *input = (dset_io_in_t *)op_data->input; + dset_read_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t iod_oh = input->iod_oh; /* dset object handle */ + iod_obj_id_t iod_id = input->iod_id; /* dset ID */ + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hid_t space_id = input->space_id; /* file space selection */ + hid_t dxpl_id; + hid_t src_id = input->dset_type_id; /* the datatype of the dataset's element */ + hid_t dst_id = input->mem_type_id; /* the memory type of the elements */ + iod_trans_id_t rtid = input->rcxt_num; + //uint32_t cs_scope = input->cs_scope; + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + size_t size, buf_size = 0; + void *buf = NULL; /* buffer to hold outgoing data */ + iod_checksum_t cs = 0; /* checksum value */ + uint32_t raw_cs_scope; + hbool_t is_vl_data; + size_t nelmts; /* number of elements selected to read */ + na_addr_t dest = HG_Handler_get_addr(op_data->hg_handle); /* destination address to push data to */ + hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the dset here or if it was already open */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the dataset if we don't have the handle yet */ + if(iod_oh.rd_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, iod_id, rtid, NULL /*hints*/, &iod_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset Read on OH %"PRIu64" OID %"PRIx64"\n", iod_oh.rd_oh.cookie, iod_id); +#endif + + if(H5P_DEFAULT == input->dxpl_id) + input->dxpl_id = H5Pcopy(H5P_DATASET_XFER_DEFAULT); + dxpl_id = input->dxpl_id; + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* retrieve size of bulk data asked for to be read */ + size = HG_Bulk_handle_get_size(bulk_handle); + + /* allocate buffer to hold data */ + if(NULL == (buf = malloc(size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* get the number of points selected */ + nelmts = (size_t)H5Sget_select_npoints(space_id); + + /* Adjust buffer is type conversion is needed. If the data + elements are of variable length, just return that they are in + is_vl_data for special processing */ + if(H5VL__iod_server_adjust_buffer(dst_id, src_id, nelmts, dxpl_id, + size, &buf, &is_vl_data, &buf_size) < 0) { + fprintf(stderr, "failed to setup write operation"); + ret_value = FAIL; + goto done; + } + + if(!is_vl_data) { + size_t elmt_size; + + /* If the data is not VL, we can read the data from the array the normal way */ + elmt_size = H5Tget_size(src_id); + if(H5VL__iod_server_final_io(iod_oh.rd_oh, space_id, elmt_size, FALSE, + buf, buf_size, (uint64_t)0, raw_cs_scope, rtid) < 0) { + fprintf(stderr, "can't read from array object\n"); + ret_value = FAIL; + goto done; + } + + { + hbool_t flag = FALSE; + + /* do data conversion */ + if(H5Tconvert(src_id, dst_id, nelmts, buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + if(raw_cs_scope) { + /* calculate a checksum for the data to be sent */ + cs = H5_checksum_crc64(buf, size); + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + /* MSC - check if client requested to corrupt data */ + if(H5Pget_dxpl_inject_corruption(dxpl_id, &flag) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read property list"); + if(flag) { + fprintf(stderr, "Injecting a bad data value to cause corruption \n"); + ((char *)buf)[0] = 54; + } + } + } + else { + /* If the data is of variable length, special access is required */ + if(H5VL__iod_server_vl_data_read(coh, axe_engine, input->axe_id, nelmts, + buf, dxpl_id, rtid) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + } + + /* Create a new block handle to write the data */ + HG_Bulk_handle_create(buf, size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); +done: + + output.ret = ret_value; + output.cs = cs; + output.buf_size = buf_size; + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset read, checksum %016lX, sending response to client\n", cs); +#endif + + input = (dset_io_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + if(buf) { + free(buf); + buf=NULL; + } + + /* close the dataset if we opened it in this routine */ + if(TRUE == opened_locally) { + if(iod_obj_close(iod_oh.rd_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_read_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_get_vl_size_cb + * + * Purpose: Retrieve the size required to store a selection of VL data. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_io_in_t *input = (dset_io_in_t *)op_data->input; + dset_read_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t iod_oh = input->iod_oh; /* dset object handle */ + iod_obj_id_t iod_id = input->iod_id; /* dset ID */ + hid_t type_id = input->mem_type_id; /* the datatype of the dataset's element */ + hid_t space_id = input->space_id; /* file space selection */ + //hid_t dxpl_id = input->dxpl_id; /* transfer property list */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + size_t buf_size, elmt_size; + void *buf = NULL; /* buffer to hold blob IDs and sizes */ + size_t nelmts; /* number of elements selected to read */ + uint8_t *buf_ptr = NULL; + na_addr_t dest = HG_Handler_get_addr(op_data->hg_handle); /* destination address to push data to */ + hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the dset here or if it was already open */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the dataset if we don't have the handle yet */ + if(iod_oh.rd_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, rtid, NULL /*hints*/, &iod_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + /* get the number of points selected */ + nelmts = (size_t)H5Sget_select_npoints(space_id); + elmt_size = sizeof(iod_obj_id_t) + sizeof(iod_size_t); + + /* allocate buffer to hold blob IDs */ + if(NULL == (buf = malloc(nelmts * elmt_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* buffer always contains the length of each sequence, so + initialize it to the size required to store those lengths */ + buf_size = nelmts * 8;//sizeof(size_t); + + /* read the array values containing the BLOB IDs and lengths */ + if(H5VL__iod_server_final_io(iod_oh.rd_oh, space_id, elmt_size, FALSE, + buf, buf_size, (uint64_t)0, cs_scope, rtid) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* MSC - create a bulk block handle. Mercury does not support + segmented handles yet, so we need a temporrary buffer. */ + { + size_t *temp_buf = NULL; + uint8_t *temp_ptr; + size_t temp_size; + unsigned u; + H5VL_iod_type_info_t type_info; + + if(NULL == (temp_buf = (size_t *)malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate size buffer"); + + buf_ptr = (uint8_t *)buf; + temp_ptr = (uint8_t *)temp_buf; + + /* Get type info */ + if(H5VL_iod_get_type_info(type_id, &type_info) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + assert(1 == type_info.num_vls); + + /* copy just the size of each VL element into the temp buffer */ + for(u=0 ; u<nelmts ; u++) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %u with BLOB ID %"PRIx64" size %zu\n", + u, *((iod_obj_id_t *)buf_ptr),*((size_t *)(buf_ptr+sizeof(iod_obj_id_t)))); +#endif + + temp_size = *((size_t *)(buf_ptr+sizeof(iod_obj_id_t))); + + if(type_info.vls[0].base_type) { + /* Standard vlen */ + temp_size = temp_size / type_info.vls[0].base_type->size; + } + else { + /* VL string; add space for NULL termination */ + temp_size ++; + } + + UINT64ENCODE(temp_ptr, (uint64_t)temp_size); + buf_ptr += elmt_size; + } + + H5VL_iod_type_info_reset(&type_info); + + /* Create a new block handle to write the data */ + HG_Bulk_handle_create(temp_buf, buf_size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); + + if(temp_buf) { + free(temp_buf); + temp_buf = NULL; + } + } + + op_data->output = buf; + +done: + + output.ret = ret_value; + output.cs = 0; + output.buf_size = buf_size; + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset get vl size (%zu), sending response to client\n", buf_size); +#endif + + input = (dset_io_in_t *)H5MM_xfree(input); + + /* close the dataset if we opened it in this routine */ + if(TRUE == opened_locally) { + if(iod_obj_close(iod_oh.rd_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_get_vl_size_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_write_cb + * + * Purpose: Writes from IOD into the function shipper BDS handle. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_io_in_t *input = (dset_io_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t iod_oh = input->iod_oh; /* dset object handle */ + iod_obj_id_t iod_id = input->iod_id; /* dset ID */ + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hg_bulk_t vl_len_bulk_handle = input->vl_len_bulk_handle; /* bulk handle for vlen length */ + hid_t space_id = input->space_id; /* file space selection */ + uint64_t cs = input->checksum; /* checksum recieved for data */ + hid_t src_id = input->mem_type_id; /* the memory type of the elements */ + hid_t dst_id = input->dset_type_id; /* the datatype of the dataset's element */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + //uint32_t cs_scope = input->cs_scope; + hid_t dxpl_id; + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + size_t size, buf_size; + hbool_t is_vl_data; + iod_checksum_t data_cs = 0; + uint32_t raw_cs_scope; + H5VL_iod_type_info_t type_info; + void *buf = NULL; + size_t nelmts; /* number of elements selected to read */ + hbool_t flag = FALSE; /* temp flag to indicate whether corruption will be inserted */ + na_addr_t source = HG_Handler_get_addr(op_data->hg_handle); /* source address to pull data from */ + hbool_t opened_locally = FALSE; /* flag to indicate whether we opened the dset here or if it was already open */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the dataset if we don't have the handle yet */ + if(iod_oh.wr_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, wtid, NULL /*hints*/, &iod_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open dataset for write"); + opened_locally = TRUE; + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset Write on OH %"PRIu64" OID %"PRIx64"\n", iod_oh.wr_oh.cookie, iod_id); +#endif + + if(H5P_DEFAULT == input->dxpl_id) + input->dxpl_id = H5Pcopy(H5P_DATASET_XFER_DEFAULT); + dxpl_id = input->dxpl_id; + + nelmts = (size_t)H5Sget_select_npoints(space_id); + + /* Get type info */ + if(H5VL_iod_get_type_info(src_id, &type_info) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "failed to get datatype info"); + + if(type_info.vls) { + hg_bulk_segment_t *segments = NULL; + size_t num_segments = 0; + char *vl_lengths = NULL; + size_t vl_lengths_size = 0; + void **free_list = NULL; + size_t free_list_len = 0; + hg_bulk_t vl_len_handle; + + /* Get size of vl_lengths array and allocate local buffer */ + vl_lengths_size = HG_Bulk_handle_get_size(vl_len_bulk_handle); + if(vl_lengths_size == 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "no vlen lengths sent"); + if(NULL == (vl_lengths = (char *)malloc(vl_lengths_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate vlen lengths buffer"); + + /* Register local memory buffer */ + if(HG_SUCCESS != HG_Bulk_handle_create(vl_lengths, vl_lengths_size, + HG_BULK_READWRITE, &vl_len_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "create vlen bulk handle"); + + /* Receive vl length data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, vl_len_bulk_handle, + vl_len_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read vlen lengths bulk data"); + + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for vlen lengths bulk data operation"); + + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(vl_len_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free vlen bulk handle"); + + if(NULL == (buf = malloc(nelmts * type_info.size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate data buffer"); + + /* Create segments from vl lengths */ + if(H5VL_iod_create_segments_recv((char *)buf, &type_info, nelmts, &segments, &num_segments, + vl_lengths, vl_lengths_size, &free_list, &free_list_len) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create segments for bulk data transfer"); + assert(segments); + +#if 1 + if(H5VL__iod_server_vl_data_write(coh, iod_id, iod_oh, space_id, src_id, dst_id, type_info, + nelmts, num_segments, segments, dxpl_id, wtid, rtid, + source, bulk_handle, raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write VL data to array object"); + +#else + { + int i; + size_t j = 0; + uint64_t *buf_ptr = (uint64_t *)vl_lengths; + + fprintf(stderr, "Buffer size: %zu\n", nelmts * type_info.size); + /* Print VL length DATA */ + for(i = 0; i < vl_lengths_size/sizeof(size_t); i++) { + fprintf(stderr, "Element %d size %lu segment %lu, size %zu\n", i, vl_lengths[j], + segments[i].address, segments[i].size); + j+=8; + } /* end for */ + } + + /* Register non-contiguous memory segments */ + if(HG_SUCCESS != HG_Bulk_handle_create_segments(segments, num_segments, + HG_BULK_READWRITE, &vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Bulk Data Handle"); + + /* Receive bulk data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, vl_data_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read bulk data"); + + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for bulk data operation"); + + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free bulk handle"); + + { + hvl_t *buf_ptr = (hvl_t *)buf; + int i, j; + + /* Print VL DATA */ + for(i = 0; i < 5; i++) { + int temp = (int)buf_ptr[i].len; + + fprintf(stderr, "Element %d size %zu: ", i, temp); + for(j = 0; j < temp; j++) + fprintf(stderr, "%d ",((unsigned int *)buf_ptr[i].p)[j]); + fprintf(stderr, "\n"); + } /* end for */ + } +#endif + + /* Free segments */ + if(segments) { + free(segments); + segments = NULL; + num_segments = 0; + } /* end if */ + + if(free_list) { + H5VL_iod_free_list_free(free_list, free_list_len); + free_list = NULL; + free_list_len = 0; + } /* end if */ + + /* Free vl_lengths */ + if(vl_lengths) { + free(vl_lengths); + vl_lengths = NULL; + vl_lengths_size = 0; + } + } + else { + size_t elmt_size; + + /* retrieve size of incoming bulk data */ + size = HG_Bulk_handle_get_size(bulk_handle); + + /* allocate buffer to hold data */ + if(NULL == (buf = malloc(size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* create a Mercury block handle for transfer */ + HG_Bulk_handle_create(buf, size, HG_BULK_READWRITE, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* free the bds block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + + /* MSC - check if client requested to corrupt data */ + if(H5Pget_dxpl_inject_corruption(dxpl_id, &flag) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read property list"); + if(flag) { + ((int *)buf)[0] = 10; + } + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* verify data if transfer flag is set */ + if(raw_cs_scope & H5_CHECKSUM_TRANSFER) { + data_cs = H5_checksum_crc64(buf, size); + if(cs != data_cs) { + fprintf(stderr, + "Errrr.. Network transfer Data corruption. expecting %"PRIu64", got %"PRIu64"\n", + cs, data_cs); + ret_value = FAIL; + goto done; + } + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + + buf_size = 0; + + /* Adjust buffer is type conversion is needed. If the data + elements are of variable length, just return that they are in + is_vl_data for special processing */ + if(H5VL__iod_server_adjust_buffer(src_id, dst_id, nelmts, dxpl_id, + size, &buf, &is_vl_data, &buf_size) < 0) { + fprintf(stderr, "failed to setup write operation"); + ret_value = FAIL; + goto done; + } + + /* convert data if needed */ + if(H5Tconvert(src_id, dst_id, nelmts, buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed") + +#if 0 + { + int *ptr = (int *)buf; + + fprintf(stderr, "DWRITE Received a buffer of size %zu with values: ", size); + for(u=0 ; u<size/sizeof(int) ; ++u) + fprintf(stderr, "%d ", ptr[u]); + fprintf(stderr, "\n"); + } +#endif + + elmt_size = H5Tget_size(dst_id); + if(H5VL__iod_server_final_io(iod_oh.wr_oh, space_id, elmt_size, TRUE, + buf, buf_size, cs, raw_cs_scope, wtid) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't write to array object"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset write, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + + input = (dset_io_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + H5VL_iod_type_info_reset(&type_info); + + if(buf) + free(buf); + + /* close the dataset if we opened it in this routine */ + if(TRUE == opened_locally) { + if(iod_obj_close(iod_oh.wr_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_write_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_set_extent_cb + * + * Purpose: Set_Extents iod HDF5 dataset. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_set_extent_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_set_extent_in_t *input = (dset_set_extent_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t iod_oh = input->iod_oh; + iod_obj_id_t iod_id = input->iod_id; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV object */ + /* int rank = input->dims.rank; rank of dataset */ + hbool_t opened_locally = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset Set Extent first dim to %zu\n", + (iod_size_t)input->dims.size[0]); +#endif + + /* open the dataset if we don't have the handle yet */ + if(iod_oh.wr_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, wtid, NULL /*hints*/, &iod_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + /* extend along the first dimension only */ + if(iod_array_extend(iod_oh.wr_oh, wtid, (iod_size_t)input->dims.size[0], NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't extend dataset"); + + /* modify the dataspace of the dataset */ + { + int rank; + hid_t space_id; + iod_handle_t mdkv_oh; + iod_size_t array_dims[H5S_MAX_RANK], current_dims[H5S_MAX_RANK]; + + /* open the metadata scratch pad */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + /* get the stored dataset dataspace */ + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + + if((rank = H5Sget_simple_extent_dims(space_id, current_dims, array_dims)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get dimentions' sizes"); + + /* Modify the size of the data space */ + if(H5Sset_extent_simple(space_id, rank, input->dims.size, array_dims) < 0) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space"); + + /* insert dataspace metadata */ + if(H5VL_iod_insert_dataspace(mdkv_oh, wtid, space_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset set_extent, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (dset_set_extent_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the dataset if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_set_extent_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_close_cb + * + * Purpose: Closes iod HDF5 dataset. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dset_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dset_close_in_t *input = (dset_close_in_t *)op_data->input; + iod_handles_t iod_oh = input->iod_oh; + //iod_obj_id_t iod_id = input->iod_id; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start dataset Close %"PRIu64" %"PRIu64"\n", + iod_oh.rd_oh.cookie, iod_oh.wr_oh.cookie); +#endif + + if(iod_obj_close(iod_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Read Array object"); + if(iod_obj_close(iod_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Write Array object"); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dset close, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (dset_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dset_close_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_final_io + * + * Read/Write to an IOD array object with an HDF5 + * selection. This is the normal way to access data given that the + * datatype is not of variable length. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__iod_server_final_io(iod_handle_t iod_oh, hid_t space_id, size_t elmt_size, + hbool_t write_op, void *buf, + size_t UNUSED buf_size, iod_checksum_t cs, + uint32_t cs_scope, iod_trans_id_t tid) +{ + int ndims, i; /* dataset's rank/number of dimensions */ + hssize_t num_descriptors = 0, n; /* number of IOD file descriptors needed to describe filespace selection */ + iod_mem_desc_t *mem_desc; /* memory descriptor used for reading array */ + iod_array_iodesc_t *file_desc; /* file descriptor used to do IO */ + iod_hyperslab_t *hslabs = NULL; /* IOD hyperslab generated from HDF5 filespace */ + iod_checksum_t *cs_list = NULL; + uint8_t *buf_ptr = NULL; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the rank of the dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + /* handle scalar dataspace */ + if(0 == ndims) { + ndims = 1; + /* allocate the IOD hyperslab descriptors needed */ + if(NULL == (hslabs = (iod_hyperslab_t *)malloc(sizeof(iod_hyperslab_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate iod array descriptors"); + + hslabs[0].start = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].stride = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].block = (iod_size_t *)malloc(sizeof(iod_size_t)); + hslabs[0].count = (iod_size_t *)malloc(sizeof(iod_size_t)); + + num_descriptors = 1; + hslabs[0].start[0] = 0; + hslabs[0].count[0] = 1; + hslabs[0].block[0] = 1; + hslabs[0].stride[0] = 1; + } + else { + /* get the number of decriptors required, i.e. the numbers of iod + I/O operations needed */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, NULL) < 0) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + + /* allocate the IOD hyperslab descriptors needed */ + if(NULL == (hslabs = (iod_hyperslab_t *)malloc + (sizeof(iod_hyperslab_t) * (size_t)num_descriptors))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate iod array descriptors"); + + for(n=0 ; n<num_descriptors ; n++) { + hslabs[n].start = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs[n].stride = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs[n].block = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + hslabs[n].count = (iod_size_t *)malloc(sizeof(iod_size_t) * (size_t)ndims); + } + + /* generate the descriptors after allocating the array */ + if(H5VL_iod_get_file_desc(space_id, &num_descriptors, hslabs) < 0) + HGOTO_ERROR2(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to generate IOD file descriptor from dataspace selection"); + } + + file_desc = (iod_array_iodesc_t *)hslabs; + buf_ptr = (uint8_t *)buf; + + if(cs_scope & H5_CHECKSUM_IOD) { + /* allocate cs array */ + if(NULL == (cs_list = (iod_checksum_t *)calloc + (sizeof(iod_checksum_t), (size_t)num_descriptors))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate checksum array"); + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO IOD DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + + /* set the memory descriptor */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + + (size_t)num_descriptors * sizeof(iod_mem_frag_t)); + mem_desc->nfrag = (long unsigned)num_descriptors; + for(n=0 ; n<num_descriptors ; n++) { + hsize_t num_bytes = 0; + hsize_t num_elems = 1; + + /* determine how many bytes the current descriptor holds */ + for(i=0 ; i<ndims ; i++) { + num_elems *= (hslabs[n].count[i] * hslabs[n].block[i]); + } + num_bytes = num_elems * elmt_size; + + mem_desc->frag[n].addr = (void *)buf_ptr; + mem_desc->frag[n].len = (iod_size_t)num_bytes; + + if(write_op && (cs_scope & H5_CHECKSUM_IOD)) + cs_list[n] = H5_checksum_crc64(buf_ptr, (size_t)num_bytes); + +#if H5VL_IOD_DEBUG + for(i=0 ; i<ndims ; i++) { + fprintf(stderr, "Dim %d: start %zu stride %zu block %zu count %zu\n", + i, (size_t)file_desc->start[i], (size_t)file_desc->stride[i], + (size_t)file_desc->block[i], (size_t)file_desc->count[i]); + } +#endif + } + + if(write_op) { + /* write to array */ + ret = iod_array_write(iod_oh, tid, NULL, mem_desc, file_desc, cs_list, NULL); + if(ret != 0) { + fprintf(stderr, "ret: %d error: %s\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't write to array object"); + } + } + else { + /* Read from array */ + ret = iod_array_read(iod_oh, tid, NULL, mem_desc, file_desc, cs_list, NULL); + if(ret != 0) { + fprintf(stderr, "ret: %d error: %s\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + } + } + + /* If this is a read operation, compute checksum for each IOD + read, and compare it against checksum returned from IOD */ + if(!write_op && (cs_scope & H5_CHECKSUM_IOD)) { + hsize_t num_bytes = 0; + hsize_t num_elems = 1; + iod_checksum_t checksum; + + buf_ptr = (uint8_t *)buf; + + for(n=0 ; n<num_descriptors ; n++) { + /* determine how many bytes the current descriptor holds */ + for(i=0 ; i<ndims ; i++) + num_elems *= (hslabs[n].count[i] * hslabs[n].block[i]); + num_bytes = num_elems * elmt_size; + + checksum = H5_checksum_crc64(buf_ptr, (size_t)num_bytes); +#if H5VL_IOD_DEBUG + fprintf(stderr, "IOD checksum = %016lX Checksum Computed = %016lX\n", + cs_list[n], checksum); +#endif + if(checksum != cs_list[n]) { + fprintf(stderr, "Data Corruption detected when reading\n"); + ret_value = FAIL; + goto done; + } + buf_ptr += num_bytes; + } + } + +done: + + /* free allocated descriptors */ + for(n=0 ; n<num_descriptors ; n++) { + free(hslabs[n].start); + free(hslabs[n].stride); + free(hslabs[n].block); + free(hslabs[n].count); + } + if(hslabs) { + free(hslabs); + hslabs = NULL; + } + if(cs_list) { + free(cs_list); + cs_list = NULL; + } + if(mem_desc) { + free(mem_desc); + mem_desc = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_final_io() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_vl_data_read + * + * Iterates over every (variable sized) element in the dataspace + * selection and reads it from IOD. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_server_vl_data_read(iod_handle_t coh, AXE_engine_t axe_engine, AXE_task_t axe_id, + size_t nelmts, void *buf, + hid_t UNUSED dxpl_id, iod_trans_id_t rtid) +{ + void *vlen_buf = NULL; + uint8_t *vlen_buf_ptr; + uint8_t *buf_ptr = (uint8_t *)buf; + void *get_size_op_data; + op_data_t *op_data = NULL; + iod_blob_io_t *io_blob = NULL; /* arary for list I/O */ + iod_checksum_t *cs_list = NULL; + iod_ret_t *ret_list = NULL; + iod_handle_t *blob_oh; + size_t u, elmt_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* retrieve the buffer that contains the blob IDs and their sizes + that was created in the get_size operation */ + if(AXE_SUCCEED != AXEget_op_data(axe_engine, axe_id, &get_size_op_data)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to get farm op_data"); + op_data = (op_data_t *)get_size_op_data; + + vlen_buf = op_data->output; + vlen_buf_ptr = (uint8_t *)vlen_buf; + + /* allocate a blob list to read the data */ + if(NULL == (io_blob = (iod_blob_io_t *)malloc(sizeof(iod_blob_io_t) * nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate blob io array"); + + /* allocate an array for the blob OHs */ + if(NULL == (blob_oh = (iod_handle_t *)malloc(sizeof(iod_handle_t) * nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate blob io array"); + + /* allocate cs array */ + if(NULL == (cs_list = (iod_checksum_t *)calloc(sizeof(iod_checksum_t), nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate checksum array"); + + /* allocate return array */ + if(NULL == (ret_list = (iod_ret_t *)calloc(sizeof(iod_ret_t), nelmts))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate return array"); + + elmt_size = sizeof(iod_obj_id_t) + sizeof(iod_size_t); + + for(u=0 ; u<nelmts; u++) { + size_t blob_size; + iod_obj_id_t blob_id; + iod_mem_desc_t *mem_desc; + iod_blob_iodesc_t *blob_desc; + + blob_id = *((iod_obj_id_t *)vlen_buf_ptr); + blob_size = *((size_t *)(vlen_buf_ptr+sizeof(iod_obj_id_t))); + vlen_buf_ptr += elmt_size; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %zu with BLOB ID %"PRIx64" size %zu\n", + u, blob_id, blob_size); +#endif + + if(iod_obj_open_read(coh, blob_id, rtid, NULL, &blob_oh[u], NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open BLOB for Read"); + + /* create memory descriptor for reading */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = (void *)buf_ptr; + mem_desc->frag[0].len = blob_size; + + /* create file descriptor for writing */ + blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + blob_desc->nfrag = 1; + blob_desc->frag[0].offset = 0; + blob_desc->frag[0].len = blob_size; + + /* setup list I/O parameters */ + io_blob[u].oh = blob_oh[u]; + io_blob[u].hints = NULL; + io_blob[u].mem_desc = mem_desc; + io_blob[u].io_desc = blob_desc; + io_blob[u].cs = NULL; //MSC - need IOD - &cs_list[u]; + io_blob[u].ret = &ret_list[u]; + + buf_ptr += blob_size; + } + + /* Read list IO */ + if(iod_blob_read_list(coh, rtid, (int)nelmts, io_blob, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from blob objects"); + + for(u=0 ; u<nelmts; u++) { + if(ret_list[u] < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + free(io_blob[u].mem_desc); + free(io_blob[u].io_desc); + + if(iod_obj_close(blob_oh[u], NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + +done: + + if(io_blob) + free(io_blob); + if(blob_oh) + free(blob_oh); + if(cs_list) + free(cs_list); + if(ret_list) + free(ret_list); + + vlen_buf = NULL; + free(op_data->output); + op_data->output = NULL; + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5VL__iod_server_vl_data_read */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_vl_data_write + * + * Iterates over every (variable sized) element in the dataspace + * selection and read/write it from IOD. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_server_vl_data_write(iod_handle_t coh, iod_obj_id_t iod_id, iod_handles_t iod_oh, + hid_t space_id, hid_t mem_type_id, hid_t UNUSED dset_type_id, + H5VL_iod_type_info_t type_info, size_t nelmts, + size_t num_segments, hg_bulk_segment_t *segments, + hid_t UNUSED dxpl_id, iod_trans_id_t wtid, iod_trans_id_t rtid, + na_addr_t source, hg_bulk_t bulk_handle, uint32_t cs_scope) +{ + char bogus; /* bogus value to pass to H5Diterate() */ + H5VL_iod_server_vl_write_t udata; + hg_bulk_t vl_data_handle; + hg_bulk_request_t bulk_request; + size_t buf_size = 0, u; + void *buf = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* Print VL length DATA */ + for(u = 0; u < num_segments; u++) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "Element %zu size %zu \n", u, segments[u].size); +#endif + buf_size += segments[u].size; + } /* end for */ + + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate data buffer"); + + /* Register local memory buffer */ + if(HG_SUCCESS != HG_Bulk_handle_create(buf, buf_size, HG_BULK_READWRITE, &vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "create vlen bulk handle"); + + /* Receive vl length data from client */ + if(HG_SUCCESS != HG_Bulk_read_all(source, bulk_handle, vl_data_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't read vlen lengths bulk data"); + + /* Wait for bulk data read to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wait for vlen lengths bulk data operation"); + + /* Free the bulk handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(vl_data_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free vlen bulk handle"); + + /* set other parameters needed to do IO */ + udata.coh = coh; + udata.iod_oh = iod_oh; + udata.nelmts = nelmts; + udata.buf_ptr = (uint8_t *)buf; + udata.buf_size = buf_size; + udata.wtid = wtid; + udata.rtid = rtid; + udata.segments = segments; + udata.cur_seg = 0; + udata.space_id = space_id; + udata.iod_id = iod_id; + + /* iterate over every element and read/write it as a BLOB object */ + if(H5Diterate(&bogus, mem_type_id, space_id, H5VL__iod_server_vl_data_write_cb, &udata) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "failed to compute buffer size"); + +done: + if(buf) { + free(buf); + buf = NULL; + } + FUNC_LEAVE_NOAPI(ret_value) +}/* end H5VL__iod_server_vl_data_write */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_vl_data_write_cb + * + * The callback to the H5Diterate routine called in + * H5VL__iod_server_vl_data_write. This will access every element in the + * array object and resolves it to a BLOB object. Then the actual data + * is read/written from/to the BLOB object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_server_vl_data_write_cb(void UNUSED *elem, hid_t type_id, unsigned ndims, + const hsize_t *point, void *_udata) +{ + H5VL_iod_server_vl_write_t *udata = (H5VL_iod_server_vl_write_t *)_udata; + iod_handle_t coh = udata->coh; /* container handle */ + //size_t nelmts = udata->nelmts; + iod_trans_id_t wtid = udata->wtid; + //iod_trans_id_t rtid = udata->rtid; + iod_handles_t iod_oh = udata->iod_oh; + iod_obj_id_t iod_id = udata->iod_id; + iod_obj_id_t blob_id = 0; + iod_handle_t blob_oh; + iod_hyperslab_t hslab; + iod_mem_desc_t *mem_desc; /* memory descriptor used for reading array */ + iod_array_iodesc_t file_desc; /* file descriptor used to read array */ + iod_blob_iodesc_t *blob_desc; /* blob descriptor */ + size_t buf_size; + unsigned u; + hbool_t created = FALSE; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* read in the point from the array object */ + hslab.start = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslab.stride = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslab.block = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + hslab.count = (iod_size_t *)malloc(sizeof(iod_size_t) * ndims); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Writing VL element # %zu\n", udata->cur_seg); +#endif + + memcpy(hslab.start, point, sizeof(size_t) * ndims); + for(u=0 ; u<ndims ; u++) { + hslab.stride[u] = 1; + hslab.block[u] = 1; + hslab.count[u] = 1; + } + file_desc = hslab; + + /* calculate the BLOB oid for the current coordinate */ + blob_id = H5VL__iod_get_vl_blob_oid(iod_id, udata->space_id, point); + + /* Attempt to Open the BLOB for write */ + ret = iod_obj_open_write(coh, blob_id, wtid, NULL, &blob_oh, NULL); + /* if the open fails, try and create the BLOB */ + if(ret != 0) { + ret = iod_obj_create(coh, wtid, NULL, IOD_OBJ_BLOB, NULL, NULL, &blob_id, NULL); + /* if the BLOB exists now, try to open it again */ + if(0 == ret || -EEXIST == ret) { + if(0 == ret) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "created BLOB with ID %"PRIx64"\n", blob_id); +#endif + created = TRUE; + } + ret = iod_obj_open_write(coh, blob_id, wtid, NULL, &blob_oh, NULL); + if(ret != 0) { + fprintf(stderr, "ret: %d error: %s %"PRIx64"\n", ret, strerror(-ret), blob_id); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to open BLOB object"); + } + } + else + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Failed to create BLOB object"); + } + + buf_size = udata->segments[udata->cur_seg].size; + + /* MSC - type conversion ?? */ + + /* create memory descriptor for writing */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = (void *)udata->buf_ptr; + mem_desc->frag[0].len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + blob_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + blob_desc->nfrag = 1; + blob_desc->frag[0].offset = 0; + blob_desc->frag[0].len = (iod_size_t)buf_size; + + /* write the VL data to the blob */ + if(iod_blob_write(blob_oh, wtid, NULL, mem_desc, blob_desc, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); + + free(mem_desc); + free(blob_desc); + + /* close BLOB */ + if(iod_obj_close(blob_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + if(created) { + /* update the array element with the blob_id and sequence length */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t) * 2); + mem_desc->nfrag = 2; + mem_desc->frag[0].addr = &blob_id; + mem_desc->frag[0].len = sizeof(iod_obj_id_t); + mem_desc->frag[1].addr = &buf_size; + mem_desc->frag[1].len = sizeof(iod_size_t); + + /* MSC - no CS from IOD yet */ +#if 0 + /* compute checksum of blob ID and sequence length */ + { + void *buffers[2]; + size_t buf_sizes[2]; + + buffers[0] = &blob_id; + buf_sizes[0] = sizeof(iod_obj_id_t); + buffers[1] = &seq_len; + buf_sizes[1] = sizeof(iod_size_t); + + entry_cs = H5_checksum_crc64_fragments(buffers, buf_sizes, 2); + } +#endif + + /* write the blob ID & size to the array element */ + if(iod_array_write(iod_oh.wr_oh, wtid, NULL, + mem_desc, &file_desc, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + free(mem_desc); + } + + /* advance buffer pointer */ + udata->buf_ptr += buf_size; + udata->cur_seg ++; + +done: + + free(hslab.start); + free(hslab.stride); + free(hslab.block); + free(hslab.count); + + FUNC_LEAVE_NOAPI(ret_value) +}/* end H5VL__iod_server_vl_data_write_cb */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_dtype.c b/src/H5VLiod_dtype.c new file mode 100644 index 0000000..88639da --- /dev/null +++ b/src/H5VLiod_dtype.c @@ -0,0 +1,513 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side datatype routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_commit_cb + * + * Purpose: Commits a dtype as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dtype_commit_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dtype_commit_in_t *input = (dtype_commit_in_t *)op_data->input; + dtype_commit_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t dtype_id = input->dtype_id; /* The ID of the datatype that needs to be created */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV to be created */ + iod_obj_id_t attr_id = input->attrkv_id; /* The ID of the attirbute KV to be created */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t dtype_oh, cur_oh; + iod_handle_t mdkv_oh; + iod_obj_id_t cur_id; + const char *name = input->name; /* name of dtype including path to commit */ + hid_t tcpl_id; + char *last_comp; /* the name of the datatype obtained from the last component in the path */ + size_t buf_size; /* size of the serialized datatype */ + void *buf; + iod_mem_desc_t *mem_desc = NULL; /* memory descriptor used for writing */ + iod_blob_iodesc_t *file_desc = NULL; /* file descriptor used to write */ + scratch_pad sp; + int step = 0; + iod_hint_list_t *obj_create_hint = NULL; + hbool_t enable_checksum = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start datatype commit %s at %"PRIu64"\n", name, loc_handle.wr_oh.cookie); +#endif + + if(H5P_DEFAULT == input->tcpl_id) + input->tcpl_id = H5Pcopy(H5P_DATATYPE_CREATE_DEFAULT); + tcpl_id = input->tcpl_id; + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_ocpl_enable_checksum(tcpl_id, &enable_checksum) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + /* the traversal will retrieve the location where the datatype needs + to be created. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_handle, name, wtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Creating Datatype ID %"PRIx64" ", dtype_id); + fprintf(stderr, "at (OH %"PRIu64" ID %"PRIx64") ", cur_oh.wr_oh.cookie, cur_id); + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) + fprintf(stderr, "with Data integrity ENABLED\n"); + else + fprintf(stderr, "with Data integrity DISABLED\n"); +#endif + + /* create the datatype */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_BLOB, + NULL, NULL, &dtype_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create BLOB"); + + if (iod_obj_open_read(coh, dtype_id, wtid, NULL, &dtype_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open BLOB"); + if (iod_obj_open_write(coh, dtype_id, wtid, NULL, &dtype_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open BLOB"); + + step ++; + + /* create the metadata KV object for the datatype */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &mdkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* create the attribute KV object for the datatype */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &attr_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create attribute KV object"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = attr_id; + sp[2] = IOD_OBJ_INVALID; + sp[3] = IOD_OBJ_INVALID; + + /* set scratch pad in datatype */ + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t sp_cs; + + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + if (iod_obj_set_scratch(dtype_oh.wr_oh, wtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + else { + if (iod_obj_set_scratch(dtype_oh.wr_oh, wtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + + /* Store Metadata in scratch pad */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open metadata KV object"); + + step ++; + + /* determine the buffer size needed to store the encoded type of the datatype */ + if(H5Tencode(input->type_id, NULL, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode datatype type"); + if(NULL == (buf = malloc (buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate type buffer"); + /* encode datatype of the datatype */ + if(H5Tencode(input->type_id, buf, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode datatype type"); + + /* create memory descriptor for writing */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = buf; + mem_desc->frag[0].len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + file_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + file_desc->nfrag = 1; + file_desc->frag[0].offset = 0; + file_desc->frag[0].len = (iod_size_t)buf_size; + + /* set scratch pad in datatype */ + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t dt_cs; + + /* calculate a checksum for the datatype */ + dt_cs = H5_checksum_crc64(buf, buf_size); + + /* write the serialized type value to the BLOB object */ + if(iod_blob_write(dtype_oh.wr_oh, wtid, NULL, mem_desc, file_desc, + &dt_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); + } + else { + /* write the serialized type value to the BLOB object */ + if(iod_blob_write(dtype_oh.wr_oh, wtid, NULL, mem_desc, file_desc, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); + } + + free(mem_desc); + free(file_desc); + + /* insert plist metadata */ + if(H5VL_iod_insert_plist(mdkv_oh, wtid, tcpl_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh, wtid, (uint64_t)1, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert object type metadata */ + if(H5VL_iod_insert_object_type(mdkv_oh, wtid, H5I_DATATYPE, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* store the datatype size */ + { + iod_kv_t kv; + + kv.key = (void *)H5VL_IOD_KEY_DTYPE_SIZE; + kv.key_len = strlen(H5VL_IOD_KEY_DTYPE_SIZE); + kv.value_len = sizeof(iod_size_t); + kv.value = &buf_size; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + if (iod_kv_set(mdkv_oh, wtid, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(mdkv_oh, wtid, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + + } + + /* close the Metadata KV object */ + if(iod_obj_close(mdkv_oh, NULL, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + step --; + + /* add link in parent group to current object */ + if(H5VL_iod_insert_new_link(cur_oh.wr_oh, wtid, last_comp, + H5L_TYPE_HARD, &dtype_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + output.iod_oh.rd_oh.cookie = dtype_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = dtype_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dtype commit, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(loc_handle.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + if(ret_value < 0) { + if(step == 2) { + iod_obj_close(mdkv_oh, NULL, NULL); + step --; + } + if(step == 1) { + iod_obj_close(dtype_oh.rd_oh, NULL, NULL); + iod_obj_close(dtype_oh.wr_oh, NULL, NULL); + } + + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + if(obj_create_hint) { + free(obj_create_hint); + obj_create_hint = NULL; + } + + input = (dtype_commit_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + last_comp = (char *)H5MM_xfree(last_comp); + free(buf); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dtype_commit_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_open_cb + * + * Purpose: Opens a datatype as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dtype_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dtype_open_in_t *input = (dtype_open_in_t *)op_data->input; + dtype_open_out_t output; + iod_handle_t coh = input->coh; /* container handle */ + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t dtype_id; /* ID of datatype to open */ + iod_handles_t dtype_oh; + iod_handle_t mdkv_oh; + const char *name = input->name; /* name of dtype including path to open */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + size_t buf_size; /* size of serialized datatype */ + void *buf = NULL; + iod_mem_desc_t *mem_desc = NULL; /* memory descriptor used for reading */ + iod_blob_iodesc_t *file_desc = NULL; /* file descriptor used to write */ + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_checksum_t dt_cs = 0, blob_cs = 0; + iod_size_t key_size=0, val_size=0; + iod_checksum_t iod_cs[2]; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start datatype open %s at (OH %"PRIu64" ID %"PRIx64")\n", + name, loc_handle.rd_oh.cookie, loc_id); +#endif + + /* Traverse Path and open dtype */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, name, rtid, + cs_scope, &dtype_id, &dtype_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* open a write handle on the ID. */ + if (iod_obj_open_write(coh, dtype_id, rtid, NULL, &dtype_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current datatype"); + + /* get scratch pad of the datatype */ + if(iod_obj_get_scratch(dtype_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.tcpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve tcpl"); + + val_size = sizeof(iod_size_t); + key_size = strlen(H5VL_IOD_KEY_DTYPE_SIZE); + + /* retrieve blob size metadata from scratch pad */ + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "datatype size lookup failed"); + + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate BLOB read buffer"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* create memory descriptor for writing */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = buf; + mem_desc->frag[0].len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + file_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + file_desc->nfrag = 1; + file_desc->frag[0].offset = 0; + file_desc->frag[0].len = (iod_size_t)buf_size; + + /* read the serialized type value from the BLOB object */ + if(iod_blob_read(dtype_oh.rd_oh, rtid, NULL, mem_desc, file_desc, &blob_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read from BLOB object"); + + if(blob_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* calculate a checksum for the datatype */ + dt_cs = H5_checksum_crc64(buf, buf_size); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "IOD BLOB checksum = %016lX Checksum Computed = %016lX\n", + blob_cs, dt_cs); +#endif + /* Verifty checksum against one given by IOD */ + if(blob_cs != dt_cs) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data Corruption detected when reading datatype"); + } + + /* decode the datatype */ + if((output.type_id = H5Tdecode(buf)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to decode datatype"); + + free(mem_desc); + free(file_desc); + free(buf); + + output.iod_id = dtype_id; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + output.iod_oh.rd_oh.cookie = dtype_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = dtype_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dtype open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.type_id = FAIL; + output.tcpl_id = FAIL; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (dtype_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dtype_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_close_cb + * + * Purpose: Closes iod HDF5 datatype. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_dtype_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + dtype_close_in_t *input = (dtype_close_in_t *)op_data->input; + iod_handles_t iod_oh = input->iod_oh; + //iod_obj_id_t iod_id = input->iod_id; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start datatype Close\n"); +#endif + + if(IOD_OH_UNDEFINED == iod_oh.wr_oh.cookie || + IOD_OH_UNDEFINED == iod_oh.rd_oh.cookie) { + HGOTO_ERROR2(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "can't close object with invalid handle"); + } + + if((iod_obj_close(iod_oh.rd_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Read OH"); + if((iod_obj_close(iod_oh.wr_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Write OH"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with dtype close, sending response to client\n"); +#endif +done: + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (dtype_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_dtype_close_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_encdec.c b/src/H5VLiod_encdec.c new file mode 100644 index 0000000..3d086e1 --- /dev/null +++ b/src/H5VLiod_encdec.c @@ -0,0 +1,937 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.org> + * + * Purpose: IOD plugin encode/decode code + */ + +#include "H5FFpublic.h" +#include "H5MMprivate.h" /* Memory management */ +#include "H5Ppublic.h" +#include "H5Qpublic.h" +#include "H5Spublic.h" +#include "H5VLiod_common.h" /* IOD Common Header */ + +#ifdef H5_HAVE_EFF + +int hg_proc_size_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + size_t *struct_data = (size_t *) data; + + ret = hg_proc_memcpy(proc, struct_data, sizeof(size_t)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +/* Define hg_proc_ret_t */ +int hg_proc_ret_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + + ret = hg_proc_int32_t(proc, (int32_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + return ret; +} + +int hg_proc_axe_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + size_t u; + hg_proc_op_t op; + axe_t *struct_data = (axe_t *) data; + + ret = hg_proc_uint64_t(proc, &struct_data->axe_id); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + ret = hg_proc_uint64_t(proc, &struct_data->start_range); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + ret = hg_proc_size_t(proc, &struct_data->count); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + ret = hg_proc_size_t(proc, &struct_data->num_parents); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + op = hg_proc_get_op(proc); + + switch(op) { + case HG_ENCODE: + for(u=0 ; u<struct_data->num_parents ; u++) { + ret = hg_proc_uint64_t(proc, &struct_data->parent_axe_ids[u]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_DECODE: + if(struct_data->num_parents) + struct_data->parent_axe_ids = (uint64_t *)malloc (sizeof(hsize_t) * + struct_data->num_parents); + + for(u=0 ; u<struct_data->num_parents ; u++) { + ret = hg_proc_uint64_t(proc, &struct_data->parent_axe_ids[u]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_FREE: + if(struct_data->num_parents) + free(struct_data->parent_axe_ids); + break; + default: + return HG_FAIL; + } + + return ret; +} +/* Define hg_proc_htri_t */ +int hg_proc_htri_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + + ret = hg_proc_int32_t(proc, (int32_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + return ret; +} + +/* Define hg_proc_hbool_t */ +int hg_proc_hbool_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + + ret = hg_proc_uint32_t(proc, (uint32_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + return ret; +} + +/* Define hg_proc_iod_handle_t */ +int hg_proc_hrpl_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + + ret = hg_proc_uint64_t(proc, (uint64_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +/* Define hg_proc_iod_handle_t */ +int hg_proc_iod_handle_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + iod_handle_t *struct_data = (iod_handle_t *)data; + + ret = hg_proc_uint64_t(proc, &struct_data->cookie); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +/* Define hg_proc_iod_handles_t */ +int hg_proc_iod_handles_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + iod_handles_t *struct_data = (iod_handles_t *)data; + + ret = hg_proc_iod_handle_t(proc, &struct_data->rd_oh); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + ret = hg_proc_iod_handle_t(proc, &struct_data->wr_oh); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +/* Define hg_proc_iod_obj_id_t */ +int hg_proc_iod_obj_id_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + iod_obj_id_t *struct_data = (iod_obj_id_t *)data; + + ret = hg_proc_uint64_t(proc, struct_data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + return ret; +} + +int hg_proc_dims_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + int i; + hg_proc_op_t op; + dims_t *struct_data = (dims_t *) data; + + ret = hg_proc_int32_t(proc, &struct_data->rank); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + op = hg_proc_get_op(proc); + + switch(op) { + case HG_ENCODE: + for(i=0 ; i<struct_data->rank ; i++) { + ret = hg_proc_uint64_t(proc, &struct_data->size[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_DECODE: + if(struct_data->rank) + struct_data->size = (hsize_t *)malloc (sizeof(hsize_t) * (size_t)struct_data->rank); + + for(i=0 ; i<struct_data->rank ; i++) { + ret = hg_proc_uint64_t(proc, &struct_data->size[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_FREE: + if(struct_data->rank) + free(struct_data->size); + break; + default: + return HG_FAIL; + } + + return ret; +} + +int hg_proc_name_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + size_t size; + name_t *struct_data = (name_t *) data; + + ret = hg_proc_memcpy(proc, struct_data->value_size, sizeof(ssize_t)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + size = (size_t)(*struct_data->value_size); + + ret = hg_proc_memcpy(proc, &struct_data->size, sizeof(size_t)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + if(NULL != struct_data->value && struct_data->size != 0) { + ret = hg_proc_raw(proc, struct_data->value, + MIN(size, struct_data->size)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + return ret; +} + +int hg_proc_binary_buf_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + hg_proc_op_t op; + binary_buf_t *struct_data = (binary_buf_t *) data; + + ret = hg_proc_raw(proc, &struct_data->buf_size, sizeof(size_t)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + op = hg_proc_get_op(proc); + + switch(op) { + case HG_ENCODE: + if(NULL != struct_data->buf && struct_data->buf_size != 0) { + ret = hg_proc_raw(proc, struct_data->buf, struct_data->buf_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_DECODE: + if(struct_data->buf_size != 0) { + struct_data->buf = malloc (struct_data->buf_size); + ret = hg_proc_raw(proc, struct_data->buf, struct_data->buf_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_FREE: + if(struct_data->buf_size != 0) { + free(struct_data->buf); + } + break; + default: + return HG_FAIL; + } + return ret; +} + +int hg_proc_value_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + value_t *struct_data = (value_t *) data; + + ret = hg_proc_raw(proc, &struct_data->val_size, sizeof(size_t)); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + if(NULL != struct_data->val && struct_data->val_size != 0) { + ret = hg_proc_raw(proc, struct_data->val, struct_data->val_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + + return ret; +} + +int hg_proc_linfo_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + H5L_ff_info_t *struct_data = (H5L_ff_info_t *) data; + + ret = hg_proc_int32_t(proc, &struct_data->type); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + if(H5L_TYPE_ERROR == struct_data->type) { + return ret; + } + + ret = hg_proc_int32_t(proc, &struct_data->cset); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + if(H5L_TYPE_HARD == struct_data->type) { + ret = hg_proc_uint64_t(proc, &struct_data->u.address); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + else if(H5L_TYPE_SOFT == struct_data->type) { + ret = hg_proc_size_t(proc, &struct_data->u.val_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + else { + HG_ERROR_DEFAULT("Proc error - link type not supported"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +int hg_proc_oinfo_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + H5O_ff_info_t *struct_data = (H5O_ff_info_t *) data; + + ret = hg_proc_uint64_t(proc, &struct_data->addr); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + ret = hg_proc_int32_t(proc, &struct_data->type); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + ret = hg_proc_uint32_t(proc, &struct_data->rc); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + ret = hg_proc_uint64_t(proc, &struct_data->num_attrs); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + return ret; +} + +/* Define hg_proc_plist_t */ +static int hg_proc_plist_t(hg_proc_t proc, hid_t *data) +{ + int ret = HG_SUCCESS; + size_t plist_size = 0; + void *buf = NULL; + hid_t plist_id; + hg_proc_op_t op; + + op = hg_proc_get_op(proc); + + switch(op) { + + case HG_ENCODE: + plist_id = *data; + /* + if(H5P_FILE_CREATE_DEFAULT != plist_id && H5P_GROUP_CREATE_DEFAULT != plist_id && + H5P_LINK_CREATE_DEFAULT != plist_id && H5P_DATASET_CREATE_DEFAULT != plist_id && + H5P_FILE_ACCESS_DEFAULT != plist_id && H5P_GROUP_ACCESS_DEFAULT != plist_id && + H5P_ATTRIBUTE_CREATE_DEFAULT != plist_id && H5P_OBJECT_COPY_DEFAULT != plist_id && + H5P_DATASET_ACCESS_DEFAULT != plist_id && H5P_DATASET_XFER_DEFAULT != plist_id && + H5P_DATATYPE_CREATE_DEFAULT != plist_id && H5P_DATATYPE_ACCESS_DEFAULT != plist_id && + H5P_LINK_ACCESS_DEFAULT != plist_id && H5P_RC_ACQUIRE_DEFAULT != plist_id && + H5P_TR_START_DEFAULT != plist_id && H5P_TR_FINISH_DEFAULT != plist_id) */ + if(H5P_OBJECT_COPY_DEFAULT != plist_id) { + if(H5Pencode(plist_id, NULL, &plist_size) < 0) { + HG_ERROR_DEFAULT("PLIST encode Proc error"); + return HG_FAIL; + } + } + + if(plist_size) { + buf = H5MM_malloc(plist_size); + if(H5Pencode(plist_id, buf, &plist_size) < 0) { + HG_ERROR_DEFAULT("PLIST encode Proc error"); + return HG_FAIL; + } + } + + ret = hg_proc_size_t(proc, &plist_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(plist_size) { + ret = hg_proc_raw(proc, buf, plist_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + H5MM_xfree(buf); + } + break; + case HG_DECODE: + ret = hg_proc_size_t(proc, &plist_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(plist_size) { + buf = H5MM_malloc(plist_size); + ret = hg_proc_raw(proc, buf, plist_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if((plist_id = H5Pdecode(buf)) < 0) { + HG_ERROR_DEFAULT("PLIST decode Proc error"); + return HG_FAIL; + } + H5MM_xfree(buf); + } + else + plist_id = H5P_DEFAULT; + + *data = plist_id; + break; + case HG_FREE: + plist_id = *data; + if(plist_id != H5P_DEFAULT) { + if(H5Pclose(plist_id) < 0) { + HG_ERROR_DEFAULT("PLIST free Proc error"); + return HG_FAIL; + } + } + break; + default: + HG_ERROR_DEFAULT("PLIST unsupported op Proc error"); + } + return ret; +} + +/* Define hg_proc_dtype_t */ +static int hg_proc_dtype_t(hg_proc_t proc, hid_t *data) +{ + int ret = HG_SUCCESS; + size_t dtype_size = 0; + void *buf = NULL; + hid_t dtype_id; + hg_proc_op_t op; + + op = hg_proc_get_op(proc); + + switch(op) { + + case HG_ENCODE: + dtype_id = *data; + if(H5Tencode(dtype_id, NULL, &dtype_size) < 0) { + HG_ERROR_DEFAULT("DTYPE encode Proc error"); + return HG_FAIL; + } + if(dtype_size) { + buf = H5MM_malloc(dtype_size); + if(H5Tencode(dtype_id, buf, &dtype_size) < 0) { + HG_ERROR_DEFAULT("DTYPE encode Proc error"); + return HG_FAIL; + } + } + + ret = hg_proc_size_t(proc, &dtype_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(dtype_size) { + ret = hg_proc_raw(proc, buf, dtype_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + H5MM_xfree(buf); + } + break; + case HG_DECODE: + ret = hg_proc_size_t(proc, &dtype_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(dtype_size) { + buf = H5MM_malloc(dtype_size); + ret = hg_proc_raw(proc, buf, dtype_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if((dtype_id = H5Tdecode(buf)) < 0) { + HG_ERROR_DEFAULT("DTYPE decode Proc error"); + return HG_FAIL; + } + H5MM_xfree(buf); + } + *data = dtype_id; + break; + case HG_FREE: + if(H5Tclose(*data) < 0) { + HG_ERROR_DEFAULT("DTYPE free Proc error"); + return HG_FAIL; + } + break; + default: + HG_ERROR_DEFAULT("DTYPE unsupported op Proc error"); + } + + return ret; +} + +/* Define hg_proc_dspace_t */ +static int hg_proc_dspace_t(hg_proc_t proc, hid_t *data) +{ + int ret = HG_SUCCESS; + size_t dspace_size = 0; + void *buf = NULL; + hid_t dspace_id; + hg_proc_op_t op; + + op = hg_proc_get_op(proc); + + switch(op) { + + case HG_ENCODE: + dspace_id = *data; + if(H5Sencode(dspace_id, NULL, &dspace_size) < 0) { + HG_ERROR_DEFAULT("DSPACE encode Proc error"); + return HG_FAIL; + } + if(dspace_size) { + buf = H5MM_malloc(dspace_size); + if(H5Sencode(dspace_id, buf, &dspace_size) < 0) { + HG_ERROR_DEFAULT("DSPACE encode Proc error"); + return HG_FAIL; + } + } + + ret = hg_proc_size_t(proc, &dspace_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(dspace_size) { + ret = hg_proc_raw(proc, buf, dspace_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + H5MM_xfree(buf); + } + break; + case HG_DECODE: + ret = hg_proc_size_t(proc, &dspace_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(dspace_size) { + buf = H5MM_malloc(dspace_size); + ret = hg_proc_raw(proc, buf, dspace_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if((dspace_id = H5Sdecode(buf)) < 0) { + HG_ERROR_DEFAULT("DSPACE decode Proc error"); + return HG_FAIL; + } + H5MM_xfree(buf); + } + *data = dspace_id; + break; + case HG_FREE: + if(H5Sclose(*data) < 0) { + HG_ERROR_DEFAULT("DSPACE free Proc error"); + return HG_FAIL; + } + break; + default: + HG_ERROR_DEFAULT("DSPACE unsupported op Proc error"); + } + + return ret; +} + +/* Define hg_proc_query_t */ +static int hg_proc_query_t(hg_proc_t proc, hid_t *data) +{ + int ret = HG_SUCCESS; + size_t query_size = 0; + void *buf = NULL; + hid_t query_id; + hg_proc_op_t op; + + op = hg_proc_get_op(proc); + + switch(op) { + + case HG_ENCODE: + query_id = *data; + if(H5Qencode(query_id, NULL, &query_size) < 0) { + HG_ERROR_DEFAULT("QUERY encode Proc error"); + return HG_FAIL; + } + if(query_size) { + buf = H5MM_malloc(query_size); + if(H5Qencode(query_id, buf, &query_size) < 0) { + HG_ERROR_DEFAULT("QUERY encode Proc error"); + return HG_FAIL; + } + } + + ret = hg_proc_size_t(proc, &query_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(query_size) { + ret = hg_proc_raw(proc, buf, query_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + H5MM_xfree(buf); + } + break; + case HG_DECODE: + ret = hg_proc_size_t(proc, &query_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if(query_size) { + buf = H5MM_malloc(query_size); + ret = hg_proc_raw(proc, buf, query_size); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + if((query_id = H5Qdecode(buf)) < 0) { + HG_ERROR_DEFAULT("QUERY decode Proc error"); + return HG_FAIL; + } + H5MM_xfree(buf); + } + *data = query_id; + break; + case HG_FREE: + if(H5Qclose(*data) < 0) { + HG_ERROR_DEFAULT("QUERY free Proc error"); + return HG_FAIL; + } + break; + default: + HG_ERROR_DEFAULT("QUERY unsupported op Proc error"); + } + + return ret; +} + +/* Define hg_proc_hid_t */ +int hg_proc_hid_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + hid_t id = *((hid_t *)data); + hg_proc_op_t op; + H5I_type_t type; + + op = hg_proc_get_op(proc); + + if (HG_ENCODE == op || HG_FREE == op) { + if(FAIL == id) + type = H5I_UNINIT; + else + type = H5Iget_type(id); + } + ret = hg_proc_int32_t(proc, &type); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + switch(type) { + case H5I_DATASPACE: + ret = hg_proc_dspace_t(proc, (hid_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + break; + case H5I_DATATYPE: + ret = hg_proc_dtype_t(proc, (hid_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + break; + case H5I_GENPROP_LST: + ret = hg_proc_plist_t(proc, (hid_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + break; + case H5I_QUERY: + ret = hg_proc_query_t(proc, (hid_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + break; + case H5I_UNINIT: + ret = hg_proc_int32_t(proc, (hid_t *)data); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + break; + default: + HG_ERROR_DEFAULT("Unsupported hid_t - Proc error"); + ret = HG_FAIL; + break; + } + return ret; +} + +int hg_proc_coords_t(hg_proc_t proc, void *data) +{ + int ret = HG_SUCCESS; + int i; + hg_proc_op_t op; + coords_t *struct_data = (coords_t *) data; + + ret = hg_proc_int32_t(proc, &struct_data->rank); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + + op = hg_proc_get_op(proc); + + switch(op) { + case HG_ENCODE: + for(i=0 ; i<struct_data->rank ; i++) { + ret = hg_proc_uint64_t(proc, &struct_data->start_cell[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + ret = hg_proc_uint64_t(proc, &struct_data->end_cell[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_DECODE: + if(struct_data->rank) { + struct_data->start_cell = (uint64_t *)malloc (sizeof(uint64_t) * (size_t)struct_data->rank); + struct_data->end_cell = (uint64_t *)malloc (sizeof(uint64_t) * (size_t)struct_data->rank); + } + + for(i=0 ; i<struct_data->rank ; i++) { + ret = hg_proc_uint64_t(proc, &struct_data->start_cell[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + ret = hg_proc_uint64_t(proc, &struct_data->end_cell[i]); + if (ret != HG_SUCCESS) { + HG_ERROR_DEFAULT("Proc error"); + ret = HG_FAIL; + return ret; + } + } + break; + case HG_FREE: + if(struct_data->rank) { + free(struct_data->start_cell); + free(struct_data->end_cell); + } + break; + default: + return HG_FAIL; + } + + return ret; +} +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_file.c b/src/H5VLiod_file.c new file mode 100644 index 0000000..775efdf --- /dev/null +++ b/src/H5VLiod_file.c @@ -0,0 +1,782 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * February, 2013 + * + * Purpose: The IOD plugin server side file routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_create_cb + * + * Purpose: Creates a file as a iod HDF5 file. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_file_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + file_create_in_t *input = (file_create_in_t *)op_data->input; + file_create_out_t output; + unsigned num_peers = input->num_peers; /* the number of peers participating in creation */ + iod_obj_id_t root_id = input->root_id; + iod_obj_id_t mdkv_id = input->mdkv_id; + iod_obj_id_t attrkv_id = input->attrkv_id; + iod_obj_id_t oidkv_id = input->oidkv_id; + hid_t fcpl_id; + unsigned int mode; /* create mode */ + iod_handle_t coh; /* container handle */ + iod_handles_t root_oh; /* root object handle */ + iod_handle_t mdkv_oh; /* metadata object handle for KV to store file's metadata */ + iod_ret_t ret, root_ret; + iod_trans_id_t first_tid = 0; + uint32_t cs_scope = 0; + iod_hint_list_t *con_open_hint = NULL; + iod_hint_list_t *obj_create_hint = NULL; + hbool_t enable_checksum = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start file create %s ", input->name); + fprintf(stderr, "with MDKV %"PRIx64" ", mdkv_id), + fprintf(stderr, "with attrKV %"PRIx64"\n", attrkv_id), + fprintf(stderr, "with OIDKV %"PRIx64"\n", oidkv_id), +#endif + + /* convert HDF5 flags to IOD flags */ + mode = (input->flags&H5F_ACC_RDWR) ? IOD_CONT_RW : IOD_CONT_R; + if (input->flags&H5F_ACC_CREAT) + mode |= IOD_CONT_CREATE; + + if(H5P_DEFAULT == input->fcpl_id) + input->fcpl_id = H5Pcopy(H5P_FILE_CREATE_DEFAULT); + fcpl_id = input->fcpl_id; + + if(H5Pget_metadata_integrity_scope(input->fapl_id, &cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + if(H5Pget_ocpl_enable_checksum(fcpl_id, &enable_checksum) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* scratch pad integrity in the container */ + if(cs_scope & H5_CHECKSUM_IOD) { + con_open_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + con_open_hint->num_hint = 1; + con_open_hint->hint[0].key = "iod_hint_co_scratch_cksum"; + } + + /* root group integrity */ + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + /* Create the Container */ + ret = iod_container_open(input->name, con_open_hint, mode, &coh, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't create container"); + + ret = iod_trans_start(coh, &first_tid, NULL, num_peers, IOD_TRANS_W, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't start transaction"); + + /* create the root group */ + root_ret = iod_obj_create(coh, first_tid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &root_id, NULL); + if(0 == root_ret || -EEXIST == root_ret) { + /* root group has been created, open it */ + ret = iod_obj_open_write(coh, root_id, first_tid, NULL, &root_oh.wr_oh, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't open root group for write"); + ret = iod_obj_open_read(coh, root_id, first_tid, NULL, &root_oh.rd_oh, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't open root group for read"); + } + else { + HGOTO_ERROR_IOD(ret, FAIL, "can't create root group"); + } + + /* for the process that succeeded in creating the group, create + the scratch pad for it too. */ + if(0 == root_ret) { + scratch_pad sp; + iod_kv_t kv; + uint64_t value = 1; + + /* create the metadata KV object for the root group */ + ret = iod_obj_create(coh, first_tid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &mdkv_id, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't create metadata KV object"); + + /* create the attribute KV object for the root group */ + ret = iod_obj_create(coh, first_tid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &attrkv_id, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't create attribute KV object"); + + /* create the KV object to hold each client's indexes for + object OIDs after each trans_finish and file_close */ + ret = iod_obj_create(coh, first_tid, NULL, IOD_OBJ_KV, NULL, NULL, &oidkv_id, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't create array for OID indexes"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = attrkv_id; + sp[2] = oidkv_id; + sp[3] = IOD_OBJ_INVALID; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t sp_cs; + + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + + /* set scratch pad in root group */ + ret = iod_obj_set_scratch(root_oh.wr_oh, first_tid, &sp, &sp_cs, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set scratch pad"); + } + else { + ret = iod_obj_set_scratch(root_oh.wr_oh, first_tid, &sp, NULL, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set scratch pad"); + } + + /* Store Metadata in scratch pad */ + ret = iod_obj_open_write(coh, input->mdkv_id, first_tid, NULL, &mdkv_oh, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't open metadata KV"); + + /* insert plist metadata */ + if(H5VL_iod_insert_plist(mdkv_oh, first_tid, fcpl_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't insert link count KV value"); + + kv.value = &value; + kv.value_len = sizeof(uint64_t); + + kv.key = (void *)H5VL_IOD_KEY_KV_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_KV_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, cs, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + else { + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, NULL, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + + kv.key = (void *)H5VL_IOD_KEY_ARRAY_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_ARRAY_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, cs, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + else { + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, NULL, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + + kv.key = (void *)H5VL_IOD_KEY_BLOB_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_BLOB_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, cs, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + else { + ret = iod_kv_set(mdkv_oh, first_tid, NULL, &kv, NULL, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't set KV pair in parent"); + } + + ret = iod_obj_close(mdkv_oh, NULL, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't close root object handle"); + } + + /* Finish the transaction */ + ret = iod_trans_finish(coh, first_tid, NULL, 0, NULL); + if(ret < 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't finish transaction 0"); + + output.coh.cookie = coh.cookie; + output.root_oh.rd_oh = root_oh.rd_oh; + output.root_oh.wr_oh = root_oh.wr_oh; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with file create coh: %"PRIu64" root rd: %"PRIu64" wr: %"PRIu64"\n", + coh.cookie, root_oh.rd_oh.cookie, root_oh.wr_oh.cookie); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.coh.cookie = IOD_OH_UNDEFINED; + output.root_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.root_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &ret_value); + } + + input = (file_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + if(con_open_hint) { + free(con_open_hint); + con_open_hint = NULL; + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_file_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_open_cb + * + * Purpose: Opens a file as a iod HDF5 file. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_file_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + file_open_in_t *input = (file_open_in_t *)op_data->input; + file_open_out_t output; + unsigned int mode = input->flags; /* File Open mode */ + hbool_t acquire = input->acquire; + iod_handle_t coh; /* container handle */ + iod_handles_t root_oh; /* root object handle */ + iod_handle_t mdkv_oh; /* metadata object handle for KV to store file's metadata */ + iod_handle_t oidkv_oh; /* object handle for KV to store file's OID indexes*/ + int num_entries; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_cont_trans_stat_t *tids = NULL; + iod_trans_id_t rtid; + iod_size_t key_size = 0, val_size = 0; + uint32_t cs_scope = 0; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start file open %s %d %d\n", input->name, input->flags, input->fapl_id); +#endif + + if(H5F_ACC_RDWR == mode) + mode = IOD_CONT_RW; + else if(H5F_ACC_RDONLY == mode) + mode = IOD_CONT_R; + else + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "invalid mode"); + + /* MSC - can't open file read only since IOD will fail when object + are opened for write */ + if(mode == IOD_CONT_R) + mode = IOD_CONT_RW; + + if(H5Pget_metadata_integrity_scope(input->fapl_id, &cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* open the container */ + if(iod_container_open(input->name, NULL, mode, &coh, NULL /*event*/)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open file"); + + if(iod_query_cont_trans_stat(coh, &tids, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get container tids status"); + + rtid = tids->latest_rdable; + + if(iod_free_cont_trans_stat(coh, tids) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free container transaction status object"); + + if(iod_trans_start(coh, &rtid, NULL, 0, IOD_TRANS_R, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't start transaction"); + + /* open the root group */ + if ((ret = iod_obj_open_read(coh, ROOT_ID, rtid, NULL, &root_oh.rd_oh, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open root object for read"); + } + if ((ret = iod_obj_open_write(coh, ROOT_ID, rtid, NULL, &root_oh.wr_oh, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open root object for write"); + } + /* get scratch pad of root group */ + if(iod_obj_get_scratch(root_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for root object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV object */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MD KV"); + + /* retrieve all metadata from scratch pad */ + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.fcpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve fcpl"); + + /* open the OID indexes KV object */ + if (iod_obj_open_read(coh, sp[2], rtid, NULL, &oidkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open OID KV"); + + ret = iod_kv_get_num(oidkv_oh, rtid, &num_entries, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't get number of KV entries"); + + val_size = sizeof(uint64_t); + + /* This was not a clean shutdown, so gather all the oid indexes + and compute the max */ + if(0 != num_entries) { + iod_kv_params_t *kvs = NULL; + iod_kv_t *kv = NULL; + iod_checksum_t *oid_cs = NULL; + iod_ret_t *oid_ret = NULL; + int i; + + kvs = (iod_kv_params_t *)malloc(sizeof(iod_kv_params_t) * (size_t)num_entries); + kv = (iod_kv_t *)malloc(sizeof(iod_kv_t) * (size_t)num_entries); + oid_cs = (iod_checksum_t *)malloc(sizeof(iod_checksum_t) * (size_t)num_entries); + oid_ret = (iod_ret_t *)malloc(sizeof(iod_ret_t) * (size_t)num_entries); + + for(i=0 ; i<num_entries ; i++) { + kv[i].key = malloc(sizeof(uint32_t)); + kv[i].key_len = sizeof(uint32_t); + kv[i].value = malloc(val_size * 3); + kv[i].value_len = val_size * 3; + kvs[i].kv = &kv[i]; + kvs[i].cs = &oid_cs[i]; + kvs[i].ret = &oid_ret[i]; + } + + ret = iod_kv_get_list(oidkv_oh, rtid, NULL, 0, &num_entries, kvs, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't get KV list from OID KV"); + + for(i=0 ; i<num_entries ; i++) { + uint64_t *oid_index = (uint64_t *)kv[i].value; + + if(output.kv_oid_index < oid_index[0]) + output.kv_oid_index = oid_index[0]; + if(output.array_oid_index < oid_index[1]) + output.array_oid_index = oid_index[1]; + if(output.blob_oid_index < oid_index[2]) + output.blob_oid_index = oid_index[2]; + } + + for(i=0 ; i<num_entries ; i++) { + free(kv[i].key); + free(kv[i].value); + } + + free(kv); + free(oid_cs); + free(oid_ret); + free(kvs); + } + /* This was a clean shutdown, so the maximum is already computed + and stored in the metadata KV */ + else { + iod_checksum_t *iod_cs = NULL; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_cs = (iod_checksum_t *)malloc(sizeof(iod_checksum_t) * 2); + } + + key_size = strlen(H5VL_IOD_KEY_KV_IDS_INDEX); + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_KV_IDS_INDEX, key_size, + &output.kv_oid_index, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "KV index lookup failed"); + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_KV_IDS_INDEX, key_size, + &output.kv_oid_index, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + key_size = strlen(H5VL_IOD_KEY_ARRAY_IDS_INDEX); + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_ARRAY_IDS_INDEX, key_size, + &output.array_oid_index, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Array index lookup failed"); + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_ARRAY_IDS_INDEX, key_size, + &output.array_oid_index, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + key_size = strlen(H5VL_IOD_KEY_BLOB_IDS_INDEX); + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_BLOB_IDS_INDEX, key_size, + &output.blob_oid_index, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "BLOB index lookup failed"); + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_BLOB_IDS_INDEX, key_size, + &output.blob_oid_index, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + if(iod_cs) { + free(iod_cs); + iod_cs = NULL; + } + } + + /* close the oid KV */ + if(iod_obj_close(oidkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close OID KV"); + /* close the metadata KV */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close MD KV"); + + output.coh.cookie = coh.cookie; + output.root_id = ROOT_ID; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + output.oidkv_id = sp[2]; + output.root_oh.rd_oh = root_oh.rd_oh; + output.root_oh.wr_oh = root_oh.wr_oh; + output.c_version = rtid; + + /* If the user did not ask to acquire the latest readable version, finish it here */ + if(TRUE != acquire) { + output.c_version = IOD_TID_UNKNOWN; + if(iod_trans_finish(coh, rtid, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't finish transaction 0"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with file open coh: %"PRIu64" root rd: %"PRIu64" wr: %"PRIu64" CV: %"PRIu64"\n", + coh.cookie, root_oh.rd_oh.cookie, root_oh.wr_oh.cookie, rtid); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.coh.cookie = IOD_OH_UNDEFINED; + output.root_id = IOD_OBJ_INVALID; + output.root_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.root_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.fcpl_id = H5P_FILE_CREATE_DEFAULT; + output.kv_oid_index = 0; + output.array_oid_index = 0; + output.blob_oid_index = 0; + output.c_version = IOD_TID_UNKNOWN; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (file_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_file_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_close_cb + * + * Purpose: Closes iod HDF5 file. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_file_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + file_close_in_t *input = (file_close_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t root_oh = input->root_oh; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start file close\n"); +#endif + + /* The root client request will create a transaction and store the + final indexes for used up IDs */ + if(input->max_kv_index || input->max_array_index || input->max_blob_index) { + iod_cont_trans_stat_t *tids = NULL; + iod_trans_id_t trans_num, rtid; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_kv_t kv; + iod_handle_t mdkv_oh; /* metadata object handle for KV to store file's metadata */ + uint32_t cs_scope = input->cs_scope; + + if(iod_query_cont_trans_stat(coh, &tids, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get container tids status"); + + trans_num = tids->latest_wrting + 1; + rtid = tids->latest_rdable; + + if(iod_free_cont_trans_stat(coh, tids) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free container transaction status object"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "File Close starting transaction %"PRIu64" rcxt %"PRIu64"\n", + trans_num, rtid); +#endif + + if((ret = iod_trans_start(coh, &rtid, NULL, 1, IOD_TRANS_R, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't start READ transaction"); + } + + if((ret = iod_trans_start(coh, &trans_num, NULL, 1, IOD_TRANS_W, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't start WRITE transaction"); + } + + /* get scratch pad of root group */ + if((ret = iod_obj_get_scratch(root_oh.rd_oh, rtid, &sp, &sp_cs, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for root object"); + } + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV object */ + if (iod_obj_open_write(coh, sp[0], trans_num, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open metadata KV"); + + /* insert current indexes in the metadata KV object */ + kv.value = &input->max_kv_index; + kv.value_len = sizeof(iod_obj_id_t); + kv.key = (void *)H5VL_IOD_KEY_KV_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_KV_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + + + kv.value = &input->max_array_index; + kv.value_len = sizeof(iod_obj_id_t); + kv.key = (void *)H5VL_IOD_KEY_ARRAY_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_ARRAY_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + + kv.value = &input->max_blob_index; + kv.value_len = sizeof(iod_obj_id_t); + kv.key = (void *)H5VL_IOD_KEY_BLOB_IDS_INDEX; + kv.key_len = strlen(H5VL_IOD_KEY_BLOB_IDS_INDEX); + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(mdkv_oh, trans_num, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close root object handle"); + + /* open the OID kv object and remove all entries since this is + a clean shutdown and the summary is stored in the metadata + KV. */ + { + iod_handles_t oidkv_oh; + int num_entries = 0, i; + iod_kv_params_t *kvs = NULL; + iod_kv_t *oid_kv = NULL; + iod_checksum_t *oid_cs = NULL; + iod_ret_t *oid_ret = NULL; + + if (iod_obj_open_write(coh, sp[2], trans_num, NULL, &oidkv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open oid KV"); + if (iod_obj_open_read(coh, sp[2], rtid, NULL, &oidkv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open oid KV"); + + ret = iod_kv_get_num(oidkv_oh.rd_oh, rtid, &num_entries, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't get number of KV entries"); + + fprintf(stderr, "NUM entries in OID index KV = %d\n", num_entries); + + if(num_entries) { + kvs = (iod_kv_params_t *)malloc(sizeof(iod_kv_params_t) * (size_t)num_entries); + oid_kv = (iod_kv_t *)malloc(sizeof(iod_kv_t) * (size_t)num_entries); + oid_cs = (iod_checksum_t *)malloc(sizeof(iod_checksum_t) * (size_t)num_entries); + oid_ret = (iod_ret_t *)malloc(sizeof(iod_ret_t) * (size_t)num_entries); + + for(i=0 ; i<num_entries ; i++) { + oid_kv[i].key = malloc(sizeof(uint32_t)); + oid_kv[i].key_len = sizeof(uint32_t); + kvs[i].kv = &oid_kv[i]; + kvs[i].cs = &oid_cs[i]; + kvs[i].ret = &oid_ret[i]; + } + + ret = iod_kv_list_key(oidkv_oh.rd_oh, rtid, NULL, 0, &num_entries, kvs, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't get list of keys"); + + ret = iod_kv_unlink_keys(oidkv_oh.wr_oh, trans_num, NULL, num_entries, kvs, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't unlink keys in OID index KV"); + + for(i=0 ; i<num_entries ; i++) + free(oid_kv[i].key); + free(oid_kv); + free(oid_cs); + free(oid_ret); + free(kvs); + } + + if(iod_obj_close(oidkv_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object handle"); + if(iod_obj_close(oidkv_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object handle"); + } + + /* finish the transaction */ + if(iod_trans_finish(coh, rtid, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't finish transaction"); + + /* finish the transaction */ + if(iod_trans_finish(coh, trans_num, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't finish transaction"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Closing ROOT Group: R: %"PRIu64" W: %"PRIu64"\n", + root_oh.rd_oh.cookie, root_oh.wr_oh.cookie); +#endif + + /* close the root group */ + if(iod_obj_close(root_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "can't close root object handle"); + if(iod_obj_close(root_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "can't close root object handle"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Closing Container: %"PRIu64"\n", coh.cookie); +#endif + + /* close the container */ + if((ret = iod_container_close(coh, NULL, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_FILE, H5E_CANTDEC, FAIL, "can't close container"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with file close, sending response to client\n"); +#endif + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "can't send result of file close to client"); + + input = (file_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_file_close_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_group.c b/src/H5VLiod_group.c new file mode 100644 index 0000000..0086bd0 --- /dev/null +++ b/src/H5VLiod_group.c @@ -0,0 +1,404 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side group routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_create_cb + * + * Purpose: Creates a group as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_group_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + group_create_in_t *input = (group_create_in_t *)op_data->input; + group_create_out_t output; + iod_handle_t coh = input->coh; /* the container handle */ + iod_handles_t loc_handle = input->loc_oh; /* The handle for current object - could be undefined */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t grp_id = input->grp_id; /* The ID of the group that needs to be created */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV to be created */ + iod_obj_id_t attrkv_id = input->attrkv_id; /* The ID of the attirbute KV to be created */ + const char *name = input->name; /* path relative to loc_id and loc_oh */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t grp_oh, cur_oh; + iod_handle_t mdkv_oh; + iod_obj_id_t cur_id; + char *last_comp = NULL; /* the name of the group obtained from traversal function */ + iod_hint_list_t *obj_create_hint = NULL; + hbool_t enable_checksum = FALSE; + hid_t gcpl_id; + scratch_pad sp; + iod_ret_t ret; + int step = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start group create %s at %"PRIu64"\n", name, loc_handle.wr_oh.cookie); +#endif + + if(H5P_DEFAULT == input->gcpl_id) + input->gcpl_id = H5Pcopy(H5P_GROUP_CREATE_DEFAULT); + gcpl_id = input->gcpl_id; + + /* get the scope for data integrity checks */ + if(H5Pget_ocpl_enable_checksum(gcpl_id, &enable_checksum) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + /* the traversal will retrieve the location where the group needs + to be created. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_handle, name, wtid, rtid, FALSE, cs_scope, + &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Creating Group ID %"PRIx64" (CV %"PRIu64", TR %"PRIu64") ", + grp_id, rtid, wtid); + fprintf(stderr, "at (OH %"PRIu64" ID %"PRIx64") ", cur_oh.wr_oh.cookie, cur_id); + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) + fprintf(stderr, "with Data integrity ENABLED\n"); + else + fprintf(stderr, "with Data integrity DISABLED\n"); +#endif + + /* create the group */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &grp_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Group"); + + if((ret = iod_obj_open_read(coh, grp_id, wtid, NULL, &grp_oh.rd_oh, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Group for read"); + } + if((ret = iod_obj_open_write(coh, grp_id, wtid, NULL, &grp_oh.wr_oh, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Group for write"); + } + + step += 1; + + /* create the metadata KV object for the group */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &mdkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* create the attribute KV object for the group */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &attrkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = attrkv_id; + sp[2] = IOD_OBJ_INVALID; + sp[3] = IOD_OBJ_INVALID; + + /* set scratch pad in group */ + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t sp_cs; + + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + if (iod_obj_set_scratch(grp_oh.wr_oh, wtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + else { + if (iod_obj_set_scratch(grp_oh.wr_oh, wtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + + /* store metadata */ + /* Open Metadata KV object for write */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create scratch pad"); + + step ++; + + /* insert plist metadata */ + if(H5VL_iod_insert_plist(mdkv_oh, wtid, gcpl_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh, wtid, (uint64_t)1, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert object type metadata */ + if(H5VL_iod_insert_object_type(mdkv_oh, wtid, H5I_GROUP, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close Metadata KV object */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + step --; + + /* add link in parent group to current object */ + if(H5VL_iod_insert_new_link(cur_oh.wr_oh, wtid, last_comp, H5L_TYPE_HARD, + &grp_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with group create, sending response to client\n"); +#endif + + /* return the object handle for the group to the client */ + output.iod_oh.rd_oh.cookie = grp_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = grp_oh.wr_oh.cookie; + HG_Handler_start_output(op_data->hg_handle, &output); + + fprintf(stderr, "Created group RD_OH %"PRIu64" WR_OH %"PRIu64"\n", + grp_oh.rd_oh.cookie, grp_oh.wr_oh.cookie); + +done: + + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(loc_handle.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + /* return an UNDEFINED oh to the client if the operation failed */ + if(ret_value < 0) { + fprintf(stderr, "Failed Group Create\n"); + + if(step == 2) { + iod_obj_close(mdkv_oh, NULL, NULL); + step --; + } + if(step == 1) { + iod_obj_close(grp_oh.rd_oh, NULL, NULL); + iod_obj_close(grp_oh.wr_oh, NULL, NULL); + } + + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + if(obj_create_hint) { + free(obj_create_hint); + obj_create_hint = NULL; + } + + last_comp = (char *)H5MM_xfree(last_comp); + input = (group_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_group_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_open_cb + * + * Purpose: Opens a group as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_group_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + group_open_in_t *input = (group_open_in_t *)op_data->input; + group_open_out_t output; + iod_handle_t coh = input->coh; + iod_handles_t loc_handle = input->loc_oh; /* location handle to start lookup */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + const char *name = input->name; /* group name including path to open */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_obj_id_t grp_id; /* The ID of the group that needs to be opened */ + iod_handles_t grp_oh; /* The group handle */ + iod_handle_t mdkv_oh; /* The metadata KV handle */ + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start group open %s at (OH %"PRIu64" ID %"PRIx64")\n", + name, loc_handle.rd_oh.cookie, loc_id); +#endif + + /* if we are opening the root group, no need to traverse */ + if(0 == strcmp(name, "/")) { + grp_id = ROOT_ID; + /* open a write handle on the ID. */ + if(iod_obj_open_read(coh, grp_id, rtid, NULL, &grp_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + } + else { + /* Traverse Path and open group */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, name, rtid, + cs_scope, &grp_id, &grp_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + } + + /* open a write handle on the ID. */ + if(iod_obj_open_write(coh, grp_id, rtid, NULL, &grp_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + /* get scratch pad of group */ + if(iod_obj_get_scratch(grp_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.gcpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve gcpl"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close meta data KV handle"); + + output.iod_id = grp_id; + output.iod_oh.rd_oh.cookie = grp_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = grp_oh.wr_oh.cookie; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with group open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.gcpl_id = H5P_GROUP_CREATE_DEFAULT; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (group_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_group_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_close_cb + * + * Purpose: Closes iod HDF5 group. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_group_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + group_close_in_t *input = (group_close_in_t *)op_data->input; + iod_handles_t iod_oh = input->iod_oh; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start group close\n"); +#endif + + if(IOD_OH_UNDEFINED == iod_oh.wr_oh.cookie || + IOD_OH_UNDEFINED == iod_oh.rd_oh.cookie) { + HGOTO_ERROR2(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "can't close object with invalid handle"); + } + + if((iod_obj_close(iod_oh.rd_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if((iod_obj_close(iod_oh.wr_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with group close, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (group_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_group_close_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_link.c b/src/H5VLiod_link.c new file mode 100644 index 0000000..127861b --- /dev/null +++ b/src/H5VLiod_link.c @@ -0,0 +1,866 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side link routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_create_cb + * + * Purpose: Creates a new link in the container (Hard or Soft). + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_create_in_t *input = (link_create_in_t *)op_data->input; + H5VL_link_create_type_t create_type = input->create_type; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t src_oh; /* The handle for creation src object */ + iod_obj_id_t src_id; /* The ID of the creation src object */ + iod_handles_t target_oh; + iod_obj_id_t target_id; /* The ID of the target object where link is created*/ + char *src_last_comp = NULL, *dst_last_comp = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Link create\n"); +#endif + + /* the traversal will retrieve the location where the link needs + to be created from. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, input->loc_id, input->loc_oh, input->loc_name, + wtid, rtid, FALSE, cs_scope, &src_last_comp, &src_id, &src_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "new link name = %s\n", src_last_comp); +#endif + + if(H5VL_LINK_CREATE_HARD == create_type) { + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_handles_t mdkv_oh; + uint64_t link_count = 0; + hbool_t opened_locally = FALSE; + + if(input->target_loc_oh.rd_oh.cookie == IOD_OH_UNDEFINED) { + /* Try and open the starting location */ + if (iod_obj_open_read(coh, input->target_loc_id, wtid, NULL, + &input->target_loc_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open start location"); + opened_locally = TRUE; + } + /* Traverse Path and open the target object */ + if(H5VL_iod_server_open_path(coh, input->target_loc_id, input->target_loc_oh, + input->target_name, rtid, cs_scope, &target_id, &target_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* add link in parent group to current object */ + if(H5VL_iod_insert_new_link(src_oh.wr_oh, wtid, src_last_comp, + H5L_TYPE_HARD, &target_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + if(input->target_loc_id != target_id) { + /* get scratch pad */ + if(iod_obj_get_scratch(target_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + else { + /* open the metadata KV */ + if (iod_obj_open_read(coh, input->target_mdkv_id, rtid, NULL, &mdkv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, input->target_mdkv_id, rtid, NULL, &mdkv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + } + + if(H5VL_iod_get_metadata(mdkv_oh.rd_oh, rtid, H5VL_IOD_LINK_COUNT, + H5VL_IOD_KEY_OBJ_LINK_COUNT, + cs_scope, NULL, &link_count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + link_count ++; + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh.wr_oh, wtid, link_count, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if(iod_obj_close(mdkv_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* close the target location */ + if(TRUE == opened_locally || + input->target_loc_oh.rd_oh.cookie != target_oh.rd_oh.cookie) { + if(iod_obj_close(target_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + } + else if(H5VL_LINK_CREATE_SOFT == create_type) { + /* add link in parent group to the source location */ + if(H5VL_iod_insert_new_link(src_oh.wr_oh, wtid, src_last_comp, + H5L_TYPE_SOFT, input->link_value, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Soft link Value = %s\n", input->link_value); +#endif + } + else + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Invalid Link type"); + + /* close the source location */ + if(input->loc_oh.rd_oh.cookie != src_oh.rd_oh.cookie) { + if(iod_obj_close(src_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + if(input->loc_oh.wr_oh.cookie != src_oh.wr_oh.cookie) { + if(iod_obj_close(src_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with link create, sending response %d to client\n", + ret_value); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + src_last_comp = (char *)H5MM_xfree(src_last_comp); + dst_last_comp = (char *)H5MM_xfree(dst_last_comp); + input = (link_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_move_cb + * + * Purpose: Moves/Copies a link in the container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_move_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_move_in_t *input = (link_move_in_t *)op_data->input; + hbool_t copy_flag = input->copy_flag; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t src_oh; /* The handle for src object group */ + iod_obj_id_t src_id; /* The ID of the src object */ + iod_handles_t dst_oh; /* The handle for the dst object where link is created*/ + iod_obj_id_t dst_id; /* The ID of the dst object where link is created*/ + char *src_last_comp = NULL, *dst_last_comp = NULL; + iod_kv_t kv; + H5VL_iod_link_t iod_link; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start link move SRC %s DST %s (%"PRIu64", %"PRIu64") to (%"PRIu64", %"PRIu64")\n", + input->src_loc_name, input->dst_loc_name, + input->src_loc_oh.wr_oh.cookie, input->src_loc_oh.rd_oh.cookie, + input->dst_loc_oh.wr_oh.cookie, input->dst_loc_oh.rd_oh.cookie); +#endif + + /* the traversal will retrieve the location where the link needs + to be moved/copied from. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, input->src_loc_id, input->src_loc_oh, + input->src_loc_name, wtid, rtid, FALSE, cs_scope, + &src_last_comp, &src_id, &src_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + + /* the traversal will retrieve the location where the link needs + to be moved/copied to. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, input->dst_loc_id, input->dst_loc_oh, + input->dst_loc_name, wtid, rtid, FALSE, cs_scope, + &dst_last_comp, &dst_id, &dst_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + + /* get the link value */ + if(H5VL_iod_get_metadata(src_oh.rd_oh, rtid, H5VL_IOD_LINK, + src_last_comp, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + + /* Insert object in the destination path */ + if(H5L_TYPE_HARD == iod_link.link_type) { + if(H5VL_iod_insert_new_link(dst_oh.wr_oh, wtid, dst_last_comp, + iod_link.link_type, &iod_link.u.iod_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + } + else if(H5L_TYPE_SOFT == iod_link.link_type) { + if(H5VL_iod_insert_new_link(dst_oh.wr_oh, wtid, dst_last_comp, + iod_link.link_type, &iod_link.u.symbolic_name, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + } + + /* if the operation type is a Move, remove the KV pair from the source object */ + if(!copy_flag) { + iod_kv_params_t kvs; + iod_ret_t ret; + iod_checksum_t cs; + + kv.key = src_last_comp; + kv.key_len = strlen(src_last_comp); + kvs.kv = &kv; + kvs.cs = &cs; + kvs.ret = &ret; + + /* remove link from source object */ + if(iod_kv_unlink_keys(src_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); + } + + /* adjust link count on target object */ + { + iod_handle_t target_oh; + iod_handles_t mdkv_oh; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + uint64_t link_count = 0; + + /* open the current group */ + if (iod_obj_open_read(coh, iod_link.u.iod_id, rtid, NULL, &target_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + /* get scratch pad */ + if(iod_obj_get_scratch(target_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh.rd_oh, rtid, H5VL_IOD_LINK_COUNT, + H5VL_IOD_KEY_OBJ_LINK_COUNT, + cs_scope, NULL, &link_count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + link_count ++; + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh.wr_oh, wtid, link_count, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if(iod_obj_close(mdkv_oh.wr_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* close the target location */ + if(iod_obj_close(target_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + } + + /* close source group if it is not the location we started the + traversal into */ + if(input->src_loc_oh.rd_oh.cookie != src_oh.rd_oh.cookie) { + iod_obj_close(src_oh.rd_oh, NULL, NULL); + } + if(input->src_loc_oh.wr_oh.cookie != src_oh.wr_oh.cookie) { + iod_obj_close(src_oh.wr_oh, NULL, NULL); + } + + /* close parent group if it is not the location we started the + traversal into */ + if(input->dst_loc_oh.rd_oh.cookie != dst_oh.rd_oh.cookie) { + iod_obj_close(dst_oh.rd_oh, NULL, NULL); + } + if(input->dst_loc_oh.wr_oh.cookie != dst_oh.wr_oh.cookie) { + iod_obj_close(dst_oh.wr_oh, NULL, NULL); + } + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with link move, sending response %d to client\n", + ret_value); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + src_last_comp = (char *)H5MM_xfree(src_last_comp); + dst_last_comp = (char *)H5MM_xfree(dst_last_comp); + input = (link_move_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + if(iod_link.link_type == H5L_TYPE_SOFT) { + if(iod_link.u.symbolic_name) + free(iod_link.u.symbolic_name); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_move_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_exists_cb + * + * Purpose: Checks if a link exists. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_exists_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_op_in_t *input = (link_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_handles_t cur_oh; + iod_obj_id_t cur_id; + const char *loc_name = input->path; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + char *last_comp = NULL; + htri_t ret = -1; + iod_size_t val_size = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start link Exists for %s on CV %d\n", loc_name, (int)rtid); +#endif + + /* the traversal will retrieve the location where the link needs + to be checked */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_oh, loc_name, rtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) { + ret = FALSE; + HGOTO_DONE(SUCCEED); + } + + /* check the last component */ + if(iod_kv_get_value(cur_oh.rd_oh, rtid, last_comp, (iod_size_t)strlen(last_comp), + NULL, &val_size, NULL, NULL) < 0) { + ret = FALSE; + } /* end if */ + else { + H5VL_iod_link_t iod_link; + + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + last_comp, cs_scope, NULL, &iod_link) < 0) { + ret = FALSE; + } + else { + iod_handle_t rd_oh; + + if (iod_obj_open_read(coh, iod_link.u.iod_id, rtid, NULL, &rd_oh, NULL) < 0) { + ret = FALSE; + } + else { + if(iod_obj_close(rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close current object handle"); + ret = TRUE; + } + } + } + +done: + + /* close parent group if it is not the location we started the + traversal into */ + if(input->loc_oh.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(input->loc_oh.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with link exists, sending %d to client\n", ret); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret); + + input = (link_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + last_comp = (char *)H5MM_xfree(last_comp); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_exists_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_get_info_cb + * + * Purpose: Checks if a link get_info. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_get_info_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_op_in_t *input = (link_op_in_t *)op_data->input; + H5L_ff_info_t linfo; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_handles_t cur_oh; + iod_obj_id_t cur_id; + const char *loc_name = input->path; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + char *last_comp = NULL; + H5VL_iod_link_t iod_link; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* the traversal will retrieve the location where the link needs + to be checked */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_oh, loc_name, rtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Link Get_Info on link %s\n", last_comp); +#endif + + /* lookup link information in the current location */ + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + last_comp, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + + /* setup link info */ + linfo.type = iod_link.link_type; + linfo.cset = 0; + switch (linfo.type) { + case H5L_TYPE_HARD: + linfo.u.address = iod_link.u.iod_id; + break; + case H5L_TYPE_SOFT: + linfo.u.val_size = strlen(iod_link.u.symbolic_name) + 1; + break; + case H5L_TYPE_ERROR: + case H5L_TYPE_EXTERNAL: + case H5L_TYPE_MAX: + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "unsuppored link type"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with link get_info, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &linfo); + +done: + + if(ret_value < 0) { + fprintf(stderr, "FAILED link get_info, sending ERROR to client\n"); + linfo.type = H5L_TYPE_ERROR; + HG_Handler_start_output(op_data->hg_handle, &linfo); + } + + /* close parent group if it is not the location we started the + traversal into */ + if(input->loc_oh.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(input->loc_oh.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + input = (link_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + last_comp = (char *)H5MM_xfree(last_comp); + + if(iod_link.link_type == H5L_TYPE_SOFT) { + if(iod_link.u.symbolic_name) + free(iod_link.u.symbolic_name); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_get_info_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_get_val_cb + * + * Purpose: Get comment for an object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_get_val_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_get_val_in_t *input = (link_get_val_in_t *)op_data->input; + link_get_val_out_t output; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + size_t length = input->length; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t cur_oh; + iod_obj_id_t cur_id; + const char *loc_name = input->path; + char *last_comp = NULL; + H5VL_iod_link_t iod_link; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* the traversal will retrieve the location where the link needs + to be checked */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_oh, loc_name, rtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Link Get_val on link %s\n", last_comp); +#endif + + /* lookup link information in the current location */ + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + last_comp, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + + if(H5L_TYPE_SOFT != iod_link.link_type) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "link is not SOFT"); + + output.value.val_size = length; + output.value.val = NULL; + + if(length) { + if(NULL == (output.value.val = (void *)malloc (length))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + memcpy(output.value.val, iod_link.u.symbolic_name, length); + } + + output.ret = ret_value; + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with get link_val, sending (%s) response to client\n", + (char *)output.value.val); +#endif + if(ret_value < 0) { + output.ret = ret_value; + output.value.val = NULL; + output.value.val_size = 0; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + /* close parent group if it is not the location we started the + traversal into */ + if(input->loc_oh.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(input->loc_oh.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + input = (link_get_val_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + last_comp = (char *)H5MM_xfree(last_comp); + + if(output.value.val) + free(output.value.val); + + if(iod_link.link_type == H5L_TYPE_SOFT) { + if(iod_link.u.symbolic_name) + free(iod_link.u.symbolic_name); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_get_val_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_remove_cb + * + * Purpose: Removes a link from a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_link_remove_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + link_op_in_t *input = (link_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t cur_oh; + iod_obj_id_t cur_id; + iod_handle_t obj_oh; + iod_handles_t mdkv_oh; + const char *loc_name = input->path; + char *last_comp = NULL; + iod_kv_params_t kvs; + iod_kv_t kv; + iod_ret_t ret; + iod_checksum_t cs; + H5VL_iod_link_t iod_link; + int step = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start link Remove %s at (%"PRIu64", %"PRIu64")\n", + loc_name, loc_oh.wr_oh.cookie, loc_oh.rd_oh.cookie); +#endif + + /* the traversal will retrieve the location where the link needs + to be removed. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_oh, loc_name, wtid, rtid, + FALSE, cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + + /* lookup object ID in the current location */ + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + last_comp, cs_scope, NULL, &iod_link) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + + /* unlink object from conainer */ + kv.key = last_comp; + kv.key_len = strlen(last_comp); + kvs.kv = &kv; + kvs.cs = &cs; + kvs.ret = &ret; + if(iod_kv_unlink_keys(cur_oh.wr_oh, wtid, NULL, 1, &kvs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); + + /* check the metadata information for the object and remove + it from the container if this is the last link to it */ + if(iod_link.link_type == H5L_TYPE_HARD) { + scratch_pad sp; + iod_checksum_t sp_cs = 0; + uint64_t link_count = 0; + iod_obj_id_t obj_id; + + obj_id = iod_link.u.iod_id; + + /* open the current group */ + if (iod_obj_open_read(coh, obj_id, rtid, NULL, &obj_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + step ++; + + /* get scratch pad */ + if(iod_obj_get_scratch(obj_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + if (iod_obj_open_write(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + step ++; + + if(H5VL_iod_get_metadata(mdkv_oh.rd_oh, rtid, H5VL_IOD_LINK_COUNT, + H5VL_IOD_KEY_OBJ_LINK_COUNT, + cs_scope, NULL, &link_count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + link_count --; + + /* if this is not the only link to the object, update the link count */ + if(0 != link_count) { + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh.wr_oh, wtid, link_count, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + } + + iod_obj_close(mdkv_oh.rd_oh, NULL, NULL); + iod_obj_close(mdkv_oh.wr_oh, NULL, NULL); + + step --; + + iod_obj_close(obj_oh, NULL, NULL); + + step --; + + /* If this was the only link to the object, remove the object */ + if(0 == link_count) { + if(iod_obj_unlink(coh, obj_id, wtid, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink object"); + if(iod_obj_unlink(coh, sp[0], wtid, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink MDKV object"); + if(iod_obj_unlink(coh, sp[1], wtid, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink ATTRKV object"); + } + } + +done: + + /* close parent group if it is not the location we started the + traversal into */ + if(input->loc_oh.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(input->loc_oh.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + if(step == 2) { + /* close the metadata scratch pad */ + iod_obj_close(mdkv_oh.rd_oh, NULL, NULL); + iod_obj_close(mdkv_oh.wr_oh, NULL, NULL); + step --; + } + if(step == 1) { + iod_obj_close(obj_oh, NULL, NULL); + step --; + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with link remove, sending response %d to client\n", + ret_value); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + last_comp = (char *)H5MM_xfree(last_comp); + input = (link_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + if(iod_link.link_type == H5L_TYPE_SOFT) { + if(iod_link.u.symbolic_name) + free(iod_link.u.symbolic_name); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_link_remove_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_map.c b/src/H5VLiod_map.c new file mode 100644 index 0000000..7e3aa0b --- /dev/null +++ b/src/H5VLiod_map.c @@ -0,0 +1,1079 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * July, 2013 + * + * Purpose: The IOD plugin server side map routines. + */ + +/* temp debug value for faking vl data */ +int g_debug_counter = 0; + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_create_cb + * + * Purpose: Creates a map as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_create_in_t *input = (map_create_in_t *)op_data->input; + map_create_out_t output; + iod_handle_t coh = input->coh; /* the container handle */ + iod_handles_t loc_handle = input->loc_oh; /* The handle for current object - could be undefined */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the current location object */ + iod_obj_id_t map_id = input->map_id; /* The ID of the map that needs to be created */ + iod_obj_id_t mdkv_id = input->mdkv_id; /* The ID of the metadata KV to be created */ + iod_obj_id_t attr_id = input->attrkv_id; /* The ID of the attirbute KV to be created */ + const char *name = input->name; /* path relative to loc_id and loc_oh */ + hid_t keytype = input->keytype_id; + hid_t valtype = input->valtype_id; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t map_oh, cur_oh; + iod_handle_t mdkv_oh; + iod_obj_id_t cur_id; + char *last_comp; /* the name of the group obtained from traversal function */ + hid_t mcpl_id; + iod_hint_list_t *obj_create_hint = NULL; + hbool_t enable_checksum = FALSE; + int step = 0; + scratch_pad sp; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map create %s at %"PRIu64"\n", + name, loc_handle.wr_oh.cookie); +#endif + + if(H5P_DEFAULT == input->mcpl_id) + input->mcpl_id = H5Pcopy(H5P_MAP_CREATE_DEFAULT); + mcpl_id = input->mcpl_id; + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_ocpl_enable_checksum(mcpl_id, &enable_checksum) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) { + obj_create_hint = (iod_hint_list_t *)malloc(sizeof(iod_hint_list_t) + sizeof(iod_hint_t)); + obj_create_hint->num_hint = 1; + obj_create_hint->hint[0].key = "iod_hint_obj_enable_cksum"; + } + + /* the traversal will retrieve the location where the map needs + to be created. The traversal will fail if an intermediate group + does not exist. */ + if(H5VL_iod_server_traverse(coh, loc_id, loc_handle, name, wtid, rtid, FALSE, + cs_scope, &last_comp, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Creating Map ID %"PRIx64") ", map_id); + fprintf(stderr, "at (OH %"PRIu64" ID %"PRIx64") ", cur_oh.wr_oh.cookie, cur_id); + if((cs_scope & H5_CHECKSUM_IOD) && enable_checksum) + fprintf(stderr, "with Data integrity ENABLED\n"); + else + fprintf(stderr, "with Data integrity DISABLED\n"); +#endif + + /* create the map */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &map_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create Map"); + + if (iod_obj_open_read(coh, map_id, wtid, NULL, &map_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Map"); + if (iod_obj_open_write(coh, map_id, wtid, NULL, &map_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open Map"); + + step ++; + + /* create the metadata KV object for the map */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &mdkv_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* create the attribute KV object for the root group */ + if(iod_obj_create(coh, wtid, obj_create_hint, IOD_OBJ_KV, + NULL, NULL, &attr_id, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create metadata KV object"); + + /* set values for the scratch pad object */ + sp[0] = mdkv_id; + sp[1] = attr_id; + sp[2] = IOD_OBJ_INVALID; + sp[3] = IOD_OBJ_INVALID; + + /* set scratch pad in map */ + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t sp_cs; + + sp_cs = H5_checksum_crc64(&sp, sizeof(sp)); + if (iod_obj_set_scratch(map_oh.wr_oh, wtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + else { + if (iod_obj_set_scratch(map_oh.wr_oh, wtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set scratch pad"); + } + + /* Open Metadata KV object for write */ + if (iod_obj_open_write(coh, mdkv_id, wtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't create scratch pad"); + + step ++; + + /* insert plist metadata */ + if(H5VL_iod_insert_plist(mdkv_oh, wtid, mcpl_id, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert link count metadata */ + if(H5VL_iod_insert_link_count(mdkv_oh, wtid, (uint64_t)1, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert object type metadata */ + if(H5VL_iod_insert_object_type(mdkv_oh, wtid, H5I_MAP, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert Key datatype metadata */ + if(H5VL_iod_insert_datatype_with_key(mdkv_oh, wtid, keytype, H5VL_IOD_KEY_MAP_KEY_TYPE, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* insert Value datatype metadata */ + if(H5VL_iod_insert_datatype_with_key(mdkv_oh, wtid, valtype, H5VL_IOD_KEY_MAP_VALUE_TYPE, + cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close MD KV object */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + step --; + + /* add link in parent group to current object */ + if(H5VL_iod_insert_new_link(cur_oh.wr_oh, wtid, last_comp, + H5L_TYPE_HARD, &map_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map create, sending response to client\n"); +#endif + + /* return the object handle for the map to the client */ + output.iod_oh.rd_oh.cookie = map_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = map_oh.wr_oh.cookie; + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + /* close parent group if it is not the location we started the + traversal into */ + if(loc_handle.rd_oh.cookie != cur_oh.rd_oh.cookie) { + iod_obj_close(cur_oh.rd_oh, NULL, NULL); + } + if(loc_handle.wr_oh.cookie != cur_oh.wr_oh.cookie) { + iod_obj_close(cur_oh.wr_oh, NULL, NULL); + } + + /* return an UNDEFINED oh to the client if the operation failed */ + if(ret_value < 0) { + fprintf(stderr, "Failed Map Create\n"); + + if(step == 2) { + iod_obj_close(mdkv_oh, NULL, NULL); + step --; + } + if(step == 1) { + iod_obj_close(map_oh.rd_oh, NULL, NULL); + iod_obj_close(map_oh.wr_oh, NULL, NULL); + } + + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + if(obj_create_hint) { + free(obj_create_hint); + obj_create_hint = NULL; + } + + last_comp = (char *)H5MM_xfree(last_comp); + input = (map_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_open_cb + * + * Purpose: Opens a map as a iod object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_open_in_t *input = (map_open_in_t *)op_data->input; + map_open_out_t output; + iod_handle_t coh = input->coh; + iod_handles_t loc_handle = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + const char *name = input->name; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_obj_id_t map_id; /* The ID of the map that needs to be opened */ + iod_handles_t map_oh; + iod_handle_t mdkv_oh; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map open %s at (OH %"PRIu64" ID %"PRIx64")\n", + name, loc_handle.rd_oh.cookie, loc_id); +#endif + + output.keytype_id = -1; + output.valtype_id = -1; + + /* Traverse Path and open map */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_handle, name, rtid, + cs_scope, &map_id, &map_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* open a write handle on the ID. */ + if (iod_obj_open_write(coh, map_id, rtid, NULL, &map_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current map"); + + /* get scratch pad of map */ + if(iod_obj_get_scratch(map_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, + H5VL_IOD_KEY_OBJ_CPL, cs_scope, NULL, &output.mcpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve gcpl"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_MAP_KEY_TYPE, + cs_scope, NULL, &output.keytype_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_MAP_VALUE_TYPE, + cs_scope, NULL, &output.valtype_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close meta data KV handle"); + + output.iod_id = map_id; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + output.iod_oh.rd_oh.cookie = map_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = map_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.keytype_id = FAIL; + output.valtype_id = FAIL; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (map_open_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_set_cb + * + * Purpose: Insert/Set a KV pair in map object + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_set_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_set_in_t *input = (map_set_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handle_t iod_oh = input->iod_oh.wr_oh; + iod_obj_id_t iod_id = input->iod_id; + hid_t key_memtype_id = input->key_memtype_id; + hid_t val_memtype_id = input->val_memtype_id; + hid_t key_maptype_id = input->key_maptype_id; + hid_t val_maptype_id = input->val_maptype_id; + binary_buf_t key = input->key; + hg_bulk_t value_handle = input->val_handle; /* bulk handle for data */ + iod_checksum_t value_cs = input->val_checksum; /* checksum recieved for data */ + hid_t dxpl_id = input->dxpl_id; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + na_addr_t source = HG_Handler_get_addr(op_data->hg_handle); /* source address to pull data from */ + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + size_t key_size, val_size, new_val_size; + void *val_buf = NULL; + iod_kv_t kv; + uint32_t raw_cs_scope; + hbool_t opened_locally = FALSE; + hbool_t val_is_vl_data = FALSE, key_is_vl_data = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Map Set Key %d on OH %"PRIu64" OID %"PRIx64"\n", + *((int *)key.buf), iod_oh.cookie, iod_id); +#endif + + /* open the map if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, wtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + if(H5P_DEFAULT == input->dxpl_id) + input->dxpl_id = H5Pcopy(H5P_DATASET_XFER_DEFAULT); + dxpl_id = input->dxpl_id; + + /* retrieve size of incoming bulk data */ + val_size = HG_Bulk_handle_get_size(value_handle); + + /* allocate buffer to hold data */ + if(NULL == (val_buf = malloc(val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* create a Mercury block handle for transfer */ + HG_Bulk_handle_create(val_buf, val_size, HG_BULK_READWRITE, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_read_all(source, value_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't get data from function shipper"); + + /* free the bds block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle"); + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* verify data if transfer flag is set */ + if(raw_cs_scope & H5_CHECKSUM_TRANSFER) { + iod_checksum_t data_cs; + + data_cs = H5_checksum_crc64(val_buf, val_size); + if(value_cs != data_cs) { + fprintf(stderr, "Errrr.. Network transfer Data corruption. expecting %"PRIu64", got %"PRIu64"\n", + value_cs, data_cs); + ret_value = FAIL; + goto done; + } + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + + /* adjust buffers for datatype conversion */ + if(H5VL__iod_server_adjust_buffer(key_memtype_id, key_maptype_id, 1, dxpl_id, + key.buf_size, &key.buf, &key_is_vl_data, &key_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + if(H5VL__iod_server_adjust_buffer(val_memtype_id, val_maptype_id, 1, dxpl_id, + val_size, &val_buf, &val_is_vl_data, &new_val_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + +#if H5VL_IOD_DEBUG + /* fake debugging */ + if(val_is_vl_data) { + H5T_class_t dt_class; + size_t seq_len = val_size, u; + uint8_t *buf_ptr = (uint8_t *)val_buf; + + dt_class = H5Tget_class(val_memtype_id); + + if(H5T_STRING == dt_class) + fprintf(stderr, "String Length %zu: %s\n", seq_len, (char *)buf_ptr); + else if(H5T_VLEN == dt_class) { + int *ptr = (int *)buf_ptr; + + fprintf(stderr, "Sequence Count %zu: ", seq_len); + for(u=0 ; u<seq_len/sizeof(int) ; ++u) + fprintf(stderr, "%d ", ptr[u]); + fprintf(stderr, "\n"); + } + } + else { + fprintf(stderr, "Map Set value = %d; size = %zu\n", *((int *)val_buf), val_size); + } +#endif + + if(!key_is_vl_data) { + /* convert data if needed */ + if(H5Tconvert(key_memtype_id, key_maptype_id, 1, key.buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + } + if(!val_is_vl_data) { + if(H5Tconvert(val_memtype_id, val_maptype_id, 1, val_buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + } + + /* MSC - do IOD checksum - can't now */ + + kv.key = key.buf; + kv.key_len = key_size; + kv.value = val_buf; + kv.value_len = (iod_size_t)new_val_size; + + /* insert kv pair into MAP */ + if(raw_cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + if (iod_kv_set(iod_oh, wtid, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in Map"); + } + else { + if (iod_kv_set(iod_oh, wtid, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in Map"); + } + +done: + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client"); + + input = (map_set_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + if(val_buf) + free(val_buf); + + /* close the map if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map set, sent %d response to client\n", ret_value); +#endif + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_set_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_get_cb + * + * Purpose: Get a KV pair in map object + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_get_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_get_in_t *input = (map_get_in_t *)op_data->input; + map_get_out_t output; + iod_handle_t coh = input->coh; + iod_handle_t iod_oh = input->iod_oh.rd_oh; + iod_obj_id_t iod_id = input->iod_id; + hid_t key_memtype_id = input->key_memtype_id; + hid_t val_memtype_id = input->val_memtype_id; + hid_t key_maptype_id = input->key_maptype_id; + hid_t val_maptype_id = input->val_maptype_id; + binary_buf_t key = input->key; + hid_t dxpl_id = input->dxpl_id; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + hbool_t val_is_vl = input->val_is_vl; + size_t client_val_buf_size = input->val_size; + hg_bulk_t value_handle = input->val_handle; /* bulk handle for data */ + uint32_t raw_cs_scope; + hbool_t key_is_vl = FALSE; + size_t key_size, val_size; + iod_size_t src_size; + void *val_buf = NULL; + hg_bulk_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + na_addr_t dest = HG_Handler_get_addr(op_data->hg_handle); /* destination address to push data to */ + hbool_t opened_locally = FALSE; + iod_checksum_t kv_cs[2]; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Map Get Key %d on OH %"PRIu64" OID %"PRIx64"\n", + *((int *)key.buf), iod_oh.cookie, iod_id); +#endif + + /* open the map if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, iod_id, rtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + if(H5P_DEFAULT == input->dxpl_id) + input->dxpl_id = H5Pcopy(H5P_DATASET_XFER_DEFAULT); + dxpl_id = input->dxpl_id; + + /* get the scope for data integrity checks for raw data */ + if(H5Pget_rawdata_integrity_scope(dxpl_id, &raw_cs_scope) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get scope for data integrity checks"); + + /* adjust buffers for datatype conversion */ + if(H5VL__iod_server_adjust_buffer(key_memtype_id, key_maptype_id, 1, dxpl_id, + key.buf_size, &key.buf, &key_is_vl, &key_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + if(iod_kv_get_value(iod_oh, rtid, key.buf, (iod_size_t)key.buf_size, NULL, + &src_size, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve value from parent KV store"); + + if(val_is_vl) { + output.ret = ret_value; + output.val_size = src_size; + fprintf(stderr, "val size = %zu\n", src_size); + if(client_val_buf_size) { + if(NULL == (val_buf = malloc((size_t)src_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate buffer"); + + if(iod_kv_get_value(iod_oh, rtid, key.buf, (iod_size_t)key.buf_size, val_buf, + &src_size, kv_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve value from parent KV store"); + + if(raw_cs_scope) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(key.buf, key.buf_size); + cs[1] = H5_checksum_crc64(val_buf, src_size); + + if(kv_cs[0] != cs[0] && kv_cs[1] != cs[1]) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected in IOD KV pair"); + + /* set checksum for the data to be sent */ + output.val_cs = kv_cs[1]; + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + + /* Create a new block handle to write the data */ + HG_Bulk_handle_create(val_buf, (size_t)src_size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, value_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); + } + } + else { + /* retrieve size of bulk data asked for to be read */ + src_size = HG_Bulk_handle_get_size(value_handle); + + if(NULL == (val_buf = malloc((size_t)src_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate buffer"); + + if(iod_kv_get_value(iod_oh, rtid, key.buf, (iod_size_t)key.buf_size, val_buf, + &src_size, kv_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve value from parent KV store"); + + if(raw_cs_scope) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(key.buf, key.buf_size); + cs[1] = H5_checksum_crc64(val_buf, src_size); + + if(kv_cs[0] != cs[0] && kv_cs[1] != cs[1]) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected in IOD KV pair"); + + /* set checksum for the data to be sent */ + output.val_cs = kv_cs[1]; + } + + /* adjust buffers for datatype conversion */ + if(H5VL__iod_server_adjust_buffer(val_memtype_id, val_maptype_id, 1, dxpl_id, + (size_t)src_size, &val_buf, &val_is_vl, &val_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* do data conversion */ + if(H5Tconvert(val_maptype_id, val_memtype_id, 1, val_buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + if(raw_cs_scope) { + /* calculate a checksum for the data to be sent */ + output.val_cs = H5_checksum_crc64(val_buf, val_size); + } +#if H5VL_IOD_DEBUG + else { + fprintf(stderr, "NO TRANSFER DATA INTEGRITY CHECKS ON RAW DATA\n"); + } +#endif + + output.val_size = val_size; + output.ret = ret_value; + + /* Create a new block handle to write the data */ + HG_Bulk_handle_create(val_buf, val_size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, value_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_handle_free(bulk_block_handle)) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map get, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map get"); + +done: + + if(ret_value < 0) { + output.ret = FAIL; + output.val_size = 0; + output.val_cs = 0; + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map get"); + } + + if(val_buf) + free(val_buf); + + input = (map_get_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the map if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_get_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_get_count_cb + * + * Purpose: Get number of KV pairs in map object + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_get_count_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_get_count_in_t *input = (map_get_count_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handle_t iod_oh = input->iod_oh.rd_oh; + iod_obj_id_t iod_id = input->iod_id; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + int num; + hsize_t output; + hbool_t opened_locally = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map get_count \n"); +#endif + + /* open the map if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, iod_id, rtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + if(iod_kv_get_num(iod_oh, rtid, &num, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve Number of KV pairs in MAP"); + + output = (hsize_t)num; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map get_count, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map get"); + +done: + + if(ret_value < 0) { + output = IOD_COUNT_UNDEFINED; + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output)) + HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map get_count"); + } + + input = (map_get_count_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the map if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_get_count_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_exists_cb + * + * Purpose: check if a key Exists in map object + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_exists_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_op_in_t *input = (map_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handle_t iod_oh = input->iod_oh.wr_oh; + iod_obj_id_t iod_id = input->iod_id; + hid_t key_memtype_id = input->key_memtype_id; + hid_t key_maptype_id = input->key_maptype_id; + binary_buf_t key = input->key; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + size_t key_size; + iod_size_t val_size = 0; + hbool_t opened_locally = FALSE; + htri_t exists; + hbool_t is_vl_data = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map exists \n"); +#endif + + /* open the map if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, iod_id, rtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + /* adjust buffers for datatype conversion */ + if(H5VL__iod_server_adjust_buffer(key_memtype_id, key_maptype_id, 1, H5P_DEFAULT, + key.buf_size, &key.buf, &is_vl_data, &key_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* determine if the Key exists by querying its value size */ + if(iod_kv_get_value(iod_oh, rtid, key.buf, (iod_size_t)key.buf_size, NULL, + &val_size, NULL, NULL) < 0) + exists = FALSE; + else + exists = TRUE; + + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map exists, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &exists)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map get"); + +done: + + if(ret_value < 0) { + exists = -1; + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &exists)) + HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map exists"); + } + + input = (map_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the map if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_exists_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_delete_cb + * + * Purpose: Delete a KV pair in map object + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_delete_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_op_in_t *input = (map_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handle_t iod_oh = input->iod_oh.wr_oh; + iod_obj_id_t iod_id = input->iod_id; + hid_t key_memtype_id = input->key_memtype_id; + hid_t key_maptype_id = input->key_maptype_id; + binary_buf_t key = input->key; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + size_t key_size; + iod_kv_t kv; + iod_kv_params_t kvs; + iod_ret_t ret; + iod_checksum_t cs; + hbool_t opened_locally = FALSE; + hbool_t is_vl_data = FALSE; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map delete \n"); +#endif + + /* open the map if we don't have the handle yet */ + if(iod_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_write(coh, iod_id, rtid, NULL /*hints*/, &iod_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + /* adjust buffers for datatype conversion */ + if(H5VL__iod_server_adjust_buffer(key_memtype_id, key_maptype_id, 1, H5P_DEFAULT, + key.buf_size, &key.buf, &is_vl_data, &key_size) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); + + kv.key = key.buf; + kv.key_len = key_size; + kvs.kv = &kv; + kvs.cs = &cs; + kvs.ret = &ret; + + if(iod_kv_unlink_keys(iod_oh, wtid, NULL, 1, &kvs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); + + if(ret < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDEC, FAIL, "Unable to unlink KV pair"); +done: + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map delete, sending %d response to client\n", ret_value); +#endif + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't send result of map delete"); + + input = (map_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the map if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(iod_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_delete_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_close_cb + * + * Purpose: Closes iod HDF5 map. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_map_close_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + map_close_in_t *input = (map_close_in_t *)op_data->input; + iod_handles_t iod_oh = input->iod_oh; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start map Close %"PRIu64" %"PRIu64"\n", + iod_oh.rd_oh.cookie, iod_oh.wr_oh.cookie); +#endif + + if((iod_obj_close(iod_oh.rd_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + if((iod_obj_close(iod_oh.wr_oh, NULL, NULL)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with map close, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (map_close_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_map_close_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_obj.c b/src/H5VLiod_obj.c new file mode 100644 index 0000000..2ec9340 --- /dev/null +++ b/src/H5VLiod_obj.c @@ -0,0 +1,982 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * June, 2013 + * + * Purpose: The IOD plugin server side general object routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_open_cb + * + * Purpose: Opens an existing object in the container + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_open_by_token_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_token_in_t *input = (object_token_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_obj_id_t obj_id = input->iod_id; /* The ID of the object */ + iod_trans_id_t tid = input->trans_num; + //uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; /* The handle for object */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Open by token = %"PRIx64"\n", obj_id); +#endif + + if (iod_obj_open_read(coh, obj_id, tid, NULL /*hints*/, &obj_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + if (iod_obj_open_write(coh, obj_id, tid, NULL /*hints*/, &obj_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with object open by token, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &obj_oh); + +done: + if(ret_value < 0) { + obj_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + obj_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(op_data->hg_handle, &obj_oh); + } + + input = (object_token_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_open_cb + * + * Purpose: Opens an existing object in the container + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_open_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_op_in_t *input = (object_op_in_t *)op_data->input; + object_open_out_t output; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; /* The handle for object */ + iod_obj_id_t obj_id; /* The ID of the object */ + iod_handle_t mdkv_oh; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Open on %s (OH %"PRIu64" ID %"PRIx64")\n", + input->loc_name, input->loc_oh.rd_oh.cookie, input->loc_id); +#endif + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, input->loc_id, input->loc_oh, input->loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if (iod_obj_open_write(coh, obj_id, rtid, NULL, &obj_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + if(obj_id != input->loc_id) { + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + else { + /* open the metadata KV */ + if (iod_obj_open_read(coh, input->loc_mdkv_id, rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_OBJECT_TYPE, H5VL_IOD_KEY_OBJ_TYPE, + cs_scope, NULL, &output.obj_type) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + switch(output.obj_type) { + case H5I_MAP: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve mcpl"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_MAP_KEY_TYPE, + cs_scope, NULL, &output.id1) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, + H5VL_IOD_KEY_MAP_VALUE_TYPE, + cs_scope, NULL, &output.id2) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + break; + case H5I_GROUP: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dcpl"); + output.id1 = FAIL; + output.id2 = FAIL; + break; + case H5I_DATASET: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dcpl"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, H5VL_IOD_KEY_OBJ_DATATYPE, + cs_scope, NULL, &output.id1) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &output.id2) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + break; + case H5I_DATATYPE: + { + size_t buf_size; /* size of serialized datatype */ + void *buf = NULL; + iod_mem_desc_t *mem_desc = NULL; /* memory descriptor used for reading */ + iod_blob_iodesc_t *file_desc = NULL; /* file descriptor used to write */ + iod_checksum_t dt_cs = 0, blob_cs = 0; + iod_size_t key_size, val_size; + iod_checksum_t iod_cs[2]; + + key_size = strlen(H5VL_IOD_KEY_DTYPE_SIZE); + val_size = sizeof(iod_size_t); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dcpl"); + + /* retrieve blob size metadata from scratch pad */ + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "datatype size lookup failed"); + + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate BLOB read buffer"); + + /* create memory descriptor for writing */ + mem_desc = (iod_mem_desc_t *)malloc(sizeof(iod_mem_desc_t) + + sizeof(iod_mem_frag_t)); + mem_desc->nfrag = 1; + mem_desc->frag[0].addr = buf; + mem_desc->frag[0].len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + file_desc = (iod_blob_iodesc_t *)malloc(sizeof(iod_blob_iodesc_t) + + sizeof(iod_blob_iofrag_t)); + file_desc->nfrag = 1; + file_desc->frag[0].offset = 0; + file_desc->frag[0].len = (iod_size_t)buf_size; + + /* read the serialized type value from the BLOB object */ + if(iod_blob_read(obj_oh.rd_oh, rtid, NULL, mem_desc, file_desc, + &blob_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read BLOB object"); + + if(blob_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* calculate a checksum for the datatype */ + dt_cs = H5_checksum_crc64(buf, buf_size); + + /* Verify checksum against one given by IOD */ + if(blob_cs != dt_cs) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data Corruption detected when reading datatype"); + } + + /* decode the datatype */ + if((output.id1 = H5Tdecode(buf)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to decode datatype"); + output.id2 = FAIL; + + free(mem_desc); + free(file_desc); + free(buf); + break; + } + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Invalid object type"); + } + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + output.iod_id = obj_id; + output.mdkv_id = sp[0]; + output.attrkv_id = sp[1]; + output.iod_oh.rd_oh.cookie = obj_oh.rd_oh.cookie; + output.iod_oh.wr_oh.cookie = obj_oh.wr_oh.cookie; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with object open, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + if(ret_value < 0) { + output.iod_oh.rd_oh.cookie = IOD_OH_UNDEFINED; + output.iod_oh.wr_oh.cookie = IOD_OH_UNDEFINED; + output.iod_id = IOD_OBJ_INVALID; + output.cpl_id = FAIL; + output.id1 = FAIL; + output.id2 = FAIL; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (object_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_open_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_copy_cb + * + * Purpose: Moves/Copies a link in the container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_copy_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_copy_in_t *input = (object_copy_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t dst_oh; /* The handle for the dst object where link is created*/ + iod_obj_id_t dst_id; /* The ID of the dst object where link is created*/ + iod_obj_id_t obj_id; /* The ID of the object to be moved/copied */ + iod_handles_t obj_oh; /* The handle for the object to be moved/copied */ + iod_obj_id_t new_id; /* The ID of the new object */ + iod_handle_t mdkv_oh;/* The handle of the metadata KV for source object */ + char *new_name = NULL; + iod_kv_t kv; + iod_size_t kv_size = sizeof(H5VL_iod_link_t); + H5VL_iod_link_t iod_link; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start object copy\n"); +#endif + + /* MSC - NEED IOD & a lot more work*/ +#if 0 + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, input->src_loc_id, input->src_loc_oh, input->src_loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + /* the traversal will retrieve the location where the objects + needs to be copied to. The traversal will fail if an + intermediate group does not exist. */ + if(H5VL_iod_server_traverse(coh, input->dst_loc_id, input->dst_loc_oh, input->dst_loc_name, + FALSE, rtid, &new_name, &dst_id, &dst_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't traverse path"); + + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_write(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_OBJECT_TYPE, H5VL_IOD_KEY_OBJ_TYPE, + cs_scope, NULL, &obj_type) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + switch(obj_type) { + case H5I_MAP: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve mcpl"); + break; + case H5I_GROUP: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve gcpl"); + break; + case H5I_DATASET: + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_PLIST, H5VL_IOD_KEY_OBJ_CPL, + cs_scope, NULL, &output.cpl_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dcpl"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, H5VL_IOD_KEY_OBJ_DATATYPE, + cs_scope, NULL, &output.type_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATASPACE, H5VL_IOD_KEY_OBJ_DATASPACE, + cs_scope, NULL, &output.space_id) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve dataspace"); + break; + case H5I_DATATYPE: + { + size_t buf_size; /* size of serialized datatype */ + void *buf = NULL; + iod_mem_desc_t mem_desc; /* memory descriptor used for reading */ + iod_blob_iodesc_t file_desc; /* file descriptor used to write */ + iod_checksum_t dt_cs = 0, blob_cs = 0; + iod_checksum_t iod_cs[2]; + + /* retrieve blob size metadata from scratch pad */ + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "datatype size lookup failed"); + + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_DTYPE_SIZE, key_size, + &buf_size, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate BLOB read buffer"); + + /* create memory descriptor for reading */ + mem_desc.nfrag = 1; + mem_desc.frag->addr = buf; + mem_desc.frag->len = (iod_size_t)buf_size; + + /* create file descriptor for writing */ + file_desc.nfrag = 1; + file_desc.frag->offset = 0; + file_desc.frag->len = (iod_size_t)buf_size; + + /* read the serialized type value from the BLOB object */ + if(iod_blob_read(obj_oh, rtid, NULL, &mem_desc, &file_desc, NULL, + &blob_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write BLOB object"); + + if(blob_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* calculate a checksum for the datatype */ + dt_cs = H5_checksum_crc64(buf, buf_size); + + /* Verify checksum against one given by IOD */ + if(blob_cs != dt_cs) + HGOTO_ERROR2(H5E_SYM, H5E_READERROR, FAIL, "Data Corruption detected when reading datatype"); + } + + /* decode the datatype */ + if((output.type_id = H5Tdecode(buf)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unable to decode datatype"); + + free(buf); + } + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Invalid object type"); + } + + /* create new object as a copy of the source object */ + /* MSC - wait to see if IOD will have an object copy */ + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + /* close the object handle */ + if(input->src_loc_oh.cookie != obj_oh.cookie && + iod_obj_close(obj_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* Insert object in the destination path */ + if(H5VL_iod_insert_new_link(dst_oh, wtid, new_name, + H5L_TYPE_HARD, &obj_id, cs_scope, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert KV value"); + + /* close dst group if it is not the location we started the + traversal into */ + if(input->dst_loc_oh.cookie != dst_oh.cookie) { + iod_obj_close(dst_oh, NULL, NULL); + } + +#endif + +done: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with object Copy, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + if(new_name) + free(new_name); + input = (object_copy_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_copy_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_exists_cb + * + * Purpose: Checks if an object exists. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_exists_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_op_in_t *input = (object_op_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; + iod_obj_id_t obj_id; + const char *loc_name = input->loc_name; + htri_t ret = -1; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Exists on %s (OH %"PRIu64" ID %"PRIx64")\n", + input->loc_name, input->loc_oh.rd_oh.cookie, input->loc_id); +#endif + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_oh, loc_name, rtid, + cs_scope, &obj_id, &obj_oh) < 0) { + ret = FALSE; + HGOTO_DONE(SUCCEED); + } + else { + /* close the object */ + if(loc_oh.rd_oh.cookie != obj_oh.rd_oh.cookie && + iod_obj_close(obj_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* set return to TRUE */ + ret = TRUE; + } + +done: + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Object exists, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret); + + input = (object_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_exists_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_get_info_cb + * + * Purpose: Checks if an object get_info. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_get_info_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_op_in_t *input = (object_op_in_t *)op_data->input; + H5O_ff_info_t oinfo; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; + iod_handle_t mdkv_oh, attrkv_oh; + iod_obj_id_t obj_id; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + H5I_type_t obj_type; + int num_attrs = 0; + const char *loc_name = input->loc_name; + uint64_t link_count = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Get Info on %s (OH %"PRIu64" ID %"PRIx64")\n", + input->loc_name, input->loc_oh.rd_oh.cookie, input->loc_id); +#endif + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_oh, loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "object does not exist"); + + oinfo.addr = obj_id; + + if(obj_id != loc_id || input->loc_mdkv_id == IOD_OBJ_INVALID) { + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + /* open the attribute KV */ + if (iod_obj_open_read(coh, sp[1], rtid, NULL, &attrkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open ATTRKV"); + } + else { + /* open the metadata KV */ + if (iod_obj_open_read(coh, input->loc_mdkv_id, rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + /* open the attribute KV */ + if (iod_obj_open_read(coh, input->loc_attrkv_id, rtid, NULL, &attrkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_OBJECT_TYPE, + H5VL_IOD_KEY_OBJ_TYPE, + cs_scope, NULL, &obj_type) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve object type"); + + switch(obj_type) { + case H5I_GROUP: + oinfo.type = H5O_TYPE_GROUP; + break; + case H5I_DATASET: + oinfo.type = H5O_TYPE_DATASET; + break; + case H5I_DATATYPE: + oinfo.type = H5O_TYPE_NAMED_DATATYPE; + break; + case H5I_MAP: + oinfo.type = H5O_TYPE_MAP; + break; + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, + "unsupported object type for H5Oget_info"); + } + + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_LINK_COUNT, + H5VL_IOD_KEY_OBJ_LINK_COUNT, + cs_scope, NULL, &link_count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link count"); + + oinfo.rc = (unsigned) link_count; + + if(iod_kv_get_num(attrkv_oh, rtid, &num_attrs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve attribute count"); + + oinfo.num_attrs = (hsize_t)num_attrs; + + /* close the metadata KV */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + /* close the attribute KV */ + if(iod_obj_close(attrkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + if(loc_oh.rd_oh.cookie != obj_oh.rd_oh.cookie && + iod_obj_close(obj_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Object get_info, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &oinfo); + +done: + if(ret_value < 0) { + oinfo.type = H5O_TYPE_UNKNOWN; + oinfo.addr = IOD_OBJ_INVALID; + oinfo.rc = 0; + oinfo.num_attrs = 0; + HG_Handler_start_output(op_data->hg_handle, &oinfo); + } + + input = (object_op_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_get_info_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_set_comment_cb + * + * Purpose: Set comment for an object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_set_comment_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_set_comment_in_t *input = (object_set_comment_in_t *)op_data->input; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + iod_trans_id_t wtid = input->trans_num; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handles_t obj_oh; + iod_handle_t mdkv_oh; + iod_obj_id_t obj_id; + const char *loc_name = input->path; + const char *comment = input->comment; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Set comment on %s (OH %"PRIu64" ID %"PRIx64")\n", + input->path, input->loc_oh.rd_oh.cookie, input->loc_id); +#endif + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_oh, loc_name, rtid, + cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if(loc_id != obj_id || input->loc_mdkv_id == IOD_OBJ_INVALID) { + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata scratch pad */ + if (iod_obj_open_write(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + else { + /* open the metadata KV */ + if (iod_obj_open_write(coh, input->loc_mdkv_id, rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + + { + iod_kv_t kv; + + kv.key = H5VL_IOD_KEY_OBJ_COMMENT; + kv.key_len = strlen(H5VL_IOD_KEY_OBJ_COMMENT); + kv.value_len = strlen(comment) + 1; + kv.value = comment; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + if (iod_kv_set(mdkv_oh, wtid, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(mdkv_oh, wtid, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set comment in MDKV"); + } + + } + + /* close metadata KV and object */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + if(loc_oh.rd_oh.cookie != obj_oh.rd_oh.cookie && + iod_obj_close(obj_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + +done: + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with set comment, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (object_set_comment_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_set_comment_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_get_comment_cb + * + * Purpose: Get comment for an object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_object_get_comment_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + object_get_comment_in_t *input = (object_get_comment_in_t *)op_data->input; + object_get_comment_out_t output; + name_t comment; + iod_handle_t coh = input->coh; + iod_handles_t loc_oh = input->loc_oh; + iod_obj_id_t loc_id = input->loc_id; + size_t length = input->length; + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + iod_handle_t mdkv_oh; + iod_handles_t obj_oh; + iod_obj_id_t obj_id; + const char *loc_name = input->path; + scratch_pad sp; + iod_checksum_t sp_cs = 0; + iod_size_t key_size, val_size = 0; + void *value = NULL; + iod_checksum_t *iod_cs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Start Object Get comment on %s (OH %"PRIu64" ID %"PRIx64")\n", + input->path, input->loc_oh.rd_oh.cookie, input->loc_id); +#endif + + /* Traverse Path and open object */ + if(H5VL_iod_server_open_path(coh, loc_id, loc_oh, loc_name, + rtid, cs_scope, &obj_id, &obj_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + if(loc_id != obj_id || input->loc_mdkv_id == IOD_OBJ_INVALID) { + /* get scratch pad of the object */ + if(iod_obj_get_scratch(obj_oh.rd_oh, rtid, &sp, &sp_cs, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + if(sp_cs && (cs_scope & H5_CHECKSUM_IOD)) { + /* verify scratch pad integrity */ + if(H5VL_iod_verify_scratch_pad(&sp, sp_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Scratch Pad failed integrity check"); + } + + /* open the metadata KV */ + if (iod_obj_open_read(coh, sp[0], rtid, NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + else { + /* open the metadata KV */ + if (iod_obj_open_read(coh, input->loc_mdkv_id, rtid, NULL, &mdkv_oh, NULL) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open MDKV"); + } + + comment.value_size = (ssize_t *)malloc(sizeof(ssize_t)); + comment.value = NULL; + comment.size = length; + + key_size = strlen(H5VL_IOD_KEY_OBJ_COMMENT); + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_cs = (iod_checksum_t *)malloc(sizeof(iod_checksum_t) * 2); + } + + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_OBJ_COMMENT, key_size, + NULL, &val_size, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "comment size lookup failed"); + + if(NULL == (value = malloc ((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(mdkv_oh, rtid, H5VL_IOD_KEY_OBJ_COMMENT, key_size, + value, &val_size, iod_cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "comment value lookup failed"); + + if(cs_scope & H5_CHECKSUM_IOD) { + if(H5VL_iod_verify_kv_pair(H5VL_IOD_KEY_OBJ_COMMENT, key_size, + value, val_size, iod_cs) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + + if(length) { + if(NULL == (comment.value = (char *)malloc (length))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + memcpy(comment.value, value, length); + } + + free(value); + + /* close metadata KV and object */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + if(loc_oh.rd_oh.cookie != obj_oh.rd_oh.cookie && + iod_obj_close(obj_oh.rd_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + *comment.value_size = (ssize_t)val_size; + +done: + output.ret = ret_value; + output.name = comment; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with get comment, sending response to client\n"); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + + if(comment.value) { + free(comment.value); + comment.value = NULL; + } + + if(comment.value_size) { + free(comment.value_size); + comment.value_size = NULL; + } + + if(iod_cs) { + free(iod_cs); + iod_cs = NULL; + } + + input = (object_get_comment_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_object_get_comment_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_server.c b/src/H5VLiod_server.c new file mode 100644 index 0000000..ad71811 --- /dev/null +++ b/src/H5VLiod_server.c @@ -0,0 +1,3795 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_PYTHON +#include <Python.h> +#endif + +#define MAX_LOC_NAME 256 + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * February, 2013 + * + * Purpose: The IOD plugin server side routines. + */ + +static AXE_engine_t engine; +static MPI_Comm iod_comm; +static int num_peers = 0; +static int terminate_requests = 0; +static hbool_t shutdown = FALSE; + +iod_obj_id_t ROOT_ID = 0; + +int num_ions_g = 0; +int my_rank_g = 0; +na_addr_t *server_addr_g = NULL; +char **server_loc_g = NULL; +hg_id_t H5VL_EFF_OPEN_CONTAINER; +hg_id_t H5VL_EFF_CLOSE_CONTAINER; +hg_id_t H5VL_EFF_ANALYSIS_FARM; +hg_id_t H5VL_EFF_ANALYSIS_FARM_TRANSFER; + +void +EFF__mercury_register_callbacks(void) +{ + + H5VL_EFF_OPEN_CONTAINER = MERCURY_REGISTER("container_open", hg_const_string_t, iod_handle_t); + MERCURY_HANDLER_REGISTER("container_open", H5VL_iod_server_container_open, + hg_const_string_t, iod_handle_t); + + H5VL_EFF_CLOSE_CONTAINER = MERCURY_REGISTER("container_close", iod_handle_t, ret_t); + MERCURY_HANDLER_REGISTER("container_close", H5VL_iod_server_container_close, + iod_handle_t, ret_t); + + MERCURY_HANDLER_REGISTER("analysis_execute", H5VL_iod_server_analysis_execute, + analysis_execute_in_t, analysis_execute_out_t); + + H5VL_EFF_ANALYSIS_FARM = MERCURY_REGISTER("analysis_farm", analysis_farm_in_t, + analysis_farm_out_t); + MERCURY_HANDLER_REGISTER("analysis_farm", H5VL_iod_server_analysis_farm, + analysis_farm_in_t, analysis_farm_out_t); + + H5VL_EFF_ANALYSIS_FARM_TRANSFER = MERCURY_REGISTER("analysis_transfer", + analysis_transfer_in_t, analysis_transfer_out_t); + MERCURY_HANDLER_REGISTER("analysis_transfer", H5VL_iod_server_analysis_transfer, + analysis_transfer_in_t, analysis_transfer_out_t); + + /* Register function and encoding/decoding functions */ + MERCURY_HANDLER_REGISTER("eff_init", H5VL_iod_server_eff_init, + eff_init_in_t, ret_t); + MERCURY_HANDLER_REGISTER("eff_finalize", H5VL_iod_server_eff_finalize, + ret_t, ret_t); + + MERCURY_HANDLER_REGISTER("file_create", H5VL_iod_server_file_create, + file_create_in_t, file_create_out_t); + MERCURY_HANDLER_REGISTER("file_open", H5VL_iod_server_file_open, + file_open_in_t, file_open_out_t); + MERCURY_HANDLER_REGISTER("file_close", H5VL_iod_server_file_close, + file_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("attr_create", H5VL_iod_server_attr_create, + attr_create_in_t, attr_create_out_t); + MERCURY_HANDLER_REGISTER("attr_open", H5VL_iod_server_attr_open, + attr_open_in_t, attr_open_out_t); + MERCURY_HANDLER_REGISTER("attr_read", H5VL_iod_server_attr_read, + attr_io_in_t, ret_t); + MERCURY_HANDLER_REGISTER("attr_write", H5VL_iod_server_attr_write, + attr_io_in_t, ret_t); + MERCURY_HANDLER_REGISTER("attr_exists", H5VL_iod_server_attr_exists, + attr_op_in_t, htri_t); + MERCURY_HANDLER_REGISTER("attr_rename", H5VL_iod_server_attr_rename, + attr_rename_in_t, ret_t); + MERCURY_HANDLER_REGISTER("attr_remove", H5VL_iod_server_attr_remove, + attr_op_in_t, ret_t); + MERCURY_HANDLER_REGISTER("attr_close", H5VL_iod_server_attr_close, + attr_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("group_create", H5VL_iod_server_group_create, + group_create_in_t, group_create_out_t); + MERCURY_HANDLER_REGISTER("group_open", H5VL_iod_server_group_open, + group_open_in_t, group_open_out_t); + MERCURY_HANDLER_REGISTER("group_close", H5VL_iod_server_group_close, + group_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("map_create", H5VL_iod_server_map_create, + map_create_in_t, map_create_out_t); + MERCURY_HANDLER_REGISTER("map_open", H5VL_iod_server_map_open, + map_open_in_t, map_open_out_t); + MERCURY_HANDLER_REGISTER("map_set", H5VL_iod_server_map_set, + map_set_in_t, ret_t); + MERCURY_HANDLER_REGISTER("map_get", H5VL_iod_server_map_get, + map_get_in_t, map_get_out_t); + MERCURY_HANDLER_REGISTER("map_get_count", H5VL_iod_server_map_get_count, + map_get_count_in_t, int64_t); + MERCURY_HANDLER_REGISTER("map_exists", H5VL_iod_server_map_exists, + map_op_in_t, hbool_t); + MERCURY_HANDLER_REGISTER("map_delete", H5VL_iod_server_map_delete, + map_op_in_t, ret_t); + MERCURY_HANDLER_REGISTER("map_close", H5VL_iod_server_map_close, + map_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("dset_create", H5VL_iod_server_dset_create, + dset_create_in_t, dset_create_out_t); + MERCURY_HANDLER_REGISTER("dset_open", H5VL_iod_server_dset_open, + dset_open_in_t, dset_open_out_t); + MERCURY_HANDLER_REGISTER("dset_read", H5VL_iod_server_dset_read, + dset_io_in_t, dset_read_out_t); + MERCURY_HANDLER_REGISTER("dset_get_vl_size", H5VL_iod_server_dset_get_vl_size, + dset_io_in_t, dset_read_out_t); + MERCURY_HANDLER_REGISTER("dset_write", H5VL_iod_server_dset_write, + dset_io_in_t, ret_t); + MERCURY_HANDLER_REGISTER("dset_set_extent", H5VL_iod_server_dset_set_extent, + dset_set_extent_in_t, ret_t); + MERCURY_HANDLER_REGISTER("dset_close", H5VL_iod_server_dset_close, + dset_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("dtype_commit", H5VL_iod_server_dtype_commit, + dtype_commit_in_t, dtype_commit_out_t); + MERCURY_HANDLER_REGISTER("dtype_open", H5VL_iod_server_dtype_open, + dtype_open_in_t, dtype_open_out_t); + MERCURY_HANDLER_REGISTER("dtype_close", H5VL_iod_server_dtype_close, + dtype_close_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("link_create", H5VL_iod_server_link_create, + link_create_in_t, ret_t); + MERCURY_HANDLER_REGISTER("link_move", H5VL_iod_server_link_move, + link_move_in_t, ret_t); + MERCURY_HANDLER_REGISTER("link_exists", H5VL_iod_server_link_exists, + link_op_in_t, htri_t); + MERCURY_HANDLER_REGISTER("link_get_info", H5VL_iod_server_link_get_info, + link_op_in_t, linfo_t); + MERCURY_HANDLER_REGISTER("link_get_val", H5VL_iod_server_link_get_val, + link_get_val_in_t, link_get_val_out_t); + MERCURY_HANDLER_REGISTER("link_iterate", H5VL_iod_server_link_iterate, + link_op_in_t, ret_t); + MERCURY_HANDLER_REGISTER("link_remove", H5VL_iod_server_link_remove, + link_op_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("object_open_by_token", H5VL_iod_server_object_open_by_token, + object_token_in_t, iod_handles_t); + MERCURY_HANDLER_REGISTER("object_open", H5VL_iod_server_object_open, + object_op_in_t, object_open_out_t); + MERCURY_HANDLER_REGISTER("object_copy", H5VL_iod_server_object_copy, + object_copy_in_t, ret_t); + MERCURY_HANDLER_REGISTER("object_exists", H5VL_iod_server_object_exists, + object_op_in_t, htri_t); + MERCURY_HANDLER_REGISTER("object_visit", H5VL_iod_server_object_visit, + object_op_in_t, ret_t); + MERCURY_HANDLER_REGISTER("set_comment", H5VL_iod_server_object_set_comment, + object_set_comment_in_t, ret_t); + MERCURY_HANDLER_REGISTER("get_comment", H5VL_iod_server_object_get_comment, + object_get_comment_in_t, object_get_comment_out_t); + MERCURY_HANDLER_REGISTER("object_get_info", H5VL_iod_server_object_get_info, + object_op_in_t, oinfo_t); + + MERCURY_HANDLER_REGISTER("read_context_acquire", H5VL_iod_server_rcxt_acquire, + rc_acquire_in_t, rc_acquire_out_t); + MERCURY_HANDLER_REGISTER("read_context_release", H5VL_iod_server_rcxt_release, + rc_release_in_t, ret_t); + MERCURY_HANDLER_REGISTER("read_context_persist", H5VL_iod_server_rcxt_persist, + rc_persist_in_t, ret_t); + MERCURY_HANDLER_REGISTER("read_context_snapshot", H5VL_iod_server_rcxt_snapshot, + rc_snapshot_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("transaction_start", H5VL_iod_server_trans_start, + tr_start_in_t, ret_t); + MERCURY_HANDLER_REGISTER("transaction_finish", H5VL_iod_server_trans_finish, + tr_finish_in_t, ret_t); + MERCURY_HANDLER_REGISTER("transaction_set_depend", H5VL_iod_server_trans_set_dependency, + tr_set_depend_in_t, ret_t); + MERCURY_HANDLER_REGISTER("transaction_skip", H5VL_iod_server_trans_skip, + tr_skip_in_t, ret_t); + MERCURY_HANDLER_REGISTER("transaction_abort", H5VL_iod_server_trans_abort, + tr_abort_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("prefetch", H5VL_iod_server_prefetch, + prefetch_in_t, hrpl_t); + MERCURY_HANDLER_REGISTER("evict", H5VL_iod_server_evict, + evict_in_t, ret_t); + + MERCURY_HANDLER_REGISTER("cancel_op", H5VL_iod_server_cancel_op, uint64_t, uint8_t); +} + +herr_t +EFF_start_server(MPI_Comm comm, MPI_Info UNUSED info) +{ + na_class_t *network_class = NULL; + AXE_engine_attr_t engine_attr; + int i; + const char *addr_name; + char **na_addr_table = NULL; + FILE *config = NULL; + herr_t ret_value = SUCCEED; + + MPI_Comm_size(comm, &num_ions_g); + MPI_Comm_rank(comm, &my_rank_g); + + /******************* Initialize mercury ********************/ + /* initialize the netwrok class */ + network_class = NA_MPI_Init(NULL, MPI_INIT_SERVER); + + /* Allocate table addrs */ + na_addr_table = (char**) malloc((size_t)num_ions_g * sizeof(char*)); + for (i = 0; i < num_ions_g; i++) { + na_addr_table[i] = (char*) malloc(MPI_MAX_PORT_NAME); + } + + addr_name = NA_MPI_Get_port_name(network_class); + strcpy(na_addr_table[my_rank_g], addr_name); + +#ifdef NA_HAS_MPI + for (i = 0; i < num_ions_g; i++) { + MPI_Bcast(na_addr_table[i], MPI_MAX_PORT_NAME, + MPI_BYTE, i, comm); + } +#endif + + /* Only rank 0 writes file */ + if (my_rank_g == 0) { + config = fopen("port.cfg", "w+"); + if (config != NULL) { + fprintf(config, "%d\n", num_ions_g); + for (i = 0; i < num_ions_g; i++) { + fprintf(config, "%s\n", na_addr_table[i]); + } + fclose(config); + } + } + + iod_comm = comm; + + if(HG_SUCCESS != HG_Init(network_class)) + return FAIL; + if(HG_SUCCESS != HG_Handler_init(network_class)) + return FAIL; + + /* Look up addr id */ + /* We do the lookup here but this may not be optimal */ + server_addr_g = (na_addr_t *) malloc((size_t)num_ions_g * sizeof(na_addr_t)); + for (i = 0; i < num_ions_g; i++) { + if(NA_SUCCESS != NA_Addr_lookup_wait(network_class, na_addr_table[i], &server_addr_g[i])) { + fprintf(stderr, "Could not find addr\n"); + return FAIL; + } + } + + /* Get array of loc string */ + server_loc_g = (char **) malloc((unsigned int) num_ions_g * sizeof(char *)); + for (i = 0; i < num_ions_g; i++) { + server_loc_g[i] = (char *) malloc(MAX_LOC_NAME); + } + + /* Only rank 0 read loc file */ + if (my_rank_g == 0) { + config = fopen("loc.cfg", "r+"); + if (!config) { + fprintf(stderr, "Warning, no loc config was found\n"); + } else { + for (i = 0; i < num_ions_g; i++) { + fscanf(config, "%s\n", server_loc_g[i]); + } + fclose(config); + } + } + /* TODO may not be necessary to do a broadcast here */ + for (i = 0; i < num_ions_g; i++) + MPI_Bcast(server_loc_g[i], MAX_LOC_NAME, MPI_BYTE, 0, comm); + + + /***************** END Initialize mercury *******************/ + + EFF__mercury_register_callbacks(); + + /* Initialize engine attribute */ + if(AXEengine_attr_init(&engine_attr) != AXE_SUCCEED) + return FAIL; + + /* Set number of threads in AXE engine */ + if(AXEset_num_threads(&engine_attr, 4) != AXE_SUCCEED) + return FAIL; + + /* Create AXE engine */ + if(AXEcreate_engine(&engine, &engine_attr) != AXE_SUCCEED) + return FAIL; + + /* Initialize Python runtime */ +#ifdef H5_HAVE_PYTHON + Py_Initialize(); +#endif + + /* Loop to receive requests from clients */ + while(1) { + HG_Handler_process(0, HG_STATUS_IGNORE); + if(shutdown) + break; + } + + /* Finalize Python runtime */ +#ifdef H5_HAVE_PYTHON + Py_Finalize(); +#endif + + if(AXE_SUCCEED != AXEterminate_engine(engine, TRUE)) + return FAIL; + + if(AXEengine_attr_destroy(&engine_attr) != AXE_SUCCEED) + return FAIL; + + /******************* Finalize mercury ********************/ + for (i = 0; i < num_ions_g; i++) { + free(server_loc_g[i]); + } + free(server_loc_g); + + for (i = 0; i < num_ions_g; i++) { + NA_Addr_free(network_class, server_addr_g[i]); + } + free(server_addr_g); + + if(HG_SUCCESS != HG_Handler_finalize()) + return FAIL; + if(HG_SUCCESS != HG_Finalize()) + return FAIL; + if(NA_SUCCESS != NA_Finalize(network_class)) + return FAIL; + + if (na_addr_table) { + for (i = 0; i < num_ions_g; i++) { + free(na_addr_table[i]); + } + free(na_addr_table); + na_addr_table = NULL; + num_ions_g = 0; + } + /***************** END Finalize mercury *******************/ + + return ret_value; +} + +static herr_t +H5VL__iod_server_finish_axe_tasks(AXE_engine_t axe_engine, AXE_task_t start_range, + size_t count) +{ + AXE_task_t u; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + for(u=start_range ; u<count+start_range ; u++) { + if(AXE_SUCCEED != AXEfinish(axe_engine, u)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE task"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_server_finish_axe_tasks() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_eff_init + * + * Purpose: Function shipper registered call for initializing the eff stack. + * this will initialize the IOD library + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_eff_init(hg_handle_t handle) +{ + uint32_t num_procs; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the input from the client connecting */ + if(HG_FAIL == HG_Handler_get_input(handle, &num_procs)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + /* initialize the IOD library */ + if(iod_initialize(iod_comm, NULL, num_procs, num_procs) < 0) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't initialize"); + + /* set the root ID */ + IOD_OBJID_SETOWNER_APP(ROOT_ID) + IOD_OBJID_SETTYPE(ROOT_ID, IOD_OBJ_KV) + + num_peers ++; + +done: + HG_Handler_start_output(handle, &ret_value); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_eff_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_eff_finalize + * + * Purpose: Function to shutdown server + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_eff_finalize(hg_handle_t handle) +{ + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + /* increment the number of terminate requests received so far */ + terminate_requests ++; + + if(iod_finalize(NULL) < 0 ) + HGOTO_ERROR2(H5E_FILE, H5E_CANTDEC, HG_FAIL, "can't finalize IOD"); + + /* if all the peers that connected at the beginning have sent the + terminate request, then finalize IOD and indicate that it is + time to shutdown the server */ + if(terminate_requests == num_peers) { + shutdown = TRUE; + } + +done: + HG_Handler_start_output(handle, &ret_value); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_eff_finalize() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_execute + * + * Purpose: Function shipper registered call for Executing Analysis. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_analysis_execute(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + analysis_execute_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (analysis_execute_in_t *)H5MM_malloc(sizeof(analysis_execute_in_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + //if(AXE_SUCCEED != AXEgenerate_task_id(engine, &axe_id)) + //HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to generate ID for AXE task"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, 0, NULL, 0, NULL, + H5VL_iod_server_analysis_execute_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_analysis_execute() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_farm + * + * Purpose: Function shipper registered call for Analysis Farming. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_analysis_farm(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + analysis_farm_in_t *input = NULL; + AXE_task_t axe_id; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (analysis_farm_in_t *)H5MM_malloc(sizeof(analysis_farm_in_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(AXE_SUCCEED != AXEgenerate_task_id(engine, &axe_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to generate ID for AXE task"); + + op_data->hg_handle = handle; + op_data->axe_id = axe_id; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, axe_id, 0, NULL, 0, NULL, + H5VL_iod_server_analysis_farm_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_analysis_farm() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_analysis_transfer + * + * Purpose: Function shipper registered call for Analysis Farming. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_analysis_transfer(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + AXE_task_t *input = NULL; + AXE_task_t axe_id; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (AXE_task_t *)H5MM_malloc(sizeof(AXE_task_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if(AXE_SUCCEED != AXEgenerate_task_id(engine, &axe_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to generate ID for AXE task"); + + if (AXE_SUCCEED != AXEcreate_task(engine, axe_id, 0, NULL, 0, NULL, + H5VL_iod_server_analysis_transfer_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_analysis_transfer() */ + +int +H5VL_iod_server_container_open(hg_handle_t handle) +{ + const char *file_name; + iod_handle_t coh; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(HG_FAIL == HG_Handler_get_input(handle, &file_name)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + /* open the container */ + printf("Calling iod_container_open on %s\n", file_name); + if(iod_container_open(file_name, NULL, IOD_CONT_R, &coh, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open file"); + + HG_Handler_start_output(handle, &coh); + +done: + if(ret_value < 0) { + coh.cookie = IOD_OH_UNDEFINED; + HG_Handler_start_output(handle, &coh); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_container_open() */ + +int +H5VL_iod_server_container_close(hg_handle_t handle) +{ + iod_handle_t coh; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(HG_FAIL == HG_Handler_get_input(handle, &coh)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + /* open the container */ + if(iod_container_close(coh, NULL, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, FAIL, "can't open file"); + +done: + HG_Handler_start_output(handle, &ret_value); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_container_open() */ + + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_cancel_op + * + * Purpose: Function to cancel an AXE operation + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_cancel_op(hg_handle_t handle) +{ + AXE_task_t axe_id; + AXE_remove_status_t remove_status; + H5ES_status_t status = H5ES_STATUS_IN_PROGRESS; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(HG_FAIL == HG_Handler_get_input(handle, &axe_id)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + /* Try to remove the task. */ + if(AXEremove(engine, axe_id, &remove_status) != AXE_SUCCEED) + HGOTO_ERROR2(H5E_SYM, H5E_CANTREMOVE, HG_FAIL, "can't remove AXE task; it has children"); + + if(remove_status == AXE_CANCELED) + HGOTO_DONE(H5VL_IOD_CANCELLED) + else if(remove_status == AXE_ALL_DONE) + HGOTO_DONE(H5VL_IOD_COMPLETED) + else if(remove_status == AXE_NOT_CANCELED) { + void *op_data; + + fprintf(stderr, "Task is running. Attempting to cancel Manually\n"); + if(AXEget_op_data(engine, axe_id, &op_data) != AXE_SUCCEED) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get op data"); + /* Attempt to cancel the task manually */ + } +done: + HG_Handler_start_output(handle, &status); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_cancel_op() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_create + * + * Purpose: Function shipper registered call for File Create. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_file_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + file_create_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (file_create_in_t *)H5MM_malloc(sizeof(file_create_in_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, 0, NULL, 0, NULL, + H5VL_iod_server_file_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_file_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_open + * + * Purpose: Function shipper registered call for File Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_file_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + file_open_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (file_open_in_t *) H5MM_malloc(sizeof(file_open_in_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, 0, NULL, 0, NULL, + H5VL_iod_server_file_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_file_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_file_close + * + * Purpose: Function shipper registered call for File Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_file_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + file_close_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (file_close_in_t *) + H5MM_malloc(sizeof(file_close_in_t)))) + HGOTO_ERROR2(H5E_FILE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_barrier_task(engine, input->axe_info.axe_id, + H5VL_iod_server_file_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_FILE, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_file_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_create + * + * Purpose: Function shipper registered call for Attr Create. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_create_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_create_in_t *) + H5MM_malloc(sizeof(attr_create_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_open + * + * Purpose: Function shipper registered call for Attr Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_open_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_open_in_t *) + H5MM_malloc(sizeof(attr_open_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_read + * + * Purpose: Function shipper registered call for Attr Read. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_read(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_io_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_io_in_t *) + H5MM_malloc(sizeof(attr_io_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_read_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_write + * + * Purpose: Function shipper registered call for Attr Write. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_write(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_io_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_io_in_t *) + H5MM_malloc(sizeof(attr_io_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_write_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_exists + * + * Purpose: Function shipper registered call for Attr Exists. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_exists(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_op_in_t *) + H5MM_malloc(sizeof(attr_op_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_exists_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_exists() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_rename + * + * Purpose: Function shipper registered call for Attr Rename. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_rename(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_rename_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_rename_in_t *) + H5MM_malloc(sizeof(attr_rename_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_rename_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_rename() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_remove + * + * Purpose: Function shipper registered call for Attr Remove. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_remove(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_op_in_t *) + H5MM_malloc(sizeof(attr_op_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_remove_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_attr_close + * + * Purpose: Function shipper registered call for Attr Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_attr_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + attr_close_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (attr_close_in_t *) + H5MM_malloc(sizeof(attr_close_in_t)))) + HGOTO_ERROR2(H5E_ATTR, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_ATTR, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_attr_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_attr_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_create + * + * Purpose: Function shipper registered call for Group Create. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_group_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + group_create_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (group_create_in_t *)H5MM_malloc(sizeof(group_create_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_group_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_group_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_open + * + * Purpose: Function shipper registered call for Group Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_group_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + group_open_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (group_open_in_t *)H5MM_malloc(sizeof(group_open_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_group_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_group_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_group_close + * + * Purpose: Function shipper registered call for Group Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_group_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + group_close_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (group_close_in_t *)H5MM_malloc(sizeof(group_close_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_group_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_group_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_create + * + * Purpose: Function shipper registered call for Dset Create. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_create_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_create_in_t *) + H5MM_malloc(sizeof(dset_create_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_open + * + * Purpose: Function shipper registered call for Dset Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_open_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_open_in_t *) + H5MM_malloc(sizeof(dset_open_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_read + * + * Purpose: Function shipper registered call for Dset Read. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_read(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_io_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_io_in_t *) + H5MM_malloc(sizeof(dset_io_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_read_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_get_vl_size + * + * Purpose: Function shipper registered call for dset get VL buffer size. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_get_vl_size(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_io_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_io_in_t *) + H5MM_malloc(sizeof(dset_io_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_get_vl_size_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_get_vl_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_write + * + * Purpose: Function shipper registered call for Dset Write. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_write(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_io_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_io_in_t *) + H5MM_malloc(sizeof(dset_io_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_write_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_set_extent + * + * Purpose: Function shipper registered call for Dset Set_Extent. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_set_extent(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_set_extent_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_set_extent_in_t *) + H5MM_malloc(sizeof(dset_set_extent_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_set_extent_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_set_extent() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dset_close + * + * Purpose: Function shipper registered call for Dset Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * January, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dset_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dset_close_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dset_close_in_t *) + H5MM_malloc(sizeof(dset_close_in_t)))) + HGOTO_ERROR2(H5E_DATASET, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATASET, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dset_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dset_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_commit + * + * Purpose: Function shipper registered call for Dtype Commit. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dtype_commit(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dtype_commit_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dtype_commit_in_t *) + H5MM_malloc(sizeof(dtype_commit_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dtype_commit_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dtype_commit() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_open + * + * Purpose: Function shipper registered call for Dtype Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dtype_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dtype_open_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dtype_open_in_t *) + H5MM_malloc(sizeof(dtype_open_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dtype_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dtype_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_dtype_close + * + * Purpose: Function shipper registered call for Dtype Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * April, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_dtype_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + dtype_close_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (dtype_close_in_t *) + H5MM_malloc(sizeof(dtype_close_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_dtype_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_dtype_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_create + * + * Purpose: Function shipper registered call for Link Creation. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_create_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_create_in_t *) + H5MM_malloc(sizeof(link_create_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_move + * + * Purpose: Function shipper registered call for Link Move. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_move(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_move_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_move_in_t *) + H5MM_malloc(sizeof(link_move_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_move_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_move() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_iterate + * + * Purpose: Function shipper registered call for Link Iteration. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_iterate(hg_handle_t UNUSED handle) +{ + //op_data_t *op_data = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + +#if 0 + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_iterate_in_t *) + H5MM_malloc(sizeof(link_iterate_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; +#endif + + //done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_exists + * + * Purpose: Function shipper registered call for Link Existance. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_exists(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_op_in_t *) + H5MM_malloc(sizeof(link_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_exists_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_exists() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_get_info + * + * Purpose: Function shipper registered call for Link get_info. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_get_info(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_op_in_t *) + H5MM_malloc(sizeof(link_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_get_info_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_get_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_get_val + * + * Purpose: Function shipper registered call for Link get_val. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_get_val(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_get_val_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_get_val_in_t *) + H5MM_malloc(sizeof(link_get_val_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_get_val_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_get_val() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_link_remove + * + * Purpose: Function shipper registered call for Link Removal. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_link_remove(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + link_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (link_op_in_t *) + H5MM_malloc(sizeof(link_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_link_remove_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_link_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_open_by_token + * + * Purpose: Function shipper registered call for Object Open by token. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_open_by_token(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_token_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_token_in_t *) + H5MM_malloc(sizeof(object_token_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_open_by_token_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_open_by_token() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_open + * + * Purpose: Function shipper registered call for Object Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_op_in_t *) + H5MM_malloc(sizeof(object_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_copy + * + * Purpose: Function shipper registered call for Object Copy. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_copy(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_copy_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_copy_in_t *) + H5MM_malloc(sizeof(object_copy_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_copy_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_visit + * + * Purpose: Function shipper registered call for Object Visit. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_visit(hg_handle_t UNUSED handle) +{ + //op_data_t *op_data = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + //done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_visit() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_exists + * + * Purpose: Function shipper registered call for Object Existance. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_exists(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_op_in_t *) + H5MM_malloc(sizeof(object_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_exists_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_exists() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_set_comment + * + * Purpose: Function shipper registered call for Set Comment. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_set_comment(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_set_comment_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_set_comment_in_t *) + H5MM_malloc(sizeof(object_set_comment_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_set_comment_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_set_comment() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_get_comment + * + * Purpose: Function shipper registered call for Get Comment. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_get_comment(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_get_comment_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_get_comment_in_t *) + H5MM_malloc(sizeof(object_get_comment_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_get_comment_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_get_comment() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_object_get_info + * + * Purpose: Function shipper registered call for Object get_info. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * May, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_object_get_info(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + object_op_in_t *input = NULL; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (object_op_in_t *) + H5MM_malloc(sizeof(object_op_in_t)))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_NOSPACE, HG_FAIL, "can't allocate input struct for decoding"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_object_get_info_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_object_get_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_create + * + * Purpose: Function shipper registered call for Map Create. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_create(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_create_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_create_in_t *)H5MM_malloc(sizeof(map_create_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_create_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_open + * + * Purpose: Function shipper registered call for Map Open. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_open(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_open_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_open_in_t *)H5MM_malloc(sizeof(map_open_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_open_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_set + * + * Purpose: Function shipper registered call for Map Set. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_set(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_set_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_set_in_t *)H5MM_malloc(sizeof(map_set_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_set_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_set() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_get + * + * Purpose: Function shipper registered call for Map Get. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_get(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_get_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_get_in_t *)H5MM_malloc(sizeof(map_get_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_get_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_get() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_get_count + * + * Purpose: Function shipper registered call for Map Get_Count. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_get_count(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_get_count_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_get_count_in_t *)H5MM_malloc(sizeof(map_get_count_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_get_count_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_get_count() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_exists + * + * Purpose: Function shipper registered call for Map Exists. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_exists(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_op_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_op_in_t *)H5MM_malloc(sizeof(map_op_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_exists_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_exists() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_delete + * + * Purpose: Function shipper registered call for Map Delete. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_delete(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_op_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_op_in_t *)H5MM_malloc(sizeof(map_op_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_delete_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_map_close + * + * Purpose: Function shipper registered call for Map Close. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * July, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_map_close(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + map_close_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (map_close_in_t *)H5MM_malloc(sizeof(map_close_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_map_close_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_map_close() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_acquire + * + * Purpose: Function shipper registered call for Read Context Acquire. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_rcxt_acquire(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + rc_acquire_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (rc_acquire_in_t *)H5MM_malloc(sizeof(rc_acquire_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_rcxt_acquire_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_rcxt_acquire() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_release + * + * Purpose: Function shipper registered call for read context release. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_rcxt_release(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + rc_release_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (rc_release_in_t *)H5MM_malloc(sizeof(rc_release_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_rcxt_release_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_rcxt_release() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_persist + * + * Purpose: Function shipper registered call for read context persist. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_rcxt_persist(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + rc_persist_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (rc_persist_in_t *)H5MM_malloc(sizeof(rc_persist_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_rcxt_persist_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_rcxt_persist() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_snapshot + * + * Purpose: Function shipper registered call for read context snapshot. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_rcxt_snapshot(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + rc_snapshot_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (rc_snapshot_in_t *)H5MM_malloc(sizeof(rc_snapshot_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_rcxt_snapshot_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_rcxt_snapshot() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_start + * + * Purpose: Function shipper registered call for transaction start. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_trans_start(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + tr_start_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (tr_start_in_t *)H5MM_malloc(sizeof(tr_start_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_trans_start_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_trans_start() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_finish + * + * Purpose: Function shipper registered call for transaction finish. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_trans_finish(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + tr_finish_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (tr_finish_in_t *)H5MM_malloc(sizeof(tr_finish_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_trans_finish_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_trans_finish() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_set_dependency + * + * Purpose: Function shipper registered call for transaction set_dependency. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_trans_set_dependency(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + tr_set_depend_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (tr_set_depend_in_t *)H5MM_malloc(sizeof(tr_set_depend_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_trans_set_dependency_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_trans_set_dependency() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_skip + * + * Purpose: Function shipper registered call for transaction skip. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_trans_skip(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + tr_skip_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (tr_skip_in_t *)H5MM_malloc(sizeof(tr_skip_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_trans_skip_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_trans_skip() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_abort + * + * Purpose: Function shipper registered call for transaction abort. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_trans_abort(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + tr_abort_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (tr_abort_in_t *)H5MM_malloc(sizeof(tr_abort_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_trans_abort_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_trans_abort() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_prefetch + * + * Purpose: Function shipper registered call for object prefetch. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2014 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_prefetch(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + prefetch_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (prefetch_in_t *)H5MM_malloc(sizeof(prefetch_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_prefetch_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_prefetch() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_evict + * + * Purpose: Function shipper registered call for object evict. + * Inserts the real worker routine into the Async Engine. + * + * Return: Success: HG_SUCCESS + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February, 2014 + * + *------------------------------------------------------------------------- + */ +int +H5VL_iod_server_evict(hg_handle_t handle) +{ + op_data_t *op_data = NULL; + evict_in_t *input; + int ret_value = HG_SUCCESS; + + FUNC_ENTER_NOAPI_NOINIT + + if(NULL == (op_data = (op_data_t *)H5MM_malloc(sizeof(op_data_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(NULL == (input = (evict_in_t *)H5MM_malloc(sizeof(evict_in_t)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate axe op_data struct"); + + if(HG_FAIL == HG_Handler_get_input(handle, input)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, HG_FAIL, "can't get input parameters"); + + if(NULL == engine) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "AXE engine not started"); + + if(input->axe_info.count && + H5VL__iod_server_finish_axe_tasks(engine, input->axe_info.start_range, + input->axe_info.count) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "Unable to cleanup AXE tasks"); + + op_data->hg_handle = handle; + op_data->input = (void *)input; + + if (AXE_SUCCEED != AXEcreate_task(engine, input->axe_info.axe_id, + input->axe_info.num_parents, input->axe_info.parent_axe_ids, + 0, NULL, H5VL_iod_server_evict_cb, op_data, NULL)) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, HG_FAIL, "can't insert task into async engine"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_server_evict() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_server.h b/src/H5VLiod_server.h new file mode 100644 index 0000000..c9b1f28 --- /dev/null +++ b/src/H5VLiod_server.h @@ -0,0 +1,436 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5VL iod server module + */ +#ifndef _H5VLiod_server_H +#define _H5VLiod_server_H + +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Ppublic.h" +#include "H5Spublic.h" +#include "H5VLiod_common.h" + +#ifdef H5_HAVE_EFF + +/* Key names for Metadata stored in KV objects */ +#define H5VL_IOD_KEY_SOFT_LINK "soft_link_value" +#define H5VL_IOD_KEY_DTYPE_SIZE "serialized_size" +#define H5VL_IOD_KEY_KV_IDS_INDEX "kv_ids_index" +#define H5VL_IOD_KEY_ARRAY_IDS_INDEX "array_ids_index" +#define H5VL_IOD_KEY_BLOB_IDS_INDEX "blob_ids_index" +#define H5VL_IOD_KEY_OBJ_COMMENT "object_comment" +#define H5VL_IOD_KEY_OBJ_CPL "object_create_plist" +#define H5VL_IOD_KEY_OBJ_LINK_COUNT "object_link_count" +#define H5VL_IOD_KEY_OBJ_TYPE "object_type" +#define H5VL_IOD_KEY_OBJ_DATATYPE "object_datatype" +#define H5VL_IOD_KEY_OBJ_DATASPACE "object_dataspace" +#define H5VL_IOD_KEY_MAP_KEY_TYPE "map_keytype" +#define H5VL_IOD_KEY_MAP_VALUE_TYPE "map_valtype" + +/* Enum for metadata types stored in MD KV for HDF5->IOD objects */ +typedef enum H5VL_iod_metadata_t { + H5VL_IOD_PLIST, /*type ID for property lists */ + H5VL_IOD_LINK_COUNT, /*type ID for link count */ + H5VL_IOD_OBJECT_TYPE, /*type ID for object type */ + H5VL_IOD_DATATYPE, /*type ID for datatypes */ + H5VL_IOD_DATASPACE, /*type ID for dataspaces */ + H5VL_IOD_LINK /*type ID for links */ +} H5VL_iod_metadata_t; + +/* the AXE op data strucutre stored with every operation */ +typedef struct op_data_t { + void *input; + void *output; + AXE_task_t axe_id; + hg_handle_t hg_handle; +} op_data_t; + +/* the IOD scratch pad type */ +typedef iod_obj_id_t scratch_pad[4]; + +/* the link value stored in KV stores */ +typedef struct H5VL_iod_link_t { + H5L_type_t link_type; /* The type of the link (Hard & Soft only suppoted for now) */ + union { + iod_obj_id_t iod_id; + char *symbolic_name; + } u; + iod_obj_id_t iod_id; /* The ID of the object the link points to */ +} H5VL_iod_link_t; + +extern iod_obj_id_t ROOT_ID; +extern int num_ions_g; +extern int my_rank_g; +extern na_addr_t *server_addr_g; +extern char **server_loc_g; +extern hg_id_t H5VL_EFF_OPEN_CONTAINER; +extern hg_id_t H5VL_EFF_CLOSE_CONTAINER; +extern hg_id_t H5VL_EFF_ANALYSIS_FARM; +extern hg_id_t H5VL_EFF_ANALYSIS_FARM_TRANSFER; + +H5_DLL void EFF__mercury_register_callbacks(void); + +H5_DLL int H5VL_iod_server_analysis_execute(hg_handle_t handle); +H5_DLL int H5VL_iod_server_analysis_farm(hg_handle_t handle); +H5_DLL int H5VL_iod_server_analysis_transfer(hg_handle_t handle); +H5_DLL int H5VL_iod_server_container_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_container_close(hg_handle_t handle); + +H5_DLL int H5VL_iod_server_eff_init(hg_handle_t handle); +H5_DLL int H5VL_iod_server_eff_finalize(hg_handle_t handle); +H5_DLL int H5VL_iod_server_file_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_file_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_file_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_read(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_write(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_exists(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_rename(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_remove(hg_handle_t handle); +H5_DLL int H5VL_iod_server_attr_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_group_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_group_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_group_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_set(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_get(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_get_count(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_exists(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_delete(hg_handle_t handle); +H5_DLL int H5VL_iod_server_map_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_read(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_get_vl_size(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_write(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_set_extent(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dset_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dtype_commit(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dtype_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_dtype_close(hg_handle_t handle); +H5_DLL int H5VL_iod_server_cancel_op(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_create(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_move(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_exists(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_get_info(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_get_val(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_remove(hg_handle_t handle); +H5_DLL int H5VL_iod_server_link_iterate(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_open_by_token(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_open(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_copy(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_visit(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_exists(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_set_comment(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_get_comment(hg_handle_t handle); +H5_DLL int H5VL_iod_server_object_get_info(hg_handle_t handle); +H5_DLL int H5VL_iod_server_rcxt_acquire(hg_handle_t handle); +H5_DLL int H5VL_iod_server_rcxt_release(hg_handle_t handle); +H5_DLL int H5VL_iod_server_rcxt_persist(hg_handle_t handle); +H5_DLL int H5VL_iod_server_rcxt_snapshot(hg_handle_t handle); +H5_DLL int H5VL_iod_server_trans_start(hg_handle_t handle); +H5_DLL int H5VL_iod_server_trans_finish(hg_handle_t handle); +H5_DLL int H5VL_iod_server_trans_set_dependency(hg_handle_t handle); +H5_DLL int H5VL_iod_server_trans_skip(hg_handle_t handle); +H5_DLL int H5VL_iod_server_trans_abort(hg_handle_t handle); +H5_DLL int H5VL_iod_server_prefetch(hg_handle_t handle); +H5_DLL int H5VL_iod_server_evict(hg_handle_t handle); + +H5_DLL void H5VL_iod_server_analysis_execute_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *_op_data); +H5_DLL void H5VL_iod_server_analysis_farm_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *_op_data); +H5_DLL void H5VL_iod_server_analysis_transfer_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *_op_data); + +H5_DLL void H5VL_iod_server_file_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_file_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_file_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_read_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_write_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_exists_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_rename_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_remove_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_attr_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_group_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_group_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_group_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_set_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_get_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_get_count_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_exists_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_delete_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_map_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_read_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_get_vl_size_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_write_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_set_extent_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dset_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dtype_commit_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dtype_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_dtype_close_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_create_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_move_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_exists_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_get_info_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_get_val_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_link_remove_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); + +H5_DLL void H5VL_iod_server_object_open_by_token_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *_op_data); +H5_DLL void H5VL_iod_server_object_open_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_object_copy_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_object_exists_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_object_set_comment_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_object_get_comment_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_object_get_info_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); + +H5_DLL void H5VL_iod_server_rcxt_acquire_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_rcxt_release_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_rcxt_persist_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_rcxt_snapshot_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_trans_start_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_trans_finish_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_trans_set_dependency_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_trans_skip_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_trans_abort_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_prefetch_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); +H5_DLL void H5VL_iod_server_evict_cb(AXE_engine_t axe_engine, + size_t num_n_parents, AXE_task_t n_parents[], + size_t num_s_parents, AXE_task_t s_parents[], + void *op_data); + +/* Helper routines used several times in different places */ +H5_DLL herr_t H5VL_iod_server_traverse(iod_handle_t coh, iod_obj_id_t loc_id, iod_handles_t loc_handle, + const char *path, iod_trans_id_t wtid, iod_trans_id_t rtid, + hbool_t create_interm_grps, uint32_t cs_scope, + char **last_comp, iod_obj_id_t *iod_id, iod_handles_t *iod_oh); +H5_DLL herr_t H5VL_iod_server_open_path(iod_handle_t coh, iod_obj_id_t loc_id, + iod_handles_t loc_handle, const char *path, + iod_trans_id_t tid, uint32_t cs_scope, + /*out*/iod_obj_id_t *iod_id, /*out*/iod_handles_t *iod_oh); +H5_DLL herr_t H5VL_iod_get_file_desc(hid_t space_id, hssize_t *count, iod_hyperslab_t *hslabs); +H5_DLL herr_t H5VL_iod_insert_plist(iod_handle_t oh, iod_trans_id_t tid, hid_t plist_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_link_count(iod_handle_t oh, iod_trans_id_t tid, uint64_t count, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_object_type(iod_handle_t oh, iod_trans_id_t tid, H5I_type_t obj_type, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_datatype(iod_handle_t oh, iod_trans_id_t tid, hid_t type_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_datatype_with_key(iod_handle_t oh, iod_trans_id_t tid, hid_t type_id, + const char *key, uint32_t cs_scope, + iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_dataspace(iod_handle_t oh, iod_trans_id_t tid, hid_t space_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event); +H5_DLL herr_t H5VL_iod_insert_new_link(iod_handle_t oh, iod_trans_id_t tid, const char *link_name, + H5L_type_t link_type, const void *link_val, + uint32_t cs_scope, iod_hint_list_t *hints, + iod_event_t *event); +H5_DLL herr_t H5VL_iod_get_metadata(iod_handle_t oh, iod_trans_id_t tid, H5VL_iod_metadata_t md_type, + const char *key, uint32_t cs_scope, iod_event_t *event, void *ret); +H5_DLL herr_t H5VL__iod_server_adjust_buffer(hid_t from_type_id, hid_t to_type_id, size_t nelmts, + hid_t dxpl_id, size_t size, void **buf, + hbool_t *is_vl_data, size_t *_buf_size); +H5_DLL herr_t H5VL_iod_verify_scratch_pad(scratch_pad *sp, iod_checksum_t iod_cs); +H5_DLL herr_t H5VL_iod_verify_kv_pair(void *key, iod_size_t key_size, void *value, iod_size_t val_size, + iod_checksum_t *iod_cs); +H5_DLL herr_t H5VL__iod_server_final_io(iod_handle_t iod_oh, hid_t space_id, size_t elmt_size, + hbool_t write_op, void *buf, size_t buf_size, + iod_checksum_t cs, uint32_t cs_scope, iod_trans_id_t tid); + +#endif /* H5_HAVE_EFF */ +#endif /* _H5VLiod_server_H */ diff --git a/src/H5VLiod_trans.c b/src/H5VLiod_trans.c new file mode 100644 index 0000000..1dd41cb --- /dev/null +++ b/src/H5VLiod_trans.c @@ -0,0 +1,773 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5VLiod_server.h" +#include "H5RCpublic.h" +#include "H5TRpublic.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * July, 2013 + * + * Purpose: The IOD plugin server side transaction and read context routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_acquire_cb + * + * Purpose: Acquire a read context of a container using a version number. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_rcxt_acquire_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + rc_acquire_in_t *input = (rc_acquire_in_t *)op_data->input; + rc_acquire_out_t output; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t c_version = input->c_version; + iod_trans_id_t acquired_version; + hid_t rcapl_id; + iod_ret_t ret; + H5RC_request_t acquire_req; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(H5P_DEFAULT == input->rcapl_id) + input->rcapl_id = H5Pcopy(H5P_RC_ACQUIRE_DEFAULT); + rcapl_id = input->rcapl_id; + + if(H5Pget_rcapl_version_request(rcapl_id, &acquire_req) < 0) { + HGOTO_ERROR2(H5E_PLIST, H5E_CANTSET,FAIL, "can't get acquire request property"); + } + + switch(acquire_req) { + case H5RC_EXACT: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Exact Acquire Read Context %"PRIu64"\n", input->c_version); +#endif + if((ret = iod_trans_start(coh, &c_version, NULL, 0, IOD_TRANS_R, NULL)) < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't acquire read context"); + } + acquired_version = c_version; + break; + case H5RC_LAST: +#if H5VL_IOD_DEBUG + fprintf(stderr, "Acquire LAST Read Context\n"); +#endif + c_version = IOD_TID_UNKNOWN; + if(iod_trans_start(coh, &c_version, NULL, 0, IOD_TRANS_R, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't acquire read context"); + acquired_version = c_version; + break; + case H5RC_NEXT: + { + iod_cont_trans_stat_t *tids; + uint64_t u; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Next Acquire Read Context %"PRIu64"\n", input->c_version); +#endif + if(iod_query_cont_trans_stat(coh, &tids, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get container tids status"); + + acquired_version = IOD_TID_UNKNOWN; + + for(u=c_version; u<tids->latest_rdable ; u++) { + if(iod_trans_start(coh, &u, NULL, 0, IOD_TRANS_R, NULL) < 0) + continue; + acquired_version = u; + break; + } + + if(IOD_TID_UNKNOWN == acquired_version) { + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, + "can't get a read version"); + } + + if(iod_free_cont_trans_stat(coh, tids) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free container transaction status object"); + break; + } + case H5RC_PREV: + { + iod_cont_trans_stat_t *tids; + uint64_t u; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Next Acquire Read Context %"PRIu64"\n", input->c_version); +#endif + if(iod_query_cont_trans_stat(coh, &tids, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't get container tids status"); + + if(c_version >= tids->latest_rdable) { + acquired_version = tids->latest_rdable; + if(iod_trans_start(coh, &acquired_version, NULL, 0, IOD_TRANS_R, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't acquire read context"); + break; + } + + acquired_version = IOD_TID_UNKNOWN; + u=c_version; + + for(u=c_version; u>0; u--) { + if(iod_trans_start(coh, &u, NULL, 0, IOD_TRANS_R, NULL) < 0) + continue; + acquired_version = u; + break; + } + + if(IOD_TID_UNKNOWN == acquired_version) { + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, + "can't get a read version"); + } + + if(iod_free_cont_trans_stat(coh, tids) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't free container transaction status object"); + + break; + } + default: + HGOTO_ERROR2(H5E_PLIST, H5E_CANTSET, FAIL, "invalid acquire request"); + } + + output.c_version = acquired_version; + output.ret = ret_value; + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Acquire Read Context. Acquired %"PRIu64"\n", output.c_version); +#endif + + HG_Handler_start_output(op_data->hg_handle, &output); + +done: + /* return an UNDEFINED oh to the client if the operation failed */ + if(ret_value < 0) { + fprintf(stderr, "Failed to Acquire Read context\n"); + output.ret = FAIL; + output.c_version = c_version; + HG_Handler_start_output(op_data->hg_handle, &output); + } + + input = (rc_acquire_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_rcxt_acquire_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_release_cb + * + * Purpose: Release a read context of a container using a version number. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_rcxt_release_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + rc_release_in_t *input = (rc_release_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Release Read Context %"PRIu64"\n", input->c_version); +#endif + + if(iod_trans_finish(coh, input->c_version, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't release Read Context"); + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Release Read context\n"); + + input = (rc_release_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_rcxt_release_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_persist_cb + * + * Purpose: Persist a read context of a container using a version number. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_rcxt_persist_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + rc_persist_in_t *input = (rc_persist_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Persist Read Context %"PRIu64"\n", input->c_version); +#endif + + if(iod_trans_persist(coh, input->c_version, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't persist Read Context"); + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Persist Read context\n"); + + input = (rc_persist_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_rcxt_persist_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_rcxt_snapshot_cb + * + * Purpose: Snapshot a read context of a container using a version number. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_rcxt_snapshot_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + rc_snapshot_in_t *input = (rc_snapshot_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t tid = input->c_version; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Snapshot %s with Read Context %"PRIu64"\n", input->snapshot_name, input->c_version); +#endif + + /* MSC - can only snapshot latest version */ + if(iod_container_snapshot(coh, tid, input->snapshot_name, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't snapshot Read Context"); + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Snapshot Read context\n"); + + input = (rc_snapshot_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_rcxt_snapshot_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_start_cb + * + * Purpose: Start a transaction on a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_trans_start_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + tr_start_in_t *input = (tr_start_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + hid_t trspl_id; + iod_trans_id_t trans_num = input->trans_num; + unsigned num_peers; /* the number of peers starting this transaction */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Transaction Start %"PRIu64"\n", input->trans_num); +#endif + + if(H5P_DEFAULT == input->trspl_id) + input->trspl_id = H5Pcopy(H5P_TR_START_DEFAULT); + trspl_id = input->trspl_id; + + if(H5Pget_trspl_num_peers(trspl_id, &num_peers) < 0) + HGOTO_ERROR2(H5E_PLIST, H5E_CANTGET, FAIL, "can't get acquire request property"); + + if(iod_trans_start(coh, &trans_num, NULL, num_peers, IOD_TRANS_W, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't start transaction"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Transaction Start\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Start Transaction\n"); + + input = (tr_start_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_trans_start_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_finish_cb + * + * Purpose: Finish a transaction on a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_trans_finish_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + tr_finish_in_t *input = (tr_finish_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + uint32_t cs_scope = input->cs_scope; + //hid_t trfpl_id; + iod_trans_id_t trans_num = input->trans_num; + hbool_t acquire = input->acquire; + uint32_t client_rank = input->client_rank; + iod_obj_id_t oidkv_id = input->oidkv_id; + iod_handle_t oidkv_oh; + uint64_t oid_index[3]; + iod_kv_t kv; + iod_ret_t ret; + int step = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Transaction Finish %"PRIu64"\n", trans_num); +#endif + + IOD_OBJID_SETTYPE(oidkv_id, IOD_OBJ_KV) + IOD_OBJID_SETOWNER_APP(oidkv_id) + + oid_index[0] = input->kv_oid_index; + oid_index[1] = input->array_oid_index; + oid_index[2] = input->blob_oid_index; + + ret = iod_obj_open_write(coh, oidkv_id, trans_num, NULL, &oidkv_oh, NULL); + if(ret != 0) + HGOTO_ERROR_IOD(ret, FAIL, "can't open oid KV"); + + step ++; + + kv.value = &oid_index; + kv.value_len = sizeof(iod_obj_id_t) * 3; + kv.key = &client_rank; + kv.key_len = sizeof(uint32_t); + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + if (iod_kv_set(oidkv_oh, trans_num, NULL, &kv, cs, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oidkv_oh, trans_num, NULL, &kv, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in oid KV"); + } + + if(iod_obj_close(oidkv_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object handle"); + + step --; + + /* Finish the transaction */ + if(iod_trans_finish(coh, trans_num, NULL, 0, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't finish transaction"); + + /* if the flag is true, acquire a read context on the finished transaction */ + if(TRUE == acquire) { +#if H5VL_IOD_DEBUG + fprintf(stderr, "Transaction Acquire after Finish %"PRIu64"\n", trans_num); +#endif + + if(iod_trans_start(coh, &trans_num, NULL, 0, IOD_TRANS_R, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't acquire read context"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Transaction Finish\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Finish Transaction\n"); + + if(step == 1) { + iod_obj_close(oidkv_oh, NULL, NULL); + } + + input = (tr_finish_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_trans_finish_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_set_dependency_cb + * + * Purpose: Set Dependency between 2 transactions on a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_trans_set_dependency_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + tr_set_depend_in_t *input = (tr_set_depend_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_depend_desc_t depends; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Transaction Set_Dependency %"PRIu64" on %"PRIu64"\n", + input->child_trans_num, input->parent_trans_num); +#endif + + /* MSC - set depends */ + + //if(iod_trans_depend(coh, depends, NULL) < 0) + //HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set dependency between transactions"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Transaction Set_Dependency\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Set_Dependency between Transactions\n"); + + input = (tr_set_depend_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_trans_set_dependency_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_skip_cb + * + * Purpose: Skip a number of transactions on a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_trans_skip_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + tr_skip_in_t *input = (tr_skip_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t start_trans_num = input->start_trans_num; + uint64_t count = input->count; + iod_trans_range_desc_t skip_ranges; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Transaction Skip %"PRIu64" starting at %"PRIu64"\n", count, start_trans_num); +#endif + + /* MSC - set skip ranges */ + skip_ranges.n_range = 1; + //if(iod_trans_skip(coh, skip_ranges, NULL) < 0) + //HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't skip transactions"); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Transaction Skip\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Skip Transaction\n"); + + input = (tr_skip_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_trans_skip_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_trans_abort_cb + * + * Purpose: Abort a transaction on a container. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_trans_abort_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + tr_abort_in_t *input = (tr_abort_in_t *)op_data->input; + iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t trans_num = input->trans_num; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Aborting Transaction %"PRIu64"\n", input->trans_num); +#endif + + ret = iod_trans_finish(coh, trans_num, NULL, IOD_TRANS_ABORT_DEPENDENT, NULL); + if(ret == -IOD_EC_TRANS_DISCARDED) + fprintf(stderr, "Transaction %"PRIu64" already discarded\n", input->trans_num); + else if(ret < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTSET, FAIL, "can't abort transaction"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Transaction Abort\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Abort Transaction\n"); + + input = (tr_abort_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_trans_abort_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_prefetch_cb + * + * Purpose: prefetch an object from central storage to BB. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_prefetch_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + prefetch_in_t *input = (prefetch_in_t *)op_data->input; + //iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t tid = input->rcxt_num; + iod_handles_t iod_oh = input->iod_oh; /* object handle */ + iod_obj_id_t iod_id = input->iod_id; /* OID */ + //H5I_type_t obj_type = input->obj_type; + //hid_t apl_id = input->apl_id; + iod_trans_id_t replica_id; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Prefetch Object (OID %"PRIx64" OH %"PRIu64") at Version %"PRIu64"\n", + iod_id, iod_oh.rd_oh.cookie, tid); +#endif + + ret = iod_obj_fetch(iod_oh.rd_oh, tid, NULL, NULL, NULL, &replica_id, NULL); + if(ret != 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't prefetch object"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Prefetch\n"); +#endif + +done: + if(SUCCEED != ret_value) + replica_id = 0; + + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &replica_id)) + fprintf(stderr, "Failed to Prefetch Object\n"); + + input = (prefetch_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_prefetch_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_evict_cb + * + * Purpose: evicts an object from BB. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * February 2014 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_evict_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + evict_in_t *input = (evict_in_t *)op_data->input; + //iod_handle_t coh = input->coh; /* the container handle */ + iod_trans_id_t tid = input->rcxt_num; + iod_handles_t iod_oh = input->iod_oh; /* object handle */ + iod_obj_id_t iod_id = input->iod_id; /* OID */ + //H5I_type_t obj_type = input->obj_type; + //hid_t apl_id = input->apl_id; + iod_trans_id_t replica_id = input->replica_id; + iod_ret_t ret; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(replica_id) { + fprintf(stderr, "Evict Object (OID %"PRIx64" OH %"PRIu64") replica tag %"PRIx64"\n", + iod_id, iod_oh.rd_oh.cookie, replica_id); + ret = iod_obj_purge(iod_oh.rd_oh, replica_id, NULL, NULL); + } + else { + fprintf(stderr, "Evict Object (OID %"PRIx64" OH %"PRIu64") at Version %"PRIu64"\n", + iod_id, iod_oh.rd_oh.cookie, tid); + ret = iod_obj_purge(iod_oh.rd_oh, tid, NULL, NULL); + } + + if(ret < 0) { + fprintf(stderr, "%d (%s).\n", ret, strerror(-ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "can't evict object"); + } + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Done with Evict\n"); +#endif + +done: + if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &ret_value)) + fprintf(stderr, "Failed to Evict Object\n"); + + input = (evict_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_evict_cb() */ + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_util.c b/src/H5VLiod_util.c new file mode 100644 index 0000000..c577ecb --- /dev/null +++ b/src/H5VLiod_util.c @@ -0,0 +1,1288 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + +#include "H5Gpkg.h" /* Groups */ +#include "H5Sprivate.h" /* Dataspaces */ +#include "H5WBprivate.h" /* Wrapped Buffers */ +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * February, 2013 + * + * Purpose: The IOD plugin server utility routines. + */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_traverse + * + * Purpose: + * Function to Traverse the path in IOD KV objects given the + * starting location ID, object handle, and path name. This walks + * through the IOD KV objects to get to the last component in the + * path. The last component is not opened. Usually this is called when + * creating an object. The Function returns the iod ID and object + * handle of the before to last component, and the last component + * string, if the user requests it. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_server_traverse(iod_handle_t coh, iod_obj_id_t loc_id, iod_handles_t loc_handle, + const char *path, iod_trans_id_t wtid, iod_trans_id_t rtid, + hbool_t create_interm_grps, uint32_t cs_scope, + /* out */char **last_comp, /* out */iod_obj_id_t *iod_id, + /* out */iod_handles_t *iod_oh) +{ + char comp_buf[1024]; /* Temporary buffer for path components */ + char *comp; /* Pointer to buffer for path components */ + H5WB_t *wb = NULL; /* Wrapped buffer for temporary buffer */ + size_t nchars; /* component name length */ + iod_handles_t cur_oh; + iod_handle_t prev_oh; + iod_obj_id_t cur_id; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* Creating intermediate groups is not supported for now */ + assert(FALSE == create_interm_grps); + + cur_oh.rd_oh.cookie = loc_handle.rd_oh.cookie; + cur_oh.wr_oh.cookie = loc_handle.wr_oh.cookie; + cur_id = loc_id; + + /* open the current group */ + if(cur_oh.rd_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, loc_id, wtid, NULL, &cur_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + } + + /* Wrap the local buffer for serialized header info */ + if(NULL == (wb = H5WB_wrap(comp_buf, sizeof(comp_buf)))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") + /* Get a pointer to a buffer that's large enough */ + if(NULL == (comp = (char *)H5WB_actual(wb, (HDstrlen(path) + 1)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Traverse the path */ + while((path = H5G__component(path, &nchars)) && *path) { + const char *s; /* Temporary string pointer */ + iod_size_t kv_size; + H5VL_iod_link_t value; + + /* Copy the component path into a null-terminated buffer. */ + HDmemcpy(comp, path, nchars); + comp[nchars] = '\0'; + + /* + * The special path `.' is a no-op. + */ + if('.' == comp[0] && !comp[1]) { + path += nchars; + continue; + } /* end if */ + + /* Check if this is the last component of the path */ + if(!((s = H5G__component(path + nchars, NULL)) && *s)) { + if(last_comp) { + *last_comp = HDstrdup(comp); + } + break; + } + + kv_size = sizeof(H5VL_iod_link_t); + + prev_oh.cookie = cur_oh.rd_oh.cookie; + + /* lookup next object in the current group */ + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + comp, cs_scope, NULL, &value) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + + /* if this a soft link, traverse the link value if the ID is undefined */ + if(H5L_TYPE_SOFT == value.link_type) { + if('/' == *value.u.symbolic_name) { + cur_id = ROOT_ID; + } + + /* Traverse Path and open the target object */ + if(H5VL_iod_server_open_path(coh, cur_id, cur_oh, value.u.symbolic_name, + rtid, cs_scope, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + free(value.u.symbolic_name); + } + else + cur_id = value.u.iod_id; + + /* Close previous read handle unless it is the original one */ + if(loc_handle.rd_oh.cookie != prev_oh.cookie) { + if(iod_obj_close(prev_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close current object handle"); + } + + /* open the current group */ + if (iod_obj_open_read(coh, cur_id, rtid, NULL, &cur_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + /* Advance to next component in string */ + path += nchars; + } /* end while */ + + /* Release temporary component buffer */ + if(wb && H5WB_unwrap(wb) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't release wrapped buffer"); + + *iod_id = cur_id; + (*iod_oh).rd_oh.cookie = cur_oh.rd_oh.cookie; + + if(cur_id != loc_id || + loc_handle.wr_oh.cookie == IOD_OH_UNDEFINED) { + /* open a write handle on the ID. */ + if (iod_obj_open_write(coh, cur_id, wtid, NULL, &cur_oh.wr_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + } + + (*iod_oh).wr_oh.cookie = cur_oh.wr_oh.cookie; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_open_path + * + * Purpose: Function to Traverse the path in IOD KV objects given the + * starting location ID, object handle, and path name. This walks + * through the IOD KV objects to get to the last component in the path + * and opens the last component for read only, i.e. does not open the + * wr_oh, but will set it to undefined. Usually this is called when + * opening an object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_server_open_path(iod_handle_t coh, iod_obj_id_t loc_id, iod_handles_t loc_handle, + const char *path, iod_trans_id_t rtid, uint32_t cs_scope, + /*out*/iod_obj_id_t *iod_id, /*out*/iod_handles_t *iod_oh) +{ + char comp_buf[1024]; /* Temporary buffer for path components */ + char *comp; /* Pointer to buffer for path components */ + H5WB_t *wb = NULL; /* Wrapped buffer for temporary buffer */ + size_t nchars; /* component name length */ + iod_handles_t cur_oh; + iod_handle_t prev_oh; + iod_obj_id_t cur_id; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + cur_oh.rd_oh.cookie = loc_handle.rd_oh.cookie; + cur_oh.wr_oh.cookie = loc_handle.wr_oh.cookie; + cur_id = loc_id; + + if(cur_oh.rd_oh.cookie == IOD_OH_UNDEFINED) { + /* open the current group */ + if (iod_obj_open_read(coh, loc_id, rtid, NULL, &cur_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open start location"); + } + + /* Wrap the local buffer for serialized header info */ + if(NULL == (wb = H5WB_wrap(comp_buf, sizeof(comp_buf)))) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") + /* Get a pointer to a buffer that's large enough */ + if(NULL == (comp = (char *)H5WB_actual(wb, (HDstrlen(path) + 1)))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Traverse the path */ + while((path = H5G__component(path, &nchars)) && *path) { + iod_size_t kv_size; + H5VL_iod_link_t value; + + /* Copy the component path into a null-terminated buffer. */ + HDmemcpy(comp, path, nchars); + comp[nchars] = '\0'; + + /* + * The special path `.' is a no-op. + */ + if('.' == comp[0] && !comp[1]) { + path += nchars; + continue; + } /* end if */ + + kv_size = sizeof(H5VL_iod_link_t); + + prev_oh.cookie = cur_oh.rd_oh.cookie; + + /* lookup next object in the current group */ + if(H5VL_iod_get_metadata(cur_oh.rd_oh, rtid, H5VL_IOD_LINK, + comp, cs_scope, NULL, &value) < 0) { + /* Close previous handle unless it is the original one */ + if(loc_handle.rd_oh.cookie != prev_oh.cookie && + iod_obj_close(prev_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close current object handle"); + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve link value"); + } + + /* if this a soft link, traverse the link value if the ID is undefined */ + if(H5L_TYPE_SOFT == value.link_type) { + if('/' == *value.u.symbolic_name) { + cur_id = ROOT_ID; + } + + /* Traverse Path and open the target object */ + if(H5VL_iod_server_open_path(coh, cur_id, cur_oh, value.u.symbolic_name, + rtid, cs_scope, &cur_id, &cur_oh) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't open object"); + + free(value.u.symbolic_name); + } + else + cur_id = value.u.iod_id; + + /* Close previous handle unless it is the original one */ + if(loc_handle.rd_oh.cookie != prev_oh.cookie && + iod_obj_close(prev_oh, NULL, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't close current object handle"); + + /* open the current group */ + if (iod_obj_open_read(coh, cur_id, rtid, NULL, &cur_oh.rd_oh, NULL) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current object"); + + /* Advance to next component in string */ + path += nchars; + } /* end while */ + + /* Release temporary component buffer */ + if(wb && H5WB_unwrap(wb) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't release wrapped buffer"); + + *iod_id = cur_id; + (*iod_oh).rd_oh.cookie = cur_oh.rd_oh.cookie; + (*iod_oh).wr_oh.cookie = IOD_OH_UNDEFINED; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_file_desc + * + * Purpose: + * Function to generate IOD hyperslab objects from HDF5 + * dataspace selections. If hslabs is NULL, a count of the number of + * hslabs needed is returned in count. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_get_file_desc(hid_t space_id, hssize_t *count, iod_hyperslab_t *hslabs) +{ + hssize_t num_descriptors = 0, n; + int ndims = 0, i; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get the rank of this dataspace */ + if((ndims = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion"); + + switch(H5Sget_select_type(space_id)) { + case H5S_SEL_NONE: + /* nothing selected */ + num_descriptors = 0; + HGOTO_DONE(SUCCEED); + case H5S_SEL_ALL: + /* The entire dataspace is selected, 1 large iod hyperslab is needed */ + num_descriptors = 1; + + if(NULL != hslabs) { + hsize_t dims[H5S_MAX_RANK]; + + /* get the dimensions sizes of the dataspace */ + if(H5Sget_simple_extent_dims(space_id, dims, NULL) < 0) + HGOTO_ERROR2(H5E_INTERNAL, H5E_CANTGET, FAIL, "unable to get dataspace dimesnsion sizes"); + /* populate the hyperslab */ + for(i=0 ; i<ndims ; i++) { + hslabs[0].start[i] = 0; + hslabs[0].block[i] = dims[i]; + hslabs[0].stride[i] = dims[i]; + hslabs[0].count[i] = 1; + } + } + break; + case H5S_SEL_POINTS: + { + /* we need a hyperslab element for each point */ + if((num_descriptors = H5Sget_select_elem_npoints(space_id)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "invalid point selection"); + + if(NULL != hslabs) { + hsize_t *points = NULL; + size_t point_count = 0; + + point_count = ndims * num_descriptors * sizeof(hsize_t); + + if(NULL == (points = (hsize_t *)malloc(point_count))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array for points coords"); + + if(H5Sget_select_elem_pointlist(space_id, (hsize_t)0, + (hsize_t)num_descriptors, points) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "Failed to retrieve point coordinates"); + + /* populate the hyperslab */ + for(n=0 ; n<num_descriptors ; n++) { + hsize_t *cur_ptr = points; /* temp pointer into points array */ + + /* adjust the current pointer to the current point */ + cur_ptr += n*ndims; + for(i=0 ; i<ndims ; i++) { + hslabs[n].start[i] = *(cur_ptr+i); + hslabs[n].count[i] = 1; + hslabs[n].block[i] = 1; + hslabs[n].stride[i] = hslabs[n].block[i]; + } + } + + free(points); + } + break; + } + case H5S_SEL_HYPERSLABS: + { + /* if the selection is a regular hyperslab + selection, only 1 iod hyperslab object is + needed */ + if(H5Sselect_is_regular(space_id)) { + num_descriptors = 1; + + if(NULL != hslabs) { + if(H5Sget_reg_hyperslab_params(space_id, + hslabs[0].start, + hslabs[0].stride, + hslabs[0].count, + hslabs[0].block) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "Failed to retrieve hyperslab selection"); + for(i=0 ; i<ndims ; i++) { + hslabs[0].stride[i] = hslabs[0].block[i] * hslabs[0].stride[i]; + } + } + } + /* Otherwise populate the hslabs by getting every block */ + else { + if((num_descriptors = H5Sget_select_hyper_nblocks(space_id)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "invalid hyperslab selection"); + + if(NULL != hslabs) { + hsize_t *blocks = NULL; + size_t block_count = 0; + + block_count = ndims * (size_t)num_descriptors * sizeof(hsize_t) * 2; + + if(NULL == (blocks = (hsize_t *)malloc(block_count))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate array for points coords"); + + fprintf(stderr, "block count = %zu\n", block_count); + + if(H5Sget_select_hyper_blocklist(space_id, (hsize_t)0, + (hsize_t)num_descriptors, blocks) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTGET, FAIL, "Failed to retrieve point coordinates"); + + /* populate the hyperslab */ + for(n=0 ; n<num_descriptors ; n++) { + hsize_t *cur_ptr = blocks; /* temp pointer into blocks array */ + + /* adjust the current pointer to the current block */ + cur_ptr += n*ndims*2; + for(i=0 ; i<ndims ; i++) { + hslabs[n].start[i] = *(cur_ptr+i); + hslabs[n].count[i] = 1; + hslabs[n].block[i] = *(cur_ptr+ndims+i) - hslabs[n].start[i]; + hslabs[n].stride[i] = hslabs[n].block[i]; + } + } + + free(blocks); + } + } + break; + } + case H5S_SEL_ERROR: + case H5S_SEL_N: + default: + HGOTO_ERROR2(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "Invalid Selection type"); + } + + *count = num_descriptors; + + done: + FUNC_LEAVE_NOAPI(ret_value) + } + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_plist + * + * Purpose: Function to insert a creation property list in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_plist(iod_handle_t oh, iod_trans_id_t tid, hid_t plist_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event) +{ + char *key = NULL; + void *value = NULL; + iod_kv_t kv; + size_t buf_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* insert group creation properties in Metadata KV */ + key = strdup(H5VL_IOD_KEY_OBJ_CPL); + + /* determine the buffer size needed to store the encoded plist */ + if(H5Pencode(plist_id, NULL, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode plist"); + if(NULL == (value = malloc (buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate plist buffer"); + /* encode plist */ + if(H5Pencode(plist_id, value, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode plist"); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = value; + kv.value_len = (iod_size_t)buf_size; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "PLIST Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(key) { + free(key); + key = NULL; + } + if(value) { + free(value); + value = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_link_count + * + * Purpose: Function to insert the link count in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_link_count(iod_handle_t oh, iod_trans_id_t tid, uint64_t count, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event) +{ + char *key = NULL; + iod_kv_t kv; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + key = strdup(H5VL_IOD_KEY_OBJ_LINK_COUNT); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = &count; + kv.value_len = sizeof(uint64_t); + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Link Count Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(key) { + free(key); + key = NULL; + } + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_object_type + * + * Purpose: Function to insert the object type in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_object_type(iod_handle_t oh, iod_trans_id_t tid, H5I_type_t obj_type, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event) +{ + char *key = NULL; + iod_kv_t kv; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + key = strdup(H5VL_IOD_KEY_OBJ_TYPE); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = &obj_type; + kv.value_len = sizeof(int32_t); + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Object Type Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(key) { + free(key); + key = NULL; + } + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_datatype + * + * Purpose: Function to insert a datatype in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_datatype(iod_handle_t oh, iod_trans_id_t tid, hid_t type_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event) +{ + char *key = NULL; + void *value = NULL; + iod_kv_t kv; + size_t buf_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* insert group creation properties in Metadata KV */ + key = strdup(H5VL_IOD_KEY_OBJ_DATATYPE); + + /* determine the buffer size needed to store the encoded type */ + if(H5Tencode(type_id, NULL, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode type"); + if(NULL == (value = malloc (buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate type buffer"); + /* encode type */ + if(H5Tencode(type_id, value, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode type"); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = value; + kv.value_len = (iod_size_t)buf_size; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Datatype Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(key) { + free(key); + key = NULL; + } + if(value) { + free(value); + value = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_datatype_with_key + * + * Purpose: Function to insert a datatype in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_datatype_with_key(iod_handle_t oh, iod_trans_id_t tid, hid_t type_id, + const char *key, uint32_t cs_scope, iod_hint_list_t *hints, + iod_event_t *event) +{ + void *value = NULL; + iod_kv_t kv; + size_t buf_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* determine the buffer size needed to store the encoded type */ + if(H5Tencode(type_id, NULL, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode type"); + if(NULL == (value = malloc (buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate type buffer"); + /* encode type */ + if(H5Tencode(type_id, value, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode type"); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = value; + kv.value_len = (iod_size_t)buf_size; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Map Datatype Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(value) { + free(value); + value = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_dataspace + * + * Purpose: Function to insert a dataspace in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_dataspace(iod_handle_t oh, iod_trans_id_t tid, hid_t space_id, + uint32_t cs_scope, iod_hint_list_t *hints, iod_event_t *event) +{ + char *key = NULL; + void *value = NULL; + iod_kv_t kv; + size_t buf_size; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* insert group creation properties in Metadata KV */ + key = strdup(H5VL_IOD_KEY_OBJ_DATASPACE); + + /* determine the buffer size needed to store the encoded space */ + if(H5Sencode(space_id, NULL, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode space"); + if(NULL == (value = malloc (buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate space buffer"); + /* encode space */ + if(H5Sencode(space_id, value, &buf_size) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTENCODE, FAIL, "failed to encode space"); + + kv.key = (void *)key; + kv.key_len = (iod_size_t)strlen(key); + kv.value = value; + kv.value_len = (iod_size_t)buf_size; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Dataspace Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + if(key) { + free(key); + key = NULL; + } + if(value) { + free(value); + value = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_insert_new_link + * + * Purpose: Function to insert a link to another object in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_insert_new_link(iod_handle_t oh, iod_trans_id_t tid, const char *link_name, + H5L_type_t link_type, const void *link_val, uint32_t cs_scope, + iod_hint_list_t *hints, iod_event_t *event) +{ + iod_kv_t kv; + void *value = NULL; + uint8_t *val_ptr = NULL; + size_t value_len; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + switch(link_type) { + case H5L_TYPE_HARD: + { + value_len = sizeof(H5L_type_t) + sizeof(iod_obj_id_t); + value = malloc(value_len); + + val_ptr = (uint8_t *)value; + + memcpy(val_ptr, &link_type, sizeof(H5L_type_t)); + memcpy(val_ptr+sizeof(H5L_type_t), link_val, sizeof(iod_obj_id_t)); + + break; + } + case H5L_TYPE_SOFT: + { + value_len = sizeof(H5L_type_t) + strlen((const char *)link_val) + 1; + value = malloc(value_len); + + val_ptr = (uint8_t *)value; + + memcpy(val_ptr, &link_type, sizeof(H5L_type_t)); + strcpy((char *)(val_ptr+sizeof(H5L_type_t)), (const char *)link_val); + + break; + } + case H5L_TYPE_ERROR: + case H5L_TYPE_EXTERNAL: + case H5L_TYPE_MAX: + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unsupported link type"); + } + + kv.key = (void *)link_name; + kv.key_len = (iod_size_t)strlen(link_name); + kv.value = value; + kv.value_len = value_len; + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(kv.key, kv.key_len); + cs[1] = H5_checksum_crc64(kv.value, kv.value_len); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Link Type Checksums key = %016lX value = %016lX\n", cs[0], cs[1]); +#endif + + if (iod_kv_set(oh, tid, hints, &kv, cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + else { + if (iod_kv_set(oh, tid, hints, &kv, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "can't set KV pair in parent"); + } + +done: + + if(value) + free(value); + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_get_metadata + * + * Purpose: Function to retrieve a particular metadata value from an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_get_metadata(iod_handle_t oh, iod_trans_id_t tid, H5VL_iod_metadata_t md_type, + const char *key, uint32_t cs_scope, iod_event_t *event, void *ret) +{ + iod_size_t key_size = strlen(key); + iod_size_t val_size = 0; + void *value = NULL; + iod_checksum_t *iod_cs = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_cs = (iod_checksum_t *)malloc(sizeof(iod_checksum_t) * 2); + } + + switch(md_type) { + case H5VL_IOD_PLIST: + { + hid_t plist_id; + + if(iod_kv_get_value(oh, tid, key, key_size, NULL, &val_size, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if((plist_id = H5Pdecode(value)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDECODE, FAIL, "failed to decode cpl"); + + *((hid_t *)ret) = plist_id; + break; + } + case H5VL_IOD_LINK_COUNT: + val_size = sizeof(uint64_t); + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "link_count lookup failed"); + + memcpy(ret, value, val_size); + break; + case H5VL_IOD_DATATYPE: + { + hid_t type_id; + + if(iod_kv_get_value(oh, tid, key, key_size, NULL, &val_size, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if((type_id = H5Tdecode(value)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDECODE, FAIL, "failed to decode datatype"); + + *((hid_t *)ret) = type_id; + break; + } + case H5VL_IOD_DATASPACE: + { + hid_t space_id; + + if(iod_kv_get_value(oh, tid, key, key_size, NULL, &val_size, NULL, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + if((space_id = H5Sdecode(value)) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTDECODE, FAIL, "failed to decode dataspace"); + + *((hid_t *)ret) = space_id; + break; + } + case H5VL_IOD_OBJECT_TYPE: + val_size = sizeof(int32_t); + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "link_count lookup failed"); + + memcpy(ret, value, val_size); + break; + case H5VL_IOD_LINK: + { + H5VL_iod_link_t *iod_link = (H5VL_iod_link_t *)ret; + uint8_t *val_ptr; + iod_ret_t iod_ret; + + if((iod_ret = iod_kv_get_value(oh, tid, key, key_size, NULL, &val_size, NULL, event)) < 0) { + fprintf(stderr, "%d (%s).\n", iod_ret, strerror(-iod_ret)); + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + } + if(NULL == (value = malloc((size_t)val_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate value buffer"); + + if(iod_kv_get_value(oh, tid, key, key_size, value, &val_size, iod_cs, event) < 0) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "lookup failed"); + + val_ptr = (uint8_t *)value; + + iod_link->link_type = *((H5L_type_t *)val_ptr); + val_ptr += sizeof(H5L_type_t); + + switch(iod_link->link_type) { + case H5L_TYPE_HARD: + iod_link->u.iod_id = *((iod_obj_id_t *)val_ptr); + break; + case H5L_TYPE_SOFT: + iod_link->u.symbolic_name = strdup((char *)val_ptr); + break; + case H5L_TYPE_ERROR: + case H5L_TYPE_EXTERNAL: + case H5L_TYPE_MAX: + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "unsupported link type"); + } + break; + } + default: + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "invalide metadata type"); + } + + if(cs_scope & H5_CHECKSUM_IOD) { + iod_checksum_t cs[2]; + + cs[0] = H5_checksum_crc64(key, key_size); + cs[1] = H5_checksum_crc64(value, val_size); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Key CS iod = %016lX computed = %016lX\n", iod_cs[0], cs[0]); + fprintf(stderr, "Value CS iod = %016lX computed = %016lX\n", iod_cs[1], cs[1]); +#endif + if(iod_cs[0] != cs[0] && iod_cs[1] != cs[1]) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected when reading metadata from IOD"); + } + +done: + if(value) { + free(value); + value = NULL; + } + + if(iod_cs) { + free(iod_cs); + iod_cs = NULL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_adjust_buffer + * + * Checks datatypes to see if type conversion is required, if + * yes, the buffer is resized accordingly. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * August, 2013 + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL__iod_server_adjust_buffer(hid_t mem_type_id, hid_t dset_type_id, size_t nelmts, + hid_t UNUSED dxpl_id, size_t size, void **buf, + hbool_t *is_vl_data, size_t *_buf_size) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + switch(H5Tget_class(dset_type_id)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + case H5T_NO_CLASS: + case H5T_STRING: + if(H5Tis_variable_str(dset_type_id)) { + *is_vl_data = TRUE; + *_buf_size = size; + break; + } + case H5T_REFERENCE: + case H5T_NCLASSES: + case H5T_COMPOUND: + { + hsize_t buf_size = 0; + size_t mem_type_size, dset_type_size; + + *is_vl_data = FALSE; + + /* retrieve source and destination datatype sizes for data conversion */ + mem_type_size = H5Tget_size(mem_type_id); + dset_type_size = H5Tget_size(dset_type_id); + + /* adjust buffer size for data conversion */ + if(mem_type_size < dset_type_size) { + buf_size = dset_type_size * nelmts; + + if(NULL == (*buf = realloc(*buf, (size_t)buf_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "Can't adjust buffer for DT conversion"); +#if H5VL_IOD_DEBUG + fprintf(stderr, "Adjusted Buffer size for dt conversion from %zu to %lld\n", + size, buf_size); +#endif + } + else { + buf_size = mem_type_size * nelmts; + if(buf_size != size) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Incoming data size is not equal to expected size"); + } + + *_buf_size = buf_size; + + break; + } + case H5T_VLEN: + *is_vl_data = TRUE; + *_buf_size = size; + break; + default: + HGOTO_ERROR2(H5E_ARGS, H5E_CANTINIT, FAIL, "unsupported datatype"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_server_adjust_buffer */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_verify_scratch_pad + * + * Purpose: Function to insert the link count in an + * IOD KV object. + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_iod_verify_scratch_pad(scratch_pad *sp, iod_checksum_t iod_cs) +{ + iod_checksum_t computed_cs = 0; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + computed_cs = H5_checksum_crc64(sp, sizeof(scratch_pad)); + + if(computed_cs != iod_cs) { + fprintf(stderr, "Scratch pad integrity check failed. IOD cs = %"PRIu64", Computed cs = %"PRIu64"\n", + iod_cs, computed_cs); + ret_value = FAIL; + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_iod_verify_scratch_pad() */ + +herr_t +H5VL_iod_verify_kv_pair(void *key, iod_size_t key_size, void *value, iod_size_t val_size, + iod_checksum_t *iod_cs) +{ + iod_checksum_t cs[2]; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + cs[0] = H5_checksum_crc64(key, key_size); + cs[1] = H5_checksum_crc64(value, val_size); + +#if H5VL_IOD_DEBUG + fprintf(stderr, "Key CS iod = %016lX computed = %016lX\n", iod_cs[0], cs[0]); + fprintf(stderr, "Value CS iod = %016lX computed = %016lX\n", iod_cs[1], cs[1]); +#endif + + if(iod_cs[0] != cs[0] && iod_cs[1] != cs[1]) + HGOTO_ERROR2(H5E_SYM, H5E_CANTINIT, FAIL, "Corruption detected in IOD KV pair"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5VL_iod_verify_kv_pair */ + +#if 0 +herr_t +H5VL_iod_map_type_convert(hid_t src_id, hid_t dst_id, void *buf, size_t buf_size) +{ + H5T_class_t class; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + class = H5Tget_class(src_id); + if(H5T_VLEN == class || (H5T_STRING == class && H5Tis_variable_str(src_id))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Can't convert VL or string types"); + + class = H5Tget_class(dset_id); + if(H5T_VLEN == class || (H5T_STRING == class && H5Tis_variable_str(dst_id))) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Can't convert VL or string types"); + + /* Check (and do) Type conversion on the Key */ + src_size = H5Tget_size(src_id); + dst_size = H5Tget_size(dst_id); + + /* adjust buffer size for datatype conversion */ + if(src_size < dst_size) { + new_size = dst_size; + if(NULL == (*buf = realloc(*buf, new_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "Can't adjust buffer for DT conversion"); + } + else { + new_size = src_size; + } + + if(NULL == (key_buf = malloc((size_t)key_size))) + HGOTO_ERROR2(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate buffer"); + memcpy(key_buf, key.buf, src_size); + + if(H5Tconvert(src_id, dst_id, 1, key_buf, NULL, dxpl_id) < 0) + HGOTO_ERROR2(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} +#endif +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLiod_view.c b/src/H5VLiod_view.c new file mode 100644 index 0000000..cf91ee0 --- /dev/null +++ b/src/H5VLiod_view.c @@ -0,0 +1,409 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Mohamad Chaarawi <chaarawi@hdfgroup.gov> + * October, 2013 + * + * Purpose: Routines to support Query/View objects. + */ + + +#include "H5VLiod_server.h" + +#ifdef H5_HAVE_EFF + +#if 0 + +static herr_t H5VL__iod_server_construct_view(iod_handle_t coh, iod_obj_id_t loc_id, + iod_trans_id_t rtid, hid_t query, + size_t *num_tokens, H5VL_token_t *tokens); +static herr_t H5VL__iod_query_selection(iod_handle_t coh, iod_obj_id_t obj_id, + iod_trans_id_t rtid, hid_t query, + size_t *num_tokens, H5VL_token_t *tokens); + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_get_layout_cb + * + * Purpose: Retrieves layout of object + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_get_layout_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + get_layout_in_t *input = (get_layout_in_t *)op_data->input; + get_layout_out_t output;; + iod_handle_t coh = input->coh; /* the container handle */ + iod_obj_id_t obj_id = input->obj_id; /* The ID of the object */ + iod_handle_t obj_oh = input->obj_oh; /* object handle */ + H5I_type_t loc_type = input->loc_type; /* type of the location where query needs to be applied */ + iod_trans_id_t rtid = input->rcxt_num; + iod_layout_t layout; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + if(obj_oh.cookie == IOD_OH_UNDEFINED) { + if (iod_obj_open_read(coh, obj_id, NULL /*hints*/, &obj_oh, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + opened_locally = TRUE; + } + + if(iod_obj_get_layout(obj_oh, rtid, &layout, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object layout"); + + output.ret = ret_value; + output.layout = layout + + HG_Handler_start_output(op_data->hg_handle, output); + +done: + + if(ret_value < 0) + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (view_create_in_t *)H5MM_xfree(input); + op_data = (op_data_t *)H5MM_xfree(op_data); + + /* close the dataset if we opened it in this routine */ + if(opened_locally) { + if(iod_obj_close(obj_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + } + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_get_layout_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_view_create_cb + * + * Purpose: Creates a view from a provided query. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_view_create_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + view_create_in_t *input = (view_create_in_t *)op_data->input; + view_create_out_t *output = NULL; + iod_handle_t coh = input->coh; /* the container handle */ + iod_obj_id_t loc_id = input->loc_id; /* The ID of the object */ + H5I_type_t loc_type = input->loc_type; /* type of the location where query needs to be applied */ + hid_t query = input->query; /* query object to apply */ + iod_trans_id_t rtid = input->rcxt_num; + uint32_t cs_scope = input->cs_scope; + int token_count; + int num_tokens = 0; + H5VL_token_t *tokens = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* If the location type is a raw data object, then only 1 token is needed */ + if(loc_type == H5I_MAP || loc_type == H5I_DATASET || loc_type == H5I_DATATYPE) + token_count = 1; + /* Otherwise the location type is a group or the root group, so we + set the initial number of tokens to the upperbound total number + of objects in the container. */ + else if(loc_type == H5I_GROUP || loc_type == H5I_FILE) { + if(iod_container_list_obj(coh, rtid, IOD_OBJ_ANY, 0, &token_count, + NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve total number of objects in container"); + } + + if(NULL == (tokens = (H5VL_token_t *)malloc(sizeof(H5VL_token_t) * token_count))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate token structs"); + + if(H5VL__iod_server_construct_view(coh, loc_id, rtid, query, &num_tokens, tokens) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "failed to construct view"); + + if(NULL == (output = (view_create_out_t *)H5MM_malloc(sizeof(view_create_out_t)))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, HG_FAIL, "can't allocate output struct for view create"); + + output->ret = ret_value; + output->num_tokens = num_tokens; + output->tokens = tokens; + op_data->output = output; + + HG_Handler_start_output(op_data->hg_handle, output); + +done: + + if(ret_value < 0) + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (view_create_in_t *)H5MM_xfree(input); + output = (view_create_out_t *)H5MM_xfree(output); + op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_view_create_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_iod_server_get_view_tokens_cb + * + * Purpose: Creates a view from a provided query. + * + * Return: Success: SUCCEED + * Failure: Negative + * + * Programmer: Mohamad Chaarawi + * September, 2013 + * + *------------------------------------------------------------------------- + */ +void +H5VL_iod_server_get_view_tokens_cb(AXE_engine_t UNUSED axe_engine, + size_t UNUSED num_n_parents, AXE_task_t UNUSED n_parents[], + size_t UNUSED num_s_parents, AXE_task_t UNUSED s_parents[], + void *_op_data) +{ + op_data_t *op_data = (op_data_t *)_op_data; + view_get_tokens_in_t *input = (view_get_tokens_in_t *)op_data->input; + AXE_task_t view_create_id = input->view_create_id; + hg_bulk_t bulk_handle = input->bulk_handle; /* bulk handle for data */ + hg_bulk_block_t bulk_block_handle; /* HG block handle */ + hg_bulk_request_t bulk_request; /* HG request */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + + /* Create a new block handle to write the data */ + HG_Bulk_block_handle_create(buf, size, HG_BULK_READ_ONLY, &bulk_block_handle); + + /* Write bulk data here and wait for the data to be there */ + if(HG_SUCCESS != HG_Bulk_write_all(dest, bulk_handle, bulk_block_handle, &bulk_request)) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + /* wait for it to complete */ + if(HG_SUCCESS != HG_Bulk_wait(bulk_request, HG_MAX_IDLE_TIME, HG_STATUS_IGNORE)) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't read from array object"); + + /* free block handle */ + if(HG_SUCCESS != HG_Bulk_block_handle_free(bulk_block_handle)) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't free bds block handle"); + + HG_Handler_start_output(op_data->hg_handle, output); + +done: + + if(ret_value < 0) + HG_Handler_start_output(op_data->hg_handle, &ret_value); + + input = (object_op_in_t *)H5MM_xfree(input); + //op_data = (op_data_t *)H5MM_xfree(op_data); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VL_iod_server_get_view_tokens_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_server_construct_view + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_server_construct_view(iod_handle_t coh, iod_obj_id_t loc_id, iod_trans_id_t rtid, + hid_t query, int *num_tokens, H5VL_token_t *tokens) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* get tokens for attributes that satisfy the query on the current + location object */ + if(query_type & H5Q_TYPE_ATTR_NAME) { + if(H5VL_iod_query_attribute(coh, rtid, loc_id, query, num_tokens, tokens) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to query dataset for selection"); + } + + if(loc_id & IOD_OBJ_TYPE_ARRAY) { + /* get token for dataset and space selection for data + elements that satisfy the query */ + if(H5VL_iod_query_selection(coh, rtid, loc_id, query, num_tokens, tokens) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to query dataset for selection"); + } + + else if(loc_id & IOD_OBJ_TYPE_KV) { + /* get tokens for links that satisfy the query on the current + location object. This will recursively call + H5VL_iod_server_construct_view() on every object ID that + has a link from the current location object. */ + if(query_type & H5Q_TYPE_LINK_NAME) { + if(H5VL_iod_query_link(coh, rtid, loc_id, query, num_tokens, tokens) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to query dataset for selection"); + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_server_construct_view() */ + + +/*------------------------------------------------------------------------- + * Function: H5VL__iod_query_selection + * + * Purpose: + * + * Return: Success: SUCCEED + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +static herr_t +H5VL__iod_query_selection(iod_handle_t coh, iod_obj_id_t obj_id, + iod_trans_id_t rtid, hid_t query, + int *num_tokens, H5VL_token_t *tokens) +{ + iod_handle_t obj_oh = IOD_OH_UNDEFINED; + hid_t layout_space = -1, queried_space = -1; + size_t nelmts; + size_t elmt_size; + size_t buf_size=0, ds_size=0, dt_size=0; + void *buf = NULL; + scratch_pad sp; + H5O_type_t otype; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT + + /* open the array object */ + if (iod_obj_open_read(coh, obj_id, NULL /*hints*/, &obj_oh, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't open current group"); + + /* get scratch pad of the dataset */ + if(iod_obj_get_scratch(obj_oh, rtid, &sp, NULL, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't get scratch pad for object"); + + /* open the metadata scratch pad */ + if (iod_obj_open_write(coh, sp[0], NULL /*hints*/, &mdkv_oh, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't open scratch pad"); + + /* retrieve the datatype of array object */ + if(H5VL_iod_get_metadata(mdkv_oh, rtid, H5VL_IOD_DATATYPE, H5VL_IOD_KEY_OBJ_DATATYPE, + NULL, NULL, type_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "failed to retrieve datatype"); + + /* close the metadata scratch pad */ + if(iod_obj_close(mdkv_oh, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close object"); + + /* get layout dataspace from the query to read from */ + layout_space = H5Qget_space(query); + + nelmts = (size_t)H5Sget_select_npoints(layout_space); + elmt_size = H5Tget_size(type_id); + buf_size = nelmts * elmt_size; + + /* allocate buffer to hold data */ + if(NULL == (buf = malloc(buf_size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate read buffer"); + + /* read the data selection from IOD. */ + /* MSC - will need to do it in pieces, not it one shot. */ + if(H5VL__iod_server_final_io(coh, obj_oh, layout_space, type_id, + FALSE, buf, buf_size, 0, 0, rtid) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREAD, FAIL, "can't read from array object"); + + if(H5Qapply(query, buf, type_id, layout_space, H5P_DEFAULT, &queried_space) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't apply query on dataspace"); + + if(H5Sencode(queried_space, NULL, &ds_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace"); + if(H5Tencode(type_id, NULL, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype"); + + token_size += sizeof(iod_obj_id_t)*3 + sizeof(H5O_type_t) + + dt_size + ds_size + sizeof(size_t)*2; + + u = *num_tokens; + tokens[u].token_size = token_size; + + if(NULL == (tokens[u].token = malloc(token_size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate token buffer"); + + buf_ptr = (uint8_t *)tokens[u].token; + + HDmemcpy(buf_ptr, &obj_id, sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(buf_ptr, &sp[0], sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + HDmemcpy(buf_ptr, &sp[1], sizeof(iod_obj_id_t)); + buf_ptr += sizeof(iod_obj_id_t); + otype = H5O_TYPE_DATASET; + HDmemcpy(buf_ptr, &otype, sizeof(H5O_type_t)); + buf_ptr += sizeof(H5O_type_t); + + HDmemcpy(buf_ptr, &dt_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5Tencode(type_id, buf_ptr, &dt_size) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype"); + buf_ptr += dt_size; + + HDmemcpy(buf_ptr, &ds_size, sizeof(size_t)); + buf_ptr += sizeof(size_t); + if(H5Sencode(queried_space, buf_ptr, &ds_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace"); + buf_ptr += space_size; + + *num_tokens ++; + +done: + + if(layout_space) + H5Sclose(layout_space); + if(queried_space) + H5Sclose(queried_space); + + if(buf) + free(buf); + + if(obj_oh != IOD_OH_UNDEFINED && iod_obj_close(obj_oh, NULL, NULL) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't close Array object"); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL__iod_query_selection() */ +#endif + +#endif /* H5_HAVE_EFF */ diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h index 33f3f5a..143cbf9 100644 --- a/src/H5VLprivate.h +++ b/src/H5VLprivate.h @@ -29,8 +29,6 @@ /****************************/ /* Library Private Typedefs */ /****************************/ -#define H5_REQUEST_NULL NULL -#define H5_EVENT_STACK_NULL -1 /*****************************/ /* Library Private Variables */ diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index 1171811..8a2ee06 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -23,20 +23,13 @@ #include "stdarg.h" #include "H5public.h" +#include "H5ESpublic.h" #include "H5Apublic.h" /* Attributes */ #include "H5Fpublic.h" #include "H5Lpublic.h" #include "H5Opublic.h" #include "H5Rpublic.h" -/* Asynchronous operation status */ -typedef enum H5ES_status_t { - H5ES_STATUS_IN_PROGRESS, /* Operation has not yet completed */ - H5ES_STATUS_SUCCEED, /* Operation has completed, successfully */ - H5ES_STATUS_FAIL, /* Operation has completed, but failed */ - H5ES_STATUS_CANCEL /* Operation has not completed and has been cancelled */ -} H5ES_status_t; - /* Dataset creation property names */ #define H5VL_DSET_TYPE_ID "dataset_type_id" #define H5VL_DSET_SPACE_ID "dataset_space_id" @@ -188,6 +181,7 @@ struct H5VL_loc_by_idx { struct H5VL_loc_by_addr { haddr_t addr; + H5O_type_t obj_type; }; struct H5VL_loc_by_ref { @@ -301,7 +295,7 @@ typedef struct H5VL_object_class_t { herr_t (*close) (void *obj, H5VL_loc_params_t loc_params, hid_t dxpl_id, void **req); } H5VL_object_class_t; -/* H5AO routines */ +/* async routines */ typedef struct H5VL_async_class_t { herr_t (*cancel)(void **, H5ES_status_t *); herr_t (*test) (void **, H5ES_status_t *); @@ -311,6 +305,7 @@ typedef struct H5VL_async_class_t { /* enum value to identify the class of a VOL plugin (mostly for comparison purposes) */ typedef enum H5VL_class_value_t { NATIVE = 0, /* This should be first */ + IOD = 1, MAX_VOL_LIB_VALUE = 128 /* This should be last */ } H5VL_class_value_t; @@ -343,6 +338,8 @@ struct H5VL_t { const char *container_name; /* name of the underlying storage container */ unsigned long feature_flags; /* VOL Driver feature Flags */ int nrefs; /* number of references by objects using this struct */ + hid_t close_estack_id; + hid_t close_dxpl_id; }; #ifdef __cplusplus diff --git a/src/H5checksum.c b/src/H5checksum.c index 48e4ce5..727bdf7 100644 --- a/src/H5checksum.c +++ b/src/H5checksum.c @@ -34,7 +34,6 @@ /***********/ #include "H5private.h" /* Generic Functions */ - /****************/ /* Local Macros */ /****************/ @@ -79,7 +78,6 @@ static uint32_t H5_crc_table[256]; /* Flag: has the table been computed? */ static hbool_t H5_crc_table_computed = FALSE; - /*------------------------------------------------------------------------- * Function: H5_checksum_fletcher32 @@ -432,6 +430,177 @@ done: FUNC_LEAVE_NOAPI(c) } /* end H5_checksum_lookup3() */ +uint32_t +H5_checksum_lookup4(const void *key, size_t length, H5_checksum_seed_t *cs) +{ + const uint8_t *k = (const uint8_t *)key; + uint32_t position = 0; + uint32_t a, b, c; /* internal state */ + int pos = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(key); + HDassert(length > 0); + + /* Set up the internal state */ + if(cs) { + if(!cs->a && !cs->b && !cs->c) { + a = b = c = 0xdeadbeef;// + ((uint32_t)cs->total_length); + /* Compute new State */ + cs->state = 12 - (length % 12); + } + else { + a = cs->a; + b = cs->b; + c = cs->c; + + /* determine position to start up on */ + if(cs->state) { + position = 12 - cs->state + 1; + } + + /* Compute new State */ + cs->state = cs->state - (length % 12); + if(cs->state < 0) { + H5_lookup3_mix(a, b, c); + cs->state = 12 + cs->state; + } + + /* Move towards mod 12 */ + switch(position) + { + case 0 : + break; + case 1 : + a+=k[pos++]; + length --; + if(0 == length) + break; + case 2 : + a+=((uint32_t)k[pos++])<<8; + length --; + if(0 == length) + break; + case 3 : + a+=((uint32_t)k[pos++])<<16; + length --; + if(0 == length) + break; + case 4 : + a+=((uint32_t)k[pos++])<<24; + length --; + if(0 == length) + break; + case 5 : + b+=k[pos++]; + length --; + if(0 == length) + break; + case 6 : + b+=((uint32_t)k[pos++])<<8; + length --; + if(0 == length) + break; + case 7 : + b+=((uint32_t)k[pos++])<<16; + length --; + if(0 == length) + break; + case 8 : + b+=((uint32_t)k[pos++])<<24; + length --; + if(0 == length) + break; + case 9 : + c+=k[pos++]; + length --; + if(0 == length) + break; + case 10: + c+=((uint32_t)k[pos++])<<8; + length --; + if(0 == length) + break; + case 11: + c+=((uint32_t)k[pos++])<<16; + length --; + if(0 == length) + break; + case 12: + c+=((uint32_t)k[pos++])<<24; + length --; + if(0 == length) + break; + H5_lookup3_mix(a, b, c); + break; + } + } + /* capture internal state if we are done at this stage */ + if(0 == length) { + cs->a = a; + cs->b = b; + cs->c = c; + H5_lookup3_final(a, b, c); + goto done; + } + } + else + a = b = c = 0xdeadbeef; //+ ((uint32_t)length); + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0+pos]; + a += ((uint32_t)k[1+pos])<<8; + a += ((uint32_t)k[2+pos])<<16; + a += ((uint32_t)k[3+pos])<<24; + b += k[4+pos]; + b += ((uint32_t)k[5+pos])<<8; + b += ((uint32_t)k[6+pos])<<16; + b += ((uint32_t)k[7+pos])<<24; + c += k[8+pos]; + c += ((uint32_t)k[9+pos])<<8; + c += ((uint32_t)k[10+pos])<<16; + c += ((uint32_t)k[11+pos])<<24; + H5_lookup3_mix(a, b, c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11+pos])<<24; + case 11: c+=((uint32_t)k[10+pos])<<16; + case 10: c+=((uint32_t)k[9+pos])<<8; + case 9 : c+=k[8+pos]; + case 8 : b+=((uint32_t)k[7+pos])<<24; + case 7 : b+=((uint32_t)k[6+pos])<<16; + case 6 : b+=((uint32_t)k[5+pos])<<8; + case 5 : b+=k[4+pos]; + case 4 : a+=((uint32_t)k[3+pos])<<24; + case 3 : a+=((uint32_t)k[2+pos])<<16; + case 2 : a+=((uint32_t)k[1+pos])<<8; + case 1 : a+=k[pos]; + break; + case 0 : goto done; + } + + /* capture internal state */ + if(cs) { + cs->a = a; + cs->b = b; + cs->c = c; + } + + H5_lookup3_final(a, b, c); + +done: + FUNC_LEAVE_NOAPI(c) +} /* end H5_checksum_lookup3() */ + /*------------------------------------------------------------------------- * Function: H5_checksum_metadata @@ -493,4 +662,3 @@ H5_hash_string(const char *str) FUNC_LEAVE_NOAPI(hash) } /* end H5_hash_string() */ - diff --git a/src/H5config.h.in b/src/H5config.h.in index 02bafd8..d99c709 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -61,6 +61,9 @@ /* Define if the __attribute__(()) extension is present */ #undef HAVE_ATTRIBUTE +/* Define to 1 if you have the <axe.h> header file. */ +#undef HAVE_AXE_H + /* Define to 1 if you have the `BSDgettimeofday' function. */ #undef HAVE_BSDGETTIMEOFDAY @@ -77,6 +80,12 @@ /* Define if the function stack tracing code is to be compiled in */ #undef HAVE_CODESTACK +/* Define to 1 if you have the <daos_api.h> header file. */ +#undef HAVE_DAOS_API_H + +/* Define to 1 if you have the <daos_types.h> header file. */ +#undef HAVE_DAOS_TYPES_H + /* Define if Darwin or Mac OS X */ #undef HAVE_DARWIN @@ -99,6 +108,9 @@ /* Define to 1 if you have the <dmalloc.h> header file. */ #undef HAVE_DMALLOC_H +/* Define if we have EFF VOL plugins support */ +#undef HAVE_EFF + /* Define if library information should be embedded in the executables */ #undef HAVE_EMBEDDED_LIBINFO @@ -190,21 +202,39 @@ /* Define to 1 if you have the `ioctl' function. */ #undef HAVE_IOCTL +/* Define to 1 if you have the <iod_api.h> header file. */ +#undef HAVE_IOD_API_H + +/* Define to 1 if you have the <iod_types.h> header file. */ +#undef HAVE_IOD_TYPES_H + /* Define to 1 if you have the <io.h> header file. */ #undef HAVE_IO_H +/* Define to 1 if you have the `axe' library (-laxe). */ +#undef HAVE_LIBAXE + +/* Define to 1 if you have the `daos_posix' library (-ldaos_posix). */ +#undef HAVE_LIBDAOS_POSIX + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `dmalloc' library (-ldmalloc). */ #undef HAVE_LIBDMALLOC +/* Define to 1 if you have the `iod' library (-liod). */ +#undef HAVE_LIBIOD + /* Define to 1 if you have the `lmpe' library (-llmpe). */ #undef HAVE_LIBLMPE /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the `mdhim' library (-lmdhim). */ +#undef HAVE_LIBMDHIM + /* Define to 1 if you have the `mpe' library (-lmpe). */ #undef HAVE_LIBMPE @@ -220,6 +250,12 @@ /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL +/* Define to 1 if you have the `pbl' library (-lpbl). */ +#undef HAVE_LIBPBL + +/* Define to 1 if you have the `plfs' library (-lplfs). */ +#undef HAVE_LIBPLFS + /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD @@ -265,12 +301,27 @@ /* Define if `MPI_Info_c2f' and `MPI_Info_f2c' exists */ #undef HAVE_MPI_MULTI_LANG_Info +/* Define to 1 if you have the <numpy/ndarrayobject.h> header file. */ +#undef HAVE_NUMPY_NDARRAYOBJECT_H + /* Define if we have parallel support */ #undef HAVE_PARALLEL +/* Define to 1 if you have the <plfs.h> header file. */ +#undef HAVE_PLFS_H + /* Define to 1 if you have the <pthread.h> header file. */ #undef HAVE_PTHREAD_H +/* Define if we have Python support */ +#undef HAVE_PYTHON + +/* Define to 1 if you have the <Python.h> header file. */ +#undef HAVE_PYTHON_H + +/* Define if we have Python NumPy support */ +#undef HAVE_PYTHON_NUMPY + /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM diff --git a/src/H5err.txt b/src/H5err.txt index c3908e4..f126066 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -69,6 +69,7 @@ MAJOR, H5E_EFL, External file list MAJOR, H5E_REFERENCE, References MAJOR, H5E_VFL, Virtual File Layer MAJOR, H5E_VOL, Virtual Object Layer +MAJOR, H5E_QUERY, Query MAJOR, H5E_TST, Ternary Search Trees MAJOR, H5E_RS, Reference Counted Strings MAJOR, H5E_ERROR, Error API diff --git a/src/H5private.h b/src/H5private.h index 859f518..0e3df0d 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -2391,13 +2391,18 @@ H5_DLL int H5A_term_interface(void); H5_DLL int H5AC_term_interface(void); H5_DLL int H5D_term_interface(void); H5_DLL int H5E_term_interface(void); +H5_DLL int H5ES_term_interface(void); +H5_DLL int H5RC_term_interface(void); +H5_DLL int H5TR_term_interface(void); H5_DLL int H5F_term_interface(void); H5_DLL int H5FS_term_interface(void); H5_DLL int H5G_term_interface(void); H5_DLL int H5I_term_interface(void); H5_DLL int H5L_term_interface(void); +H5_DLL int H5M_term_interface(void); H5_DLL int H5P_term_interface(void); H5_DLL int H5PL_term_interface(void); +H5_DLL int H5Q_term_interface(void); H5_DLL int H5R_term_interface(void); H5_DLL int H5S_term_interface(void); H5_DLL int H5T_term_interface(void); @@ -2407,6 +2412,7 @@ H5_DLL int H5Z_term_interface(void); H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len); H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len); H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval); +H5_DLL uint32_t H5_checksum_lookup4(const void *data, size_t len, H5_checksum_seed_t *cs); H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval); H5_DLL uint32_t H5_hash_string(const char *str); diff --git a/src/H5public.h b/src/H5public.h index 5bfc909..9874fb1 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -94,6 +94,10 @@ extern "C" { ((H5_VERS_MAJOR==Maj) && (H5_VERS_MINOR<Min)) || \ (H5_VERS_MAJOR<Maj)) +#ifdef H5_HAVE_EFF +typedef uint64_t hrpl_t; +#endif /* H5_HAVE_EFF */ + /* * Status return values. Failed integer functions in HDF5 result almost * always in a negative value (unsigned failing functions sometimes return @@ -106,7 +110,6 @@ extern "C" { */ typedef int herr_t; - /* * Boolean type. Successful return values are zero (false) or positive * (true). The typical true value is 1 but don't bet on it. Boolean @@ -301,6 +304,15 @@ typedef struct H5_ih_info_t { hsize_t heap_size; } H5_ih_info_t; +/* Internal Checksum state */ +typedef struct H5_checksum_seed_t { + uint32_t a; + uint32_t b; + uint32_t c; + int32_t state; + size_t total_length; +} H5_checksum_seed_t; + /* Functions in H5.c */ H5_DLL herr_t H5open(void); H5_DLL herr_t H5close(void); @@ -313,6 +325,7 @@ H5_DLL herr_t H5get_libversion(unsigned *majnum, unsigned *minnum, unsigned *relnum); H5_DLL herr_t H5check_version(unsigned majnum, unsigned minnum, unsigned relnum); +H5_DLL uint32_t H5checksum(const void *key, size_t length, H5_checksum_seed_t *cs); #ifdef __cplusplus } diff --git a/src/H5trace.c b/src/H5trace.c index 6dcabd0..5f18869 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -40,6 +40,9 @@ #include "H5Ipkg.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ +#include "H5Qpublic.h" /* Queries */ +#include "H5RCpublic.h" /* Read Contexts */ + #ifdef H5_HAVE_PARALLEL /* datatypes of predefined drivers needed by H5_trace() */ #include "H5FDmpio.h" @@ -1159,6 +1162,26 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "%ld (group)", (long)obj); break; + case H5I_MAP: + fprintf(out, "%ld (map)", (long)obj); + break; + + case H5I_RC: + fprintf(out, "%ld (read context)", (long)obj); + break; + + case H5I_TR: + fprintf(out, "%ld (transaction)", (long)obj); + break; + + case H5I_QUERY: + fprintf(out, "%ld (query)", (long)obj); + break; + + case H5I_VIEW: + fprintf(out, "%ld (view)", (long)obj); + break; + case H5I_DATATYPE: if(obj == H5T_NATIVE_SCHAR_g) fprintf(out, "H5T_NATIVE_SCHAR"); @@ -1285,6 +1308,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "%ld (object driver)", (long)obj); break; + case H5I_ES: + fprintf(out, "%ld (event queue)", (long)obj); + break; + case H5I_GENPROP_CLS: fprintf(out, "%ld (genprop class)", (long)obj); break; @@ -1415,6 +1442,30 @@ H5_trace(const double *returning, const char *func, const char *type, ...) } /* end else */ break; + case 'l': + if(ptr) { + if(vp) { + fprintf(out, "0x%lx", (unsigned long)vp); + if(asize_idx >= 0 && asize[asize_idx] >= 0) { + int *p = (int*)vp; + + fprintf(out, " {"); + for(i = 0; i < asize[asize_idx]; i++) + fprintf(out, "%s%d", (i ? ", " : ""), p[i]); + fprintf(out, "}"); + } /* end if */ + } /* end if */ + else + fprintf(out, "NULL"); + } /* end if */ + else { + uint64_t is = va_arg(ap, uint64_t); + + fprintf (out, "%llu", is); + asize[argno] = is; + } /* end else */ + break; + case 't': if(ptr) { if(vp) @@ -1442,6 +1493,26 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "H5I_GROUP"); break; + case H5I_MAP: + fprintf(out, "H5I_MAP"); + break; + + case H5I_RC: + fprintf(out, "H5I_RC"); + break; + + case H5I_TR: + fprintf(out, "H5I_TR"); + break; + + case H5I_QUERY: + fprintf(out, "H5I_QUERY"); + break; + + case H5I_VIEW: + fprintf(out, "H5I_VIEW"); + break; + case H5I_DATATYPE: fprintf(out, "H5I_DATATYPE"); break; @@ -1470,6 +1541,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "H5I_VOL"); break; + case H5I_ES: + fprintf(out, "H5I_ES"); + break; + case H5I_GENPROP_CLS: fprintf(out, "H5I_GENPROP_CLS"); break; @@ -1705,6 +1780,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "H5O_TYPE_GROUP"); break; + case H5O_TYPE_MAP: + fprintf(out, "H5O_TYPE_MAP"); + break; + case H5O_TYPE_DATASET: fprintf(out, "H5O_TYPE_DATASET"); break; @@ -1768,6 +1847,92 @@ H5_trace(const double *returning, const char *func, const char *type, ...) } /* end else */ break; + case 'Q': + switch(type[1]) { + case 't': + if(ptr) { + if(vp) + fprintf(out, "0x%lx", (unsigned long)vp); + else + fprintf(out, "NULL"); + } /* end if */ + else { + H5Q_type_t qtype = (H5Q_type_t)va_arg(ap, int); + + switch(qtype) { + case H5Q_TYPE_DATA_ELEM: + fprintf(out, "H5Q_TYPE_DATA_ELEM"); + break; + case H5Q_TYPE_ATTR_NAME: + fprintf(out, "H5Q_TYPE_ATTR_NAME"); + break; + case H5Q_TYPE_LINK_NAME: + fprintf(out, "H5Q_TYPE_LINK_NAME"); + break; + default: + fprintf(out, "BADTYPE(%d)", qtype); + break; + } /* end switch */ + } /* end else */ + break; + case 'm': + if(ptr) { + if(vp) + fprintf(out, "0x%lx", (unsigned long)vp); + else + fprintf(out, "NULL"); + } /* end if */ + else { + H5Q_match_op_t qmatch = (H5Q_match_op_t)va_arg(ap, int); + + switch(qmatch) { + case H5Q_MATCH_EQUAL: + fprintf(out, "H5Q_MATCH_EQUAL"); + break; + case H5Q_MATCH_NOT_EQUAL: + fprintf(out, "H5Q_MATCH_NOT_EQUAL"); + break; + case H5Q_MATCH_LESS_THAN: + fprintf(out, "H5Q_MATCH_LESS_THAN"); + break; + case H5Q_MATCH_GREATER_THAN: + fprintf(out, "H5Q_MATCH_GREATER_THAN"); + break; + default: + fprintf(out, "BADTYPE(%d)", qmatch); + break; + } /* end switch */ + } /* end else */ + break; + case 'c': + if(ptr) { + if(vp) + fprintf(out, "0x%lx", (unsigned long)vp); + else + fprintf(out, "NULL"); + } /* end if */ + else { + H5Q_combine_op_t qcomb = (H5Q_combine_op_t)va_arg(ap, int); + + switch(qcomb) { + case H5Q_COMBINE_AND: + fprintf(out, "H5Q_COMBINE_AND"); + break; + case H5Q_COMBINE_OR: + fprintf(out, "H5Q_COMBINE_OR"); + break; + default: + fprintf(out, "BADTYPE(%d)", qcomb); + break; + } /* end switch */ + } /* end else */ + break; + default: + fprintf(out, "BADTYPE(S%c)", type[1]); + goto error; + } /* end switch */ + break; + case 'R': switch(type[1]) { case 't': @@ -1803,7 +1968,61 @@ H5_trace(const double *returning, const char *func, const char *type, ...) } /* end switch */ } /* end else */ break; +#ifdef H5_HAVE_EFF + case 'c': + if(ptr) { + if(vp) + fprintf(out, "0x%lx", (unsigned long)vp); + else + fprintf(out, "NULL"); + } /* end if */ + else { + H5RC_request_t request = (H5RC_request_t)va_arg(ap, int); + + switch(request) { + case H5RC_EXACT: + fprintf(out, "H5RC_EXACT"); + break; + case H5RC_PREV: + fprintf(out, "H5RC_PREV"); + break; + case H5RC_NEXT: + fprintf(out, "H5RC_NEXT"); + break; + case H5RC_LAST: + fprintf(out, "H5RC_LAST"); + break; + default: + fprintf(out, "BADTYPE(%ld)", (long)request); + break; + } /* end switch */ + } /* end else */ + break; + + case 'p': + if(ptr) { + if(vp) { + fprintf(out, "0x%lx", (unsigned long)vp); + if(asize_idx >= 0 && asize[asize_idx] >= 0) { + int *p = (int*)vp; + + fprintf(out, " {"); + for(i = 0; i < asize[asize_idx]; i++) + fprintf(out, "%s%d", (i ? ", " : ""), p[i]); + fprintf(out, "}"); + } /* end if */ + } /* end if */ + else + fprintf(out, "NULL"); + } /* end if */ + else { + hrpl_t replica_id = va_arg(ap, hrpl_t); + fprintf (out, "%"PRIx64"", replica_id); + asize[argno] = replica_id; + } /* end else */ + break; +#endif default: fprintf(out, "BADTYPE(S%c)", type[1]); goto error; diff --git a/src/Makefile.am b/src/Makefile.am index 7e843a0..8511b96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,9 +59,13 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \ H5FAstat.c H5FAtest.c \ H5VL.c H5VLint.c H5VLnative.c \ + H5VLiod.c H5VLiod_common.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ + H5VLiod_file.c H5VLiod_group.c H5VLiod_map.c H5VLiod_dset.c H5VLiod_dtype.c \ + H5VLiod_attr.c H5VLiod_link.c H5VLiod_obj.c H5VLiod_trans.c H5VLiod_analysis.c \ H5FD.c H5FDcore.c \ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \ + H5FF.c H5ES.c H5RC.c H5TR.c H5M.c H5AS.c\ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \ H5G.c H5Gbtree2.c H5Gcache.c \ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ @@ -88,9 +92,10 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \ H5Pdeprec.c H5Pdxpl.c H5Pencdec.c \ H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ - H5Pgcpl.c H5Pint.c \ + H5Pgcpl.c H5Pmcpl.c H5Pmapl.c H5Pint.c H5Prcapl.c H5Ptrspl.c H5Ptrfpl.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \ H5PL.c \ + H5Q.c \ H5R.c H5Rdeprec.c \ H5UC.c \ H5RS.c \ @@ -117,10 +122,12 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5Epubgen.h H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDdirect.h \ H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h \ - H5VLpublic.h H5VLnative.h \ + H5VLpublic.h H5VLnative.h H5VLiod.h \ + H5FFpublic.h H5ESpublic.h H5RCpublic.h H5TRpublic.h H5Mpublic.h H5ASpublic.h\ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ H5MMpublic.h H5Opublic.h H5Ppublic.h \ H5PLextern.h \ + H5Qpublic.h \ H5Rpublic.h H5Spublic.h \ H5Tpublic.h H5Zpublic.h diff --git a/src/Makefile.in b/src/Makefile.in index 8408524..595b0dd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -81,7 +81,9 @@ noinst_PROGRAMS = H5detect$(EXEEXT) H5make_libsettings$(EXEEXT) TESTS = subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4/ax_python.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/bin/mkinstalldirs @@ -135,10 +137,16 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Fquery.lo H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo \ H5Ftest.lo H5FA.lo H5FAcache.lo H5FAdbg.lo H5FAdblock.lo \ H5FAdblkpage.lo H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5VL.lo \ - H5VLint.lo H5VLnative.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \ - H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ - H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \ - H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \ + H5VLint.lo H5VLnative.lo H5VLiod.lo H5VLiod_common.lo \ + H5VLiod_client.lo H5VLiod_server.lo H5VLiod_encdec.lo \ + H5VLiod_util.lo H5VLiod_file.lo H5VLiod_group.lo \ + H5VLiod_map.lo H5VLiod_dset.lo H5VLiod_dtype.lo \ + H5VLiod_attr.lo H5VLiod_link.lo H5VLiod_obj.lo \ + H5VLiod_trans.lo H5VLiod_analysis.lo H5FD.lo H5FDcore.lo \ + H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo \ + H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo \ + H5FDspace.lo H5FDstdio.lo H5FF.lo H5ES.lo H5RC.lo H5TR.lo \ + H5M.lo H5AS.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \ H5FSsection.lo H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo \ H5Gcache.lo H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo \ H5Gint.lo H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo \ @@ -159,8 +167,9 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \ H5P.lo H5Pacpl.lo H5Pdapl.lo H5Pdcpl.lo H5Pdeprec.lo \ H5Pdxpl.lo H5Pencdec.lo H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo \ - H5Pgcpl.lo H5Pint.lo H5Plapl.lo H5Plcpl.lo H5Pocpl.lo \ - H5Pocpypl.lo H5Pstrcpl.lo H5Ptest.lo H5PL.lo H5R.lo \ + H5Pgcpl.lo H5Pmcpl.lo H5Pmapl.lo H5Pint.lo H5Prcapl.lo \ + H5Ptrspl.lo H5Ptrfpl.lo H5Plapl.lo H5Plcpl.lo H5Pocpl.lo \ + H5Pocpypl.lo H5Pstrcpl.lo H5Ptest.lo H5PL.lo H5Q.lo H5R.lo \ H5Rdeprec.lo H5UC.lo H5RS.lo H5S.lo H5Sall.lo H5Sdbg.lo \ H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo \ H5Stest.lo H5SL.lo H5SM.lo H5SMbtree2.lo H5SMcache.lo \ @@ -290,6 +299,7 @@ DYNAMIC_DIRS = @DYNAMIC_DIRS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ +EFF = @EFF@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXTERNAL_FILTERS = @EXTERNAL_FILTERS@ @@ -354,9 +364,17 @@ LT_STATIC_EXEC = @LT_STATIC_EXEC@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ +MCHECKSUM_CFLAGS = @MCHECKSUM_CFLAGS@ +MCHECKSUM_LIBS = @MCHECKSUM_LIBS@ +MERCURY_CFLAGS = @MERCURY_CFLAGS@ +MERCURY_LIBS = @MERCURY_LIBS@ MKDIR_P = @MKDIR_P@ MPE = @MPE@ MPI_GET_SIZE = @MPI_GET_SIZE@ +MYAXE_LIBS = @MYAXE_LIBS@ +MYDAOS_POSIX_LIBS = @MYDAOS_POSIX_LIBS@ +MYIOD_LIBS = @MYIOD_LIBS@ +MYPLFS_LIBS = @MYPLFS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ @@ -374,6 +392,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARALLEL = @PARALLEL@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PYTHON = @PYTHON@ +PYTHON_BIN = @PYTHON_BIN@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_INCLUDE_DIR = @PYTHON_INCLUDE_DIR@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_LIB = @PYTHON_LIB@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ ROOT = @ROOT@ RUNPARALLEL = @RUNPARALLEL@ @@ -554,9 +585,13 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \ H5FAstat.c H5FAtest.c \ H5VL.c H5VLint.c H5VLnative.c \ + H5VLiod.c H5VLiod_common.c H5VLiod_client.c H5VLiod_server.c H5VLiod_encdec.c H5VLiod_util.c \ + H5VLiod_file.c H5VLiod_group.c H5VLiod_map.c H5VLiod_dset.c H5VLiod_dtype.c \ + H5VLiod_attr.c H5VLiod_link.c H5VLiod_obj.c H5VLiod_trans.c H5VLiod_analysis.c \ H5FD.c H5FDcore.c \ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \ + H5FF.c H5ES.c H5RC.c H5TR.c H5M.c H5AS.c\ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \ H5G.c H5Gbtree2.c H5Gcache.c \ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ @@ -583,9 +618,10 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \ H5Pdeprec.c H5Pdxpl.c H5Pencdec.c \ H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ - H5Pgcpl.c H5Pint.c \ + H5Pgcpl.c H5Pmcpl.c H5Pmapl.c H5Pint.c H5Prcapl.c H5Ptrspl.c H5Ptrfpl.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \ H5PL.c \ + H5Q.c \ H5R.c H5Rdeprec.c \ H5UC.c \ H5RS.c \ @@ -612,10 +648,12 @@ include_HEADERS = hdf5.h H5api_adpt.h H5overflow.h H5pubconf.h H5public.h H5vers H5Epubgen.h H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDdirect.h \ H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h \ - H5VLpublic.h H5VLnative.h \ + H5VLpublic.h H5VLnative.h H5VLiod.h \ + H5FFpublic.h H5ESpublic.h H5RCpublic.h H5TRpublic.h H5Mpublic.h H5ASpublic.h\ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ H5MMpublic.h H5Opublic.h H5Ppublic.h \ H5PLextern.h \ + H5Qpublic.h \ H5Rpublic.h H5Spublic.h \ H5Tpublic.h H5Zpublic.h @@ -757,6 +795,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5A.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5AC.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5AS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Abtree2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adense.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adeprec.Plo@am__quote@ @@ -803,6 +842,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAsblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAstat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAtest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5ES.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Edeprec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Eint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5F.Plo@am__quote@ @@ -827,6 +867,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDsec2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDspace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDstdio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FL.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FO.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FS.Plo@am__quote@ @@ -897,6 +938,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Itest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Lexternal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5M.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFaggr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFdbg.Plo@am__quote@ @@ -952,11 +994,18 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Plapl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Plcpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pmapl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pmcpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pocpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pocpypl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Prcapl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pstrcpl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ptest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ptrfpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ptrspl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Q.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5R.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5RC.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5RS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Rdeprec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5S.Plo@am__quote@ @@ -976,6 +1025,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Sselect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Stest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5T.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5TR.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5TS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Tarray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Tbit.Plo@am__quote@ @@ -1003,6 +1053,22 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5UC.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VL.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_analysis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_attr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_dset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_dtype.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_encdec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_group.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_link.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_map.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_obj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_server.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_trans.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLiod_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VLnative.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5VM.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5WB.Plo@am__quote@ @@ -26,22 +26,28 @@ #include "H5ACpublic.h" /* Metadata cache */ #include "H5Dpublic.h" /* Datasets */ #include "H5Epublic.h" /* Errors */ +#include "H5ESpublic.h" /* Event Stacks */ #include "H5Fpublic.h" /* Files */ #include "H5FDpublic.h" /* File drivers */ +#include "H5FFpublic.h" /* FastForward wrappers */ #include "H5Gpublic.h" /* Groups */ #include "H5Ipublic.h" /* ID management */ #include "H5Lpublic.h" /* Links */ #include "H5MMpublic.h" /* Memory management */ #include "H5Opublic.h" /* Object headers */ #include "H5Ppublic.h" /* Property lists */ +#include "H5Qpublic.h" /* Queries */ #include "H5Rpublic.h" /* References */ +#include "H5RCpublic.h" /* Read Contexts */ #include "H5Spublic.h" /* Dataspaces */ #include "H5Tpublic.h" /* Datatypes */ +#include "H5TRpublic.h" /* Transcations */ #include "H5Zpublic.h" /* Data filters */ #include "H5VLpublic.h" /* VOL plugins */ /* Predefined VOL plugins */ #include "H5VLnative.h" /* Native HDF5 plugin */ +#include "H5VLiod.h" /* IOD VOL plugin */ /* Predefined file drivers */ #include "H5FDcore.h" /* Files stored entirely in memory */ diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in index b594cc2..ab7d8a9 100644 --- a/src/libhdf5.settings.in +++ b/src/libhdf5.settings.in @@ -57,6 +57,7 @@ Languages: Features: --------- Parallel HDF5: @PARALLEL@ + Exascale Fast Forward Stack: @EFF@ High Level library: @HDF5_HL@ Threadsafety: @THREADSAFE@ Default API Mapping: @DEFAULT_API_VERSION@ |