mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-10-07 04:02:30 +03:00
---------------------- ./configure.in ./src/H5Fprivate.h ./src/H5Fsec2.c We now detect and use lseek64() on systems that have it (e.g., Irix64) and are able to generate >2GB files on Irix XFS file systems (and anything else that supports large files). This change also removed some warning messages from the Irix `-64' compiler. > $ ls -l istore.h5 > -rw-r--r-- 1 matzke meshtv 8605436856 Feb 17 14:03 istore.h5 ./configure.in ./src/H5Fprivate.h ./src/H5Fstdio.h We now detect and use fseek64() on systems that have it (e.g., Irix64) and are able to generate >2GB files on Irix XFS file systems (and anything else that supports large files). This change also removed some warning messages from the Iris `-64' compiler. ./src/H5E.c ./src/H5Epublic.h Added the H5E_OVERFLOW error to signal file address overflow. ./src/H5Fpublic.h ./examples/h5_chunk_read.c ./examples/h5_compound.c ./examples/h5_extend_write.c ./examples/h5_group.c ./examples/h5_read.c ./examples/h5_write.c ./html/Datasets.html ./html/Files.html ./html/H5.api.html ./html/H5.intro.html ./html/H5.sample_code.html ./html/ph5example.c ./html/review1.html ./test/cmpd_dset.c ./test/dsets.c ./test/extend.c ./test/tfile.c ./test/th5p.c ./test/theap.c ./test/tohdr.c ./test/tstab.c ./testpar/phdf5.c Renamed file access constants to follow the naming scheme. Also changed the base names a little to be more accurate as to what they do. The old names H5ACC_WRITE and H5ACC_OVERWRITE will temporarily work. H5ACC_DEFAULT --> H5F_ACC_RDONLY for H5Fopen() H5ACC_DEFAULT --> H5F_ACC_EXCL for H5Fcreate() H5ACC_WRITE --> H5F_ACC_RDWR H5ACC_OVERWRITE --> H5F_ACC_TRUNC Albert or Kim: The H5ACC_INDEPENDENT and H5ACC_COLLECTIVE macros in H5Fpublic.h should be an enum typedef and have names more like H5F_MPIO_INDEPENDENT and H5F_MPIO_COLLECTIVE. Also change the access_mode argument of H5Cset_mpio(). H5Fcreate() and H5Fopen() are more strict now about which flags are acceptable for the operation. ./src/H5Fprivate.h ./src/H5F.c ./src/H5C.c Changed the file access template to make it more general. A union contains a struct for each type of low-level driver and the default template is initialized at run-time. ./src/H5Fpublic.h ./src/H5F.c Added H5Fget_access_template() and cleaned up H5Fget_create_template(). ./src/H5C.c The H5Cset_mpi() no longer trashes the file access template when an error is detected. We check for errors and *then* update the file access template. Added H5C_close() so Albert and Kim have a place to release the MPI communicator and info from the file access property list. Kim or Albert: I notice in H5Cset_mpi() you copy the MPI communicator. Do you need to do something similar in H5C_copy()? ./src/H5F.c Added more error checking for the file creation and access property lists because it used to be possible to make the library dump core by swapping the creation and access property list ID numbers of H5Fcreate(). ./test/istore.c ./test/tfile.c ./test/th5p.c ./test/theap.c ./test/tohdr.c ./test/tstab.c ./testpar/testphdf5.c One must pass H5C_DEFAULT as the file creation or access property list in order to get the default property list. It is no longer possible to pass zero or any other arbitrary bad object ID. ./src/H5Fcore.c ./src/H5Ffamly.c ./src/H5Flow.c ./src/H5Fmpio.c ./src/H5Fsec2.c ./src/H5Fsplit.c ./src/H5Fstdio.c ./src/H5MF.c The file access property list is passed to all H5F_low_...() functions and to the drivers. ./src/H5Fcore.c The block size can be set at run time on a per-file basis instead of at compile time across all files. The "5000 items in a group test" now takes 1.6 seconds. ./src/H5private.h Removed inclusion of mpi.h and mpio.h since they're included from H5public.h. ./src/H5Cpublic.h ./src/H5C.c Added H5Cset_stdio(), H5Cset_sec2(), H5Cset_core(), H5Cset_split(), and H5Cset_family() in addition to the H5Cset_mpio() that Kim and Albert already wrote. We still need the H5Cget_driver() and an H5Cget...() counterpart for each of those functions. The split and family drivers still need a little work but I'm checking this in anyway.
887 lines
25 KiB
C
887 lines
25 KiB
C
/*
|
|
* Copyright (C) 1997 NCSA
|
|
* All rights reserved.
|
|
*
|
|
* Programmer: Robb Matzke <matzke@viper.llnl.gov>
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Purpose: This file contains virtual functions for the H5F_low
|
|
* class. These are functions that operate on various kinds
|
|
* of files at a level where the file is just a one-dimensional
|
|
* array of bytes.
|
|
*/
|
|
#include <H5private.h>
|
|
#include <H5Eprivate.h>
|
|
#include <H5Fprivate.h>
|
|
#include <H5MMprivate.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#define addr_defined(X) (((uint64)(-1)!=(X)->offset) ? TRUE : FALSE)
|
|
|
|
#define PABLO_MASK H5F_low
|
|
static hbool_t interface_initialize_g = FALSE;
|
|
#define INTERFACE_INIT NULL
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_class
|
|
*
|
|
* Purpose: Given a driver identifier return the class pointer for that
|
|
* low-level driver.
|
|
*
|
|
* Return: Success: A low-level driver class pointer.
|
|
*
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, February 18, 1998
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
const H5F_low_class_t *
|
|
H5F_low_class (H5F_driver_t driver)
|
|
{
|
|
const H5F_low_class_t *type = NULL;
|
|
|
|
FUNC_ENTER (H5F_low_class, NULL);
|
|
|
|
switch (driver) {
|
|
case H5F_LOW_STDIO:
|
|
type = H5F_LOW_STDIO_g;
|
|
break;
|
|
|
|
case H5F_LOW_SEC2:
|
|
type = H5F_LOW_SEC2_g;
|
|
break;
|
|
|
|
case H5F_LOW_CORE:
|
|
type = H5F_LOW_CORE_g;
|
|
break;
|
|
|
|
#ifdef HAVE_PARALLEL
|
|
case H5F_LOW_MPIO:
|
|
type = H5F_LOW_MPIO_g;
|
|
break;
|
|
#endif
|
|
|
|
case H5F_LOW_SPLIT:
|
|
type = H5F_LOW_SPLIT_g;
|
|
break;
|
|
|
|
case H5F_LOW_FAMILY:
|
|
type = H5F_LOW_FAMILY_g;
|
|
break;
|
|
|
|
default:
|
|
HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, NULL,
|
|
"unknown low-level driver");
|
|
}
|
|
|
|
FUNC_LEAVE (type);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_open
|
|
*
|
|
* Purpose: Opens a file of type TYPE with name NAME according to the
|
|
* field of bit flags FLAGS which are:
|
|
*
|
|
* H5F_ACC_WRITE: The file is open for read/write access.
|
|
* Without this bit set, the file would be open
|
|
* for read-only access.
|
|
*
|
|
* H5F_ACC_CREAT: The file is created if it doesn't already
|
|
* exist. On unix, the file permissions are set
|
|
* to 0666 modified by the umask.
|
|
*
|
|
* H5F_ACC_EXCL: This function will fail if the file already
|
|
* exists.
|
|
*
|
|
* H5F_ACC_TRUNC: Truncate the file to a zero-length file as it
|
|
* is opened. This allows existing files to be
|
|
* overwritten.
|
|
*
|
|
* The KEY argument is initialized with data which is unique to
|
|
* this file. Opening the same file (even by a different name)
|
|
* should return the same key.
|
|
*
|
|
* This is a virtual function only; the actual open operation is
|
|
* performed by the subclass. This function will fail if the
|
|
* subclass hasn't defined an open method.
|
|
*
|
|
* Errors:
|
|
* IO CANTOPENFILE Open failed.
|
|
*
|
|
* Return: Success: Pointer to the new file descriptor.
|
|
*
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5F_low_t *
|
|
H5F_low_open(const H5F_low_class_t *type, const char *name,
|
|
const H5F_access_t *access_parms, uintn flags,
|
|
H5F_search_t *key/*out*/)
|
|
{
|
|
H5F_low_t *lf = NULL;
|
|
|
|
FUNC_ENTER(H5F_low_open, NULL);
|
|
|
|
assert(type && type->open);
|
|
assert(name && *name);
|
|
|
|
if (NULL == (lf = (type->open) (name, access_parms, flags, key))) {
|
|
HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed");
|
|
}
|
|
lf->type = type;
|
|
|
|
FUNC_LEAVE(lf);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_close
|
|
*
|
|
* Purpose: Closes a low-level file. The subclass should free all
|
|
* resources used by the file descriptor but should not free the
|
|
* file descriptor itself. The close method in the subclass is
|
|
* optional; lack of a close method results in only the file
|
|
* descriptor being freed.
|
|
*
|
|
* It is safe to call this function with a null pointer for the
|
|
* file descriptor. This function returns a null pointer that
|
|
* the caller can assign to the file descriptor pointer as it's
|
|
* closed like `desc=H5F_low_close(desc)'.
|
|
*
|
|
* Errors:
|
|
* IO CLOSEERROR Close failed.
|
|
*
|
|
* Return: Success: NULL
|
|
*
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5F_low_t *
|
|
H5F_low_close(H5F_low_t *lf, const H5F_access_t *access_parms)
|
|
{
|
|
FUNC_ENTER(H5F_low_close, NULL);
|
|
|
|
if (lf) {
|
|
if ((lf->type->close) (lf, access_parms) < 0) {
|
|
H5MM_xfree(lf);
|
|
HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, NULL, "close failed");
|
|
}
|
|
H5MM_xfree(lf);
|
|
}
|
|
FUNC_LEAVE(NULL);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_read
|
|
*
|
|
* Purpose: Reads SIZE bytes of data beginning at address ADDR of the
|
|
* file LF and puts the result in BUF. Behavior when reading
|
|
* past the logical or physical end of file is to return zeros
|
|
* for that part of the request.
|
|
*
|
|
* This is only a virtual function; the subclass must define a
|
|
* read method or this function will fail.
|
|
*
|
|
* Errors:
|
|
* IO READERROR Read failed.
|
|
* IO UNSUPPORTED No read method.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5F_low_read(H5F_low_t *lf, const H5F_access_t *access_parms,
|
|
const haddr_t *addr, size_t size, uint8 *buf/*out*/)
|
|
{
|
|
herr_t ret_value = FAIL;
|
|
|
|
FUNC_ENTER(H5F_low_read, FAIL);
|
|
|
|
assert(lf && lf->type);
|
|
assert(addr && addr_defined(addr));
|
|
assert(buf);
|
|
|
|
if (lf->type->read) {
|
|
if ((ret_value = (lf->type->read) (lf, access_parms, addr, size,
|
|
buf)) < 0) {
|
|
HRETURN_ERROR(H5E_IO, H5E_READERROR, ret_value, "read failed");
|
|
}
|
|
} else {
|
|
HRETURN_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "no read method");
|
|
}
|
|
|
|
FUNC_LEAVE(ret_value);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_write
|
|
*
|
|
* Purpose: Writes SIZE bytes of data from BUF into the file LF beginning
|
|
* at address ADDR of the file. Writing past the logical or
|
|
* physical end of file causes the file to be extended.
|
|
*
|
|
* This is a virtual function only; if the subclass doesn't
|
|
* define a write method then this function will fail.
|
|
*
|
|
* Errors:
|
|
* IO UNSUPPORTED No write method.
|
|
* IO WRITEERROR Write failed.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5F_low_write(H5F_low_t *lf, const H5F_access_t *access_parms,
|
|
const haddr_t *addr, size_t size, const uint8 *buf)
|
|
{
|
|
herr_t ret_value = FAIL;
|
|
haddr_t tmp_addr;
|
|
|
|
FUNC_ENTER(H5F_low_write, FAIL);
|
|
|
|
assert(lf && lf->type);
|
|
assert(addr && addr_defined(addr));
|
|
assert(buf);
|
|
|
|
/* Extend the file eof marker if we write past it */
|
|
tmp_addr = *addr;
|
|
H5F_addr_inc(&tmp_addr, size);
|
|
if (H5F_addr_gt(&tmp_addr, &(lf->eof))) {
|
|
fprintf(stderr, "HDF5-DIAG: extending file w/o allocation\n");
|
|
lf->eof = tmp_addr;
|
|
}
|
|
/* Write the data */
|
|
if (lf->type->write) {
|
|
if ((ret_value = (lf->type->write) (lf, access_parms, addr, size,
|
|
buf)) < 0) {
|
|
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, ret_value, "write failed");
|
|
}
|
|
} else {
|
|
HRETURN_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "no write method");
|
|
}
|
|
|
|
FUNC_LEAVE(ret_value);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_flush
|
|
*
|
|
* Purpose: Flushes file buffers to disk. For instance, the stdio.h
|
|
* driver would call fflush(). Flushing also insures that the
|
|
* file exists to the current logical EOF (the library maintains
|
|
* a notion of EOF which is independent of the physical EOF) by
|
|
* reading and writing the last byte. On some systems, this
|
|
* allocates a single block at the end of the file while on
|
|
* other systems it allocates all blocks up to the end of the
|
|
* file. Extending the physical file is necessary because
|
|
* H5F_open() checks for truncated files.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Monday, November 10, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5F_low_flush(H5F_low_t *lf, const H5F_access_t *access_parms)
|
|
{
|
|
haddr_t last_byte;
|
|
uint8 buf[1];
|
|
|
|
FUNC_ENTER(H5F_low_flush, FAIL);
|
|
|
|
assert(lf && lf->type);
|
|
|
|
/* Make sure the last block of the file has been allocated on disk */
|
|
H5F_addr_reset(&last_byte);
|
|
if (addr_defined(&(lf->eof)) && H5F_addr_gt(&(lf->eof), &last_byte)) {
|
|
last_byte = lf->eof;
|
|
last_byte.offset -= 1;
|
|
if (H5F_low_read(lf, access_parms, &last_byte, 1, buf) >= 0) {
|
|
H5F_low_write(lf, access_parms, &last_byte, 1, buf);
|
|
}
|
|
}
|
|
/* Invoke the subclass the flush method */
|
|
if (lf->type->flush) {
|
|
if ((lf->type->flush) (lf, access_parms) < 0) {
|
|
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL,
|
|
"low level flush failed");
|
|
}
|
|
}
|
|
FUNC_LEAVE(SUCCEED);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_size
|
|
*
|
|
* Purpose: Returns the current logical size of the file in bytes. This
|
|
* may differ from the physical size of the file (most
|
|
* subclasses extend the physical file size during the write
|
|
* operation instead of the alloc operation).
|
|
*
|
|
* The next absolute file address is returned through the
|
|
* EOF argument. This is the address of the logical end of
|
|
* file (that is, the address of the first byte past the last
|
|
* byte which is logically in the file).
|
|
*
|
|
* Warning: The return value type (size_t) may not be large enough to
|
|
* represent the true size of the file. In such cases, the
|
|
* maximum possible size is returned. It is better to look at
|
|
* the EOF output argument to determine the total size.
|
|
*
|
|
* Errors:
|
|
* IO UNSUPPORTED No size method.
|
|
*
|
|
* Return: Success: Current size of file
|
|
*
|
|
* Failure: 0
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, October 22, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
size_t
|
|
H5F_low_size(H5F_low_t *lf, haddr_t *eof /*out */ )
|
|
{
|
|
size_t size = (size_t) (-1); /*max possible size */
|
|
|
|
FUNC_ENTER(H5F_low_size, 0);
|
|
|
|
assert(lf && lf->type);
|
|
assert(eof);
|
|
|
|
*eof = lf->eof;
|
|
if (eof->offset < size)
|
|
size = eof->offset;
|
|
|
|
FUNC_LEAVE(size);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_access
|
|
*
|
|
* Purpose: Determines if a file can be accessed in a particular way by a
|
|
* particular subclass. The access modes for a file are the
|
|
* same as those of access(2), namely
|
|
*
|
|
* F_OK: determines if the file (or all parts of a multi-part
|
|
* file) exists.
|
|
*
|
|
* R_OK: determines if the file (or all parts of a multi-part
|
|
* file) are readable.
|
|
*
|
|
* W_OK: determines if the file (or all parts of a multi-part
|
|
* file) are writable.
|
|
*
|
|
* If a subclass doesn't define an access method, then we treat
|
|
* the name as if it were a local Unix file and test
|
|
* accessibility with the access(2) function. The KEY is
|
|
* returned as a device number and i-node pair.
|
|
*
|
|
* Return: Success: TRUE or FALSE. If TRUE, then KEY is
|
|
* initialized with data that makes this file
|
|
* unique (same value as H5F_low_open).
|
|
*
|
|
* Failure: FAIL, KEY is undefined.
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, October 24, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
H5F_low_access(const H5F_low_class_t *type, const char *name,
|
|
const H5F_access_t *access_parms, int mode,
|
|
H5F_search_t *key/*out*/)
|
|
{
|
|
hbool_t ret_value;
|
|
struct stat sb;
|
|
|
|
FUNC_ENTER(H5F_low_size, FAIL);
|
|
assert(type);
|
|
|
|
if (type->access) {
|
|
ret_value = (type->access) (name, access_parms, mode, key /*out*/);
|
|
|
|
} else {
|
|
ret_value = (0 == access(name, mode) ? TRUE : FALSE);
|
|
if (key) {
|
|
stat(name, &sb);
|
|
key->dev = sb.st_dev;
|
|
key->ino = sb.st_ino;
|
|
}
|
|
}
|
|
|
|
FUNC_LEAVE(ret_value);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_extend
|
|
*
|
|
* Purpose: Increases the logical size of a file by moving the logical
|
|
* end of file marker. A subclass can override this function by
|
|
* providing its own allocation method.
|
|
*
|
|
* Return: Success: SUCCEED, the address of the old end-of-file
|
|
* is returned through the ADDR argument and the
|
|
* logical size of the file has been extended by
|
|
* SIZE bytes.
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Thursday, November 13, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5F_low_extend(H5F_low_t *lf, const H5F_access_t *access_parms, intn op,
|
|
size_t size, haddr_t *addr/*out*/)
|
|
{
|
|
FUNC_ENTER(H5F_low_alloc, FAIL);
|
|
|
|
assert(lf);
|
|
assert(size > 0);
|
|
assert(addr);
|
|
|
|
if (lf->type->extend) {
|
|
if ((lf->type->extend) (lf, access_parms, op, size, addr/*out*/) < 0) {
|
|
HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
|
"unable to extend file");
|
|
}
|
|
} else {
|
|
*addr = lf->eof;
|
|
H5F_addr_inc(&(lf->eof), size);
|
|
}
|
|
|
|
FUNC_LEAVE(SUCCEED);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_low_seteof
|
|
*
|
|
* Purpose: Sets the logical end-of-file to the specified address.
|
|
*
|
|
* Return: Success: SUCCEED
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Thursday, November 13, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5F_low_seteof(H5F_low_t *lf, const haddr_t *addr)
|
|
{
|
|
FUNC_ENTER(H5F_low_seteof, FAIL);
|
|
|
|
assert(lf);
|
|
assert(addr && addr_defined(addr));
|
|
|
|
lf->eof = *addr;
|
|
|
|
FUNC_LEAVE(SUCCEED);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_cmp
|
|
*
|
|
* Purpose: Compares two addresses.
|
|
*
|
|
* Return: Success: <0 if A1<A2
|
|
* =0 if A1=A2
|
|
* >0 if A1>A2
|
|
*
|
|
* Failure: never fails
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
intn
|
|
H5F_addr_cmp(const haddr_t *a1, const haddr_t *a2)
|
|
{
|
|
FUNC_ENTER(H5F_addr_cmp, FAIL);
|
|
|
|
assert(a1 && addr_defined(a1));
|
|
assert(a2 && addr_defined(a2));
|
|
|
|
if (a1->offset < a2->offset)
|
|
HRETURN(-1);
|
|
if (a1->offset > a2->offset)
|
|
HRETURN(1);
|
|
|
|
FUNC_LEAVE(0);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_undef
|
|
*
|
|
* Purpose: Cause an address to become undefined.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_undef(haddr_t *addr /*out */ )
|
|
{
|
|
assert(addr);
|
|
|
|
addr->offset = -1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_defined
|
|
*
|
|
* Purpose: Determines if an address has a defined value.
|
|
*
|
|
* Return: Success: TRUE or FALSE
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
H5F_addr_defined(const haddr_t *addr)
|
|
{
|
|
FUNC_ENTER(H5F_addr_defined, FAIL);
|
|
FUNC_LEAVE(addr_defined(addr));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_reset
|
|
*
|
|
* Purpose: Reset the address to zero.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_reset(haddr_t *addr /*out */ )
|
|
{
|
|
assert(addr);
|
|
addr->offset = 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_zerop
|
|
*
|
|
* Purpose: Determines if an address is zero.
|
|
*
|
|
* Return: Success: TRUE or FALSE
|
|
*
|
|
* Failure: FAIL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
H5F_addr_zerop(const haddr_t *addr)
|
|
{
|
|
FUNC_ENTER(H5F_addr_zerop, FAIL);
|
|
FUNC_LEAVE(0 == addr->offset ? TRUE : FALSE);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_encode(H5F_t *f, uint8 **pp, const haddr_t *addr)
|
|
{
|
|
int i;
|
|
haddr_t tmp;
|
|
|
|
assert(f);
|
|
assert(pp && *pp);
|
|
assert(addr);
|
|
|
|
if (addr_defined(addr)) {
|
|
tmp = *addr;
|
|
for (i = 0; i < H5F_SIZEOF_ADDR(f); i++) {
|
|
*(*pp)++ = (uint8)(tmp.offset & 0xff);
|
|
tmp.offset >>= 8;
|
|
}
|
|
assert("overflow" && 0 == tmp.offset);
|
|
|
|
} 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(H5F_t *f, const uint8 **pp, haddr_t *addr /*out */ )
|
|
{
|
|
int i;
|
|
haddr_t tmp;
|
|
uint8 c;
|
|
hbool_t all_zero = TRUE;
|
|
|
|
assert(f);
|
|
assert(pp && *pp);
|
|
assert(addr);
|
|
|
|
addr->offset = 0;
|
|
|
|
for (i = 0; i < H5F_SIZEOF_ADDR(f); i++) {
|
|
c = *(*pp)++;
|
|
if (c != 0xff)
|
|
all_zero = FALSE;
|
|
|
|
if (i < sizeof(addr->offset)) {
|
|
tmp.offset = c;
|
|
tmp.offset <<= i * 8; /*use tmp to get casting right */
|
|
addr->offset |= tmp.offset;
|
|
} else if (!all_zero) {
|
|
assert(0 == **pp); /*overflow */
|
|
}
|
|
}
|
|
if (all_zero)
|
|
H5F_addr_undef(addr);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_print
|
|
*
|
|
* Purpose: Print an address
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_print(FILE * stream, const haddr_t *addr)
|
|
{
|
|
haddr_t tmp;
|
|
|
|
assert(stream);
|
|
assert(addr);
|
|
|
|
if (addr_defined(addr)) {
|
|
/*
|
|
* It would be nice if we could use the `%Lu', `%llu', or `%qu', but
|
|
* we don't know which is supported. So we split the address into a
|
|
* low 4-bytes and a high 4-bytes. If the high 4-bytes are non-zero
|
|
* then we print the address in hexadecimal, otherwise we use decimal.
|
|
*/
|
|
tmp = *addr;
|
|
tmp.offset >>= 32;
|
|
if (tmp.offset) {
|
|
fprintf(stream, "0x%08lx%08lx",
|
|
(unsigned long) (tmp.offset),
|
|
(unsigned long) (addr->offset & 0xffffffff));
|
|
} else {
|
|
fprintf(stream, "%lu", (unsigned long) (addr->offset));
|
|
}
|
|
} else {
|
|
fprintf(stream, "UNDEF");
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_pow2
|
|
*
|
|
* Purpose: Returns an address which is a power of two.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_pow2(uintn n, haddr_t *addr /*out */ )
|
|
{
|
|
assert(addr);
|
|
assert(n < 8 * sizeof(addr->offset));
|
|
|
|
addr->offset = 1;
|
|
addr->offset <<= n;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_inc
|
|
*
|
|
* Purpose: Increments an address by some number of bytes.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_inc(haddr_t *addr /*in,out */ , size_t inc)
|
|
{
|
|
assert(addr && addr_defined(addr));
|
|
assert(addr->offset <= addr->offset + inc);
|
|
addr->offset += inc;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_add
|
|
*
|
|
* Purpose: Adds two addresses and puts the result in the first argument.
|
|
*
|
|
* Return: void
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
H5F_addr_add(haddr_t *a1 /*in,out */ , const haddr_t *a2)
|
|
{
|
|
assert(a1 && addr_defined(a1));
|
|
assert(a2 && addr_defined(a2));
|
|
a1->offset += a2->offset;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5F_addr_hash
|
|
*
|
|
* Purpose: Computes a hash value of an address between 0 and MOD-1,
|
|
* inclusive.
|
|
*
|
|
* Return: Success: The hash value
|
|
*
|
|
* Failure: never fails
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, November 7, 1997
|
|
*
|
|
* Modifications:
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
uintn
|
|
H5F_addr_hash(const haddr_t *addr, uintn mod)
|
|
{
|
|
assert(addr && addr_defined(addr));
|
|
assert(mod > 0);
|
|
|
|
return (unsigned)(addr->offset % mod); /*ignore file number */
|
|
}
|