summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2016-11-18 01:48:21 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2016-11-18 01:48:21 (GMT)
commiteba0ff43c968ef9a0b09edf19c1e337cfcae0816 (patch)
tree53142d64c8e678f0862533b17790bb4ea72fa87c
parent248a93cde8d87dd3a8162831103b5358a166fed8 (diff)
downloadhdf5-eba0ff43c968ef9a0b09edf19c1e337cfcae0816.zip
hdf5-eba0ff43c968ef9a0b09edf19c1e337cfcae0816.tar.gz
hdf5-eba0ff43c968ef9a0b09edf19c1e337cfcae0816.tar.bz2
Remove 'clear' callback from metadata cache client interface, using the
new 'entry cleaned' notify action innstead.
-rw-r--r--src/H5AC.c4
-rw-r--r--src/H5ACprivate.h1
-rw-r--r--src/H5B2cache.c3
-rw-r--r--src/H5Bcache.c1
-rw-r--r--src/H5C.c21
-rw-r--r--src/H5Cepoch.c14
-rw-r--r--src/H5Cprivate.h63
-rw-r--r--src/H5EAcache.c5
-rw-r--r--src/H5FAcache.c3
-rw-r--r--src/H5FScache.c2
-rw-r--r--src/H5Fsuper_cache.c2
-rw-r--r--src/H5Gcache.c1
-rw-r--r--src/H5HFcache.c3
-rw-r--r--src/H5HGcache.c1
-rw-r--r--src/H5HLcache.c2
-rw-r--r--src/H5Ocache.c279
-rw-r--r--src/H5SMcache.c2
-rw-r--r--test/cache_common.c11
-rw-r--r--test/earray.c1
-rw-r--r--testpar/t_cache.c73
20 files changed, 151 insertions, 341 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 1c6f3c9..764dfcd 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -567,7 +567,7 @@ H5AC_dest(H5F_t *f, hid_t dxpl_id)
#ifdef H5_HAVE_PARALLEL
/* destroying the cache, so clear all collective entries */
- if(H5C_clear_coll_entries(f->shared->cache, 0) < 0)
+ if(H5C_clear_coll_entries(f->shared->cache, FALSE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_clear_coll_entries() failed.")
aux_ptr = (H5AC_aux_t *)H5C_get_aux_ptr(f->shared->cache);
@@ -726,7 +726,7 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id)
#ifdef H5_HAVE_PARALLEL
/* flushing the cache, so clear all collective entries */
- if(H5C_clear_coll_entries(f->shared->cache, 0) < 0)
+ if(H5C_clear_coll_entries(f->shared->cache, FALSE) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTGET, FAIL, "H5C_clear_coll_entries() failed.")
/* Attempt to flush all entries from rank 0 & Bcast clean list to other ranks */
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index abda6ae..3a260d0 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -187,7 +187,6 @@ typedef H5C_pre_serialize_func_t H5AC_pre_serialize_func_t;
typedef H5C_serialize_func_t H5AC_serialize_func_t;
typedef H5C_notify_func_t H5AC_notify_func_t;
typedef H5C_free_icr_func_t H5AC_free_icr_func_t;
-typedef H5C_clear_func_t H5AC_clear_func_t;
typedef H5C_get_fsf_size_t H5AC_get_fsf_size_t;
typedef H5C_class_t H5AC_class_t;
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index c9e2767..32db4b0 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -106,7 +106,6 @@ const H5AC_class_t H5AC_BT2_HDR[1] = {{
H5B2__cache_hdr_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5B2__cache_hdr_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -123,7 +122,6 @@ const H5AC_class_t H5AC_BT2_INT[1] = {{
H5B2__cache_int_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5B2__cache_int_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -140,7 +138,6 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
H5B2__cache_leaf_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5B2__cache_leaf_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index d485049..44c5e62 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -80,7 +80,6 @@ const H5AC_class_t H5AC_BT[1] = {{
H5B__serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5B__free_icr, /* 'free_icr' callback */
- NULL, /* 'clear" callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5C.c b/src/H5C.c
index 3b32aa7..a1477d4 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -776,8 +776,7 @@ H5C_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
#if H5C_DO_EXTREME_SANITY_CHECKS
if(H5C_validate_lru_list(cache_ptr) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
- "LRU extreme sanity check failed on entry.\n");
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "LRU extreme sanity check failed on entry.\n");
#endif /* H5C_DO_EXTREME_SANITY_CHECKS */
/* Look for entry in cache */
@@ -806,7 +805,7 @@ H5C_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5C_class_t *type,
* This will clear the entry, and then delete it from the cache.
*/
- /* Pass along 'free file space' flag to cache client. */
+ /* Pass along 'free file space' flag */
flush_flags |= (flags & H5C__FREE_FILE_SPACE_FLAG);
/* Delete the entry from the skip list on destroy */
@@ -5960,7 +5959,7 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_
/* verify that the entry is no longer part of any flush dependencies */
HDassert(entry_ptr->flush_dep_nparents == 0);
HDassert(entry_ptr->flush_dep_nchildren == 0);
- }
+ } /* end if */
else {
HDassert(clear_only || write_entry);
HDassert(entry_ptr->is_dirty);
@@ -5987,9 +5986,6 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_
H5C__UPDATE_INDEX_FOR_ENTRY_CLEAN(cache_ptr, entry_ptr);
- if(entry_ptr->type->clear && (entry_ptr->type->clear)(f, (void *)entry_ptr, FALSE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to clear entry")
-
/* Check for entry changing status and do notifications, etc. */
if(was_dirty) {
/* If the entry's type has a 'notify' callback send a 'entry cleaned'
@@ -6088,19 +6084,10 @@ H5C__flush_single_entry(const H5F_t *f, hid_t dxpl_id, H5C_cache_entry_t *entry_
/* Check for actually destroying the entry in memory */
/* (As opposed to taking ownership of it) */
if(destroy_entry) {
- /* if the entry is dirty and it has a clear callback,
- * call this callback now. Since this callback exists,
- * it follows tht the client maintains its own dirty bits,
- * which must be cleared before the entry is freed to avoid
- * sanity check failures. Also clear the dirty flag for
- * the same reason.
- */
if(entry_ptr->is_dirty) {
+ /* Reset dirty flag */
entry_ptr->is_dirty = FALSE;
- if(entry_ptr->type->clear && (entry_ptr->type->clear)(f, (void *)entry_ptr, TRUE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to clear entry")
-
/* If the entry's type has a 'notify' callback send a 'entry cleaned'
* notice now that the entry is fully integrated into the cache.
*/
diff --git a/src/H5Cepoch.c b/src/H5Cepoch.c
index 3dbf57f..eacb247 100644
--- a/src/H5Cepoch.c
+++ b/src/H5Cepoch.c
@@ -76,8 +76,6 @@ static herr_t H5C__epoch_marker_serialize(const H5F_t *f,
void * image_ptr, size_t len, void * thing);
static herr_t H5C__epoch_marker_notify(H5C_notify_action_t action, void *thing);
static herr_t H5C__epoch_marker_free_icr(void * thing);
-static herr_t H5C__epoch_marker_clear(const H5F_t *f, void * thing,
- hbool_t about_to_destroy);
static herr_t H5C__epoch_marker_fsf_size(const void H5_ATTR_UNUSED * thing,
size_t H5_ATTR_UNUSED * fsf_size_ptr);
@@ -110,7 +108,6 @@ const H5C_class_t H5C__epoch_marker_class =
/* serialize = */ H5C__epoch_marker_serialize,
/* notify = */ H5C__epoch_marker_notify,
/* free_icr = */ H5C__epoch_marker_free_icr,
- /* clear = */ H5C__epoch_marker_clear,
/* fsf_size = */ H5C__epoch_marker_fsf_size,
};
@@ -211,17 +208,6 @@ H5C__epoch_marker_free_icr(void H5_ATTR_UNUSED * thing)
static herr_t
-H5C__epoch_marker_clear(const H5F_t H5_ATTR_UNUSED *f, void H5_ATTR_UNUSED * thing, hbool_t H5_ATTR_UNUSED about_to_destroy)
-{
- FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
-
- HERROR(H5E_CACHE, H5E_SYSTEM, "called unreachable fcn.");
-
- FUNC_LEAVE_NOAPI(FAIL)
-} /* end H5C__epoch_marker_clear() */
-
-
-static herr_t
H5C__epoch_marker_fsf_size(const void H5_ATTR_UNUSED * thing, size_t H5_ATTR_UNUSED *fsf_size_ptr)
{
FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index be04265..c4037b0 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -733,65 +733,7 @@ typedef struct H5C_t H5C_t;
*
* At least when compiled with debug, it would be useful if the
* free ICR call would fail if the in core representation has been
- * modified since the last serialize of clear callback.
- *
- * CLEAR: Pointer to the clear callback.
- *
- * In principle, there should be no need for the clear callback,
- * as the dirty flag should be maintained by the metadata cache.
- *.
- * However, some clients maintain dirty bits on internal data,
- * and we need some way of keeping these dirty bits in sync with
- * those maintained by the metadata cache. This callback exists
- * to serve this purpose. If defined, it is called whenever the
- * cache marks dirty entry clean, or when the cache is about to
- * discard a dirty entry without writing it to disk (This
- * happens as the result of an unprotect call with the
- * H5AC__DELETED_FLAG set, and the H5C__TAKE_OWNERSHIP_FLAG not
- * set.)
- *
- * Arguably, this functionality should be in the NOTIFY callback.
- * However, this callback is specific to only a few clients, and
- * it will be called relatively frequently. Hence it is made its
- * own callback to minimize overhead.
- *
- * The typedef for the clear callback is as follows:
- *
- * typedef herr_t (*H5C_clear_func_t)(const H5F_t *f,
- * void * thing,
- * hbool_t about_to_destroy);
- *
- * The parameters of the clear callback are as follows:
- *
- * f: File pointer.
- *
- * thing: Pointer to void containing the address of the in core
- * representation of the target metadata cache entry. This
- * is the same pointer that would be returned by a protect()
- * call of the associated addr and len.
- *
- * about_to_destroy: Boolean flag used to indicate whether the
- * metadata cache is about to destroy the target metadata
- * cache entry. The callback may use this flag to omit
- * operations that are irrelevant it the entry is about
- * to be destroyed.
- *
- * Processing in the clear function should proceed as follows:
- *
- * Reset all internal dirty bits in the target metadata cache entry.
- *
- * If the about_to_destroy flag is TRUE, the clear function may
- * ommit any dirty bit that will not trigger a sanity check failure
- * or otherwise cause problems in the subsequent free icr call.
- * In particular, the call must ensure that the free icr call will
- * not fail due to changes prior to this call, and after the
- * last serialize or clear call.
- *
- * If the function is successful, it must return SUCCEED.
- *
- * If it fails for any reason, the function must return FAIL and
- * push error information on the error stack with the error API
- * routines.
+ * modified since the last serialize callback.
*
* GET_FSF_SIZE: Pointer to the get file space free size callback.
*
@@ -888,8 +830,6 @@ typedef herr_t (*H5C_serialize_func_t)(const H5F_t *f, void *image_ptr,
size_t len, void *thing);
typedef herr_t (*H5C_notify_func_t)(H5C_notify_action_t action, void *thing);
typedef herr_t (*H5C_free_icr_func_t)(void *thing);
-typedef herr_t (*H5C_clear_func_t)(const H5F_t *f, void * thing,
- hbool_t about_to_destroy);
typedef herr_t (*H5C_get_fsf_size_t)(const void * thing, size_t *fsf_size_ptr);
/* Metadata cache client class definition */
@@ -905,7 +845,6 @@ typedef struct H5C_class_t {
H5C_serialize_func_t serialize;
H5C_notify_func_t notify;
H5C_free_icr_func_t free_icr;
- H5C_clear_func_t clear;
H5C_get_fsf_size_t fsf_size;
} H5C_class_t;
diff --git a/src/H5EAcache.c b/src/H5EAcache.c
index e944393..4a53b5c 100644
--- a/src/H5EAcache.c
+++ b/src/H5EAcache.c
@@ -137,7 +137,6 @@ const H5AC_class_t H5AC_EARRAY_HDR[1] = {{
H5EA__cache_hdr_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5EA__cache_hdr_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -154,7 +153,6 @@ const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{
H5EA__cache_iblock_serialize, /* 'serialize' callback */
H5EA__cache_iblock_notify, /* 'notify' callback */
H5EA__cache_iblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -171,7 +169,6 @@ const H5AC_class_t H5AC_EARRAY_SBLOCK[1] = {{
H5EA__cache_sblock_serialize, /* 'serialize' callback */
H5EA__cache_sblock_notify, /* 'notify' callback */
H5EA__cache_sblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -188,7 +185,6 @@ const H5AC_class_t H5AC_EARRAY_DBLOCK[1] = {{
H5EA__cache_dblock_serialize, /* 'serialize' callback */
H5EA__cache_dblock_notify, /* 'notify' callback */
H5EA__cache_dblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
H5EA__cache_dblock_fsf_size, /* 'fsf_size' callback */
}};
@@ -205,7 +201,6 @@ const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1] = {{
H5EA__cache_dblk_page_serialize, /* 'serialize' callback */
H5EA__cache_dblk_page_notify, /* 'notify' callback */
H5EA__cache_dblk_page_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5FAcache.c b/src/H5FAcache.c
index f904a78..9574c9f 100644
--- a/src/H5FAcache.c
+++ b/src/H5FAcache.c
@@ -114,7 +114,6 @@ const H5AC_class_t H5AC_FARRAY_HDR[1] = {{
H5FA__cache_hdr_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5FA__cache_hdr_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -131,7 +130,6 @@ const H5AC_class_t H5AC_FARRAY_DBLOCK[1] = {{
H5FA__cache_dblock_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5FA__cache_dblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
H5FA__cache_dblock_fsf_size, /* 'fsf_size' callback */
}};
@@ -148,7 +146,6 @@ const H5AC_class_t H5AC_FARRAY_DBLK_PAGE[1] = {{
H5FA__cache_dblk_page_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5FA__cache_dblk_page_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5FScache.c b/src/H5FScache.c
index 9b44d8a..b403a69 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -118,7 +118,6 @@ const H5AC_class_t H5AC_FSPACE_HDR[1] = {{
H5FS__cache_hdr_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5FS__cache_hdr_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -135,7 +134,6 @@ const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{
H5FS__cache_sinfo_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5FS__cache_sinfo_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index 61ab253..d863159 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -104,7 +104,6 @@ const H5AC_class_t H5AC_SUPERBLOCK[1] = {{
H5F__cache_superblock_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5F__cache_superblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -121,7 +120,6 @@ const H5AC_class_t H5AC_DRVRINFO[1] = {{
H5F__cache_drvrinfo_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5F__cache_drvrinfo_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5Gcache.c b/src/H5Gcache.c
index 8ac0215..c3e1c12 100644
--- a/src/H5Gcache.c
+++ b/src/H5Gcache.c
@@ -99,7 +99,6 @@ const H5AC_class_t H5AC_SNODE[1] = {{
H5G__cache_node_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5G__cache_node_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index bcf1344..0e9485f 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -138,7 +138,6 @@ const H5AC_class_t H5AC_FHEAP_HDR[1] = {{
H5HF__cache_hdr_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5HF__cache_hdr_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -155,7 +154,6 @@ const H5AC_class_t H5AC_FHEAP_IBLOCK[1] = {{
H5HF__cache_iblock_serialize, /* 'serialize' callback */
H5HF__cache_iblock_notify, /* 'notify' callback */
H5HF__cache_iblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -172,7 +170,6 @@ const H5AC_class_t H5AC_FHEAP_DBLOCK[1] = {{
H5HF__cache_dblock_serialize, /* 'serialize' callback */
H5HF__cache_dblock_notify, /* 'notify' callback */
H5HF__cache_dblock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5HGcache.c b/src/H5HGcache.c
index 31f40f5..b01f30e 100644
--- a/src/H5HGcache.c
+++ b/src/H5HGcache.c
@@ -88,7 +88,6 @@ const H5AC_class_t H5AC_GHEAP[1] = {{
H5HG__cache_heap_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5HG__cache_heap_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
index a9a9851..5697121 100644
--- a/src/H5HLcache.c
+++ b/src/H5HLcache.c
@@ -110,7 +110,6 @@ const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{
H5HL__cache_prefix_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5HL__cache_prefix_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -126,7 +125,6 @@ const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{
H5HL__cache_datablock_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5HL__cache_datablock_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index badeb69..edabc52 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -74,8 +74,8 @@ static void *H5O__cache_deserialize(const void *image, size_t len,
static herr_t H5O__cache_image_len(const void *thing, size_t *image_len);
static herr_t H5O__cache_serialize(const H5F_t *f, void *image, size_t len,
void *thing);
+static herr_t H5O__cache_notify(H5AC_notify_action_t action, void *_thing);
static herr_t H5O__cache_free_icr(void *thing);
-static herr_t H5O__cache_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy);
static herr_t H5O__cache_chk_get_load_size(const void *udata, size_t *image_len);
static void *H5O__cache_chk_deserialize(const void *image, size_t len,
@@ -83,8 +83,8 @@ static void *H5O__cache_chk_deserialize(const void *image, size_t len,
static herr_t H5O__cache_chk_image_len(const void *thing, size_t *image_len);
static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len,
void *thing);
+static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing);
static herr_t H5O__cache_chk_free_icr(void *thing);
-static herr_t H5O__cache_chk_clear(const H5F_t *f, void *thing, hbool_t about_to_destroy);
/* Chunk routines */
static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len,
@@ -112,9 +112,8 @@ const H5AC_class_t H5AC_OHDR[1] = {{
H5O__cache_image_len, /* 'image_len' callback */
NULL, /* 'pre_serialize' callback */
H5O__cache_serialize, /* 'serialize' callback */
- NULL, /* 'notify' callback */
+ H5O__cache_notify, /* 'notify' callback */
H5O__cache_free_icr, /* 'free_icr' callback */
- H5O__cache_clear, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -129,9 +128,8 @@ const H5AC_class_t H5AC_OHDR_CHK[1] = {{
H5O__cache_chk_image_len, /* 'image_len' callback */
NULL, /* 'pre_serialize' callback */
H5O__cache_chk_serialize, /* 'serialize' callback */
- NULL, /* 'notify' callback */
+ H5O__cache_chk_notify, /* 'notify' callback */
H5O__cache_chk_free_icr, /* 'free_icr' callback */
- H5O__cache_chk_clear, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -592,123 +590,111 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__cache_serialize() */
-/**********************************/
-/* no H5O_cache_notify() function */
-/**********************************/
-
/*-------------------------------------------------------------------------
- * Function: H5O__cache_free_icr
+ * Function: H5O__cache_notify
*
- * Purpose: Free the in core representation of the supplied object header.
+ * Purpose: Handle cache action notifications
*
- * Note: The metadata cache sets the object's cache_info.magic to
- * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
- * callback (checked in assert).
+ * Return: Non-negative on success/Negative on failure
*
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: John Mainzer
- * 7/28/14
+ * Programmer: Quincey Koziol
+ * Jul 23 2016
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__cache_free_icr(void *_thing)
-{
- H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */
- herr_t ret_value = SUCCEED; /* Return value */
+H5O__cache_notify(H5AC_notify_action_t action, void *_thing)
+{
+ H5O_t *oh = (H5O_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /* Check arguments */
+ /*
+ * Check arguments.
+ */
HDassert(oh);
- HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
- HDassert(oh->cache_info.type == H5AC_OHDR);
- /* Destroy object header */
- if(H5O__free(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header")
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
+ {
+ unsigned u; /* Local index variable */
+
+ /* Mark messages stored with the object header (i.e. messages in chunk 0) as clean */
+ for(u = 0; u < oh->nmesgs; u++)
+ if(oh->mesg[u].chunkno == 0)
+ oh->mesg[u].dirty = FALSE;
+#ifndef NDEBUG
+ /* Reset the number of messages dirtied by decoding */
+ oh->ndecode_dirtied = 0;
+#endif /* NDEBUG */
+ }
+ break;
+
+ case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
+ case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* do nothing */
+ break;
+
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O__cache_free_icr() */
+} /* end H5O__cache_notify() */
/*-------------------------------------------------------------------------
- * Function: H5O__cache_clear
- *
- * Purpose: Clear all dirty bits associated with this cache entry.
+ * Function: H5O__cache_free_icr
*
- * This is ncessary as the object header cache client maintains
- * its own dirty bits on individual messages. These dirty bits
- * used to be cleared by the old V2 metadata cache flush callback,
- * but now the metadata cache must clear them explicitly, as
- * the serialize callback does not imply that the data has been
- * written to disk.
+ * Purpose: Free the in core representation of the supplied object header.
*
- * This callback is also necessary for the parallel case.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
- * 9/22/14
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-#ifdef H5_HAVE_PARALLEL
-H5O__cache_clear(const H5F_t *f, void *_thing, hbool_t H5_ATTR_UNUSED about_to_destroy)
-#else
-H5O__cache_clear(const H5F_t H5_ATTR_UNUSED *f, void *_thing, hbool_t H5_ATTR_UNUSED about_to_destroy)
-#endif /* H5_HAVE_PARALLEL */
+H5O__cache_free_icr(void *_thing)
{
- H5O_t *oh = (H5O_t *)_thing; /* Object header to reset */
- unsigned u; /* Local index variable */
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */
herr_t ret_value = SUCCEED; /* Return value */
-#ifdef H5_HAVE_PARALLEL
FUNC_ENTER_STATIC
-#else
- FUNC_ENTER_STATIC_NOERR
-#endif /* H5_HAVE_PARALLEL */
/* Check arguments */
HDassert(oh);
- HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
HDassert(oh->cache_info.type == H5AC_OHDR);
-#ifdef H5_HAVE_PARALLEL
- if((oh->nchunks > 0) && (!about_to_destroy)) {
- /* Scan through chunk 0 (the chunk stored contiguously with this
- * object header) and cause it to update its image of all entries
- * currently marked dirty. Must do this in the parallel case, as
- * it is possible that this processor may clear this object header
- * several times before flushing it -- thus causing undefined
- * sections of the image to be written to disk overwriting valid data.
- */
- if(H5O__chunk_serialize(f, oh, 0) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
- /* Mark messages stored with the object header (i.e. messages in chunk 0) as clean */
- for(u = 0; u < oh->nmesgs; u++)
- if(oh->mesg[u].chunkno == 0)
- oh->mesg[u].dirty = FALSE;
-
-#ifndef NDEBUG
- /* Reset the number of messages dirtied by decoding */
- oh->ndecode_dirtied = 0;
-#endif /* NDEBUG */
+ /* Destroy object header */
+ if(H5O__free(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header")
-#ifdef H5_HAVE_PARALLEL
done:
-#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O__cache_clear() */
+} /* end H5O__cache_free_icr() */
/*-------------------------------------------------------------------------
@@ -905,116 +891,115 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O__cache_chk_serialize() */
-/**************************************/
-/* no H5O_cache_chk_notify() function */
-/**************************************/
-
/*-------------------------------------------------------------------------
- * Function: H5O__cache_chk_free_icr
+ * Function: H5O__cache_chk_notify
*
- * Purpose: Free the in core memory associated with the supplied object
- * header continuation chunk.
+ * Purpose: Handle cache action notifications
*
- * Note: The metadata cache sets the object's cache_info.magic to
- * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
- * callback (checked in assert).
+ * Return: Non-negative on success/Negative on failure
*
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: John Mainzer
- * 7/28/14
+ * Programmer: Neil Fortner
+ * Mar 20 2012
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O__cache_chk_free_icr(void *_thing)
+H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing)
{
- H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing;
+ void *parent = NULL; /* Chunk containing continuation message that points to this chunk */
+ H5O_chunk_proxy_t *cont_chk_proxy = NULL; /* Proxy for chunk containing continuation message that points to this chunk, if not chunk 0 */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /* Check arguments */
+ /*
+ * Check arguments.
+ */
HDassert(chk_proxy);
- HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
- HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ HDassert(chk_proxy->oh);
- /* Destroy object header chunk proxy */
- if(H5O__chunk_dest(chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
+ {
+ unsigned u; /* Local index variable */
+
+ /* Mark messages in chunk as clean */
+ for(u = 0; u < chk_proxy->oh->nmesgs; u++)
+ if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
+ chk_proxy->oh->mesg[u].dirty = FALSE;
+ }
+ break;
+
+ case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
+ case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* do nothing */
+ break;
+
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
done:
+ if(cont_chk_proxy)
+ if(H5O_chunk_unprotect(chk_proxy->f, H5AC_ind_read_dxpl_id, cont_chk_proxy, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O__cache_chk_free_icr() */
+} /* end H5O__cache_chk_notify() */
/*-------------------------------------------------------------------------
- * Function: H5O__cache_chk_clear
- *
- * Purpose: Clear all dirty bits associated with this cache entry.
+ * Function: H5O__cache_chk_free_icr
*
- * This is ncessary as the object header cache client maintains
- * its own dirty bits on individual messages. These dirty bits
- * used to be cleared by the old V2 metadata cache flush callback,
- * but now the metadata cache must clear them explicitly, as
- * the serialize callback does not imply that the data has been
- * written to disk.
+ * Purpose: Free the in core memory associated with the supplied object
+ * header continuation chunk.
*
- * This callback is also necessary for the parallel case.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
* Return: Success: SUCCEED
* Failure: FAIL
*
* Programmer: John Mainzer
- * 9/22/14
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-#ifdef H5_HAVE_PARALLEL
-H5O__cache_chk_clear(const H5F_t *f, void *_thing, hbool_t about_to_destroy)
-#else
-H5O__cache_chk_clear(const H5F_t H5_ATTR_UNUSED *f, void *_thing, hbool_t H5_ATTR_UNUSED about_to_destroy)
-#endif /* H5_HAVE_PARALLEL */
-{
- H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to reset */
- H5O_t *oh; /* Object header for chunk */
- unsigned u; /* Local index variable */
+H5O__cache_chk_free_icr(void *_thing)
+{
+ H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */
herr_t ret_value = SUCCEED; /* Return value */
-#ifdef H5_HAVE_PARALLEL
FUNC_ENTER_STATIC
-#else
- FUNC_ENTER_STATIC_NOERR
-#endif /* H5_HAVE_PARALLEL */
/* Check arguments */
HDassert(chk_proxy);
- HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
- oh = chk_proxy->oh;
- HDassert(oh);
- HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
- HDassert(oh->cache_info.type == H5AC_OHDR);
-
-#ifdef H5_HAVE_PARALLEL
- if((chk_proxy->oh->cache_info.is_dirty) && (!about_to_destroy))
- if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header chunk")
-#endif /* H5_HAVE_PARALLEL */
- /* Mark messages in chunk as clean */
- for(u = 0; u < chk_proxy->oh->nmesgs; u++)
- if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
- chk_proxy->oh->mesg[u].dirty = FALSE;
+ /* Destroy object header chunk proxy */
+ if(H5O__chunk_dest(chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
-#ifdef H5_HAVE_PARALLEL
done:
-#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O__cache_chk_clear() */
+} /* end H5O__cache_chk_free_icr() */
/*-------------------------------------------------------------------------
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index 3cac052..26db5d3 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -92,7 +92,6 @@ const H5AC_class_t H5AC_SOHM_TABLE[1] = {{
H5SM__cache_table_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5SM__cache_table_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
@@ -108,7 +107,6 @@ const H5AC_class_t H5AC_SOHM_LIST[1] = {{
H5SM__cache_list_serialize, /* 'serialize' callback */
NULL, /* 'notify' callback */
H5SM__cache_list_free_icr, /* 'free_icr' callback */
- NULL, /* 'clear' callback */
NULL, /* 'fsf_size' callback */
}};
diff --git a/test/cache_common.c b/test/cache_common.c
index 247ac57..4bea2a8 100644
--- a/test/cache_common.c
+++ b/test/cache_common.c
@@ -314,7 +314,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
pico_free_icr,
NULL,
- NULL,
},
{
NANO_ENTRY_TYPE,
@@ -329,7 +328,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
nano_free_icr,
NULL,
- NULL,
},
{
MICRO_ENTRY_TYPE,
@@ -344,7 +342,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
micro_free_icr,
NULL,
- NULL,
},
{
TINY_ENTRY_TYPE,
@@ -359,7 +356,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
tiny_free_icr,
NULL,
- NULL,
},
{
SMALL_ENTRY_TYPE,
@@ -374,7 +370,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
small_free_icr,
NULL,
- NULL,
},
{
MEDIUM_ENTRY_TYPE,
@@ -389,7 +384,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
medium_free_icr,
NULL,
- NULL,
},
{
LARGE_ENTRY_TYPE,
@@ -404,7 +398,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
large_free_icr,
NULL,
- NULL,
},
{
HUGE_ENTRY_TYPE,
@@ -419,7 +412,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
huge_free_icr,
NULL,
- NULL,
},
{
MONSTER_ENTRY_TYPE,
@@ -434,7 +426,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
monster_free_icr,
NULL,
- NULL,
},
{
VARIABLE_ENTRY_TYPE,
@@ -449,7 +440,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
NULL,
variable_free_icr,
NULL,
- NULL,
},
{
NOTIFY_ENTRY_TYPE,
@@ -464,7 +454,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
notify_notify,
notify_free_icr,
NULL,
- NULL,
}
};
diff --git a/test/earray.c b/test/earray.c
index 5211b97..17daefd 100644
--- a/test/earray.c
+++ b/test/earray.c
@@ -197,7 +197,6 @@ const H5AC_class_t H5AC_EARRAY_TEST[1] = {{
/* serialize */ earray_cache_test_serialize,
/* notify */ NULL,
/* free_icr */ earray_cache_test_free_icr,
- /* clear */ NULL,
/* fsf_size */ NULL,
}};
diff --git a/testpar/t_cache.c b/testpar/t_cache.c
index 8312512..b855f5d 100644
--- a/testpar/t_cache.c
+++ b/testpar/t_cache.c
@@ -139,7 +139,8 @@ int total_writes = 0;
* happen to overlap some collective operation.
*
* cleared: Boolean flag that is set to true whenever the entry is
- * dirty, and is cleared via a call to datum_clear().
+ * dirty, and is cleared via a call to datum_notify with the
+ * "entry cleaned" action.
*
* flushed: Boolean flag that is set to true whenever the entry is
* dirty, and is flushed by the metadata cache.
@@ -409,8 +410,6 @@ static herr_t datum_notify(H5C_notify_action_t action, void *thing);
static herr_t datum_free_icr(void * thing);
-static herr_t datum_clear(H5F_t * f, void * thing, hbool_t about_to_destroy);
-
#define DATUM_ENTRY_TYPE H5AC_TEST_ID
#define NUMBER_OF_ENTRY_TYPES 1
@@ -444,7 +443,6 @@ const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
/* serialize */ datum_serialize,
/* notify */ datum_notify,
/* free_icr */ datum_free_icr,
- /* clear */ datum_clear,
/* fsf_size */ NULL,
}
};
@@ -2893,7 +2891,16 @@ datum_notify(H5C_notify_action_t action, void *thing)
fflush(stdout);
}
- /* do nothing */
+ entry_ptr->cleared = TRUE;
+ entry_ptr->dirty = FALSE;
+
+ datum_clears++;
+
+ if(entry_ptr->header.is_pinned) {
+ datum_pinned_clears++;
+ HDassert( entry_ptr->global_pinned || entry_ptr->local_pinned );
+ } /* end if */
+
break;
case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
@@ -2991,62 +2998,6 @@ datum_free_icr(void * thing)
} /* datum_free_icr() */
-/*-------------------------------------------------------------------------
- * Function: datum_clear
- *
- * Purpose: Mark the datum as clean.
- *
- * Do not write it to the server, or increment the version.
- *
- * Return: SUCCEED
- *
- * Programmer: John Mainzer
- * 12/29/05
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-datum_clear(H5F_t H5_ATTR_UNUSED * f,
- void * thing,
- hbool_t H5_ATTR_UNUSED about_to_destroy)
-{
- int idx;
- struct datum * entry_ptr;
-
- HDassert( thing );
-
- entry_ptr = (struct datum *)thing;
-
- idx = addr_to_datum_index(entry_ptr->base_addr);
-
- HDassert( idx >= 0 );
- HDassert( idx < NUM_DATA_ENTRIES );
- HDassert( idx < virt_num_data_entries );
- HDassert( &(data[idx]) == entry_ptr );
-
- HDassert( entry_ptr->header.addr == entry_ptr->base_addr );
- HDassert( ( entry_ptr->header.size == entry_ptr->len ) ||
- ( entry_ptr->header.size == entry_ptr->local_len ) );
-
- HDassert( ( entry_ptr->dirty ) ||
- ( entry_ptr->header.is_dirty == entry_ptr->dirty ) );
-
- entry_ptr->cleared = TRUE;
- entry_ptr->dirty = FALSE;
-
- datum_clears++;
-
- if ( entry_ptr->header.is_pinned ) {
-
- datum_pinned_clears++;
- HDassert( entry_ptr->global_pinned || entry_ptr->local_pinned );
- }
-
- return(SUCCEED);
-
-} /* datum_clear() */
-
-
/*****************************************************************************/
/************************** test utility functions ***************************/
/*****************************************************************************/