diff options
author | Robb Matzke <matzke@llnl.gov> | 1998-10-08 17:13:14 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1998-10-08 17:13:14 (GMT) |
commit | 19ec99786adba12a7517f633888c3976738135ce (patch) | |
tree | 8d40536cf23cbded60afb3133c1cefd1aebeb3ed /src | |
parent | 1fddd40b8b45e8ced68d2192e10baf000deb0857 (diff) | |
download | hdf5-19ec99786adba12a7517f633888c3976738135ce.zip hdf5-19ec99786adba12a7517f633888c3976738135ce.tar.gz hdf5-19ec99786adba12a7517f633888c3976738135ce.tar.bz2 |
[svn-r745] Changes since 19981002
----------------------
./doc/html/H5.format.html
./src/H5HG.c
Fixed a bug in the global heap that caused H5HG_read() to
write past the end of the buffer in certain cases.
./test/big.c
The test is skipped if hdf5 was configured with
`--disable-hsizet'.
./src/H5Ofill.c
Data type conversions are implemented for the fill value.
./src/H5.c
Tracing prints one of H5P_FILE_CREATE, H5P_FILE_ACCESS,
H5P_DATASET_CREATE, H5P_DATASET_XFER, or H5P_MOUNT instead of
the more cryptic H5I_TEMPLATE_* constants.
./src/H5D.c
Removed prototype for H5D_find_name().
./src/H5I.c
The GROUP_MASK and ID_MASK are both calculated from GROUP_BITS
instead of being set by hand.
We don't use the sign bit of hid_t; all valid hid_t values are
positive so we can say things like `if ((file=H5Fopen(...))<0)'.
Changed `(int)pow(2.0,x)' to `1<<x' so we don't have to worry
about rounding.
Fixed H5I_get_type() so it doesn't always fail an assertion.
./src/H5E.c
./src/H5Epublic.h
Added minor error H5E_MOUNT
./src/H5F.c
./src/H5Fprivate.h
Added H5Fmount() and H5Funmount(). Mounting and unmounting
works as documented but some of the other things aren't
implemented yet, the biggest being current working groups
always acting on the root of the mount tree, and H5Fclose()
closing the entire tree. The rest of the stuff will be added
shortly...
./src/H5P.c
./src/H5Ppublic.h
Added the H5P_MOUNT property list but haven't implemented any
particular properties for it yet.
./src/H5Gstab.c
Hard links across files return an error instead of failing an
assertion.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5.c | 22 | ||||
-rw-r--r-- | src/H5Dprivate.h | 1 | ||||
-rw-r--r-- | src/H5E.c | 1 | ||||
-rw-r--r-- | src/H5Epublic.h | 1 | ||||
-rw-r--r-- | src/H5F.c | 395 | ||||
-rw-r--r-- | src/H5Fprivate.h | 23 | ||||
-rw-r--r-- | src/H5Fpublic.h | 2 | ||||
-rw-r--r-- | src/H5G.c | 12 | ||||
-rw-r--r-- | src/H5Gstab.c | 5 | ||||
-rw-r--r-- | src/H5HG.c | 56 | ||||
-rw-r--r-- | src/H5I.c | 41 | ||||
-rw-r--r-- | src/H5Ofill.c | 84 | ||||
-rw-r--r-- | src/H5P.c | 25 | ||||
-rw-r--r-- | src/H5Ppublic.h | 13 |
14 files changed, 623 insertions, 58 deletions
@@ -1769,7 +1769,27 @@ H5_trace (hbool_t returning, const char *func, const char *type, ...) case H5I_TEMPLATE_5: case H5I_TEMPLATE_6: case H5I_TEMPLATE_7: - fprintf (out, "H5I_TEMPLATE_%d",(int)(id_type-H5I_TEMPLATE_0)); + switch (H5Pget_class(id_type)) { + case H5P_FILE_CREATE: + fprintf(out, "H5P_FILE_CREATE"); + break; + case H5P_FILE_ACCESS: + fprintf(out, "H5P_FILE_ACCESS"); + break; + case H5P_DATASET_CREATE: + fprintf(out, "H5P_DATASET_CREATE"); + break; + case H5P_DATASET_XFER: + fprintf(out, "H5P_DATASET_XFER"); + break; + case H5P_MOUNT: + fprintf(out, "H5P_MOUNT"); + break; + default: + fprintf (out, "H5I_TEMPLATE_%d", + (int)(id_type-H5I_TEMPLATE_0)); + break; + } break; case H5I_GROUP: fprintf (out, "H5I_GROUP"); diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 4e15bf1..1f23d82 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -77,7 +77,6 @@ herr_t H5D_read (H5D_t *dataset, const H5T_t *mem_type, herr_t H5D_write (H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, const H5D_xfer_t *xfer_parms, const void *buf); -hid_t H5D_find_name (hid_t file_id, H5I_type_t UNUSED, const char *name); herr_t H5D_extend (H5D_t *dataset, const hsize_t *size); H5G_entry_t *H5D_entof (H5D_t *dataset); H5T_t *H5D_typeof (H5D_t *dset); @@ -77,6 +77,7 @@ static const H5E_minor_mesg_t H5E_minor_mesg_g[] = { {H5E_NOTHDF5, "Not an HDF5 file"}, {H5E_BADFILE, "Bad file ID accessed"}, {H5E_TRUNCATED, "File has been truncated"}, + {H5E_MOUNT, "File mount error"}, {H5E_SEEKERROR, "Seek failed"}, {H5E_READERROR, "Read failed"}, {H5E_WRITEERROR, "Write failed"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index a31317f..fed1296 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -100,6 +100,7 @@ typedef enum H5E_minor_t { H5E_NOTHDF5, /*not an HDF5 format file */ H5E_BADFILE, /*bad file ID accessed */ H5E_TRUNCATED, /*file has been truncated */ + H5E_MOUNT, /*file mount error */ /* Generic low-level file I/O errors */ H5E_SEEKERROR, /*seek failed */ @@ -94,6 +94,13 @@ const H5F_create_t H5F_create_dflt = { */ H5F_access_t H5F_access_dflt; +/* + * Define the default mount property list. + */ +const H5F_mprop_t H5F_mount_dflt = { + FALSE, /* Absolute symlinks are wrt mount root */ +}; + /* Interface initialization */ static intn interface_initialize_g = FALSE; #define INTERFACE_INIT H5F_init_interface @@ -1661,6 +1668,394 @@ H5Fclose(hid_t file_id) done: FUNC_LEAVE(ret_value < 0 ? FAIL : SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5F_mount + * + * Purpose: Mount file CHILD onto the group specified by LOC and NAME, + * using mount properties in PLIST. CHILD must not already be + * mouted and must not be a mount ancestor of the mount-point. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, + const H5F_mprop_t *plist) +{ + H5G_t *mount_point = NULL; /*mount point group */ + H5G_entry_t *mp_ent = NULL; /*mount point symbol table entry*/ + H5F_t *ancestor = NULL; /*ancestor files */ + H5F_t *parent = NULL; /*file containing mount point */ + intn lt, rt, md, cmp; /*binary search indices */ + H5G_entry_t *ent = NULL; /*temporary symbol table entry */ + herr_t ret_value = FAIL; /*return value */ + + FUNC_ENTER(H5F_mount, FAIL); + assert(loc); + assert(name && *name); + assert(child); + assert(plist); + + /* + * Check that the child isn't mounted, that the mount point exists, and + * that the mount wouldn't introduce a cycle in the mount tree. + */ + if (child->mtab.parent) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted"); + } + if (NULL==(mount_point=H5G_open(loc, name))) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found"); + } + parent = H5G_fileof(mount_point); + mp_ent = H5G_entof(mount_point); + for (ancestor=parent; ancestor; ancestor=ancestor->mtab.parent) { + if (ancestor==child) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, + "mount would introduce a cycle"); + } + } + + /* + * Use a binary search to locate the position that the child should be + * inserted into the parent mount table. At the end of this paragraph + * `md' will be the index where the child should be inserted. + */ + lt = md = 0; + rt = parent->mtab.nmounts; + cmp = -1; + while (lt<rt && cmp) { + md = (lt+rt)/2; + ent = H5G_entof(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(&(mp_ent->header), &(ent->header)); + if (cmp<0) { + rt = md; + } else if (cmp>0) { + lt = md+1; + } + } + if (cmp>0) md++; + if (!cmp) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, + "mount point is already in use"); + } + + /* Make room in the table */ + if (parent->mtab.nmounts>=parent->mtab.nalloc) { + uintn n = MAX(16, 2*parent->mtab.nalloc); + H5F_mount_t *x = H5MM_realloc(parent->mtab.child, + n*sizeof(parent->mtab.child[0])); + if (!x) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed for mount table"); + } + parent->mtab.child = x; + parent->mtab.nalloc = n; + } + + /* Insert into table */ + HDmemmove(parent->mtab.child+md+1, + parent->mtab.child+md, + (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); + parent->mtab.nmounts++; + parent->mtab.child[md].group = mount_point; + parent->mtab.child[md].file = child; + child->mtab.parent = parent; + ret_value = SUCCEED; + + done: + if (ret_value<0 && mount_point) { + H5G_close(mount_point); + } + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_unmount + * + * Purpose: Unmount the child which is mounted at the group specified by + * LOC and NAME or fail if nothing is mounted there. Neither + * file is closed. + * + * Because the mount point is specified by name and opened as a + * group, the H5G_namei() will resolve it to the root of the + * mounted file, not the group where the file is mounted. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_unmount(H5G_entry_t *loc, const char *name) +{ + H5G_t *mounted = NULL; /*mount point group */ + H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */ + H5F_t *child = NULL; /*mounted file */ + H5F_t *parent = NULL; /*file where mounted */ + H5G_entry_t *ent = NULL; /*temporary symbol table entry */ + herr_t ret_value = FAIL; /*return value */ + uintn i; /*coutners */ + intn lt, rt, md, cmp; /*binary search indices */ + + FUNC_ENTER(H5F_unmount, FAIL); + assert(loc); + assert(name && *name); + + /* + * Get the mount point, or more precisely the root of the mounted file. + * If we get the root group and the file has a parent in the mount tree, + * then we must have found the mount point. + */ + if (NULL==(mounted=H5G_open(loc, name))) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found"); + } + child = H5G_fileof(mounted); + mnt_ent = H5G_entof(mounted); + ent = H5G_entof(child->shared->root_grp); + + if (child->mtab.parent && + H5F_addr_eq(&(mnt_ent->header), &(ent->header))) { + /* + * We've been given the root group of the child. We do a reverse + * lookup in the parent's mount table to find the correct entry. + */ + parent = child->mtab.parent; + for (i=0; i<parent->mtab.nmounts; i++) { + if (parent->mtab.child[i].file==child) { + /* Unmount the child */ + parent->mtab.nmounts -= 1; + H5G_close(parent->mtab.child[i].group); + child->mtab.parent = NULL; + HDmemmove(parent->mtab.child+i, + parent->mtab.child+i+1, + ((parent->mtab.nmounts-i)* + sizeof(parent->mtab.child[0]))); + ret_value = SUCCEED; + } + } + assert(ret_value>=0); + + } else { + /* + * We've been given the mount point in the parent. We use a binary + * search in the parent to locate the mounted file, if any. + */ + parent = child; /*we guessed wrong*/ + lt = 0; + rt = parent->mtab.nmounts; + cmp = -1; + while (lt<rt && cmp) { + md = (lt+rt)/2; + ent = H5G_entof(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(&(mnt_ent->header), &(ent->header)); + if (cmp<0) { + rt = md; + } else { + lt = md+1; + } + } + if (cmp) { + HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point"); + } + + /* Unmount the child */ + parent->mtab.nmounts -= 1; + H5G_close(parent->mtab.child[md].group); + parent->mtab.child[md].file->mtab.parent = NULL; + HDmemmove(parent->mtab.child+md, + parent->mtab.child+md+1, + (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); + ret_value = SUCCEED; + } + + done: + if (mounted) H5G_close(mounted); + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5F_mountpoint + * + * Purpose: If ENT is a mount point then copy the entry for the root + * group of the mounted file into ENT. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_mountpoint(H5G_entry_t *find/*in,out*/) +{ + H5F_t *parent = find->file; + intn lt, rt, md, cmp; + H5G_entry_t *ent = NULL; + + FUNC_ENTER(H5F_mountpoint, FAIL); + assert(find); + + /* + * The loop is necessary because we might have file1 mounted at the root + * of file2, which is mounted somewhere in file3. + */ + do { + /* + * Use a binary search to find the potential mount point in the mount + * table for the parent + */ + lt = 0; + rt = parent->mtab.nmounts; + cmp = -1; + while (lt<rt && cmp) { + md = (lt+rt)/2; + ent = H5G_entof(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(&(find->header), &(ent->header)); + if (cmp<0) { + rt = md; + } else { + lt = md+1; + } + } + + /* Copy root info over to ENT */ + if (0==cmp) { + ent = H5G_entof(parent->mtab.child[md].file->shared->root_grp); + *find = *ent; + } + } while (!cmp); + + FUNC_LEAVE(SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Fmount + * + * Purpose: Mount file CHILD_ID onto the group specified by LOC_ID and + * NAME using mount properties PLIST_ID. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) +{ + H5G_entry_t *loc = NULL; + const H5F_mprop_t *plist = NULL; + H5F_t *child = NULL; + + FUNC_ENTER(H5Fmount, FAIL); + H5TRACE4("e","isii",loc_id,name,child_id,plist_id); + + /* Check arguments */ + if (NULL==(loc=H5G_loc(loc_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + } + if (!name || !*name) { + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + } + if (H5I_FILE!=H5I_get_type(child_id) || + NULL==(child=H5I_object(child_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + } + if (H5P_DEFAULT==plist_id) { + plist = &H5F_mount_dflt; + } else if (H5P_MOUNT!=H5P_get_class(plist_id) || + NULL==(plist=H5I_object(plist_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a mount property list"); + } + + /* Do the mount */ + if (H5F_mount(loc, name, child, plist)<0) { + HRETURN_ERROR(H5E_FILE, H5E_MOUNT, FAIL, + "unable to mount file"); + } + + FUNC_LEAVE(SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Funmount + * + * Purpose: Given a mount point, dissassociate the mount point's file + * from the file mounted there. Do not close either file. + * + * The mount point can either be the group in the parent or the + * root group of the mounted file (both groups have the same + * name). If the mount point was opened before the mount then + * it's the group in the parent, but if it was opened after the + * mount then it's the root group of the child. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Funmount(hid_t loc_id, const char *name) +{ + H5G_entry_t *loc = NULL; + + FUNC_ENTER(H5Funmount, FAIL); + H5TRACE2("i","is",loc_id,name); + + /* Check args */ + if (NULL==(loc=H5G_loc(loc_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + } + if (!name || !*name) { + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + } + + /* Unmount */ + if (H5F_unmount(loc, name)<0) { + HRETURN_ERROR(H5E_FILE, H5E_MOUNT, FAIL, + "unable to unmount file"); + } + + FUNC_LEAVE(SUCCEED); +} + /*------------------------------------------------------------------------- * Function: H5F_block_read diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 7f25090..8f33cc0 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -426,6 +426,25 @@ typedef struct H5F_rdcc_t { struct H5F_rdcc_ent_t **slot; /* Chunk slots, each points to a chunk*/ } H5F_rdcc_t; +/* Mount property list */ +typedef struct H5F_mprop_t { + hbool_t local; /* Are absolute symlinks local to file? */ +} H5F_mprop_t; + +/* A record of the mount table */ +typedef struct H5F_mount_t { + struct H5G_t *group; /* Mount point group held open */ + struct H5F_t *file; /* File mounted at that point */ +} H5F_mount_t; + +/* The mount table */ +typedef struct H5F_mtab_t { + struct H5F_t *parent;/* Parent file */ + uintn nmounts;/* Number of children which are mounted */ + uintn nalloc; /* Number of mount slots allocated */ + H5F_mount_t *child; /* An array of mount records */ +} H5F_mtab_t; + /* * Define the structure to store the file information for HDF5 files. One of * these structures is allocated per file, not per H5Fopen(). @@ -463,6 +482,7 @@ typedef struct H5F_t { struct H5G_cwgstk_t *cwg_stack; /* CWG stack for push/pop functions*/ uintn nopen; /* Number of open object headers*/ hbool_t close_pending; /* File close is pending */ + H5F_mtab_t mtab; /* File mount table */ } H5F_t; #ifdef NOT_YET @@ -509,10 +529,12 @@ struct H5O_efl_t; struct H5O_pline_t; struct H5D_xfer_t; struct H5O_fill_t; +struct H5G_entry_t; /* library variables */ extern const H5F_create_t H5F_create_dflt; extern H5F_access_t H5F_access_dflt; +extern const H5F_mprop_t H5F_mount_dflt; #ifdef HAVE_PARALLEL extern hbool_t H5_mpi_1_metawrite_g; @@ -529,6 +551,7 @@ herr_t H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, intn fwidth); herr_t H5F_istore_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, intn fwidth, int ndims); +herr_t H5F_mountpoint(struct H5G_entry_t *find/*in,out*/); /* Functions that operate on array storage */ herr_t H5F_arr_create(H5F_t *f, struct H5O_layout_t *layout /*in,out*/); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index d00c1d7..319eeeb 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -85,6 +85,8 @@ herr_t H5Fflush(hid_t object_id); herr_t H5Fclose (hid_t file_id); hid_t H5Fget_create_plist (hid_t file_id); hid_t H5Fget_access_plist (hid_t file_id); +herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist); +herr_t H5Funmount(hid_t loc, const char *name); #ifdef __cplusplus } @@ -1019,6 +1019,11 @@ H5G_basename(const char *name, size_t *size_p) * FOLLOW_SLINK is false and the last component of the name is a * symbolic link then that link is not followed. At most NLINKS * are followed and the next link generates an error. + * + * Mounted files are handled by calling H5F_mountpoint() after + * each step of the translation. If the input argument to that + * function is a mount point then the argument shall be replaced + * with information about the root group of the mounted file. * * Errors: * @@ -1075,7 +1080,6 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, HDmemset(grp_ent, 0, sizeof(H5G_entry_t)); H5F_addr_undef(&(grp_ent->header)); - /* traverse the name */ while ((name = H5G_component(name, &nchars)) && *name) { if (rest) *rest = name; @@ -1132,6 +1136,7 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, } /* next component */ + H5F_mountpoint(obj_ent/*in,out*/); name += nchars; } if (rest) *rest = name; /*final null */ @@ -1737,10 +1742,11 @@ H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent) * Insert the object into a symbol table. */ if (H5O_link(ent, 1) < 0) { - HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "link inc failure"); + HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, + "unable to increment hard link count"); } if (H5G_stab_insert(&grp, rest, ent) < 0) { - HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't insert"); + HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to insert name"); } FUNC_LEAVE(SUCCEED); } diff --git a/src/H5Gstab.c b/src/H5Gstab.c index cd71183..2e36135 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -191,7 +191,10 @@ H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent) assert(grp_ent && grp_ent->file); assert(name && *name); assert(obj_ent && obj_ent->file); - assert(grp_ent->file->shared == obj_ent->file->shared); + if (grp_ent->file->shared != obj_ent->file->shared) { + HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, + "interfile hard links are not allowed"); + } /* initialize data to pass through B-tree */ if (NULL == H5O_read(grp_ent, H5O_STAB, 0, &stab)) { @@ -136,7 +136,7 @@ H5HG_create (H5F_t *f, size_t size) H5F_encode_length (f, p, size); /* The freespace object */ - heap->obj[0].size = size - H5HG_SIZEOF_HDR (f); + heap->obj[0].size = size - H5HG_SIZEOF_HDR(f); heap->obj[0].begin = p; UINT16ENCODE(p, 0); /*object ID*/ UINT16ENCODE(p, 0); /*reference count*/ @@ -294,10 +294,11 @@ H5HG_load (H5F_t *f, const haddr_t *addr, const void __unused__ *udata1, p += 4; /*reserved*/ H5F_decode_length (f, p, heap->obj[idx].size); heap->obj[idx].begin = begin; - p = begin + heap->obj[idx].size; + p = begin + H5HG_ALIGN(heap->obj[idx].size); } } - assert (p==heap->chunk+heap->size); + assert(p==heap->chunk+heap->size); + assert(heap->obj[0].size==H5HG_ALIGN(heap->obj[0].size)); /* * Add the new heap to the CWFS list, removing some other entry if @@ -404,7 +405,9 @@ H5HG_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, H5HG_heap_t *heap) * * Purpose: Given a heap with enough free space, this function will split * the free space to make a new empty heap object and initialize - * the header. + * the header. SIZE is the exact size of the object data to be + * stored. It will be increased to make room for the object + * header and then rounded up for alignment. * * Return: Success: The heap object ID of the new object. * @@ -422,12 +425,13 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, int cwfsno, size_t size) { int idx; uint8 *p = NULL; - + size_t need = H5HG_ALIGN(H5HG_SIZEOF_OBJHDR(f) + size); + FUNC_ENTER (H5HG_alloc, FAIL); /* Check args */ assert (heap); - assert (heap->obj[0].size>=size); + assert (heap->obj[0].size>=need); /* * Find an ID for the new object. ID zero is reserved for the free space @@ -449,7 +453,7 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, int cwfsno, size_t size) H5F_encode_length (f, p, size); /* Fix the free space object */ - if (size==heap->obj[0].size) { + if (need==heap->obj[0].size) { /* * All free space has been exhausted from this collection. Remove the * heap from the CWFS list. @@ -462,13 +466,13 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, int cwfsno, size_t size) (f->shared->ncwfs-cwfsno)*sizeof(H5HG_heap_t*)); } - } else if (heap->obj[0].size-size >= H5HG_SIZEOF_OBJHDR (f)) { + } else if (heap->obj[0].size-need >= H5HG_SIZEOF_OBJHDR (f)) { /* * Some free space remains and it's larger than a heap object header, * so write the new free heap object header to the heap. */ - heap->obj[0].size -= size; - heap->obj[0].begin += size; + heap->obj[0].size -= need; + heap->obj[0].begin += need; p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ @@ -480,8 +484,8 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, int cwfsno, size_t size) * Some free space remains but it's smaller than a heap object header, * so we don't write the header. */ - heap->obj[0].size -= size; - heap->obj[0].begin += size; + heap->obj[0].size -= need; + heap->obj[0].begin += need; } heap->dirty = 1; @@ -566,7 +570,7 @@ H5HG_insert (H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/) } /* Split the free space to make room for the new object */ - idx = H5HG_alloc (f, heap, cwfsno, need); + idx = H5HG_alloc (f, heap, cwfsno, size); assert (idx>0); /* Copy data into the heap */ @@ -683,7 +687,7 @@ H5HG_read (H5F_t *f, H5HG_t *hobj, void *object/*out*/) } assert (hobj->idx>0 && hobj->idx<heap->nalloc); assert (heap->obj[hobj->idx].begin); - size = heap->obj[hobj->idx].size - H5HG_SIZEOF_OBJHDR (f); + size = heap->obj[hobj->idx].size; p = heap->obj[hobj->idx].begin + H5HG_SIZEOF_OBJHDR (f); if (!object && NULL==(object = H5MM_malloc (size))) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, @@ -788,7 +792,7 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) { uint8 *p=NULL, *obj_start=NULL; H5HG_heap_t *heap = NULL; - size_t size; + size_t need; intn i; FUNC_ENTER (H5HG_remove, FAIL); @@ -808,29 +812,29 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) assert (hobj->idx>0 && hobj->idx<heap->nalloc); assert (heap->obj[hobj->idx].begin); obj_start = heap->obj[hobj->idx].begin; - size = heap->obj[hobj->idx].size; + need = H5HG_ALIGN(heap->obj[hobj->idx].size); /* Move the new free space to the end of the heap */ for (i=0; i<heap->nalloc; i++) { if (heap->obj[i].begin > heap->obj[hobj->idx].begin) { - heap->obj[i].begin -= size; + heap->obj[i].begin -= need; } } if (NULL==heap->obj[0].begin) { - heap->obj[0].begin = heap->chunk + (heap->size-size); - heap->obj[0].size = size; + heap->obj[0].begin = heap->chunk + (heap->size-need); + heap->obj[0].size = need; heap->obj[0].nrefs = 0; } else { - heap->obj[0].size += size; + heap->obj[0].size += need; } - HDmemmove (obj_start, obj_start+size, - heap->size-((obj_start+size)-heap->chunk)); + HDmemmove (obj_start, obj_start+need, + heap->size-((obj_start+need)-heap->chunk)); if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) { p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ UINT32ENCODE(p, 0); /*reserved*/ - H5F_encode_length (f, p, size); + H5F_encode_length (f, p, need); } HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t)); heap->dirty = 1; @@ -940,9 +944,11 @@ H5HG_debug(H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, fprintf (stream, "%*s%-*s %d\n", indent+3, "", MIN(fwidth-3, 0), "Reference count:", h->obj[i].nrefs); - fprintf (stream, "%*s%-*s %lu\n", indent+3, "", MIN(fwidth-3, 0), + fprintf (stream, "%*s%-*s %lu/%lu\n", indent+3, "", + MIN(fwidth-3, 0), "Size of object body:", - (unsigned long)(h->obj[i].size)); + (unsigned long)(h->obj[i].size), + (unsigned long)H5HG_ALIGN(h->obj[i].size)); size = h->obj[i].size - H5HG_SIZEOF_OBJHDR (f); p = h->obj[i].begin + H5HG_SIZEOF_OBJHDR (f); for (j=0; j<size; j+=16) { @@ -84,18 +84,25 @@ static herr_t H5I_init_interface(void); # define ID_CACHE_SIZE 4 /*# of previous atoms cached */ #endif -/* # of bits to use for Group ID in each atom (change if H5I_MAXID>32) */ -#define GROUP_BITS 5 -#define GROUP_MASK 0x1F +/* + * Number of bits to use for Group ID in each atom. Increase if H5I_MAXID + * becomes too large (an assertion would fail in H5I_init_interface). This is + * the only number that must be changed since all other bit field sizes and + * masks are calculated from GROUP_BITS. + */ +#define GROUP_BITS 5 +#define GROUP_MASK ((1<<GROUP_BITS)-1) -/* # of bits to use for the Atom index in each atom (assumes 8-bit bytes) */ -#define ID_BITS ((sizeof(hid_t)*8)-GROUP_BITS) -#define ID_MASK 0x07FFFFFF +/* + * Number of bits to use for the Atom index in each atom (assumes 8-bit + * bytes). We don't use the sign bit. + */ +#define ID_BITS ((sizeof(hid_t)*8)-(GROUP_BITS+1)) +#define ID_MASK ((1<<ID_BITS)-1) /* Map an atom to a Group number */ -#define H5I_GROUP(a) ((H5I_type_t) \ - ((((hid_t)(a))>> \ - ((sizeof(hid_t)*8)-GROUP_BITS))&GROUP_MASK)) +#define H5I_GROUP(a) ((H5I_type_t)(((hid_t)(a)>>ID_BITS) & GROUP_MASK)) + #ifdef HASH_SIZE_POWER_2 /* @@ -107,11 +114,11 @@ static herr_t H5I_init_interface(void); /* * Map an ID to a hash location. */ -# define H5I_LOC(a,s) (((hid_t)(a)&ID_MASK)%(s)) +# define H5I_LOC(a,s) (((hid_t)(a)&ID_MASK)%(s)) #endif /* Combine a Group number and an atom index into an atom */ -#define H5I_MAKE(g,i) ((((hid_t)(g)&GROUP_MASK)<<ID_BITS)| \ +#define H5I_MAKE(g,i) ((((hid_t)(g)&GROUP_MASK)<<ID_BITS)| \ ((hid_t)(i)&ID_MASK)) #ifdef IDS_ARE_CACHED @@ -148,8 +155,15 @@ H5I_init_interface(void) herr_t ret_value = SUCCEED; FUNC_ENTER(H5I_init_interface, FAIL); - /* Make certain the ID types don't overflow the number of bits allocated for them in an ID */ + /* + * Make certain the ID types don't overflow the number of bits allocated + * for them in an ID. + */ +#if 0 assert((int)H5I_MAXID<=(int)pow((double)2.0,(double)GROUP_BITS)); +#else + assert(H5I_MAXID<=(1<<GROUP_BITS)); +#endif /* Registers the cleanup routine with the exit chain */ ret_value = H5_add_exit(&H5I_term_interface); @@ -554,9 +568,8 @@ H5I_get_type(hid_t id) FUNC_ENTER(H5I_get_type, H5I_BADID); - assert(id>H5I_BADID && id<H5I_MAXID); - ret_value = H5I_GROUP(id); + assert(ret_value>H5I_BADID && ret_value<H5I_MAXID); FUNC_LEAVE(ret_value); } diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 29e5914..cdedf98 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -10,6 +10,7 @@ */ #include <H5private.h> #include <H5Eprivate.h> +#include <H5Iprivate.h> #include <H5MMprivate.h> #include <H5Oprivate.h> @@ -296,7 +297,9 @@ H5O_fill_debug(H5F_t *f, const void *_mesg, FILE *stream, intn indent, * Function: H5O_fill_convert * * Purpose: Convert a fill value from whatever data type it currently has - * to the specified data type. + * to the specified dataset type. The `type' field of the fill + * value struct will be set to NULL to indicate that it has the + * same type as the dataset. * * Return: Success: SUCCEED * @@ -312,6 +315,16 @@ H5O_fill_debug(H5F_t *f, const void *_mesg, FILE *stream, intn indent, herr_t H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type) { + H5T_cdata_t *cdata=NULL; /*conversion data */ + H5T_conv_t cfunc=NULL; /*conversion function */ + void *buf=NULL, *bkg=NULL; /*conversion buffers */ + herr_t status; /*conversion status */ + hid_t src_id=-1, dst_id=-1; /*data type identifiers */ + herr_t ret_value=FAIL; /*return value */ +#ifdef H5T_DEBUG + H5_timer_t timer; /*debugging timer */ +#endif + FUNC_ENTER(H5O_fill_convert, FAIL); assert(fill); assert(dset_type); @@ -322,10 +335,69 @@ H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type) fill->type = NULL; HRETURN(SUCCEED); } - - - HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, - "fill value conversion not supported yet"); - FUNC_LEAVE(SUCCEED); + /* + * Can we convert between source and destination data types? + */ + if (NULL==(cfunc=H5T_find(fill->type, dset_type, H5T_BKG_NO, &cdata))) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to convert between src and dst data types"); + } + if ((src_id = H5I_register(H5I_DATATYPE, + H5T_copy(fill->type, H5T_COPY_TRANSIENT)))<0 || + (dst_id = H5I_register(H5I_DATATYPE, + H5T_copy(dset_type, H5T_COPY_TRANSIENT)))<0) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to copy/register data type"); + } + + /* + * Data type conversions are always done in place, so we need a buffer + * that is large enough for both source and destination. + */ + if (H5T_get_size(fill->type)>=H5T_get_size(dset_type)) { + buf = fill->buf; + } else { + if (NULL==(buf=H5MM_malloc(H5T_get_size(dset_type)))) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed for type conversion"); + } + HDmemcpy(buf, fill->buf, H5T_get_size(fill->type)); + } + if (cdata->need_bkg>=H5T_BKG_TEMP && + NULL==(bkg=H5MM_malloc(H5T_get_size(dset_type)))) { + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed for type conversion"); + } + + /* Do the conversion */ +#ifdef H5T_DEBUG + H5T_timer_begin(&timer, cdata); +#endif + cdata->command = H5T_CONV_CONV; + status = (cfunc)(src_id, dst_id, cdata, 1, buf, bkg); +#ifdef H5T_DEBUG + H5T_timer_end(&timer, cdata, 1); +#endif + if (status<0) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "data type conversion failed"); + } + + /* Update the fill message */ + if (buf!=fill->buf) { + H5MM_xfree(fill->buf); + fill->buf = buf; + } + H5T_close(fill->type); + fill->type = NULL; + fill->size = H5T_get_size(dset_type); + ret_value = SUCCEED; + + done: + if (src_id>=0) H5I_dec_ref(src_id); + if (dst_id>=0) H5I_dec_ref(dst_id); + if (buf!=fill->buf) H5MM_xfree(buf); + H5MM_xfree(bkg); + FUNC_LEAVE(ret_value); } @@ -188,6 +188,14 @@ H5Pcreate(H5P_class_t type) HDmemcpy(plist, &H5D_xfer_dflt, sizeof(H5D_xfer_t)); break; + case H5P_MOUNT: + if (NULL==(plist = H5MM_malloc(sizeof(H5F_mprop_t)))) { + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "memory allocation failed"); + } + HDmemcpy(plist, &H5F_mount_dflt, sizeof(H5F_mprop_t)); + break; + default: HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown property list class"); @@ -355,6 +363,10 @@ H5P_close (H5P_class_t type, void *plist) /*nothing to do*/ break; + case H5P_MOUNT: + /*nothing to do*/ + break; + default: HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "unknown property list class"); @@ -2712,10 +2724,12 @@ H5Pget_fill_value(hid_t plist_id, hid_t type_id, void *value/*out*/) H5T_conv_t cfunc = NULL; /*conversion function */ void *buf = NULL; /*conversion buffer */ void *bkg = NULL; /*conversion buffer */ - H5_timer_t timer; /*conversion timer */ hid_t src_id = -1; /*source data type id */ herr_t status; herr_t ret_value = FAIL; +#ifdef H5T_DEBUG + H5_timer_t timer; /*conversion timer */ +#endif FUNC_ENTER(H5Pget_fill_value, FAIL); H5TRACE3("e","iix",plist_id,type_id,value); @@ -3150,6 +3164,10 @@ H5P_copy (H5P_class_t type, const void *src) size = sizeof(H5D_xfer_t); break; + case H5P_MOUNT: + size = sizeof(H5F_mprop_t); + break; + default: HRETURN_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "unknown property list class"); @@ -3220,6 +3238,11 @@ H5P_copy (H5P_class_t type, const void *src) break; case H5P_DATASET_XFER: + /* Nothing to do */ + break; + + case H5P_MOUNT: + /* Nothing to do */ break; default: diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index cccd4fd..c59b506 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -27,15 +27,16 @@ #include <H5Fpublic.h> #include <H5Zpublic.h> -/* Template classes */ +/* Property list classes */ typedef enum H5P_class_t { H5P_NO_CLASS = -1, /*error return value */ - H5P_FILE_CREATE = 0, /*file creation template */ - H5P_FILE_ACCESS = 1, /*file access template */ - H5P_DATASET_CREATE = 2, /*dataset creation template */ - H5P_DATASET_XFER = 3, /*dataset transfer template */ + H5P_FILE_CREATE = 0, /*file creation properties */ + H5P_FILE_ACCESS = 1, /*file access properties */ + H5P_DATASET_CREATE = 2, /*dataset creation properties */ + H5P_DATASET_XFER = 3, /*dataset transfer properties */ + H5P_MOUNT = 4, /*file mounting properties */ - H5P_NCLASSES = 4 /*this must be last! */ + H5P_NCLASSES = 5 /*this must be last! */ } H5P_class_t; #ifdef __cplusplus |