summaryrefslogtreecommitdiffstats
path: root/src/H5O.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-01-09 17:20:03 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-01-09 17:20:03 (GMT)
commit9a433b99a56dc575f1c0b11f95b744de61859dbb (patch)
treed8c766537cb9adc364c902bd45477d97f67a4a9f /src/H5O.c
parent7fd449cb7987772a2881a5ced2ae7ad5231f1fa3 (diff)
downloadhdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.zip
hdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.tar.gz
hdf5-9a433b99a56dc575f1c0b11f95b744de61859dbb.tar.bz2
[svn-r6252] Purpose:
Lots of performance improvements & a couple new internal API interfaces. Description: Performance Improvements: - Cached file offset & length sizes in shared file struct, to avoid constantly looking them up in the FCPL. - Generic property improvements: - Added "revision" number to generic property classes to speed up comparisons. - Changed method of storing properties from using a hash-table to the TBBT routines in the library. - Share the propery names between classes and the lists derived from them. - Removed redundant 'def_value' buffer from each property. - Switching code to use a "copy on write" strategy for properties in each list, where the properties in each list are shared with the properties in the class, until a property's value is changed in a list. - Fixed error in layout code which was allocating too many buffers. - Redefined public macros of the form (H5open()/H5check, <variable>) internally to only be (<variable>), avoiding innumerable useless calls to H5open() and H5check_version(). - Reuse already zeroed buffers in H5F_contig_fill instead of constantly re-zeroing them. - Don't write fill values if writing entire dataset. - Use gettimeofday() system call instead of time() system when checking the modification time of a dataset. - Added reference counted string API and use it for tracking the names of objects opening in a file (for the ID->name code). - Removed redundant H5P_get() calls in B-tree routines. - Redefine H5T datatype macros internally to the library, to avoid calling H5check redundantly. - Keep dataspace information for dataset locally instead of reading from disk each time. Added new module to track open objects in a file, to allow this (which will be useful eventually for some FPH5 metadata caching issues). - Remove H5AC_find macro which was inlining metadata cache lookups, and call function instead. - Remove redundant memset() calls from H5G_namei() routine. - Remove redundant checking of object type when locating objects in metadata cache and rely on the address only. - Create default dataset object to use when default dataset creation property list is used to create datasets, bypassing querying for all the property list values. - Use default I/O vector size when performing raw data with the default dataset transfer property list, instead of querying for I/O vector size. - Remove H5P_DEFAULT internally to the library, replacing it with more specific default property list based on the type of property list needed. - Remove redundant memset() calls in object header message (H5O*) routines. - Remove redunant memset() calls in data I/O routines. - Split free-list allocation routines into malloc() and calloc()- like routines, instead of one combined routine. - Remove lots of indirection in H5O*() routines. - Simplify metadata cache entry comparison routine (used when flushing entire cache out). - Only enable metadata cache statistics when H5AC_DEBUG is turned on, instead of always tracking them. - Simplify address comparison macro (H5F_addr_eq). - Remove redundant metadata cache entry protections during dataset creation by protecting the object header once and making all the modifications necessary for the dataset creation before unprotecting it. - Reduce # of "number of element in extent" computations performed by computing and storing the value during dataspace creation. - Simplify checking for group location's file information, when file has not been involving in file-mounting operations. - Use binary encoding for modification time, instead of ASCII. - Hoist H5HL_peek calls (to get information in a local heap) out of loops in many group routine. - Use static variable for iterators of selections, instead of dynamically allocation them each time. - Lookup & insert new entries in one step, avoiding traversing group's B-tree twice. - Fixed memory leak in H5Gget_objname_idx() routine (tangential to performance improvements, but fixed along the way). - Use free-list for reference counted strings. - Don't bother copying object names into cached group entries, since they are re-created when an object is opened. The benchmark I used to measure these results created several thousand small (2K) datasets in a file and wrote out the data for them. This is Elena's "regular.c" benchmark. These changes resulted in approximately ~4.3x speedup of the development branch when compared to the previous code in the development branch and ~1.4x speedup compared to the release branch. Additionally, these changes reduce the total memory used (code and data) by the development branch by ~800KB, bringing the development branch back into the same ballpark as the release branch. I'll send out a more detailed description of the benchmark results as a followup note. New internal API routines: Added "reference counted strings" API for tracking strings that get used by multiple owners without duplicating the strings. Added "ternary search tree" API for text->object mappings. Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)} Other platforms/configurations tested? FreeBSD 4.7 (sleipnir) serial & parallel Solaris 2.6 (baldric) serial
Diffstat (limited to 'src/H5O.c')
-rw-r--r--src/H5O.c395
1 files changed, 312 insertions, 83 deletions
diff --git a/src/H5O.c b/src/H5O.c
index 7817b55..e266b86 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -27,6 +27,10 @@
#include "H5Oprivate.h"
#include "H5Pprivate.h"
+#ifdef H5_HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif /* H5_HAVE_GETTIMEOFDAY */
+
#define PABLO_MASK H5O_mask
/* PRIVATE PROTOTYPES */
@@ -39,7 +43,6 @@ static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type,
size_t size);
static unsigned H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size);
static unsigned H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size);
-static herr_t H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force);
/* H5O inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_OHDR[1] = {{
@@ -73,6 +76,7 @@ static const H5O_class_t *const message_type_g[] = {
NULL, /*0x000F Shared header message */
H5O_CONT, /*0x0010 Object header continuation */
H5O_STAB, /*0x0011 Symbol table */
+ H5O_MTIME_NEW, /*0x0012 New Object modification date and time */
};
/*
@@ -168,7 +172,6 @@ H5O_create(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/)
assert(f);
assert(ent);
- HDmemset(ent, 0, sizeof(H5G_entry_t));
size_hint = H5O_ALIGN (MAX (H5O_MIN_SIZE, size_hint));
/* allocate disk space for header and first chunk */
@@ -224,7 +227,7 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header)
ent->header = header;
/* allocate the object header and fill in header fields */
- if (NULL == (oh = H5FL_ALLOC(H5O_t, 1)))
+ if (NULL == (oh = H5FL_MALLOC(H5O_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
oh->dirty = TRUE;
@@ -235,7 +238,7 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header)
oh->nchunks = 1;
oh->alloc_nchunks = H5O_NCHUNKS;
- if (NULL == (oh->chunk = H5FL_ARR_ALLOC(H5O_chunk_t, oh->alloc_nchunks, 0)))
+ if (NULL == (oh->chunk = H5FL_ARR_MALLOC(H5O_chunk_t, oh->alloc_nchunks)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
tmp_addr = ent->header + (hsize_t)H5O_SIZEOF_HDR(f);
@@ -243,14 +246,14 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header)
oh->chunk[0].addr = tmp_addr;
oh->chunk[0].size = size_hint;
- if (NULL == (oh->chunk[0].image = H5FL_BLK_ALLOC(chunk_image, size_hint, 1)))
+ if (NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, size_hint)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* create the message list and initialize the first message */
oh->nmesgs = 1;
oh->alloc_nmesgs = H5O_NMESGS;
- if (NULL == (oh->mesg = H5FL_ARR_ALLOC(H5O_mesg_t, oh->alloc_nmesgs, 1)))
+ if (NULL == (oh->mesg = H5FL_ARR_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
oh->mesg[0].type = H5O_NULL;
@@ -431,7 +434,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1,
assert(!_udata2);
/* allocate ohdr and init chunk list */
- if (NULL==(oh = H5FL_ALLOC(H5O_t,1)))
+ if (NULL==(oh = H5FL_CALLOC(H5O_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* read fixed-lenth part of object header */
@@ -461,7 +464,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1,
/* build the message array */
oh->alloc_nmesgs = MAX(H5O_NMESGS, nmesgs);
- if (NULL==(oh->mesg=H5FL_ARR_ALLOC(H5O_mesg_t,oh->alloc_nmesgs,1)))
+ if (NULL==(oh->mesg=H5FL_ARR_CALLOC(H5O_mesg_t,oh->alloc_nmesgs)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* read each chunk from disk */
@@ -483,7 +486,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1,
oh->chunk[chunkno].dirty = FALSE;
oh->chunk[chunkno].addr = chunk_addr;
oh->chunk[chunkno].size = chunk_size;
- if (NULL==(oh->chunk[chunkno].image = H5FL_BLK_ALLOC(chunk_image,chunk_size,0)))
+ if (NULL==(oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image,chunk_size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
if (H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id,
oh->chunk[chunkno].image) < 0)
@@ -595,6 +598,7 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
uint8_t buf[16], *p;
int id;
unsigned u;
+ H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
H5O_cont_t *cont = NULL;
herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL;
unsigned combine=0; /* Whether to combine the object header prefix & the first chunk */
@@ -642,26 +646,26 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
} /* end else */
/* encode messages */
- for (u = 0; u < oh->nmesgs; u++) {
- if (oh->mesg[u].dirty) {
- p = oh->mesg[u].raw - H5O_SIZEOF_MSGHDR(f);
+ for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) {
+ if (curr_msg->dirty) {
+ p = curr_msg->raw - H5O_SIZEOF_MSGHDR(f);
- id = oh->mesg[u].type->id;
+ id = curr_msg->type->id;
UINT16ENCODE(p, id);
- assert (oh->mesg[u].raw_size<H5O_MAX_SIZE);
- UINT16ENCODE(p, oh->mesg[u].raw_size);
- *p++ = oh->mesg[u].flags;
+ assert (curr_msg->raw_size<H5O_MAX_SIZE);
+ UINT16ENCODE(p, curr_msg->raw_size);
+ *p++ = curr_msg->flags;
*p++ = 0; /*reserved*/
*p++ = 0; /*reserved*/
*p++ = 0; /*reserved*/
- if (oh->mesg[u].native) {
- assert(oh->mesg[u].type->encode);
+ if (curr_msg->native) {
+ assert(curr_msg->type->encode);
/* allocate file space for chunks that have none yet */
- if (H5O_CONT_ID == oh->mesg[u].type->id &&
- !H5F_addr_defined(((H5O_cont_t *)(oh->mesg[u].native))->addr)) {
- cont = (H5O_cont_t *) (oh->mesg[u].native);
+ if (H5O_CONT_ID == curr_msg->type->id &&
+ !H5F_addr_defined(((H5O_cont_t *)(curr_msg->native))->addr)) {
+ cont = (H5O_cont_t *) (curr_msg->native);
assert(cont->chunkno < oh->nchunks);
assert(!H5F_addr_defined(oh->chunk[cont->chunkno].addr));
cont->size = oh->chunk[cont->chunkno].size;
@@ -676,23 +680,23 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
* encode a Shared Object message instead of the object
* which is being shared.
*/
- assert(oh->mesg[u].raw >=
- oh->chunk[oh->mesg[u].chunkno].image);
- assert (oh->mesg[u].raw_size ==
- H5O_ALIGN (oh->mesg[u].raw_size));
- assert(oh->mesg[u].raw + oh->mesg[u].raw_size <=
- oh->chunk[oh->mesg[u].chunkno].image +
- oh->chunk[oh->mesg[u].chunkno].size);
- if (oh->mesg[u].flags & H5O_FLAG_SHARED) {
+ assert(curr_msg->raw >=
+ oh->chunk[curr_msg->chunkno].image);
+ assert (curr_msg->raw_size ==
+ H5O_ALIGN (curr_msg->raw_size));
+ assert(curr_msg->raw + curr_msg->raw_size <=
+ oh->chunk[curr_msg->chunkno].image +
+ oh->chunk[curr_msg->chunkno].size);
+ if (curr_msg->flags & H5O_FLAG_SHARED) {
encode = H5O_SHARED->encode;
} else {
- encode = oh->mesg[u].type->encode;
+ encode = curr_msg->type->encode;
}
- if ((encode)(f, oh->mesg[u].raw, oh->mesg[u].native)<0)
+ if ((encode)(f, curr_msg->raw, curr_msg->native)<0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message");
}
- oh->mesg[u].dirty = FALSE;
- oh->chunk[oh->mesg[u].chunkno].dirty = TRUE;
+ curr_msg->dirty = FALSE;
+ oh->chunk[curr_msg->chunkno].dirty = TRUE;
}
}
@@ -702,7 +706,7 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
assert(H5F_addr_defined(oh->chunk[u].addr));
if(u==0 && combine) {
/* Allocate space for the combined prefix and first chunk */
- if((p=H5FL_BLK_ALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size),0))==NULL)
+ if((p=H5FL_BLK_MALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size)))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* Copy in the prefix */
@@ -739,11 +743,11 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
oh->chunk = H5FL_ARR_FREE(H5O_chunk_t,oh->chunk);
/* destroy messages */
- for (u = 0; u < oh->nmesgs; u++) {
- if (oh->mesg[u].flags & H5O_FLAG_SHARED) {
- H5O_free(H5O_SHARED, oh->mesg[u].native);
+ for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) {
+ if (curr_msg->flags & H5O_FLAG_SHARED) {
+ H5O_free(H5O_SHARED, curr_msg->native);
} else {
- H5O_free(oh->mesg[u].type, oh->mesg[u].native);
+ H5O_free(curr_msg->type, curr_msg->native);
}
}
oh->mesg = H5FL_ARR_FREE(H5O_mesg_t,oh->mesg);
@@ -969,7 +973,7 @@ H5O_count (H5G_entry_t *ent, const H5O_class_t *type)
assert (type);
/* Load the object header */
- if (NULL==(oh=H5AC_find (ent->file, H5AC_OHDR, ent->header, NULL, NULL)))
+ if (NULL==(oh=H5AC_find_f (ent->file, H5AC_OHDR, ent->header, NULL, NULL)))
HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header");
for (u=acc=0; u<oh->nmesgs; u++) {
@@ -1020,7 +1024,7 @@ H5O_exists(H5G_entry_t *ent, const H5O_class_t *type, int sequence)
assert(sequence>=0);
/* Load the object header */
- if (NULL==(oh=H5AC_find(ent->file, H5AC_OHDR, ent->header, NULL, NULL)))
+ if (NULL==(oh=H5AC_find_f(ent->file, H5AC_OHDR, ent->header, NULL, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header");
/* Scan through the messages looking for the right one */
@@ -1182,7 +1186,7 @@ H5O_find_in_ohdr(H5F_t *f, haddr_t addr, const H5O_class_t **type_p,
assert(type_p);
/* Load the object header */
- if (NULL == (oh = H5AC_find(f, H5AC_OHDR, addr, NULL, NULL)))
+ if (NULL == (oh = H5AC_find_f(f, H5AC_OHDR, addr, NULL, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, UFAIL, "unable to load object header");
/* Scan through the messages looking for the right one */
@@ -1244,6 +1248,10 @@ done:
* the sequence number 5 if there is no message with sequence
* number 4).
*
+ * The UPDATE_TIME argument is a boolean that allows the caller
+ * to skip updating the modification time. This is useful when
+ * several calls to H5O_modify will be made in a sequence.
+ *
* Return: Success: The sequence number of the message that
* was modified or created.
*
@@ -1264,14 +1272,15 @@ done:
*/
int
H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
- unsigned flags, const void *mesg)
+ unsigned flags, unsigned update_time, const void *mesg)
{
- H5O_t *oh = NULL;
+ H5O_t *oh=NULL;
int sequence;
- unsigned idx;
+ unsigned idx; /* Index of message to modify */
+ H5O_mesg_t *idx_msg; /* Pointer to message to modify */
int ret_value = FAIL;
- size_t size = 0;
- H5O_shared_t sh_mesg = {0,{{0,0}}};
+ size_t size=0;
+ H5O_shared_t sh_mesg;
FUNC_ENTER_NOAPI(H5O_modify, FAIL);
@@ -1290,8 +1299,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header");
/* Count similar messages */
- for (idx = 0, sequence = -1; idx < oh->nmesgs; idx++) {
- if (type->id != oh->mesg[idx].type->id)
+ for (idx = 0, sequence = -1, idx_msg=&oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) {
+ if (type->id != idx_msg->type->id)
continue;
if (++sequence == overwrite)
break;
@@ -1311,6 +1320,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
if (overwrite < 0) {
/* Allocate space for the new message */
if (flags & H5O_FLAG_SHARED) {
+ HDmemset(&sh_mesg,0,sizeof(H5O_shared_t));
+
if (NULL==type->get_share)
HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, FAIL, "message class is not sharable");
if ((type->get_share)(ent->file, mesg, &sh_mesg/*out*/)<0) {
@@ -1342,7 +1353,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
size = (H5O_SHARED->raw_size)(ent->file, &sh_mesg);
}
}
- if (0==(flags & H5O_FLAG_SHARED)) {
+ /* This can't be an 'else' statement due to the possibility of the shared bit getting turned off above */
+ if (0== (flags & H5O_FLAG_SHARED)) {
size = (type->raw_size) (ent->file, mesg);
if (size>=H5O_MAX_SIZE)
HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large (16k max)");
@@ -1358,25 +1370,28 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite,
HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message");
}
+ /* Set pointer to the correct message */
+ idx_msg=&oh->mesg[idx];
/* Copy the native value into the object header */
if (flags & H5O_FLAG_SHARED) {
- if (NULL==(oh->mesg[idx].native = H5MM_malloc (sizeof (H5O_shared_t))))
+ if (NULL==(idx_msg->native = H5MM_malloc (sizeof (H5O_shared_t))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- HDmemcpy(oh->mesg[idx].native,&sh_mesg,sizeof(H5O_shared_t));
+ HDmemcpy(idx_msg->native,&sh_mesg,sizeof(H5O_shared_t));
} else {
- if (oh->mesg[idx].native)
- H5O_reset (oh->mesg[idx].type, oh->mesg[idx].native);
- oh->mesg[idx].native = (type->copy) (mesg, oh->mesg[idx].native);
- if (NULL == oh->mesg[idx].native)
+ if (idx_msg->native)
+ H5O_reset (idx_msg->type, idx_msg->native);
+ idx_msg->native = (type->copy) (mesg, idx_msg->native);
+ if (NULL == idx_msg->native)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header");
}
/* Update the modification time message if any */
- H5O_touch_oh(ent->file, oh, FALSE);
+ if(update_time)
+ H5O_touch_oh(ent->file, oh, FALSE);
- oh->mesg[idx].flags = flags;
- oh->mesg[idx].dirty = TRUE;
+ idx_msg->flags = flags;
+ idx_msg->dirty = TRUE;
oh->dirty = TRUE;
/* Set return value */
@@ -1391,6 +1406,206 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_protect
+ *
+ * Purpose: Wrapper around H5AC_protect for use during a H5O_protect->
+ * H5O_append->...->H5O_append->H5O_unprotect sequence of calls
+ * during an object's creation.
+ *
+ * Return: Success: Pointer to the object header structure for the
+ * object.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5O_t *
+H5O_protect(H5G_entry_t *ent)
+{
+ H5O_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_protect, NULL);
+
+ /* check args */
+ assert(ent);
+ assert(ent->file);
+ assert(H5F_addr_defined(ent->header));
+
+ if (0==(ent->file->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file");
+
+ if (NULL == (ret_value = H5AC_protect(ent->file, H5AC_OHDR, ent->header, NULL, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header");
+
+done:
+ FUNC_LEAVE(ret_value);
+} /* end H5O_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_unprotect
+ *
+ * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect->
+ * H5O_append->...->H5O_append->H5O_unprotect sequence of calls
+ * during an object's creation.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_unprotect(H5G_entry_t *ent, H5O_t *oh)
+{
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_unprotect, FAIL);
+
+ /* check args */
+ assert(ent);
+ assert(ent->file);
+ assert(H5F_addr_defined(ent->header));
+ assert(oh);
+
+ if (H5AC_unprotect(ent->file, H5AC_OHDR, ent->header, oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header");
+
+done:
+ FUNC_LEAVE(ret_value);
+} /* end H5O_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_append
+ *
+ * Purpose: Simplified version of H5O_modify, used when creating a new
+ * object header message (usually during object creation)
+ *
+ * Modifies an existing message or creates a new message.
+ * The cache fields in that symbol table entry ENT are *not*
+ * updated, you must do that separately because they often
+ * depend on multiple object header messages. Besides, we
+ * don't know which messages will be constant and which will
+ * not.
+ *
+ * Return: Success: The sequence number of the message that
+ * was created.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5O_append(H5F_t *f, H5O_t *oh, const H5O_class_t *type,
+ unsigned flags, const void *mesg)
+{
+ unsigned idx; /* Index of message to modify */
+ H5O_mesg_t *idx_msg; /* Pointer to message to modify */
+ int ret_value = FAIL;
+ size_t size=0;
+ H5O_shared_t sh_mesg;
+
+ FUNC_ENTER_NOAPI(H5O_append, FAIL);
+
+ /* check args */
+ assert(f);
+ assert(oh);
+ assert(type);
+ assert(0==(flags & ~H5O_FLAG_BITS));
+ assert(mesg);
+
+ /* Allocate space for the new message */
+ if (flags & H5O_FLAG_SHARED) {
+ HDmemset(&sh_mesg,0,sizeof(H5O_shared_t));
+
+ if (NULL==type->get_share)
+ HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, FAIL, "message class is not sharable");
+ if ((type->get_share)(f, mesg, &sh_mesg/*out*/)<0) {
+ /*
+ * If the message isn't shared then turn off the shared bit
+ * and treat it as an unshared message.
+ */
+ H5E_clear ();
+ flags &= ~H5O_FLAG_SHARED;
+ } else if (sh_mesg.in_gh) {
+ /*
+ * The shared message is stored in the global heap.
+ * Increment the reference count on the global heap message.
+ */
+ if (H5HG_link (f, &(sh_mesg.u.gh), 1)<0)
+ HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count");
+ size = (H5O_SHARED->raw_size)(f, &sh_mesg);
+ } else {
+ /*
+ * The shared message is stored in some other object header.
+ * The other object header must be in the same file as the
+ * new object header. Increment the reference count on that
+ * object header.
+ */
+ if (sh_mesg.u.ent.file->shared != f->shared)
+ HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed");
+ if (H5O_link (&(sh_mesg.u.ent), 1)<0)
+ HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count");
+ size = (H5O_SHARED->raw_size)(f, &sh_mesg);
+ }
+ }
+ /* This can't be an 'else' statement due to the possibility of the shared bit getting turned off above */
+ if (0== (flags & H5O_FLAG_SHARED)) {
+ size = (type->raw_size) (f, mesg);
+ if (size>=H5O_MAX_SIZE)
+ HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large (16k max)");
+ }
+ if ((idx = H5O_alloc(f, oh, type, size)) == UFAIL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message");
+
+ /* Set pointer to the correct message */
+ idx_msg=&oh->mesg[idx];
+
+ /* Copy the native value into the object header */
+ if (flags & H5O_FLAG_SHARED) {
+ if (NULL==(idx_msg->native = H5MM_malloc (sizeof (H5O_shared_t))))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ HDmemcpy(idx_msg->native,&sh_mesg,sizeof(H5O_shared_t));
+ } else {
+ if (idx_msg->native)
+ H5O_reset (idx_msg->type, idx_msg->native);
+ idx_msg->native = (type->copy) (mesg, idx_msg->native);
+ if (NULL == idx_msg->native)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header");
+ }
+
+ idx_msg->flags = flags;
+ idx_msg->dirty = TRUE;
+ oh->dirty = TRUE;
+
+ /* Set return value */
+ ret_value = idx;
+
+done:
+ FUNC_LEAVE(ret_value);
+} /* end H5O_append() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_touch_oh
*
* Purpose: If FORCE is non-zero then create a modification time message
@@ -1406,11 +1621,14 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force)
{
unsigned idx;
- time_t now = HDtime(NULL);
+#ifdef H5_HAVE_GETTIMEOFDAY
+ struct timeval now_tv;
+#endif /* H5_HAVE_GETTIMEOFDAY */
+ time_t now;
size_t size;
herr_t ret_value=SUCCEED; /* Return value */
@@ -1420,22 +1638,29 @@ H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force)
/* Look for existing message */
for (idx=0; idx<oh->nmesgs; idx++) {
- if (H5O_MTIME==oh->mesg[idx].type)
+ if (H5O_MTIME==oh->mesg[idx].type || H5O_MTIME_NEW==oh->mesg[idx].type)
break;
}
+#ifdef H5_HAVE_GETTIMEOFDAY
+ HDgettimeofday(&now_tv,NULL);
+ now=now_tv.tv_sec;
+#else /* H5_HAVE_GETTIMEOFDAY */
+ now = HDtime(NULL);
+#endif /* H5_HAVE_GETTIMEOFDAY */
+
/* Create a new message */
if (idx==oh->nmesgs) {
if (!force)
HGOTO_DONE(SUCCEED); /*nothing to do*/
- size = (H5O_MTIME->raw_size)(f, &now);
- if ((idx=H5O_alloc(f, oh, H5O_MTIME, size))==UFAIL)
+ size = (H5O_MTIME_NEW->raw_size)(f, &now);
+ if ((idx=H5O_alloc(f, oh, H5O_MTIME_NEW, size))==UFAIL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message");
}
/* Update the native part */
if (NULL==oh->mesg[idx].native) {
- if (NULL==(oh->mesg[idx].native = H5FL_ALLOC(time_t,0)))
+ if (NULL==(oh->mesg[idx].native = H5FL_MALLOC(time_t)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message");
}
*((time_t*)(oh->mesg[idx].native)) = now;
@@ -1833,7 +2058,7 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size)
oh->chunk[chunkno].dirty = TRUE;
oh->chunk[chunkno].addr = HADDR_UNDEF;
oh->chunk[chunkno].size = size;
- if (NULL==(oh->chunk[chunkno].image = p = H5FL_BLK_ALLOC(chunk_image,size,1)))
+ if (NULL==(oh->chunk[chunkno].image = p = H5FL_BLK_CALLOC(chunk_image,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed");
/*
@@ -1944,9 +2169,8 @@ done:
static unsigned
H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
{
- unsigned chunkno;
unsigned idx;
- unsigned null_idx;
+ H5O_mesg_t *msg; /* Pointer to newly allocated message */
size_t aligned_size = H5O_ALIGN(size);
unsigned ret_value; /* Return value */
@@ -1975,6 +2199,8 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
/* if we didn't find one, then allocate more header space */
if (idx >= oh->nmesgs) {
+ unsigned chunkno;
+
/*
* Look for a chunk which hasn't had disk space allocated yet
* since we can just increase the size of that chunk.
@@ -1995,9 +2221,15 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
}
}
+ /* Set pointer to newly allocated message */
+ msg=&oh->mesg[idx];
+
/* do we need to split the null message? */
- if (oh->mesg[idx].raw_size > aligned_size) {
- assert(oh->mesg[idx].raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f));
+ if (msg->raw_size > aligned_size) {
+ H5O_mesg_t *null_msg; /* Pointer to null message */
+ size_t mesg_size = aligned_size+ H5O_SIZEOF_MSGHDR(f); /* Total size of newly allocated message */
+
+ assert(msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f));
if (oh->nmesgs >= oh->alloc_nmesgs) {
int old_alloc=oh->alloc_nmesgs;
@@ -2013,23 +2245,20 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
HDmemset(&oh->mesg[old_alloc],0,
(oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t));
}
- null_idx = oh->nmesgs++;
- oh->mesg[null_idx].type = H5O_NULL;
- oh->mesg[null_idx].dirty = TRUE;
- oh->mesg[null_idx].native = NULL;
- oh->mesg[null_idx].raw = oh->mesg[idx].raw +
- aligned_size +
- H5O_SIZEOF_MSGHDR(f);
- oh->mesg[null_idx].raw_size = oh->mesg[idx].raw_size -
- (aligned_size + H5O_SIZEOF_MSGHDR(f));
- oh->mesg[null_idx].chunkno = oh->mesg[idx].chunkno;
- oh->mesg[idx].raw_size = aligned_size;
+ null_msg=&oh->mesg[oh->nmesgs++];
+ null_msg->type = H5O_NULL;
+ null_msg->dirty = TRUE;
+ null_msg->native = NULL;
+ null_msg->raw = msg->raw + mesg_size;
+ null_msg->raw_size = msg->raw_size - mesg_size;
+ null_msg->chunkno = msg->chunkno;
+ msg->raw_size = aligned_size;
}
/* initialize the new message */
- oh->mesg[idx].type = type;
- oh->mesg[idx].dirty = TRUE;
- oh->mesg[idx].native = NULL;
+ msg->type = type;
+ msg->dirty = TRUE;
+ msg->native = NULL;
oh->dirty = TRUE;