diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2012-03-31 08:49:35 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2012-03-31 08:49:35 (GMT) |
commit | c2a9dcb8977f81ff8e66bfd41c72f106993d3086 (patch) | |
tree | a73dacf5ae2aa108fce2d14dc731f9558baddfc8 /src | |
parent | b51ffb25fe610675a7470cf50efed5bcdf2bf79f (diff) | |
download | hdf5-c2a9dcb8977f81ff8e66bfd41c72f106993d3086.zip hdf5-c2a9dcb8977f81ff8e66bfd41c72f106993d3086.tar.gz hdf5-c2a9dcb8977f81ff8e66bfd41c72f106993d3086.tar.bz2 |
[svn-r22219] Description:
Merge "file image" changes from feature branch back to trunk.
Tested on:
Mac OSX/64 10.7.3 (amazon) w/debug
(h5committest upcoming)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Dint.c | 3 | ||||
-rw-r--r-- | src/H5E.c | 12 | ||||
-rw-r--r-- | src/H5Edefin.h | 1 | ||||
-rw-r--r-- | src/H5Einit.h | 5 | ||||
-rw-r--r-- | src/H5Epubgen.h | 2 | ||||
-rw-r--r-- | src/H5Eterm.h | 3 | ||||
-rw-r--r-- | src/H5F.c | 284 | ||||
-rw-r--r-- | src/H5FD.c | 82 | ||||
-rw-r--r-- | src/H5FDcore.c | 293 | ||||
-rw-r--r-- | src/H5FDfamily.c | 2 | ||||
-rw-r--r-- | src/H5FDlog.c | 2 | ||||
-rw-r--r-- | src/H5FDprivate.h | 26 | ||||
-rw-r--r-- | src/H5FDpublic.h | 40 | ||||
-rw-r--r-- | src/H5FDsec2.c | 2 | ||||
-rw-r--r-- | src/H5Fprivate.h | 5 | ||||
-rw-r--r-- | src/H5Fpublic.h | 1 | ||||
-rw-r--r-- | src/H5Gname.c | 11 | ||||
-rw-r--r-- | src/H5I.c | 144 | ||||
-rw-r--r-- | src/H5Iprivate.h | 2 | ||||
-rw-r--r-- | src/H5Oattribute.c | 11 | ||||
-rw-r--r-- | src/H5Pfapl.c | 497 | ||||
-rw-r--r-- | src/H5Pint.c | 54 | ||||
-rw-r--r-- | src/H5Ppublic.h | 6 | ||||
-rw-r--r-- | src/H5T.c | 3 | ||||
-rw-r--r-- | src/H5err.txt | 1 |
25 files changed, 1226 insertions, 266 deletions
diff --git a/src/H5Dint.c b/src/H5Dint.c index 5c905bb..28d5367 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -2436,7 +2436,8 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id) udata.dxpl_id = dxpl_id; /* Iterate over all the open datasets */ - H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE); + if(H5I_iterate(H5I_DATASET, H5D_flush_cb, &udata, FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to flush cached dataset info") done: FUNC_LEAVE_NOAPI(ret_value) @@ -107,7 +107,7 @@ static H5E_cls_t *H5E_register_class(const char *cls_name, const char *lib_name, const char *version); static herr_t H5E_unregister_class(H5E_cls_t *cls); static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size); -static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key); +static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata); static herr_t H5E_close_msg(H5E_msg_t *err); static H5E_msg_t *H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg); static H5E_t *H5E_get_current_stack(void); @@ -543,8 +543,8 @@ H5E_unregister_class(H5E_cls_t *cls) HDassert(cls); /* Iterate over all the messages and delete those in this error class */ - /* (Ignore return value, since callback isn't designed to return a particular object) */ - (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE); + if(H5I_iterate(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE) < 0) + HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class") /* Free error class structure */ if(H5E_free_class(cls) < 0) @@ -631,7 +631,7 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) /*------------------------------------------------------------------------- * Function: H5E_close_msg_cb * - * Purpose: H5I_search callback function to close error messages in the + * Purpose: H5I_iterate callback function to close error messages in the * error class. * * Return: Non-negative value on success/Negative on failure @@ -642,10 +642,10 @@ H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) *------------------------------------------------------------------------- */ static int -H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key) +H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata) { H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr; - H5E_cls_t *cls = (H5E_cls_t*)key; + H5E_cls_t *cls = (H5E_cls_t*)udata; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 887c2bb..ee284c4 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -93,6 +93,7 @@ hid_t H5E_CANTRELEASE_g = FAIL; /* Unable to release object */ hid_t H5E_CANTGET_g = FAIL; /* Can't get value */ hid_t H5E_CANTSET_g = FAIL; /* Can't set value */ hid_t H5E_DUPCLASS_g = FAIL; /* Duplicate class name in parent class */ +hid_t H5E_SETDISALLOWED_g = FAIL; /* Disallowed operation */ /* Free space errors */ hid_t H5E_CANTMERGE_g = FAIL; /* Can't merge objects */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 802c94a..6881e48 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -339,6 +339,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Duplicate class name in parent class") HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_SETDISALLOWED_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Disallowed operation"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_SETDISALLOWED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* Free space errors */ assert(H5E_CANTMERGE_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index f6a20f2..967b248 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -155,9 +155,11 @@ H5_DLLVAR hid_t H5E_CANTRELEASE_g; /* Unable to release object */ #define H5E_CANTGET (H5OPEN H5E_CANTGET_g) #define H5E_CANTSET (H5OPEN H5E_CANTSET_g) #define H5E_DUPCLASS (H5OPEN H5E_DUPCLASS_g) +#define H5E_SETDISALLOWED (H5OPEN H5E_SETDISALLOWED_g) H5_DLLVAR hid_t H5E_CANTGET_g; /* Can't get value */ H5_DLLVAR hid_t H5E_CANTSET_g; /* Can't set value */ H5_DLLVAR hid_t H5E_DUPCLASS_g; /* Duplicate class name in parent class */ +H5_DLLVAR hid_t H5E_SETDISALLOWED_g; /* Disallowed operation */ /* Free space errors */ #define H5E_CANTMERGE (H5OPEN H5E_CANTMERGE_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 921b3b6..5edcd34 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -94,7 +94,8 @@ H5E_CANTRELEASE_g= /* Property list errors */ H5E_CANTGET_g= H5E_CANTSET_g= -H5E_DUPCLASS_g= +H5E_DUPCLASS_g= +H5E_SETDISALLOWED_g= /* Free space errors */ H5E_CANTMERGE_g= @@ -52,7 +52,7 @@ typedef struct H5F_olist_t { } H5F_olist_t; /* PRIVATE PROTOTYPES */ -static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); +static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr); static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf); @@ -363,11 +363,6 @@ done: * * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value to ssize_t to accommadate - * potential large number of objects. * *------------------------------------------------------------------------- */ @@ -375,18 +370,24 @@ ssize_t H5Fget_obj_count(hid_t file_id, unsigned types) { H5F_t *f = NULL; /* File to query */ - ssize_t ret_value; /* Return value */ + size_t obj_count = 0; /* Number of opened objects */ + ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("Zs", "iIu", file_id, types); + /* Check arguments */ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id") if(0 == (types & H5F_OBJ_ALL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type") - /* H5F_get_obj_count doesn't fail */ - ret_value = (ssize_t)H5F_get_obj_count(f, types, TRUE); + /* Perform the query */ + if(H5F_get_obj_count(f, types, TRUE, &obj_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") + + /* Set the return value */ + ret_value = (ssize_t)obj_count; done: FUNC_LEAVE_API(ret_value) @@ -399,31 +400,30 @@ done: * Purpose: Private function return the number of opened object IDs * (files, datasets, groups, datatypes) in the same file. * - * Return: Non-negative on success; can't fail. + * Return: SUCCEED on success, FAIL on failure. * * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value to size_t to accommadate - * potential large number of objects. - * *------------------------------------------------------------------------- */ -size_t -H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref) +herr_t +H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr) { - size_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); - /* H5F_get_objects doesn't fail */ - ret_value = H5F_get_objects(f, types, 0, NULL, app_ref); + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") +done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_get_obj_count() */ /*------------------------------------------------------------------------- @@ -448,19 +448,25 @@ ssize_t H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list) { H5F_t *f = NULL; /* File to query */ - ssize_t ret_value; /* Return value */ + size_t obj_id_count = 0; /* Number of open objects */ + ssize_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list); + /* Check arguments */ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id") if(0 == (types & H5F_OBJ_ALL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type") HDassert(oid_list); - /* H5F_get_objects doesn't fail */ - ret_value = (ssize_t)H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE); + /* Perform the query */ + if(H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_id_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed") + + /* Set the return value */ + ret_value = (ssize_t)obj_id_count; done: FUNC_LEAVE_API(ret_value) @@ -477,26 +483,25 @@ done: * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * Raymond Lu - * 24 September 2008 - * Changed the return value and MAX_OBJTS to size_t to accommadate - * potential large number of objects. - * *------------------------------------------------------------------------- */ -size_t -H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref) +herr_t +H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr) { - size_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(obj_id_count_ptr); - /* H5F_get_objects doesn't fail */ - ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref); + /* Perform the query */ + if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed") +done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_get_obj_ids() */ /*--------------------------------------------------------------------------- @@ -512,14 +517,18 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list * *--------------------------------------------------------------------------- */ -static size_t -H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref) +static herr_t +H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr) { size_t obj_id_count=0; /* Number of open IDs */ H5F_olist_t olist; /* Structure to hold search results */ - size_t ret_value; /* Return value */ + htri_t type_exists; /* Whether objects of a type are open */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(obj_id_count_ptr); /* Set up search information */ olist.obj_id_list = (max_index==0 ? NULL : obj_id_list); @@ -537,45 +546,50 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_ olist.file_info.ptr.shared = f ? f->shared : NULL; } /* end else */ - /* Search through file IDs to count the number, and put their - * IDs on the object list. H5I_search returns NULL if no object - * is found, so don't return failure in this function. */ + /* Iterate through file IDs to count the number, and put their + * IDs on the object list. */ if(types & H5F_OBJ_FILE) { olist.obj_type = H5I_FILE; - (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref); + if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)") } /* end if */ /* Search through dataset IDs to count number of datasets, and put their * IDs on the object list */ if(types & H5F_OBJ_DATASET) { olist.obj_type = H5I_DATASET; - (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)") + } /* end if */ /* Search through group IDs to count number of groups, and put their * IDs on the object list */ if(types & H5F_OBJ_GROUP) { olist.obj_type = H5I_GROUP; - (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)") + } /* end if */ /* Search through datatype IDs to count number of named datatypes, and put their * IDs on the object list */ if(types & H5F_OBJ_DATATYPE) { olist.obj_type = H5I_DATATYPE; - (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)") + } /* end if */ /* Search through attribute IDs to count number of attributes, and put their * IDs on the object list */ if(types & H5F_OBJ_ATTR) { olist.obj_type = H5I_ATTR; - (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref); - } + if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)") + } /* end if */ /* Set the number of objects currently open */ - ret_value = obj_id_count; + *obj_id_count_ptr = obj_id_count; +done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_objects() */ @@ -593,8 +607,6 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_ * Programmer: Raymond Lu * Wednesday, Dec 5, 2001 * - * Modification: - * *------------------------------------------------------------------------- */ static int @@ -626,8 +638,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) /* Check if we've filled up the array. Return TRUE only if * we have filled up the array. Otherwise return FALSE(RET_VALUE is - * preset to FALSE) because H5I_search needs the return value of FALSE - * to continue searching. */ + * preset to FALSE) because H5I_iterate needs the return value of + * FALSE to continue the iteration. */ if(olist->max_index>0 && olist->list_index>=olist->max_index) HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */ } @@ -691,8 +703,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) /* Check if we've filled up the array. Return TRUE only if * we have filled up the array. Otherwise return FALSE(RET_VALUE is - * preset to FALSE) because H5I_search needs the return value of FALSE - * to continue searching. */ + * preset to FALSE) because H5I_iterate needs the return value of + * FALSE to continue iterating. */ if(olist->max_index>0 && olist->list_index>=olist->max_index) HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */ } /* end if */ @@ -1785,8 +1797,6 @@ done: * Programmer: Quincey Koziol * Tuesday, July 19, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -1868,27 +1878,36 @@ H5F_try_close(H5F_t *f) if(f->nopen_objs > 0) { size_t obj_count; /* # of open objects */ hid_t objs[128]; /* Array of objects to close */ + herr_t result; /* Local result from obj ID query */ size_t u; /* Local index variable */ /* Get the list of IDs of open dataset, group, & attribute objects */ - while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) { + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0 ) { + /* Try to close all the open objects in this file */ for(u = 0; u < obj_count; u++) if(H5I_dec_ref(objs[u]) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)") /* Get the list of IDs of open named datatype objects */ /* (Do this separately from the dataset & attribute IDs, because * they could be using one of the named datatypes and then the * open named datatype ID will get closed twice) */ - while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) { + while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 + && obj_count != 0) { + /* Try to close all the open objects in this file */ for(u = 0; u < obj_count; u++) if(H5I_dec_ref(objs[u]) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object") } /* end while */ + if(result < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)") } /* end if */ } /* end if */ @@ -2551,6 +2570,139 @@ done: /*------------------------------------------------------------------------- + * Function: H5Fget_file_image + * + * Purpose: If a buffer is provided (via the buf_ptr argument) and is + * big enough (size in buf_len argument), load *buf_ptr with + * an image of the open file whose ID is provided in the + * file_id parameter, and return the number of bytes copied + * to the buffer. + * + * If the buffer exists, but is too small to contain an image + * of the indicated file, return a negative number. + * + * Finally, if no buffer is provided, return the size of the + * buffer needed. This value is simply the eoa of the target + * file. + * + * Note that any user block is skipped. + * + * Also note that the function may not be used on files + * opened with either the split/multi file driver or the + * family file driver. + * + * In the former case, the sparse address space makes the + * get file image operation impractical, due to the size of + * the image typically required. + * + * In the case of the family file driver, the problem is + * the driver message in the super block, which will prevent + * the image being opened with any driver other than the + * family file driver -- which negates the purpose of the + * operation. This can be fixed, but no resources for + * this now. + * + * Return: Success: Bytes copied / number of bytes needed. + * Failure: negative value + * + * Programmer: John Mainzer + * 11/15/11 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len) +{ + H5F_t *file; /* File object for file ID */ + H5FD_t *fd_ptr; /* file driver */ + haddr_t eoa; /* End of file address */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("Zs", "i*xz", file_id, buf_ptr, buf_len); + + /* Check args */ + if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + if(!file || !file->shared || !file->shared->lf) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer") + fd_ptr = file->shared->lf; + if(!fd_ptr->cls) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer") + + /* the address space used by the split and multi file drivers is not + * a good fit for this call. Since the plan is to depreciate these + * drivers anyway, don't bother to do a "force fit". + * + * The following clause tests for the multi file driver, and fails + * if the supplied file has the multi file driver as its top level + * file driver. However, this test will not work if there is some + * other file driver sitting on top of the multi file driver. + * + * I'm not sure if this is possible at present, but in all likelyhood, + * it will become possible in the future. On the other hand, we may + * remove the split/multi file drivers before then. + * + * I am leaving this solution in for now, but we should review it, + * and improve the solution if necessary. + * + * JRM -- 11/11/22 + */ + if(HDstrcmp(fd_ptr->cls->name, "multi") == 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.") + + /* While the family file driver is conceptually fully compatible + * with the get file image operation, it sets a file driver message + * in the super block that prevents the image being opened with any + * driver other than the family file driver. Needless to say, this + * rather defeats the purpose of the get file image operation. + * + * While this problem is quire solvable, the required time and + * resources are lacking at present. Hence, for now, we don't + * allow the get file image operation to be perfomed on files + * opened with the family file driver. + * + * Observe that the following test only looks at the top level + * driver, and fails if there is some other driver sitting on to + * of the family file driver. + * + * I don't think this can happen at present, but that may change + * in the future. + * JRM -- 12/21/11 + */ + if(HDstrcmp(fd_ptr->cls->name, "family") == 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.") + + + /* Go get the actual file size */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") + + /* set ret_value = to eoa -- will overwrite this if appropriate */ + ret_value = (ssize_t)eoa; + + /* test to see if a buffer was provided -- if not, we are done */ + if(buf_ptr != NULL) { + size_t space_needed; /* size of file image */ + + /* Check for buffer too small */ + if((haddr_t)buf_len < eoa) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small") + + space_needed = (size_t)eoa; + + /* read in the file image */ + /* (Note compensation for base address addition in internal routine) */ + if(H5FD_read(fd_ptr, H5AC_ind_dxpl_id, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Fget_file_image() */ + + +/*------------------------------------------------------------------------- * Function: H5Fget_mdc_config * * Purpose: Retrieves the current automatic cache resize configuration @@ -70,6 +70,10 @@ static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size, static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), void *pl); static herr_t H5FD_free_cls(H5FD_class_t *cls); +static herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl); +static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl); +static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/); +static int H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/); /*********************/ /* Package Variables */ @@ -750,17 +754,15 @@ done: * Programmer: Robb Matzke * Tuesday, August 3, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl) { H5FD_class_t *driver; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* Check args */ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id))) @@ -871,17 +873,15 @@ done: * Programmer: Robb Matzke * Tuesday, August 3, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl, void **copied_dxpl) { H5FD_class_t *driver; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT /* Check args */ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id))) @@ -1039,6 +1039,8 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) H5FD_t *file = NULL; /* VFD file struct */ hid_t driver_id = -1; /* VFD ID */ H5P_genplist_t *plist; /* Property list pointer */ + unsigned long driver_flags = 0; /* File-inspecific driver feature flags */ + H5FD_file_image_info_t file_image_info; /* Initial file image */ H5FD_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -1061,6 +1063,19 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) if(NULL == driver->open) HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method") + /* Query driver flag */ + H5FD_driver_query(driver, &driver_flags); + + /* Get initial file image info */ + if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file image info") + + /* If an image is provided, make sure the driver supports this feature */ + HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || + ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + if((file_image_info.buffer != NULL) && !(driver_flags & H5FD_FEAT_ALLOW_FILE_IMAGE)) + HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file image set, but not supported.") + /* Dispatch to file driver */ if(HADDR_UNDEF == maxaddr) maxaddr = driver->maxaddr; @@ -1318,19 +1333,17 @@ done: * Programmer: Quincey Koziol * Friday, August 25, 2000 * - * Modifications: - * *------------------------------------------------------------------------- */ -int +static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/) { - int ret_value=0; + int ret_value = 0; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT - assert(f); - assert(flags); + HDassert(f); + HDassert(flags); /* Check for query driver and call it */ if(f->cls->query) @@ -1340,7 +1353,44 @@ H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_query() */ + + +/*------------------------------------------------------------------------- +* Function: H5FD_driver_query +* +* Purpose: Similar to H5FD_query(), but intended for cases when we don't +* have a file available (e.g. before one is opened). Since we +* can't use the file to get the driver, the driver is passed in +* as a parameter. +* +* Return: Success: non-negative +* Failure: negative +* +* Programmer: Jacob Gruber +* Wednesday, August 17, 2011 +* +*------------------------------------------------------------------------- +*/ +static int +H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/) +{ + int ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + HDassert(driver); + HDassert(flags); + + /* Check for the driver to query and then query it */ + if(driver->query) + ret_value = (driver->query)(NULL, flags); + else + *flags = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_driver_query() */ /*------------------------------------------------------------------------- diff --git a/src/H5FDcore.c b/src/H5FDcore.c index ff99cab..1fef36c 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -101,6 +101,7 @@ typedef struct H5FD_core_t { HANDLE hFile; /* Native windows file handle */ #endif /* H5_HAVE_WIN32_API */ hbool_t dirty; /*changes not saved? */ + H5FD_file_image_callbacks_t fi_callbacks; /* file image callbacks */ } H5FD_core_t; /* Driver-specific file access properties */ @@ -412,6 +413,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, #endif h5_stat_t sb; int fd=-1; + H5FD_file_image_info_t file_image_info; H5FD_t *ret_value; FUNC_ENTER_NOAPI_NOINIT @@ -434,10 +436,32 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, if(H5F_ACC_CREAT & flags) o_flags |= O_CREAT; if(H5F_ACC_EXCL & flags) o_flags |= O_EXCL; + /* Retrieve initial file image info */ + if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial file image info") + + /* If the file image exists and this is an open, make sure the file doesn't exist */ + HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || + ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) { + if(HDopen(name, o_flags, 0666) >= 0) + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists") + + /* If backing store is requested, create and stat the file + * Note: We are forcing the O_CREAT flag here, even though this is + * technically an open. + */ + if(fa->backing_store) { + if((fd = HDopen(name, o_flags | O_CREAT, 0666)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file") + if(HDfstat(fd, &sb) < 0) + HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file") + } /* end if */ + } /* end if */ /* Open backing store, and get stat() from file. The only case that backing * store is off is when the backing_store flag is off and H5F_ACC_CREAT is * on. */ - if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { + else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { if(fa && (fd = HDopen(name, o_flags, 0666)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") if(HDfstat(fd, &sb) < 0) @@ -460,6 +484,9 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, /* If save data in backing store. */ file->backing_store = fa->backing_store; + /* Save file image callbacks */ + file->fi_callbacks = file_image_info.callbacks; + if(fd >= 0) { /* Retrieve information for determining uniqueness of file */ #ifdef H5_HAVE_WIN32_API @@ -491,51 +518,70 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, size_t size; /* Retrieve file size */ - size = (size_t)sb.st_size; + if(file_image_info.buffer && file_image_info.size > 0) + size = file_image_info.size; + else + size = (size_t)sb.st_size; /* Check if we should allocate the memory buffer and read in existing data */ if(size) { - /* Allocate memory for the file's data */ - if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory block") + /* Allocate memory for the file's data, using the file image callback if available. */ + if(file->fi_callbacks.image_malloc) { + if(NULL == (file->mem = (unsigned char*)file->fi_callbacks.image_malloc(size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "image malloc callback failed") + } /* end if */ + else { + if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate memory block") + } /* end else */ /* Set up data structures */ file->eof = size; - /* Read in existing data, being careful of interrupted system calls, - * partial results, and the end of the file. - */ - while(size > 0) { - - h5_core_io_t bytes_in = 0; /* # of bytes to read */ - h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */ - - /* Trying to read more bytes than the return type can handle is - * undefined behavior in POSIX. - */ - if(size > H5_CORE_MAX_IO_BYTES_g) - bytes_in = H5_CORE_MAX_IO_BYTES_g; - else - bytes_in = (h5_core_io_t)size; - - do { - bytes_read = HDread(file->fd, file->mem, bytes_in); - } while(-1 == bytes_read && EINTR == errno); - - if(-1 == bytes_read) { /* error */ - int myerrno = errno; - time_t mytime = HDtime(NULL); - HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); - - HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset); + /* If there is an initial file image, copy it, using the callback if possible */ + if(file_image_info.buffer && file_image_info.size > 0) { + if(file->fi_callbacks.image_memcpy) { + if(file->mem != file->fi_callbacks.image_memcpy(file->mem, file_image_info.buffer, size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata)) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed") } /* end if */ - - HDassert(bytes_read >= 0); - HDassert((size_t)bytes_read <= size); - - size -= (size_t)bytes_read; - - } /* end while */ + else + HDmemcpy(file->mem, file_image_info.buffer, size); + } /* end if */ + /* Read in existing data from the file if there is no image */ + else { + /* Read in existing data, being careful of interrupted system calls, + * partial results, and the end of the file. + */ + while(size > 0) { + h5_core_io_t bytes_in = 0; /* # of bytes to read */ + h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */ + + /* Trying to read more bytes than the return type can handle is + * undefined behavior in POSIX. + */ + if(size > H5_CORE_MAX_IO_BYTES_g) + bytes_in = H5_CORE_MAX_IO_BYTES_g; + else + bytes_in = (h5_core_io_t)size; + + do { + bytes_read = HDread(file->fd, file->mem, bytes_in); + } while(-1 == bytes_read && EINTR == errno); + + if(-1 == bytes_read) { /* error */ + int myerrno = errno; + time_t mytime = HDtime(NULL); + HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); + + HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset); + } /* end if */ + + HDassert(bytes_read >= 0); + HDassert((size_t)bytes_read <= size); + + size -= (size_t)bytes_read; + } /* end while */ + } /* end else */ } /* end if */ } /* end if */ @@ -578,8 +624,15 @@ H5FD_core_close(H5FD_t *_file) HDclose(file->fd); if(file->name) H5MM_xfree(file->name); - if(file->mem) - H5MM_xfree(file->mem); + if(file->mem) { + /* Use image callback if available */ + if(file->fi_callbacks.image_free) { + if(file->fi_callbacks.image_free(file->mem, H5FD_FILE_IMAGE_OP_FILE_CLOSE, file->fi_callbacks.udata) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(file->mem); + } /* end if */ HDmemset(file, 0, sizeof(H5FD_core_t)); H5MM_xfree(file); @@ -700,9 +753,11 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ + *flags |= H5FD_FEAT_ALLOW_FILE_IMAGE; /* OK to use file image feature with this VFD */ + *flags |= H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS; /* OK to use file image callbacks with this VFD */ /* If the backing store is open, a POSIX file handle is available */ - if(file->fd >= 0 && file->backing_store) + if(file && file->fd >= 0 && file->backing_store) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ } /* end if */ @@ -976,9 +1031,16 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had if((addr + size) % file->increment) new_eof += file->increment; - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + /* (Re)allocate memory for the file buffer, using callbacks if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes with callback", (unsigned long long)new_eof) + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + } /* end else */ + #ifdef H5_CLEAR_MEMORY HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ @@ -989,6 +1051,8 @@ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); /* Write from BUF to memory */ HDmemcpy(file->mem + addr, buf, size); + + /* Mark memory buffer as modified */ file->dirty = TRUE; done: @@ -1075,6 +1139,28 @@ done: * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. * + * Addendum -- 12/2/11 + * For file images opened with the core file driver, it is + * necessary that we avoid reallocating the core file driver's + * buffer uneccessarily. + * + * To this end, I have made the following functional changes + * to this function. + * + * If we are closing, and there is no backing store, this + * function becomes a no-op. + * + * If we are closing, and there is backing store, we set the + * eof to equal the eoa, and truncate the backing store to + * the new eof + * + * If we are not closing, we realloc the buffer to size equal + * to the smallest multiple of the allocation increment that + * equals or exceeds the eoa and set the eof accordingly. + * Note that we no longer truncate the backing store to the + * new eof if applicable. + * -- JRM + * * Return: Success: Non-negative * Failure: Negative * @@ -1085,7 +1171,7 @@ done: */ /* ARGSUSED */ static herr_t -H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) +H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) { H5FD_core_t *file = (H5FD_core_t*)_file; size_t new_eof; /* New size of memory buffer */ @@ -1095,68 +1181,83 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) HDassert(file); - /* Determine new size of memory buffer */ - H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); - if(file->eoa % file->increment) - new_eof += file->increment; - - /* Extend the file to make sure it's large enough */ - if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { - unsigned char *x; /* Pointer to new buffer for file data */ + /* if we are closing and not using backing store, do nothing */ + if(!closing || file->backing_store) { + if(closing) /* set eof to eoa */ + new_eof = file->eoa; + else { /* set eof to smallest multiple of increment that exceeds eoa */ + /* Determine new size of memory buffer */ + H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); + if(file->eoa % file->increment) + new_eof += file->increment; + } /* end else */ + + /* Extend the file to make sure it's large enough */ + if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { + unsigned char *x; /* Pointer to new buffer for file data */ + + /* (Re)allocate memory for the file buffer, using callback if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block with callback") + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block") + } /* end else */ - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") #ifdef H5_CLEAR_MEMORY -if(file->eof < new_eof) - HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); + if(file->eof < new_eof) + HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ - file->mem = x; + file->mem = x; - /* Update backing store, if using it */ - if(file->fd >= 0 && file->backing_store) { + /* Update backing store, if using it and if closing */ + if(closing && (file->fd >= 0) && file->backing_store) { #ifdef H5_HAVE_WIN32_API - LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */ - DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer() - * Only used as an error code here. - */ - DWORD dwError; /* DWORD error code from GetLastError() */ - BOOL bError; /* Boolean error flag */ - - /* Windows uses this odd QuadPart union for 32/64-bit portability */ - li.QuadPart = (__int64)file->eoa; - - /* Extend the file to make sure it's large enough. - * - * Since INVALID_SET_FILE_POINTER can technically be a valid return value - * from SetFilePointer(), we also need to check GetLastError(). - */ - dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN); - if(INVALID_SET_FILE_POINTER == dwPtrLow) { - dwError = GetLastError(); - if(dwError != NO_ERROR ) - HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer") - } - - bError = SetEndOfFile(file->hFile); - if(0 == bError) - HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") + LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */ + DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer() + * Only used as an error code here. + */ + DWORD dwError; /* DWORD error code from GetLastError() */ + BOOL bError; /* Boolean error flag */ + + /* Windows uses this odd QuadPart union for 32/64-bit portability */ + li.QuadPart = (__int64)file->eoa; + + /* Extend the file to make sure it's large enough. + * + * Since INVALID_SET_FILE_POINTER can technically be a valid return value + * from SetFilePointer(), we also need to check GetLastError(). + */ + dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN); + if(INVALID_SET_FILE_POINTER == dwPtrLow) { + dwError = GetLastError(); + if(dwError != NO_ERROR ) + HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer") + } + + bError = SetEndOfFile(file->hFile); + if(0 == bError) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #else /* H5_HAVE_WIN32_API */ #ifdef H5_VMS - /* Reset seek offset to the beginning of the file, so that the file isn't - * re-extended later. This may happen on Open VMS. */ - if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + /* Reset seek offset to the beginning of the file, so that the file isn't + * re-extended later. This may happen on Open VMS. */ + if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") #endif /* H5_VMS */ - if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") + if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #endif /* H5_HAVE_WIN32_API */ - } /* end if */ + } /* end if */ - /* Update the eof value */ - file->eof = new_eof; - } /* end if */ + /* Update the eof value */ + file->eof = new_eof; + } /* end if */ + } /* end if(file->eof < file->eoa) */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_core_truncate() */ + diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 17683ce..6f6d757 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -995,7 +995,7 @@ H5FD_family_query(const H5FD_t * _file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ /* Check for flags that are set by h5repart */ - if(file->repart_members) + if(file && file->repart_members) *flags |= H5FD_FEAT_DIRTY_SBLK_LOAD; /* Mark the superblock dirty when it is loaded (so the family member sizes are rewritten) */ } /* end if */ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index cb5ce3c..0b5c677 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -918,7 +918,7 @@ H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ /* Check for flags that are set by h5repart */ - if(file->fam_to_sec2) + if(file && file->fam_to_sec2) *flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */ } /* end if */ diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 4f7d059..9c19562 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -52,6 +52,29 @@ typedef enum { } H5FD_file_op_t; +/* Define structure to hold initial file image and other relevant information */ +typedef struct { + void *buffer; + size_t size; + H5FD_file_image_callbacks_t callbacks; +} H5FD_file_image_info_t; + +/* Define default file image info */ +#define H5FD_DEFAULT_FILE_IMAGE_INFO { \ + /* file image buffer */ NULL, \ + /* buffer size */ 0, \ + { /* Callbacks */ \ + /* image_malloc */ NULL, \ + /* image_memcpy */ NULL, \ + /* image_realloc */ NULL, \ + /* image_free */ NULL, \ + /* udata_copy */ NULL, \ + /* udata_free */ NULL, \ + /* udata */ NULL, \ + } \ +} + + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -72,17 +95,14 @@ H5_DLL herr_t H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf); H5_DLL herr_t H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf); H5_DLL void *H5FD_fapl_get(H5FD_t *file); H5_DLL herr_t H5FD_fapl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info); -H5_DLL herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl); H5_DLL herr_t H5FD_fapl_close(hid_t driver_id, void *fapl); H5_DLL herr_t H5FD_dxpl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info); -H5_DLL herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl); H5_DLL herr_t H5FD_dxpl_close(hid_t driver_id, void *dxpl); H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref); H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); H5_DLL herr_t H5FD_close(H5FD_t *file); H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2); -H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/); H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f, hsize_t size, haddr_t *align_addr, hsize_t *align_size); H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, struct H5F_t *f, diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index f495e2d..ab19c68 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -222,6 +222,19 @@ typedef enum H5F_mem_t H5FD_mem_t; * instead of the default H5D_ALLOC_TIME_LATE */ #define H5FD_FEAT_ALLOCATE_EARLY 0x00000200 + /* + * Defining the H5FD_FEAT_ALLOW_FILE_IMAGE for a VFL driver means that + * the driver is able to use a file image in the fapl as the initial + * contents of a file. + */ +#define H5FD_FEAT_ALLOW_FILE_IMAGE 0x00000400 + /* + * Defining the H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS for a VFL driver + * means that the driver is able to use callbacks to make a copy of the + * image to store in memory. + */ +#define H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS 0x00000800 + /* Forward declaration */ typedef struct H5FD_t H5FD_t; @@ -291,6 +304,33 @@ struct H5FD_t { hsize_t alignment; /* Allocation alignment */ }; +/* Define enum for the source of file image callbacks */ +typedef enum { + H5FD_FILE_IMAGE_OP_NO_OP, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, + H5FD_FILE_IMAGE_OP_FILE_OPEN, + H5FD_FILE_IMAGE_OP_FILE_RESIZE, + H5FD_FILE_IMAGE_OP_FILE_CLOSE, +} H5FD_file_image_op_t; + +/* Define structure to hold file image callbacks */ +typedef struct { + void *(*image_malloc)(size_t size, H5FD_file_image_op_t file_image_op, + void *udata); + void *(*image_memcpy)(void *dest, const void *src, size_t size, + H5FD_file_image_op_t file_image_op, void *udata); + void *(*image_realloc)(void *ptr, size_t size, + H5FD_file_image_op_t file_image_op, void *udata); + herr_t (*image_free)(void *ptr, H5FD_file_image_op_t file_image_op, + void *udata); + void *(*udata_copy)(void *udata); + herr_t (*udata_free)(void *udata); + void *udata; +} H5FD_file_image_callbacks_t; + #ifdef __cplusplus extern "C" { #endif diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index 6d4a76a..4201e07 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -560,7 +560,7 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ /* Check for flags that are set by h5repart */ - if(file->fam_to_sec2) + if(file && file->fam_to_sec2) *flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */ } /* end if */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 868674f..40e075b 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -417,6 +417,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t; #define H5F_ACS_LATEST_FORMAT_NAME "latest_format" /* 'Use latest format version' flag */ #define H5F_ACS_WANT_POSIX_FD_NAME "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address */ #define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */ +#define H5F_ACS_FILE_IMAGE_INFO_NAME "file_image_info" /* struct containing initial file image and callback info */ /* ======================== File Mount properties ====================*/ #define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */ @@ -528,8 +529,8 @@ H5_DLL H5F_t *H5F_get_parent(const H5F_t *f); H5_DLL unsigned H5F_get_nmounts(const H5F_t *f); H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); -H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref); -H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); +H5_DLL herr_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr); +H5_DLL herr_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr); /* Functions than retrieve values set/cached from the superblock/FCPL */ H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index d88538b..f32b3e0 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -192,6 +192,7 @@ H5_DLL herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist); H5_DLL herr_t H5Funmount(hid_t loc, const char *name); H5_DLL hssize_t H5Fget_freespace(hid_t file_id); H5_DLL herr_t H5Fget_filesize(hid_t file_id, hsize_t *size); +H5_DLL ssize_t H5Fget_file_image(hid_t file_id, void * buf_ptr, size_t buf_len); H5_DLL herr_t H5Fget_mdc_config(hid_t file_id, H5AC_cache_config_t * config_ptr); H5_DLL herr_t H5Fset_mdc_config(hid_t file_id, diff --git a/src/H5Gname.c b/src/H5Gname.c index 62875dc..576d866 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -782,7 +782,7 @@ done: /*------------------------------------------------------------------------- * Function: H5G_name_replace_cb * - * Purpose: H5I_search callback function to replace group entry names + * Purpose: H5I_iterate callback function to replace group entry names * * Return: Success: 0, Failure: -1 * @@ -1166,15 +1166,18 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file, /* Search through group IDs */ if(search_group) - H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_GROUP, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over groups") /* Search through dataset IDs */ if(search_dataset) - H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_DATASET, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datasets") /* Search through datatype IDs */ if(search_datatype) - H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE); + if(H5I_iterate(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over datatypes") } /* end if */ } /* end if */ @@ -108,6 +108,11 @@ typedef struct { H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */ } H5I_id_type_t; +typedef struct { + H5I_search_func_t app_cb; /* Application's callback routine */ + void *app_key; /* Application's "key" (user data) */ + void *ret_obj; /* Object to return */ +} H5I_search_ud_t; /*-------------------- Locally scoped variables -----------------------------*/ @@ -127,6 +132,7 @@ H5FL_DEFINE_STATIC(H5I_id_info_t); /*--------------------- Local function prototypes ---------------------------*/ static H5I_id_info_t *H5I_find_id(hid_t id); +static int H5I_search_cb(void *obj, hid_t id, void *udata); #ifdef H5I_DEBUG_OUTPUT static herr_t H5I_debug(H5I_type_t type); #endif /* H5I_DEBUG_OUTPUT */ @@ -1905,6 +1911,40 @@ done: /*------------------------------------------------------------------------- + * Function: H5I_search_cb + * + * Purpose: Callback routine for H5Isearch, when it calls H5I_iterate. + * Calls "user" callback search function, and then sets return + * value, based on the result of that callback. + * + * Return: Success: The first object in the type for which FUNC + * returns non-zero. NULL if FUNC returned zero + * for every object in the type. + * Failure: NULL + * + * Programmer: Quincey Koziol + * Friday, March 30, 2012 + * + *------------------------------------------------------------------------- + */ +static int +H5I_search_cb(void *obj, hid_t id, void *_udata) +{ + H5I_search_ud_t *udata = (H5I_search_ud_t *)_udata; /* User data for callback */ + int ret_value; /* Callback return value */ + + FUNC_ENTER_NOAPI_NOINIT + + ret_value = (*udata->app_cb)(obj, id, udata->app_key); + if(ret_value > 0) + udata->ret_obj = obj; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_search_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5Isearch * * Purpose: Apply function FUNC to each member of type TYPE and return a @@ -1931,14 +1971,27 @@ done: void * H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key) { - void * ret_value; /* Return value */ + H5I_search_ud_t udata; /* Context for iteration */ + void *ret_value; /* Return value */ FUNC_ENTER_API(NULL) + /* Check arguments */ if(H5I_IS_LIB_TYPE(type)) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type") - ret_value = H5I_search(type, func, key, TRUE); + /* Set up udata struct */ + udata.app_cb = func; + udata.app_key = key; + udata.ret_obj = NULL; + + /* Note that H5I_iterate returns an error code. We ignore it + * here, as we can't do anything with it without revising the API. + */ + H5I_iterate(type, H5I_search_cb, &udata, TRUE); + + /* Set return value */ + ret_value = udata.ret_obj; done: FUNC_LEAVE_API(ret_value) @@ -1946,62 +1999,71 @@ done: /*------------------------------------------------------------------------- - * Function: H5I_search + * Function: H5I_iterate * - * Purpose: Apply function FUNC to each member of type TYPE and return a - * pointer to the first object for which FUNC returns non-zero. - * The FUNC should take a pointer to the object and the KEY as - * arguments and return non-zero to terminate the search (zero - * to continue). + * Purpose: Apply function FUNC to each member of type TYPE (with + * non-zero application reference count if app_ref is TRUE). + * Stop if FUNC returns a non zero value (i.e. anything + * other than H5_ITER_CONT). * - * Limitation: Currently there is no way to start searching from where a - * previous search left off. + * If FUNC returns a positive value (i.e. H5_ITER_STOP), + * return SUCCEED. * - * Return: Success: The first object in the type for which FUNC - * returns non-zero. NULL if FUNC returned zero - * for every object in the type. - * Failure: NULL + * If FUNC returns a negative value (i.e. H5_ITER_ERROR), + * return FAIL. + * + * The FUNC should take a pointer to the object and the + * udata as arguments and return non-zero to terminate + * siteration, and zero to continue. * - * Programmer: Robb Matzke - * Friday, February 19, 1999 + * Limitation: Currently there is no way to start the iteration from + * where a previous iteration left off. + * + * Return: Success: SUCCEED + * Failure: FAIL * - * Modifications: Neil Fortner - * Wednesday, October 1, 2008 - * Added app_ref parameter. When set to TRUE, the function will only - * operate on ids that have a nonzero application reference count. + * Programmer: John Mainzer + * Monday, December 6, 2011 * *------------------------------------------------------------------------- */ -void * -H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref) +herr_t +H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref) { - H5I_id_type_t *type_ptr; /*ptr to the type */ - void *ret_value = NULL; /*return value */ + H5I_id_type_t *type_ptr; /*ptr to the type */ + herr_t ret_value = SUCCEED; /*return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_NOAPI(FAIL) /* Check arguments */ if(type <= H5I_BADID || type >= H5I_next_type) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number") + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number") type_ptr = H5I_id_type_list_g[type]; - if(type_ptr == NULL || type_ptr->count <= 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type") - /* Only iterate through hash table if there are IDs in group */ - if(type_ptr->ids > 0) { - H5I_id_info_t *id_ptr; /*ptr to the new ID */ - H5I_id_info_t *next_id; /*ptr to the next ID */ - unsigned i; /*counter */ + /* Only iterate through hash table if it is initialized and there are IDs in group */ + if(type_ptr && type_ptr->count > 0 && type_ptr->ids > 0) { + unsigned u; /* Counter */ /* Start at the beginning of the array */ - for(i = 0; i < type_ptr->hash_size; i++) { - id_ptr = type_ptr->id_list[i]; + for(u = 0; u < type_ptr->hash_size; u++) { + H5I_id_info_t *id_ptr; /* Ptr to the new ID */ + + id_ptr = type_ptr->id_list[u]; while(id_ptr) { - next_id = id_ptr->next; /* Protect against ID being deleted in callback */ - /* (Casting away const OK -QAK) */ - if((!app_ref || id_ptr->app_count) && (*func)((void *)id_ptr->obj_ptr, id_ptr->id, key)) - /* (Casting away const OK -QAK) */ - HGOTO_DONE((void *)id_ptr->obj_ptr); /*found the item*/ + H5I_id_info_t *next_id; /* Ptr to the next ID */ + + /* Protect against ID being deleted in callback */ + next_id = id_ptr->next; + if((!app_ref) || (id_ptr->app_count > 0)) { + herr_t cb_ret_val; /* Callback return value */ + + /* (Casting away const OK) */ + cb_ret_val = (*func)((void *)id_ptr->obj_ptr, id_ptr->id, udata); + if(cb_ret_val > 0) + HGOTO_DONE(SUCCEED) /* terminate iteration early */ + else if(cb_ret_val < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "func failed") + } /* end if */ id_ptr = next_id; } /* end while */ } /* end for */ @@ -2009,7 +2071,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5I_search() */ +} /* end H5I_iterate() */ /*------------------------------------------------------------------------- diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 98423df..bc0ef41 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -62,7 +62,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id); H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref); H5_DLL void *H5I_remove(hid_t id); H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type); -H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref); +H5_DLL herr_t H5I_iterate(H5I_type_t type, H5I_search_func_t func, void *udata, hbool_t app_ref); H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref); H5_DLL int H5I_dec_ref(hid_t id); diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 055fb69..30ec732 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -703,18 +703,23 @@ H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_t HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number") /* Count all opened attributes */ - num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE); + if(H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE, &num_open_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't count opened attributes") /* Find out whether the attribute has been opened */ if(num_open_attr) { + size_t check_num_attr; /* Number of open attribute IDs */ size_t u; /* Local index variable */ /* Allocate space for the attribute ID list */ if(NULL == (attr_id_list = (hid_t *)H5MM_malloc(num_open_attr * sizeof(hid_t)))) - HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "unable to allocate memory for attribute ID list") + HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "unable to allocate memory for attribute ID list") /* Retrieve the IDs of all opened attributes */ - H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE); + if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE, &check_num_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get IDs of opened attributes") + if(check_num_attr != num_open_attr) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "open attribute count mismatch") /* Iterate over the attributes */ for(u = 0; u < num_open_attr; u++) { diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index c3371c9..7f72c85 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -40,6 +40,7 @@ #include "H5Fprivate.h" /* Files */ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory Management */ #include "H5Ppkg.h" /* Property lists */ /* Includes needed to set as default file driver */ @@ -122,6 +123,12 @@ /* Definition for external file cache size */ #define H5F_ACS_EFC_SIZE_SIZE sizeof(unsigned) #define H5F_ACS_EFC_SIZE_DEF 0 +/* Definition of pointer to initial file image info */ +#define H5F_ACS_FILE_IMAGE_INFO_SIZE sizeof(H5FD_file_image_info_t) +#define H5F_ACS_FILE_IMAGE_INFO_DEF H5FD_DEFAULT_FILE_IMAGE_INFO +#define H5F_ACS_FILE_IMAGE_INFO_DEL H5P_file_image_info_del +#define H5F_ACS_FILE_IMAGE_INFO_COPY H5P_file_image_info_copy +#define H5F_ACS_FILE_IMAGE_INFO_CLOSE H5P_file_image_info_close /******************/ @@ -149,6 +156,10 @@ static herr_t H5P_facc_reg_prop(H5P_genclass_t *pclass); static herr_t H5P_facc_create(hid_t fapl_id, void *copy_data); static herr_t H5P_facc_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data); +/* File image info property callbacks */ +static herr_t H5P_file_image_info_del(hid_t prop_id, const char *name, size_t size, void *value); +static herr_t H5P_file_image_info_copy(const char *name, size_t size, void *value); +static herr_t H5P_file_image_info_close(const char *name, size_t size, void *value); /*********************/ /* Package Variables */ @@ -215,6 +226,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) hbool_t latest_format = H5F_ACS_LATEST_FORMAT_DEF; /* Default setting for "use the latest version of the format" flag */ hbool_t want_posix_fd = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */ unsigned efc_size = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */ + H5FD_file_image_info_t file_image_info = H5F_ACS_FILE_IMAGE_INFO_DEF; /* Default file image info and callbacks */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -300,6 +312,10 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass) if(H5P_register_real(pclass, H5F_ACS_EFC_SIZE_NAME, H5F_ACS_EFC_SIZE_SIZE, &efc_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the initial file image info */ + if(H5P_register_real(pclass, H5F_ACS_FILE_IMAGE_INFO_NAME, H5F_ACS_FILE_IMAGE_INFO_SIZE, &file_image_info, NULL, NULL, NULL, H5F_ACS_FILE_IMAGE_INFO_DEL, H5F_ACS_FILE_IMAGE_INFO_COPY, NULL, H5F_ACS_FILE_IMAGE_INFO_CLOSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_facc_reg_prop() */ @@ -2101,3 +2117,484 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_elink_file_cache_size() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_file_image + * + * Purpose: Sets the initial file image. Some file drivers can initialize + * the starting data in a file from a buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t image_info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*xz", fapl_id, buf_ptr, buf_len); + + /* validate parameters */ + if(!(((buf_ptr == NULL) && (buf_len == 0)) || ((buf_ptr != NULL) && (buf_len > 0)))) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "inconsistant buf_ptr and buf_len"); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old image info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image pointer") + + /* Release previous buffer, if it exists */ + if(image_info.buffer != NULL) { + if(image_info.callbacks.image_free) { + if(SUCCEED != image_info.callbacks.image_free(image_info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(image_info.buffer); + } /* end if */ + + /* Update struct */ + if(buf_ptr) { + /* Allocate memory */ + if(image_info.callbacks.image_malloc) { + if(NULL == (image_info.buffer = image_info.callbacks.image_malloc(buf_len, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, image_info.callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else + if(NULL == (image_info.buffer = H5MM_malloc(buf_len))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") + + /* Copy data */ + if(image_info.callbacks.image_memcpy) { + if(image_info.buffer != image_info.callbacks.image_memcpy(image_info.buffer, + buf_ptr, buf_len, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_SET, + image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(image_info.buffer, buf_ptr, buf_len); + } /* end if */ + else + image_info.buffer = NULL; + + image_info.size = buf_len; + + /* Set values */ + if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_file_image() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_file_image + * + * Purpose: If the file image exists and buf_ptr_ptr is not NULL, + * allocate a buffer of the correct size, copy the image into + * the new buffer, and return the buffer to the caller in + * *buf_ptr_ptr. Do this using the file image callbacks + * if defined. + * + * NB: It is the responsibility of the caller to free the + * buffer whose address is returned in *buf_ptr_ptr. Do + * this using free if the file image callbacks are not + * defined, or with whatever method is appropriate if + * the callbacks are defined. + * + * If buf_ptr_ptr is not NULL, and no image exists, set + * *buf_ptr_ptr to NULL. + * + * If buf_len_ptr is not NULL, set *buf_len_ptr equal + * to the length of the file image if it exists, and + * to 0 if it does not. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t image_info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i**x*z", fapl_id, buf_ptr_ptr, buf_len_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get values */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info") + + /* verify file image field consistancy */ + HDassert(((image_info.buffer != NULL) && (image_info.size > 0)) || + ((image_info.buffer == NULL) && (image_info.size == 0))); + + /* Set output size */ + if(buf_len_ptr != NULL) + *buf_len_ptr = image_info.size; + + /* Duplicate the image if desired, using callbacks if available */ + if(buf_ptr_ptr != NULL) { + void * copy_ptr = NULL; /* Copy of memory image */ + + if(image_info.buffer != NULL) { + /* Allocate memory */ + if(image_info.callbacks.image_malloc) { + if(NULL == (copy_ptr = image_info.callbacks.image_malloc(image_info.size, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, image_info.callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else + if(NULL == (copy_ptr = H5MM_malloc(image_info.size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate copy") + + /* Copy data */ + if(image_info.callbacks.image_memcpy) { + if(copy_ptr != image_info.callbacks.image_memcpy(copy_ptr, image_info.buffer, + image_info.size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_GET, + image_info.callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(copy_ptr, image_info.buffer, image_info.size); + } /* end if */ + + *buf_ptr_ptr = copy_ptr; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_file_image */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_file_image_callbacks + * + * Purpose: Sets the callbacks for file images. Some file drivers allow + * the use of user-defined callbacks for allocating, freeing and + * copying the drivers internal buffer, potentially allowing a + * clever user to do optimizations such as avoiding large mallocs + * and memcpys or to perform detailed logging. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*x", fapl_id, callbacks_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get old file image info") + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + /* Make sure a file image hasn't already been set */ + if(info.buffer != NULL || info.size > 0) + HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "setting callbacks when an image is already set is forbidden. It could cause memory leaks.") + + /* verify that callbacks_ptr is not NULL */ + if(NULL == callbacks_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr") + + /* Make sure udata callbacks are going to be set if udata is going to be set */ + if(callbacks_ptr->udata) + if(callbacks_ptr->udata_copy == NULL || callbacks_ptr->udata_free == NULL) + HGOTO_ERROR(H5E_PLIST, H5E_SETDISALLOWED, FAIL, "udata callbacks must be set if udata is set") + + /* Release old udata if it exists */ + if(info.callbacks.udata != NULL) { + HDassert(info.callbacks.udata_free); + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + + /* Update struct */ + info.callbacks = *callbacks_ptr; + + if(callbacks_ptr->udata) { + HDassert(callbacks_ptr->udata_copy); + HDassert(callbacks_ptr->udata_free); + if((info.callbacks.udata = callbacks_ptr->udata_copy(callbacks_ptr->udata)) == NULL) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy the suppplied udata") + } /* end if */ + + /* Set values */ + if(H5P_set(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file image info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_file_image_callbacks() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_file_image_callbacks + * + * Purpose: Sets the callbacks for file images. Some file drivers allow + * the use of user-defined callbacks for allocating, freeing and + * copying the drivers internal buffer, potentially allowing a + * clever user to do optimizations such as avoiding large mallocs + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_file_image_callbacks(hid_t fapl_id, H5FD_file_image_callbacks_t *callbacks_ptr) +{ + H5P_genplist_t *fapl; /* Property list pointer */ + H5FD_file_image_info_t info; /* File image info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*x", fapl_id, callbacks_ptr); + + /* Get the plist structure */ + if(NULL == (fapl = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get old info */ + if(H5P_get(fapl, H5F_ACS_FILE_IMAGE_INFO_NAME, &info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file image info") + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + /* verify that callbacks_ptr is not NULL */ + if(NULL == callbacks_ptr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL callbacks_ptr") + + /* Transfer values to parameters */ + *callbacks_ptr = info.callbacks; + + /* Copy udata if it exists */ + if(info.callbacks.udata != NULL) { + HDassert(info.callbacks.udata_copy); + if((callbacks_ptr->udata = info.callbacks.udata_copy(info.callbacks.udata)) == 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't copy udata") + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_file_image_callbacks() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_del + * + * Purpose: Delete callback for the file image info property, called + * when the property is deleted from the plist. The buffer + * and udata may need to be freed, possibly using their + * respective callbacks so the default free won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = *(H5FD_file_image_info_t *)value; + + /* verify file image field consistancy */ + HDassert(((info.buffer != NULL) && (info.size > 0)) || + ((info.buffer == NULL) && (info.size == 0))); + + if(info.buffer && info.size > 0) { + /* Free buffer */ + if(info.callbacks.image_free) { + if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + free(info.buffer); + } /* end if */ + + /* Free udata if it exists */ + if(info.callbacks.udata) { + if(NULL == info.callbacks.udata_free) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") + + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_del() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_copy + * + * Purpose: Copy callback for the file image info property. The buffer + * and udata may need to be copied, possibly using their + * respective callbacks so the default copy won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_copy(const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t *info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = (H5FD_file_image_info_t *)value; + + /* verify file image field consistancy */ + HDassert(((info->buffer != NULL) && (info->size > 0)) || + ((info->buffer == NULL) && (info->size == 0))); + + if(info->buffer && info->size > 0) { + void *old_buffer; /* Pointer to old image buffer */ + + /* Store the old buffer */ + old_buffer = info->buffer; + + /* Allocate new buffer */ + if(info->callbacks.image_malloc) { + if(NULL == (info->buffer = info->callbacks.image_malloc(info->size, + H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, info->callbacks.udata))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "image malloc callback failed") + } /* end if */ + else { + if(NULL == (info->buffer = H5MM_malloc(info->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") + } /* end else */ + + /* Copy data to new buffer */ + if(info->callbacks.image_memcpy) { + if(info->buffer != info->callbacks.image_memcpy(info->buffer, old_buffer, + info->size, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_COPY, + info->callbacks.udata)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(info->buffer, old_buffer, info->size); + } /* end if */ + } /* end if */ + + /* Copy udata if it exists */ + if(info->callbacks.udata) { + void *old_udata = info->callbacks.udata; + + if(NULL == info->callbacks.udata_copy) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_copy not defined") + + info->callbacks.udata = info->callbacks.udata_copy(old_udata); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_file_image_info_close + * + * Purpose: Close callback for the file image info property. The buffer + * and udata may need to be freed, possibly using their + * respective callbacks so the standard free won't work. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Jacob Gruber + * Thurday, August 11, 2011 + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_file_image_info_close(const char UNUSED *name, size_t UNUSED size, void *value) +{ + H5FD_file_image_info_t info; /* Image info struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + if(value) { + info = *(H5FD_file_image_info_t *)value; + + if(info.buffer != NULL && info.size > 0) { + /* Free buffer */ + if(info.callbacks.image_free) { + if(info.callbacks.image_free(info.buffer, H5FD_FILE_IMAGE_OP_PROPERTY_LIST_CLOSE, + info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(info.buffer); + } /* end if */ + } /* end if */ + + /* Free udata if it exists */ + if(info.callbacks.udata) { + if(NULL == info.callbacks.udata_free) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata_free not defined") + if(info.callbacks.udata_free(info.callbacks.udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "udata_free callback failed") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5P_file_image_info_close() */ + diff --git a/src/H5Pint.c b/src/H5Pint.c index 08b8af6..46a06a0 100644 --- a/src/H5Pint.c +++ b/src/H5Pint.c @@ -51,6 +51,7 @@ typedef struct { const H5P_genclass_t *parent; /* Pointer to parent class */ const char *name; /* Pointer to name to check */ + H5P_genclass_t *new_class; /* Pointer to class during path traversal */ } H5P_check_class_t; @@ -1358,11 +1359,11 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod) /*-------------------------------------------------------------------------- NAME - H5P_check_class + H5P_open_class_path_cb PURPOSE Internal callback routine to check for duplicated names in parent class. USAGE - int H5P_check_class(obj, id, key) + int H5P_open_class_path_cb(obj, id, key) H5P_genclass_t *obj; IN: Pointer to class hid_t id; IN: ID of object being looked at const void *key; IN: Pointer to information used to compare @@ -1378,27 +1379,29 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod) REVISION LOG --------------------------------------------------------------------------*/ static int -H5P_check_class(void *_obj, hid_t UNUSED id, void *_key) +H5P_open_class_path_cb(void *_obj, hid_t UNUSED id, void *_key) { - H5P_genclass_t *obj=(H5P_genclass_t *)_obj; /* Pointer to the class for this ID */ - const H5P_check_class_t *key=(const H5P_check_class_t *)_key; /* Pointer to key information for comparison */ - int ret_value=0; /* Return value */ + H5P_genclass_t *obj = (H5P_genclass_t *)_obj; /* Pointer to the class for this ID */ + H5P_check_class_t *key = (H5P_check_class_t *)_key; /* Pointer to key information for comparison */ + int ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(obj); - HDassert(H5I_GENPROP_CLS==H5I_get_type(id)); + HDassert(H5I_GENPROP_CLS == H5I_get_type(id)); HDassert(key); /* Check if the class object has the same parent as the new class */ - if(obj->parent==key->parent) { + if(obj->parent == key->parent) { /* Check if they have the same name */ - if(HDstrcmp(obj->name,key->name)==0) - ret_value=1; /* Indicate a match */ + if(HDstrcmp(obj->name, key->name) == 0) { + key->new_class = obj; + ret_value = 1; /* Indicate a match */ + } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5P_check_class() */ +} /* end H5P_open_class_path_cb() */ /*-------------------------------------------------------------------------- @@ -4555,8 +4558,8 @@ H5P_open_class_path(const char *path) char *curr_name; /* Pointer to current component of path name */ char *delimit; /* Pointer to path delimiter during traversal */ H5P_genclass_t *curr_class; /* Pointer to class during path traversal */ - H5P_genclass_t *ret_value; /* Return value */ H5P_check_class_t check_info; /* Structure to hold the information for checking duplicate names */ + H5P_genclass_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -4569,20 +4572,24 @@ H5P_open_class_path(const char *path) /* Find the generic property class with this full path */ curr_name = tmp_path; curr_class = NULL; - while((delimit=HDstrchr(curr_name,'/'))!=NULL) { + while(NULL != (delimit = HDstrchr(curr_name, '/'))) { /* Change the delimiter to terminate the string */ - *delimit='\0'; + *delimit = '\0'; /* Set up the search structure */ - check_info.parent=curr_class; - check_info.name=curr_name; + check_info.parent = curr_class; + check_info.name = curr_name; + check_info.new_class = NULL; /* Find the class with this name & parent by iterating over the open classes */ - if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE))) - HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") + if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes") + else if(NULL == check_info.new_class) + HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") /* Advance the pointer in the path to the start of the next component */ - curr_name=delimit+1; + curr_class = check_info.new_class; + curr_name = delimit + 1; } /* end while */ /* Should be pointing to the last component in the path name now... */ @@ -4590,13 +4597,16 @@ H5P_open_class_path(const char *path) /* Set up the search structure */ check_info.parent = curr_class; check_info.name = curr_name; + check_info.new_class = NULL; /* Find the class with this name & parent by iterating over the open classes */ - if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE))) + if(H5I_iterate(H5I_GENPROP_CLS, H5P_open_class_path_cb, &check_info, FALSE) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_BADITER, NULL, "can't iterate over classes") + else if(NULL == check_info.new_class) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class") /* Copy it */ - if(NULL == (ret_value = H5P_copy_pclass(curr_class))) + if(NULL == (ret_value = H5P_copy_pclass(check_info.new_class))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class") done: @@ -4604,7 +4614,7 @@ done: H5MM_xfree(tmp_path); FUNC_LEAVE_NOAPI(ret_value) -} /* H5P_open_class_path() */ +} /* H5P_open_class_path() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 9015940..654772a 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -322,6 +322,12 @@ H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low, H5F_libver_t *high); H5_DLL herr_t H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size); H5_DLL herr_t H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size); +H5_DLL herr_t H5Pset_file_image(hid_t fapl_id, void *buf_ptr, size_t buf_len); +H5_DLL herr_t H5Pget_file_image(hid_t fapl_id, void **buf_ptr_ptr, size_t *buf_len_ptr); +H5_DLL herr_t H5Pset_file_image_callbacks(hid_t fapl_id, + H5FD_file_image_callbacks_t *callbacks_ptr); +H5_DLL herr_t H5Pget_file_image_callbacks(hid_t fapl_id, + H5FD_file_image_callbacks_t *callbacks_ptr); /* Dataset creation property list (DCPL) routines */ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout); @@ -1449,7 +1449,8 @@ H5T_term_interface(void) H5T_g.asoft = 0; /* Unlock all datatypes, then free them */ - H5I_search(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE); + /* note that we are ignoring the return value from H5I_iterate() */ + H5I_iterate(H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE); H5I_dec_type_ref(H5I_DATATYPE); /* Reset all the datatype IDs */ diff --git a/src/H5err.txt b/src/H5err.txt index 71d27a6..b4cb28b 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -220,6 +220,7 @@ MINOR, DSPACE, H5E_CANTCOMPARE, Can't compare objects MINOR, PLIST, H5E_CANTGET, Can't get value MINOR, PLIST, H5E_CANTSET, Can't set value MINOR, PLIST, H5E_DUPCLASS, Duplicate class name in parent class +MINOR, PLIST, H5E_SETDISALLOWED, Disallowed operation # Link errors MINOR, LINK, H5E_TRAVERSE, Link traversal failure |