summaryrefslogtreecommitdiffstats
path: root/src/H5Flow.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1997-11-14 14:42:14 (GMT)
committerRobb Matzke <matzke@llnl.gov>1997-11-14 14:42:14 (GMT)
commitcdeeb5553a3920565d87201761dadd1fe32aa3b1 (patch)
treea209c61f85983c1a76bf5c65d1f3285c4861ec46 /src/H5Flow.c
parent73897627660169de753597b9ff045d3112646506 (diff)
downloadhdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.zip
hdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.tar.gz
hdf5-cdeeb5553a3920565d87201761dadd1fe32aa3b1.tar.bz2
[svn-r136] ./MANIFEST
./src/Makefile.in Added H5Ffamily.c and H5Fsplit.c ./src/H5B.c ./src/H5Bprivate.h ./src/H5Gnode.c Added `const' to sublass arguments. ./src/H5F.c ./src/H5Flow.c ./src/H5Fsec2.c Make sure file buffers get flushed during a call to H5Fflush(). Check for overflow in address encoding and decoding. ./src/H5Ffam.c ./src/H5Fprivate.c ./test/istore.c Implementation of file families so 32-bit machines can access 64-bit files. ./src/H5Oprivate.h Removed H5O_NO_ADDR constant. ./config/freebsd2.2.1 ./config/linux Added -DH5G_DEBUG and -DH5F_DEBUG to the list of debugging flags. ./html/H5.format.html Changed some <offset>-sized things to <length>-sized things. ./src/H5AC.c ./src/H5ACprivate.h ./src/H5B.c ./src/H5Bprivate.h ./src/H5C.c ./src/H5D.c ./src/H5F.c ./src/H5Fcore.c ./src/H5Fistore.c ./src/H5Flow.c ./src/H5Fprivate.h ./src/H5Fsec2.c ./src/H5Fstdio.c ./src/H5G.c ./src/H5Gent.c ./src/H5Gnode.c ./src/H5Gpkg.h ./src/H5Gprivate.h ./src/H5Gshad.c ./src/H5Gstab.c ./src/H5H.c ./src/H5Hprivate.h ./src/H5MF.c ./src/H5MFprivate.h ./src/H5O.c ./src/H5Ocont.c ./src/H5Oistore.c ./src/H5Oprivate.h ./src/H5Ostab.c ./src/H5Ostdst.c ./src/H5pivate.h ./src/debug.c ./test/istore.c ./test/theap.c ./test/tohdr.c ./test/tstab.c Lots of changes caused by generalizing addresses. The haddr_t is now a struct, so you can no longer perform arithmetic on it. But since it's small, simple, and often used, storage is allocated like with an integer. But we always pass them around by reference. That is, when using an address in another struct, allocate space: struct my_struct { char *name; haddr_t address; } x; But when passing it to a function, pass by reference: H5F_addr_print (stderr, &(x.address)); Addresses should be initialized with H5F_addr_undef (&(x.address)); Functions for operating on addresses are in H5Flow.c and begin with H5F_addr_... Functions never return haddr_t or haddr_t*; they always pass them through arguments instead. A function that returns an address through an argument does so with its last argument and it is marked with `/*out*/'. Calls to such functions also mark output-only arguments with `/*out*/' ./src/H5Fsplit.c (new) A two-member family where all meta data goes in the first member and all raw data goes in the second member. ./src/H5B.c ./src/H5D.c ./src/H5F.c ./src/H5Ffamily.c ./src/H5Fistore.c ./src/H5Flow.c ./src/H5Fprivate.h ./src/H5Fsec2.c ./src/H5Fstdio.c ./src/H5Gnode.c ./src/H5H.c ./src/H5MF.c ./src/H5MFprivate.h ./src/H5O.c Differentiate between meta data storage and raw data storage. Provide a mechanism so that the file driver can extend the file to allocate more memory. ./src/H5E.c ./src/H5Epublic.c Added the error H5E_TRUNCATED to be reported when the file is shorter than the length recorded in the boot block. ./src/H5F.c Added H5F_locate_signature() so we only do it in one place now. ./INSTALL ./INSTALL_MAINT Just a couple clarifications. ./html/ExternalFiles.html ./html/storage.html Documents how external files work. ./test/hyperslab.c ./test/istore.c Fixed printf's on 64-bit machines. ./test/istore.c Added ifdef's to test the split file driver.
Diffstat (limited to 'src/H5Flow.c')
-rw-r--r--src/H5Flow.c588
1 files changed, 562 insertions, 26 deletions
diff --git a/src/H5Flow.c b/src/H5Flow.c
index 18cc417..55010bc 100644
--- a/src/H5Flow.c
+++ b/src/H5Flow.c
@@ -22,7 +22,6 @@
#define PABLO_MASK H5F_low
static hbool_t interface_initialize_g = FALSE;
-
/*-------------------------------------------------------------------------
* Function: H5F_low_open
@@ -46,8 +45,12 @@ static hbool_t interface_initialize_g = FALSE;
* overwritten.
*
* The KEY argument is initialized with data which is unique to
- * this file. For unix files, it's the device number and
- * i-node. Other low level drivers might use data.
+ * 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.
@@ -65,7 +68,7 @@ static hbool_t interface_initialize_g = FALSE;
*/
H5F_low_t *
H5F_low_open (const H5F_low_class_t *type, const char *name, uintn flags,
- H5F_search_t *key)
+ H5F_search_t *key/*out*/)
{
H5F_low_t *lf = NULL;
@@ -82,12 +85,20 @@ H5F_low_open (const H5F_low_class_t *type, const char *name, uintn flags,
FUNC_LEAVE (lf);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_low_close
*
- * Purpose: Closes a low-level file.
+ * 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.
@@ -124,7 +135,12 @@ H5F_low_close (H5F_low_t *lf)
* Function: H5F_low_read
*
* Purpose: Reads SIZE bytes of data beginning at address ADDR of the
- * file LF and puts the result in BUF.
+ * 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.
@@ -142,13 +158,15 @@ H5F_low_close (H5F_low_t *lf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
+H5F_low_read (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ uint8 *buf/*out*/)
{
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_low_read, NULL, FAIL);
assert (lf && lf->type);
+ assert (addr && H5F_addr_defined (addr));
assert (buf);
if (lf->type->read) {
@@ -167,7 +185,11 @@ H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
* Function: H5F_low_write
*
* Purpose: Writes SIZE bytes of data from BUF into the file LF beginning
- * at address ADDR of the file.
+ * 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.
@@ -185,15 +207,27 @@ H5F_low_read (H5F_low_t *lf, haddr_t addr, size_t size, uint8 *buf)
*-------------------------------------------------------------------------
*/
herr_t
-H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
+H5F_low_write (H5F_low_t *lf, const haddr_t *addr, size_t size,
+ const uint8 *buf)
{
herr_t ret_value = FAIL;
+ haddr_t tmp_addr;
FUNC_ENTER (H5F_low_write, NULL, FAIL);
assert (lf && lf->type);
+ assert (addr && H5F_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, addr, size, buf))<0) {
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, ret_value);/*write failed*/
@@ -204,13 +238,63 @@ H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
FUNC_LEAVE (ret_value);
}
-
/*-------------------------------------------------------------------------
+ * Function: H5F_low_flush
+ *
+ * Purpose: Flushes file buffers to disk. For instance, the stdio.h
+ * driver would call fflush().
+ *
+ * If the subclass doesn't define a flush method then this
+ * function doesn't do anything.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, November 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_low_flush (H5F_low_t *lf)
+{
+ FUNC_ENTER (H5F_low_flush, NULL, FAIL);
+
+ assert (lf && lf->type);
+
+ if (lf->type->flush) {
+ if ((lf->type->flush)(lf)<0) {
+ /* Low level flush failed */
+ HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_low_size
*
- * Purpose: Returns the current size of the file in bytes.
+ * 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.
@@ -227,36 +311,48 @@ H5F_low_write (H5F_low_t *lf, haddr_t addr, size_t size, const uint8 *buf)
*-------------------------------------------------------------------------
*/
size_t
-H5F_low_size (H5F_low_t *lf)
+H5F_low_size (H5F_low_t *lf, haddr_t *eof/*out*/)
{
- size_t size;
+ size_t size = (size_t)(-1); /*max possible size*/
FUNC_ENTER (H5F_low_size, NULL, 0);
assert (lf && lf->type);
+ assert (eof);
- if (lf->type->size) {
- size = (lf->type->size)(lf);
- } else {
- HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0);/*no size method*/
- }
+ *eof = lf->eof;
+ if (eof->offset < size) size = eof->offset;
FUNC_LEAVE (size);
}
-
/*-------------------------------------------------------------------------
* Function: H5F_low_access
*
- * Purpose: Sort of like access(2) except it might do special things for
- * various types of low-level file drivers.
+ * 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.
+ * unique (same value as H5F_low_open).
*
- * Failure: FAIL
+ * Failure: FAIL, KEY is undefined.
*
* Programmer: Robb Matzke
* Friday, October 24, 1997
@@ -267,7 +363,7 @@ H5F_low_size (H5F_low_t *lf)
*/
hbool_t
H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
- H5F_search_t *key)
+ H5F_search_t *key/*out*/)
{
hbool_t ret_value;
struct stat sb;
@@ -276,7 +372,7 @@ H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
assert (type);
if (type->access) {
- ret_value = (type->access)(name, mode, key);
+ ret_value = (type->access)(name, mode, key/*out*/);
} else {
ret_value = (0==access (name, mode));
@@ -289,3 +385,443 @@ H5F_low_access (const H5F_low_class_t *type, const char *name, int mode,
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, intn op, size_t size, haddr_t *addr/*out*/)
+{
+ FUNC_ENTER (H5F_low_alloc, NULL, FAIL);
+
+ assert (lf);
+ assert (size>0);
+ assert (addr);
+
+ if (lf->type->extend) {
+ if ((lf->type->extend)(lf, op, size, addr/*out*/)<0) {
+ /* Unable to extend file */
+ HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ }
+ } 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, NULL, FAIL);
+
+ assert (lf);
+ assert (addr && H5F_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, NULL, FAIL);
+
+ assert (a1 && H5F_addr_defined (a1));
+ assert (a2 && H5F_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)
+{
+ 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, NULL, FAIL);
+ FUNC_LEAVE (-1!=addr->offset && addr->offset>=0);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * 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)
+{
+ 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, NULL, FAIL);
+ FUNC_LEAVE (0==addr->offset);
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * 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 (H5F_addr_defined (addr)) {
+ tmp = *addr;
+ for (i=0; i<H5F_SIZEOF_OFFSET (f); i++) {
+ *(*pp)++ = tmp.offset & 0xff;
+ tmp.offset >>= 8;
+ }
+ assert ("overflow" && 0==tmp.offset);
+
+ } else {
+ for (i=0; i<H5F_SIZEOF_OFFSET (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_OFFSET (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 (H5F_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 (n>=0);
+ 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 && H5F_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 && H5F_addr_defined (a1));
+ assert (a2 && H5F_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 && H5F_addr_defined (addr));
+ assert (mod>0);
+
+ return addr->offset % mod; /*ignore file number*/
+}