Files
hdf5/src/H5F.c
Quincey Koziol e3101ecc46 [svn-r17555] Description:
Bring r17553 from trunk to 1.8 branch:

	Bring general fixes/improvements from file_free_space branch back to
trunk.

Tested on:
       FreeBSD/32 6.3 (duty) in debug mode
       FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
       Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
                               in debug mode
       Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x,
                               w/C++ & FORTRAN, in production mode
       Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
                               w/szip filter, in production mode
       Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
                               in production mode
       Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
       Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
       Mac OS X/32 10.5.8 (amazon) in debug mode
       Mac OS X/32 10.5.8 (amazon) w/C++ & FORTRAN, w/threadsafe,
                               in production mode
2009-09-29 16:53:19 -05:00

2839 lines
100 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5F_init_interface
/* Packages needed by this file... */
#include "H5private.h" /* Generic Functions */
#include "H5Aprivate.h" /* Attributes */
#include "H5ACprivate.h" /* Metadata cache */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
#include "H5Tprivate.h" /* Datatypes */
/* Predefined file drivers */
#include "H5FDcore.h" /*temporary in-memory files */
#include "H5FDfamily.h" /*family of files */
#include "H5FDlog.h" /* sec2 driver with logging, for debugging */
#include "H5FDmpi.h" /* MPI-based file drivers */
#include "H5FDmulti.h" /*multiple files partitioned by mem usage */
#include "H5FDsec2.h" /*Posix unbuffered I/O */
#include "H5FDstdio.h" /* Standard C buffered I/O */
#ifdef H5_HAVE_WINDOWS
#include "H5FDwindows.h" /* Windows buffered I/O */
#endif
#include "H5FDdirect.h" /*Linux direct I/O */
/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */
typedef struct H5F_olist_t {
H5I_type_t obj_type; /* Type of object to look for */
hid_t *obj_id_list; /* Pointer to the list of open IDs to return */
size_t *obj_id_count; /* Number of open IDs */
struct {
hbool_t local; /* Set flag for "local" file searches */
union {
H5F_file_t *shared; /* Pointer to shared file to look inside */
const H5F_t *file; /* Pointer to file to look inside */
} ptr;
} file_info;
size_t list_index; /* Current index in open ID array */
size_t max_index; /* Maximum # of IDs to put into array */
} H5F_olist_t;
/* PRIVATE PROTOTYPES */
static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id,
H5FD_t *lf);
static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id);
static herr_t H5F_close(H5F_t *f);
/* Declare a free list to manage the H5F_t struct */
H5FL_DEFINE(H5F_t);
/* Declare a free list to manage the H5F_file_t struct */
H5FL_DEFINE(H5F_file_t);
/*-------------------------------------------------------------------------
* Function: H5F_init
*
* Purpose: Initialize the interface from some other layer.
*
* Return: Success: non-negative
* Failure: negative
*
* Programmer: Robb Matzke
* Wednesday, December 16, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_init(void)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_init, FAIL)
/* FUNC_ENTER() does all the work */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_init() */
/*-------------------------------------------------------------------------
* Function: H5F_init_interface
*
* Purpose: Initialize interface-specific information.
*
* Return: Success: non-negative
* Failure: negative
*
* Programmer: Robb Matzke
* Friday, November 20, 1998
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_init_interface(void)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_init_interface)
/*
* Initialize the atom group for the file IDs.
*/
if(H5I_register_type(H5I_FILE, (size_t)H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<H5I_FILE)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_init_interface() */
/*-------------------------------------------------------------------------
* Function: H5F_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
*
*-------------------------------------------------------------------------
*/
int
H5F_term_interface(void)
{
int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_term_interface)
if(H5_interface_initialize_g) {
if((n = H5I_nmembers(H5I_FILE)) != 0) {
H5I_clear_type(H5I_FILE, FALSE, FALSE);
} else {
/* Make certain we've cleaned up all the shared file objects */
H5F_sfile_assert_num(0);
H5I_dec_type_ref(H5I_FILE);
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
} /* end else */
} /* end if */
FUNC_LEAVE_NOAPI(n)
} /* H5F_term_interface() */
/*-------------------------------------------------------------------------
* Function: H5Fget_create_plist
*
* Purpose: Get an atom for a copy of the file-creation property list for
* this file. This function returns an atom with a copy of the
* properties used to create a file.
*
* Return: Success: template ID
*
* Failure: FAIL
*
* Programmer: Unknown
*
*-------------------------------------------------------------------------
*/
hid_t
H5Fget_create_plist(hid_t file_id)
{
H5F_t *file; /* File info */
H5P_genplist_t *plist; /* Property list */
hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_create_plist, FAIL)
H5TRACE1("i", "i", file_id);
/* check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
if(NULL == (plist = (H5P_genplist_t *)H5I_object(file->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Create the property list object to return */
if((ret_value = H5P_copy_plist(plist, TRUE)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file creation properties")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_create_plist() */
/*-------------------------------------------------------------------------
* Function: H5Fget_access_plist
*
* Purpose: Returns a copy of the file access property list of the
* specified file.
*
* NOTE: Make sure that, if you are going to overwrite
* information in the copied property list that was
* previously opened and assigned to the property list, then
* you must close it before overwriting the values.
*
* Return: Success: Object ID for a copy of the file access
* property list.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, February 18, 1998
*
*-------------------------------------------------------------------------
*/
hid_t
H5Fget_access_plist(hid_t file_id)
{
H5F_t *f; /* File info */
hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_access_plist, FAIL)
H5TRACE1("i", "i", file_id);
/* Check args */
if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Retrieve the file's access property list */
if((ret_value = H5F_get_access_plist(f, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file access property list")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_access_plist() */
/*-------------------------------------------------------------------------
* Function: H5F_get_access_plist
*
* Purpose: Returns a copy of the file access property list of the
* specified file.
*
* NOTE: Make sure that, if you are going to overwrite
* information in the copied property list that was
* previously opened and assigned to the property list, then
* you must close it before overwriting the values.
*
* Return: Success: Object ID for a copy of the file access
* property list.
*
* Failure: FAIL
*
* Programmer: Quincey Koziol
* Wednesday, May 25, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
hid_t
H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
{
H5P_genplist_t *new_plist; /* New property list */
H5P_genplist_t *old_plist; /* Old property list */
void *driver_info=NULL;
hid_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5F_get_access_plist, FAIL)
/* Check args */
HDassert(f);
/* Make a copy of the default file access property list */
if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Copy properties of the file access property list */
if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment threshold")
if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment")
if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference")
if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size")
if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size")
if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
/*
* Since we're resetting the driver ID and info, close them if they
* exist in this new property list.
*/
if(H5P_facc_close(ret_value, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information")
/* Increment the reference count on the driver ID and insert it into the property list */
if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID")
/* Set the driver "info" in the property list */
driver_info = H5FD_fapl_get(f->shared->lf);
if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info")
/* Set the file close degree appropriately */
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) {
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
} else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) {
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_access_plist() */
/*-------------------------------------------------------------------------
* Function: H5Fget_obj_count
*
* Purpose: Public function returning the number of opened object IDs
* (files, datasets, groups and datatypes) in the same file.
*
* Return: Non-negative on success; negative on failure.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value to ssize_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
ssize_t
H5Fget_obj_count(hid_t file_id, unsigned types)
{
H5F_t *f = NULL; /* File to query */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_obj_count, FAIL)
H5TRACE2("Zs", "iIu", file_id, types);
if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
/* H5F_get_obj_count doesn't fail */
ret_value = (ssize_t)H5F_get_obj_count(f, types, TRUE);
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_obj_count() */
/*-------------------------------------------------------------------------
* Function: H5F_get_obj_count
*
* Purpose: Private function return the number of opened object IDs
* (files, datasets, groups, datatypes) in the same file.
*
* Return: Non-negative on success; can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value to size_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
size_t
H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
{
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_count)
/* H5F_get_objects doesn't fail */
ret_value = H5F_get_objects(f, types, 0, NULL, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5Fget_object_ids
*
* Purpose: Public function to return a list of opened object IDs.
*
* Return: Non-negative on success; negative on failure.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value to ssize_t and MAX_OBJTS to size_t to
* accommadate potential large number of objects.
*
*-------------------------------------------------------------------------
*/
ssize_t
H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
{
H5F_t *f = NULL; /* File to query */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_obj_ids, FAIL)
H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list);
if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
HDassert(oid_list);
/* H5F_get_objects doesn't fail */
ret_value = (ssize_t)H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE);
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_obj_ids() */
/*-------------------------------------------------------------------------
* Function: H5F_get_obj_ids
*
* Purpose: Private function to return a list of opened object IDs.
*
* Return: Non-negative on success; can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
* Raymond Lu
* 24 September 2008
* Changed the return value and MAX_OBJTS to size_t to accommadate
* potential large number of objects.
*
*-------------------------------------------------------------------------
*/
size_t
H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref)
{
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_ids)
/* H5F_get_objects doesn't fail */
ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
/*---------------------------------------------------------------------------
* Function: H5F_get_objects
*
* Purpose: This function is called by H5F_get_obj_count or
* H5F_get_obj_ids to get number of object IDs and/or a
* list of opened object IDs (in return value).
* Return: Non-negative on success; Can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
*---------------------------------------------------------------------------
*/
static size_t
H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref)
{
size_t obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_objects)
/* Set up search information */
olist.obj_id_list = (max_index==0 ? NULL : obj_id_list);
olist.obj_id_count = &obj_id_count;
olist.list_index = 0;
olist.max_index = max_index;
/* Determine if we are searching for local or global objects */
if(types & H5F_OBJ_LOCAL) {
olist.file_info.local = TRUE;
olist.file_info.ptr.file = f;
} /* end if */
else {
olist.file_info.local = FALSE;
olist.file_info.ptr.shared = f ? f->shared : NULL;
} /* end else */
/* Search through file IDs to count the number, and put their
* IDs on the object list. H5I_search returns NULL if no object
* is found, so don't return failure in this function. */
if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
(void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref);
} /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATASET) {
olist.obj_type = H5I_DATASET;
(void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
if(types & H5F_OBJ_GROUP) {
olist.obj_type = H5I_GROUP;
(void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATATYPE) {
olist.obj_type = H5I_DATATYPE;
(void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
if(types & H5F_OBJ_ATTR) {
olist.obj_type = H5I_ATTR;
(void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref);
}
/* Set the number of objects currently open */
ret_value = obj_id_count;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_objects() */
/*-------------------------------------------------------------------------
* Function: H5F_get_objects_cb
*
* Purpose: H5F_get_objects' callback function. It verifies if an
* object is in the file, and either count it or put its ID
* on the list.
*
* Return: TRUE if the array of object IDs is filled up.
* FALSE otherwise.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
*
*-------------------------------------------------------------------------
*/
static int
H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
{
H5F_olist_t *olist = (H5F_olist_t *)key; /* Alias for search info */
int ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_get_objects_cb)
HDassert(obj_ptr);
HDassert(olist);
/* Count file IDs */
if(olist->obj_type == H5I_FILE) {
if((olist->file_info.local &&
(!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) ))
|| (!olist->file_info.local &&
( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) {
/* Add the object's ID to the ID list, if appropriate */
if(olist->obj_id_list) {
olist->obj_id_list[olist->list_index] = obj_id;
olist->list_index++;
}
/* Increment the number of open objects */
if(olist->obj_id_count)
(*olist->obj_id_count)++;
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
* preset to FALSE) because H5I_search needs the return value of FALSE
* to continue searching. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
}
} /* end if */
else { /* either count opened object IDs or put the IDs on the list */
H5O_loc_t *oloc; /* Group entry info for object */
switch(olist->obj_type) {
case H5I_ATTR:
oloc = H5A_oloc((H5A_t *)obj_ptr);
break;
case H5I_GROUP:
oloc = H5G_oloc((H5G_t *)obj_ptr);
break;
case H5I_DATASET:
oloc = H5D_oloc((H5D_t *)obj_ptr);
break;
case H5I_DATATYPE:
if(H5T_is_named((H5T_t*)obj_ptr)==TRUE)
oloc = H5T_oloc((H5T_t*)obj_ptr);
else
oloc = NULL;
break;
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object")
} /* end switch */
if((olist->file_info.local &&
( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
|| (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE)
|| (oloc && oloc->file == olist->file_info.ptr.file)))
|| (!olist->file_info.local &&
((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
|| (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE)
|| (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
/* Add the object's ID to the ID list, if appropriate */
if(olist->obj_id_list) {
olist->obj_id_list[olist->list_index] = obj_id;
olist->list_index++;
} /* end if */
/* Increment the number of open objects */
if(olist->obj_id_count)
(*olist->obj_id_count)++;
/* Check if we've filled up the array. Return TRUE only if
* we have filled up the array. Otherwise return FALSE(RET_VALUE is
* preset to FALSE) because H5I_search needs the return value of FALSE
* to continue searching. */
if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
} /* end if */
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_objects_cb() */
/*-------------------------------------------------------------------------
* Function: H5Fget_vfd_handle
*
* Purpose: Returns a pointer to the file handle of the low-level file
* driver.
*
* Return: Success: non-negative value.
*
* Failture: negative.
*
* Programmer: Raymond Lu
* Sep. 16, 2002
*
* Modification:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_vfd_handle(hid_t file_id, hid_t fapl, void **file_handle)
{
H5F_t *file; /* File to query */
herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_vfd_handle, FAIL)
H5TRACE3("e", "ii**x", file_id, fapl, file_handle);
/* Check args */
if(!file_handle)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file handle pointer")
/* Get the file */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
ret_value = H5F_get_vfd_handle(file, fapl, file_handle);
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_vfd_handle() */
/*-------------------------------------------------------------------------
* Function: H5F_get_vfd_handle
*
* Purpose: Returns a pointer to the file handle of the low-level file
* driver. This is the private function for H5Fget_vfd_handle.
*
* Return: Success: Non-negative.
*
* Failture: negative.
*
* Programmer: Raymond Lu
* Sep. 16, 2002
*
* Modification:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void**file_handle)
{
herr_t ret_value;
FUNC_ENTER_NOAPI_NOINIT(H5F_get_vfd_handle)
assert(file_handle);
if((ret_value=H5FD_get_vfd_handle(file->shared->lf, fapl, file_handle)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file handle for file driver")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5Fis_hdf5
*
* Purpose: Check the file signature to detect an HDF5 file.
*
* Bugs: This function is not robust: it only uses the default file
* driver when attempting to open the file when in fact it
* should use all known file drivers.
*
* Return: Success: TRUE/FALSE
*
* Failure: Negative
*
* Programmer: Unknown
*
* Modifications:
* Robb Matzke, 1999-08-02
* Rewritten to use the virtual file layer.
*-------------------------------------------------------------------------
*/
htri_t
H5Fis_hdf5(const char *name)
{
H5FD_t *file = NULL; /* Low-level file struct */
htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fis_hdf5, FAIL)
H5TRACE1("t", "*s", name);
/* Check args and all the boring stuff. */
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
/* Open the file at the virtual file layer */
if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
/* The file is an hdf5 file if the hdf5 file signature can be found */
ret_value = (HADDR_UNDEF != H5F_locate_signature(file, H5AC_ind_dxpl_id));
done:
/* Close the file */
if(file)
if(H5FD_close(file) < 0 && ret_value >= 0)
HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
FUNC_LEAVE_API(ret_value)
} /* end H5Fis_hdf5() */
/*-------------------------------------------------------------------------
* Function: H5F_new
*
* Purpose: Creates a new file object and initializes it. The
* H5Fopen and H5Fcreate functions then fill in various
* fields. If SHARED is a non-null pointer then the shared info
* to which it points has the reference count incremented.
* Otherwise a new, empty shared info struct is created and
* initialized with the specified file access property list.
*
* Errors:
*
* Return: Success: Ptr to a new file struct.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 18 1997
*
*-------------------------------------------------------------------------
*/
static H5F_t *
H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
{
H5F_t *f = NULL, *ret_value;
FUNC_ENTER_NOAPI_NOINIT(H5F_new)
if(NULL == (f = H5FL_CALLOC(H5F_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
f->file_id = -1;
if(shared) {
HDassert(lf == NULL);
f->shared = shared;
} /* end if */
else {
H5P_genplist_t *plist; /* Property list */
size_t u; /* Local index variable */
HDassert(lf != NULL);
if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
f->shared->sohm_addr = HADDR_UNDEF;
f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
for(u = 0; u < NELMTS(f->shared->fs_addr); u++)
f->shared->fs_addr[u] = HADDR_UNDEF;
f->shared->accum.loc = HADDR_UNDEF;
f->shared->lf = lf;
/*
* Copy the file creation and file access property lists into the
* new file handle. We do this early because some values might need
* to change as the file is being opened.
*/
if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
f->shared->fcpl_id = H5P_copy_plist(plist, FALSE);
/* Get the FCPL values to cache */
if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address")
if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size")
if(H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes")
HDassert(f->shared->sohm_nindexes < 255);
/* Get the FAPL values to cache */
if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots")
if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size")
if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk")
if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME,&(f->shared->gc_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference")
if(H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag")
if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
/* Get the VFD values to cache */
f->shared->maxaddr = H5FD_get_maxaddr(lf);
if(!H5F_addr_defined(f->shared->maxaddr))
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
if(H5MF_init_merge_flags(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
f->shared->tmp_addr = f->shared->maxaddr;
/* Disable temp. space allocation for parallel I/O (for now) */
/* (When we've arranged to have the relocated metadata addresses (and
* sizes) broadcast during the "end of epoch" metadata operations,
* this can be enabled - QAK)
*/
/* (This should be disabled when the metadata journaling branch is
* merged into the trunk and journaling is enabled, at least until
* we make it work. - QAK)
*/
f->shared->use_tmp_space = !(IS_H5FD_MPI(f));
/*
* Create a metadata cache with the specified number of elements.
* The cache might be created with a different number of elements and
* the access property list should be updated to reflect that.
*/
if(SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg)))
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache")
/* Create the file's "open object" information */
if(H5FO_create(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
/* Add new "shared" struct to list of open files */
if(H5F_sfile_add(f->shared) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
} /* end else */
f->shared->nrefs++;
/* Create the file's "top open object" information */
if(H5FO_top_create(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
/* Set return value */
ret_value = f;
done:
if(!ret_value && f) {
if(!shared)
(void)H5FL_FREE(H5F_file_t, f->shared);
(void)H5FL_FREE(H5F_t, f);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_new() */
/*-------------------------------------------------------------------------
* Function: H5F_dest
*
* Purpose: Destroys a file structure. This function flushes the cache
* but doesn't do any other cleanup other than freeing memory
* for the file struct. The shared info for the file is freed
* only when its reference count reaches zero.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 18 1997
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_dest(H5F_t *f, hid_t dxpl_id)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_dest)
/* Sanity check */
HDassert(f);
HDassert(f->shared);
if(1 == f->shared->nrefs) {
/* Flush at this point since the file will be closed */
/* (Only try to flush here if the file structure was successfully
* initialized (i.e., the file struct is being shutdown in an
* orderly manner with the 'closing' flag set)
*/
if(f->closing) {
#if H5AC_DUMP_STATS_ON_CLOSE
/* Dump debugging info */
H5AC_stats(f);
#endif /* H5AC_DUMP_STATS_ON_CLOSE */
/* Shutdown file free space manager(s) */
/* (We should release the free space information now (before truncating
* the file and before the metadata cache is shut down) since the
* free space manager is holding some data structures in memory
* and also because releasing free space can shrink the file's
* 'eoa' value)
*/
if(H5MF_close(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
/* Unpin the superblock, since we're about to destroy the cache */
if(H5AC_unpin_entry(f, f->shared->sblock) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock")
f->shared->sblock = NULL;
} /* end if */
/* Remove shared file struct from list of open files */
if(H5F_sfile_remove(f->shared) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
/* Shutdown the metadata cache */
if(H5AC_dest(f, dxpl_id))
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
/*
* Do not close the root group since we didn't count it, but free
* the memory associated with it.
*/
if(f->shared->root_grp) {
/* Free the ID to name buffer */
if(H5G_free_grp_name(f->shared->root_grp) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
/* Free the memory for the root group */
if(H5G_free(f->shared->root_grp) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
f->shared->root_grp = NULL;
} /* end if */
/* Destroy other components of the file */
if(H5F_accum_reset(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs);
if(H5G_node_close(f) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
/* Destroy file creation properties */
if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
/* Push error, but keep going*/
HDONE_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
if(H5I_dec_ref(f->shared->fcpl_id, FALSE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close property list")
/* Only truncate the file on an orderly close, with write-access */
if(f->closing && (H5F_ACC_RDWR & H5F_INTENT(f))) {
/* Truncate the file to the current allocated size */
if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)TRUE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed")
} /* end if */
/* Close the file */
if(H5FD_close(f->shared->lf) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
/* Free mount table */
f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
f->shared->mtab.nalloc = 0;
/* Destroy shared file struct */
f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
} else if(f->shared->nrefs > 0) {
/*
* There are other references to the shared part of the file.
* Only decrement the reference count.
*/
--f->shared->nrefs;
}
/* Free the non-shared part of the file */
f->name = (char *)H5MM_xfree(f->name);
f->extpath = (char *)H5MM_xfree(f->extpath);
if(H5FO_top_dest(f) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
f->shared = NULL;
(void)H5FL_FREE(H5F_t, f);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_dest() */
/*-------------------------------------------------------------------------
* Function: H5F_open
*
* Purpose: Opens (or creates) a file. This function understands the
* following flags which are similar in nature to the Posix
* open(2) flags.
*
* H5F_ACC_RDWR: Open with read/write access. If the file is
* currently open for read-only access then it
* will be reopened. Absence of this flag
* implies read-only access.
*
* H5F_ACC_CREAT: Create a new file if it doesn't exist yet.
* The permissions are 0666 bit-wise AND with
* the current umask. H5F_ACC_WRITE must also
* be specified.
*
* H5F_ACC_EXCL: This flag causes H5F_open() to fail if the
* file already exists.
*
* H5F_ACC_TRUNC: The file is truncated and a new HDF5 superblock
* is written. This operation will fail if the
* file is already open.
*
* Unlinking the file name from the group directed graph while
* the file is opened causes the file to continue to exist but
* one will not be able to upgrade the file from read-only
* access to read-write access by reopening it. Disk resources
* for the file are released when all handles to the file are
* closed. NOTE: This paragraph probably only applies to Unix;
* deleting the file name in other OS's has undefined results.
*
* The CREATE_PARMS argument is optional. A null pointer will
* cause the default file creation parameters to be used.
*
* The ACCESS_PARMS argument is optional. A null pointer will
* cause the default file access parameters to be used.
*
* Return: Success: A new file pointer.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Tuesday, September 23, 1997
*
*-------------------------------------------------------------------------
*/
H5F_t *
H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id)
{
H5F_t *file = NULL; /*the success return value */
H5F_file_t *shared = NULL; /*shared part of `file' */
H5FD_t *lf = NULL; /*file driver part of `shared' */
unsigned tent_flags; /*tentative flags */
H5FD_class_t *drvr; /*file driver class info */
H5P_genplist_t *a_plist; /*file access property list */
H5F_close_degree_t fc_degree; /*file close degree */
H5F_t *ret_value; /*actual return value */
FUNC_ENTER_NOAPI(H5F_open, NULL)
/*
* If the driver has a `cmp' method then the driver is capable of
* determining when two file handles refer to the same file and the
* library can insure that when the application opens a file twice
* that the two handles coordinate their operations appropriately.
* Otherwise it is the application's responsibility to never open the
* same file more than once at a time.
*/
if((drvr = H5FD_get_class(fapl_id)) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
/*
* Opening a file is a two step process. First we try to open the
* file in a way which doesn't affect its state (like not truncating
* or creating it) so we can compare it with files that are already
* open. If that fails then we try again with the full set of flags
* (only if they're different than the original failed attempt).
* However, if the file driver can't distinquish between files then
* there's no reason to open the file tentatively because it's the
* application's responsibility to prevent this situation (there's no
* way for us to detect it here anyway).
*/
if(drvr->cmp)
tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL);
else
tent_flags = flags;
if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
if(tent_flags == flags)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
H5E_clear_stack(NULL);
tent_flags = flags;
if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
} /* end if */
/* Is the file already open? */
if((shared = H5F_sfile_search(lf)) != NULL) {
/*
* The file is already open, so use that one instead of the one we
* just opened. We only one one H5FD_t* per file so one doesn't
* confuse the other. But fail if this request was to truncate the
* file (since we can't do that while the file is open), or if the
* request was to create a non-existent file (since the file already
* exists), or if the new request adds write access (since the
* readers don't expect the file to change under them).
*/
if(H5FD_close(lf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
if(flags & H5F_ACC_TRUNC)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
if(flags & H5F_ACC_EXCL)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
/* Allocate new "high-level" file struct */
if((file = H5F_new(shared, fcpl_id, fapl_id, NULL)) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
} /* end if */
else {
/* Check if tentative open was good enough */
if(flags != tent_flags) {
/*
* This file is not yet open by the library and the flags we used to
* open it are different than the desired flags. Close the tentative
* file and open it for real.
*/
if(H5FD_close(lf) < 0) {
file = NULL; /*to prevent destruction of wrong file*/
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
} /* end if */
if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) {
file = NULL; /*to prevent destruction of wrong file*/
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
} /* end if */
} /* end if */
if(NULL == (file = H5F_new(NULL, fcpl_id, fapl_id, lf)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
file->shared->flags = flags;
} /* end else */
/* Short cuts */
shared = file->shared;
lf = shared->lf;
/*
* The intent at the top level file struct are not necessarily the same as
* the flags at the bottom. The top level describes how the file can be
* accessed through the HDF5 library. The bottom level describes how the
* file can be accessed through the C library.
*/
file->intent = flags;
file->name = H5MM_xstrdup(name);
/*
* Read or write the file superblock, depending on whether the file is
* empty or not.
*/
if(0 == H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) {
/*
* We've just opened a fresh new file (or truncated one). We need
* to create & write the superblock.
*/
/* Initialize information about the superblock and allocate space for it */
/* (Writes superblock extension messages, if there are any) */
if(H5F_super_init(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock")
/* Create and open the root group */
/* (This must be after the space for the superblock is allocated in
* the file, since the superblock must be at offset 0)
*/
if(H5G_mkroot(file, dxpl_id, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
} else if (1 == shared->nrefs) {
/* Read the superblock if it hasn't been read before. */
if(H5F_super_read(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
/* Open the root group */
if(H5G_mkroot(file, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
} /* end if */
/* Get the file access property list, for future queries */
if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
/*
* Decide the file close degree. If it's the first time to open the
* file, set the degree to access property list value; if it's the
* second time or later, verify the access property list value matches
* the degree in shared file structure.
*/
if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
if(shared->nrefs == 1) {
if(fc_degree == H5F_CLOSE_DEFAULT)
shared->fc_degree = lf->cls->fc_degree;
else
shared->fc_degree = fc_degree;
} else if(shared->nrefs > 1) {
if(fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
if(fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
/* formulate the absolute path for later search of target file for external link */
if (H5_build_extpath(name, &file->extpath) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
/* Success */
ret_value = file;
done:
if(!ret_value && file)
if(H5F_dest(file, dxpl_id) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_open() */
/*-------------------------------------------------------------------------
* Function: H5Fcreate
*
* Purpose: This is the primary function for creating HDF5 files . The
* flags parameter determines whether an existing file will be
* overwritten or not. All newly created files are opened for
* both reading and writing. All flags may be combined with the
* bit-wise OR operator (`|') to change the behavior of the file
* create call.
*
* The more complex behaviors of a file's creation and access
* are controlled through the file-creation and file-access
* property lists. The value of H5P_DEFAULT for a template
* value indicates that the library should use the default
* values for the appropriate template.
*
* See also: H5Fpublic.h for the list of supported flags. H5Ppublic.h for
* the list of file creation and file access properties.
*
* Return: Success: A file ID
*
* Failure: FAIL
*
* Programmer: Unknown
*
*-------------------------------------------------------------------------
*/
hid_t
H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
{
H5F_t *new_file = NULL; /*file struct for new file */
hid_t ret_value; /*return value */
FUNC_ENTER_API(H5Fcreate, FAIL)
H5TRACE4("i", "*sIuii", filename, flags, fcpl_id, fapl_id);
/* Check/fix arguments */
if(!filename || !*filename)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name")
/* In this routine, we only accept the following flags:
* H5F_ACC_EXCL, H5F_ACC_TRUNC and H5F_ACC_DEBUG
*/
if(flags & ~(H5F_ACC_EXCL | H5F_ACC_TRUNC | H5F_ACC_DEBUG))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags")
/* The H5F_ACC_EXCL and H5F_ACC_TRUNC flags are mutually exclusive */
if((flags & H5F_ACC_EXCL) && (flags & H5F_ACC_TRUNC))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mutually exclusive flags for file creation")
/* Check file creation property list */
if(H5P_DEFAULT == fcpl_id)
fcpl_id = H5P_FILE_CREATE_DEFAULT;
else
if(TRUE != H5P_isa_class(fcpl_id, H5P_FILE_CREATE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file create property list")
/* Check the file access property list */
if(H5P_DEFAULT == fapl_id)
fapl_id = H5P_FILE_ACCESS_DEFAULT;
else
if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list")
/*
* Adjust bit flags by turning on the creation bit and making sure that
* the EXCL or TRUNC bit is set. All newly-created files are opened for
* reading and writing.
*/
if (0==(flags & (H5F_ACC_EXCL|H5F_ACC_TRUNC)))
flags |= H5F_ACC_EXCL; /*default*/
flags |= H5F_ACC_RDWR | H5F_ACC_CREAT;
/*
* Create a new file or truncate an existing file.
*/
if(NULL == (new_file = H5F_open(filename, flags, fcpl_id, fapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file")
/* Get an atom for the file */
if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
/* Keep this ID in file object structure */
new_file->file_id = ret_value;
done:
if(ret_value < 0 && new_file)
if(H5F_close(new_file) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
FUNC_LEAVE_API(ret_value)
} /* end H5Fcreate() */
/*-------------------------------------------------------------------------
* Function: H5Fopen
*
* Purpose: This is the primary function for accessing existing HDF5
* files. The FLAGS argument determines whether writing to an
* existing file will be allowed or not. All flags may be
* combined with the bit-wise OR operator (`|') to change the
* behavior of the file open call. The more complex behaviors
* of a file's access are controlled through the file-access
* property list.
*
* See Also: H5Fpublic.h for a list of possible values for FLAGS.
*
* Return: Success: A file ID
*
* Failure: FAIL
*
* Programmer: Unknown
*
* Modifications:
* Robb Matzke, 1997-07-18
* File struct creation and destruction is through H5F_new() and
* H5F_dest(). Reading the root symbol table entry is done with
* H5G_decode().
*
* Robb Matzke, 1997-09-23
* Most of the work is now done by H5F_open() since H5Fcreate()
* and H5Fopen() originally contained almost identical code.
*
* Robb Matzke, 1998-02-18
* Added better error checking for the flags and the file access
* property list. It used to be possible to make the library
* dump core by passing an object ID that was not a file access
* property list.
*
* Robb Matzke, 1999-08-02
* The file access property list is passed to the H5F_open() as
* object IDs.
*-------------------------------------------------------------------------
*/
hid_t
H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
{
H5F_t *new_file = NULL; /*file struct for new file */
hid_t ret_value; /*return value */
FUNC_ENTER_API(H5Fopen, FAIL)
H5TRACE3("i", "*sIui", filename, flags, fapl_id);
/* Check/fix arguments. */
if(!filename || !*filename)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name")
/* Reject undefined flags (~H5F_ACC_PUBLIC_FLAGS) and the H5F_ACC_TRUNC & H5F_ACC_EXCL flags */
if((flags & ~H5F_ACC_PUBLIC_FLAGS) ||
(flags & H5F_ACC_TRUNC) || (flags & H5F_ACC_EXCL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags")
if(H5P_DEFAULT == fapl_id)
fapl_id = H5P_FILE_ACCESS_DEFAULT;
else
if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list")
/* Open the file */
if(NULL == (new_file = H5F_open(filename, flags, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open file")
/* Get an atom for the file */
if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
/* Keep this ID in file object structure */
new_file->file_id = ret_value;
done:
if(ret_value < 0 && new_file && H5F_try_close(new_file) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
FUNC_LEAVE_API(ret_value)
} /* end H5Fopen() */
/*-------------------------------------------------------------------------
* Function: H5Fflush
*
* Purpose: Flushes all outstanding buffers of a file to disk but does
* not remove them from the cache. The OBJECT_ID can be a file,
* dataset, group, attribute, or named data type.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Thursday, August 6, 1998
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fflush(hid_t object_id, H5F_scope_t scope)
{
H5F_t *f = NULL; /* File to flush */
H5O_loc_t *oloc = NULL; /* Object location for ID */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fflush, FAIL)
H5TRACE2("e", "iFs", object_id, scope);
switch(H5I_get_type(object_id)) {
case H5I_FILE:
if(NULL == (f = (H5F_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
break;
case H5I_GROUP:
{
H5G_t *grp;
if(NULL == (grp = (H5G_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier")
oloc = H5G_oloc(grp);
}
break;
case H5I_DATATYPE:
{
H5T_t *type;
if(NULL == (type = (H5T_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier")
oloc = H5T_oloc(type);
}
break;
case H5I_DATASET:
{
H5D_t *dset;
if(NULL == (dset = (H5D_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
oloc = H5D_oloc(dset);
}
break;
case H5I_ATTR:
{
H5A_t *attr;
if(NULL == (attr = (H5A_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier")
oloc = H5A_oloc(attr);
}
break;
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
} /* end switch */
if(!f) {
if(!oloc)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not assocated with a file")
f = oloc->file;
} /* end if */
if(!f)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not associated with a file")
/* Flush the file */
/*
* Nothing to do if the file is read only. This determination is
* made at the shared open(2) flags level, implying that opening a
* file twice, once for read-only and once for read-write, and then
* calling H5Fflush() with the read-only handle, still causes data
* to be flushed.
*/
if(H5F_ACC_RDWR & H5F_INTENT(f)) {
/* Flush other files, depending on scope */
if(H5F_SCOPE_GLOBAL == scope) {
/* Call the flush routine for mounted file hierarchies */
if(H5F_flush_mounts(f, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush mounted file hierarchy")
} /* end if */
else {
/* Call the flush routine, for this file */
if(H5F_flush(f, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
} /* end else */
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fflush() */
/*-------------------------------------------------------------------------
* Function: H5F_flush
*
* Purpose: Flushes cached data.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 29 1997
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_flush(H5F_t *f, hid_t dxpl_id)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_flush, FAIL)
/* Sanity check arguments */
HDassert(f);
/* Flush any cached dataset storage raw data */
if(H5D_flush(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
/* Release any space allocated to space aggregators, so that the eoa value
* corresponds to the end of the space written to in the file.
*/
/* (needs to happen before cache flush, with superblock write, since the
* 'eoa' value is written in superblock -QAK)
*/
if(H5MF_free_aggrs(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space")
/* Flush the entire metadata cache */
if(H5AC_flush(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
/* Flush out the metadata accumulator */
if(H5F_accum_flush(f, dxpl_id) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
/* Flush file buffers to disk. */
if(H5FD_flush(f->shared->lf, dxpl_id, FALSE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_flush() */
/*-------------------------------------------------------------------------
* Function: H5F_close
*
* Purpose: Closes a file or causes the close operation to be pended.
* This function is called two ways: from the API it gets called
* by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref()
* decrements the file ID reference count to zero. The file ID
* is removed from the H5I_FILE group by H5I_dec_ref() just
* before H5F_close() is called. If there are open object
* headers then the close is pended by moving the file to the
* H5I_FILE_CLOSING ID group (the f->closing contains the ID
* assigned to file).
*
* This function is also called directly from H5O_close() when
* the last object header is closed for the file and the file
* has a pending close.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Tuesday, September 23, 1997
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_close(H5F_t *f)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_close)
/* Sanity check */
HDassert(f);
HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
/* Perform checks for "semi" file close degree here, since closing the
* file is not allowed if there are objects still open */
if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
/* Get the number of open objects and open files on this file/mount hierarchy */
if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
/* If there are no other file IDs open on this file/mount hier., but
* there are still open objects, issue an error and bail out now,
* without decrementing the file ID's reference count and triggering
* a "real" attempt at closing the file */
if(nopen_files == 1 && nopen_objs > 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
} /* end if */
/* Reset the file ID for this file */
f->file_id = -1;
/* Attempt to close the file/mount hierarchy */
if(H5F_try_close(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_close() */
/*-------------------------------------------------------------------------
* Function: H5F_try_close
*
* Purpose: Attempts to close a file due to one of several actions:
* - The reference count on the file ID dropped to zero
* - The last open object was closed in the file
* - The file was unmounted
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, July 19, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_try_close(H5F_t *f)
{
unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_try_close)
/* Sanity check */
HDassert(f);
HDassert(f->shared);
/* Check if this file is already in the process of closing */
if(f->closing)
HGOTO_DONE(SUCCEED)
/* Get the number of open objects and open files on this file/mount hierarchy */
if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
/*
* Close file according to close degree:
*
* H5F_CLOSE_WEAK: if there are still objects open, wait until
* they are all closed.
* H5F_CLOSE_SEMI: if there are still objects open, return fail;
* otherwise, close file.
* H5F_CLOSE_STRONG: if there are still objects open, close them
* first, then close file.
*/
switch(f->shared->fc_degree) {
case H5F_CLOSE_WEAK:
/*
* If file or object IDS are still open then delay deletion of
* resources until they have all been closed. Flush all
* caches and update the object header anyway so that failing to
* close all objects isn't a major problem.
*/
if((nopen_files + nopen_objs) > 0)
HGOTO_DONE(SUCCEED)
break;
case H5F_CLOSE_SEMI:
/* Can leave safely if file IDs are still open on this file */
if(nopen_files > 0)
HGOTO_DONE(SUCCEED)
/* Sanity check: If close degree if "semi" and we have gotten this
* far and there are objects left open, bail out now */
HDassert(nopen_files == 0 && nopen_objs == 0);
/* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */
break;
case H5F_CLOSE_STRONG:
/* If there are other open files in the hierarchy, we can leave now */
if(nopen_files > 0)
HGOTO_DONE(SUCCEED)
/* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */
break;
default:
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
} /* end switch */
/* Mark this file as closing (prevents re-entering file shutdown code below) */
f->closing = TRUE;
/* If the file close degree is "strong", close all the open objects in this file */
if(f->shared->fc_degree == H5F_CLOSE_STRONG) {
HDassert(nopen_files == 0);
/* Forced close of all opened objects in this file */
if(f->nopen_objs > 0) {
unsigned obj_count; /* # of open objects */
hid_t objs[128]; /* Array of objects to close */
unsigned u; /* Local index variable */
/* Get the list of IDs of open dataset, group, & attribute objects */
while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u], FALSE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
/* Get the list of IDs of open named datatype objects */
/* (Do this separately from the dataset & attribute IDs, because
* they could be using one of the named datatypes and then the
* open named datatype ID will get closed twice)
*/
while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u], FALSE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
} /* end if */
} /* end if */
/* Check if this is a child file in a mounting hierarchy & proceed up the
* hierarchy if so.
*/
if(f->parent)
if(H5F_try_close(f->parent) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
/* Unmount and close each child before closing the current file. */
if(H5F_close_mounts(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
/* Flush at this point since the file will be closed. Don't invalidate
* the cache, since this file might still be open using another handle.
* However, make sure we flush in case that handle is read-only; its
* copy of the cache needs to be clean.
* Only try to flush the file if it was opened with write access.
*/
if(f->intent & H5F_ACC_RDWR) {
/* Flush all caches */
if(H5F_flush(f, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
} /* end if */
/*
* Destroy the H5F_t struct and decrement the reference count for the
* shared H5F_file_t struct. If the reference count for the H5F_file_t
* struct reaches zero then destroy it also.
*/
if(H5F_dest(f, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_try_close() */
/*-------------------------------------------------------------------------
* Function: H5Fclose
*
* Purpose: This function closes the file specified by FILE_ID by
* flushing all data to storage, and terminating access to the
* file through FILE_ID. If objects (e.g., datasets, groups,
* etc.) are open in the file then the underlying storage is not
* closed until those objects are closed; however, all data for
* the file and the open objects is flushed.
*
* Return: Success: Non-negative
*
* Failure: Negative
*
* Programmer: Robb Matzke
* Saturday, February 20, 1999
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fclose(hid_t file_id)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fclose, FAIL)
H5TRACE1("e", "i", file_id);
/* Check/fix arguments. */
if(H5I_FILE != H5I_get_type(file_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID")
/*
* Decrement reference count on atom. When it reaches zero the file will
* be closed.
*/
if(H5I_dec_ref(file_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fclose() */
/*-------------------------------------------------------------------------
* Function: H5Freopen
*
* Purpose: Reopen a file. The new file handle which is returned points
* to the same file as the specified file handle. Both handles
* share caches and other information. The only difference
* between the handles is that the new handle is not mounted
* anywhere and no files are mounted on it.
*
* Return: Success: New file ID
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 16, 1998
*
* Modifications:
* Quincey Koziol, May 14, 2002
* Keep old file's read/write intent in reopened file.
*
*-------------------------------------------------------------------------
*/
hid_t
H5Freopen(hid_t file_id)
{
H5F_t *old_file = NULL;
H5F_t *new_file = NULL;
hid_t ret_value;
FUNC_ENTER_API(H5Freopen, FAIL)
H5TRACE1("i", "i", file_id);
/* Check arguments */
if(NULL == (old_file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Get a new "top level" file struct, sharing the same "low level" file struct */
if(NULL == (new_file = H5F_new(old_file->shared, H5P_FILE_CREATE_DEFAULT, H5P_FILE_ACCESS_DEFAULT, NULL)))
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to reopen file")
/* Keep old file's read/write intent in new file */
new_file->intent = old_file->intent;
/* Duplicate old file's name */
new_file->name = H5MM_xstrdup(old_file->name);
if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
/* Keep this ID in file object structure */
new_file->file_id = ret_value;
done:
if(ret_value < 0 && new_file)
if(H5F_dest(new_file, H5AC_dxpl_id) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
FUNC_LEAVE_API(ret_value)
} /* end H5Freopen() */
/*-------------------------------------------------------------------------
* Function: H5Fget_intent
*
* Purpose: Public API to retrieve the file's 'intent' flags passed
* during H5Fopen()
*
* Return: Non-negative on success/negative on failure
*
* Programmer: James Laird
* August 23, 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_intent(hid_t file_id, unsigned *intent_flags)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fget_intent, FAIL)
H5TRACE2("e", "i*Iu", file_id, intent_flags);
/* If no intent flags were passed in, exit quietly */
if(intent_flags) {
H5F_t * file; /* Pointer to file structure */
/* Get the internal file structure */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* HDF5 uses some flags internally that users don't know about.
* Simplify things for them so that they only get either H5F_ACC_RDWR
* or H5F_ACC_RDONLY.
*/
if(H5F_INTENT(file) & H5F_ACC_RDWR)
*intent_flags = H5F_ACC_RDWR;
else
*intent_flags = H5F_ACC_RDONLY;
} /* end if */
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_intent() */
/*-------------------------------------------------------------------------
* Function: H5F_get_id
*
* Purpose: Get the file ID, incrementing it, or "resurrecting" it as
* appropriate.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Raymond Lu
* Oct 29, 2003
*
*-------------------------------------------------------------------------
*/
hid_t
H5F_get_id(H5F_t *file, hbool_t app_ref)
{
hid_t ret_value;
FUNC_ENTER_NOAPI_NOINIT(H5F_get_id)
HDassert(file);
if(file->file_id == -1) {
/* Get an atom for the file */
if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
} else {
/* Increment reference count on atom. */
if(H5I_inc_ref(file->file_id, app_ref) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
} /* end else */
ret_value = file->file_id;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_id() */
/*-------------------------------------------------------------------------
* Function: H5F_get_eoa
*
* Purpose: Quick and dirty routine to retrieve the file's 'eoa' value
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* June 1, 2004
*
*-------------------------------------------------------------------------
*/
haddr_t
H5F_get_eoa(const H5F_t *f, H5FD_mem_t type)
{
haddr_t ret_value;
FUNC_ENTER_NOAPI(H5F_get_eoa, HADDR_UNDEF)
HDassert(f);
HDassert(f->shared);
/* Dispatch to driver */
if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f->shared->lf, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_eoa() */
/*-------------------------------------------------------------------------
* Function: H5F_incr_nopen_objs
*
* Purpose: Increment the number of open objects for a file.
*
* Return: Success: The number of open objects, after the increment
*
* Failure: (can't happen)
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Mar 6 2007
*
*-------------------------------------------------------------------------
*/
unsigned
H5F_incr_nopen_objs(H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_incr_nopen_objs)
HDassert(f);
FUNC_LEAVE_NOAPI(++f->nopen_objs)
} /* end H5F_incr_nopen_objs() */
/*-------------------------------------------------------------------------
* Function: H5F_decr_nopen_objs
*
* Purpose: Decrement the number of open objects for a file.
*
* Return: Success: The number of open objects, after the decrement
*
* Failure: (can't happen)
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Mar 6 2007
*
*-------------------------------------------------------------------------
*/
unsigned
H5F_decr_nopen_objs(H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_decr_nopen_objs)
HDassert(f);
FUNC_LEAVE_NOAPI(--f->nopen_objs)
} /* end H5F_decr_nopen_objs() */
/*-------------------------------------------------------------------------
* Function: H5F_addr_encode_len
*
* Purpose: Encodes an address into the buffer pointed to by *PP and
* then increments the pointer to the first byte after the
* address. An undefined value is stored as all 1's.
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, November 7, 1997
*
*-------------------------------------------------------------------------
*/
void
H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr)
{
unsigned u; /* Local index variable */
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_addr_encode_len)
HDassert(addr_len);
HDassert(pp && *pp);
if(H5F_addr_defined(addr)) {
for(u = 0; u < addr_len; u++) {
*(*pp)++ = (uint8_t)(addr & 0xff);
addr >>= 8;
} /* end for */
HDassert("overflow" && 0 == addr);
} /* end if */
else {
for(u = 0; u < addr_len; u++)
*(*pp)++ = 0xff;
} /* end else */
FUNC_LEAVE_NOAPI_VOID
} /* end H5F_addr_encode_len() */
/*-------------------------------------------------------------------------
* Function: H5F_addr_encode
*
* Purpose: Encodes an address into the buffer pointed to by *PP and
* then increments the pointer to the first byte after the
* address. An undefined value is stored as all 1's.
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, November 7, 1997
*
*-------------------------------------------------------------------------
*/
void
H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_addr_encode)
HDassert(f);
H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr);
FUNC_LEAVE_NOAPI_VOID
} /* end H5F_addr_encode() */
/*-------------------------------------------------------------------------
* Function: H5F_addr_decode_len
*
* Purpose: Decodes an address from the buffer pointed to by *PP and
* updates the pointer to point to the next byte after the
* address.
*
* If the value read is all 1's then the address is returned
* with an undefined value.
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, November 7, 1997
*
*-------------------------------------------------------------------------
*/
void
H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
{
hbool_t all_zero = TRUE; /* True if address was all zeroes */
unsigned u; /* Local index variable */
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_addr_decode_len)
HDassert(addr_len);
HDassert(pp && *pp);
HDassert(addr_p);
/* Reset value in destination */
*addr_p = 0;
/* Decode bytes from address */
for(u = 0; u < addr_len; u++) {
uint8_t c; /* Local decoded byte */
/* Get decoded byte (and advance pointer) */
c = *(*pp)++;
/* Check for non-undefined address byte value */
if(c != 0xff)
all_zero = FALSE;
if(u < sizeof(*addr_p)) {
haddr_t tmp = c; /* Local copy of address, for casting */
/* Shift decoded byte to correct position */
tmp <<= (u * 8); /*use tmp to get casting right */
/* Merge into already decoded bytes */
*addr_p |= tmp;
} /* end if */
else
if(!all_zero)
HDassert(0 == **pp); /*overflow */
} /* end for */
/* If 'all_zero' is still TRUE, the address was entirely composed of '0xff'
* bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination
* to that value */
if(all_zero)
*addr_p = HADDR_UNDEF;
FUNC_LEAVE_NOAPI_VOID
} /* end H5F_addr_decode_len() */
/*-------------------------------------------------------------------------
* Function: H5F_addr_decode
*
* Purpose: Decodes an address from the buffer pointed to by *PP and
* updates the pointer to point to the next byte after the
* address.
*
* If the value read is all 1's then the address is returned
* with an undefined value.
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, November 7, 1997
*
*-------------------------------------------------------------------------
*/
void
H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_addr_decode)
HDassert(f);
H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p);
FUNC_LEAVE_NOAPI_VOID
} /* end H5F_addr_decode() */
/*-------------------------------------------------------------------------
* Function: H5Fget_freespace
*
* Purpose: Retrieves the amount of free space in the file.
*
* Return: Success: Amount of free space for type
* Failure: Negative
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Oct 6, 2003
*
*-------------------------------------------------------------------------
*/
hssize_t
H5Fget_freespace(hid_t file_id)
{
H5F_t *file; /* File object for file ID */
hsize_t tot_space; /* Amount of free space in the file */
hssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_freespace, FAIL)
H5TRACE1("Hs", "i", file_id);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual amount of free space in the file */
if(H5MF_get_freespace(file, H5AC_ind_dxpl_id, &tot_space, NULL) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
ret_value = (hssize_t)tot_space;
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_freespace() */
/*-------------------------------------------------------------------------
* Function: H5Fget_filesize
*
* Purpose: Retrieves the file size of the HDF5 file. This function
* is called after an existing file is opened in order
* to learn the true size of the underlying file.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: David Pitt
* david.pitt@bigpond.com
* Apr 27, 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_filesize(hid_t file_id, hsize_t *size)
{
H5F_t *file; /* File object for file ID */
haddr_t eof; /* End of file address */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_filesize, FAIL)
H5TRACE2("e", "i*h", file_id, size);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual file size */
if(HADDR_UNDEF == (eof = H5FDget_eof(file->shared->lf)))
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
*size = (hsize_t)eof;
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_filesize() */
/*-------------------------------------------------------------------------
* Function: H5Fget_mdc_config
*
* Purpose: Retrieves the current automatic cache resize configuration
* from the metadata cache, and return it in *config_ptr.
*
* Note that the version field of *config_Ptr must be correctly
* filled in by the caller. This allows us to adapt for
* obsolete versions of the structure.
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* 3/24/05
*
* Modifications:
*
* Reworked for the addition of the config_ptr parameter.
* JRM -- 4/7/05
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_mdc_config(hid_t file_id,
H5AC_cache_config_t *config_ptr)
{
H5F_t *file; /* File object for file ID */
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_config, FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
if((NULL == config_ptr) || (config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad config_ptr")
/* Go get the resize configuration */
result = H5AC_get_cache_auto_resize_config(file->shared->cache, config_ptr);
if ( result != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"H5AC_get_cache_auto_resize_config() failed.");
}
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_mdc_config() */
/*-------------------------------------------------------------------------
* Function: H5Fset_mdc_config
*
* Purpose: Sets the current metadata cache automatic resize
* configuration, using the contents of the instance of
* H5AC_cache_config_t pointed to by config_ptr.
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* 3/24/05
*
* Modifications:
*
* None.
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fset_mdc_config(hid_t file_id,
H5AC_cache_config_t *config_ptr)
{
H5F_t *file; /* File object for file ID */
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fset_mdc_config, FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* set the resize configuration */
result = H5AC_set_cache_auto_resize_config(file->shared->cache, config_ptr);
if ( result != SUCCEED ) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
"H5AC_set_cache_auto_resize_config() failed.");
}
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fset_mdc_config() */
/*-------------------------------------------------------------------------
* Function: H5Fget_mdc_hit_rate
*
* Purpose: Retrieves the current hit rate from the metadata cache.
* This rate is the overall hit rate since the last time
* the hit rate statistics were reset either manually or
* automatically.
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* 3/24/05
*
* Modifications:
*
* None.
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_mdc_hit_rate(hid_t file_id,
double *hit_rate_ptr)
{
H5F_t *file; /* File object for file ID */
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_hit_rate, FAIL)
H5TRACE2("e", "i*d", file_id, hit_rate_ptr);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
if(NULL == hit_rate_ptr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL hit rate pointer")
/* Go get the current hit rate */
result = H5AC_get_cache_hit_rate(file->shared->cache, hit_rate_ptr);
if ( result != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"H5AC_get_cache_hit_rate() failed.");
}
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_mdc_hit_rate() */
/*-------------------------------------------------------------------------
* Function: H5Fget_mdc_size
*
* Purpose: Retrieves the maximum size, minimum clean size, current
* size, and current number of entries from the metadata
* cache associated with the specified file. If any of
* the ptr parameters are NULL, the associated datum is
* not returned.
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* 3/24/05
*
* Modifications:
*
* None.
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_mdc_size(hid_t file_id,
size_t *max_size_ptr,
size_t *min_clean_size_ptr,
size_t *cur_size_ptr,
int *cur_num_entries_ptr)
{
H5F_t *file; /* File object for file ID */
int32_t cur_num_entries;
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_size, FAIL)
H5TRACE5("e", "i*z*z*z*Is", file_id, max_size_ptr, min_clean_size_ptr,
cur_size_ptr, cur_num_entries_ptr);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the size data */
result = H5AC_get_cache_size(file->shared->cache,
max_size_ptr,
min_clean_size_ptr,
cur_size_ptr,
&cur_num_entries);
if ( result != SUCCEED ) {
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
"H5AC_get_cache_size() failed.");
} else if ( cur_num_entries_ptr != NULL ) {
*cur_num_entries_ptr = (int)cur_num_entries;
}
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_mdc_size() */
/*-------------------------------------------------------------------------
* Function: H5Freset_mdc_hit_rate_stats
*
* Purpose: Reset the hit rate statistic whose current value can
* be obtained via the H5Fget_mdc_hit_rate() call. Note
* that this statistic will also be reset once per epoch
* by the automatic cache resize code if it is enabled.
*
* It is probably a bad idea to call this function unless
* you are controlling cache size from your program instead
* of using our cache size control code.
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
* 3/24/05
*
* Modifications:
*
* None.
*
*-------------------------------------------------------------------------
*/
herr_t
H5Freset_mdc_hit_rate_stats(hid_t file_id)
{
H5F_t *file; /* File object for file ID */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Freset_mdc_hit_rate_stats, FAIL)
H5TRACE1("e", "i", file_id);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Reset the hit rate statistic */
if(H5AC_reset_cache_hit_rate_stats(file->shared->cache) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't reset cache hit rate")
done:
FUNC_LEAVE_API(ret_value)
} /* H5Freset_mdc_hit_rate_stats() */
/*-------------------------------------------------------------------------
* Function: H5Fget_name
*
* Purpose: Gets the name of the file to which object OBJ_ID belongs.
* If `name' is non-NULL then write up to `size' bytes into that
* buffer and always return the length of the entry name.
* Otherwise `size' is ignored and the function does not store the name,
* just returning the number of characters required to store the name.
* If an error occurs then the buffer pointed to by `name' (NULL or non-NULL)
* is unchanged and the function returns a negative value.
*
* Return: Success: The length of the file name
* Failure: Negative
*
* Programmer: Raymond Lu
* June 29, 2004
*
*-------------------------------------------------------------------------
*/
ssize_t
H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
{
H5F_t *f; /* Top file in mount hierarchy */
size_t len;
ssize_t ret_value;
FUNC_ENTER_API (H5Fget_name, FAIL)
H5TRACE3("Zs", "ixz", obj_id, name, size);
/* For file IDs, get the file object directly */
/* (This prevents the H5G_loc() call from returning the file pointer for
* the top file in a mount hierarchy)
*/
if(H5I_get_type(obj_id) == H5I_FILE ) {
if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
} /* end if */
else {
H5G_loc_t loc; /* Object location */
/* Get symbol table entry */
if(H5G_loc(obj_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
f = loc.oloc->file;
} /* end else */
len = HDstrlen(f->name);
if(name) {
HDstrncpy(name, f->name, MIN(len+1,size));
if(len >= size)
name[size-1]='\0';
} /* end if */
/* Set return value */
ret_value = (ssize_t)len;
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_name() */
/*-------------------------------------------------------------------------
* Function: H5Fget_info
* 1. Get storage size for superblock extension if there is one
* 2. Get the amount of btree and heap storage for entries
* in the SOHM table if there is one.
* Consider success when there is no superblock extension and/or SOHM table
*
* Return: Success: non-negative on success
* Failure: Negative
*
* Programmer: Vailin Choi
* July 11, 2007
*
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_info(hid_t obj_id, H5F_info_t *finfo)
{
H5F_t *f; /* Top file in mount hierarchy */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_info, FAIL)
H5TRACE2("e", "i*x", obj_id, finfo);
/* Check args */
if(!finfo)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
/* For file IDs, get the file object directly */
/* (This prevents the H5G_loc() call from returning the file pointer for
* the top file in a mount hierarchy)
*/
if(H5I_get_type(obj_id) == H5I_FILE ) {
if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
} /* end if */
else {
H5G_loc_t loc; /* Object location */
/* Get symbol table entry */
if(H5G_loc(obj_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
f = loc.oloc->file;
} /* end else */
HDassert(f->shared);
/* Reset file info struct */
HDmemset(finfo, 0, sizeof(H5F_info_t));
/* Check for superblock extension info */
if(H5F_super_size(f, H5AC_ind_dxpl_id, NULL, &finfo->super_ext_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "Unable to retrieve superblock extension size")
/* Check for SOHM info */
if(H5F_addr_defined(f->shared->sohm_addr))
if(H5SM_ih_size(f, H5AC_ind_dxpl_id, finfo) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "Unable to retrieve SOHM btree & heap storage info")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_info() */