From 2bd041f8787562928ba8a060843cdeeb386bebf0 Mon Sep 17 00:00:00 2001 From: Dana Robinson Date: Tue, 11 Jun 2019 09:04:23 -0700 Subject: Added H5Fdelete call and VOL support (but no VFD/native implementation). --- java/src/hdf/hdf5lib/HDF5Constants.java | 3 + .../hdf5lib/exceptions/HDF5LibraryException.java | 5 +- java/src/jni/h5Constants.c | 2 + src/H5F.c | 73 +++++++++++++- src/H5Fint.c | 4 +- src/H5Fpublic.h | 1 + src/H5VLcallback.c | 2 +- src/H5VLnative_file.c | 8 +- src/H5VLpassthru.c | 2 +- src/H5VLpublic.h | 3 +- src/H5err.txt | 1 + src/H5trace.c | 3 + test/tfile.c | 107 +++++++++++++++++++++ 13 files changed, 202 insertions(+), 12 deletions(-) diff --git a/java/src/hdf/hdf5lib/HDF5Constants.java b/java/src/hdf/hdf5lib/HDF5Constants.java index 8054ee8..cb5ed22 100644 --- a/java/src/hdf/hdf5lib/HDF5Constants.java +++ b/java/src/hdf/hdf5lib/HDF5Constants.java @@ -121,6 +121,7 @@ public class HDF5Constants { public static final long H5E_CANTDEC = H5E_CANTDEC(); public static final long H5E_CANTDECODE = H5E_CANTDECODE(); public static final long H5E_CANTDELETE = H5E_CANTDELETE(); + public static final long H5E_CANTDELETEFILE = H5E_CANTDELETEFILE(); public static final long H5E_CANTENCODE = H5E_CANTENCODE(); public static final long H5E_CANTFLUSH = H5E_CANTFLUSH(); public static final long H5E_CANTFREE = H5E_CANTFREE(); @@ -863,6 +864,8 @@ public class HDF5Constants { private static native final long H5E_CANTDELETE(); + private static native final long H5E_CANTDELETEFILE(); + private static native final long H5E_CANTENCODE(); private static native final long H5E_CANTFLUSH(); diff --git a/java/src/hdf/hdf5lib/exceptions/HDF5LibraryException.java b/java/src/hdf/hdf5lib/exceptions/HDF5LibraryException.java index 3a1361a..54acbdd 100644 --- a/java/src/hdf/hdf5lib/exceptions/HDF5LibraryException.java +++ b/java/src/hdf/hdf5lib/exceptions/HDF5LibraryException.java @@ -171,6 +171,9 @@ public class HDF5LibraryException extends HDF5Exception { else if (err_code == HDF5Constants.H5E_MOUNT) { return "file mount error"; } + else if (err_code == HDF5Constants.H5E_CANTDELETEFILE) { + return "Unable to delete file"; + } else if (err_code == HDF5Constants.H5E_SEEKERROR) { return "seek failed"; } @@ -262,7 +265,7 @@ public class HDF5LibraryException extends HDF5Exception { return "unrecognized message"; } else if (err_code == HDF5Constants.H5E_CANTDELETE) { - return " Can't delete message"; + return "Can't delete message"; } else if (err_code == HDF5Constants.H5E_CANTOPENOBJ) { return "Can't open object"; diff --git a/java/src/jni/h5Constants.c b/java/src/jni/h5Constants.c index 4b10479..b9e320f 100644 --- a/java/src/jni/h5Constants.c +++ b/java/src/jni/h5Constants.c @@ -204,6 +204,8 @@ Java_hdf_hdf5lib_HDF5Constants_H5E_1CANTDECODE(JNIEnv *env, jclass cls) { return JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5E_1CANTDELETE(JNIEnv *env, jclass cls) { return H5E_CANTDELETE; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5E_1CANTDELETEFILE(JNIEnv *env, jclass cls) { return H5E_CANTDELETEFILE; } +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5E_1CANTENCODE(JNIEnv *env, jclass cls) { return H5E_CANTENCODE; } JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5E_1CANTFLUSH(JNIEnv *env, jclass cls) { return H5E_CANTFLUSH; } diff --git a/src/H5F.c b/src/H5F.c index 779c940..e123d0b 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -560,20 +560,21 @@ done: * * Purpose: Check if the file can be opened with the given fapl. * - * Return: TRUE/FALSE/FAIL + * Return: Succeed: TRUE/FALSE + * Failure: FAIL (includes file does not exist) * *------------------------------------------------------------------------- */ htri_t -H5Fis_accessible(const char *name, hid_t fapl_id) +H5Fis_accessible(const char *filename, hid_t fapl_id) { htri_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) - H5TRACE2("t", "*si", name, fapl_id); + H5TRACE2("t", "*si", filename, fapl_id); /* Check args */ - if(!name || !*name) + if(!filename || !*filename) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") /* Check the file access property list */ @@ -584,7 +585,7 @@ H5Fis_accessible(const char *name, hid_t fapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list") /* Check if file is accessible */ - if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, name, &ret_value) < 0) + if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0) HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5") done: @@ -838,6 +839,68 @@ done: /*------------------------------------------------------------------------- + * Function: H5Fdelete + * + * Purpose: Deletes an HDF5 file. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fdelete(const char *filename, hid_t fapl_id) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ + htri_t is_hdf5 = FAIL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "*si", filename, fapl_id); + + /* Check args */ + if(!filename || !*filename) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") + + /* 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") + + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + + /* Get the VOL info from the fapl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(fapl_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list") + if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info") + + /* Stash a copy of the "top-level" connector property, before any pass-through + * connectors modify or unwrap it. + */ + if(H5CX_set_vol_connector_prop(&connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context") + + /* Make sure this is HDF5 storage for this VOL connector */ + if(H5VL_file_specific(NULL, H5VL_FILE_IS_ACCESSIBLE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &is_hdf5) < 0) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to determine if file is accessible as HDF5") + if(!is_hdf5) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "not an HDF5 file") + + /* Delete the file */ + if(H5VL_file_specific(NULL, H5VL_FILE_DELETE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, fapl_id, filename, &ret_value) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTDELETEFILE, FAIL, "unable to delete the file") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fdelete() */ + + +/*------------------------------------------------------------------------- * Function: H5Freopen * * Purpose: Reopen a file. The new file handle which is returned points diff --git a/src/H5Fint.c b/src/H5Fint.c index 2e8771c..ee9afed 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -863,7 +863,7 @@ H5F__is_hdf5(const char *name, hid_t fapl_id) * should work with arbitrary VFDs, unlike H5Fis_hdf5(). */ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF))) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to open file") /* The file is an hdf5 file if the hdf5 file signature can be found */ if(H5FD_locate_signature(file, &sig_addr) < 0) @@ -874,7 +874,7 @@ done: /* Close the file */ if(file) if(H5FD_close(file) < 0 && TRUE == ret_value) - HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file") FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__is_hdf5() */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 52f1ee2..dd794e4 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -233,6 +233,7 @@ H5_DLL hid_t H5Fopen(const char *filename, unsigned flags, H5_DLL hid_t H5Freopen(hid_t file_id); H5_DLL herr_t H5Fflush(hid_t object_id, H5F_scope_t scope); H5_DLL herr_t H5Fclose(hid_t file_id); +H5_DLL herr_t H5Fdelete(const char *filename, hid_t fapl_id); H5_DLL hid_t H5Fget_create_plist(hid_t file_id); H5_DLL hid_t H5Fget_access_plist(hid_t file_id); H5_DLL herr_t H5Fget_intent(hid_t file_id, unsigned *intent); diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index 2d1274c..696ccab 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -3041,7 +3041,7 @@ H5VL_file_specific(const H5VL_object_t *vol_obj, H5VL_file_specific_t specific_t arg_started = TRUE; /* Special treatment of file access check */ - if(specific_type == H5VL_FILE_IS_ACCESSIBLE) { + if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) { H5P_genplist_t *plist; /* Property list pointer */ H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ va_list tmp_args; /* argument list passed from the API call */ diff --git a/src/H5VLnative_file.c b/src/H5VLnative_file.c index 8903911..eeaade6 100644 --- a/src/H5VLnative_file.c +++ b/src/H5VLnative_file.c @@ -386,10 +386,16 @@ H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type, /* Call private routine */ if((*ret = H5F__is_hdf5(name, fapl_id)) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "error in HDF5 file check") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "error in HDF5 file check") break; } + /* H5Fdelete */ + case H5VL_FILE_DELETE: + { + HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "H5Fdelete() is currently not supported in the native VOL connector") + break; + } default: diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index ef92ddb..78150c5 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -1733,7 +1733,7 @@ H5VL_pass_through_file_specific(void *file, H5VL_file_specific_t specific_type, /* Re-issue 'file specific' call, using the unwrapped pieces */ ret_value = H5VL_pass_through_file_specific_reissue(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, (int)loc_type, name, child_file->under_object, plist_id); } /* end if */ - else if(specific_type == H5VL_FILE_IS_ACCESSIBLE) { + else if(specific_type == H5VL_FILE_IS_ACCESSIBLE || specific_type == H5VL_FILE_DELETE) { H5VL_pass_through_info_t *info; hid_t fapl_id, under_fapl_id; const char *name; diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index ebe424a..fc3ee8a 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -105,7 +105,8 @@ typedef enum H5VL_file_specific_t { H5VL_FILE_REOPEN, /* Reopen the file */ H5VL_FILE_MOUNT, /* Mount a file */ H5VL_FILE_UNMOUNT, /* Unmount a file */ - H5VL_FILE_IS_ACCESSIBLE /* Check if a file is accessible */ + H5VL_FILE_IS_ACCESSIBLE, /* Check if a file is accessible */ + H5VL_FILE_DELETE /* Delete a file */ } H5VL_file_specific_t; /* types for group GET callback */ diff --git a/src/H5err.txt b/src/H5err.txt index 4eedc0f..d4edfba 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -134,6 +134,7 @@ MINOR, FILEACC, H5E_NOTHDF5, Not an HDF5 file MINOR, FILEACC, H5E_BADFILE, Bad file ID accessed MINOR, FILEACC, H5E_TRUNCATED, File has been truncated MINOR, FILEACC, H5E_MOUNT, File mount error +MINOR, FILEACC, H5E_CANTDELETEFILE, Unable to delete file # Generic low-level file I/O errors MINOR, FILE, H5E_SEEKERROR, Seek failed diff --git a/src/H5trace.c b/src/H5trace.c index 1125072..ff81ae8 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -2758,6 +2758,9 @@ H5_trace(const double *returning, const char *func, const char *type, ...) case H5VL_FILE_IS_ACCESSIBLE: HDfprintf(out, "H5VL_FILE_IS_ACCESSIBLE"); break; + case H5VL_FILE_DELETE: + HDfprintf(out, "H5VL_FILE_DELETE"); + break; default: HDfprintf(out, "%ld", (long)specific); break; diff --git a/test/tfile.c b/test/tfile.c index 695d437..6318787 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -1850,6 +1850,102 @@ test_file_ishdf5(const char *env_h5_drvr) } /* end test_file_ishdf5() */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ + +/**************************************************************** +** +** test_file_delete(): tests H5Fdelete for all VFDs +** +*****************************************************************/ +#define FILE_DELETE "test_file_delete" +#define FILE_DELETE_NOT_HDF5 "test_file_delete_not_hdf5" +static void +test_file_delete(hid_t fapl_id) +{ + hid_t fid = H5I_INVALID_HID; /* File to be deleted */ + char filename[FILENAME_LEN]; /* Filename to use */ + htri_t is_hdf5; /* Whether a file is an HDF5 file */ + int fd; /* POSIX file descriptor */ + int iret; + herr_t ret; + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Deletion of HDF5 Files\n")); + + /*************/ + /* HDF5 FILE */ + /*************/ + + /* This is just a placeholder until the native VOL connector supports + * H5Fdelete(). + */ + + /* Get fapl-dependent filename */ + h5_fixname(FILE_DELETE, fapl_id, filename, sizeof(filename)); + + /* Create a file */ + fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + CHECK(fid, H5I_INVALID_HID, "H5Fcreate"); + + /* Close file */ + ret = H5Fclose(fid); + VERIFY(ret, SUCCEED, "H5Fclose"); + + /* Verify that the file is an HDF5 file */ + is_hdf5 = H5Fis_accessible(filename, fapl_id); + VERIFY(is_hdf5, TRUE, "H5Fis_accessible"); + + /* Attempt to delete the file - should fail */ + H5E_BEGIN_TRY { + ret = H5Fdelete(filename, fapl_id); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Fdelete"); + + /* Verify that the file still exists */ + is_hdf5 = H5Fis_accessible(filename, fapl_id); + VERIFY(is_hdf5, TRUE, "H5Fis_accessible"); + + /* Actually delete the test file */ + h5_delete_test_file(FILE_DELETE, fapl_id); + + /*****************/ + /* NON-HDF5 FILE */ + /*****************/ + + /* Get fapl-dependent filename */ + h5_fixname(FILE_DELETE_NOT_HDF5, fapl_id, filename, sizeof(filename)); + + /* Create a non-HDF5 file */ + fd = HDopen(filename, O_RDWR | O_CREAT | O_TRUNC, H5_POSIX_CREATE_MODE_RW); + CHECK_I(fd, "HDopen"); + + /* Close the file */ + ret = HDclose(fd); + VERIFY(ret, 0, "HDclose"); + + /* Verify that the file is not an HDF5 file */ + /* Note that you can get a FAIL result when h5_fixname() + * perturbs the filename as a file with that exact name + * may not have been created since we created it with + * open(2) and not the library. + */ + H5E_BEGIN_TRY { + is_hdf5 = H5Fis_accessible(filename, fapl_id); + } H5E_END_TRY; + VERIFY(is_hdf5, SUCCEED, "H5Fis_accessible"); + + /* Try to delete it (should fail) */ + H5E_BEGIN_TRY { + ret = H5Fdelete(filename, fapl_id); + } H5E_END_TRY; + VERIFY(ret, FAIL, "H5Fdelete"); + + /* Delete the file */ + iret = HDremove(filename); + VERIFY(iret, 0, "HDremove"); + +} /* end test_file_delete() */ + + /**************************************************************** ** ** test_file_open_dot(): low-level file test routine. @@ -7606,6 +7702,8 @@ void test_file(void) { const char *env_h5_drvr; /* File Driver value from environment */ + hid_t fapl_id = H5I_INVALID_HID; /* VFD-dependent fapl ID */ + herr_t ret; /* Output message about test being performed */ MESSAGE(5, ("Testing Low-Level File I/O\n")); @@ -7615,6 +7713,10 @@ test_file(void) if(env_h5_drvr == NULL) env_h5_drvr = "nomatch"; + /* Improved version of VFD-dependent checks */ + fapl_id = h5_fileaccess(); + CHECK(fapl_id, H5I_INVALID_HID, "h5_fileaccess"); + test_file_create(); /* Test file creation(also creation templates)*/ test_file_open(); /* Test file opening */ test_file_reopen(); /* Test file reopening */ @@ -7624,6 +7726,7 @@ test_file(void) test_file_perm(); /* Test file access permissions */ test_file_perm2(); /* Test file access permission again */ test_file_is_accessible(env_h5_drvr); /* Test detecting HDF5 files correctly */ + test_file_delete(fapl_id); /* Test H5Fdelete */ test_file_open_dot(); /* Test opening objects with "." for a name */ test_file_open_overlap(); /* Test opening files in an overlapping manner */ test_file_getname(); /* Test basic H5Fget_name() functionality */ @@ -7662,6 +7765,10 @@ test_file(void) test_file_ishdf5(env_h5_drvr); /* Test detecting HDF5 files correctly */ test_deprec(); /* Test deprecated routines */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ + + ret = H5Pclose(fapl_id); + CHECK(ret, FAIL, "H5Pclose"); + } /* test_file() */ -- cgit v0.12