1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*-------------------------------------------------------------------------
15  *
16  * Created:             H5ACproxy_entry.c
17  *
18  * Purpose:             Functions and a cache client for a "proxy" cache entry.
19  *			A proxy cache entry is used as a placeholder for entire
20  *			data structures to attach flush dependencies, etc.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 #include "H5ACmodule.h" /* This source code file is part of the H5AC module */
29 
30 /***********/
31 /* Headers */
32 /***********/
33 #include "H5private.h"   /* Generic Functions                    */
34 #include "H5ACpkg.h"     /* Metadata cache                       */
35 #include "H5Eprivate.h"  /* Error handling                       */
36 #include "H5MFprivate.h" /* File memory management		*/
37 
38 /****************/
39 /* Local Macros */
40 /****************/
41 
42 /******************/
43 /* Local Typedefs */
44 /******************/
45 
46 /********************/
47 /* Package Typedefs */
48 /********************/
49 
50 /********************/
51 /* Local Prototypes */
52 /********************/
53 
54 /* Metadata cache (H5AC) callbacks */
55 static herr_t H5AC__proxy_entry_image_len(const void *thing, size_t *image_len);
56 static herr_t H5AC__proxy_entry_serialize(const H5F_t *f, void *image_ptr, size_t len, void *thing);
57 static herr_t H5AC__proxy_entry_notify(H5AC_notify_action_t action, void *thing);
58 static herr_t H5AC__proxy_entry_free_icr(void *thing);
59 
60 /*********************/
61 /* Package Variables */
62 /*********************/
63 
64 /* H5AC proxy entries inherit cache-like properties from H5AC */
65 const H5AC_class_t H5AC_PROXY_ENTRY[1] = {{
66     H5AC_PROXY_ENTRY_ID,         /* Metadata client ID */
67     "Proxy entry",               /* Metadata client name (for debugging) */
68     H5FD_MEM_SUPER,              /* File space memory type for client */
69     0,                           /* Client class behavior flags */
70     NULL,                        /* 'get_initial_load_size' callback */
71     NULL,                        /* 'get_final_load_size' callback */
72     NULL,                        /* 'verify_chksum' callback */
73     NULL,                        /* 'deserialize' callback */
74     H5AC__proxy_entry_image_len, /* 'image_len' callback */
75     NULL,                        /* 'pre_serialize' callback */
76     H5AC__proxy_entry_serialize, /* 'serialize' callback */
77     H5AC__proxy_entry_notify,    /* 'notify' callback */
78     H5AC__proxy_entry_free_icr,  /* 'free_icr' callback */
79     NULL,                        /* 'fsf_size' callback */
80 }};
81 
82 /*****************************/
83 /* Library Private Variables */
84 /*****************************/
85 
86 /*******************/
87 /* Local Variables */
88 /*******************/
89 
90 /* Declare a free list to manage H5AC_proxy_entry_t objects */
91 H5FL_DEFINE_STATIC(H5AC_proxy_entry_t);
92 
93 /*-------------------------------------------------------------------------
94  * Function:    H5AC_proxy_entry_create
95  *
96  * Purpose:     Create a new proxy entry
97  *
98  * Return:	Success:	Pointer to the new proxy entry object.
99  *		Failure:	NULL
100  *
101  * Programmer:  Quincey Koziol
102  *              September 17, 2016
103  *
104  *-------------------------------------------------------------------------
105  */
106 H5AC_proxy_entry_t *
H5AC_proxy_entry_create(void)107 H5AC_proxy_entry_create(void)
108 {
109     H5AC_proxy_entry_t *pentry    = NULL; /* Pointer to new proxy entry */
110     H5AC_proxy_entry_t *ret_value = NULL; /* Return value */
111 
112     FUNC_ENTER_NOAPI(NULL)
113 
114     /* Allocate new proxy entry */
115     if (NULL == (pentry = H5FL_CALLOC(H5AC_proxy_entry_t)))
116         HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, NULL, "can't allocate proxy entry")
117 
118     /* Set non-zero fields */
119     pentry->addr = HADDR_UNDEF;
120 
121     /* Set return value */
122     ret_value = pentry;
123 
124 done:
125     /* Release resources on error */
126     if (!ret_value)
127         if (pentry)
128             pentry = H5FL_FREE(H5AC_proxy_entry_t, pentry);
129 
130     FUNC_LEAVE_NOAPI(ret_value)
131 } /* end H5AC_proxy_entry_create() */
132 
133 /*-------------------------------------------------------------------------
134  * Function:    H5AC_proxy_entry_add_parent
135  *
136  * Purpose:     Add a parent to a proxy entry
137  *
138  * Return:      Non-negative on success/Negative on failure
139  *
140  * Programmer:  Quincey Koziol
141  *              September 17, 2016
142  *
143  *-------------------------------------------------------------------------
144  */
145 herr_t
H5AC_proxy_entry_add_parent(H5AC_proxy_entry_t * pentry,void * _parent)146 H5AC_proxy_entry_add_parent(H5AC_proxy_entry_t *pentry, void *_parent)
147 {
148     H5AC_info_t *parent    = (H5AC_info_t *)_parent; /* Parent entry's cache info */
149     herr_t       ret_value = SUCCEED;                /* Return value */
150 
151     FUNC_ENTER_NOAPI(FAIL)
152 
153     /* Sanity checks */
154     HDassert(parent);
155     HDassert(pentry);
156 
157     /* Add parent to the list of parents */
158     if (NULL == pentry->parents)
159         if (NULL == (pentry->parents = H5SL_create(H5SL_TYPE_HADDR, NULL)))
160             HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL,
161                         "unable to create skip list for parents of proxy entry")
162 
163     /* Insert parent address into skip list */
164     if (H5SL_insert(pentry->parents, parent, &parent->addr) < 0)
165         HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "unable to insert parent into proxy's skip list")
166 
167     /* Add flush dependency on parent */
168     if (pentry->nchildren > 0) {
169         /* Sanity check */
170         HDassert(H5F_addr_defined(pentry->addr));
171 
172         if (H5AC_create_flush_dependency(parent, pentry) < 0)
173             HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "unable to set flush dependency on proxy entry")
174     } /* end if */
175 
176 done:
177     FUNC_LEAVE_NOAPI(ret_value)
178 } /* end H5AC_proxy_entry_add_parent() */
179 
180 /*-------------------------------------------------------------------------
181  * Function:    H5AC_proxy_entry_remove_parent
182  *
183  * Purpose:     Removes a parent from a proxy entry
184  *
185  * Return:      Non-negative on success/Negative on failure
186  *
187  * Programmer:  Quincey Koziol
188  *              September 17, 2016
189  *
190  *-------------------------------------------------------------------------
191  */
192 herr_t
H5AC_proxy_entry_remove_parent(H5AC_proxy_entry_t * pentry,void * _parent)193 H5AC_proxy_entry_remove_parent(H5AC_proxy_entry_t *pentry, void *_parent)
194 {
195     H5AC_info_t *parent = (H5AC_info_t *)_parent; /* Pointer to the parent entry */
196     H5AC_info_t *rem_parent;                      /* Pointer to the removed parent entry */
197     herr_t       ret_value = SUCCEED;             /* Return value */
198 
199     FUNC_ENTER_NOAPI(FAIL)
200 
201     /* Sanity checks */
202     HDassert(pentry);
203     HDassert(pentry->parents);
204     HDassert(parent);
205 
206     /* Remove parent from skip list */
207     if (NULL == (rem_parent = (H5AC_info_t *)H5SL_remove(pentry->parents, &parent->addr)))
208         HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "unable to remove proxy entry parent from skip list")
209     if (!H5F_addr_eq(rem_parent->addr, parent->addr))
210         HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "removed proxy entry parent not the same as real parent")
211 
212     /* Shut down the skip list, if this is the last parent */
213     if (0 == H5SL_count(pentry->parents)) {
214         /* Sanity check */
215         HDassert(0 == pentry->nchildren);
216 
217         if (H5SL_close(pentry->parents) < 0)
218             HGOTO_ERROR(H5E_CACHE, H5E_CLOSEERROR, FAIL, "can't close proxy parent skip list")
219         pentry->parents = NULL;
220     } /* end if */
221 
222     /* Remove flush dependency between the proxy entry and a parent */
223     if (pentry->nchildren > 0)
224         if (H5AC_destroy_flush_dependency(parent, pentry) < 0)
225             HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "unable to remove flush dependency on proxy entry")
226 
227 done:
228     FUNC_LEAVE_NOAPI(ret_value)
229 } /* end H5AC_proxy_entry_remove_parent() */
230 
231 /*-------------------------------------------------------------------------
232  * Function:	H5AC__proxy_entry_add_child_cb
233  *
234  * Purpose:	Callback routine for adding an entry as a flush dependency for
235  *		a proxy entry.
236  *
237  * Return:	Success:	Non-negative on success
238  *		Failure:	Negative
239  *
240  * Programmer:	Quincey Koziol
241  *		Thursday, September 22, 2016
242  *
243  *-------------------------------------------------------------------------
244  */
245 static int
H5AC__proxy_entry_add_child_cb(void * _item,void H5_ATTR_UNUSED * _key,void * _udata)246 H5AC__proxy_entry_add_child_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
247 {
248     H5AC_info_t *       parent    = (H5AC_info_t *)_item;         /* Pointer to the parent entry */
249     H5AC_proxy_entry_t *pentry    = (H5AC_proxy_entry_t *)_udata; /* Pointer to the proxy entry */
250     int                 ret_value = H5_ITER_CONT;                 /* Callback return value */
251 
252     FUNC_ENTER_STATIC
253 
254     /* Add flush dependency on parent for proxy entry */
255     if (H5AC_create_flush_dependency(parent, pentry) < 0)
256         HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, H5_ITER_ERROR,
257                     "unable to set flush dependency for virtual entry")
258 
259 done:
260     FUNC_LEAVE_NOAPI(ret_value)
261 } /* end H5AC__proxy_entry_add_child_cb() */
262 
263 /*-------------------------------------------------------------------------
264  * Function:    H5AC_proxy_entry_add_child
265  *
266  * Purpose:     Add a child a proxy entry
267  *
268  * Return:      Non-negative on success/Negative on failure
269  *
270  * Programmer:  Quincey Koziol
271  *              September 17, 2016
272  *
273  *-------------------------------------------------------------------------
274  */
275 herr_t
H5AC_proxy_entry_add_child(H5AC_proxy_entry_t * pentry,H5F_t * f,void * child)276 H5AC_proxy_entry_add_child(H5AC_proxy_entry_t *pentry, H5F_t *f, void *child)
277 {
278     herr_t ret_value = SUCCEED; /* Return value */
279 
280     FUNC_ENTER_NOAPI(FAIL)
281 
282     /* Sanity checks */
283     HDassert(pentry);
284     HDassert(child);
285 
286     /* Check for first child */
287     if (0 == pentry->nchildren) {
288         /* Get an address, if the proxy doesn't already have one */
289         if (!H5F_addr_defined(pentry->addr))
290             if (HADDR_UNDEF == (pentry->addr = H5MF_alloc_tmp(f, 1)))
291                 HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL,
292                             "temporary file space allocation failed for proxy entry")
293 
294         /* Insert the proxy entry into the cache */
295         if (H5AC_insert_entry(f, H5AC_PROXY_ENTRY, pentry->addr, pentry, H5AC__PIN_ENTRY_FLAG) < 0)
296             HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "unable to cache proxy entry")
297 
298         /* Proxies start out clean (insertions are automatically marked dirty) */
299         if (H5AC_mark_entry_clean(pentry) < 0)
300             HGOTO_ERROR(H5E_CACHE, H5E_CANTCLEAN, FAIL, "can't mark proxy entry clean")
301 
302         /* Proxies start out serialized (insertions are automatically marked unserialized) */
303         if (H5AC_mark_entry_serialized(pentry) < 0)
304             HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "can't mark proxy entry clean")
305 
306         /* If there are currently parents, iterate over the list of parents, creating flush dependency on them
307          */
308         if (pentry->parents)
309             if (H5SL_iterate(pentry->parents, H5AC__proxy_entry_add_child_cb, pentry) < 0)
310                 HGOTO_ERROR(H5E_CACHE, H5E_BADITER, FAIL, "can't visit parents")
311     } /* end if */
312 
313     /* Add flush dependency on proxy entry */
314     if (H5AC_create_flush_dependency(pentry, child) < 0)
315         HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "unable to set flush dependency on proxy entry")
316 
317     /* Increment count of children */
318     pentry->nchildren++;
319 
320 done:
321     FUNC_LEAVE_NOAPI(ret_value)
322 } /* end H5AC_proxy_entry_add_child() */
323 
324 /*-------------------------------------------------------------------------
325  * Function:	H5AC__proxy_entry_remove_child_cb
326  *
327  * Purpose:	Callback routine for removing an entry as a flush dependency for
328  *		proxy entry.
329  *
330  * Return:	Success:	Non-negative on success
331  *		Failure:	Negative
332  *
333  * Programmer:	Quincey Koziol
334  *		Thursday, September 22, 2016
335  *
336  *-------------------------------------------------------------------------
337  */
338 static int
H5AC__proxy_entry_remove_child_cb(void * _item,void H5_ATTR_UNUSED * _key,void * _udata)339 H5AC__proxy_entry_remove_child_cb(void *_item, void H5_ATTR_UNUSED *_key, void *_udata)
340 {
341     H5AC_info_t *       parent    = (H5AC_info_t *)_item;         /* Pointer to the parent entry */
342     H5AC_proxy_entry_t *pentry    = (H5AC_proxy_entry_t *)_udata; /* Pointer to the proxy entry */
343     int                 ret_value = H5_ITER_CONT;                 /* Callback return value */
344 
345     FUNC_ENTER_STATIC
346 
347     /* Remove flush dependency on parent for proxy entry */
348     if (H5AC_destroy_flush_dependency(parent, pentry) < 0)
349         HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, H5_ITER_ERROR,
350                     "unable to remove flush dependency for proxy entry")
351 
352 done:
353     FUNC_LEAVE_NOAPI(ret_value)
354 } /* end H5AC__proxy_entry_remove_child_cb() */
355 
356 /*-------------------------------------------------------------------------
357  * Function:    H5AC_proxy_entry_remove_child
358  *
359  * Purpose:     Remove a child a proxy entry
360  *
361  * Return:      Non-negative on success/Negative on failure
362  *
363  * Programmer:  Quincey Koziol
364  *              September 17, 2016
365  *
366  *-------------------------------------------------------------------------
367  */
368 herr_t
H5AC_proxy_entry_remove_child(H5AC_proxy_entry_t * pentry,void * child)369 H5AC_proxy_entry_remove_child(H5AC_proxy_entry_t *pentry, void *child)
370 {
371     herr_t ret_value = SUCCEED; /* Return value */
372 
373     FUNC_ENTER_NOAPI(FAIL)
374 
375     /* Sanity checks */
376     HDassert(pentry);
377     HDassert(child);
378 
379     /* Remove flush dependency on proxy entry */
380     if (H5AC_destroy_flush_dependency(pentry, child) < 0)
381         HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "unable to remove flush dependency on proxy entry")
382 
383     /* Decrement count of children */
384     pentry->nchildren--;
385 
386     /* Check for last child */
387     if (0 == pentry->nchildren) {
388         /* Check for flush dependencies on proxy's parents */
389         if (pentry->parents)
390             /* Iterate over the list of parents, removing flush dependency on them */
391             if (H5SL_iterate(pentry->parents, H5AC__proxy_entry_remove_child_cb, pentry) < 0)
392                 HGOTO_ERROR(H5E_CACHE, H5E_BADITER, FAIL, "can't visit parents")
393 
394         /* Unpin proxy */
395         if (H5AC_unpin_entry(pentry) < 0)
396             HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPIN, FAIL, "can't unpin proxy entry")
397 
398         /* Remove proxy entry from cache */
399         if (H5AC_remove_entry(pentry) < 0)
400             HGOTO_ERROR(H5E_CACHE, H5E_CANTREMOVE, FAIL, "unable to remove proxy entry")
401     } /* end if */
402 
403 done:
404     FUNC_LEAVE_NOAPI(ret_value)
405 } /* end H5AC_proxy_entry_remove_child() */
406 
407 /*-------------------------------------------------------------------------
408  * Function:    H5AC_proxy_entry_dest
409  *
410  * Purpose:     Destroys a proxy entry in memory.
411  *
412  * Return:      Non-negative on success/Negative on failure
413  *
414  * Programmer:  Quincey Koziol
415  *              September 17, 2016
416  *
417  *-------------------------------------------------------------------------
418  */
419 herr_t
H5AC_proxy_entry_dest(H5AC_proxy_entry_t * pentry)420 H5AC_proxy_entry_dest(H5AC_proxy_entry_t *pentry)
421 {
422     herr_t ret_value = SUCCEED; /* Return value */
423 
424     FUNC_ENTER_NOAPI(FAIL)
425 
426     /* Sanity checks */
427     HDassert(pentry);
428     HDassert(NULL == pentry->parents);
429     HDassert(0 == pentry->nchildren);
430     HDassert(0 == pentry->ndirty_children);
431     HDassert(0 == pentry->nunser_children);
432 
433     /* Free the proxy entry object */
434     pentry = H5FL_FREE(H5AC_proxy_entry_t, pentry);
435 
436 done:
437     FUNC_LEAVE_NOAPI(ret_value)
438 } /* end H5AC_proxy_entry_dest() */
439 
440 /*-------------------------------------------------------------------------
441  * Function:    H5AC__proxy_entry_image_len
442  *
443  * Purpose:     Compute the size of the data structure on disk.
444  *
445  * Return:      Non-negative on success/Negative on failure
446  *
447  * Programmer:  Quincey Koziol
448  *              September 17, 2016
449  *
450  *-------------------------------------------------------------------------
451  */
452 static herr_t
H5AC__proxy_entry_image_len(const void H5_ATTR_UNUSED * thing,size_t * image_len)453 H5AC__proxy_entry_image_len(const void H5_ATTR_UNUSED *thing, size_t *image_len)
454 {
455     FUNC_ENTER_STATIC_NOERR
456 
457     /* Check arguments */
458     HDassert(image_len);
459 
460     /* Set the image length size to 1 byte */
461     *image_len = 1;
462 
463     FUNC_LEAVE_NOAPI(SUCCEED)
464 } /* end H5AC__proxy_entry_image_len() */
465 
466 /*-------------------------------------------------------------------------
467  * Function:    H5AC__proxy_entry_serialize
468  *
469  * Purpose:	Serializes a data structure for writing to disk.
470  *
471  * Note:	Should never be invoked.
472  *
473  * Return:      Non-negative on success/Negative on failure
474  *
475  * Programmer:  Quincey Koziol
476  *              September 17, 2016
477  *
478  *-------------------------------------------------------------------------
479  */
480 static herr_t
H5AC__proxy_entry_serialize(const H5F_t H5_ATTR_UNUSED * f,void H5_ATTR_UNUSED * image,size_t H5_ATTR_UNUSED len,void H5_ATTR_UNUSED * thing)481 H5AC__proxy_entry_serialize(const H5F_t H5_ATTR_UNUSED *f, void H5_ATTR_UNUSED *image,
482                             size_t H5_ATTR_UNUSED len, void H5_ATTR_UNUSED *thing)
483 {
484     FUNC_ENTER_STATIC_NOERR /* Yes, even though this pushes an error on the stack */
485 
486         /* Should never be invoked */
487         HDassert(0 && "Invalid callback?!?");
488 
489     HERROR(H5E_CACHE, H5E_CANTSERIALIZE, "called unreachable fcn.");
490 
491     FUNC_LEAVE_NOAPI(FAIL)
492 } /* end H5AC__proxy_entry_serialize() */
493 
494 /*-------------------------------------------------------------------------
495  * Function:    H5AC__proxy_entry_notify
496  *
497  * Purpose:     Handle cache action notifications
498  *
499  * Return:      Non-negative on success/Negative on failure
500  *
501  * Programmer:  Quincey Koziol
502  *              September 17, 2016
503  *
504  *-------------------------------------------------------------------------
505  */
506 static herr_t
H5AC__proxy_entry_notify(H5AC_notify_action_t action,void * _thing)507 H5AC__proxy_entry_notify(H5AC_notify_action_t action, void *_thing)
508 {
509     H5AC_proxy_entry_t *pentry    = (H5AC_proxy_entry_t *)_thing;
510     herr_t              ret_value = SUCCEED; /* Return value */
511 
512     FUNC_ENTER_STATIC
513 
514     /* Sanity check */
515     HDassert(pentry);
516 
517     switch (action) {
518         case H5AC_NOTIFY_ACTION_AFTER_INSERT:
519             break;
520 
521         case H5AC_NOTIFY_ACTION_AFTER_LOAD:
522 #ifdef NDEBUG
523             HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid notify action from metadata cache")
524 #else  /* NDEBUG */
525             HDassert(0 && "Invalid action?!?");
526 #endif /* NDEBUG */
527             break;
528 
529         case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
530 #ifdef NDEBUG
531             HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "invalid notify action from metadata cache")
532 #else  /* NDEBUG */
533             HDassert(0 && "Invalid action?!?");
534 #endif /* NDEBUG */
535             break;
536 
537         case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
538             /* Sanity checks */
539             HDassert(0 == pentry->ndirty_children);
540             HDassert(0 == pentry->nunser_children);
541 
542             /* No action */
543             break;
544 
545         case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
546             /* Sanity checks */
547             HDassert(pentry->ndirty_children > 0);
548 
549             /* No action */
550             break;
551 
552         case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
553             /* Sanity checks */
554             HDassert(0 == pentry->ndirty_children);
555 
556             /* No action */
557             break;
558 
559         case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
560             /* Increment # of dirty children */
561             pentry->ndirty_children++;
562 
563             /* Check for first dirty child */
564             if (1 == pentry->ndirty_children)
565                 if (H5AC_mark_entry_dirty(pentry) < 0)
566                     HGOTO_ERROR(H5E_CACHE, H5E_CANTDIRTY, FAIL, "can't mark proxy entry dirty")
567             break;
568 
569         case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
570             /* Sanity check */
571             HDassert(pentry->ndirty_children > 0);
572 
573             /* Decrement # of dirty children */
574             pentry->ndirty_children--;
575 
576             /* Check for last dirty child */
577             if (0 == pentry->ndirty_children)
578                 if (H5AC_mark_entry_clean(pentry) < 0)
579                     HGOTO_ERROR(H5E_CACHE, H5E_CANTCLEAN, FAIL, "can't mark proxy entry clean")
580             break;
581 
582         case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
583             /* Increment # of unserialized children */
584             pentry->nunser_children++;
585 
586             /* Check for first unserialized child */
587             if (1 == pentry->nunser_children)
588                 if (H5AC_mark_entry_unserialized(pentry) < 0)
589                     HGOTO_ERROR(H5E_CACHE, H5E_CANTUNSERIALIZE, FAIL, "can't mark proxy entry unserialized")
590             break;
591 
592         case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
593             /* Sanity check */
594             HDassert(pentry->nunser_children > 0);
595 
596             /* Decrement # of unserialized children */
597             pentry->nunser_children--;
598 
599             /* Check for last unserialized child */
600             if (0 == pentry->nunser_children)
601                 if (H5AC_mark_entry_serialized(pentry) < 0)
602                     HGOTO_ERROR(H5E_CACHE, H5E_CANTSERIALIZE, FAIL, "can't mark proxy entry serialized")
603             break;
604 
605         default:
606 #ifdef NDEBUG
607             HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "unknown notify action from metadata cache")
608 #else  /* NDEBUG */
609             HDassert(0 && "Unknown action?!?");
610 #endif /* NDEBUG */
611     }  /* end switch */
612 
613 done:
614     FUNC_LEAVE_NOAPI(ret_value)
615 } /* end H5AC__proxy_entry_notify() */
616 
617 /*-------------------------------------------------------------------------
618  * Function:	H5AC__proxy_entry_free_icr
619  *
620  * Purpose:	Destroy/release an "in core representation" of a data
621  *              structure
622  *
623  * Return:	Non-negative on success/Negative on failure
624  *
625  * Programmer:  Quincey Koziol
626  *              September 17, 2016
627  *
628  *-------------------------------------------------------------------------
629  */
630 static herr_t
H5AC__proxy_entry_free_icr(void * _thing)631 H5AC__proxy_entry_free_icr(void *_thing)
632 {
633     H5AC_proxy_entry_t *pentry    = (H5AC_proxy_entry_t *)_thing;
634     herr_t              ret_value = SUCCEED; /* Return value */
635 
636     FUNC_ENTER_STATIC
637 
638     /* Destroy the proxy entry */
639     if (H5AC_proxy_entry_dest(pentry) < 0)
640         HGOTO_ERROR(H5E_CACHE, H5E_CANTFREE, FAIL, "unable to destroy proxy entry")
641 
642 done:
643     FUNC_LEAVE_NOAPI(ret_value)
644 } /* H5AC__proxy_entry_free_icr() */
645