summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5.c22
-rw-r--r--src/H5Dprivate.h1
-rw-r--r--src/H5E.c1
-rw-r--r--src/H5Epublic.h1
-rw-r--r--src/H5F.c395
-rw-r--r--src/H5Fprivate.h23
-rw-r--r--src/H5Fpublic.h2
-rw-r--r--src/H5G.c12
-rw-r--r--src/H5Gstab.c5
-rw-r--r--src/H5HG.c56
-rw-r--r--src/H5I.c41
-rw-r--r--src/H5Ofill.c84
-rw-r--r--src/H5P.c25
-rw-r--r--src/H5Ppublic.h13
14 files changed, 623 insertions, 58 deletions
diff --git a/src/H5.c b/src/H5.c
index 4c3b583..5ca82e3 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -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);
diff --git a/src/H5E.c b/src/H5E.c
index da16fb5..5123b5e 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -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 */
diff --git a/src/H5F.c b/src/H5F.c
index 937cf5e..fe3dfb6 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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
}
diff --git a/src/H5G.c b/src/H5G.c
index 3864dcf..2aa045d 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -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)) {
diff --git a/src/H5HG.c b/src/H5HG.c
index b0e4c9d..f3e73bf 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -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) {
diff --git a/src/H5I.c b/src/H5I.c
index 06ee59c..2de9b25 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -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);
}
diff --git a/src/H5P.c b/src/H5P.c
index 663f009..d9ee64f 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -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