summaryrefslogtreecommitdiffstats
path: root/src/H5Oflush.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Oflush.c')
-rw-r--r--src/H5Oflush.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/H5Oflush.c b/src/H5Oflush.c
index 0bec096..6484dfd 100644
--- a/src/H5Oflush.c
+++ b/src/H5Oflush.c
@@ -54,6 +54,53 @@ static herr_t H5O_oh_tag(const H5O_loc_t *oloc, hid_t dxpl_id, haddr_t *tag);
/*-------------------------------------------------------------------------
+ * Function: H5Oflush
+ *
+ * Purpose: Flushes all buffers associated with an object to disk.
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Mike McGreevy
+ * May 19, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Oflush(hid_t obj_id)
+{
+ H5O_loc_t *oloc; /* object location */
+ void *obj_ptr; /* Pointer to object */
+ const H5O_obj_class_t *obj_class = NULL; /* Class of object */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", obj_id);
+
+ /* Check args */
+ if(NULL == (oloc = H5O_get_loc(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object")
+
+ /* Get the object pointer */
+ if(NULL == (obj_ptr = H5I_object(obj_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier")
+
+ /* Get the object class */
+ if(NULL == (obj_class = H5O_obj_class(oloc, H5AC_ind_read_dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object class")
+
+ /* Flush the object of this class */
+ if(obj_class->flush && obj_class->flush(obj_ptr, H5AC_ind_read_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")
+
+ /* Flush the object metadata and invoke flush callback */
+ if(H5O_flush_common(oloc, obj_id, H5AC_ind_read_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object and object flush callback")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Oflush() */
+
+/*-------------------------------------------------------------------------
* Function: H5O_flush_common
*
* Purpose: Flushes the object's metadata
@@ -130,3 +177,211 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_oh_tag() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_refresh_metadata
+ *
+ * Purpose: Refreshes all buffers associated with an object.
+ *
+ * Note: This is based on the original H5O_refresh_metadata() but
+ * is split into 2 routines.
+ * This is done so that H5Fstart_swmr_write() can use these
+ * 2 routines to refresh opened objects. This may be
+ * restored back to the original code when H5Fstart_swmr_write()
+ * uses a different approach to handle issues with opened objects.
+ * H5Fstart_swmr_write() no longer calls the 1st routine. (12/24/15)
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Mike McGreevy/Vailin Choi
+ * July 28, 2010/Feb 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_refresh_metadata(hid_t oid, H5O_loc_t oloc, hid_t dxpl_id)
+{
+ hbool_t objs_incr = FALSE; /* Whether the object count in the file was incremented */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* If the file is opened with write access, no need to perform refresh actions. */
+ if(!(H5F_INTENT(oloc.file) & H5F_ACC_RDWR)) {
+ H5G_loc_t obj_loc;
+ H5O_loc_t obj_oloc;
+ H5G_name_t obj_path;
+
+ /* Create empty object location */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* "Fake" another open object in the file, so that it doesn't get closed
+ * if this object is the only thing holding the file open.
+ */
+ H5F_incr_nopen_objs(oloc.file);
+ objs_incr = TRUE;
+
+ /* Close object & evict its metadata */
+ if((H5O_refresh_metadata_close(oid, oloc, &obj_loc, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
+
+ /* Re-open the object, re-fetching its metadata */
+ if((H5O_refresh_metadata_reopen(oid, &obj_loc, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")
+ } /* end if */
+
+done:
+ if(objs_incr)
+ H5F_decr_nopen_objs(oloc.file);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5O_refresh_metadata() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_refresh_metadata_close
+ *
+ * Purpose: This is the first part of the original routine H5O_refresh_metadata().
+ * (1) Save object location information.
+ * (2) Handle multiple dataset opens
+ * (3) Get object cork status
+ * (4) Close the object
+ * (5) Flush and evict object metadata
+ * (6) Re-cork the object if needed
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Mike McGreevy/Vailin Choi
+ * July 28, 2010/Feb 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_refresh_metadata_close(hid_t oid, H5O_loc_t oloc, H5G_loc_t *obj_loc, hid_t dxpl_id)
+{
+ haddr_t tag = 0; /* Tag for object */
+ hbool_t corked = FALSE; /* Whether object's metadata is corked */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Make deep local copy of object's location information */
+ if(obj_loc) {
+ H5G_loc_t tmp_loc;
+
+ H5G_loc(oid, &tmp_loc);
+ H5G_loc_copy(obj_loc, &tmp_loc, H5_COPY_DEEP);
+ } /* end if */
+
+ /* Get object's type */
+ if(H5I_get_type(oid) == H5I_DATASET)
+ if(H5D_mult_refresh_close(oid, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to prepare refresh for dataset")
+
+ /* Retrieve tag for object */
+ if(H5O_oh_tag(&oloc, dxpl_id, &tag) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to get object header address")
+
+ /* Get cork status of the object with tag */
+ if(H5AC_cork(oloc.file, tag, H5AC__GET_CORKED, &corked) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_SYSTEM, FAIL, "unable to retrieve an object's cork status")
+
+ /* Close the object */
+ if(H5I_dec_ref(oid) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to close object")
+
+ /* Flush metadata based on tag value of the object */
+ if(H5F_flush_tagged_metadata(oloc.file, tag, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata")
+
+ /* Evict the object's tagged metadata */
+ if(H5F_evict_tagged_metadata(oloc.file, tag, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict metadata")
+
+ /* Re-cork object with tag */
+ if(corked)
+ if(H5AC_cork(oloc.file, tag, H5AC__SET_CORK, &corked) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_SYSTEM, FAIL, "unable to cork the object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5O_refresh_metadata_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_refresh_metadata_reopen
+ *
+ * Purpose: This is the second part of the original routine H5O_refresh_metadata().
+ * (1) Re-open object with the saved object location information.
+ * (2) Re-register object ID with the re-opened object.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Mike McGreevy/Vailin Choi
+ * July 28, 2010/Feb 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_refresh_metadata_reopen(hid_t oid, H5G_loc_t *obj_loc, hid_t dxpl_id)
+{
+ void *object = NULL; /* Dataset for this operation */
+ H5I_type_t type; /* Type of object for the ID */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Get object's type */
+ type = H5I_get_type(oid);
+
+ switch(type) {
+ case(H5I_GROUP):
+ /* Re-open the group */
+ if(NULL == (object = H5G_open(obj_loc, dxpl_id)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+ break;
+
+ case(H5I_DATATYPE):
+ /* Re-open the named datatype */
+ if(NULL == (object = H5T_open(obj_loc, dxpl_id)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
+ break;
+
+ case(H5I_DATASET):
+ /* Re-open the dataset */
+ if(NULL == (object = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT, dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
+ if(H5D_mult_refresh_reopen((H5D_t *)object, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to finish refresh for dataset")
+ break;
+
+ case(H5I_UNINIT):
+ case(H5I_BADID):
+ case(H5I_FILE):
+ case(H5I_DATASPACE):
+ case(H5I_ATTR):
+ case(H5I_REFERENCE):
+ case(H5I_VFL):
+ case(H5I_GENPROP_CLS):
+ case(H5I_GENPROP_LST):
+ case(H5I_ERROR_CLASS):
+ case(H5I_ERROR_MSG):
+ case(H5I_ERROR_STACK):
+ case(H5I_NTYPES):
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, FAIL, "not a valid file object ID (dataset, group, or datatype)")
+ break;
+ } /* end switch */
+
+ /* Re-register ID for the object */
+ if((H5I_register_with_id(type, object, TRUE, oid)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to re-register object atom")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5O_refresh_metadata_reopen() */
+