/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 COPYING file, which can be found at the root of the source code * * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Purpose: * The Splitter VFD implements a file driver which relays all the VFD calls * to an underlying VFD, and send all the write calls to another underlying * VFD, SEC2 for now. */ /* This source code file is part of the H5FD driver module */ #include "H5FDdrvr_module.h" #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fprivate.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ #include "H5FDsplitter.h" /* Splitter file driver */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5FDsec2.h" /* Generic Functions */ #include "H5FDstdio.h" /* Generic Functions */ #include "H5Pprivate.h" /* Property lists */ /* The driver identification number, initialized at runtime */ static hid_t H5FD_SPLITTER_g = 0; /* The version of the H5F_splitter_vfd_config_t structure used */ #define H5F__CURR_SPLITTER_VFD_CONFIG_VERSION 1 /* * Driver-specific file access properties */ typedef struct H5FD_splitter_fapl_t { hid_t rw_fapl_id; /* fapl for the R/W channel */ hid_t wo_fapl_id; /* fapl for the W/O channel */ char wo_path[H5FD_MAX_FILENAME_LEN + 1]; /* file name for the W/O channel */ char log_file_path[H5FD_MAX_FILENAME_LEN + 1]; /* file in which to record any errors reported by the W/O path */ hbool_t ignore_wo_errs; /* TRUE to ignore errors on the W/O channel */ } H5FD_splitter_fapl_t; /* * The information of this splitter. */ typedef struct H5FD_splitter_t { H5FD_t pub; /* public stuff, must be first */ unsigned version; /* version of the H5F_splitter_vfd_config_t structure used */ H5FD_splitter_fapl_t fa; /* driver-specific file access properties */ H5FD_t *rw_file; /* pointer of R/W channel */ H5FD_t *wo_file; /* pointer of W/O channel */ } H5FD_splitter_t; /* * These macros check for overflow of various quantities. These macros * assume that HDoff_t is signed and haddr_t and size_t are unsigned. * * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t' * is too large to be represented by the second argument * of the file seek function. * * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too * large to be represented by the `size_t' type. * * REGION_OVERFLOW: Checks whether an address and size pair describe data * which can be addressed entirely by the second * argument of the file seek function. */ #define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1) #define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR)) #define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR) #define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \ HADDR_UNDEF==(A)+(Z) || \ (HDoff_t)((A)+(Z))<(HDoff_t)(A)) /* Private functions */ static int copy_underfapl(); /* Prototypes */ static herr_t H5FD_splitter_term(void); static void *H5FD_splitter_fapl_get(H5FD_t *_file); static void *H5FD_splitter_fapl_copy(const void *_old_fa); static herr_t H5FD_splitter_fapl_free(void *_fapl); static hsize_t H5FD_splitter_sb_size(H5FD_t H5_ATTR_UNUSED *_file); static herr_t H5FD_splitter_sb_encode(H5FD_t *_file, char *name/*out*/, unsigned char *buf/*out*/); static herr_t H5FD_splitter_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf); static H5FD_t *H5FD_splitter_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); static herr_t H5FD_splitter_close(H5FD_t *_file); static int H5FD_splitter_cmp(const H5FD_t *_f1, const H5FD_t *_f2); static herr_t H5FD_splitter_query(const H5FD_t *_file, unsigned long *flags /* out */); static haddr_t H5FD_splitter_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type); static herr_t H5FD_splitter_set_eoa(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr); static haddr_t H5FD_splitter_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type); static herr_t H5FD_splitter_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle); static herr_t H5FD_splitter_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, void *buf); static herr_t H5FD_splitter_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf); static herr_t H5FD_splitter_flush(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static herr_t H5FD_splitter_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static herr_t H5FD_splitter_lock(H5FD_t *_file, hbool_t rw); static herr_t H5FD_splitter_unlock(H5FD_t *_file); static herr_t H5FD_splitter_get_type_map(const H5FD_t *_file, H5FD_mem_t *type_map); static haddr_t H5FD_splitter_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); static herr_t H5FD_splitter_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size); static const H5FD_class_t H5FD_splitter_g = { "splitter", /* name */ MAXADDR, /* maxaddr */ H5F_CLOSE_WEAK, /* fc_degree */ H5FD_splitter_term, /* terminate */ H5FD_splitter_sb_size, /* sb_size */ H5FD_splitter_sb_encode, /* sb_encode */ H5FD_splitter_sb_decode, /* sb_decode */ sizeof(H5FD_splitter_fapl_t), /* fapl_size */ H5FD_splitter_fapl_get, /* fapl_get */ H5FD_splitter_fapl_copy, /* fapl_copy */ H5FD_splitter_fapl_free, /* fapl_free */ 0, /* dxpl_size */ NULL, /* dxpl_copy */ NULL, /* dxpl_free */ H5FD_splitter_open, /* open */ H5FD_splitter_close, /* close */ H5FD_splitter_cmp, /* cmp */ H5FD_splitter_query, /* query */ H5FD_splitter_get_type_map, /* get_type_map */ H5FD_splitter_alloc, /* alloc */ H5FD_splitter_free, /* free */ H5FD_splitter_get_eoa, /* get_eoa */ H5FD_splitter_set_eoa, /* set_eoa */ H5FD_splitter_get_eof, /* get_eof */ H5FD_splitter_get_handle, /* get_handle */ H5FD_splitter_read, /* read */ H5FD_splitter_write, /* write */ H5FD_splitter_flush, /* flush */ H5FD_splitter_truncate, /* truncate */ H5FD_splitter_lock, /* lock */ H5FD_splitter_unlock, /* unlock */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; /* Declare a free list to manage the H5FD_splitter_t struct */ H5FL_DEFINE_STATIC(H5FD_splitter_t); /*------------------------------------------------------------------------- * Function: H5FD__init_package * * Purpose: Initializes any interface-specific data or routines. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ static herr_t H5FD__init_package(void) { herr_t ret_value = SUCCEED; FUNC_ENTER_STATIC if (H5FD_splitter_init() < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize splitter VFD") done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FD__init_package() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_init * * Purpose: Initialize this driver by registering the driver with the * library. * * Return: Success: The driver ID for the splitter driver. * Failure: Negative * * August 27, 2018 * *------------------------------------------------------------------------- */ hid_t H5FD_splitter_init(void) { hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_NOAPI(FAIL) if (H5I_VFL != H5I_get_type(H5FD_SPLITTER_g)) H5FD_SPLITTER_g = H5FDregister(&H5FD_splitter_g); /* Set return value */ ret_value = H5FD_SPLITTER_g; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_init() */ /*--------------------------------------------------------------------------- * Function: H5FD_splitter_term * * Purpose: Shut down the VFD * * Returns: SUCCEED (Can't fail) * * August 27, 2018 * *--------------------------------------------------------------------------- */ static herr_t H5FD_splitter_term(void) { FUNC_ENTER_NOAPI_NOINIT_NOERR /* Reset VFL ID */ H5FD_SPLITTER_g = 0; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FD_splitter_term() */ /*------------------------------------------------------------------------- * Function: H5Pset_fapl_splitter * * Purpose: Sets the file access property list FAPL_ID to use the * splitter driver. There are no driver * specific properties. * * Return: SUCCEED/FAIL * * August 27, 2018 * *------------------------------------------------------------------------- */ herr_t H5Pset_fapl_splitter(hid_t fapl_id, H5F_splitter_vfd_config_t *vfd_config) { H5FD_splitter_fapl_t fapl; /* driver-specific file access properties */ H5P_genplist_t *plist; /* Property list pointer */ H5P_genplist_t *rw_plist; /* Property list pointer of R/W channel */ H5P_genplist_t *wo_plist; /* Property list pointer of W/O channel */ int name_len = 0; herr_t ret_value; hid_t driver = -1; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*x", fapl_id, vfd_config); /* Check arguments */ if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") /* Copy the file access property lists */ if (H5P_FILE_ACCESS_DEFAULT == vfd_config->rw_fapl_id) { if (H5I_inc_ref(vfd_config->rw_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "unable to increment ref count") fapl.rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; } else { if(H5I_GENPROP_LST == H5I_get_type(vfd_config->rw_fapl_id)) { if(NULL == (rw_plist = (H5P_genplist_t *)H5I_object(vfd_config->rw_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") fapl.rw_fapl_id = H5P_copy_plist(rw_plist, FALSE); } } if (H5P_FILE_ACCESS_DEFAULT == vfd_config->wo_fapl_id) { if (H5I_inc_ref(vfd_config->wo_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, FAIL, "unable to increment ref count") fapl.wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; } else { if(H5I_GENPROP_LST == H5I_get_type(vfd_config->wo_fapl_id)) { if(NULL == (wo_plist = (H5P_genplist_t *)H5I_object(vfd_config->wo_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") fapl.wo_fapl_id = H5P_copy_plist(wo_plist, FALSE); } } /* Add driver-specific file access properties */ name_len = HDstrlen(vfd_config->wo_path); HDstrncpy(fapl.wo_path, vfd_config->wo_path, name_len); fapl.wo_path[name_len] = '\0'; name_len = HDstrlen(vfd_config->log_file_path); HDstrncpy(fapl.log_file_path, vfd_config->log_file_path, name_len); fapl.ignore_wo_errs = TRUE; ret_value = H5Pset_driver(fapl_id, H5FD_SPLITTER, &fapl); done: FUNC_LEAVE_API(ret_value) } /* end H5Pset_fapl_splitter() */ /*------------------------------------------------------------------------- * Function: H5Pget_fapl_splitter * * Purpose: Returns information about the splitter file access property * list through the structure splitter_config. * * Return: SUCCEED/FAIL * * August 27, 2018 * *------------------------------------------------------------------------- */ herr_t H5Pget_fapl_splitter(hid_t fapl_id, H5F_splitter_vfd_config_t *vfd_config) { H5FD_splitter_fapl_t *fapl; H5P_genplist_t *plist; /* Property list pointer */ H5P_genplist_t *rw_plist; /* Property list pointer of R/W channel */ H5P_genplist_t *wo_plist; /* Property list pointer of W/O channel */ int name_len = 0; herr_t ret_value = SUCCEED; FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*x", fapl_id, vfd_config); /* Check arguments */ if (TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") /* Check and get the splitter fapl */ 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 (H5FD_SPLITTER != H5P_peek_driver(plist)) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver") if (NULL == (fapl = (H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist))) HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to get specific-driver info") /* Check and get the R/W and W/O fapls */ if (TRUE != H5P_isa_class(fapl->rw_fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") if (fapl->rw_fapl_id) { if (NULL == (rw_plist = (H5P_genplist_t *)H5I_object(fapl->rw_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") vfd_config->rw_fapl_id = H5P_copy_plist(rw_plist, FALSE); } if (fapl->wo_fapl_id) { if (NULL == (wo_plist = (H5P_genplist_t *)H5I_object(fapl->wo_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list") vfd_config->wo_fapl_id = H5P_copy_plist(wo_plist, FALSE); } /* Get other details */ name_len = HDstrlen(fapl->wo_path); HDstrncpy(vfd_config->wo_path, fapl->wo_path, name_len); name_len = HDstrlen(fapl->log_file_path); HDstrncpy(vfd_config->log_file_path, fapl->log_file_path, name_len); vfd_config->ignore_wo_errs = fapl->ignore_wo_errs; done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_fapl_splitter() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_flush * * Purpose: * * * Return: Success: The driver ID for the splitter driver. * Failure: Negative * * August 27, 2018 * *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_flush(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT if (H5FDflush(file->rw_file, dxpl_id, closing) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "unable to flush R/W file") if (H5FDflush(file->wo_file, dxpl_id, closing) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "unable to flush W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_flush() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_read * * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR * into buffer BUF according to data transfer properties in * DXPL_ID. * * buffer BUF. * Failure: FAIL, Contents of buffer BUF are undefined. * * August 27, 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size, void *buf /*out*/) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(file && file->pub.cls); HDassert(buf); /* Check for overflow conditions */ if (!H5F_addr_defined(addr)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined, addr = %llu", (unsigned long long)addr) if (REGION_OVERFLOW(addr, size)) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu", (unsigned long long)addr) /* Only read from R/W channel */ if (H5FDread(file->rw_file, type, dxpl_id, addr, size, buf)<0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "R/W file write failed") done: if (ret_value < 0) { /* Reset last file I/O information */ #if 0 file->pos = HADDR_UNDEF; file->op = OP_UNKNOWN; #endif } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_read() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_write * * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR * from buffer BUF according to data transfer properties in * DXPL_ID. * * Return: SUCCEED/FAIL * * August 27, 2018 * *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; H5P_genplist_t *plist = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT if (NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list") /* Write to each file */ if (H5FDwrite(file->rw_file, type, dxpl_id, addr, size, buf)<0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "R/W file write failed") if (H5FDwrite(file->wo_file, type, dxpl_id, addr, size, buf)<0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "W/O file write failed") done: if (ret_value < 0) { /* Reset last file I/O information */ #if 0 /* from existing vfd */ file->pos = HADDR_UNDEF; file->op = OP_UNKNOWN; #endif } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_write() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_fapl_get * * Purpose: Returns a file access property list which indicates how the * specified file is being accessed. The return list could be * used to access another file the same way. * * Return: Success: Ptr to new file access property list with all * members copied from the file struct. * * Failure: NULL * * Septempber 2018 * *------------------------------------------------------------------------- */ static void * H5FD_splitter_fapl_get(H5FD_t *_file) { H5FD_splitter_t *file = (H5FD_splitter_t*)_file; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); return H5FD_splitter_fapl_copy(&(file->fa)); } /*------------------------------------------------------------------------- * Function: H5FD_splitter_fapl_copy * * Purpose: Copies the file access properties. * * Return: Success: Ptr to a new property list * Failure: NULL * * September 2018 *------------------------------------------------------------------------- */ static void * H5FD_splitter_fapl_copy(const void *_old_fa) { const H5FD_splitter_fapl_t *old_fa = (const H5FD_splitter_fapl_t*)_old_fa; H5FD_splitter_fapl_t *new_fa = NULL; /* New FAPL info */ H5P_genplist_t *rw_plist; /* Property list pointer of R/W channel */ H5P_genplist_t *wo_plist; /* Property list pointer of W/O channel */ int path_len = 0; void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(old_fa); /* Allocate the new FAPL info */ if (NULL == (new_fa = (H5FD_splitter_fapl_t *)calloc((size_t)1,sizeof(H5FD_splitter_fapl_t)))) HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "unable to allocate log file FAPL") /* Copy the general information */ HDmemcpy(new_fa, old_fa, sizeof(H5FD_splitter_fapl_t)); /* Deep copy the file names */ path_len = HDstrlen(old_fa->wo_path); if (path_len > 0) HDstrncpy(new_fa->wo_path, old_fa->wo_path, path_len); path_len = HDstrlen(old_fa->log_file_path); if (path_len > 0) HDstrncpy(new_fa->log_file_path, old_fa->log_file_path, path_len); new_fa->ignore_wo_errs = old_fa->ignore_wo_errs; if (old_fa->rw_fapl_id >= 0) { if (H5Iinc_ref(old_fa->rw_fapl_id) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") new_fa->rw_fapl_id = old_fa->rw_fapl_id; } if (old_fa->wo_fapl_id >= 0) { if (H5Iinc_ref(old_fa->wo_fapl_id) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") new_fa->wo_fapl_id = old_fa->wo_fapl_id; } /* Set return value */ ret_value = new_fa; done: if (NULL == ret_value) if (new_fa) { if(new_fa->wo_path) /* new_fa->wo_path = (char *)H5MM_xfree(new_fa->wo_path); */ H5MM_xfree(new_fa->wo_path); if(new_fa->log_file_path) H5MM_xfree(new_fa->log_file_path); H5MM_free(new_fa); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_fapl_copy() */ /*------------------------------------------------------------------------- * Function: copy_underfapl * * Purpose: Copies the under layer file access list. * * Return: Success: Ptr to a new property list * Failure: NULL * * September 2018 *------------------------------------------------------------------------- */ #if 0 static int copy_underfapl() { if(ufapl_id == H5P_FILE_ACCESS_DEFAULT) { if(H5I_inc_ref(ufapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") /* file->fa.rw_fapl_id = fapl->rw_fapl_id; */ file->fa.rw_fapl_id = fapl->rw_fapl_id; } /* end if */ else { if (NULL == (rw_plist = (H5P_genplist_t *)H5I_object(fapl->rw_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") file->fa.rw_fapl_id = H5P_copy_plist(rw_plist, FALSE); if (file->fa.rw_fapl_id < 0) HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "unable to copy file access property list") } /* end else */ } #endif /*------------------------------------------------------------------------- * Function: H5FD_splitter_open * * Purpose: Create and/or opens a file as an HDF5 file. * * Return: Success: A pointer to a new file data structure. The * public fields will be initialized by the * caller, which is always H5FD_open(). * Failure: NULL * * August 27, 2018 *------------------------------------------------------------------------- */ static H5FD_t * H5FD_splitter_open(const char *name, unsigned flags, hid_t splitter_fapl_id, haddr_t maxaddr) { H5FD_splitter_t *file = NULL; /* splitter VFD info */ H5FD_splitter_fapl_t *fapl = NULL; /* splitter VFD info */ int fd = -1; /* File descriptor */ int o_flags; /* Flags for open() call */ hsize_t eof = HADDR_UNDEF; haddr_t eoa = HADDR_UNDEF; H5FD_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ if (!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name") if (H5F_ACC_RDONLY & flags) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "read-only is not allowed") if (0 == maxaddr || HADDR_UNDEF == maxaddr) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr") if (ADDR_OVERFLOW(maxaddr)) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr") if (H5P_FILE_ACCESS_DEFAULT==splitter_fapl_id || H5FD_SPLITTER!=H5Pget_driver(splitter_fapl_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "driver is not splitter") /* Initialize file from file access properties */ if (NULL ==(file = (H5FD_splitter_t *)H5FL_CALLOC(H5FD_splitter_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct") if(H5P_FILE_ACCESS_DEFAULT == splitter_fapl_id) { file->fa.rw_fapl_id = H5P_FILE_ACCESS_DEFAULT; if(H5I_inc_ref(file->fa.rw_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") file->fa.wo_fapl_id = H5P_FILE_ACCESS_DEFAULT; if(H5I_inc_ref(file->fa.wo_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") } /* end if */ else { H5P_genplist_t *plist = NULL; H5P_genplist_t *rw_plist; /* Property list pointer of R/W channel */ H5P_genplist_t *wo_plist; /* Property list pointer of W/O channel */ /* Get the file access properties */ if(NULL == (plist = (H5P_genplist_t *)H5I_object(splitter_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") if(NULL == (fapl = (const H5FD_splitter_fapl_t *)H5P_peek_driver_info(plist))) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get VFL driver info") if(fapl->rw_fapl_id == H5P_FILE_ACCESS_DEFAULT) { if(H5I_inc_ref(fapl->rw_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") file->fa.rw_fapl_id = fapl->rw_fapl_id; } /* end if */ else { if (NULL == (rw_plist = (H5P_genplist_t *)H5I_object(fapl->rw_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") file->fa.rw_fapl_id = H5P_copy_plist(rw_plist, FALSE); if (file->fa.rw_fapl_id < 0) HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "unable to copy file access property list") } /* end else */ if(fapl->wo_fapl_id == H5P_FILE_ACCESS_DEFAULT) { if(H5I_inc_ref(fapl->wo_fapl_id, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") file->fa.wo_fapl_id = fapl->wo_fapl_id; } /* end if */ else { if (NULL == (wo_plist = (H5P_genplist_t *)H5I_object(fapl->wo_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") file->fa.wo_fapl_id = H5P_copy_plist(wo_plist, FALSE); if (file->fa.rw_fapl_id < 0) HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "unable to copy file access property list") } /* end else */ } /* end else splitter_fapl_id */ HDstrcpy(file->fa.wo_path, fapl->wo_path); HDstrcpy(file->fa.log_file_path, fapl->log_file_path); file->fa.ignore_wo_errs = fapl->ignore_wo_errs; /* necessary? */ file->rw_file = NULL; file->wo_file = NULL; file->rw_file = H5FDopen(name, flags, fapl->rw_fapl_id, HADDR_UNDEF); if (!file->rw_file) HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL, "unable to open R/W file") file->wo_file = H5FDopen(fapl->wo_path, flags, fapl->wo_fapl_id, HADDR_UNDEF); if (!file->wo_file) HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL, "unable to open R/W file") /* Set return value */ ret_value = (H5FD_t*)file; done: if (NULL == ret_value) { H5I_dec_ref(file->fa.rw_fapl_id); H5I_dec_ref(file->fa.wo_fapl_id); if (!file->rw_file) H5FDclose(file->rw_file); if (!file->wo_file) H5FDclose(file->wo_file); if (file) H5FL_FREE(H5FD_splitter_t, file); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_open() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_close * * Purpose: Closes both local and remote files. * * Return: Success: SUCCEED * Failure: FAIL, file not closed. * * August 27, 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_close(H5FD_t *_file) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Close the local file if it's been opened */ if (file->rw_file) if (H5FDclose(file->rw_file) == FAIL) HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close R/W file") /* Close the W/O file if it's been opened */ if (file->wo_file) if (H5FDclose(file->wo_file) == FAIL) HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close W/O file") /* Release the file info */ file = H5FL_FREE(H5FD_splitter_t, file); file = NULL; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_close() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_get_eoa * * Purpose: Returns the end-of-address marker for the file. The EOA * marker is the first address past the last byte allocated in * the format address space. * * Return: Success: The end-of-address-marker * * Failure: HADDR_UNDEF * * Septempber 2018 *------------------------------------------------------------------------- */ static haddr_t H5FD_splitter_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type) { const H5FD_splitter_t *file = (const H5FD_splitter_t *)_file; haddr_t ret_value = HADDR_UNDEF; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); if ((ret_value = H5FDget_eoa(file->rw_file, type)) == HADDR_UNDEF) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, HADDR_UNDEF, "unable to get eoa") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_set_eoa * * Purpose: Set the end-of-address marker for the file. This function is * called shortly after an existing HDF5 file is opened in order * to tell the driver where the end of the HDF5 data is located. * * Return: SUCCEED (Can't fail) * * September 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_set_eoa(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; haddr_t eoa = 0; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); if (H5FDset_eoa(file->rw_file, type, addr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "H5FDset_eoa failed for R/W file") if (H5FDset_eoa(file->wo_file, type, addr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "H5FDset_eoa failed for W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_set_eoa() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_get_eof * * Purpose: Returns the end-of-address marker for the file. The EOA * marker is the first address past the last byte allocated in * the format address space. * * Return: Success: The end-of-address-marker * * Failure: HADDR_UNDEF * * Septempber 2018 *------------------------------------------------------------------------- */ static haddr_t H5FD_splitter_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type) { const H5FD_splitter_t *file = (const H5FD_splitter_t *)_file; haddr_t eof = 0; haddr_t ret_value = HADDR_UNDEF; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); if ((ret_value = H5FDget_eof(file->rw_file, type)) == HADDR_UNDEF) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, HADDR_UNDEF, "unable to get eof") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_truncate * * Purpose: Notify driver to truncate the file back to the allocated size. * * Return: Success: Non-negative * Failure: Negative * * August 27, 2018 * *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); if (file->rw_file && H5FDtruncate(file->rw_file, dxpl_id, closing) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "unable to truncate R/W file") if (file->wo_file && H5FDtruncate(file->wo_file, dxpl_id, closing) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "unable to truncate W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_sb_size * * Purpose: Obtains the number of bytes required to store the driver file * access data in the HDF5 superblock. * * Return: Success: Number of bytes required. * * Failure: 0 if an error occurs or if the driver has no * data to store in the superblock. * * NOTE: no public API for H5FD_sb_size, need to add * * September 2018 *------------------------------------------------------------------------- */ static hsize_t H5FD_splitter_sb_size(H5FD_t H5_ATTR_UNUSED *_file) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; hsize_t ret_value = 0; FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); if (file->rw_file && H5FD_sb_size(file->rw_file) < 0) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unable to ...sb_size... R/W file") if (file->wo_file && H5FD_sb_size(file->wo_file) < 0) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "unable to ...sb_size... W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_sb_encode * * Purpose: Encode driver-specific data into the output arguments. * * Return: Success: Non-negative * * Failure: Negative * * NOTE: no public API for H5FD_sb_size, need to add * * September 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_sb_encode(H5FD_t *_file, char *name/*out*/, unsigned char *buf/*out*/) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); if (file->rw_file && H5FD_sb_encode(file->rw_file, name, buf) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to encode R/W file") if (file->wo_file && H5FD_sb_encode(file->wo_file, name, buf) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to encode W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_sb_decode * * Purpose: Decodes the driver information block. * * Return: Success: Non-negative * * Failure: Negative * * NOTE: no public API for H5FD_sb_size, need to add * * September 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); if (H5FD_sb_load(file->rw_file, name, buf) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "unable to decode R/W file") if (H5FD_sb_load(file->wo_file, name, buf) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "unable to decode W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_cmp * * Purpose: Compare the keys of two files. * * Return: Success: A value like strcmp() * * Failure: Must never fail * * September 2018 *------------------------------------------------------------------------- */ static int H5FD_splitter_cmp(const H5FD_t *_f1, const H5FD_t *_f2) { H5FD_splitter_t *f1 = (H5FD_splitter_t*)_f1; H5FD_splitter_t *f2 = (H5FD_splitter_t*)_f2; herr_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check arguments */ HDassert(f1); HDassert(f2); ret_value = H5FDcmp(f1->rw_file, f2->rw_file); FUNC_LEAVE_NOAPI(ret_value) } /*-------------------------------------------------------------------------- * Function: H5FD_splitter_get_handle * * Purpose: Returns a pointer to the file handle of low-level virtual * file driver. * * Return: Success: Non-negative * * Failure: Negative * * Septempber 2018 *-------------------------------------------------------------------------- */ static herr_t H5FD_splitter_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle) { H5FD_splitter_t *file = (H5FD_splitter_t*)_file; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(file); HDassert(file->rw_file); HDassert(file_handle); /* Only do for R/W for now??? */ ret_value = H5FDget_vfd_handle(file->rw_file, file->fa.rw_fapl_id, file_handle); if (ret_value < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to get handle of R/W file") done: FUNC_LEAVE_NOAPI(ret_value) } /*-------------------------------------------------------------------------- * Function: H5FD_splitter_fapl_free * * Purpose: Releases the file access lists * * Return: Success: Non-negative * * Failure: Negative * * Septempber 2018 *-------------------------------------------------------------------------- */ static herr_t H5FD_splitter_fapl_free(void *_fapl) { H5FD_splitter_fapl_t *fapl = (H5FD_splitter_fapl_t*)_fapl; H5FD_splitter_fapl_t *rw_wapl, *wo_fapl; H5P_genplist_t *rw_plist; H5P_genplist_t *wo_plist; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(fapl); if(H5I_dec_ref(fapl->rw_fapl_id) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close R/W fapl ID") if(H5I_dec_ref(fapl->rw_fapl_id) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close W/O fapl ID") /* if (fapl->rw_fapl_id) H5Pclose(fapl->rw_fapl_id); if (fapl->wo_fapl_id) H5Pclose(fapl->wo_fapl_id); */ /* free wo_path and log_file_path if dynamic */ H5MM_free(fapl); done: FUNC_LEAVE_NOAPI(ret_value) } /*-------------------------------------------------------------------------- * Function: H5FD_splitter_lock * * Purpose: Sets a file lock. * * Return: Success: Non-negative * * Failure: Negative * * Septempber 2018 *-------------------------------------------------------------------------- */ static herr_t H5FD_splitter_lock(H5FD_t *_file, hbool_t rw) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Place the lock on each file */ if (H5FDlock(file->rw_file, rw) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTLOCK, FAIL, "unable to lock R/W file") if (H5FDlock(file->wo_file, rw) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTLOCK, FAIL, "unable to lock W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*-------------------------------------------------------------------------- * Function: H5FD_splitter_unlock * * Purpose: Removes a file lock. * * Return: Success: Non-negative * * Failure: Negative * * Septempber 2018 *-------------------------------------------------------------------------- */ static herr_t H5FD_splitter_unlock(H5FD_t *_file) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Remove the lock on each file */ if (H5FD_unlock(file->rw_file) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTUNLOCK, FAIL, "unable to unlock R/W file") if (H5FD_unlock(file->wo_file) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTUNLOCK, FAIL, "unable to unlock W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5FD_splitter_query * * Purpose: Set the flags that this VFL driver is capable of supporting. * (listed in H5FDpublic.h) * * Return: SUCCEED (Can't fail) * * Septempber 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_query(const H5FD_t *_file, unsigned long *flags /* out */) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT if ( file ) { /* Check arguments */ HDassert(file); HDassert(file->rw_file); if (H5FDquery(file->rw_file, flags) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTLOCK, FAIL, "unable to query R/W file") } else { /* file is NULL, so set *flags to 0 */ /* review this? */ *flags = 0; } done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_query() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_alloc * * Purpose: Set the flags that this VFL driver is capable of supporting. * (listed in H5FDpublic.h) * * Return: SUCCEED (Can't fail) * * Septempber 2018 *------------------------------------------------------------------------- */ static haddr_t H5FD_splitter_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Remove the lock on each file */ if (H5FDalloc(file->rw_file, type, dxpl_id, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to allocate for R/W file") if (H5FDalloc(file->wo_file, type, dxpl_id, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to allocate for W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_alloc() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_get_type_map * * Purpose: Set the flags that this VFL driver is capable of supporting. * (listed in H5FDpublic.h) * * Return: SUCCEED (Can't fail) * * Septempber 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_get_type_map(const H5FD_t *_file, H5FD_mem_t *type_map) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Remove the lock on each file */ if (H5FD_get_fs_type_map(file->rw_file, type_map) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to allocate for R/W file") if (H5FD_get_fs_type_map(file->wo_file, type_map) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to allocate for W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_get_type_map() */ /*------------------------------------------------------------------------- * Function: H5FD_splitter_free * * Purpose: Set the flags that this VFL driver is capable of supporting. * (listed in H5FDpublic.h) * * Return: SUCCEED (Can't fail) * * Septempber 2018 *------------------------------------------------------------------------- */ static herr_t H5FD_splitter_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) { H5FD_splitter_t *file = (H5FD_splitter_t *)_file; /* VFD file struct */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(file); HDassert(file->rw_file); HDassert(file->wo_file); /* Remove the lock on each file */ if (H5FDfree(file->rw_file, type, dxpl_id, addr, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "unable to allocate for R/W file") if (H5FDfree(file->wo_file, type, dxpl_id, addr, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "unable to allocate for W/O file") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_splitter_free() */