From b8201120fc7547b912222f22a41193921a0c003a Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 5 Oct 2003 16:12:26 -0500 Subject: [svn-r7538] Purpose: Bug fixes and code cleanup Description: Lots of changes here: - Fixed bug #691 - when shared datatypes are used in attributes they are incorrectly copied into the attribute instead of referring the the named datatype in the file. This required bumping the version of the attribute message. The new version of the attribute message is only written out when a shared datatype is used in the attribute. [Also, this format change made the size of the attribute smaller.] - Added information to attribute debugging routine so that shared datatypes are displayed correctly with the h5debug tool. - Refactored the H5O* routines to extract code that was common to several routines into subroutines to call. - Added 'link' method for H5O message sub-classes, which increments the link count on shared objects when a message is created which shares them. - Corrected [unreported] bug where the link count was not being decremented on the shared object when a object header message with a reference to that object was deleted from the file. - Reduced size of shared message from 49 bytes (which was incorrect anyway and should have been 48 bytes) to 10 bytes, which required bumping the version of "shared" messages. - Refactored some of the shared datatype routines to allow for easier queries of "committedness" internally to the library and also added routine to easily increment/decrement the reference count of a shared datatype. Platforms tested: FreeBSD 4.9 (sleipnir) h5committest --- release_docs/RELEASE.txt | 3 + src/H5A.c | 18 +- src/H5HG.c | 2 +- src/H5HGprivate.h | 2 +- src/H5O.c | 500 ++++++++++++++++++++++++++--------------------- src/H5Oattr.c | 296 ++++++++++++++++++++++++---- src/H5Obogus.c | 1 + src/H5Ocont.c | 1 + src/H5Odtype.c | 1 + src/H5Oefl.c | 1 + src/H5Ofill.c | 2 + src/H5Olayout.c | 1 + src/H5Omtime.c | 2 + src/H5Oname.c | 1 + src/H5Onull.c | 1 + src/H5Opkg.h | 8 + src/H5Opline.c | 1 + src/H5Oprivate.h | 3 +- src/H5Osdspace.c | 1 + src/H5Oshared.c | 302 ++++++++++++++++++++++++++-- src/H5Ostab.c | 1 + src/H5Tcommit.c | 66 ++++++- src/H5Tprivate.h | 2 + 23 files changed, 922 insertions(+), 294 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 30dfc9b..67f5957 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -76,6 +76,9 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Correctly create reference to shared datatype in attribute, instead + of making a copy of the shared datatype in the attribute. + QAK - 2003/10/01 - Revert changes which caused files >2GB to fail when created with MPI-I/O file driver on certain platforms. QAK - 2003/09/16 - Allow compound datatypes to grow in size. SLU - 2003/09/10 diff --git a/src/H5A.c b/src/H5A.c index dccef50..f60c0ac 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -250,8 +250,22 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, if (H5G_ent_copy(&(attr->ent),ent,H5G_COPY_DEEP)<0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") - /* Compute the internal sizes */ - attr->dt_size=H5O_raw_size(H5O_DTYPE_ID,attr->ent.file,type); + /* Compute the size of pieces on disk */ + if(H5T_committed(attr->dt)) { + H5O_shared_t sh_mesg; + + /* Reset shared message information */ + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + + /* Get shared message information for datatype */ + if (H5O_get_share(H5O_DTYPE_ID,attr->ent.file, type, &sh_mesg/*out*/)<0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + + /* Compute shared message size for datatype */ + attr->dt_size=H5O_raw_size(H5O_SHARED_ID,attr->ent.file,&sh_mesg); + } /* end if */ + else + attr->dt_size=H5O_raw_size(H5O_DTYPE_ID,attr->ent.file,type); assert(attr->dt_size>0); attr->ds_size=H5O_raw_size(H5O_SDSPACE_ID,attr->ent.file,&(space->extent.u.simple)); assert(attr->ds_size>0); diff --git a/src/H5HG.c b/src/H5HG.c index 98372eb..47df258 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -891,7 +891,7 @@ done: *------------------------------------------------------------------------- */ int -H5HG_link (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, int adjust) +H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust) { H5HG_heap_t *heap = NULL; int ret_value; /* Return value */ diff --git a/src/H5HGprivate.h b/src/H5HGprivate.h index 8e589e1..56589f9 100644 --- a/src/H5HGprivate.h +++ b/src/H5HGprivate.h @@ -43,7 +43,7 @@ typedef struct H5HG_heap_t H5HG_heap_t; H5_DLL herr_t H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/); H5_DLL void *H5HG_read(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, void *object); -H5_DLL int H5HG_link(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, int adjust); +H5_DLL int H5HG_link(H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust); H5_DLL herr_t H5HG_remove(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj); /* Debugging functions */ diff --git a/src/H5O.c b/src/H5O.c index f436e29..d9ef4ff 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -49,15 +49,12 @@ static herr_t H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header); static herr_t H5O_reset_real(const H5O_class_t *type, void *native); -static void * H5O_free_real(const H5O_class_t *type, void *mesg); static void * H5O_copy_real(const H5O_class_t *type, const void *mesg, void *dst); static int H5O_count_real (H5G_entry_t *ent, const H5O_class_t *type, hid_t dxpl_id); static htri_t H5O_exists_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t dxpl_id); -static void * H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, - int sequence, void *mesg, hid_t dxpl_id); #ifdef NOT_YET static herr_t H5O_share(H5F_t *f, hid_t dxpl_id, const H5O_class_t *type, const void *mesg, H5HG_t *hobj/*out*/); @@ -76,6 +73,12 @@ static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, 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_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh); +static herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg); +static unsigned H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, + const H5O_class_t *orig_type, const void *orig_mesg, H5O_shared_t *sh_mesg, + const H5O_class_t **new_type, const void **new_mesg, hid_t dxpl_id); +static herr_t H5O_write_mesg(H5O_t *oh, unsigned idx, const H5O_class_t *type, + const void *mesg, unsigned flags); /* Metadata cache callbacks */ static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, @@ -119,7 +122,7 @@ static const H5O_class_t *const message_type_g[] = { H5O_ATTR, /*0x000C Attribute list */ H5O_NAME, /*0x000D Object name */ H5O_MTIME, /*0x000E Object modification date and time */ - NULL, /*0x000F Shared header message */ + H5O_SHARED, /*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 */ @@ -582,7 +585,8 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* decode next object header continuation message */ for (chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) { if (H5O_CONT_ID == oh->mesg[curmesg].type->id) { - H5O_cont_t *cont = NULL; + H5O_cont_t *cont; + cont = (H5O_CONT->decode) (f, dxpl_id, oh->mesg[curmesg].raw, NULL); oh->mesg[curmesg].native = cont; chunk_addr = cont->addr; @@ -1003,8 +1007,7 @@ H5O_free (hid_t type_id, void *mesg) assert(type); /* Call the "real" free routine */ - if((ret_value=H5O_free_real(type, mesg))==NULL) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to free object header"); + ret_value=H5O_free_real(type, mesg); done: FUNC_LEAVE_NOAPI(ret_value); @@ -1028,7 +1031,7 @@ done: * *------------------------------------------------------------------------- */ -static void * +void * H5O_free_real(const H5O_class_t *type, void *mesg) { void * ret_value=NULL; /* Return value */ @@ -1156,7 +1159,7 @@ done: *------------------------------------------------------------------------- */ int -H5O_link(H5G_entry_t *ent, int adjust, hid_t dxpl_id) +H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id) { H5O_t *oh = NULL; hbool_t deleted=FALSE; /* Whether the object was deleted as a result of this action */ @@ -1505,7 +1508,7 @@ done: * actually destroys the object in the cache. *------------------------------------------------------------------------- */ -static void * +void * H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mesg, hid_t dxpl_id) { H5O_t *oh = NULL; @@ -1548,28 +1551,9 @@ H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mes * message in the global heap or some other object header. */ H5O_shared_t *shared; - void *tmp_buf, *tmp_mesg; shared = (H5O_shared_t *)(oh->mesg[idx].native); - if (shared->in_gh) { - if (NULL==(tmp_buf = H5HG_read (ent->file, dxpl_id, &(shared->u.gh), NULL))) - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to read shared message from global heap"); - tmp_mesg = (type->decode)(ent->file, dxpl_id, tmp_buf, shared); - tmp_buf = H5MM_xfree (tmp_buf); - if (!tmp_mesg) - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to decode object header shared message"); - if (mesg) { - HDmemcpy (mesg, tmp_mesg, type->native_size); - H5MM_xfree (tmp_mesg); - } else { - ret_value = tmp_mesg; - } - } else { - ret_value = H5O_read_real(&(shared->u.ent), type, 0, mesg, dxpl_id); - if (type->set_share && - (type->set_share)(ent->file, ret_value, shared)<0) - HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information"); - } + ret_value=H5O_shared_read(ent->file,dxpl_id,shared,type,mesg); } else { /* * The message is not shared, but rather exists in the object @@ -1590,7 +1574,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_find_in_ohdr + * Function: H5O_find_in_ohdr * * Purpose: Find a message in the object header without consulting * a symbol table entry. @@ -1622,6 +1606,7 @@ H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, /* Check args */ assert(f); + assert(oh); assert(type_p); /* Scan through the messages looking for the right one */ @@ -1789,7 +1774,6 @@ H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, int sequence; unsigned idx; /* Index of message to modify */ H5O_mesg_t *idx_msg; /* Pointer to message to modify */ - size_t size=0; H5O_shared_t sh_mesg; int ret_value; @@ -1815,64 +1799,24 @@ H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, continue; if (++sequence == overwrite) break; - } + } /* end for */ /* Was the right message found? */ - if (overwrite >= 0 && - (idx >= oh->nmesgs || sequence != overwrite)) { - + if (overwrite >= 0 && (idx >= oh->nmesgs || sequence != overwrite)) { /* But can we insert a new one with this sequence number? */ - if (overwrite == sequence + 1) { + if (overwrite == sequence + 1) overwrite = -1; - } else { + else HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message not found"); - } - } + } /* end if */ + + /* Check for creating new message */ 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) { - /* - * If the message isn't shared then turn off the shared bit - * and treat it as an unshared message. - */ - H5E_clear (NULL); - 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 (ent->file, dxpl_id, &(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)(ent->file, &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 != ent->file->shared) - HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed"); - if (H5O_link (&(sh_mesg.u.ent), 1, dxpl_id)<0) - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); - size = (H5O_SHARED->raw_size)(ent->file, &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) (ent->file, mesg); - if (size>=H5O_MAX_SIZE) - HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large (16k max)"); - } - idx = H5O_alloc(ent->file, oh, type, size); - if (idx == UFAIL) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message"); + /* Create a new message */ + if((idx=H5O_new_mesg(ent->file,oh,&flags,type,mesg,&sh_mesg,&type,&mesg,dxpl_id))==UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message"); + + /* Set the correct sequence number for the message created */ sequence++; } else if (oh->mesg[idx].flags & H5O_FLAG_CONSTANT) { @@ -1881,30 +1825,14 @@ H5O_modify_real(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==(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_real(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"); - } + /* Write the information to the message */ + if(H5O_write_mesg(oh,idx,type,mesg,flags)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message"); /* Update the modification time message if any */ if(update_time) H5O_touch_oh(ent->file, oh, FALSE); - idx_msg->flags = flags; - idx_msg->dirty = TRUE; - oh->cache_info.dirty = TRUE; - /* Set return value */ ret_value = sequence; @@ -2007,13 +1935,6 @@ done: * 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. * @@ -2064,13 +1985,6 @@ done: * 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. * @@ -2089,8 +2003,6 @@ H5O_append_real(H5F_t *f, hid_t dxpl_id, 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 */ - size_t size=0; H5O_shared_t sh_mesg; int ret_value = FAIL; @@ -2103,76 +2015,143 @@ H5O_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t *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)); + /* Create a new message */ + if((idx=H5O_new_mesg(f,oh,&flags,type,mesg,&sh_mesg,&type,&mesg,dxpl_id))==UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message"); + + /* Write the information to the message */ + if(H5O_write_mesg(oh,idx,type,mesg,flags)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message"); + + /* Set return value */ + ret_value = idx; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_append_real () */ + + +/*------------------------------------------------------------------------- + * Function: H5O_new_mesg + * + * Purpose: Create a new message in an object header + * + * Return: Success: Index of message + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, September 3, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static unsigned +H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_class_t *orig_type, + const void *orig_mesg, H5O_shared_t *sh_mesg, const H5O_class_t **new_type, + const void **new_mesg, hid_t dxpl_id) +{ + size_t size; /* Size of space allocated for object header */ + unsigned ret_value=UFAIL; /* Return value */ + + FUNC_ENTER_NOINIT(H5O_new_mesg); - 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) { + /* check args */ + assert(f); + assert(oh); + assert(flags); + assert(orig_type); + assert(orig_mesg); + assert(sh_mesg); + assert(new_mesg); + assert(new_type); + + /* Check for shared message */ + if (*flags & H5O_FLAG_SHARED) { + HDmemset(sh_mesg,0,sizeof(H5O_shared_t)); + + if (NULL==orig_type->get_share) + HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable"); + if ((orig_type->get_share)(f, orig_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 (NULL); - 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, dxpl_id, &(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); + *flags &= ~H5O_FLAG_SHARED; } 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, dxpl_id)<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"); - + /* Change type & message to use shared information */ + *new_type=H5O_SHARED; + *new_mesg=sh_mesg; + } /* end else */ + } /* end if */ + else { + *new_type=orig_type; + *new_mesg=orig_mesg; + } /* end else */ + + /* Compute the size needed to store the message on disk */ + if ((size = ((*new_type)->raw_size) (f, *new_mesg)) >=H5O_MAX_SIZE) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large (16k max)"); + + /* Allocate space in the object headed for the message */ + if ((ret_value = H5O_alloc(f, oh, orig_type, size)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "unable to allocate space for message"); + + /* Increment any links in message */ + if((*new_type)->link && ((*new_type)->link)(f,dxpl_id,(*new_mesg))<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, UFAIL, "unable to adjust shared object link count"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_new_mesg() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_write_mesg + * + * Purpose: Write message to object header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, September 3, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_write_mesg(H5O_t *oh, unsigned idx, const H5O_class_t *type, + const void *mesg, unsigned flags) +{ + H5O_mesg_t *idx_msg; /* Pointer to message to modify */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5O_write_mesg); + + /* check args */ + assert(oh); + assert(type); + assert(mesg); + /* 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_real(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"); - } - + /* Reset existing native information */ + H5O_reset_real(type, idx_msg->native); + + /* Copy the native value for the message */ + if (NULL == (idx_msg->native = (type->copy) (mesg, 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->cache_info.dirty = TRUE; - /* Set return value */ - ret_value = idx; - done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5O_append_real () */ +} /* end H5O_write_mesg() */ /*------------------------------------------------------------------------- @@ -2478,10 +2457,10 @@ done: static herr_t H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t dxpl_id) { - H5O_t *oh = NULL; + H5O_t *oh = NULL; + H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ int seq, nfailed = 0; - unsigned u; - H5O_shared_t *sh_mesg = NULL; + unsigned u; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5O_remove_real); @@ -2499,40 +2478,32 @@ H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t d if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); - for (u = seq = 0; u < oh->nmesgs; u++) { - if (type->id != oh->mesg[u].type->id) + for (u = seq = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + if (type->id != curr_msg->type->id) continue; if (seq++ == sequence || H5O_ALL == sequence) { + /* * Keep track of how many times we failed trying to remove constant * messages. */ - if (oh->mesg[u].flags & H5O_FLAG_CONSTANT) { + if (curr_msg->flags & H5O_FLAG_CONSTANT) { nfailed++; continue; - } + } /* end if */ - if (oh->mesg[u].flags & H5O_FLAG_SHARED) { - if (NULL==oh->mesg[u].native) { - sh_mesg = (H5O_SHARED->decode)(ent->file, dxpl_id, oh->mesg[u].raw, - NULL); - if (NULL==(oh->mesg[u].native = sh_mesg)) - HGOTO_ERROR (H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode shared message info"); - } - if (sh_mesg->in_gh) { - if (H5HG_link (ent->file, dxpl_id, &(sh_mesg->u.gh), -1)<0) - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to decrement link count on shared message"); - } else { - if (H5O_link (&(sh_mesg->u.ent), -1, dxpl_id)<0) - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to decrement link count on shared message"); - } - } + /* Free any space referred to in the file from this message */ + if(H5O_delete_mesg(ent->file,dxpl_id,curr_msg)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); /* change message type to nil and zero it */ - oh->mesg[u].type = H5O_NULL; - HDmemset(oh->mesg[u].raw, 0, oh->mesg[u].raw_size); - oh->mesg[u].native = H5O_free_real(type, oh->mesg[u].native); - oh->mesg[u].dirty = TRUE; + curr_msg->type = H5O_NULL; + HDmemset(curr_msg->raw, 0, curr_msg->raw_size); + if(curr_msg->flags & H5O_FLAG_SHARED) + curr_msg->native = H5O_free_real(H5O_SHARED, curr_msg->native); + else + curr_msg->native = H5O_free_real(type, curr_msg->native); + curr_msg->dirty = TRUE; oh->cache_info.dirty = TRUE; H5O_touch_oh(ent->file, oh, FALSE); } @@ -3095,6 +3066,51 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_get_share + * + * Purpose: Call the 'get_share' method for a + * particular class of object header. + * + * Return: Success: Non-negative, and SHARE describes the shared + * object. + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Oct 2 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_get_share(hid_t type_id, H5F_t *f, const void *mesg, H5O_shared_t *share) +{ + const H5O_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_get_share,FAIL); + + /* Check args */ + assert(type_id>=0 && type_id<(hid_t)(sizeof(message_type_g)/sizeof(message_type_g[0]))); + type=message_type_g[type_id]; /* map the type ID to the actual type object */ + assert (type); + assert (type->get_share); + assert (f); + assert (mesg); + assert (share); + + /* Compute the raw data size for the mesg */ + if ((ret_value = (type->get_share)(f, mesg, share))<0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve shared message information"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_get_share() */ + + +/*------------------------------------------------------------------------- * Function: H5O_delete * * Purpose: Delete an object header from a file. This frees the file @@ -3173,33 +3189,13 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh) assert (f); assert (oh); - /* Walk through the list of object header messages, asking each on to + /* Walk through the list of object header messages, asking each one to * delete any file space used */ for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { - const H5O_class_t *type = NULL; - - /* Don't handle shared messages yet */ - assert(!(curr_msg->flags & H5O_FLAG_SHARED)); - - /* Get the message's type */ - type = curr_msg->type; - - /* Check if there is a file space deletion callback for this type of message */ - if(type->del) { - /* - * Decode the message if necessary. - */ - if (NULL == curr_msg->native) { - assert(type->decode); - curr_msg->native = (type->decode) (f, dxpl_id, curr_msg->raw, NULL); - if (NULL == curr_msg->native) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message"); - } /* end if */ - - if ((type->del)(f, dxpl_id, curr_msg->native)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); - } /* end if */ + /* Free any space referred to in the file from this message */ + if(H5O_delete_mesg(f,dxpl_id,curr_msg)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); } /* end for */ /* Free all the chunks for the object header */ @@ -3227,6 +3223,62 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_delete_mesg + * + * Purpose: Internal function to: + * Delete an object header message from a file. This frees the file + * space used for anything referred to in the object header message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * September 26 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg) +{ + const H5O_class_t *type; /* Type of object to free */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5O_delete_mesg); + + /* Check args */ + assert (f); + assert (mesg); + + /* Get the message to free's type */ + if(mesg->flags & H5O_FLAG_SHARED) + type=H5O_SHARED; + else + type = mesg->type; + + /* Check if there is a file space deletion callback for this type of message */ + if(type->del) { + /* + * Decode the message if necessary. + */ + if (NULL == mesg->native) { + assert(type->decode); + mesg->native = (type->decode) (f, dxpl_id, mesg->raw, NULL); + if (NULL == mesg->native) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message"); + } /* end if */ + + if ((type->del)(f, dxpl_id, mesg->native)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_delete_msg() */ + + +/*------------------------------------------------------------------------- * Function: H5O_debug_id * * Purpose: Act as a proxy for calling the 'debug' method for a @@ -3410,7 +3462,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f decode = oh->mesg[i].type->decode; debug = oh->mesg[i].type->debug; } - if (NULL==oh->mesg[i].native && oh->mesg[i].type->decode) + if (NULL==oh->mesg[i].native && decode) oh->mesg[i].native = (decode)(f, dxpl_id, oh->mesg[i].raw, NULL); if (NULL==oh->mesg[i].native) debug = NULL; diff --git a/src/H5Oattr.c b/src/H5Oattr.c index f1217a9..fdf24a6 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -35,6 +35,8 @@ static void *H5O_attr_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_sha static void *H5O_attr_copy (const void *_mesg, void *_dest); static size_t H5O_attr_size (H5F_t *f, const void *_mesg); static herr_t H5O_attr_reset (void *_mesg); +static herr_t H5O_attr_delete (H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_attr_debug (H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -49,14 +51,22 @@ const H5O_class_t H5O_ATTR[1] = {{ H5O_attr_size, /* size of raw message */ H5O_attr_reset, /* reset method */ NULL, /* free method */ - NULL, /* file delete method */ + H5O_attr_delete, /* file delete method */ + H5O_attr_link, /* link method */ NULL, /* get share method */ NULL, /* set share method */ H5O_attr_debug, /* debug the message */ }}; +/* This is the initial version, which does not have support for shared datatypes */ #define H5O_ATTR_VERSION 1 +/* This version allows support for shared datatypes */ +#define H5O_ATTR_VERSION_NEW 2 + +/* Flags for attribute flag encoding */ +#define H5O_ATTR_FLAG_TYPE_SHARED 0x01 + /* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL @@ -99,6 +109,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * H5S_simple_t *simple; /*simple dimensionality information */ size_t name_len; /*attribute name length */ int version; /*message version number*/ + unsigned flags=0; /* Attribute flags */ H5A_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_attr_decode, NULL); @@ -112,11 +123,14 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * /* Version number */ version = *p++; - if (version!=H5O_ATTR_VERSION) + if (version!=H5O_ATTR_VERSION && version!=H5O_ATTR_VERSION_NEW) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for attribute message"); - /* Reserved */ - p++; + /* Get the flags byte if we have a later version of the attribute */ + if(version>H5O_ATTR_VERSION) + flags = *p++; + else + p++; /* Byte is unused when version<2 */ /* * Decode the sizes of the parts of the attribute. The sizes stored in @@ -130,12 +144,34 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * if (NULL==(attr->name=H5MM_malloc(name_len))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); HDmemcpy(attr->name,p,name_len); - p += H5O_ALIGN(name_len); /* advance the memory pointer */ + if(version < H5O_ATTR_VERSION_NEW) + p += H5O_ALIGN(name_len); /* advance the memory pointer */ + else + p += name_len; /* advance the memory pointer */ /* decode the attribute datatype */ - if((attr->dt=(H5O_DTYPE->decode)(f,dxpl_id,p,NULL))==NULL) - HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); - p += H5O_ALIGN(attr->dt_size); + if (flags & H5O_ATTR_FLAG_TYPE_SHARED) { + H5O_shared_t *shared; /* Shared information */ + + /* Get the shared information */ + if (NULL == (shared = (H5O_SHARED->decode) (f, dxpl_id, p, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message"); + + /* Get the actual datatype information */ + if((attr->dt= H5O_shared_read(f, dxpl_id, shared, H5O_DTYPE, NULL))==NULL) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); + + /* Free the shared information */ + H5O_free_real(H5O_SHARED, shared); + } /* end if */ + else { + if((attr->dt=(H5O_DTYPE->decode)(f,dxpl_id,p,NULL))==NULL) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); + } /* end else */ + if(version < H5O_ATTR_VERSION_NEW) + p += H5O_ALIGN(attr->dt_size); + else + p += attr->dt_size; /* decode the attribute dataspace */ if (NULL==(attr->ds = H5FL_CALLOC(H5S_t))) @@ -159,7 +195,10 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * /* Default to entire dataspace being selected */ if(H5S_select_all(attr->ds,0)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); - p += H5O_ALIGN(attr->ds_size); + if(version < H5O_ATTR_VERSION_NEW) + p += H5O_ALIGN(attr->ds_size); + else + p += attr->ds_size; /* Compute the size of the data */ H5_ASSIGN_OVERFLOW(attr->data_size,H5S_get_simple_extent_npoints(attr->ds)*H5T_get_size(attr->dt),hsize_t,size_t); @@ -206,9 +245,11 @@ done: static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) { - const H5A_t *attr = (const H5A_t *) mesg; - size_t name_len; /* Attribute name length */ - herr_t ret_value=SUCCEED; /* Return value */ + const H5A_t *attr = (const H5A_t *) mesg; + size_t name_len; /* Attribute name length */ + unsigned version; /* Attribute version */ + hbool_t type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_attr_encode, FAIL); @@ -217,16 +258,31 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) assert(p); assert(attr); - /* Version */ - *p++ = H5O_ATTR_VERSION; + /* Check whether datatype is shared */ + if(H5T_committed(attr->dt)) + type_shared = TRUE; + else + type_shared = FALSE; + + /* Check which version to write out */ + if(type_shared) + version = H5O_ATTR_VERSION_NEW; /* Write out new version if shared datatype */ + else + version = H5O_ATTR_VERSION; - /* Reserved */ - *p++ = 0; + /* Encode Version */ + *p++ = version; + + /* Set attribute flags if version >1 */ + if(version>H5O_ATTR_VERSION) + *p++ = (type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 ); /* Set flags for attribute */ + else + *p++ = 0; /* Reserved, for version <2 */ /* * Encode the lengths of the various parts of the attribute message. The * encoded lengths are exact but we pad each part except the data to be a - * multiple of eight bytes. + * multiple of eight bytes (in the first version). */ name_len = HDstrlen(attr->name)+1; UINT16ENCODE(p, name_len); @@ -239,19 +295,47 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) */ HDmemcpy(p, attr->name, name_len); HDmemset(p+name_len, 0, H5O_ALIGN(name_len)-name_len); - p += H5O_ALIGN(name_len); + if(version < H5O_ATTR_VERSION_NEW) + p += H5O_ALIGN(name_len); + else + p += name_len; /* encode the attribute datatype */ - if((H5O_DTYPE->encode)(f,p,attr->dt)<0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype"); - HDmemset(p+attr->dt_size, 0, H5O_ALIGN(attr->dt_size)-attr->dt_size); - p += H5O_ALIGN(attr->dt_size); + if(type_shared) { + H5O_shared_t sh_mesg; + + /* Reset shared message information */ + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + + /* Get shared message information from datatype */ + if ((H5O_DTYPE->get_share)(f, attr->dt, &sh_mesg/*out*/)<0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode shared attribute datatype"); + + /* Encode shared message information for datatype */ + if((H5O_SHARED->encode)(f,p,&sh_mesg)<0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode shared attribute datatype"); + } /* end if */ + else { + /* Encode datatype information */ + if((H5O_DTYPE->encode)(f,p,attr->dt)<0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype"); + } /* end else */ + if(version < H5O_ATTR_VERSION_NEW) { + HDmemset(p+attr->dt_size, 0, H5O_ALIGN(attr->dt_size)-attr->dt_size); + p += H5O_ALIGN(attr->dt_size); + } /* end if */ + else + p += attr->dt_size; /* encode the attribute dataspace */ if((H5O_SDSPACE->encode)(f,p,&(attr->ds->extent.u.simple))<0) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace"); - HDmemset(p+attr->ds_size, 0, H5O_ALIGN(attr->ds_size)-attr->ds_size); - p += H5O_ALIGN(attr->ds_size); + if(version < H5O_ATTR_VERSION_NEW) { + HDmemset(p+attr->ds_size, 0, H5O_ALIGN(attr->ds_size)-attr->ds_size); + p += H5O_ALIGN(attr->ds_size); + } /* end if */ + else + p += attr->ds_size; /* Store attribute data */ HDmemcpy(p,attr->data,attr->data_size); @@ -327,11 +411,13 @@ done: * Added padding between message parts for alignment. --------------------------------------------------------------------------*/ static size_t -H5O_attr_size(H5F_t UNUSED *f, const void *mesg) +H5O_attr_size(H5F_t UNUSED *f, const void *_mesg) { - size_t ret_value = 0; + const H5A_t *attr = (const H5A_t *)_mesg; size_t name_len; - const H5A_t *attr = (const H5A_t *) mesg; + unsigned version; /* Attribute version */ + hbool_t type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ + size_t ret_value = 0; FUNC_ENTER_NOAPI(H5O_attr_size, 0); @@ -339,14 +425,38 @@ H5O_attr_size(H5F_t UNUSED *f, const void *mesg) name_len = HDstrlen(attr->name)+1; - ret_value = 2 + /*name size inc. null */ - 2 + /*type size */ - 2 + /*space size */ - 2 + /*reserved */ - H5O_ALIGN(name_len) + /*attribute name */ - H5O_ALIGN(attr->dt_size) + /*data type */ - H5O_ALIGN(attr->ds_size) + /*data space */ - attr->data_size; /*the data itself */ + /* Check whether datatype is shared */ + if(H5T_committed(attr->dt)) + type_shared = TRUE; + else + type_shared = FALSE; + + /* Check which version to write out */ + if(type_shared) + version = H5O_ATTR_VERSION_NEW; /* Write out new version if shared datatype */ + else + version = H5O_ATTR_VERSION; + + if(version < H5O_ATTR_VERSION_NEW) + ret_value = 1 + /*version */ + 1 + /*reserved */ + 2 + /*name size inc. null */ + 2 + /*type size */ + 2 + /*space size */ + H5O_ALIGN(name_len) + /*attribute name */ + H5O_ALIGN(attr->dt_size) + /*data type */ + H5O_ALIGN(attr->ds_size) + /*data space */ + attr->data_size; /*the data itself */ + else + ret_value = 1 + /*version */ + 1 + /*flags */ + 2 + /*name size inc. null */ + 2 + /*type size */ + 2 + /*space size */ + name_len + /*attribute name */ + attr->dt_size + /*data type */ + attr->ds_size + /*data space */ + attr->data_size; /*the data itself */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -390,6 +500,83 @@ done: } +/*------------------------------------------------------------------------- + * Function: H5O_attr_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, September 26, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_delete(H5F_t UNUSED *f, hid_t dxpl_id, const void *_mesg) +{ + const H5A_t *attr = (const H5A_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_attr_delete, FAIL); + + /* check args */ + assert(f); + assert(attr); + + /* Check whether datatype is shared */ + if(H5T_committed(attr->dt)) { + /* Decrement the reference count on the shared datatype */ + if(H5T_link(attr->dt,-1,dxpl_id)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared datatype link count"); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_attr_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_attr_link + * + * Purpose: Increment reference count on any objects referenced by + * message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, September 26, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_link(H5F_t UNUSED *f, hid_t dxpl_id, const void *_mesg) +{ + const H5A_t *attr = (const H5A_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_attr_link, FAIL); + + /* check args */ + assert(f); + assert(attr); + + /* Check whether datatype is shared */ + if(H5T_committed(attr->dt)) { + /* Increment the reference count on the shared datatype */ + if(H5T_link(attr->dt,1,dxpl_id)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared datatype link count"); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_attr_link() */ + + /*-------------------------------------------------------------------------- NAME H5O_attr_debug @@ -413,6 +600,9 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in int fwidth) { const H5A_t *mesg = (const H5A_t *)_mesg; + H5O_shared_t sh_mesg; /* Shared message information */ + void *dt_mesg; /* Pointer to datatype message to dump */ + herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int)=NULL; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_attr_debug, FAIL); @@ -436,16 +626,38 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in H5G_ent_debug(f, dxpl_id, &(mesg->ent), stream, indent+3, MAX(0, fwidth-3), HADDR_UNDEF); - fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Data type size:", - (unsigned long)(mesg->dt_size)); fprintf(stream, "%*sData type...\n", indent, ""); - (H5O_DTYPE->debug)(f, dxpl_id, mesg->dt, stream, indent+3, MAX(0, fwidth-3)); + fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3), + "Size:", + (unsigned long)(mesg->dt_size)); + fprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX(0,fwidth-3), + "Shared:", + (H5T_committed(mesg->dt) ? "Yes" : "No") + ); + if(H5T_committed(mesg->dt)) { + /* Reset shared message information */ + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + + /* Get shared message information from datatype */ + if ((H5O_DTYPE->get_share)(f, mesg->dt, &sh_mesg/*out*/)<0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't retrieve shared message information"); + + debug=H5O_SHARED->debug; + dt_mesg=&sh_mesg; + } /* end if */ + else { + debug=H5O_DTYPE->debug; + dt_mesg=mesg->dt; + } /* end else */ + if(debug) + (debug)(f, dxpl_id, dt_mesg, stream, indent+3, MAX(0, fwidth-3)); + else + fprintf(stream, "%*s\n", indent + 6, ""); - fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Data space size:", - (unsigned long)(mesg->ds_size)); fprintf(stream, "%*sData space...\n", indent, ""); + fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3), + "Size:", + (unsigned long)(mesg->ds_size)); H5S_debug(f, dxpl_id, mesg->ds, stream, indent+3, MAX(0, fwidth-3)); done: diff --git a/src/H5Obogus.c b/src/H5Obogus.c index 90b7b3d..b049654 100644 --- a/src/H5Obogus.c +++ b/src/H5Obogus.c @@ -58,6 +58,7 @@ const H5O_class_t H5O_BOGUS[1] = {{ NULL, /*free internal memory */ NULL, /*free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_bogus_debug, /*debug the message */ diff --git a/src/H5Ocont.c b/src/H5Ocont.c index 4b54c4a..e8dca5b 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -55,6 +55,7 @@ const H5O_class_t H5O_CONT[1] = {{ NULL, /*reset method */ NULL, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_cont_debug, /*debugging */ diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 2c943cf..5ab3fb4 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -51,6 +51,7 @@ const H5O_class_t H5O_DTYPE[1] = {{ H5O_dtype_reset, /* reset method */ H5O_dtype_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ H5O_dtype_get_share, /* get share method */ H5O_dtype_set_share, /* set share method */ H5O_dtype_debug, /* debug the message */ diff --git a/src/H5Oefl.c b/src/H5Oefl.c index ec33293..4ecd5f8 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -54,6 +54,7 @@ const H5O_class_t H5O_EFL[1] = {{ H5O_efl_reset, /*reset method */ NULL, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_efl_debug, /*debug the message */ diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 13da259..b2595a0 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -61,6 +61,7 @@ const H5O_class_t H5O_FILL[1] = {{ H5O_fill_reset, /*free internal memory */ H5O_fill_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_fill_debug, /*debug the message */ @@ -78,6 +79,7 @@ const H5O_class_t H5O_FILL_NEW[1] = {{ H5O_fill_new_reset, /*free internal memory */ H5O_fill_new_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_fill_new_debug, /*debug the message */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index fc1eeae..b9a41ec 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -51,6 +51,7 @@ const H5O_class_t H5O_LAYOUT[1] = {{ H5O_layout_reset, /*reset method */ H5O_layout_free, /*free the struct */ H5O_layout_delete, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_layout_debug, /*debug the message */ diff --git a/src/H5Omtime.c b/src/H5Omtime.c index b1d7496..0f56ee1 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -58,6 +58,7 @@ const H5O_class_t H5O_MTIME[1] = {{ H5O_mtime_reset, /* reset method */ H5O_mtime_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_mtime_debug, /*debug the message */ @@ -76,6 +77,7 @@ const H5O_class_t H5O_MTIME_NEW[1] = {{ H5O_mtime_reset, /* reset method */ H5O_mtime_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_mtime_debug, /*debug the message */ diff --git a/src/H5Oname.c b/src/H5Oname.c index e6b9fb6..231a177 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -55,6 +55,7 @@ const H5O_class_t H5O_NAME[1] = {{ H5O_name_reset, /*free internal memory */ NULL, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_name_debug, /*debug the message */ diff --git a/src/H5Onull.c b/src/H5Onull.c index ca811da..bcf3da3 100644 --- a/src/H5Onull.c +++ b/src/H5Onull.c @@ -44,6 +44,7 @@ const H5O_class_t H5O_NULL[1] = {{ NULL, /*no reset method */ NULL, /*no free method */ NULL, /*no file delete method */ + NULL, /*no link method */ NULL, /*no get share method */ NULL, /*no set share method */ NULL, /*no debug method */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 1255764..866e1b7 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -67,6 +67,7 @@ typedef struct H5O_class_t { herr_t (*reset)(void *); /*free nested data structs */ herr_t (*free)(void *); /*free main data struct */ herr_t (*del)(H5F_t *, hid_t, const void *); /* Delete space in file referenced by this message */ + herr_t (*link)(H5F_t *, hid_t, const void *); /* Increment any links in file reference by this message */ herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); /* Get shared information */ herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); /* Set shared information */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); @@ -195,6 +196,13 @@ H5_DLLVAR const H5O_class_t H5O_MTIME_NEW[1]; H5_DLLVAR const H5O_class_t H5O_PLIST[1]; /* Package-local function prototypes */ +H5_DLL void * H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, + int sequence, void *mesg, hid_t dxpl_id); +H5_DLL void * H5O_free_real(const H5O_class_t *type, void *mesg); + +/* Shared object operators */ +H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, + const H5O_class_t *type, void *mesg); /* Symbol table operators */ H5_DLL void *H5O_stab_fast(const H5G_cache_t *cache, const struct H5O_class_t *type, diff --git a/src/H5Opline.c b/src/H5Opline.c index 21e5b11..972e5e0 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -57,6 +57,7 @@ const H5O_class_t H5O_PLINE[1] = {{ H5O_pline_reset, /* reset method */ H5O_pline_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /* get share method */ NULL, /* set share method */ H5O_pline_debug, /* debug the message */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index ed07b24..bcd2e5b 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -208,7 +208,7 @@ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/); H5_DLL herr_t H5O_open(H5G_entry_t *ent); H5_DLL herr_t H5O_close(H5G_entry_t *ent); -H5_DLL int H5O_link(H5G_entry_t *ent, int adjust, hid_t dxpl_id); +H5_DLL int H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id); H5_DLL int H5O_count(H5G_entry_t *ent, hid_t type_id, hid_t dxpl_id); H5_DLL htri_t H5O_exists(H5G_entry_t *ent, hid_t type_id, int sequence, hid_t dxpl_id); @@ -232,6 +232,7 @@ H5_DLL herr_t H5O_reset(hid_t type_id, void *native); H5_DLL void *H5O_free(hid_t type_id, void *mesg); H5_DLL void *H5O_copy(hid_t type_id, const void *mesg, void *dst); H5_DLL size_t H5O_raw_size(hid_t type_id, H5F_t *f, const void *mesg); +H5_DLL herr_t H5O_get_share(hid_t type_id, H5F_t *f, const void *mesg, H5O_shared_t *share); H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); H5_DLL herr_t H5O_debug_id(hid_t type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, int indent, int fwidth); H5_DLL herr_t H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 69e3de7..cc24e19 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -47,6 +47,7 @@ const H5O_class_t H5O_SDSPACE[1] = {{ H5O_sdspace_reset, /* default reset method */ H5O_sdspace_free, /* free method */ NULL, /* file delete method */ + NULL, /* link method */ NULL, /* get share method */ NULL, /* set share method */ H5O_sdspace_debug, /* debug the message */ diff --git a/src/H5Oshared.c b/src/H5Oshared.c index f3f399e..1444e03 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -25,17 +25,22 @@ * the global heap. */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ #define H5O_PACKAGE /*suppress error about including H5Opkg */ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ #include "H5Gprivate.h" /* Groups */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*, H5O_shared_t *sh); static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*); -static size_t H5O_shared_size (H5F_t*, const void*); +static void *H5O_shared_copy(const void *_mesg, void *_dest); +static size_t H5O_shared_size (H5F_t*, const void *_mesg); +static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_shared_debug (H5F_t*, hid_t dxpl_id, const void*, FILE*, int, int); /* This message derives from H5O */ @@ -45,17 +50,22 @@ const H5O_class_t H5O_SHARED[1] = {{ sizeof(H5O_shared_t), /*native message size */ H5O_shared_decode, /*decode method */ H5O_shared_encode, /*encode method */ - NULL, /*no copy method */ + H5O_shared_copy, /*copy the native value */ H5O_shared_size, /*size method */ NULL, /*no reset method */ NULL, /*no free method */ - NULL, /* file delete method */ + H5O_shared_delete, /*file delete method */ + H5O_shared_link, /*link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_shared_debug, /*debug method */ }}; -#define H5O_SHARED_VERSION 1 +/* Old version, with full symbol table entry as link for object header sharing */ +#define H5O_SHARED_VERSION_1 1 + +/* New version, with just address of object as link for object header sharing */ +#define H5O_SHARED_VERSION 2 /* Interface initialization */ #define PABLO_MASK H5O_shared_mask @@ -64,6 +74,123 @@ static int interface_initialize_g = 0; /*------------------------------------------------------------------------- + * Function: H5O_shared_read + * + * Purpose: Reads a message referred to by a shared message. + * + * Return: Success: Ptr to message in native format. The message + * should be freed by calling H5O_reset(). If + * MESG is a null pointer then the caller should + * also call H5MM_xfree() on the return value + * after calling H5O_reset(). + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 24 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_class_t *type, void *mesg) +{ + void *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_shared_read,NULL); + + /* check args */ + assert(f); + assert(shared); + assert(type); + + /* Get the shared message */ + if (shared->in_gh) { + void *tmp_buf, *tmp_mesg; + + if (NULL==(tmp_buf = H5HG_read (f, dxpl_id, &(shared->u.gh), NULL))) + HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to read shared message from global heap"); + tmp_mesg = (type->decode)(f, dxpl_id, tmp_buf, shared); + tmp_buf = H5MM_xfree (tmp_buf); + if (!tmp_mesg) + HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to decode object header shared message"); + if (mesg) { + HDmemcpy (mesg, tmp_mesg, type->native_size); + H5MM_xfree (tmp_mesg); + } /* end if */ + else + ret_value = tmp_mesg; + } /* end if */ + else { + ret_value = H5O_read_real(&(shared->u.ent), type, 0, mesg, dxpl_id); + if (type->set_share && + (type->set_share)(f, ret_value, shared)<0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information"); + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_shared_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_shared_link_adj + * + * Purpose: Changes the link count for the object referenced by a shared + * message. + * + * Return: Success: New link count + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 26 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adjust) +{ + int ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_shared_link_adj,FAIL); + + /* check args */ + assert(f); + assert(shared); + + if (shared->in_gh) { + /* + * The shared message is stored in the global heap. + * Adjust the reference count on the global heap message. + */ + if ((ret_value = H5HG_link (f, dxpl_id, &(shared->u.gh), adjust))<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + } /* end if */ + 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. Adjust the reference count on that + * object header. + */ + if (shared->u.ent.file->shared != f->shared) + HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed"); + if ((ret_value = H5O_link (&(shared->u.ent), adjust, dxpl_id))<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_shared_link_adj() */ + + +/*------------------------------------------------------------------------- * Function: H5O_shared_decode * * Purpose: Decodes a shared object message and returns it. @@ -95,28 +222,36 @@ H5O_shared_decode (H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf, H5O_share assert (!sh); /* Decode */ - if (NULL==(mesg = H5MM_calloc (sizeof *mesg))) + if (NULL==(mesg = H5MM_calloc (sizeof(H5O_shared_t)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Version */ version = *buf++; - if (version!=H5O_SHARED_VERSION) + if (version!=H5O_SHARED_VERSION_1 && version!=H5O_SHARED_VERSION) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message"); - /* Flags */ + /* Get the shared information flags */ flags = *buf++; mesg->in_gh = (flags & 0x01); - /* Reserved */ - buf += 6; + /* Skip reserved bytes (for version 1) */ + if(version==H5O_SHARED_VERSION_1) + buf += 6; /* Body */ if (mesg->in_gh) { - H5F_addr_decode (f, &buf, &(mesg->u.gh.addr)); - INT32DECODE (buf, mesg->u.gh.idx); - } else { - H5G_ent_decode (f, &buf, &(mesg->u.ent)); - } + H5F_addr_decode (f, &buf, &(mesg->u.gh.addr)); + INT32DECODE (buf, mesg->u.gh.idx); + } /* end if */ + else { + if(version==H5O_SHARED_VERSION_1) + H5G_ent_decode (f, &buf, &(mesg->u.ent)); + else { + assert(version==H5O_SHARED_VERSION); + H5F_addr_decode (f, &buf, &(mesg->u.ent.header)); + mesg->u.ent.file=f; + } /* end else */ + } /* end else */ /* Set return value */ ret_value=mesg; @@ -165,6 +300,7 @@ H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) *buf++ = H5O_SHARED_VERSION; flags = mesg->in_gh ? 0x01 : 0x00; *buf++ = flags; +#ifdef OLD_WAY *buf++ = 0; /*reserved 1*/ *buf++ = 0; /*reserved 2*/ *buf++ = 0; /*reserved 3*/ @@ -175,9 +311,17 @@ H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) if (mesg->in_gh) { H5F_addr_encode (f, &buf, mesg->u.gh.addr); INT32ENCODE (buf, mesg->u.gh.idx); - } else { + } /* end if */ + else H5G_ent_encode (f, &buf, &(mesg->u.ent)); - } +#else /* OLD_WAY */ + if (mesg->in_gh) { + H5F_addr_encode (f, &buf, mesg->u.gh.addr); + INT32ENCODE (buf, mesg->u.gh.idx); + } /* end if */ + else + H5F_addr_encode (f, &buf, mesg->u.ent.header); +#endif /* OLD_WAY */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -185,6 +329,49 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_shared_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 26 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_shared_copy(const void *_mesg, void *_dest) +{ + const H5O_shared_t *mesg = (const H5O_shared_t *) _mesg; + H5O_shared_t *dest = (H5O_shared_t *) _dest; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_shared_copy, NULL); + + /* check args */ + assert(mesg); + if (!dest && NULL==(dest = H5MM_malloc (sizeof(H5O_shared_t)))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* copy */ + *dest = *mesg; + + /* Set return value */ + ret_value=dest; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_shared_copy() */ + + +/*------------------------------------------------------------------------- * Function: H5O_shared_size * * Purpose: Returns the length of a shared object message. @@ -201,16 +388,18 @@ done: *------------------------------------------------------------------------- */ static size_t -H5O_shared_size (H5F_t *f, const void UNUSED *_mesg) +H5O_shared_size (H5F_t *f, const void *_mesg) { + const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; size_t ret_value; FUNC_ENTER_NOAPI(H5O_shared_size, 0); - ret_value = 1 + /*the flags field */ - 7 + /*reserved */ - MAX (H5F_SIZEOF_ADDR(f)+4, /*sharing via global heap */ - H5G_SIZEOF_ENTRY(f)); /*sharing by another obj hdr */ + ret_value = 1 + /*version */ + 1 + /*the flags field */ + (shared->in_gh ? + (H5F_SIZEOF_ADDR(f)+4) : /*sharing via global heap */ + H5F_SIZEOF_ADDR(f)); /*sharing by another obj hdr */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -218,6 +407,77 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_shared_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, September 26, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +{ + const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_shared_delete, FAIL); + + /* check args */ + assert(f); + assert(shared); + + /* Decrement the reference count on the shared object */ + if(H5O_shared_link_adj(f,dxpl_id,shared,-1)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_shared_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_shared_link + * + * Purpose: Increment reference count on any objects referenced by + * message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, September 26, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) +{ + const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_shared_link, FAIL); + + /* check args */ + assert(f); + assert(shared); + + /* Decrement the reference count on the shared object */ + if(H5O_shared_link_adj(f,dxpl_id,shared,1)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_shared_link() */ + + +/*------------------------------------------------------------------------- * Function: H5O_shared_debug * * Purpose: Prints debugging info for the message diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 521ffe3..8b33884 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -59,6 +59,7 @@ const H5O_class_t H5O_STAB[1] = {{ NULL, /*default reset method */ H5O_stab_free, /* free method */ H5O_stab_delete, /* file delete method */ + NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_stab_debug, /*debug the message */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 5582339..38e0e06 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -124,7 +124,7 @@ H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id) H5F_t *file = NULL; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_commit, FAIL); + FUNC_ENTER_NOINIT(H5T_commit); assert (loc); assert (name && *name); @@ -204,9 +204,71 @@ H5Tcommitted(hid_t type_id) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* Set return value */ - ret_value= (H5T_STATE_OPEN==type->state || H5T_STATE_NAMED==type->state); + ret_value= H5T_committed(type); done: FUNC_LEAVE_API(ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5T_committed + * + * Purpose: Determines if a data type is committed or not. + * + * Return: Success: TRUE if committed, FALSE otherwise. + * + * Programmer: Quincey Koziol + * Wednesday, September 24, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5T_committed(H5T_t *type) +{ + /* Use no-init for efficiency */ + FUNC_ENTER_NOINIT(H5T_committed); + + assert (type); + + FUNC_LEAVE_NOAPI(H5T_STATE_OPEN==type->state || H5T_STATE_NAMED==type->state); +} /* end H5T_committed() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_link + * + * Purpose: Adjust the link count for an object header by adding + * ADJUST to the link count. + * + * Return: Success: New link count + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, September 26, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id) +{ + int ret_value; /* Return value */ + + /* Use no-init for efficiency */ + FUNC_ENTER_NOAPI(H5T_link,FAIL); + + assert (type); + + /* Adjust the link count on the named datatype */ + if((ret_value=H5O_link(&(type->ent),adjust,dxpl_id))<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_LINK, FAIL, "unable to adjust named datatype link count"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_link() */ + diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 1897dbf..ce975a1 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -72,6 +72,8 @@ H5_DLL herr_t H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, hsize_t ndim, hssize_t *point, void *_op_data); H5_DLL htri_t H5T_is_sensible(const H5T_t *dt); H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); +H5_DLL htri_t H5T_committed(H5T_t *type); +H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id); /* Reference specific functions */ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); -- cgit v0.12