summaryrefslogtreecommitdiffstats
path: root/src/H5FD.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1999-08-10 20:21:32 (GMT)
committerRobb Matzke <matzke@llnl.gov>1999-08-10 20:21:32 (GMT)
commitcbf68fc824f69dcdc0fcd38a83a3fee8c7093c28 (patch)
treeb7075c9f11db1b343593b5e0619a285ccc8418af /src/H5FD.c
parent7d949c9da91b33955d4e253c1093a4f23fb63523 (diff)
downloadhdf5-cbf68fc824f69dcdc0fcd38a83a3fee8c7093c28.zip
hdf5-cbf68fc824f69dcdc0fcd38a83a3fee8c7093c28.tar.gz
hdf5-cbf68fc824f69dcdc0fcd38a83a3fee8c7093c28.tar.bz2
[svn-r1568] Changes since 19990730
---------------------- This extensive change is the virtual file layer implementation. I've ported and tested the sec2, family, and core drivers and only ported the mpio driver (Albert will test it). So if you need MPIO I would recommend sticking with the previous version for a while. You will get a few compile warnings about split and stdio drivers not being implemented and possibly tracing information not inserted in some of the drivers. You can safely ignore them but I plan to fix them. I'm still working on the split driver because I just realized that it needs a part of the VFL that isn't written yet. Documentation is being updated also because there were some minor changes (mostly just name changes). It should be available on my web site later this week. ./MANIFEST ./src/Makefile.in ./src/hdf5.h ./src/H5Flow.c [REMOVED] ./src/H5Fstdio.c [REMOVED] ./src/H5Fsec2.c [REMOVED] ./src/H5Fsplit.c [REMOVED] ./src/H5Fmpio.c [REMOVED] ./src/H5Ffamily.c [REMOVED] ./src/H5Fcore.c [REMOVED] ./src/H5MFpublic.h [REMOVED] ./src/H5FD.c [NEW] ./src/H5FDcore.c [NEW] ./src/H5FDcore.h [NEW] ./src/H5FDfamily.c [NEW] ./src/H5FDfamily.h [NEW] ./src/H5FDmpio.c [NEW] ./src/H5FDmpio.h [NEW] ./src/H5FDprivate.h [NEW] ./src/H5FDpublic.h [NEW] ./src/H5FDsec2.c [NEW] ./src/H5FDsec2.h [NEW] Removed/added files for virtual file layer. ./bin/trace ./src/H5.c Removed unused public datatypes and added new VFL public datatypes. Changed an error message. ./config/BlankForm ./config/dec-flags ./config/gnu-flags ./config/hpux10.20 ./config/hpux9.03 ./config/irix5.x ./config/irix6.x ./config/solaris2.x ./config/unicosmk Removed the H5F_OPT_SEEK and H5F_LOW_DFLT constants from the configuration since they're no longer applicable. The default file driver is always the sec2 driver and it always optimizes calls to lseek() or lseek64(). ./config/depend.in C preprocessor errors generated during automatic dependency building are sent to /dev/null to prevent them from appearing twice in the make output. ./src/H5AC.c ./src/H5B.c ./src/H5D.c ./src/H5F.c ./src/H5G.c ./src/H5Gent.c ./src/H5Gnode.c ./src/H5HG.c ./src/H5HL.c ./src/H5O.c ./src/H5Oattr.c ./src/H5Odtype.c ./src/H5Oefl.c ./src/H5Oshared.c ./src/H5T.c ./src/H5detect.c ./test/ohdr.c Changed H5F_ADDR_UNDEF to HADDR_UNDEF to be more consistent with the `haddr_t' datatype which is now a public type. ./src/H5D.c ./src/H5P.c ./src/H5Ppublic.h ./src/H5Tconv.c ./test/cmpd_dset.c ./test/dsets.c ./test/overhead.c ./test/tselect.c ./test/tvltypes.c The H5P_DATASET_XFER constant was changed to H5P_DATA_XFER because the properties apply to all types of I/O operations, not just datasets. ./src/H5B.c ./src/H5Bprivate.h ./src/H5D.c ./src/H5Dpublic.h ./src/H5F.c ./src/H5Farray.c ./src/H5Fistore.c ./src/H5Fprivate.h ./src/H5Fpublic.h ./src/H5Gnode.c ./src/H5Gpkg.h ./src/H5HG.c ./src/H5HL.c ./src/H5O.c ./src/H5R.c ./src/H5Sall.c ./src/H5Shyper.c ./src/H5Smpio.c ./src/H5Spoint.c ./src/H5Sprivate.h ./test/big.c ./test/h5test.c ./test/istore.c ./testpar/t_dset.c ./testpar/t_file.c ./tools/h5debug.c ./tools/h5ls.c Modified to work with the virtual file layer by calling H5FD_* functions instead of H5F_low_* functions and by passing file access and data transfer properties by object ID instead of pointer. Changed H5D_transfer_t to H5FD_mpio_xfer_t since the COLLECTIVE vs. INDEPENDENT transfer mode is specific to the MPIO file driver. Moved MPIO-specific stuff into the MPIO driver. ./src/H5B.c ./src/H5D.c ./src/H5Fprivate.h The H5F_mpio_* private functions were renamed and placed in the H5FDmpio driver except those which appeared in H5Smpio.c. ./src/H5E.c ./src/H5Epublic.h Added major error number H5E_VFL for virtual file layer related errors. ./src/H5F.c ./src/H5Fprivate.h Changed the logic that controls whether the boot block is written. Instead of assuming that the first call to write the boot block is only to allocate space, I've added a function argument which makes this explicit. Changed the way files are compared so that a driver-defined comparison function can be called. Files which belong to different drivers are always considered different. Removed H5F_driver_t since file drivers are now identified by object ID instead of a special non-user-extendible datatype. Removed all the hard-coded low-level file properties which have been replaced by the various file drivers. ./src/H5I.c ./src/H5Iprivate.h Added the H5I_inc_ref() which was removed a few months ago since we finally have a use for it. ./src/H5Ipublic.h Added the H5I_VFL object ID type to identify file drivers in the virtual file layer. ./src/H5MF.c ./src/H5MFprivate.h Moved all the allocation/deallocation code into the virtual file layer which allows file drivers to override much of it. ./src/H5P.c ./src/H5Ppublic.h Moved file driver-specific code into the various file driver files. The H5Pcopy() and H5Pclose() functions make calls into the virtual file driver to manage the memory for driver-specific file access and data transfer properties. ./src/H5private.h ./src/H5public.h The `haddr_t' type is now public. ./test/tfile.c Added a few more comments.
Diffstat (limited to 'src/H5FD.c')
-rw-r--r--src/H5FD.c1642
1 files changed, 1642 insertions, 0 deletions
diff --git a/src/H5FD.c b/src/H5FD.c
new file mode 100644
index 0000000..e8b13b7
--- /dev/null
+++ b/src/H5FD.c
@@ -0,0 +1,1642 @@
+/*
+ * Copyright © 1999 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Monday, July 26, 1999
+ *
+ * Purpose: The Virtual File Layer as described in documentation. This is
+ * the greatest common denominator for all types of storage
+ * access whether a file, memory, network, etc. This layer
+ * usually just dispatches the request to an actual file driver
+ * layer.
+ */
+
+/* Packages needed by this file */
+#include <H5private.h> /*library functions */
+#include <H5Eprivate.h> /*error handling */
+#include <H5Fprivate.h> /*files */
+#include <H5FDprivate.h> /*virtual file driver */
+#include <H5Iprivate.h> /*interface abstraction layer */
+#include <H5MMprivate.h> /*memory management */
+#include <H5Pprivate.h> /*property lists */
+
+/* Interface initialization */
+#define PABLO_MASK H5FD_mask
+#define INTERFACE_INIT H5FD_init_interface
+static intn interface_initialize_g = 0;
+
+/* static prototypes */
+static herr_t H5FD_init_interface(void);
+static herr_t H5FD_free_cls(H5FD_class_t *cls);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_init_interface
+ *
+ * Purpose: Initialize the virtual file layer.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Monday, July 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_init_interface(void)
+{
+ FUNC_ENTER(H5FD_init_interface, FAIL);
+
+ if (H5I_init_group(H5I_VFL, H5I_VFL_HASHSIZE, 0,
+ (H5I_free_t)H5FD_free_cls)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "unable to initialize interface");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_term_interface
+ *
+ * Purpose: Terminate this interface: free all memory and reset global
+ * variables to their initial values. Release all ID groups
+ * associated with this interface.
+ *
+ * Return: Success: Positive if anything was done that might
+ * have affected other interfaces; zero
+ * otherwise.
+ *
+ * Failure: Never fails.
+ *
+ * Programmer: Robb Matzke
+ * Friday, February 19, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5FD_term_interface(void)
+{
+ intn n = 0;
+
+ if (interface_initialize_g) {
+ if ((n=H5I_nmembers(H5I_VFL))) {
+ H5I_clear_group(H5I_VFL, FALSE);
+ } else {
+ H5I_destroy_group(H5I_VFL);
+ interface_initialize_g = 0;
+ n = 1; /*H5I*/
+ }
+ }
+ return n;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_free_cls
+ *
+ * Purpose: Frees a file driver class struct and returns an indication of
+ * success. This function is used as the free callback for the
+ * virtual file layer object identifiers (cf H5FD_init_interface).
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Monday, July 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_free_cls(H5FD_class_t *cls)
+{
+ FUNC_ENTER(H5FD_free_cls, FAIL);
+ H5MM_xfree(cls);
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDregister
+ *
+ * Purpose: Registers a new file driver as a member of the virtual file
+ * driver class. Certain fields of the class struct are
+ * required and that is checked here so it doesn't have to be
+ * checked every time the field is accessed.
+ *
+ * Return: Success: A file driver ID which is good until the
+ * library is closed or the driver is
+ * unregistered.
+ *
+ * Failure: A negative value.
+ *
+ * Programmer: Robb Matzke
+ * Monday, July 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5FDregister(const H5FD_class_t *cls)
+{
+ hid_t retval;
+ H5FD_class_t *saved;
+ H5FD_mem_t type;
+
+ FUNC_ENTER(H5FDregister, FAIL);
+ H5TRACE1("i","x",cls);
+
+ /* Check arguments */
+ if (!cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "null class pointer is disallowed");
+ }
+ if (!cls->open || !cls->close) {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "`open' and/or `close' methods are not defined");
+ }
+ if (!cls->get_eoa || !cls->set_eoa) {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "`get_eoa' and/or `set_eoa' methods are not defined");
+ }
+ if (!cls->get_eof) {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "`get_eof' method is not defined");
+ }
+ if (!cls->read || !cls->write) {
+ HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL,
+ "`read' and/or `write' method is not defined");
+ }
+ for (type=0; type<H5FD_MEM_NTYPES; type++) {
+ if (cls->fl_map[type]<H5FD_MEM_NOLIST ||
+ cls->fl_map[type]>=H5FD_MEM_NTYPES) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid free-list mapping");
+ }
+ }
+
+ /* Copy the class structure so the caller can reuse or free it */
+ if (NULL==(saved=H5MM_malloc(sizeof(H5FD_class_t)))) {
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "memory allocation failed for file driver class struct");
+ }
+ *saved = *cls;
+
+ /* Create the new class ID */
+ if ((retval=H5I_register(H5I_VFL, saved))<0) {
+ HRETURN_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register file driver ID");
+ }
+
+ FUNC_LEAVE(retval);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDunregister
+ *
+ * Purpose: Removes a driver ID from the library. This in no way affects
+ * file access property lists which have been defined to use
+ * this driver or files which are already opened under this
+ * driver.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Monday, July 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDunregister(hid_t driver_id)
+{
+ FUNC_ENTER(H5FDunregister, FAIL);
+ H5TRACE1("e","i",driver_id);
+
+ /* Check arguments */
+ if (H5I_VFL!=H5I_get_type(driver_id) ||
+ NULL==H5I_object(driver_id)) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a file driver");
+ }
+
+ /* The H5FD_class_t struct will be freed by this function */
+ if (H5I_dec_ref(driver_id)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "unable to unregister file driver");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_fapl_copy
+ *
+ * Purpose: Copies the driver-specific part of the file access property
+ * list.
+ *
+ * Return: Success: Pointer to new driver-specific file access
+ * properties.
+ *
+ * Failure: NULL, but also returns null with no error
+ * pushed onto the error stack if the OLD_FAPL
+ * is null.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, August 3, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5FD_fapl_copy(hid_t driver_id, const void *old_fapl)
+{
+ void *new_fapl = NULL;
+ H5FD_class_t *driver=NULL;
+
+ FUNC_ENTER(H5FD_fapl_copy, NULL);
+
+ /* Check args */
+ if (H5I_VFL!=H5I_get_type(driver_id) ||
+ NULL==(driver=H5I_object(driver_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a driver ID");
+ }
+ if (!old_fapl) HRETURN(NULL); /*but no error*/
+
+ /* Allow the driver to copy or do it ourselves */
+ if (driver->fapl_copy) {
+ new_fapl = (driver->fapl_copy)(old_fapl);
+ } else if (driver->fapl_size>0) {
+ new_fapl = H5MM_malloc(driver->fapl_size);
+ HDmemcpy(new_fapl, old_fapl, driver->fapl_size);
+ } else {
+ HRETURN_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL,
+ "no way to copy driver file access property list");
+ }
+
+ FUNC_LEAVE(new_fapl);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_fapl_free
+ *
+ * Purpose: Frees the driver-specific file access property list.
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, August 3, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_fapl_free(hid_t driver_id, void *fapl)
+{
+ H5FD_class_t *driver=NULL;
+
+ FUNC_ENTER(H5FD_fapl_free, FAIL);
+ H5TRACE2("e","ix",driver_id,fapl);
+
+ /* Check args */
+ if (H5I_VFL!=H5I_get_type(driver_id) ||
+ NULL==(driver=H5I_object(driver_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID");
+ }
+
+ /* Allow driver to free or do it ourselves */
+ if (fapl && driver->fapl_free) {
+ if ((driver->fapl_free)(fapl)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver fapl_free request failed");
+ }
+ } else {
+ H5MM_xfree(fapl);
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_dxpl_copy
+ *
+ * Purpose: Copies the driver-specific part of the data transfer property
+ * list.
+ *
+ * Return: Success: Pointer to new driver-specific data transfer
+ * properties.
+ *
+ * Failure: NULL, but also returns null with no error
+ * pushed onto the error stack if the OLD_DXPL
+ * is null.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, August 3, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl)
+{
+ void *new_dxpl = NULL;
+ H5FD_class_t *driver=NULL;
+
+ FUNC_ENTER(H5FD_dxpl_copy, NULL);
+
+ /* Check args */
+ if (H5I_VFL!=H5I_get_type(driver_id) ||
+ NULL==(driver=H5I_object(driver_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL,
+ "not a driver ID");
+ }
+ if (!old_dxpl) HRETURN(NULL); /*but no error*/
+
+ /* Allow the driver to copy or do it ourselves */
+ if (driver->dxpl_copy) {
+ new_dxpl = (driver->dxpl_copy)(old_dxpl);
+ } else if (driver->dxpl_size>0) {
+ new_dxpl = H5MM_malloc(driver->dxpl_size);
+ HDmemcpy(new_dxpl, old_dxpl, driver->dxpl_size);
+ } else {
+ HRETURN_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL,
+ "no way to copy driver file access property list");
+ }
+
+ FUNC_LEAVE(new_dxpl);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_dxpl_free
+ *
+ * Purpose: Frees the driver-specific data transfer property list.
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, August 3, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_dxpl_free(hid_t driver_id, void *dxpl)
+{
+ H5FD_class_t *driver=NULL;
+
+ FUNC_ENTER(H5FD_dxpl_free, FAIL);
+ H5TRACE2("e","ix",driver_id,dxpl);
+
+ /* Check args */
+ if (H5I_VFL!=H5I_get_type(driver_id) ||
+ NULL==(driver=H5I_object(driver_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID");
+ }
+
+ /* Allow driver to free or do it ourselves */
+ if (dxpl && driver->dxpl_free) {
+ if ((driver->dxpl_free)(dxpl)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver dxpl_free request failed");
+ }
+ } else {
+ H5MM_xfree(dxpl);
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDopen
+ *
+ * Purpose: Opens a file named NAME for the type(s) of access described
+ * by the bit vector FLAGS according to a file access property
+ * list FAPL_ID (which may be the constant H5P_DEFAULT). The
+ * file should expect to handle format addresses in the range [0,
+ * MAXADDR] (if MAXADDR is the undefined address then the caller
+ * doesn't care about the address range).
+ *
+ * Possible values for the FLAGS bits are:
+ *
+ * H5F_ACC_RDWR: Open the file for read and write access. If
+ * this bit is not set then open the file for
+ * read only access. It is permissible to open a
+ * file for read and write access when only read
+ * access is requested by the library (the
+ * library will never attempt to write to a file
+ * which it opened with only read access).
+ *
+ * H5F_ACC_CREATE: Create the file if it doesn't already exist.
+ * However, see H5F_ACC_EXCL below.
+ *
+ * H5F_ACC_TRUNC: Truncate the file if it already exists. This
+ * is equivalent to deleting the file and then
+ * creating a new empty file.
+ *
+ * H5F_ACC_EXCL: When used with H5F_ACC_CREATE, if the file
+ * already exists then the open should fail.
+ * Note that this is unsupported/broken with
+ * some file drivers (e.g., sec2 across nfs) and
+ * will contain a race condition when used to
+ * perform file locking.
+ *
+ * The MAXADDR is the maximum address which will be requested by
+ * the library during an allocation operation. Usually this is
+ * the same value as the MAXADDR field of the class structure,
+ * but it can be smaller if the driver is being used under some
+ * other driver.
+ *
+ * Note that when the driver `open' callback gets control that
+ * the public part of the file struct (the H5FD_t part) will be
+ * incomplete and will be filled in after that callback returns.
+ *
+ * Return: Success: Pointer to a new file driver struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, July 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5FD_t *
+H5FDopen(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
+{
+ H5FD_t *ret_value=NULL;
+
+ FUNC_ENTER(H5FDopen, NULL);
+
+ if (NULL==(ret_value=H5FD_open(name, flags, fapl_id, maxaddr))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, NULL,
+ "unable to open file");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_open
+ *
+ * Purpose: Private version of H5FDopen()
+ *
+ * Return: Success: Pointer to a new file driver struct
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5FD_t *
+H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
+{
+ const H5F_access_t *fapl=NULL;
+ H5FD_class_t *driver;
+ H5FD_t *file=NULL;
+
+ FUNC_ENTER(H5FD_open, NULL);
+
+ /* Check arguments */
+ if (H5P_DEFAULT==fapl_id) {
+ fapl = &H5F_access_dflt;
+ } else if (H5P_FILE_ACCESS != H5P_get_class(fapl_id) ||
+ NULL == (fapl = H5I_object(fapl_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL,
+ "not a file access property list");
+ }
+ if (0==maxaddr) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, NULL,
+ "zero format address range");
+ }
+
+ /* Get driver info */
+ if (H5I_VFL!=H5I_get_type(fapl->driver_id) ||
+ NULL==(driver=H5I_object(fapl->driver_id))) {
+ HRETURN_ERROR(H5E_VFL, H5E_BADVALUE, NULL,
+ "invalid driver ID in file access property list");
+ }
+ if (NULL==driver->open) {
+ HRETURN_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL,
+ "file driver has no `open' method");
+ }
+
+ /* Dispatch to file driver */
+ if (HADDR_UNDEF==maxaddr) maxaddr = driver->maxaddr;
+ if (NULL==(file=(driver->open)(name, flags, fapl_id, maxaddr))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "open failed");
+ }
+
+ /*
+ * Fill in public fields. We must increment the reference count on the
+ * driver ID to prevent it from being freed while this file is open.
+ */
+ file->driver_id = fapl->driver_id;
+ H5I_inc_ref(file->driver_id);
+ file->cls = driver;
+ file->maxaddr = maxaddr;
+ HDmemset(file->fl, 0, sizeof(file->fl));
+
+ FUNC_LEAVE(file);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDclose
+ *
+ * Purpose: Closes the file by calling the driver `close' callback, which
+ * should free all driver-private data and free the file struct.
+ * Note that the public part of the file struct (the H5FD_t part)
+ * will be all zero during the driver close callback like during
+ * the `open' callback.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, July 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDclose(H5FD_t *file)
+{
+ FUNC_ENTER(H5FDclose, FAIL);
+ H5TRACE1("e","x",file);
+
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+
+ if (H5FD_close(file)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to close file");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_close
+ *
+ * Purpose: Private version of H5FDclose()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_close(H5FD_t *file)
+{
+ const H5FD_class_t *driver;
+ H5FD_free_t *cur, *next;
+ H5FD_mem_t i;
+#ifdef H5F_DEBUG
+ uintn nblocks=0;
+ hsize_t nbytes=0;
+#endif
+
+ FUNC_ENTER(H5FD_close, FAIL);
+ assert(file && file->cls);
+
+ /* Free all free-lists, leaking any memory thus described */
+ for (i=0; i<H5FD_MEM_NTYPES; i++) {
+ for (cur=file->fl[i]; cur; cur=next) {
+#ifdef H5F_DEBUG
+ nblocks++;
+ nbytes += cur->size;
+#endif
+ next = cur->next;
+ H5MM_xfree(cur);
+ }
+ file->fl[i]=NULL;
+ }
+#ifdef H5F_DEBUG
+ if (nblocks && H5DEBUG(F)) {
+ fprintf(H5DEBUG(F),
+ "H5F: leaked %lu bytes of file memory in %u blocks\n",
+ (unsigned long)nbytes, nblocks);
+ }
+#endif
+
+ /* Prepare to close file by clearing all public fields */
+ driver = file->cls;
+ H5I_dec_ref(file->driver_id);
+ HDmemset(file, 0, sizeof(H5FD_t));
+
+ /*
+ * Dispatch to the driver for actual close. If the driver fails to
+ * close the file then the file will be in an unusable state.
+ */
+ assert(driver->close);
+ if ((driver->close)(file)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "close failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDcmp
+ *
+ * Purpose: Compare the keys of two files using the file driver callback
+ * if the files belong to the same driver, otherwise sort the
+ * files by driver class pointer value.
+ *
+ * Return: Success: A value like strcmp()
+ *
+ * Failure: Must never fail. If both file handles are
+ * invalid then they compare equal. If one file
+ * handle is invalid then it compares less than
+ * the other. If both files belong to the same
+ * driver and the driver doesn't provide a
+ * comparison callback then the file pointers
+ * themselves are compared.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, July 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FDcmp(const H5FD_t *f1, const H5FD_t *f2)
+{
+ intn ret_value;
+
+ FUNC_ENTER(H5FDcmp, -1); /*return value is arbitrary*/
+ H5TRACE2("Is","xx",f1,f2);
+
+ ret_value = H5FD_cmp(f1, f2);
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_cmp
+ *
+ * Purpose: Private version of H5FDcmp()
+ *
+ * Return: Success: A value like strcmp()
+ *
+ * Failure: Must never fail.
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2)
+{
+ intn ret_value;
+
+ FUNC_ENTER(H5FD_cmp, -1); /*return value is arbitrary*/
+
+ if ((!f1 || !f1->cls) && (!f2 || !f2->cls)) return 0;
+ if (!f1 || !f1->cls) return -1;
+ if (!f2 || !f2->cls) return 1;
+ if (f1->cls < f2->cls) return -1;
+ if (f1->cls > f2->cls) return 1;
+
+ /* Files are same driver; no cmp callback */
+ if (!f1->cls->cmp) {
+ if (f1<f2) return -1;
+ if (f1>f2) return 1;
+ return 0;
+ }
+
+ ret_value = (f1->cls->cmp)(f1, f2);
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDalloc
+ *
+ * Purpose: Allocates SIZE bytes of memory from the FILE. The memory will
+ * be used according to the allocation class TYPE. First we try
+ * to satisfy the request from one of the free lists, according
+ * to the free list map provided by the driver. The free list
+ * array has one entry for each request type and the value of
+ * that array element can be one of four possibilities:
+ *
+ * It can be the constant H5FD_MEM_DEFAULT (or zero) which
+ * indicates that the identity mapping is used. In other
+ * words, the request type maps to its own free list.
+ *
+ * It can be the request type itself, which has the same
+ * effect as the H5FD_MEM_DEFAULT value above.
+ *
+ * It can be the ID for another request type, which
+ * indicates that the free list for the specified type
+ * should be used instead.
+ *
+ * It can be the constant H5FD_MEM_NOLIST which means that
+ * no free list should be used for this type of request.
+ *
+ * If the request cannot be satisfied from a free list then
+ * either the driver's `alloc' callback is invoked (if one was
+ * supplied) or the end-of-address marker is extended. The
+ * `alloc' callback is always called with the same arguments as
+ * the H5FDalloc().
+ *
+ * Return: Success: The format address of the new file memory.
+ *
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, July 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FDalloc(H5FD_t *file, H5FD_mem_t type, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF;
+
+ FUNC_ENTER(H5FDalloc, HADDR_UNDEF);
+ H5TRACE3("a","xMth",file,type,size);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF,
+ "invalid file pointer");
+ }
+ if (type<0 || type>=H5FD_MEM_NTYPES) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF,
+ "invalid request type");
+ }
+ if (size<=0) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF,
+ "zero-size request");
+ }
+
+ /* Do the real work */
+ if (HADDR_UNDEF==(ret_value=H5FD_alloc(file, type, size))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "unable to allocate file memory");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_alloc
+ *
+ * Purpose: Private version of H5FDalloc()
+ *
+ * Return: Success: The format address of the new file memory.
+ *
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF;
+ H5FD_mem_t mapped_type;
+
+ FUNC_ENTER(H5FD_alloc, HADDR_UNDEF);
+
+ /* Check args */
+ assert(file && file->cls);
+ assert(type>=0 && type<H5FD_MEM_NTYPES);
+ assert(size>0);
+
+ /* Map the allocation request to a free list */
+ if (H5FD_MEM_DEFAULT==file->cls->fl_map[type]) {
+ mapped_type = type;
+ } else {
+ mapped_type = file->cls->fl_map[type];
+ }
+
+ /*
+ * Try to satisfy the request from the free list. First try to find an
+ * exact match, otherwise use the best match.
+ */
+ if (mapped_type>=0) {
+ H5FD_free_t *prev=NULL, *best=NULL;
+ H5FD_free_t *cur = file->fl[mapped_type];
+ while (cur) {
+ if (cur->size==size) {
+ ret_value = cur->addr;
+ if (prev) prev->next = cur->next;
+ else file->fl[mapped_type] = cur->next;
+ H5MM_xfree(cur);
+ HRETURN(ret_value);
+ } else if (cur->size>size &&
+ (!best || cur->size<best->size)) {
+ best = cur;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if (best) {
+ ret_value = best->addr;
+ best->addr += size;
+ best->size -= size;
+ HRETURN(ret_value);
+ }
+ }
+
+ /*
+ * Dispatch to driver `alloc' callback or extend the end-of-address
+ * marker
+ */
+ if (file->cls->alloc) {
+ ret_value = (file->cls->alloc)(file, type, size);
+ if (HADDR_UNDEF==ret_value) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "driver allocation request failed");
+ }
+ } else {
+ haddr_t eoa = (file->cls->get_eoa)(file);
+ if (H5F_addr_overflow(eoa, size) || eoa+size>file->maxaddr) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation request failed");
+ }
+ ret_value = eoa;
+ eoa += size;
+ if ((file->cls->set_eoa)(file, eoa)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation request failed");
+ }
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDfree
+ *
+ * Purpose: Frees format addresses starting with ADDR and continuing for
+ * SIZE bytes in the file FILE. The type of space being freed is
+ * specified by TYPE, which is mapped to a free list as
+ * described for the H5FDalloc() function above. If the request
+ * doesn't map to a free list then either the application `free'
+ * callback is invoked (if defined) or the memory is leaked.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, July 28, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDfree(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size)
+{
+ FUNC_ENTER(H5FDfree, FAIL);
+ H5TRACE4("e","xMtah",file,type,addr,size);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+ if (type<0 || type>=H5FD_MEM_NTYPES) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid request type");
+ }
+
+ /* Do the real work */
+ if (H5FD_free(file, type, addr, size)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "file deallocation request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_free
+ *
+ * Purpose: Private version of H5FDfree()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size)
+{
+ H5FD_mem_t mapped_type;
+
+ FUNC_ENTER(H5FD_free, FAIL);
+
+ /* Check args */
+ assert(file && file->cls);
+ assert(type>=0 && type<H5FD_MEM_NTYPES);
+ if (!H5F_addr_defined(addr) || addr>file->maxaddr || 0==size ||
+ H5F_addr_overflow(addr, size) || addr+size>file->maxaddr) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region");
+ }
+
+ /* Map request type to free list */
+ if (H5FD_MEM_DEFAULT==file->cls->fl_map[type]) {
+ mapped_type = type;
+ } else {
+ mapped_type = file->cls->fl_map[type];
+ }
+
+ /*
+ * If the request maps to a free list then add memory to the free list
+ * without ever telling the driver that it was freed. Otherwise let the
+ * driver deallocate the memory.
+ */
+ if (mapped_type>=0) {
+ H5FD_free_t *cur = H5MM_malloc(sizeof(H5FD_free_t));
+ cur->addr = addr;
+ cur->size = size;
+ cur->next = file->fl[mapped_type];
+ file->fl[mapped_type] = cur;
+ } else if (file->cls->free) {
+ if ((file->cls->free)(file, type, addr, size)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver free request failed");
+ }
+ } else {
+ /* leak memory */
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDrealloc
+ *
+ * Purpose: Changes the size of an allocated chunk of memory, possibly
+ * also changing its location in the file.
+ *
+ * Return: Success: New address of the block of memory, not
+ * necessarily the same as the original address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, August 3, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FDrealloc(H5FD_t *file, H5FD_mem_t type, haddr_t old_addr, hsize_t old_size,
+ hsize_t new_size)
+{
+ haddr_t ret_value=HADDR_UNDEF;
+
+ FUNC_ENTER(H5FDrealloc, HADDR_UNDEF);
+ H5TRACE5("a","xMtahh",file,type,old_addr,old_size,new_size);
+
+ if (HADDR_UNDEF==(ret_value=H5FD_realloc(file, type, old_addr, old_size,
+ new_size))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "file reallocation request failed");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_realloc
+ *
+ * Purpose: Private version of H5FDrealloc()
+ *
+ * Return: Success: New address of the block of memory, not
+ * necessarily the same as the original address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_realloc(H5FD_t *file, H5FD_mem_t type, haddr_t old_addr, hsize_t old_size,
+ hsize_t new_size)
+{
+ haddr_t new_addr=old_addr;
+ uint8_t _buf[8192];
+ uint8_t *buf=_buf;
+
+ FUNC_ENTER(H5FD_realloc, HADDR_UNDEF);
+
+ if (new_size==old_size) {
+ /*nothing to do*/
+
+ } else if (0==old_size) {
+ /* allocate memory */
+ assert(!H5F_addr_defined(old_addr));
+ if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
+ HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation failed");
+ }
+
+ } else if (0==new_size) {
+ /* free memory */
+ assert(H5F_addr_defined(old_addr));
+ H5FDfree(file, type, old_addr, old_size);
+ new_addr = HADDR_UNDEF;
+
+ } else if (new_size<old_size) {
+ /* free the end of the block */
+ H5FDfree(file, type, old_addr+old_size, old_size-new_size);
+
+ } else {
+ /* move memory to new location */
+ if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
+ HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation failed");
+ }
+ if (old_size>sizeof(_buf) && NULL==(buf=H5MM_malloc(old_size))) {
+ H5FDfree(file, type, new_addr, new_size);
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF,
+ "memory allocation failed");
+ }
+ if (H5FDread(file, H5P_DEFAULT, old_addr, old_size, buf)<0 ||
+ H5FDwrite(file, H5P_DEFAULT, new_addr, old_size, buf)) {
+ H5FDfree(file, type, new_addr, new_size);
+ H5MM_xfree(buf);
+ HRETURN_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF,
+ "unable to move file block");
+ }
+
+ if (buf!=_buf) H5MM_xfree(buf);
+ H5FDfree(file, type, old_addr, old_size);
+ }
+
+ FUNC_LEAVE(new_addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDget_eoa
+ *
+ * Purpose: Returns the address of the first byte after the last
+ * allocated memory in the file.
+ *
+ * Return: Success: First byte after allocated memory.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Friday, July 30, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FDget_eoa(H5FD_t *file)
+{
+ haddr_t addr;
+
+ FUNC_ENTER(H5FDget_eoa, HADDR_UNDEF);
+ H5TRACE1("a","x",file);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF,
+ "invalid file pointer");
+ }
+
+ /* The real work */
+ if (HADDR_UNDEF==(addr=H5FD_get_eoa(file))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "file get eoa request failed");
+ }
+
+ FUNC_LEAVE(addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eoa
+ *
+ * Purpose: Private version of H5FDget_eoa()
+ *
+ * Return: Success: First byte after allocated memory.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eoa(H5FD_t *file)
+{
+ haddr_t addr;
+
+ FUNC_ENTER(H5FD_get_eoa, HADDR_UNDEF);
+ assert(file && file->cls);
+
+ /* Dispatch to driver */
+ if (HADDR_UNDEF==(addr=(file->cls->get_eoa)(file))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "driver get_eoa request failed");
+ }
+
+ FUNC_LEAVE(addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDset_eoa
+ *
+ * Purpose: Set the end-of-address marker for the file. The ADDR is the
+ * address of the first byte past the last allocated byte of the
+ * file. This function is called from two places:
+ *
+ * It is called after an existing file is opened in order to
+ * "allocate" enough space to read the superblock and then
+ * to "allocate" the entire hdf5 file based on the contents
+ * of the superblock.
+ *
+ * It is called during file memory allocation if the
+ * allocation request cannot be satisfied from the free list
+ * and the driver didn't supply an allocation callback.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative, no side effect
+ *
+ * Programmer: Robb Matzke
+ * Friday, July 30, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDset_eoa(H5FD_t *file, haddr_t addr)
+{
+ FUNC_ENTER(H5FDset_eoa, FAIL);
+ H5TRACE2("e","xa",file,addr);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+ if (!H5F_addr_defined(addr) || addr>file->maxaddr) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid end-of-address value");
+ }
+
+ /* The real work */
+ if (H5FD_set_eoa(file, addr)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "file set eoa request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_set_eoa
+ *
+ * Purpose: Private version of H5FDset_eoa()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative, no side effect
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_set_eoa(H5FD_t *file, haddr_t addr)
+{
+ FUNC_ENTER(H5FD_set_eoa, FAIL);
+ assert(file && file->cls);
+ assert(H5F_addr_defined(addr) && addr<=file->maxaddr);
+
+ /* Dispatch to driver */
+ if ((file->cls->set_eoa)(file, addr)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver set_eoa request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDget_eof
+ *
+ * Purpose: Returns the end-of-file address, which is the greater of the
+ * end-of-format address and the actual EOF marker. This
+ * function is called after an existing file is opened in order
+ * for the library to learn the true size of the underlying file
+ * and to determine whether the hdf5 data has been truncated.
+ *
+ * It is also used when a file is first opened to learn whether
+ * the file is empty or not.
+ *
+ * It is permissible for the driver to return the maximum address
+ * for the file size if the file is not empty.
+ *
+ * Return: Success: The EOF address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 29, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FDget_eof(H5FD_t *file)
+{
+ haddr_t addr;
+
+ FUNC_ENTER(H5FDget_eof, HADDR_UNDEF);
+ H5TRACE1("a","x",file);
+
+ /* Check arguments */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF,
+ "invalid file pointer");
+ }
+
+ /* The real work */
+ if (HADDR_UNDEF==(addr=H5FD_get_eof(file))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "file get eof request failed");
+ }
+
+ FUNC_LEAVE(addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eof
+ *
+ * Purpose: Private version of H5FDget_eof()
+ *
+ * Return: Success: The EOF address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eof(H5FD_t *file)
+{
+ haddr_t addr=HADDR_UNDEF;
+
+ FUNC_ENTER(H5FD_get_eof, HADDR_UNDEF);
+ assert(file && file->cls);
+
+ /* Dispatch to driver */
+ if (file->cls->get_eof) {
+ if (HADDR_UNDEF==(addr=(file->cls->get_eof)(file))) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF,
+ "driver get_eof request failed");
+ }
+ } else {
+ addr = file->maxaddr;
+ }
+
+ FUNC_LEAVE(addr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDread
+ *
+ * Purpose: Reads SIZE bytes from FILE beginning at address ADDR
+ * according to the data transfer property list DXPL_ID (which may
+ * be the constant H5P_DEFAULT). The result is written into the
+ * buffer BUF.
+ *
+ * Return: Success: Non-negative. The read result is written into
+ * the BUF buffer which should be allocated by
+ * the caller.
+ *
+ * Failure: Negative. The contents of BUF is undefined.
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 29, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDread(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+ void *buf/*out*/)
+{
+ FUNC_ENTER(H5FDread, FAIL);
+ H5TRACE5("e","xiahx",file,dxpl_id,addr,size,buf);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+ if (H5P_DEFAULT!=dxpl_id &&
+ (H5P_DATA_XFER!=H5P_get_class(dxpl_id) ||
+ NULL==H5I_object(dxpl_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a data transfer property list");
+ }
+ if (!buf) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer");
+ }
+
+ /* Do the real work */
+ if (H5FD_read(file, dxpl_id, addr, size, buf)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file read request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_read
+ *
+ * Purpose: Private version of H5FDread()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_read(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+ void *buf/*out*/)
+{
+ FUNC_ENTER(H5FD_read, FAIL);
+ assert(file && file->cls);
+ assert(H5P_DEFAULT==dxpl_id ||
+ (H5P_DATA_XFER==H5P_get_class(dxpl_id) || H5I_object(dxpl_id)));
+ assert(buf);
+
+ /* The no-op case */
+ if (0==size) HRETURN(SUCCEED);
+
+ /* Dispatch to driver */
+ if ((file->cls->read)(file, dxpl_id, addr, size, buf)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver read request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDwrite
+ *
+ * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according
+ * to the data transfer property list DXPL_ID (which may be the
+ * constant H5P_DEFAULT). The bytes to be written come from the
+ * buffer BUF.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 29, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDwrite(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+ const void *buf)
+{
+ FUNC_ENTER(H5FDwrite, FAIL);
+ H5TRACE5("e","xiahx",file,dxpl_id,addr,size,buf);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+ if (H5P_DEFAULT!=dxpl_id &&
+ (H5P_DATA_XFER!=H5P_get_class(dxpl_id) ||
+ NULL==H5I_object(dxpl_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a data transfer property list");
+ }
+ if (!buf) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer");
+ }
+
+ /* The real work */
+ if (H5FD_write(file, dxpl_id, addr, size, buf)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "file write request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_write
+ *
+ * Purpose: Private version of H5FDwrite()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_write(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+ const void *buf)
+{
+ FUNC_ENTER(H5FD_write, FAIL);
+ assert(file && file->cls);
+ assert(H5P_DEFAULT==dxpl_id ||
+ (H5P_DATA_XFER==H5P_get_class(dxpl_id) && H5I_object(dxpl_id)));
+ assert(buf);
+
+ /* The no-op case */
+ if (0==size) HRETURN(SUCCEED);
+
+ /* Dispatch to driver */
+ if ((file->cls->write)(file, dxpl_id, addr, size, buf)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver write request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FDflush
+ *
+ * Purpose: Notify driver to flush all cached data. If the driver has no
+ * flush method then nothing happens.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 29, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FDflush(H5FD_t *file)
+{
+ FUNC_ENTER(H5FDflush, FAIL);
+ H5TRACE1("e","x",file);
+
+ /* Check args */
+ if (!file || !file->cls) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ }
+
+ /* Do the real work */
+ if (H5FD_flush(file)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "file flush request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_flush
+ *
+ * Purpose: Private version of H5FDflush()
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_flush(H5FD_t *file)
+{
+ FUNC_ENTER(H5FD_flush, FAIL);
+ assert(file && file->cls);
+
+ if (file->cls->flush &&
+ (file->cls->flush)(file)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver flush request failed");
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}