mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-04-12 17:31:09 +08:00
Purpose: Feature Description: Datatypes and groups now use H5FO "file object" code that was previously only used by datasets. These objects will hold a file open if the file is closed but they have not yet been closed. If these objects are unlinked then relinked, they will not be destroyed. If they are opened twice (even by two different names), both IDs will "see" changes made to the object using the other ID. When an object is opened using two different names (e.g., if a dataset was opened under one name, then mounted and opened under its new name), calling H5Iget_name() on a given hid_t will return the name used to open that hid_t, not the current name of the object (this is a feature, and a change from the previous behavior of datasets). Solution: Used H5FO code that was already in place for datasets. Broke H5D_t's, H5T_t's, and H5G_t's into a "shared" struct and a private struct. The shared structs (H5D_shared_t, etc.) hold the object's information and are used by all IDs that point to a given object in the file. The private structs are pointed to by the hid_t and contain the object's group entry information (including its name) and a pointer to the shared struct for that object. This changed the naming of structs throughout the library (e.g., datatype->size is now datatype->shared->size). I added an updated H5Tinit.c to windows.zip. Platforms tested: Visual Studio 7, sleipnir, arabica, verbena Misc. update:
4809 lines
168 KiB
C
4809 lines
168 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
|
||
|
||
/* Interface initialization */
|
||
#define H5_INTERFACE_INIT_FUNC H5F_init_interface
|
||
|
||
/* Pablo information */
|
||
/* (Put before include files to avoid problems with inline functions) */
|
||
#define PABLO_MASK H5F_mask
|
||
|
||
/* 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 "H5FLprivate.h" /* Free lists */
|
||
#include "H5FPprivate.h" /* Flexible parallel */
|
||
#include "H5Iprivate.h" /* IDs */
|
||
#include "H5Gprivate.h" /* Groups */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
#include "H5Pprivate.h" /* Property lists */
|
||
#include "H5Tprivate.h" /* Datatypes */
|
||
|
||
/* Predefined file drivers */
|
||
#include "H5FDcore.h" /*temporary in-memory files */
|
||
#include "H5FDfamily.h" /*family of files */
|
||
#include "H5FDgass.h" /*GASS I/O */
|
||
#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 "H5FDsrb.h" /*SRB I/O */
|
||
#include "H5FDstdio.h" /* Standard C buffered I/O */
|
||
#include "H5FDstream.h" /*in-memory files streamed via sockets */
|
||
|
||
/* 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 */
|
||
unsigned *obj_id_count; /* Number of open IDs */
|
||
H5F_file_t *shared; /* Pointer to file to look inside */
|
||
unsigned list_index; /* Current index in open ID array */
|
||
int max_index; /* Maximum # of IDs to put into array */
|
||
} H5F_olist_t;
|
||
|
||
/* PRIVATE PROTOTYPES */
|
||
static H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id,
|
||
hid_t fapl_id, hid_t dxpl_id);
|
||
static herr_t H5F_close(H5F_t *f);
|
||
|
||
#ifdef NOT_YET
|
||
static herr_t H5F_flush_all(hbool_t invalidate);
|
||
static int H5F_flush_all_cb(void *f, hid_t fid, void *_invalidate);
|
||
#endif /* NOT_YET */
|
||
|
||
static hsize_t H5F_init_superblock(H5F_t *f, hid_t dxpl_id);
|
||
static herr_t H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf);
|
||
static herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size);
|
||
|
||
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id);
|
||
static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id);
|
||
static herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags);
|
||
static haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id);
|
||
static int H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
|
||
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);
|
||
|
||
/* Declare a free list to manage the H5F_t struct */
|
||
H5FL_DEFINE_STATIC(H5F_t);
|
||
|
||
/* Declare a free list to manage the H5F_file_t struct */
|
||
H5FL_DEFINE_STATIC(H5F_file_t);
|
||
|
||
/* Declare the external free list for the H5G_t struct */
|
||
H5FL_EXTERN(H5G_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
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_init_interface
|
||
*
|
||
* Purpose: Initialize interface-specific information.
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, November 20, 1998
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 4 Aug 1997
|
||
* Changed pablo mask from H5_mask to H5F_mask for the FUNC_LEAVE call.
|
||
* It was already H5F_mask for the PABLO_TRACE_ON call.
|
||
*
|
||
* Kim Yates, 1998-08-16
|
||
* Added .disp, .btype, .ftype to H5F_access_t.
|
||
*
|
||
* Robb Matzke, 1999-02-19
|
||
* Added initialization for the H5I_FILE_CLOSING ID group.
|
||
*
|
||
* Raymond Lu, April 10, 2000
|
||
* Put SRB into the 'Register predefined file drivers' list.
|
||
*
|
||
* Thomas Radke, 2000-09-12
|
||
* Put Stream VFD into the 'Register predefined file drivers' list.
|
||
*
|
||
* Raymond Lu, 2001-10-14
|
||
* Change File creation property list to generic property list mechanism.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_init_interface(void)
|
||
{
|
||
size_t nprops; /* Number of properties */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
/* File creation property class variables. In sequence, they are
|
||
* - File create property list class to modify
|
||
* - Default value for size of file user block
|
||
* - Default value for 1/2 rank for symbol table leaf nodes
|
||
* - Default value for 1/2 rank for btree internal nodes
|
||
* - Default value for byte number in an address
|
||
* - Default value for byte number for object size
|
||
* - Default value for version number of superblock
|
||
* - Default value for free-space version number
|
||
* - Default value for object directory version number
|
||
* - Default value for share-header format version
|
||
*/
|
||
H5P_genclass_t *crt_pclass;
|
||
hsize_t userblock_size = H5F_CRT_USER_BLOCK_DEF;
|
||
unsigned sym_leaf_k = H5F_CRT_SYM_LEAF_DEF;
|
||
unsigned btree_k[H5B_NUM_BTREE_ID] = H5F_CRT_BTREE_RANK_DEF;
|
||
size_t sizeof_addr = H5F_CRT_ADDR_BYTE_NUM_DEF;
|
||
size_t sizeof_size = H5F_CRT_OBJ_BYTE_NUM_DEF;
|
||
unsigned superblock_ver = H5F_CRT_SUPER_VERS_DEF;
|
||
unsigned freespace_ver = H5F_CRT_FREESPACE_VERS_DEF;
|
||
unsigned objectdir_ver = H5F_CRT_OBJ_DIR_VERS_DEF;
|
||
unsigned sharedheader_ver = H5F_CRT_SHARE_HEAD_VERS_DEF;
|
||
/* File access property class variables. In sequence, they are
|
||
* - File access property class to modify
|
||
* - Size of meta data cache(elements)
|
||
* - Size of raw data chunk cache(elements)
|
||
* - Size of raw data chunk cache(bytes)
|
||
* - Preemption for reading chunks
|
||
* - Threshold for alignment
|
||
* - Alignment
|
||
* - Minimum metadata allocation block size
|
||
* - Maximum sieve buffer size
|
||
* - Garbage-collect reference
|
||
* - File driver ID
|
||
* - File driver info
|
||
*/
|
||
H5P_genclass_t *acs_pclass;
|
||
int mdc_nelmts = H5F_ACS_META_CACHE_SIZE_DEF;
|
||
size_t rdcc_nelmts = H5F_ACS_DATA_CACHE_ELMT_SIZE_DEF;
|
||
size_t rdcc_nbytes = H5F_ACS_DATA_CACHE_BYTE_SIZE_DEF;
|
||
double rdcc_w0 = H5F_ACS_PREEMPT_READ_CHUNKS_DEF;
|
||
hsize_t threshold = H5F_ACS_ALIGN_THRHD_DEF;
|
||
hsize_t alignment = H5F_ACS_ALIGN_DEF;
|
||
hsize_t meta_block_size = H5F_ACS_META_BLOCK_SIZE_DEF;
|
||
size_t sieve_buf_size = H5F_ACS_SIEVE_BUF_SIZE_DEF;
|
||
hsize_t sdata_block_size = H5F_ACS_SDATA_BLOCK_SIZE_DEF;
|
||
unsigned gc_ref = H5F_ACS_GARBG_COLCT_REF_DEF;
|
||
hid_t driver_id = H5F_ACS_FILE_DRV_ID_DEF;
|
||
void *driver_info = H5F_ACS_FILE_DRV_INFO_DEF;
|
||
H5F_close_degree_t close_degree = H5F_CLOSE_DEGREE_DEF;
|
||
hsize_t family_offset = H5F_ACS_FAMILY_OFFSET_DEF;
|
||
H5FD_mem_t mem_type = H5F_ACS_MULTI_TYPE_DEF;
|
||
|
||
/* File mount property class variable.
|
||
* - Mount property class to modify
|
||
* - whether absolute symlinks is local to file
|
||
*/
|
||
H5P_genclass_t *mnt_pclass;
|
||
hbool_t local = H5F_MNT_SYM_LOCAL_DEF;
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_init_interface)
|
||
|
||
/*
|
||
* Initialize the atom group for the file IDs. There are two groups:
|
||
* the H5I_FILE group contains all the ID's for files which are currently
|
||
* open at the public API level while the H5I_FILE_CLOSING group contains
|
||
* ID's for files for which the application has called H5Fclose() but
|
||
* which are pending completion because there are object headers still
|
||
* open within the file.
|
||
*/
|
||
if (H5I_register_type(H5I_FILE, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0 ||
|
||
H5I_register_type(H5I_FILE_CLOSING, H5I_FILEID_HASHSIZE, 0, (H5I_free_t)H5F_close)<0)
|
||
HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
|
||
|
||
/* ========== File Creation Property Class Initialization ============*/
|
||
assert(H5P_CLS_FILE_CREATE_g!=-1);
|
||
|
||
/* Get the pointer to file creation class */
|
||
if(NULL == (crt_pclass = H5I_object(H5P_CLS_FILE_CREATE_g)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
|
||
|
||
/* Get the number of properties in the class */
|
||
if(H5P_get_nprops_pclass(crt_pclass,&nprops)<0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties")
|
||
|
||
/* Assume that if there are properties in the class, they are the default ones */
|
||
if(nprops==0) {
|
||
/* Register the user block size */
|
||
if(H5P_register(crt_pclass,H5F_CRT_USER_BLOCK_NAME,H5F_CRT_USER_BLOCK_SIZE, &userblock_size,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the 1/2 rank for symbol table leaf nodes */
|
||
if(H5P_register(crt_pclass,H5F_CRT_SYM_LEAF_NAME,H5F_CRT_SYM_LEAF_SIZE, &sym_leaf_k,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the 1/2 rank for btree internal nodes */
|
||
if(H5P_register(crt_pclass,H5F_CRT_BTREE_RANK_NAME,H5F_CRT_BTREE_RANK_SIZE, btree_k,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the byte number for an address */
|
||
if(H5P_register(crt_pclass,H5F_CRT_ADDR_BYTE_NUM_NAME, H5F_CRT_ADDR_BYTE_NUM_SIZE, &sizeof_addr,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the byte number for object size */
|
||
if(H5P_register(crt_pclass,H5F_CRT_OBJ_BYTE_NUM_NAME, H5F_CRT_OBJ_BYTE_NUM_SIZE,&sizeof_size,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the superblock version number */
|
||
if(H5P_register(crt_pclass,H5F_CRT_SUPER_VERS_NAME,H5F_CRT_SUPER_VERS_SIZE, &superblock_ver,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the free-space version number */
|
||
if(H5P_register(crt_pclass,H5F_CRT_FREESPACE_VERS_NAME, H5F_CRT_FREESPACE_VERS_SIZE,&freespace_ver,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the object directory version number */
|
||
if(H5P_register(crt_pclass,H5F_CRT_OBJ_DIR_VERS_NAME, H5F_CRT_OBJ_DIR_VERS_SIZE,&objectdir_ver,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the shared-header version number */
|
||
if(H5P_register(crt_pclass,H5F_CRT_SHARE_HEAD_VERS_NAME, H5F_CRT_SHARE_HEAD_VERS_SIZE, &sharedheader_ver,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
/* Only register the default property list if it hasn't been created yet */
|
||
if(H5P_LST_FILE_CREATE_g==(-1)) {
|
||
/* Register the default file creation property list */
|
||
if((H5P_LST_FILE_CREATE_g = H5P_create_id(crt_pclass))<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
/* ========== File Access Property Class Initialization ============*/
|
||
assert(H5P_CLS_FILE_ACCESS_g!=-1);
|
||
|
||
/* Get the pointer to file creation class */
|
||
if(NULL == (acs_pclass = H5I_object(H5P_CLS_FILE_ACCESS_g)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
|
||
|
||
/* Get the number of properties in the class */
|
||
if(H5P_get_nprops_pclass(acs_pclass,&nprops)<0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties")
|
||
|
||
/* Assume that if there are properties in the class, they are the default ones */
|
||
if(nprops==0) {
|
||
/* Register the size of meta data cache(elements) */
|
||
if(H5P_register(acs_pclass,H5F_ACS_META_CACHE_SIZE_NAME,H5F_ACS_META_CACHE_SIZE_SIZE, &mdc_nelmts,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the size of raw data chunk cache (elements) */
|
||
if(H5P_register(acs_pclass,H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME,H5F_ACS_DATA_CACHE_ELMT_SIZE_SIZE, &rdcc_nelmts,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the size of raw data chunk cache(bytes) */
|
||
if(H5P_register(acs_pclass,H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME,H5F_ACS_DATA_CACHE_BYTE_SIZE_SIZE, &rdcc_nbytes,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the preemption for reading chunks */
|
||
if(H5P_register(acs_pclass,H5F_ACS_PREEMPT_READ_CHUNKS_NAME,H5F_ACS_PREEMPT_READ_CHUNKS_SIZE, &rdcc_w0,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the threshold for alignment */
|
||
if(H5P_register(acs_pclass,H5F_ACS_ALIGN_THRHD_NAME,H5F_ACS_ALIGN_THRHD_SIZE, &threshold,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the alignment */
|
||
if(H5P_register(acs_pclass,H5F_ACS_ALIGN_NAME,H5F_ACS_ALIGN_SIZE, &alignment,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the minimum metadata allocation block size */
|
||
if(H5P_register(acs_pclass,H5F_ACS_META_BLOCK_SIZE_NAME,H5F_ACS_META_BLOCK_SIZE_SIZE, &meta_block_size,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the maximum sieve buffer size */
|
||
if(H5P_register(acs_pclass,H5F_ACS_SIEVE_BUF_SIZE_NAME,H5F_ACS_SIEVE_BUF_SIZE_SIZE, &sieve_buf_size,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the minimum "small data" allocation block size */
|
||
if(H5P_register(acs_pclass,H5F_ACS_SDATA_BLOCK_SIZE_NAME,H5F_ACS_SDATA_BLOCK_SIZE_SIZE, &sdata_block_size,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the garbage collection reference */
|
||
if(H5P_register(acs_pclass,H5F_ACS_GARBG_COLCT_REF_NAME,H5F_ACS_GARBG_COLCT_REF_SIZE, &gc_ref,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the file driver ID */
|
||
if(H5P_register(acs_pclass,H5F_ACS_FILE_DRV_ID_NAME,H5F_ACS_FILE_DRV_ID_SIZE, &driver_id,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the file driver info */
|
||
if(H5P_register(acs_pclass,H5F_ACS_FILE_DRV_INFO_NAME,H5F_ACS_FILE_DRV_INFO_SIZE, &driver_info,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the file close degree */
|
||
if(H5P_register(acs_pclass,H5F_CLOSE_DEGREE_NAME,H5F_CLOSE_DEGREE_SIZE, &close_degree,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the offset of family driver info */
|
||
if(H5P_register(acs_pclass,H5F_ACS_FAMILY_OFFSET_NAME,H5F_ACS_FAMILY_OFFSET_SIZE, &family_offset,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
|
||
/* Register the data type of multi driver info */
|
||
if(H5P_register(acs_pclass,H5F_ACS_MULTI_TYPE_NAME,H5F_ACS_MULTI_TYPE_SIZE, &mem_type,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
/* Only register the default property list if it hasn't been created yet */
|
||
if(H5P_LST_FILE_ACCESS_g==(-1)) {
|
||
/* Register the default file access property list */
|
||
if((H5P_LST_FILE_ACCESS_g = H5P_create_id(acs_pclass))<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
/* ================ Mount Porperty Class Initialization ==============*/
|
||
assert(H5P_CLS_MOUNT_g!=-1);
|
||
|
||
/* Get the pointer to file mount class */
|
||
if(NULL == (mnt_pclass = H5I_object(H5P_CLS_MOUNT_g)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
|
||
|
||
/* Get the number of properties in the class */
|
||
if(H5P_get_nprops_pclass(mnt_pclass,&nprops)<0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties")
|
||
|
||
/* Assume that if there are properties in the class, they are the default ones */
|
||
if(nprops==0) {
|
||
/* Register property of whether symlinks is local to file */
|
||
if(H5P_register(mnt_pclass,H5F_MNT_SYM_LOCAL_NAME,H5F_MNT_SYM_LOCAL_SIZE, &local,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
/* Only register the default property list if it hasn't been created yet */
|
||
if(H5P_LST_MOUNT_g==(-1)) {
|
||
/* Register the default file mount property list */
|
||
if((H5P_LST_MOUNT_g = H5P_create_id(mnt_pclass))<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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))) {
|
||
H5I_clear_type(H5I_FILE, FALSE);
|
||
} else if (0==(n=H5I_nmembers(H5I_FILE_CLOSING))) {
|
||
H5I_dec_type_ref(H5I_FILE);
|
||
H5I_dec_type_ref(H5I_FILE_CLOSING);
|
||
H5_interface_initialize_g = 0;
|
||
n = 1; /*H5I*/
|
||
}
|
||
}
|
||
FUNC_LEAVE_NOAPI(n)
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
* Function: H5F_acs_create
|
||
*
|
||
* Purpose: Callback routine which is called whenever a file access
|
||
* property list is closed. This routine performs any generic
|
||
* initialization needed on the properties the library put into
|
||
* the list.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* Tuesday, Oct 23, 2001
|
||
*
|
||
* Modifications:
|
||
*
|
||
*----------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5F_acs_create(hid_t fapl_id, void UNUSED *copy_data)
|
||
{
|
||
hid_t driver_id;
|
||
void* driver_info;
|
||
H5P_genplist_t *plist; /* Property list */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_acs_create, FAIL)
|
||
|
||
/* Check argument */
|
||
if(NULL == (plist = H5I_object(fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
|
||
|
||
/* Retrieve properties */
|
||
if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get drver ID")
|
||
if(H5P_get(plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get drver info")
|
||
|
||
if(driver_id > 0) {
|
||
/* Set the driver for the property list */
|
||
if(H5FD_fapl_open(plist, driver_id, driver_info)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*--------------------------------------------------------------------------
|
||
* Function: H5F_acs_copy
|
||
*
|
||
* Purpose: Callback routine which is called whenever a file access
|
||
* property list is copied. This routine performs any generic
|
||
* copy needed on the properties.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
* Programmer: Raymond Lu
|
||
* Tuesday, Oct 23, 2001
|
||
*
|
||
* Modifications:
|
||
*
|
||
*--------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5F_acs_copy(hid_t new_fapl_id, hid_t old_fapl_id, void UNUSED *copy_data)
|
||
{
|
||
hid_t driver_id;
|
||
void* driver_info;
|
||
H5P_genplist_t *new_plist; /* New property list */
|
||
H5P_genplist_t *old_plist; /* Old property list */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_acs_copy, FAIL)
|
||
|
||
if(NULL == (new_plist = H5I_object(new_fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
|
||
if(NULL == (old_plist = H5I_object(old_fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
|
||
|
||
/* Get values from old property list */
|
||
if(H5P_get(old_plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get drver ID")
|
||
if(H5P_get(old_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get drver info")
|
||
|
||
if(driver_id > 0) {
|
||
/* Set the driver for the property list */
|
||
if(H5FD_fapl_open(new_plist, driver_id, driver_info)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*--------------------------------------------------------------------------
|
||
* Function: H5F_acs_close
|
||
*
|
||
* Purpose: Callback routine which is called whenever a file access
|
||
* property list is closed. This routine performs any generic
|
||
* cleanup needed on the properties.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* Tuesday, Oct 23, 2001
|
||
*
|
||
* Modifications:
|
||
*
|
||
*---------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
herr_t
|
||
H5F_acs_close(hid_t fapl_id, void UNUSED *close_data)
|
||
{
|
||
hid_t driver_id;
|
||
void *driver_info;
|
||
H5P_genplist_t *plist; /* Property list */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_acs_close, FAIL)
|
||
|
||
/* Check argument */
|
||
if(NULL == (plist = H5I_object(fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
|
||
|
||
if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
|
||
HGOTO_DONE(FAIL) /* Can't return errors when library is shutting down */
|
||
if(H5P_get(plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
|
||
HGOTO_DONE(FAIL) /* Can't return errors when library is shutting down */
|
||
|
||
if(driver_id > 0) {
|
||
/* Close the driver for the property list */
|
||
if(H5FD_fapl_close(driver_id, driver_info)<0)
|
||
HGOTO_DONE(FAIL) /* Can't return errors when library is shutting down */
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
#ifdef NOT_YET
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_flush_all_cb
|
||
*
|
||
* Purpose: Callback function for H5F_flush_all().
|
||
*
|
||
* Return: Always returns zero.
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, February 19, 1999
|
||
*
|
||
* Modifications:
|
||
* Bill Wendling, 2003-03-18
|
||
* Changed H5F_flush to accept H5F_flush_t flags instead of a
|
||
* series of h5bool_t's.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
H5F_flush_all_cb(void *_f, hid_t UNUSED fid, void *_invalidate)
|
||
{
|
||
H5F_t *f=(H5F_t *)_f;
|
||
unsigned invalidate = (*((hbool_t*)_invalidate);
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_flush_all_cb)
|
||
|
||
H5F_flush(f, H5F_SCOPE_LOCAL, (invalidate ? H5F_FLUSH_INVALIDATE : H5F_FLUSH_NONE));
|
||
|
||
FUNC_LEAVE_NOAPI(0)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_flush_all
|
||
*
|
||
* Purpose: Flush all open files. If INVALIDATE is true then also remove
|
||
* everything from the cache.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Thursday, February 18, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5F_flush_all(hbool_t invalidate)
|
||
{
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_flush_all, FAIL)
|
||
|
||
H5I_search(H5I_FILE,H5F_flush_all_cb,&invalidate);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
#endif /* NOT_YET */
|
||
|
||
#ifdef NOT_YET
|
||
|
||
/*--------------------------------------------------------------------------
|
||
NAME
|
||
H5F_encode_length_unusual -- encode an unusual length size
|
||
USAGE
|
||
void H5F_encode_length_unusual(f, p, l)
|
||
const H5F_t *f; IN: pointer to the file record
|
||
uint8_t **p; IN: pointer to buffer pointer to encode length in
|
||
uint8_t *l; IN: pointer to length to encode
|
||
|
||
ERRORS
|
||
|
||
RETURNS
|
||
none
|
||
DESCRIPTION
|
||
Encode non-standard (i.e. not 2, 4 or 8-byte) lengths in file meta-data.
|
||
--------------------------------------------------------------------------*/
|
||
void
|
||
H5F_encode_length_unusual(const H5F_t *f, uint8_t **p, uint8_t *l)
|
||
{
|
||
int i = (int)H5F_SIZEOF_SIZE(f)-1;
|
||
|
||
#ifdef WORDS_BIGENDIAN
|
||
/*
|
||
* For non-little-endian platforms, encode each byte in memory backwards.
|
||
*/
|
||
for (/*void*/; i>=0; i--, (*p)++)*(*p) = *(l+i);
|
||
#else
|
||
/* platform has little-endian integers */
|
||
HDmemcpy(*p,l,(size_t)(i+1));
|
||
*p+=(i+1);
|
||
#endif
|
||
|
||
}
|
||
#endif /* NOT_YET */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 18 Feb 1998
|
||
* Calls H5P_copy_plist() to copy the property list and H5P_close() to free
|
||
* that property list if an error occurs.
|
||
*
|
||
* Raymond Lu, Oct 14, 2001
|
||
* Changed to generic property list.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5Fget_create_plist(hid_t file_id)
|
||
{
|
||
H5F_t *file = NULL;
|
||
H5P_genplist_t *plist; /* Property list */
|
||
hid_t ret_value;
|
||
|
||
FUNC_ENTER_API(H5Fget_create_plist, FAIL)
|
||
H5TRACE1("i","i",file_id);
|
||
|
||
/* check args */
|
||
if (NULL==(file=H5I_object_verify(file_id, H5I_FILE)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
|
||
if(NULL == (plist = 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)) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file creation properties")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
* Raymond Lu, Oct 23, 2001
|
||
* Changed file access property list to the new generic
|
||
* property list.
|
||
*
|
||
* Bill Wendling, Apr 21, 2003
|
||
* Fixed bug where the driver ID and info in the property
|
||
* list were being overwritten but the original ID and info
|
||
* weren't being close.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5Fget_access_plist(hid_t file_id)
|
||
{
|
||
H5F_t *f = NULL;
|
||
H5P_genplist_t *new_plist; /* New property list */
|
||
H5P_genplist_t *old_plist; /* Old property list */
|
||
hid_t ret_value = SUCCEED;
|
||
void *driver_info=NULL;
|
||
|
||
FUNC_ENTER_API(H5Fget_access_plist, FAIL)
|
||
H5TRACE1("i","i",file_id);
|
||
|
||
/* Check args */
|
||
if (NULL==(f=H5I_object_verify(file_id, H5I_FILE)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
|
||
|
||
/* Make a copy of the default file access property list */
|
||
if(NULL == (old_plist = 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)) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list")
|
||
if(NULL == (new_plist = 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_SIZE_NAME, &(f->shared->mdc_nelmts)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set meta data cache size")
|
||
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache element size")
|
||
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->lf->def_meta_block_size)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set meta data 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->lf->def_sdata_block_size)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
|
||
|
||
/*
|
||
* Since we're resetting the driver ID and info, close them if they
|
||
* exist in this new property list.
|
||
*/
|
||
if (H5F_acs_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)<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_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_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) {
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5Fget_obj_count(hid_t file_id, unsigned types)
|
||
{
|
||
H5F_t *f=NULL;
|
||
int ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_API(H5Fget_obj_count, FAIL)
|
||
H5TRACE2("Is","iIu",file_id,types);
|
||
|
||
if( file_id != (hid_t)H5F_OBJ_ALL && (NULL==(f=H5I_object_verify(file_id,H5I_FILE))) )
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
|
||
if( (types&H5F_OBJ_ALL)==0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
|
||
|
||
if((ret_value = H5F_get_obj_count(f, types))<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCOUNT, FAIL, "can't get object count")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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; negative on failure.
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* Wednesday, Dec 5, 2001
|
||
*
|
||
* Modification:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5F_get_obj_count(const H5F_t *f, unsigned types)
|
||
{
|
||
int ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_get_obj_count)
|
||
|
||
if((ret_value=H5F_get_objects(f, types, -1, NULL)) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get counts of opened file IDs and object IDs in the file")
|
||
|
||
done:
|
||
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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Fget_obj_ids(hid_t file_id, unsigned types, int max_objs, hid_t *oid_list)
|
||
{
|
||
herr_t ret_value;
|
||
H5F_t *f=NULL;
|
||
|
||
FUNC_ENTER_API(H5Fget_obj_ids, FAIL)
|
||
H5TRACE4("e","iIuIs*i",file_id,types,max_objs,oid_list);
|
||
|
||
if( file_id != (hid_t)H5F_OBJ_ALL && (NULL==(f=H5I_object_verify(file_id,H5I_FILE))) )
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
|
||
if( (types&H5F_OBJ_ALL)==0)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
|
||
assert(oid_list);
|
||
|
||
ret_value = H5F_get_obj_ids(f, types, max_objs, oid_list);
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_get_object_ids
|
||
*
|
||
* Purpose: Private 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:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *oid_list)
|
||
{
|
||
int ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_get_obj_ids)
|
||
|
||
if((ret_value=H5F_get_objects(f, types, max_objs, oid_list)) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object IDs opened in the file")
|
||
|
||
done:
|
||
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; negative on failure.
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* Wednesday, Dec 5, 2001
|
||
*
|
||
* Modification:
|
||
*
|
||
*---------------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_list)
|
||
{
|
||
unsigned obj_id_count=0; /* Number of open IDs */
|
||
H5F_olist_t olist; /* Structure to hold search results */
|
||
int 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;
|
||
/* Shared file structure is used to verify if file IDs refer to the same
|
||
* file. */
|
||
if(f != NULL)
|
||
olist.shared = f->shared;
|
||
else
|
||
olist.shared = NULL;
|
||
|
||
/* Search through file IDs to count the number, and put their
|
||
* IDs on the object list */
|
||
if( (types & H5F_OBJ_FILE) && H5I_nmembers(H5I_FILE) > 0 ) {
|
||
olist.obj_type = H5I_FILE;
|
||
(void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist);
|
||
}
|
||
|
||
/* Search through dataset IDs to count number of datasets, and put their
|
||
* IDs on the object list */
|
||
if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_DATASET) && H5I_nmembers(H5I_DATASET) > 0 ) {
|
||
olist.obj_type = H5I_DATASET;
|
||
(void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist);
|
||
}
|
||
|
||
/* Search through group IDs to count number of groups, and put their
|
||
* IDs on the object list */
|
||
if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_GROUP) && H5I_nmembers(H5I_GROUP) > 0 ) {
|
||
olist.obj_type = H5I_GROUP;
|
||
(void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist);
|
||
}
|
||
|
||
/* Search through datatype IDs to count number of named datatypes, and put their
|
||
* IDs on the object list */
|
||
if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_DATATYPE) && H5I_nmembers(H5I_DATATYPE) > 0 ) {
|
||
olist.obj_type = H5I_DATATYPE;
|
||
(void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist);
|
||
}
|
||
|
||
/* Search through attribute IDs to count number of attributes, and put their
|
||
* IDs on the object list */
|
||
if( (max_index<0 || (int)olist.list_index< max_index) && (types & H5F_OBJ_ATTR) && H5I_nmembers(H5I_ATTR) > 0 ) {
|
||
olist.obj_type = H5I_ATTR;
|
||
(void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist);
|
||
}
|
||
|
||
/* Set the number of objects currently open */
|
||
H5_ASSIGN_OVERFLOW(ret_value,obj_id_count,unsigned,int);
|
||
|
||
#ifdef LATER
|
||
done:
|
||
#endif /* LATER */
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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.
|
||
*
|
||
* 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)
|
||
|
||
assert(obj_ptr);
|
||
assert(olist);
|
||
|
||
/* Count file IDs */
|
||
if(olist->obj_type == H5I_FILE) {
|
||
if( !olist->shared || (olist->shared && ((H5F_t*)obj_ptr)->shared == olist->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 */
|
||
if(olist->max_index>=0 && (int)olist->list_index>=olist->max_index)
|
||
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
|
||
}
|
||
} else { /* either count opened object IDs or put the IDs on the list */
|
||
H5G_entry_t *ent; /* Group entry info for object */
|
||
|
||
switch(olist->obj_type) {
|
||
case H5I_ATTR:
|
||
ent = H5A_entof((H5A_t*)obj_ptr);
|
||
break;
|
||
case H5I_GROUP:
|
||
ent = H5G_entof((H5G_t*)obj_ptr);
|
||
break;
|
||
case H5I_DATASET:
|
||
ent = H5D_entof((H5D_t*)obj_ptr);
|
||
break;
|
||
case H5I_DATATYPE:
|
||
if(H5T_is_named((H5T_t*)obj_ptr)==TRUE)
|
||
ent = H5T_entof((H5T_t*)obj_ptr);
|
||
else
|
||
ent = NULL;
|
||
break;
|
||
default:
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object")
|
||
}
|
||
|
||
if( (!olist->shared && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE)
|
||
|| (!olist->shared && olist->obj_type!=H5I_DATATYPE)
|
||
|| (ent && ent->file->shared == olist->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 */
|
||
if(olist->max_index>=0 && (int)olist->list_index>=olist->max_index)
|
||
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
|
||
}
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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=NULL;
|
||
herr_t ret_value;
|
||
|
||
FUNC_ENTER_API(H5Fget_vfd_handle, FAIL)
|
||
H5TRACE3("e","iix",file_id,fapl,file_handle);
|
||
|
||
/* Check args */
|
||
assert(file_handle);
|
||
if(NULL==(file=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)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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: H5F_equal
|
||
*
|
||
* Purpose: Compares NEEDLE to a file from the HAYSTACK.
|
||
*
|
||
* Return: Success: Returns positive if two files are equal,
|
||
* zero otherwise.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, August 2, 1999
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
/* ARGSUSED */
|
||
static int
|
||
H5F_equal(void *_haystack, hid_t UNUSED id, void *_needle)
|
||
{
|
||
H5F_t *haystack = (H5F_t*)_haystack;
|
||
const H5FD_t *needle = (const H5FD_t*)_needle;
|
||
int retval;
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_equal)
|
||
|
||
retval = (0==H5FD_cmp(haystack->shared->lf, needle));
|
||
|
||
FUNC_LEAVE_NOAPI(retval)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_locate_signature
|
||
*
|
||
* Purpose: Finds the HDF5 super block signature in a file. The signature
|
||
* can appear at address 0, or any power of two beginning with
|
||
* 512.
|
||
*
|
||
* Return: Success: The absolute format address of the signature.
|
||
*
|
||
* Failure: HADDR_UNDEF
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Friday, November 7, 1997
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1999-08-02
|
||
* Rewritten to use the virtual file layer.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static haddr_t
|
||
H5F_locate_signature(H5FD_t *file, hid_t dxpl_id)
|
||
{
|
||
haddr_t addr, eoa;
|
||
uint8_t buf[H5F_SIGNATURE_LEN];
|
||
unsigned n, maxpow;
|
||
haddr_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_locate_signature)
|
||
|
||
/* Find the least N such that 2^N is larger than the file size */
|
||
if (HADDR_UNDEF==(addr=H5FD_get_eof(file)) ||
|
||
HADDR_UNDEF==(eoa=H5FD_get_eoa(file)))
|
||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to obtain EOF/EOA value")
|
||
for (maxpow=0; addr; maxpow++)
|
||
addr>>=1;
|
||
maxpow = MAX(maxpow, 9);
|
||
|
||
/*
|
||
* Search for the file signature at format address zero followed by
|
||
* powers of two larger than 9.
|
||
*/
|
||
for (n=8; n<maxpow; n++) {
|
||
addr = (8==n) ? 0 : (haddr_t)1 << n;
|
||
if (H5FD_set_eoa(file, addr+H5F_SIGNATURE_LEN)<0)
|
||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to set EOA value for file signature")
|
||
if (H5FD_read(file, H5FD_MEM_SUPER, dxpl_id, addr, H5F_SIGNATURE_LEN, buf)<0)
|
||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to read file signature")
|
||
if (!HDmemcmp(buf, H5F_SIGNATURE, H5F_SIGNATURE_LEN))
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* If the signature was not found then reset the EOA value and return
|
||
* failure.
|
||
*/
|
||
if (n>=maxpow) {
|
||
(void)H5FD_set_eoa(file, eoa); /* Ignore return value */
|
||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to find a valid file signature")
|
||
}
|
||
|
||
/* Set return value */
|
||
ret_value=addr;
|
||
|
||
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;
|
||
htri_t ret_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)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Raymond Lu, Oct 14, 2001
|
||
* Changed the file creation and access property list to the
|
||
* new generic property list.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5F_t *
|
||
H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
|
||
{
|
||
H5F_t *f=NULL, *ret_value;
|
||
int n;
|
||
H5P_genplist_t *plist; /* Property list */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_new)
|
||
|
||
if (NULL==(f=H5FL_CALLOC(H5F_t)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||
|
||
if (shared) {
|
||
f->shared = shared;
|
||
} else {
|
||
f->shared = H5FL_CALLOC(H5F_file_t);
|
||
f->shared->super_addr = HADDR_UNDEF;
|
||
f->shared->base_addr = HADDR_UNDEF;
|
||
f->shared->freespace_addr = HADDR_UNDEF;
|
||
f->shared->driver_addr = HADDR_UNDEF;
|
||
|
||
/*
|
||
* 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 = H5I_object(fcpl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
|
||
f->shared->fcpl_id = H5P_copy_plist(plist);
|
||
|
||
/* 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_SYM_LEAF_NAME, &f->shared->sym_leaf_k)<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size")
|
||
if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, &f->shared->btree_k[0])<0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes")
|
||
|
||
/* Check for non-default indexed storage B-tree internal 'K' value
|
||
* and increment the version # of the superblock if it is a non-default
|
||
* value.
|
||
*/
|
||
if(f->shared->btree_k[H5B_ISTORE_ID]!=HDF5_BTREE_ISTORE_IK_DEF) {
|
||
unsigned super_vers=HDF5_SUPERBLOCK_VERSION_MAX; /* Super block version */
|
||
H5P_genplist_t *c_plist; /* Property list */
|
||
|
||
if(NULL == (c_plist = H5I_object(f->shared->fcpl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
|
||
if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set superblock version")
|
||
} /* end if */
|
||
|
||
if(NULL == (plist = H5I_object(fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
|
||
|
||
if(H5P_get(plist, H5F_ACS_META_CACHE_SIZE_NAME, &(f->shared->mdc_nelmts)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data cache size")
|
||
if(H5P_get(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache element size")
|
||
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 cache 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")
|
||
|
||
/*
|
||
* Create a meta data 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 ((n=H5AC_create(f, f->shared->mdc_nelmts))<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache")
|
||
|
||
f->shared->mdc_nelmts = n;
|
||
|
||
/* Create the file's "open object" information */
|
||
if(H5FO_create(f)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object TBBT")
|
||
} /* end else */
|
||
|
||
f->shared->nrefs++;
|
||
f->nrefs = 1;
|
||
|
||
/* Set return value */
|
||
ret_value = f;
|
||
|
||
done:
|
||
if (!ret_value && f) {
|
||
if (!shared)
|
||
H5FL_FREE(H5F_file_t,f->shared);
|
||
H5FL_FREE(H5F_t,f);
|
||
}
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 1998-10-14
|
||
* Nothing happens unless the reference count for the H5F_t goes to
|
||
* zero. The reference counts are decremented here.
|
||
*
|
||
* Robb Matzke, 1999-02-19
|
||
* More careful about decrementing reference counts so they don't go
|
||
* negative or wrap around to some huge value. Nothing happens if a
|
||
* reference count is already zero.
|
||
*
|
||
* Robb Matzke, 2000-10-31
|
||
* H5FL_FREE() aborts if called with a null pointer (unlike the
|
||
* original H5MM_free()).
|
||
*
|
||
* Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
|
||
* Added `id to name' support.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_dest(H5F_t *f, hid_t dxpl_id)
|
||
{
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_dest)
|
||
|
||
if (f && 1==f->nrefs) {
|
||
if (1==f->shared->nrefs) {
|
||
/*
|
||
* 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) {
|
||
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
|
||
ret_value = FAIL; /*but keep going*/
|
||
} /* end if */
|
||
|
||
/* Free the memory for the root group */
|
||
H5G_free(f->shared->root_grp);
|
||
f->shared->root_grp=NULL;
|
||
}
|
||
if (H5AC_dest(f, dxpl_id)) {
|
||
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
|
||
ret_value = FAIL; /*but keep going*/
|
||
}
|
||
if (H5FO_dest(f)<0) {
|
||
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
|
||
ret_value = FAIL; /*but keep going*/
|
||
} /* end if */
|
||
f->shared->cwfs = H5MM_xfree (f->shared->cwfs);
|
||
if (H5G_node_close(f)<0) {
|
||
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
|
||
ret_value = FAIL; /*but keep going*/
|
||
} /* end if */
|
||
|
||
/* Destroy file creation properties */
|
||
if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
|
||
if((ret_value=H5I_dec_ref(f->shared->fcpl_id)) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close property list")
|
||
|
||
/* Destroy shared file struct */
|
||
if (H5FD_close(f->shared->lf)<0) {
|
||
HERROR(H5E_FILE, H5E_CANTINIT, "problems closing file");
|
||
ret_value = FAIL; /*but keep going*/
|
||
}
|
||
f->shared = 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 = H5MM_xfree(f->name);
|
||
f->mtab.child = H5MM_xfree(f->mtab.child);
|
||
f->mtab.nalloc = 0;
|
||
H5FL_FREE(H5F_t,f);
|
||
} else if (f && f->nrefs>0) {
|
||
/*
|
||
* There are other references to this file. Only decrement the
|
||
* reference count.
|
||
*/
|
||
--f->nrefs;
|
||
}
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
* Albert Cheng, 1998-02-05
|
||
* Added the access_parms argument to pass down access template
|
||
* information.
|
||
*
|
||
* Robb Matzke, 1998-02-18
|
||
* The H5F_access_t changed to allow more generality. The low
|
||
* level driver is part of the file access template so the TYPE
|
||
* argument has been removed.
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* Rewritten to use the virtual file layer.
|
||
*
|
||
* Robb Matzke, 1999-08-16
|
||
* Added decoding of file driver information block, which uses a
|
||
* formerly reserved address slot in the boot block in order to
|
||
* be compatible with previous versions of the file format.
|
||
*
|
||
* Robb Matzke, 1999-08-20
|
||
* Optimizations for opening a file. If the driver can't
|
||
* determine when two file handles refer to the same file then
|
||
* we open the file in one step. Otherwise if the first attempt
|
||
* to open the file fails then we skip the second attempt if the
|
||
* arguments would be the same.
|
||
*
|
||
* Raymond Lu, 2001-10-14
|
||
* Changed the file creation and access property lists to the
|
||
* new generic property list.
|
||
*
|
||
* Bill Wendling, 2003-03-18
|
||
* Modified H5F_flush call to take one flag instead of
|
||
* multiple Boolean flags.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static 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' */
|
||
H5G_entry_t root_ent; /*root symbol table entry */
|
||
unsigned tent_flags; /*tentative flags */
|
||
H5FD_class_t *drvr; /*file driver class info */
|
||
hbool_t driver_has_cmp; /*`cmp' callback defined? */
|
||
H5P_genplist_t *a_plist; /*file access property list */
|
||
H5F_close_degree_t fc_degree; /*file close degree */
|
||
H5F_t *ret_value = NULL; /*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")
|
||
driver_has_cmp = (NULL!=drvr->cmp);
|
||
|
||
/*
|
||
* 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 (driver_has_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 ((file=H5I_search(H5I_FILE, H5F_equal, lf)) ||
|
||
(file=H5I_search(H5I_FILE_CLOSING, H5F_equal, lf))) {
|
||
/*
|
||
* 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) {
|
||
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 (flags & H5F_ACC_TRUNC) {
|
||
file = NULL; /*to prevent destruction of wrong file*/
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
|
||
}
|
||
if (flags & H5F_ACC_EXCL) {
|
||
file = NULL; /*to prevent destruction of wrong file*/
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
|
||
}
|
||
if ((flags & H5F_ACC_RDWR) && 0==(file->intent & H5F_ACC_RDWR)) {
|
||
file = NULL; /*to prevent destruction of wrong file*/
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
|
||
}
|
||
|
||
if ((file = H5F_new(file->shared, fcpl_id, fapl_id)) == NULL)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
|
||
|
||
lf = file->shared->lf;
|
||
} else 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")
|
||
}
|
||
if (NULL==(file = H5F_new(NULL, fcpl_id, fapl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
|
||
file->shared->flags = flags;
|
||
file->shared->lf = lf;
|
||
} else {
|
||
/*
|
||
* This file is not yet open by the library and our tentative opening
|
||
* above is good enough.
|
||
*/
|
||
if (NULL==(file = H5F_new(NULL, fcpl_id, fapl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
|
||
|
||
file->shared->flags = flags;
|
||
file->shared->lf = lf;
|
||
}
|
||
|
||
/* 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)) {
|
||
hsize_t buf_size=0; /* Size of buffer needed to hold superblock info */
|
||
void *buf=NULL; /* Buffer to hold superblock info */
|
||
|
||
/*
|
||
* We've just opened a fresh new file (or truncated one). We need
|
||
* to create & write the superblock.
|
||
*/
|
||
#ifdef H5_HAVE_FPHDF5
|
||
if (!H5FD_is_fphdf5_driver(lf) || H5FD_fphdf5_is_captain(lf)) {
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
/* Initialize information about the superblock and allocate space for it */
|
||
if ((buf_size=H5F_init_superblock(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)
|
||
*/
|
||
if (H5G_mkroot(file, dxpl_id, NULL)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
if (H5FD_is_fphdf5_driver(lf)) {
|
||
/* Allocate room for the superblock buffer */
|
||
H5_CHECK_OVERFLOW(buf_size, hsize_t, size_t);
|
||
if((buf=H5MM_malloc((size_t)buf_size))==NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for superblock buffer")
|
||
} /* end if */
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
|
||
/* Write the superblock to the file */
|
||
/* (This must be after the root group is created, since the root
|
||
* group's symbol table entry is part of the superblock)
|
||
*/
|
||
if (H5F_write_superblock(file, dxpl_id, buf) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to write file superblock")
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
} /* end if */
|
||
|
||
/* If this file is using the FPHDF5 driver, broadcast the superblock
|
||
* from the captain to the other clients
|
||
*/
|
||
if (H5FD_is_fphdf5_driver(lf)) {
|
||
int mrc; /*MPI return code */
|
||
H5FP_super_t super_info; /* Superblock information */
|
||
|
||
/* Captain sets up the information */
|
||
if (H5FD_fphdf5_is_captain(lf)) {
|
||
super_info.addr=shared->super_addr;
|
||
super_info.size=buf_size;
|
||
} /* end if */
|
||
|
||
/* Broadcast the superblock information */
|
||
if ((mrc = MPI_Bcast(&super_info, 1, H5FP_super, (int)H5FP_capt_barrier_rank,
|
||
H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mrc)
|
||
|
||
/* Non-captain clients allocate the buffer now */
|
||
if (!H5FD_fphdf5_is_captain(lf)) {
|
||
/* Allocate room for the superblock buffer */
|
||
H5_CHECK_OVERFLOW(super_info.size, hsize_t, size_t);
|
||
if((buf=H5MM_malloc((size_t)super_info.size))==NULL)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for superblock buffer")
|
||
} /* end if */
|
||
|
||
/* Broadcast the actual superblock */
|
||
H5_CHECK_OVERFLOW(super_info.size, hsize_t, int);
|
||
if ((mrc = MPI_Bcast(buf, (int)super_info.size, MPI_BYTE, (int)H5FP_capt_barrier_rank,
|
||
H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS)
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mrc)
|
||
|
||
if (!H5FD_fphdf5_is_captain(lf)) {
|
||
if (H5F_read_superblock(file, dxpl_id, &root_ent, super_info.addr,
|
||
buf, (size_t)super_info.size) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
|
||
}
|
||
|
||
/* The following barrier ensures that all set eoa operations
|
||
* associated with creating the superblock are complete before
|
||
* we attempt any allocations.
|
||
* JRM - 4/13/04
|
||
*/
|
||
if ( (mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS )
|
||
{
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mrc)
|
||
}
|
||
|
||
if (!H5FD_fphdf5_is_captain(lf)) {
|
||
if (H5G_mkroot(file, dxpl_id, &root_ent) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
|
||
}
|
||
|
||
/* All clients free the buffer used for broadcasting the superblock */
|
||
buf = H5MM_xfree (buf);
|
||
} /* end if */
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
} else if (1 == shared->nrefs) {
|
||
#ifdef H5_HAVE_FPHDF5
|
||
int mrc; /*MPI return code */
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
|
||
/* Read the superblock if it hasn't been read before. */
|
||
if (HADDR_UNDEF == (shared->super_addr = H5F_locate_signature(lf,dxpl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, "unable to find file signature")
|
||
|
||
if (H5F_read_superblock(file, dxpl_id, &root_ent, shared->super_addr, NULL, 0) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
if (H5FD_is_fphdf5_driver(lf)) {
|
||
/* reading the superblock generates lots of set_eoa calls. To avoid
|
||
* race conditions with allocations, make sure that everyone is done
|
||
* reading the superblock before we proceed.
|
||
*/
|
||
if ( (mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS ) {
|
||
HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mrc)
|
||
}
|
||
}
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
|
||
/* Make sure we can open the root group */
|
||
if (H5G_mkroot(file, dxpl_id, &root_ent) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
|
||
}
|
||
|
||
/*
|
||
* 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(NULL == (a_plist = H5I_object(fapl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
|
||
if(H5P_get(a_plist, H5F_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 = shared->lf->cls->fc_degree;
|
||
else
|
||
shared->fc_degree = fc_degree;
|
||
} else if(shared->nrefs > 1) {
|
||
if(fc_degree==H5F_CLOSE_DEFAULT && shared->fc_degree!=shared->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")
|
||
}
|
||
|
||
/* 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)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1997-07-18
|
||
* File struct creation and destruction is through H5F_new() and
|
||
* H5F_dest(). Writing the root symbol table entry is done with
|
||
* H5G_encode().
|
||
*
|
||
* Robb Matzke, 1997-08-29
|
||
* Moved creation of the boot block to H5F_flush().
|
||
*
|
||
* 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
|
||
* Better error checking for the creation and access property
|
||
* lists. It used to be possible to swap the two and core the
|
||
* library. Also, zero is no longer valid as a default property
|
||
* list; one must use H5P_DEFAULT instead.
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* The file creation and file access property lists are passed
|
||
* to the H5F_open() as object IDs.
|
||
*
|
||
* Raymond Lu, 2001-10-14
|
||
* Changed the file creation and access property list to the
|
||
* new generic property list.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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")
|
||
if (flags & ~(H5F_ACC_EXCL|H5F_ACC_TRUNC|H5F_ACC_DEBUG))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags")
|
||
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))<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)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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")
|
||
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))<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_close(new_file)<0)
|
||
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1998-10-16
|
||
* Added the `scope' argument.
|
||
*
|
||
* Bill Wendling, 2003-03-18
|
||
* Modified H5F_flush call to take one flag instead of
|
||
* several Boolean flags.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Fflush(hid_t object_id, H5F_scope_t scope)
|
||
{
|
||
H5F_t *f = NULL;
|
||
H5G_t *grp = NULL;
|
||
H5T_t *type = NULL;
|
||
H5D_t *dset = NULL;
|
||
H5A_t *attr = NULL;
|
||
H5G_entry_t *ent = NULL;
|
||
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=H5I_object(object_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
|
||
break;
|
||
|
||
case H5I_GROUP:
|
||
if (NULL==(grp=H5I_object(object_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier")
|
||
ent = H5G_entof(grp);
|
||
break;
|
||
|
||
case H5I_DATATYPE:
|
||
if (NULL==(type=H5I_object(object_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier")
|
||
ent = H5T_entof(type);
|
||
break;
|
||
|
||
case H5I_DATASET:
|
||
if (NULL==(dset=H5I_object(object_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
|
||
ent = H5D_entof(dset);
|
||
break;
|
||
|
||
case H5I_ATTR:
|
||
if (NULL==(attr=H5I_object(object_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier")
|
||
ent = H5A_entof(attr);
|
||
break;
|
||
|
||
default:
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
|
||
}
|
||
|
||
if (!f) {
|
||
if (!ent)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not assocated with a file")
|
||
f = ent->file;
|
||
}
|
||
if (!f)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not associated with a file")
|
||
|
||
/* Flush the file */
|
||
if (H5F_flush(f, H5AC_dxpl_id, scope, H5F_FLUSH_NONE) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "flush failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_read_superblock
|
||
*
|
||
* Purpose: Reads the superblock from the file or from the BUF. If
|
||
* ADDR is a valid address, then it reads it from the file.
|
||
* If not, then BUF must be non-NULL for it to read from the
|
||
* BUF.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Bill Wendling
|
||
* wendling@ncsa.uiuc.edu
|
||
* Sept 12, 2003
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size)
|
||
{
|
||
haddr_t stored_eoa; /*relative end-of-addr in file */
|
||
haddr_t eof; /*end of file address */
|
||
uint8_t *q; /*ptr into temp I/O buffer */
|
||
size_t sizeof_addr = 0;
|
||
size_t sizeof_size = 0;
|
||
const size_t fixed_size = 24; /*fixed sizeof superblock */
|
||
unsigned sym_leaf_k = 0;
|
||
size_t variable_size; /*variable sizeof superblock */
|
||
unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree internal node 'K' values */
|
||
H5F_file_t *shared = NULL; /* shared part of `file' */
|
||
H5FD_t *lf = NULL; /* file driver part of `shared' */
|
||
uint8_t *p; /* Temporary pointer into encoding buffers */
|
||
uint8_t *start_p; /* Start of encoding buffers */
|
||
unsigned i; /* Index variable */
|
||
unsigned chksum; /* Checksum temporary variable */
|
||
size_t driver_size; /* Size of driver info block, in bytes */
|
||
char driver_name[9]; /* Name of driver, for driver info block */
|
||
unsigned super_vers; /* Super block version */
|
||
unsigned freespace_vers; /* Freespace info version */
|
||
unsigned obj_dir_vers; /* Object header info version */
|
||
unsigned share_head_vers; /* Shared header info version */
|
||
uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */
|
||
H5P_genplist_t *c_plist; /* File creation property list */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
/* Decoding */
|
||
FUNC_ENTER_NOAPI(H5F_read_superblock, FAIL)
|
||
|
||
/* Short cuts */
|
||
shared = f->shared;
|
||
lf = shared->lf;
|
||
|
||
/* Get the shared file creation property list */
|
||
if (NULL == (c_plist = H5I_object(shared->fcpl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
|
||
|
||
/* Read the superblock if it hasn't been read before. */
|
||
if (addr == HADDR_UNDEF) {
|
||
if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature")
|
||
} else {
|
||
shared->super_addr = addr;
|
||
}
|
||
|
||
if (!buf) {
|
||
start_p = p = sbuf;
|
||
buf_size=sizeof(sbuf);
|
||
|
||
if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 ||
|
||
H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, p) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock")
|
||
} else {
|
||
start_p = p = buf;
|
||
}
|
||
|
||
/* Signature, already checked */
|
||
p += H5F_SIGNATURE_LEN;
|
||
|
||
/* Superblock version */
|
||
super_vers = *p++;
|
||
|
||
if (super_vers > HDF5_SUPERBLOCK_VERSION_MAX)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set superblock version")
|
||
|
||
/* Freespace version */
|
||
freespace_vers = *p++;
|
||
|
||
if (HDF5_FREESPACE_VERSION != freespace_vers)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to free space version")
|
||
|
||
/* Root group version number */
|
||
obj_dir_vers = *p++;
|
||
|
||
if (HDF5_OBJECTDIR_VERSION != obj_dir_vers)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad object directory version number")
|
||
if (H5P_set(c_plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set object directory version")
|
||
|
||
/* Skip over reserved byte */
|
||
p++;
|
||
|
||
/* Shared header version number */
|
||
share_head_vers = *p++;
|
||
|
||
if (HDF5_SHAREDHEADER_VERSION != share_head_vers)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad shared-header format version number")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set shared-header format version")
|
||
|
||
/* Size of file addresses */
|
||
sizeof_addr = *p++;
|
||
|
||
if (sizeof_addr != 2 && sizeof_addr != 4 &&
|
||
sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number in an address")
|
||
|
||
shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */
|
||
|
||
/* Size of file sizes */
|
||
sizeof_size = *p++;
|
||
|
||
if (sizeof_size != 2 && sizeof_size != 4 &&
|
||
sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number for object size")
|
||
|
||
shared->sizeof_size = sizeof_size; /* Keep a local copy also */
|
||
|
||
/* Skip over reserved byte */
|
||
p++;
|
||
|
||
/* Various B-tree sizes */
|
||
UINT16DECODE(p, sym_leaf_k);
|
||
|
||
if (sym_leaf_k < 1)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad symbol table leaf node 1/2 rank")
|
||
|
||
if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes")
|
||
|
||
shared->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */
|
||
|
||
/* Need 'get' call to set other array values */
|
||
if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes")
|
||
|
||
UINT16DECODE(p, btree_k[H5B_SNODE_ID]);
|
||
|
||
if (btree_k[H5B_SNODE_ID] < 1)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad 1/2 rank for btree internal nodes")
|
||
|
||
/*
|
||
* Delay setting the value in the property list until we've checked
|
||
* for the indexed storage B-tree internal 'K' value later.
|
||
*/
|
||
|
||
/* File consistency flags. Not really used yet */
|
||
UINT32DECODE(p, shared->consist_flags);
|
||
assert(((size_t)(p - start_p)) == fixed_size);
|
||
|
||
/* Decode the variable-length part of the superblock... */
|
||
variable_size = (super_vers>0 ? 4 : 0) + /* Potential indexed storage B-tree internal 'K' value */
|
||
H5F_SIZEOF_ADDR(f) + /*base addr*/
|
||
H5F_SIZEOF_ADDR(f) + /*global free list*/
|
||
H5F_SIZEOF_ADDR(f) + /*end-of-address*/
|
||
H5F_SIZEOF_ADDR(f) + /*reserved address*/
|
||
H5G_SIZEOF_ENTRY(f); /*root group ptr*/
|
||
assert(fixed_size + variable_size <= buf_size);
|
||
|
||
/* The buffer (buf) is either passed in or the "local_buf" variable now */
|
||
if(!buf) {
|
||
if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 ||
|
||
H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size,
|
||
variable_size, p) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock")
|
||
} /* end if */
|
||
|
||
/*
|
||
* If the superblock version # is greater than 0, read in the indexed
|
||
* storage B-tree internal 'K' value
|
||
*/
|
||
if (super_vers > 0) {
|
||
UINT16DECODE(p, btree_k[H5B_ISTORE_ID]);
|
||
p += 2; /* reserved */
|
||
} else {
|
||
btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF;
|
||
}
|
||
|
||
/* Set the B-tree internal node values, etc */
|
||
if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
|
||
|
||
HDmemcpy(shared->btree_k, btree_k, sizeof(unsigned) * H5B_NUM_BTREE_ID); /* Keep a local copy also */
|
||
|
||
H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/);
|
||
H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/);
|
||
H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
|
||
H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/);
|
||
|
||
if (H5G_ent_decode(f, (const uint8_t **)&p, root_ent/*out*/) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry")
|
||
|
||
/*
|
||
* Check if superblock address is different from base address and
|
||
* adjust base address and "end of address" address if so.
|
||
*/
|
||
if (!H5F_addr_eq(shared->super_addr,shared->base_addr)) {
|
||
/* Check if the superblock moved earlier in the file */
|
||
if (H5F_addr_lt(shared->super_addr, shared->base_addr))
|
||
stored_eoa -= (shared->base_addr - shared->super_addr);
|
||
else
|
||
/* The superblock moved later in the file */
|
||
stored_eoa += (shared->super_addr - shared->base_addr);
|
||
|
||
shared->base_addr = shared->super_addr;
|
||
} /* end if */
|
||
|
||
/* Compute super block checksum */
|
||
assert(sizeof(chksum) == sizeof(shared->super_chksum));
|
||
|
||
for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < fixed_size + variable_size; ++i)
|
||
q[i % sizeof(shared->super_chksum)] ^= start_p[i];
|
||
|
||
/* Set the super block checksum */
|
||
shared->super_chksum = chksum;
|
||
|
||
/* Decode the optional driver information block */
|
||
if (H5F_addr_defined(shared->driver_addr)) {
|
||
haddr_t drv_addr = shared->base_addr + shared->driver_addr;
|
||
uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE]; /* Local buffer */
|
||
size_t dbuf_size; /* Size available for driver info */
|
||
const uint8_t *driver_p; /* Remember beginning of driver info block */
|
||
|
||
if(!buf) {
|
||
driver_p = p = dbuf;
|
||
dbuf_size=sizeof(dbuf);
|
||
|
||
if (H5FD_set_eoa(lf, drv_addr + 16) < 0 ||
|
||
H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, 16, p) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block")
|
||
} /* end if */
|
||
else {
|
||
driver_p = p;
|
||
dbuf_size=buf_size-(p-start_p);
|
||
} /* end else */
|
||
|
||
/* Version number */
|
||
if (HDF5_DRIVERINFO_VERSION != *p++)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "bad driver information block version number")
|
||
|
||
p += 3; /* reserved */
|
||
|
||
/* Driver info size */
|
||
UINT32DECODE(p, driver_size);
|
||
|
||
/* Driver name and/or version */
|
||
HDstrncpy(driver_name, (const char *)p, 8);
|
||
driver_name[8] = '\0';
|
||
p += 8; /* advance past name/version */
|
||
|
||
/* Read driver information and decode */
|
||
assert((driver_size + 16) <= dbuf_size);
|
||
|
||
if(!buf) {
|
||
if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 ||
|
||
H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information")
|
||
} /* end if */
|
||
|
||
if (H5FD_sb_decode(lf, driver_name, p) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information")
|
||
|
||
/* Compute driver info block checksum */
|
||
assert(sizeof(chksum) == sizeof(shared->drvr_chksum));
|
||
|
||
for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i)
|
||
q[i % sizeof(shared->drvr_chksum)] ^= driver_p[i];
|
||
|
||
/* Set the driver info block checksum */
|
||
shared->drvr_chksum = chksum;
|
||
} /* end if */
|
||
|
||
/*
|
||
* The user-defined data is the area of the file before the base
|
||
* address.
|
||
*/
|
||
if (H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &shared->base_addr) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set usr block size")
|
||
|
||
/*
|
||
* Make sure that the data is not truncated. One case where this is
|
||
* possible is if the first file of a family of files was opened
|
||
* individually.
|
||
*/
|
||
if (HADDR_UNDEF == (eof = H5FD_get_eof(lf)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
if (!H5FD_is_fphdf5_driver(lf) || H5FD_fphdf5_is_captain(lf))
|
||
#endif /* !H5_HAVE_FPHDF5 */
|
||
if (eof < stored_eoa)
|
||
HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file")
|
||
|
||
/*
|
||
* Tell the file driver how much address space has already been
|
||
* allocated so that it knows how to allocate additional memory.
|
||
*/
|
||
if (H5FD_set_eoa(lf, stored_eoa) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to set end-of-address marker for file")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_init_superblock
|
||
*
|
||
* Purpose: Allocates the superblock for the file and initializes
|
||
* information about the superblock in memory. Does not write
|
||
* any superblock information to the file.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Sept 15, 2003
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static hsize_t
|
||
H5F_init_superblock(H5F_t *f, hid_t dxpl_id)
|
||
{
|
||
hsize_t userblock_size = 0; /* Size of userblock, in bytes */
|
||
size_t superblock_size; /* Size of superblock, in bytes */
|
||
size_t driver_size; /* Size of driver info block (bytes)*/
|
||
unsigned super_vers; /* Super block version */
|
||
haddr_t addr; /* Address of superblock */
|
||
H5P_genplist_t *plist; /* Property list */
|
||
hsize_t ret_value;
|
||
|
||
/* Encoding */
|
||
FUNC_ENTER_NOAPI(H5F_init_superblock, UFAIL)
|
||
|
||
/* Get the shared file creation property list */
|
||
if (NULL == (plist = H5I_object(f->shared->fcpl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, UFAIL, "not a property list")
|
||
|
||
/*
|
||
* The superblock starts immediately after the user-defined
|
||
* header, which we have already insured is a proper size. The
|
||
* base address is set to the same thing as the superblock for
|
||
* now.
|
||
*/
|
||
if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, UFAIL, "unable to get user block size")
|
||
f->shared->super_addr = userblock_size;
|
||
f->shared->base_addr = f->shared->super_addr;
|
||
f->shared->consist_flags = 0x03;
|
||
|
||
/* Grab superblock version from property list */
|
||
if (H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, UFAIL, "unable to get super block version")
|
||
|
||
/* Compute the size of the superblock */
|
||
superblock_size=H5F_SIGNATURE_LEN /* Signature length (8 bytes) */
|
||
+ 16 /* Length of required fixed-size portion */
|
||
+ ((super_vers>0) ? 4 : 0) /* Version specific fixed-size portion */
|
||
+ 4 * H5F_sizeof_addr(f) /* Variable-sized addresses */
|
||
+ H5G_SIZEOF_ENTRY(f); /* Size of root group symbol table entry */
|
||
|
||
/* Compute the size of the driver information block. */
|
||
H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t);
|
||
if (driver_size > 0)
|
||
driver_size += 16; /* Driver block header */
|
||
|
||
/*
|
||
* Allocate space for the userblock, superblock, and driver info
|
||
* block. We do it with one allocation request because the
|
||
* userblock and superblock need to be at the beginning of the
|
||
* file and only the first allocation request is required to
|
||
* return memory at format address zero.
|
||
*/
|
||
|
||
H5_CHECK_OVERFLOW(f->shared->base_addr, haddr_t, hsize_t);
|
||
addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, dxpl_id,
|
||
((hsize_t)f->shared->base_addr + superblock_size + driver_size));
|
||
|
||
if (HADDR_UNDEF == addr)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, UFAIL,
|
||
"unable to allocate file space for userblock and/or superblock")
|
||
|
||
if (0 != addr)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, UFAIL,
|
||
"file driver failed to allocate userblock and/or superblock at address zero")
|
||
|
||
/*
|
||
* The file driver information block begins immediately after the
|
||
* superblock.
|
||
*/
|
||
if (driver_size > 0)
|
||
f->shared->driver_addr = superblock_size;
|
||
|
||
/* Return the size of the super block+driver info block */
|
||
ret_value=superblock_size+driver_size;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_init_superblock() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_write_superblock
|
||
*
|
||
* Purpose: Writes (and optionally allocates) the superblock for the file.
|
||
* If BUF is non-NULL, then write the serialized superblock
|
||
* information into it. It should be a buffer of size
|
||
* H5F_SUPERBLOCK_SIZE + H5F_DRVINFOBLOCK_SIZE or larger.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Bill Wendling
|
||
* wendling@ncsa.uiuc.edu
|
||
* Sept 12, 2003
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf)
|
||
{
|
||
uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Superblock encoding buffer */
|
||
uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE];/* Driver info block encoding buffer*/
|
||
uint8_t *p = NULL; /* Ptr into encoding buffers */
|
||
unsigned i; /* Index variable */
|
||
unsigned chksum; /* Checksum temporary variable */
|
||
size_t superblock_size; /* Size of superblock, in bytes */
|
||
size_t driver_size; /* Size of driver info block (bytes)*/
|
||
char driver_name[9]; /* Name of driver, for driver info block */
|
||
unsigned super_vers; /* Super block version */
|
||
unsigned freespace_vers; /* Freespace info version */
|
||
unsigned obj_dir_vers; /* Object header info version */
|
||
unsigned share_head_vers; /* Shared header info version */
|
||
H5P_genplist_t *plist; /* Property list */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
/* Encoding */
|
||
FUNC_ENTER_NOAPI(H5F_write_superblock, FAIL)
|
||
|
||
/* Get the shared file creation property list */
|
||
if (NULL == (plist = H5I_object(f->shared->fcpl_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
|
||
|
||
/* Grab values from property list */
|
||
if (H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get super block version")
|
||
if (H5P_get(plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get free space version")
|
||
if (H5P_get(plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get object directory version")
|
||
if (H5P_get(plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get shared-header format version")
|
||
|
||
/* Encode the file super block */
|
||
p = sbuf;
|
||
HDmemcpy(p, H5F_SIGNATURE, H5F_SIGNATURE_LEN);
|
||
p += H5F_SIGNATURE_LEN;
|
||
*p++ = (uint8_t)super_vers;
|
||
*p++ = (uint8_t)freespace_vers;
|
||
*p++ = (uint8_t)obj_dir_vers;
|
||
*p++ = 0; /* reserved*/
|
||
*p++ = (uint8_t)share_head_vers;
|
||
assert (H5F_SIZEOF_ADDR(f) <= 255);
|
||
*p++ = (uint8_t)H5F_SIZEOF_ADDR(f);
|
||
assert (H5F_SIZEOF_SIZE(f) <= 255);
|
||
*p++ = (uint8_t)H5F_SIZEOF_SIZE(f);
|
||
*p++ = 0; /* reserved */
|
||
UINT16ENCODE(p, f->shared->sym_leaf_k);
|
||
UINT16ENCODE(p, f->shared->btree_k[H5B_SNODE_ID]);
|
||
UINT32ENCODE(p, f->shared->consist_flags);
|
||
|
||
/*
|
||
* Versions of the superblock >0 have the indexed storage B-tree
|
||
* internal 'K' value stored
|
||
*/
|
||
if (super_vers > 0) {
|
||
UINT16ENCODE(p, f->shared->btree_k[H5B_ISTORE_ID]);
|
||
*p++ = 0; /*reserved */
|
||
*p++ = 0; /*reserved */
|
||
}
|
||
|
||
H5F_addr_encode(f, &p, f->shared->base_addr);
|
||
H5F_addr_encode(f, &p, f->shared->freespace_addr);
|
||
H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf));
|
||
H5F_addr_encode(f, &p, f->shared->driver_addr);
|
||
|
||
if(H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp))<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information")
|
||
|
||
H5_ASSIGN_OVERFLOW(superblock_size, p - sbuf, int, size_t);
|
||
|
||
/* Double check we didn't overrun the block (unlikely) */
|
||
assert(superblock_size <= sizeof(sbuf));
|
||
|
||
/* Encode the driver information block. */
|
||
H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t);
|
||
|
||
if (driver_size > 0) {
|
||
driver_size += 16; /* Driver block header */
|
||
|
||
/* Double check we didn't overrun the block (unlikely) */
|
||
assert(driver_size <= sizeof(dbuf));
|
||
|
||
/* Encode the driver information block */
|
||
p = dbuf;
|
||
|
||
*p++ = HDF5_DRIVERINFO_VERSION; /* Version */
|
||
*p++ = 0; /* reserved */
|
||
*p++ = 0; /* reserved */
|
||
*p++ = 0; /* reserved */
|
||
|
||
/* Driver info size, excluding header */
|
||
UINT32ENCODE(p, driver_size - 16);
|
||
|
||
/* Encode driver-specific data */
|
||
if (H5FD_sb_encode(f->shared->lf, driver_name, dbuf + 16) < 0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
|
||
|
||
/* Driver name */
|
||
HDmemcpy(dbuf + 8, driver_name, 8);
|
||
} /* end if */
|
||
|
||
/* Compute super block checksum */
|
||
assert(sizeof(chksum) == sizeof(f->shared->super_chksum));
|
||
|
||
for (p = (uint8_t *)&chksum, chksum = 0, i = 0; i < superblock_size; ++i)
|
||
p[i % sizeof(f->shared->super_chksum)] ^= sbuf[i];
|
||
|
||
/* Compare with current checksums */
|
||
if (chksum != f->shared->super_chksum) {
|
||
/* Write superblock */
|
||
if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id,
|
||
f->shared->super_addr, superblock_size, sbuf) < 0)
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock")
|
||
|
||
/* Update checksum information if different */
|
||
f->shared->super_chksum = chksum;
|
||
}
|
||
|
||
/* Check for driver info block */
|
||
if (HADDR_UNDEF != f->shared->driver_addr) {
|
||
/* Compute driver info block checksum */
|
||
assert(sizeof(chksum) == sizeof(f->shared->drvr_chksum));
|
||
|
||
for (p = (uint8_t *)&chksum, chksum = 0, i = 0; i < driver_size; ++i)
|
||
p[i % sizeof(f->shared->drvr_chksum)] ^= dbuf[i];
|
||
|
||
/* Compare with current checksums */
|
||
if (chksum != f->shared->drvr_chksum) {
|
||
/* Write driver information block */
|
||
if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id,
|
||
f->shared->base_addr + f->shared->driver_addr, driver_size, dbuf) < 0)
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write driver information block")
|
||
|
||
/* Update checksum information if different */
|
||
f->shared->drvr_chksum = chksum;
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
/* Update the user's buffer, if given */
|
||
if (buf) {
|
||
HDmemcpy(buf, sbuf, superblock_size);
|
||
HDmemcpy(&buf[superblock_size], dbuf, driver_size);
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_flush
|
||
*
|
||
* Purpose: Flushes (and optionally invalidates) cached data plus the
|
||
* file super block. If the logical file size field is zero
|
||
* then it is updated to be the length of the super block.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 29 1997
|
||
*
|
||
* Modifications:
|
||
* rky 1998-08-28
|
||
* Only p0 writes metadata to disk.
|
||
*
|
||
* Robb Matzke, 1998-10-16
|
||
* Added the `scope' argument to indicate what should be
|
||
* flushed. If the value is H5F_SCOPE_GLOBAL then the entire
|
||
* virtual file is flushed; a value of H5F_SCOPE_LOCAL means
|
||
* that only the specified file is flushed. A value of
|
||
* H5F_SCOPE_DOWN means flush the specified file and all
|
||
* children.
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* If ALLOC_ONLY is non-zero then all this function does is
|
||
* allocate space for the userblock and superblock. Also
|
||
* rewritten to use the virtual file layer.
|
||
*
|
||
* Robb Matzke, 1999-08-16
|
||
* The driver information block is encoded and either allocated
|
||
* or written to disk.
|
||
*
|
||
* Raymond Lu, 2001-10-14
|
||
* Changed to new generic property list.
|
||
*
|
||
* Quincey Koziol, 2002-05-20
|
||
* Added 'closing' parameter
|
||
*
|
||
* Quincey Koziol, 2002-06-05
|
||
* Added boot block & driver info block checksumming, to avoid
|
||
* writing them out when they haven't changed.
|
||
*
|
||
* Quincey Koziol, 2002-06-06
|
||
* Return the remainders of the metadata & "small data" blocks to
|
||
* the free list of blocks for the file.
|
||
*
|
||
* Bill Wendling, 2003-03-18
|
||
* Modified the flags being passed in to be one flag instead
|
||
* of several.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags)
|
||
{
|
||
unsigned nerrors = 0; /* Errors from nested flushes */
|
||
unsigned i; /* Index variable */
|
||
herr_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_flush)
|
||
|
||
/* Sanity check arguments */
|
||
assert(f);
|
||
|
||
/*
|
||
* 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 H5F_flush() with the read-only handle, still causes data
|
||
* to be flushed.
|
||
*/
|
||
if (0 == (H5F_ACC_RDWR & f->shared->flags))
|
||
HGOTO_DONE(SUCCEED)
|
||
|
||
/* Flush other stuff depending on scope */
|
||
if (H5F_SCOPE_GLOBAL == scope) {
|
||
while (f->mtab.parent)
|
||
f = f->mtab.parent;
|
||
|
||
scope = H5F_SCOPE_DOWN;
|
||
}
|
||
|
||
if (H5F_SCOPE_DOWN == scope)
|
||
for (i = 0; i < f->mtab.nmounts; i++)
|
||
if (H5F_flush(f->mtab.child[i].file, dxpl_id, scope, flags) < 0)
|
||
nerrors++;
|
||
|
||
/* Flush any cached dataset storage raw data */
|
||
if (H5D_flush(f, dxpl_id, flags) < 0)
|
||
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
|
||
|
||
/*
|
||
* If we are invalidating everything (which only happens just before
|
||
* the file closes), release the unused portion of the metadata and
|
||
* "small data" blocks back to the free lists in the file.
|
||
*/
|
||
if (flags & H5F_FLUSH_INVALIDATE) {
|
||
#ifdef H5_HAVE_FPHDF5
|
||
/*
|
||
* If this is not the SAP, then we want to send a "free"
|
||
* command to the SAP to free up the EOMA and EOSDA
|
||
* information. This might also update the EOA information on
|
||
* the clients...
|
||
*/
|
||
if (H5FD_is_fphdf5_driver(f->shared->lf) && !H5FD_fphdf5_is_sap(f->shared->lf)) {
|
||
unsigned req_id = 0;
|
||
H5FP_status_t status = H5FP_STATUS_OK;
|
||
|
||
/* Send the request to the SAP */
|
||
if (H5FP_request_update_eoma_eosda(f->shared->lf,
|
||
&req_id, &status) != SUCCEED)
|
||
/* FIXME: Should we check the "status" variable here? */
|
||
HGOTO_ERROR(H5E_FPHDF5, H5E_CANTFREE, FAIL,
|
||
"server couldn't free from file")
|
||
} else {
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
|
||
if (f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) {
|
||
/* Return the unused portion of the metadata block to a free list */
|
||
if (f->shared->lf->eoma != 0)
|
||
if (H5FD_free(f->shared->lf, H5FD_MEM_DEFAULT, dxpl_id,
|
||
f->shared->lf->eoma, f->shared->lf->cur_meta_block_size) < 0)
|
||
HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free metadata block")
|
||
|
||
/* Reset metadata block information, just in case */
|
||
f->shared->lf->eoma=0;
|
||
f->shared->lf->cur_meta_block_size=0;
|
||
} /* end if */
|
||
|
||
if (f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) {
|
||
/* Return the unused portion of the "small data" block to a free list */
|
||
if (f->shared->lf->eosda != 0)
|
||
if (H5FD_free(f->shared->lf, H5FD_MEM_DRAW, dxpl_id,
|
||
f->shared->lf->eosda, f->shared->lf->cur_sdata_block_size) < 0)
|
||
HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free 'small data' block")
|
||
|
||
/* Reset "small data" block information, just in case */
|
||
f->shared->lf->eosda=0;
|
||
f->shared->lf->cur_sdata_block_size=0;
|
||
} /* end if */
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
}
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
} /* end if */
|
||
|
||
/* flush (and invalidate) the entire meta data cache */
|
||
/*
|
||
* FIXME: This should be CLEAR_ONLY for non-captain processes.
|
||
* Need to fix the H5G_mkroot() call so that only the captain
|
||
* allocates object headers (calls the H5O_init function...via a
|
||
* lot of other functions first)....
|
||
*/
|
||
if (H5AC_flush(f, dxpl_id, NULL, HADDR_UNDEF, flags & (H5F_FLUSH_INVALIDATE | H5F_FLUSH_CLEAR_ONLY)) < 0)
|
||
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush meta data cache")
|
||
|
||
/* Write the superblock to disk */
|
||
if (H5F_write_superblock(f, dxpl_id, NULL) != SUCCEED)
|
||
HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "unable to superblock to file")
|
||
|
||
/* Flush file buffers to disk. */
|
||
if (H5FD_flush(f->shared->lf, dxpl_id,
|
||
(unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0)
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
|
||
|
||
/* Check flush errors for children - errors are already on the stack */
|
||
ret_value = (nerrors ? FAIL : SUCCEED);
|
||
|
||
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
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1998-10-14
|
||
* Nothing happens unless the H5F_t reference count is one (the
|
||
* file is flushed anyway). The reference count is decremented
|
||
* by H5F_dest().
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* Modified to use the virtual file layer.
|
||
*
|
||
* Bill Wendling, 2003-03-18
|
||
* Modified H5F_flush call to take one flag instead of
|
||
* several Boolean flags.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_close(H5F_t *f)
|
||
{
|
||
H5F_close_degree_t fc_degree; /* What action to take when closing the last file ID for a file */
|
||
unsigned closing=0; /* Indicate that the file will be closed */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_close, FAIL)
|
||
|
||
assert(f->nrefs>0);
|
||
|
||
/*
|
||
* If this file is referenced more than once then just decrement the
|
||
* count and return.
|
||
*/
|
||
if (f->nrefs>1) {
|
||
/* Decrement reference counts */
|
||
if (H5F_dest(f, H5AC_dxpl_id)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
|
||
HGOTO_DONE(SUCCEED)
|
||
} /* end if */
|
||
|
||
/* Double-check that this file should be closed */
|
||
assert(1==f->nrefs);
|
||
|
||
/* Get the close degree from the file */
|
||
fc_degree = f->shared->fc_degree;
|
||
|
||
/* if close degree if "semi" and there are objects left open and we are
|
||
* holding open the file with this file ID, fail now */
|
||
if(fc_degree==H5F_CLOSE_SEMI && f->nopen_objs>0 && f->shared->nrefs==1)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
|
||
|
||
/*
|
||
* Unmount and close each child before closing the current file.
|
||
*/
|
||
assert(NULL==f->mtab.parent);
|
||
for (u=0; u<f->mtab.nmounts; u++) {
|
||
f->mtab.child[u].file->mtab.parent = NULL;
|
||
if(H5G_close(f->mtab.child[u].group)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group")
|
||
if(H5F_close(f->mtab.child[u].file)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
|
||
} /* end if */
|
||
f->mtab.nmounts = 0;
|
||
|
||
/*
|
||
* 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(fc_degree) {
|
||
case H5F_CLOSE_WEAK:
|
||
/*
|
||
* If object headers are still open then delay deletion of
|
||
* resources until they have all been closed. Flush all
|
||
* caches and update the object eader anyway so that failing toi
|
||
* close all objects isn't a major problem. If the file is on
|
||
* the H5I_FILE list then move it to the H5I_FILE_CLOSING list
|
||
* instead.
|
||
*/
|
||
if (f->nopen_objs>0) {
|
||
#ifdef H5F_DEBUG
|
||
if (H5DEBUG(F)) {
|
||
fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
|
||
"open (file close will complete when %s closed)\n",
|
||
f->name,
|
||
f->nopen_objs,
|
||
1 == f->nopen_objs?" is":"s are",
|
||
1 == f->nopen_objs?"that header is":"those headers are");
|
||
}
|
||
#endif
|
||
/* Register an ID for closing the file later */
|
||
if (!f->closing)
|
||
f->closing = H5I_register(H5I_FILE_CLOSING, f);
|
||
|
||
/* Invalidate file ID */
|
||
f->file_id = -1;
|
||
|
||
HGOTO_DONE(SUCCEED)
|
||
} else {
|
||
if (f->closing) {
|
||
|
||
#ifdef H5F_DEBUG
|
||
if (H5DEBUG(F))
|
||
fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
|
||
#endif
|
||
} /* end if */
|
||
|
||
/* Indicate that the file will be closing */
|
||
closing=1;
|
||
} /* end else */
|
||
break;
|
||
|
||
case H5F_CLOSE_SEMI:
|
||
if (f->nopen_objs>0) {
|
||
#ifdef H5F_DEBUG
|
||
if (H5DEBUG(F)) {
|
||
fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
|
||
"open (file close will complete when %s closed)\n",
|
||
f->name,
|
||
f->nopen_objs,
|
||
1 == f->nopen_objs?" is":"s are",
|
||
1 == f->nopen_objs?"that header is":"those headers are");
|
||
}
|
||
#endif
|
||
/* Register an ID for closing the file later */
|
||
if (!f->closing)
|
||
f->closing = H5I_register(H5I_FILE_CLOSING, f);
|
||
|
||
/* Invalidate file ID */
|
||
f->file_id = -1;
|
||
|
||
HGOTO_DONE(SUCCEED)
|
||
} else {
|
||
if (!f->closing && f->shared->nrefs>1)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
|
||
|
||
/* Indicate that the file will be closing */
|
||
closing=1;
|
||
} /* end else */
|
||
break;
|
||
|
||
case H5F_CLOSE_STRONG:
|
||
/* Force to close all opened objects in file */
|
||
while(f->nopen_objs > 0) {
|
||
int obj_count; /* # of open objects */
|
||
hid_t objs[128]; /* Array of objects to close */
|
||
int i; /* Local index variable */
|
||
|
||
/* Get the list of IDs of open dataset objects */
|
||
while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_DATASET, (sizeof(objs)/sizeof(objs[0])), objs))) {
|
||
|
||
/* Try to close all the open objects */
|
||
for(i=0; i<obj_count; i++)
|
||
if(H5I_dec_ref(objs[i]) < 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
|
||
} /* end while */
|
||
|
||
/* Get the list of IDs of open group objects */
|
||
while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_GROUP, (sizeof(objs)/sizeof(objs[0])), objs))) {
|
||
|
||
/* Try to close all the open objects */
|
||
for(i=0; i<obj_count; i++)
|
||
if(H5I_dec_ref(objs[i]) < 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
|
||
} /* end while */
|
||
|
||
/* Get the list of IDs of open named datatype objects */
|
||
while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_DATATYPE, (sizeof(objs)/sizeof(objs[0])), objs))) {
|
||
|
||
/* Try to close all the open objects */
|
||
for(i=0; i<obj_count; i++)
|
||
if(H5I_dec_ref(objs[i]) < 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
|
||
} /* end while */
|
||
|
||
/* Get the list of IDs of open attribute objects */
|
||
while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_ATTR, (sizeof(objs)/sizeof(objs[0])), objs))) {
|
||
|
||
/* Try to close all the open objects */
|
||
for(i=0; i<obj_count; i++)
|
||
if(H5I_dec_ref(objs[i]) < 0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
|
||
} /* end while */
|
||
} /* end while */
|
||
|
||
/* Indicate that the file will be closing */
|
||
closing=1;
|
||
break;
|
||
|
||
default:
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
|
||
} /* end switch */
|
||
|
||
/* Invalidate file ID */
|
||
f->file_id = -1;
|
||
|
||
/* Only flush at this point if the file will be closed */
|
||
assert(closing);
|
||
/* Dump debugging info */
|
||
#if H5AC_DUMP_STATS_ON_CLOSE
|
||
H5AC_stats(f);
|
||
#endif /* H5AC_DUMP_STATS_ON_CLOSE */
|
||
|
||
/* Only try to flush the file if it was opened with write access */
|
||
if(f->intent&H5F_ACC_RDWR) {
|
||
#ifdef H5_HAVE_FPHDF5
|
||
/*
|
||
* We only want the captain to perform the flush of the metadata
|
||
* to the file.
|
||
*/
|
||
if (!H5FD_is_fphdf5_driver(f->shared->lf) ||
|
||
H5FD_fphdf5_is_captain(f->shared->lf)) {
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
|
||
/* Flush and destroy all caches */
|
||
if (H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL,
|
||
H5F_FLUSH_INVALIDATE | H5F_FLUSH_CLOSING) < 0)
|
||
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
|
||
|
||
#ifdef H5_HAVE_FPHDF5
|
||
} else {
|
||
/*
|
||
* If this isn't the captain process, flush but only clear
|
||
* the flags.
|
||
*/
|
||
if (H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL,
|
||
H5F_FLUSH_INVALIDATE | H5F_FLUSH_CLOSING | H5F_FLUSH_CLEAR_ONLY) < 0)
|
||
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
|
||
}
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
} /* 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_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 (NULL==H5I_object_verify(file_id,H5I_FILE))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom")
|
||
|
||
/*
|
||
* Decrement reference count on atom. When it reaches zero the file will
|
||
* be closed.
|
||
*/
|
||
if (H5I_dec_ref (file_id)<0)
|
||
HGOTO_ERROR (H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_mount
|
||
*
|
||
* Purpose: Mount file CHILD onto the group specified by LOC and NAME,
|
||
* using mount properties in PLIST. CHILD must not already be
|
||
* mouted and must not be a mount ancestor of the mount-point.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, October 6, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 1998-10-14
|
||
* The reference count for the mounted H5F_t is incremented.
|
||
*
|
||
* Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002
|
||
* Added `id to name' support.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child,
|
||
hid_t UNUSED plist_id, hid_t dxpl_id)
|
||
{
|
||
H5G_t *mount_point = NULL; /*mount point group */
|
||
H5G_entry_t *mp_ent = NULL; /*mount point symbol table entry*/
|
||
H5F_t *ancestor = NULL; /*ancestor files */
|
||
H5F_t *parent = NULL; /*file containing mount point */
|
||
unsigned lt, rt, md; /*binary search indices */
|
||
int cmp; /*binary search comparison value*/
|
||
H5G_entry_t *ent = NULL; /*temporary symbol table entry */
|
||
H5G_entry_t mp_open_ent; /* entry of moint point to be opened */
|
||
H5RS_str_t *name_r; /* Ref-counted version of name */
|
||
herr_t ret_value = SUCCEED; /*return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_mount)
|
||
|
||
assert(loc);
|
||
assert(name && *name);
|
||
assert(child);
|
||
assert(TRUE==H5P_isa_class(plist_id,H5P_MOUNT));
|
||
|
||
/*
|
||
* Check that the child isn't mounted, that the mount point exists, and
|
||
* that the mount wouldn't introduce a cycle in the mount tree.
|
||
*/
|
||
if (child->mtab.parent)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted")
|
||
if (H5G_find(loc, name, NULL, &mp_open_ent/*out*/, H5AC_dxpl_id) < 0)
|
||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found");
|
||
if (NULL==(mount_point=H5G_open(&mp_open_ent, dxpl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found")
|
||
|
||
parent = H5G_fileof(mount_point);
|
||
mp_ent = H5G_entof(mount_point);
|
||
for (ancestor=parent; ancestor; ancestor=ancestor->mtab.parent) {
|
||
if (ancestor==child)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle")
|
||
}
|
||
|
||
/*
|
||
* Use a binary search to locate the position that the child should be
|
||
* inserted into the parent mount table. At the end of this paragraph
|
||
* `md' will be the index where the child should be inserted.
|
||
*/
|
||
lt = md = 0;
|
||
rt=parent->mtab.nmounts;
|
||
cmp = -1;
|
||
while (lt<rt && cmp) {
|
||
md = (lt+rt)/2;
|
||
ent = H5G_entof(parent->mtab.child[md].group);
|
||
cmp = H5F_addr_cmp(mp_ent->header, ent->header);
|
||
if (cmp<0) {
|
||
rt = md;
|
||
} else if (cmp>0) {
|
||
lt = md+1;
|
||
}
|
||
}
|
||
if (cmp>0)
|
||
md++;
|
||
if (!cmp)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use")
|
||
|
||
/* Make room in the table */
|
||
if (parent->mtab.nmounts>=parent->mtab.nalloc) {
|
||
unsigned n = MAX(16, 2*parent->mtab.nalloc);
|
||
H5F_mount_t *x = H5MM_realloc(parent->mtab.child,
|
||
n*sizeof(parent->mtab.child[0]));
|
||
if (!x)
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for mount table")
|
||
parent->mtab.child = x;
|
||
parent->mtab.nalloc = n;
|
||
}
|
||
|
||
/* Insert into table */
|
||
HDmemmove(parent->mtab.child+md+1, parent->mtab.child+md,
|
||
(parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
|
||
parent->mtab.nmounts++;
|
||
parent->mtab.child[md].group = mount_point;
|
||
parent->mtab.child[md].file = child;
|
||
child->mtab.parent = parent;
|
||
child->nrefs++;
|
||
|
||
/* Search the open IDs and replace names for mount operation */
|
||
/* We pass H5G_UNKNOWN as object type; search all IDs */
|
||
name_r=H5RS_wrap(name);
|
||
assert(name_r);
|
||
if (H5G_replace_name( H5G_UNKNOWN, loc, name_r, NULL, NULL, NULL, OP_MOUNT )<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to replace name")
|
||
if(H5RS_decr(name_r)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement name string")
|
||
|
||
done:
|
||
if (ret_value<0 && mount_point)
|
||
if(H5G_close(mount_point)<0)
|
||
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close mounted group")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_unmount
|
||
*
|
||
* Purpose: Unmount the child which is mounted at the group specified by
|
||
* LOC and NAME or fail if nothing is mounted there. Neither
|
||
* file is closed.
|
||
*
|
||
* Because the mount point is specified by name and opened as a
|
||
* group, the H5G_namei() will resolve it to the root of the
|
||
* mounted file, not the group where the file is mounted.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, October 6, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Robb Matzke, 1998-10-14
|
||
* The ref count for the child is decremented by calling H5F_close().
|
||
*
|
||
* Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002
|
||
* Added `id to name' support.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
|
||
{
|
||
H5G_t *mounted = NULL; /*mount point group */
|
||
H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */
|
||
H5F_t *child = NULL; /*mounted file */
|
||
H5F_t *parent = NULL; /*file where mounted */
|
||
H5G_entry_t *ent = NULL; /*temporary symbol table entry */
|
||
H5G_entry_t mnt_open_ent; /* entry used to open mount point*/
|
||
herr_t ret_value = FAIL; /*return value */
|
||
unsigned i; /*coutners */
|
||
unsigned lt, rt, md=0; /*binary search indices */
|
||
int cmp; /*binary search comparison value*/
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_unmount)
|
||
|
||
assert(loc);
|
||
assert(name && *name);
|
||
|
||
/*
|
||
* Get the mount point, or more precisely the root of the mounted file.
|
||
* If we get the root group and the file has a parent in the mount tree,
|
||
* then we must have found the mount point.
|
||
*/
|
||
if (H5G_find(loc, name, NULL, &mnt_open_ent/*out*/, H5AC_dxpl_id) < 0)
|
||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found");
|
||
if (NULL==(mounted=H5G_open(&mnt_open_ent, dxpl_id)))
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found")
|
||
child = H5G_fileof(mounted);
|
||
mnt_ent = H5G_entof(mounted);
|
||
ent = H5G_entof(child->shared->root_grp);
|
||
|
||
if (child->mtab.parent &&
|
||
H5F_addr_eq(mnt_ent->header, ent->header)) {
|
||
/*
|
||
* We've been given the root group of the child. We do a reverse
|
||
* lookup in the parent's mount table to find the correct entry.
|
||
*/
|
||
parent = child->mtab.parent;
|
||
for (i=0; i<parent->mtab.nmounts; i++) {
|
||
if (parent->mtab.child[i].file==child) {
|
||
/* Search the open IDs replace names to reflect unmount operation */
|
||
if (H5G_replace_name( H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0)
|
||
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ")
|
||
|
||
/* Unmount the child */
|
||
parent->mtab.nmounts -= 1;
|
||
if(H5G_close(parent->mtab.child[i].group)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
|
||
child->mtab.parent = NULL;
|
||
if(H5F_close(child)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
|
||
HDmemmove(parent->mtab.child+i, parent->mtab.child+i+1,
|
||
(parent->mtab.nmounts-i)* sizeof(parent->mtab.child[0]));
|
||
ret_value = SUCCEED;
|
||
}
|
||
}
|
||
assert(ret_value>=0);
|
||
|
||
} else {
|
||
/*
|
||
* We've been given the mount point in the parent. We use a binary
|
||
* search in the parent to locate the mounted file, if any.
|
||
*/
|
||
parent = child; /*we guessed wrong*/
|
||
lt = 0;
|
||
rt = parent->mtab.nmounts;
|
||
cmp = -1;
|
||
while (lt<rt && cmp) {
|
||
md = (lt+rt)/2;
|
||
ent = H5G_entof(parent->mtab.child[md].group);
|
||
cmp = H5F_addr_cmp(mnt_ent->header, ent->header);
|
||
if (cmp<0) {
|
||
rt = md;
|
||
} else {
|
||
lt = md+1;
|
||
}
|
||
}
|
||
if (cmp)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point")
|
||
|
||
/* Unmount the child */
|
||
parent->mtab.nmounts -= 1;
|
||
if(H5G_close(parent->mtab.child[md].group)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
|
||
parent->mtab.child[md].file->mtab.parent = NULL;
|
||
if(H5F_close(parent->mtab.child[md].file)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
|
||
HDmemmove(parent->mtab.child+md, parent->mtab.child+md+1,
|
||
(parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
|
||
ret_value = SUCCEED;
|
||
}
|
||
|
||
done:
|
||
if (mounted)
|
||
if(H5G_close(mounted)<0 && ret_value>=0)
|
||
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close group")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_mountpoint
|
||
*
|
||
* Purpose: If ENT is a mount point then copy the entry for the root
|
||
* group of the mounted file into ENT.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, October 6, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002
|
||
* Added `id to name' support.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5F_mountpoint(H5G_entry_t *find/*in,out*/)
|
||
{
|
||
H5F_t *parent = find->file;
|
||
unsigned lt, rt, md=0;
|
||
int cmp;
|
||
H5G_entry_t *ent = NULL;
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_mountpoint, FAIL)
|
||
|
||
assert(find);
|
||
|
||
/*
|
||
* The loop is necessary because we might have file1 mounted at the root
|
||
* of file2, which is mounted somewhere in file3.
|
||
*/
|
||
do {
|
||
/*
|
||
* Use a binary search to find the potential mount point in the mount
|
||
* table for the parent
|
||
*/
|
||
lt = 0;
|
||
rt = parent->mtab.nmounts;
|
||
cmp = -1;
|
||
while (lt<rt && cmp) {
|
||
md = (lt+rt)/2;
|
||
ent = H5G_entof(parent->mtab.child[md].group);
|
||
cmp = H5F_addr_cmp(find->header, ent->header);
|
||
if (cmp<0) {
|
||
rt = md;
|
||
} else {
|
||
lt = md+1;
|
||
}
|
||
}
|
||
|
||
/* Copy root info over to ENT */
|
||
if (0==cmp) {
|
||
/* Get the entry for the root group in the child's file */
|
||
ent = H5G_entof(parent->mtab.child[md].file->shared->root_grp);
|
||
|
||
/* Don't lose the user path of the group when we copy the root group's entry */
|
||
if(H5G_ent_copy(find,ent,H5G_COPY_LIMITED)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy group entry")
|
||
|
||
/* Switch to child's file */
|
||
parent = ent->file;
|
||
}
|
||
} while (!cmp);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_has_mount
|
||
*
|
||
* Purpose: Check if a file has mounted files within it.
|
||
*
|
||
* Return: Success: TRUE/FALSE
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, January 2, 2002
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5F_has_mount(const H5F_t *file)
|
||
{
|
||
htri_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_has_mount, FAIL)
|
||
|
||
assert(file);
|
||
|
||
if(file->mtab.nmounts>0)
|
||
ret_value=TRUE;
|
||
else
|
||
ret_value=FALSE;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_has_mount() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_is_mount
|
||
*
|
||
* Purpose: Check if a file is mounted within another file.
|
||
*
|
||
* Return: Success: TRUE/FALSE
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, January 2, 2002
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5F_is_mount(const H5F_t *file)
|
||
{
|
||
htri_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_is_mount, FAIL)
|
||
|
||
assert(file);
|
||
|
||
if(file->mtab.parent!=NULL)
|
||
ret_value=TRUE;
|
||
else
|
||
ret_value=FALSE;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_is_mount() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Fmount
|
||
*
|
||
* Purpose: Mount file CHILD_ID onto the group specified by LOC_ID and
|
||
* NAME using mount properties PLIST_ID.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, October 6, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
|
||
{
|
||
H5G_entry_t *loc = NULL;
|
||
H5F_t *child = NULL;
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_API(H5Fmount, FAIL)
|
||
H5TRACE4("e","isii",loc_id,name,child_id,plist_id);
|
||
|
||
/* Check arguments */
|
||
if (NULL==(loc=H5G_loc(loc_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
|
||
if (!name || !*name)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
|
||
if (NULL==(child=H5I_object_verify(child_id,H5I_FILE)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
|
||
if(H5P_DEFAULT == plist_id)
|
||
plist_id = H5P_MOUNT_DEFAULT;
|
||
else
|
||
if(TRUE != H5P_isa_class(plist_id, H5P_MOUNT))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not property list")
|
||
|
||
/* Do the mount */
|
||
if (H5F_mount(loc, name, child, plist_id, H5AC_dxpl_id)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Funmount
|
||
*
|
||
* Purpose: Given a mount point, dissassociate the mount point's file
|
||
* from the file mounted there. Do not close either file.
|
||
*
|
||
* The mount point can either be the group in the parent or the
|
||
* root group of the mounted file (both groups have the same
|
||
* name). If the mount point was opened before the mount then
|
||
* it's the group in the parent, but if it was opened after the
|
||
* mount then it's the root group of the child.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, October 6, 1998
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5Funmount(hid_t loc_id, const char *name)
|
||
{
|
||
H5G_entry_t *loc = NULL;
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_API(H5Funmount, FAIL)
|
||
H5TRACE2("e","is",loc_id,name);
|
||
|
||
/* Check args */
|
||
if (NULL==(loc=H5G_loc(loc_id)))
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
|
||
if (!name || !*name)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
|
||
|
||
/* Unmount */
|
||
if (H5F_unmount(loc, name, H5AC_dxpl_id)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file")
|
||
|
||
done:
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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);
|
||
|
||
if (NULL==(old_file=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)))
|
||
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;
|
||
|
||
if ((ret_value=H5I_register(H5I_FILE, new_file))<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_close(new_file)<0)
|
||
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
|
||
FUNC_LEAVE_API(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_get_intent
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: 'intent' on success/abort on failure (shouldn't fail)
|
||
*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* September 29, 2000
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
unsigned
|
||
H5F_get_intent(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent)
|
||
|
||
assert(f);
|
||
|
||
FUNC_LEAVE_NOAPI(f->intent)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sizeof_addr
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the size of the file's size_t
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: 'sizeof_addr' on success/abort on failure (shouldn't fail)
|
||
*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* September 29, 2000
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Raymond Lu, Oct 14, 2001
|
||
* Changed to generic property list.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t
|
||
H5F_sizeof_addr(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->sizeof_addr)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sizeof_size
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the size of the file's off_t
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: 'sizeof_size' on success/abort on failure (shouldn't fail)
|
||
*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* September 29, 2000
|
||
*
|
||
* Modifications:
|
||
*
|
||
* Raymond Lu, Oct 14, 2001
|
||
* Changed to the new generic property list.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t
|
||
H5F_sizeof_size(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->sizeof_size)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sym_leaf_k
|
||
*
|
||
* Purpose: Replaced a macro to retrieve the symbol table leaf size,
|
||
* now that the generic properties are being used to store
|
||
* the values.
|
||
*
|
||
* Return: Success: Non-negative, and the symbol table leaf size is
|
||
* returned.
|
||
*
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* slu@ncsa.uiuc.edu
|
||
* Oct 14 2001
|
||
*
|
||
* Modifications:
|
||
* Quincey Koziol, 2001-10-15
|
||
* Added this header and removed unused ret_value variable.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
unsigned H5F_sym_leaf_k(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_Kvalue
|
||
*
|
||
* Purpose: Replaced a macro to retrieve a B-tree key value for a certain
|
||
* type, now that the generic properties are being used to store
|
||
* the B-tree values.
|
||
*
|
||
* Return: Success: Non-negative, and the B-tree key value is
|
||
* returned.
|
||
*
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* slu@ncsa.uiuc.edu
|
||
* Oct 14 2001
|
||
*
|
||
* Modifications:
|
||
* Quincey Koziol, 2001-10-15
|
||
* Added this header and removed unused ret_value variable.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
unsigned
|
||
H5F_Kvalue(const H5F_t *f, const H5B_class_t *type)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
assert(type);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id])
|
||
} /* end H5F_Kvalue() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_rdcc_nelmts
|
||
*
|
||
* Purpose: Replaced a macro to retrieve the raw data cache number of elments,
|
||
* now that the generic properties are being used to store
|
||
* the values.
|
||
*
|
||
* Return: Success: Non-negative, and the raw data cache number of
|
||
* of elemnts is returned.
|
||
*
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Jun 1 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t H5F_rdcc_nelmts(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts)
|
||
} /* end H5F_rdcc_nelmts() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_rdcc_nbytes
|
||
*
|
||
* Purpose: Replaced a macro to retrieve the raw data cache number of bytes,
|
||
* now that the generic properties are being used to store
|
||
* the values.
|
||
*
|
||
* Return: Success: Non-negative, and the raw data cache number of
|
||
* of bytes is returned.
|
||
*
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Jun 1 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t H5F_rdcc_nbytes(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes)
|
||
} /* end H5F_rdcc_nbytes() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_rdcc_w0
|
||
*
|
||
* Purpose: Replaced a macro to retrieve the raw data cache 'w0' value
|
||
* now that the generic properties are being used to store
|
||
* the values.
|
||
*
|
||
* Return: Success: Non-negative, and the raw data cache 'w0' value
|
||
* is returned.
|
||
*
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Jun 2 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
double H5F_rdcc_w0(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->rdcc_w0)
|
||
} /* end H5F_rdcc_w0() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_has_feature
|
||
*
|
||
* Purpose: Check if a file has a particular feature enabled
|
||
*
|
||
* Return: Success: Non-negative - TRUE or FALSE
|
||
* Failure: Negative (should not happen)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* May 31 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hbool_t H5F_has_feature(const H5F_t *f, unsigned feature)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->lf->feature_flags&feature);
|
||
} /* end H5F_has_feature() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_get_driver_id
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: 'driver_id' on success/abort on failure (shouldn't fail)
|
||
*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* October 10, 2000
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5F_get_driver_id(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
assert(f->shared->lf);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->lf->driver_id)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_get_fileno
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* March 27, 2002
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
|
||
{
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
assert(f->shared->lf);
|
||
assert(filenum);
|
||
|
||
/* Retrieve the file's serial number */
|
||
if(H5FD_get_fileno(f->shared->lf,filenum)<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_get_fileno() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hid_t
|
||
H5F_get_id(H5F_t *file)
|
||
{
|
||
hid_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT(H5F_get_id)
|
||
|
||
assert(file);
|
||
|
||
if(file->file_id == -1) {
|
||
if(H5I_remove(file->closing)==NULL)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_READERROR, FAIL, "unable to remove from closing list")
|
||
|
||
/* Get an atom for the file */
|
||
if ((file->file_id = H5I_register(H5I_FILE, file))<0)
|
||
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
|
||
|
||
/* Indicate file is not closing */
|
||
file->closing = 0;
|
||
} else {
|
||
/* Increment reference count on atom. */
|
||
if (H5I_inc_ref(file->file_id)<0)
|
||
HGOTO_ERROR (H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed");
|
||
}
|
||
|
||
ret_value = file->file_id;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_get_id() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_get_base_addr
|
||
*
|
||
* Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value
|
||
* (Mainly added to stop non-file routines from poking about in the
|
||
* H5F_t data structure)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
|
||
* December 20, 2002
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
haddr_t
|
||
H5F_get_base_addr(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->base_addr)
|
||
} /* end H5F_get_base_addr() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
haddr_t
|
||
H5F_get_eoa(const H5F_t *f)
|
||
{
|
||
haddr_t ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_get_eoa, HADDR_UNDEF)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
/* Dispatch to driver */
|
||
if (HADDR_UNDEF==(ret_value=H5FD_get_eoa(f->shared->lf)))
|
||
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_get_eoa() */
|
||
|
||
#ifdef H5_HAVE_PARALLEL
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_mpi_get_rank
|
||
*
|
||
* Purpose: Retrieves the rank of an MPI process.
|
||
*
|
||
* Return: Success: The rank (non-negative)
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, January 30, 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5F_mpi_get_rank(const H5F_t *f)
|
||
{
|
||
int ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL)
|
||
|
||
assert(f && f->shared);
|
||
|
||
/* Dispatch to driver */
|
||
if ((ret_value=H5FD_mpi_get_rank(f->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_mpi_get_rank() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_mpi_get_comm
|
||
*
|
||
* Purpose: Retrieves the file's communicator
|
||
*
|
||
* Return: Success: The communicator (non-negative)
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, January 30, 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
MPI_Comm
|
||
H5F_mpi_get_comm(const H5F_t *f)
|
||
{
|
||
MPI_Comm ret_value;
|
||
|
||
FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL)
|
||
|
||
assert(f && f->shared);
|
||
|
||
/* Dispatch to driver */
|
||
if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
|
||
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5F_mpi_get_comm() */
|
||
#endif /* H5_HAVE_PARALLEL */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_grp_btree_shared
|
||
*
|
||
* Purpose: Replaced a macro to retrieve the shared B-tree node info
|
||
* now that the generic properties are being used to store
|
||
* the values.
|
||
*
|
||
* Return: Success: Non-void, and the shared B-tree node info
|
||
* is returned.
|
||
*
|
||
* Failure: void (should not happen)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Jul 5 2004
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5RC_t *H5F_grp_btree_shared(const H5F_t *f)
|
||
{
|
||
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
|
||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared)
|
||
|
||
assert(f);
|
||
assert(f->shared);
|
||
|
||
FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared)
|
||
} /* end H5F_grp_btree_shared() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_block_read
|
||
*
|
||
* Purpose: Reads some data from a file/server/etc into a buffer.
|
||
* The data is contiguous. The address is relative to the base
|
||
* address for the file.
|
||
*
|
||
* Errors:
|
||
* IO READERROR Low-level read failed.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Jul 10 1997
|
||
*
|
||
* Modifications:
|
||
* Albert Cheng, 1998-06-02
|
||
* Added XFER_MODE argument
|
||
*
|
||
* Robb Matzke, 1999-07-28
|
||
* The ADDR argument is passed by value.
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* Modified to use the virtual file layer. The data transfer
|
||
* property list is passed in by object ID since that's how the
|
||
* virtual file layer needs it.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id,
|
||
void *buf/*out*/)
|
||
{
|
||
haddr_t abs_addr;
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
|
||
|
||
assert (f);
|
||
assert (f->shared);
|
||
assert(size<SIZET_MAX);
|
||
assert (buf);
|
||
|
||
/* convert the relative address to an absolute address */
|
||
abs_addr = f->shared->base_addr + addr;
|
||
|
||
/* Read the data */
|
||
if (H5FD_read(f->shared->lf, type, dxpl_id, abs_addr, size, buf)<0)
|
||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_block_write
|
||
*
|
||
* Purpose: Writes some data from memory to a file/server/etc. The
|
||
* data is contiguous. The address is relative to the base
|
||
* address.
|
||
*
|
||
* Errors:
|
||
* IO WRITEERROR Low-level write failed.
|
||
* IO WRITEERROR No write intent.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Jul 10 1997
|
||
*
|
||
* Modifications:
|
||
* Albert Cheng, 1998-06-02
|
||
* Added XFER_MODE argument
|
||
*
|
||
* Robb Matzke, 1999-07-28
|
||
* The ADDR argument is passed by value.
|
||
*
|
||
* Robb Matzke, 1999-08-02
|
||
* Modified to use the virtual file layer. The data transfer
|
||
* property list is passed in by object ID since that's how the
|
||
* virtual file layer needs it.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
|
||
hid_t dxpl_id, const void *buf)
|
||
{
|
||
haddr_t abs_addr;
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
|
||
|
||
assert (f);
|
||
assert (f->shared);
|
||
assert (size<SIZET_MAX);
|
||
assert (buf);
|
||
|
||
if (0==(f->intent & H5F_ACC_RDWR))
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent")
|
||
|
||
/* Convert the relative address to an absolute address */
|
||
abs_addr = f->shared->base_addr + addr;
|
||
|
||
/* Write the data */
|
||
if (H5FD_write(f->shared->lf, type, dxpl_id, abs_addr, size, buf))
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
* Robb Matzke, 1999-07-28
|
||
* The ADDR argument is passed by value.
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void
|
||
H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr)
|
||
{
|
||
unsigned i;
|
||
|
||
assert(f);
|
||
assert(pp && *pp);
|
||
|
||
if (H5F_addr_defined(addr)) {
|
||
for (i=0; i<H5F_SIZEOF_ADDR(f); i++) {
|
||
*(*pp)++ = (uint8_t)(addr & 0xff);
|
||
addr >>= 8;
|
||
}
|
||
assert("overflow" && 0 == addr);
|
||
|
||
} else {
|
||
for (i=0; i<H5F_SIZEOF_ADDR(f); i++)
|
||
*(*pp)++ = 0xff;
|
||
}
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void
|
||
H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
|
||
{
|
||
unsigned i;
|
||
haddr_t tmp;
|
||
uint8_t c;
|
||
hbool_t all_zero = TRUE;
|
||
|
||
assert(f);
|
||
assert(pp && *pp);
|
||
assert(addr_p);
|
||
|
||
*addr_p = 0;
|
||
|
||
for (i=0; i<H5F_SIZEOF_ADDR(f); i++) {
|
||
c = *(*pp)++;
|
||
if (c != 0xff)
|
||
all_zero = FALSE;
|
||
|
||
if (i<sizeof(*addr_p)) {
|
||
tmp = c;
|
||
tmp <<= (i * 8); /*use tmp to get casting right */
|
||
*addr_p |= tmp;
|
||
} else if (!all_zero) {
|
||
assert(0 == **pp); /*overflow */
|
||
}
|
||
}
|
||
if (all_zero)
|
||
*addr_p = HADDR_UNDEF;
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5Fget_freespace
|
||
*
|
||
* Purpose: Retrieves the amount of free space (of a given type) in the
|
||
* file. If TYPE is 'H5FD_MEM_DEFAULT', then the amount of free
|
||
* space for all types is returned.
|
||
*
|
||
* Return: Success: Amount of free space for type
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Oct 6, 2003
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
hssize_t
|
||
H5Fget_freespace(hid_t file_id)
|
||
{
|
||
H5F_t *file=NULL; /* File object for file ID */
|
||
hssize_t ret_value; /* Return value */
|
||
|
||
FUNC_ENTER_API(H5Fget_freespace, FAIL)
|
||
H5TRACE1("Hs","i",file_id);
|
||
|
||
/* Check args */
|
||
if(NULL==(file=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((ret_value = H5FD_get_freespace(file->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
|
||
|
||
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=NULL; /* File object for file ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
haddr_t eof;
|
||
|
||
FUNC_ENTER_API(H5Fget_filesize, FAIL)
|
||
H5TRACE2("e","i*h",file_id,size);
|
||
|
||
/* Check args */
|
||
if(NULL==(file=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((eof = H5FDget_eof(file->shared->lf))==HADDR_UNDEF)
|
||
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_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
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
ssize_t
|
||
H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
|
||
{
|
||
H5G_entry_t *ent; /*symbol table entry */
|
||
size_t len=0;
|
||
ssize_t ret_value;
|
||
|
||
FUNC_ENTER_API (H5Fget_name, FAIL);
|
||
H5TRACE3("Zs","ixz",obj_id,name,size);
|
||
|
||
/* get symbol table entry */
|
||
if((ent = H5G_loc(obj_id))==NULL)
|
||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID")
|
||
|
||
len = HDstrlen(ent->file->name);
|
||
|
||
if(name) {
|
||
HDstrncpy(name, ent->file->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() */
|
||
|