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://support.hdfgroup.org/ftp/HDF5/releases.  *
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:		H5Omessage.c
17  *			Dec  3 2006
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Object header message routines.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
30 
31 
32 /***********/
33 /* Headers */
34 /***********/
35 #include "H5private.h"		/* Generic Functions			*/
36 #include "H5Aprivate.h"		/* Attributes	  			*/
37 #include "H5Eprivate.h"		/* Error handling		  	*/
38 #include "H5Fprivate.h"		/* File access				*/
39 #include "H5Iprivate.h"		/* IDs			  		*/
40 #include "H5MMprivate.h"	/* Memory management			*/
41 #include "H5Opkg.h"             /* Object headers			*/
42 #include "H5SMprivate.h"        /* Shared object header messages        */
43 
44 
45 /****************/
46 /* Local Macros */
47 /****************/
48 
49 
50 /******************/
51 /* Local Typedefs */
52 /******************/
53 
54 /* User data for iteration while removing a message */
55 typedef struct {
56     H5F_t      *f;              /* Pointer to file for insertion */
57     hid_t dxpl_id;              /* DXPL during iteration */
58     int sequence;               /* Sequence # to search for */
59     unsigned nfailed;           /* # of failed message removals */
60     H5O_operator_t op;          /* Callback routine for removal operations */
61     void *op_data;              /* Callback data for removal operations */
62     hbool_t adj_link;           /* Whether to adjust links when removing messages */
63 } H5O_iter_rm_t;
64 
65 
66 /********************/
67 /* Package Typedefs */
68 /********************/
69 
70 
71 /********************/
72 /* Local Prototypes */
73 /********************/
74 
75 static herr_t H5O__msg_reset_real(const H5O_msg_class_t *type, void *native);
76 static herr_t H5O__msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
77     unsigned sequence, unsigned *oh_modified, void *_udata/*in,out*/);
78 static herr_t H5O__copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t idx,
79     const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
80     unsigned update_flags);
81 
82 
83 /*********************/
84 /* Package Variables */
85 /*********************/
86 
87 
88 /*****************************/
89 /* Library Private Variables */
90 /*****************************/
91 
92 
93 /*******************/
94 /* Local Variables */
95 /*******************/
96 
97 
98 
99 /*-------------------------------------------------------------------------
100  * Function:	H5O_msg_create
101  *
102  * Purpose:	Create a new object header message
103  *
104  * Return:	Success:	Non-negative
105  *
106  *		Failure:	Negative
107  *
108  * Programmer:	Quincey Koziol
109  *		koziol@hdfgroup.org
110  *		Dec  1 2006
111  *
112  *-------------------------------------------------------------------------
113  */
114 herr_t
H5O_msg_create(const H5O_loc_t * loc,unsigned type_id,unsigned mesg_flags,unsigned update_flags,void * mesg,hid_t dxpl_id)115 H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
116     unsigned update_flags, void *mesg, hid_t dxpl_id)
117 {
118     H5O_t *oh = NULL;                   /* Object header */
119     herr_t ret_value = SUCCEED;         /* Return value */
120 
121     FUNC_ENTER_NOAPI(FAIL)
122 
123     /* check args */
124     HDassert(loc);
125     HDassert(type_id < NELMTS(H5O_msg_class_g));
126     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
127     HDassert(mesg);
128 
129     /* Pin the object header */
130     if(NULL == (oh = H5O_pin(loc, dxpl_id)))
131 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
132 
133     /* Go append message to object header */
134     if(H5O_msg_append_oh(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0)
135 	HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header")
136 
137 done:
138     if(oh && H5O_unpin(oh) < 0)
139         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
140 
141     FUNC_LEAVE_NOAPI(ret_value)
142 } /* end H5O_msg_create() */
143 
144 
145 /*-------------------------------------------------------------------------
146  * Function:	H5O_msg_append_oh
147  *
148  * Purpose:	Simplified version of H5O_msg_create, used when creating a new
149  *              object header message (usually during object creation) and
150  *              several messages will be added to the object header at once.
151  *
152  * Return:	Success:	Non-negative
153  *
154  *		Failure:	Negative
155  *
156  * Programmer:	Quincey Koziol
157  *		koziol@ncsa.uiuc.edu
158  *		Dec 31 2002
159  *
160  *-------------------------------------------------------------------------
161  */
162 herr_t
H5O_msg_append_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh,unsigned type_id,unsigned mesg_flags,unsigned update_flags,void * mesg)163 H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
164     unsigned mesg_flags, unsigned update_flags, void *mesg)
165 {
166     const H5O_msg_class_t *type;        /* Original H5O class type for the ID */
167     herr_t ret_value = SUCCEED;         /* Return value */
168 
169     FUNC_ENTER_NOAPI(FAIL)
170 
171     /* check args */
172     HDassert(f);
173     HDassert(oh);
174     HDassert(H5O_ATTR_ID != type_id);   /* Attributes are modified in another routine */
175     HDassert(type_id < NELMTS(H5O_msg_class_g));
176     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
177     HDassert(type);
178     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
179     HDassert(mesg);
180 
181     /* Append new message to object header */
182     if(H5O_msg_append_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
183         HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new message in header")
184 
185 done:
186     FUNC_LEAVE_NOAPI(ret_value)
187 } /* end H5O_msg_append_oh() */
188 
189 
190 /*-------------------------------------------------------------------------
191  * Function:	H5O_msg_append_real
192  *
193  * Purpose:	Append a new message to an object header.
194  *
195  * Return:	Success:	Non-negative
196  *
197  *		Failure:	Negative
198  *
199  * Programmer:	Quincey Koziol
200  *		koziol@hdfgroup.org
201  *		Dec  8 2006
202  *
203  *-------------------------------------------------------------------------
204  */
205 herr_t
H5O_msg_append_real(H5F_t * f,hid_t dxpl_id,H5O_t * oh,const H5O_msg_class_t * type,unsigned mesg_flags,unsigned update_flags,void * mesg)206 H5O_msg_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
207     unsigned mesg_flags, unsigned update_flags, void *mesg)
208 {
209     size_t idx;                         /* Index of message to modify */
210     herr_t ret_value = SUCCEED;         /* Return value */
211 
212     FUNC_ENTER_NOAPI(FAIL)
213 
214     /* check args */
215     HDassert(f);
216     HDassert(oh);
217     HDassert(type);
218     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
219     HDassert(mesg);
220 
221     /* Allocate space for a new message */
222     if(H5O_msg_alloc(f, dxpl_id, oh, type, &mesg_flags, mesg, &idx) < 0)
223         HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message")
224 
225     /* Copy the information for the message */
226     if(H5O__copy_mesg(f, dxpl_id, oh, idx, type, mesg, mesg_flags, update_flags) < 0)
227         HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to write message")
228 #ifdef H5O_DEBUG
229 H5O_assert(oh);
230 #endif /* H5O_DEBUG */
231 
232 done:
233     FUNC_LEAVE_NOAPI(ret_value)
234 } /* end H5O_msg_append_real() */
235 
236 
237 /*-------------------------------------------------------------------------
238  * Function:	H5O_msg_write
239  *
240  * Purpose:	Modifies an existing message or creates a new message.
241  *
242  *              The UPDATE_FLAGS argument are flags that allow the caller
243  *              to skip updating the modification time or reseting the message
244  *              data.  This is useful when several calls to H5O_msg_write will be
245  *              made in a sequence.
246  *
247  * Return:	Success:	Non-negative
248  *
249  *		Failure:	Negative
250  *
251  * Programmer:	Robb Matzke
252  *		matzke@llnl.gov
253  *		Aug  6 1997
254  *
255  *-------------------------------------------------------------------------
256  */
257 herr_t
H5O_msg_write(const H5O_loc_t * loc,unsigned type_id,unsigned mesg_flags,unsigned update_flags,void * mesg,hid_t dxpl_id)258 H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
259     unsigned update_flags, void *mesg, hid_t dxpl_id)
260 {
261     H5O_t *oh = NULL;                   /* Object header to use */
262     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
263     herr_t ret_value = SUCCEED;         /* Return value */
264 
265     FUNC_ENTER_NOAPI(FAIL)
266 
267     /* check args */
268     HDassert(loc);
269     HDassert(loc->file);
270     HDassert(H5F_addr_defined(loc->addr));
271     HDassert(H5O_ATTR_ID != type_id);   /* Attributes are modified in another routine */
272     HDassert(type_id < NELMTS(H5O_msg_class_g));
273     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
274     HDassert(type);
275     HDassert(mesg);
276     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
277 
278     /* Pin the object header */
279     if(NULL == (oh = H5O_pin(loc, dxpl_id)))
280 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
281 
282     /* Call the "real" modify routine */
283     if(H5O_msg_write_real(loc->file, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
284         HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
285 
286 done:
287     if(oh && H5O_unpin(oh) < 0)
288         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
289 
290     FUNC_LEAVE_NOAPI(ret_value)
291 } /* end H5O_msg_write() */
292 
293 
294 /*-------------------------------------------------------------------------
295  * Function:	H5O_msg_write_oh
296  *
297  * Purpose:	Modifies an existing message or creates a new message.
298  *
299  *              The UPDATE_FLAGS argument are flags that allow the caller
300  *              to skip updating the modification time or reseting the message
301  *              data.  This is useful when several calls to H5O_msg_write will be
302  *              made in a sequence.
303  *
304  * Return:	Success:	Non-negative
305  *		Failure:	Negative
306  *
307  * Programmer:	Quincey Koziol
308  *		koziol@hdfgroup.org
309  *		Dec  6 2007
310  *
311  *-------------------------------------------------------------------------
312  */
313 herr_t
H5O_msg_write_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh,unsigned type_id,unsigned mesg_flags,unsigned update_flags,void * mesg)314 H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
315     unsigned mesg_flags, unsigned update_flags, void *mesg)
316 {
317     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
318     herr_t ret_value = SUCCEED;         /* Return value */
319 
320     FUNC_ENTER_NOAPI_TAG(dxpl_id, oh->cache_info.addr, FAIL)
321 
322     /* check args */
323     HDassert(f);
324     HDassert(oh);
325     HDassert(H5O_ATTR_ID != type_id);   /* Attributes are modified in another routine */
326     HDassert(type_id < NELMTS(H5O_msg_class_g));
327     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
328     HDassert(type);
329     HDassert(mesg);
330     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
331 
332     /* Call the "real" modify routine */
333     if(H5O_msg_write_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
334         HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
335 
336 done:
337     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
338 } /* end H5O_msg_write_oh() */
339 
340 
341 /*-------------------------------------------------------------------------
342  * Function:	H5O_msg_write_real
343  *
344  * Purpose:	Modifies an existing message or creates a new message.
345  *
346  *              The UPDATE_FLAGS argument are flags that allow the caller
347  *              to skip updating the modification time or reseting the message
348  *              data.  This is useful when several calls to H5O_msg_write will be
349  *              made in a sequence.
350  *
351  * Return:	Success:	Non-negative
352  *
353  *		Failure:	Negative
354  *
355  * Programmer:	Robb Matzke
356  *		matzke@llnl.gov
357  *		Aug  6 1997
358  *
359  *-------------------------------------------------------------------------
360  */
361 herr_t
H5O_msg_write_real(H5F_t * f,hid_t dxpl_id,H5O_t * oh,const H5O_msg_class_t * type,unsigned mesg_flags,unsigned update_flags,void * mesg)362 H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
363     unsigned mesg_flags, unsigned update_flags, void *mesg)
364 {
365     H5O_mesg_t         *idx_msg;        /* Pointer to message to modify */
366     size_t		idx;            /* Index of message to modify */
367     herr_t	        ret_value = SUCCEED;    /* Return value */
368 
369     FUNC_ENTER_NOAPI_NOINIT
370 
371     /* check args */
372     HDassert(f);
373     HDassert(oh);
374     HDassert(type);
375     HDassert(type != H5O_MSG_ATTR);
376     HDassert(mesg);
377     HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
378 
379     /* Locate message of correct type */
380     for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
381 	if(type == idx_msg->type)
382             break;
383     if(idx == oh->nmesgs)
384         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
385 
386     /* Check for modifying a constant message */
387     if(!(update_flags & H5O_UPDATE_FORCE) && (idx_msg->flags & H5O_MSG_FLAG_CONSTANT))
388 	HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
389     /* This message is shared, but it's being modified. */
390     else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
391         htri_t status;              /* Status of "try share" call */
392 
393          /* First, sanity check to make sure it's not a committed message;
394           *     these can't ever be modified.
395           */
396         HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED);
397 
398         /* Also, sanity check that a message doesn't switch status from being
399          *      shared (or sharable) to being unsharable.  (Which could cause
400          *      a message to increase in size in the object header)
401          */
402         HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE));
403 
404         /* Remove the old message from the SOHM index */
405         /* (It would be more efficient to try to share the message first, then
406          *      delete it (avoiding thrashing the index in the case the ref.
407          *      count on the message is one), but this causes problems when
408          *      the location of the object changes (from in another object's
409          *      header to the SOHM heap), so just delete it first -QAK)
410          */
411         if(H5SM_delete(f, dxpl_id, oh, (H5O_shared_t *)idx_msg->native) < 0)
412             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index")
413 
414         /* If we're replacing a shared message, the new message must be shared
415          * (or else it may increase in size!), so pass in NULL for the OH
416          * location.
417          *
418          * XXX: This doesn't handle freeing extra space in object header from
419          *      a message shrinking.
420          */
421         if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), 0, idx_msg->type->id, mesg, &mesg_flags)) < 0)
422             HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message")
423         if(status == FALSE && (mesg_flags & H5O_MSG_FLAG_SHARED))
424             HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status")
425     } /* end if */
426 
427     /* Copy the information for the message */
428     if(H5O__copy_mesg(f, dxpl_id, oh, idx, type, mesg, mesg_flags, update_flags) < 0)
429         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message")
430 #ifdef H5O_DEBUG
431 H5O_assert(oh);
432 #endif /* H5O_DEBUG */
433 
434 done:
435     FUNC_LEAVE_NOAPI(ret_value)
436 } /* end H5O_msg_write_real() */
437 
438 
439 /*-------------------------------------------------------------------------
440  * Function:	H5O_msg_read
441  *
442  * Purpose:	Reads a message from an object header and returns a pointer
443  *		to it.	The caller will usually supply the memory through
444  *		MESG and the return value will be MESG.	 But if MESG is
445  *		the null pointer, then this function will malloc() memory
446  *		to hold the result and return its pointer instead.
447  *
448  * Return:	Success:	Ptr to message in native format.  The message
449  *				should be freed by calling H5O_msg_reset().  If
450  *				MESG is a null pointer then the caller should
451  *				also call H5MM_xfree() on the return value
452  *				after calling H5O_msg_reset().
453  *
454  *		Failure:	NULL
455  *
456  * Programmer:	Robb Matzke
457  *		matzke@llnl.gov
458  *		Aug  6 1997
459  *
460  *-------------------------------------------------------------------------
461  */
462 void *
H5O_msg_read(const H5O_loc_t * loc,unsigned type_id,void * mesg,hid_t dxpl_id)463 H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
464     hid_t dxpl_id)
465 {
466     H5O_t *oh = NULL;                   /* Object header to use */
467     void *ret_value = NULL;             /* Return value */
468 
469     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, NULL)
470 
471     /* check args */
472     HDassert(loc);
473     HDassert(loc->file);
474     HDassert(H5F_addr_defined(loc->addr));
475     HDassert(type_id < NELMTS(H5O_msg_class_g));
476 
477     /* Get the object header */
478     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
479 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
480 
481     /* Call the "real" read routine */
482     if(NULL == (ret_value = H5O_msg_read_oh(loc->file, dxpl_id, oh, type_id, mesg)))
483 	HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header message")
484 
485 done:
486     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
487 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
488 
489     FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
490 } /* end H5O_msg_read() */
491 
492 
493 /*-------------------------------------------------------------------------
494  * Function:	H5O_msg_read_oh
495  *
496  * Purpose:	Reads a message from an object header and returns a pointer
497  *		to it.	The caller will usually supply the memory through
498  *		MESG and the return value will be MESG.	 But if MESG is
499  *		the null pointer, then this function will malloc() memory
500  *		to hold the result and return its pointer instead.
501  *
502  * Return:	Success:	Ptr to message in native format.  The message
503  *				should be freed by calling H5O_msg_reset().  If
504  *				MESG is a null pointer then the caller should
505  *				also call H5MM_xfree() on the return value
506  *				after calling H5O_msg_reset().
507  *
508  *		Failure:	NULL
509  *
510  * Programmer:	Robb Matzke
511  *		matzke@llnl.gov
512  *		Aug  6 1997
513  *
514  *-------------------------------------------------------------------------
515  */
516 void *
H5O_msg_read_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh,unsigned type_id,void * mesg)517 H5O_msg_read_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
518     void *mesg)
519 {
520     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
521     unsigned       idx;                 /* Message's index in object header */
522     void           *ret_value = NULL;
523 
524     FUNC_ENTER_NOAPI_NOINIT
525 
526     /* check args */
527     HDassert(f);
528     HDassert(oh);
529     HDassert(type_id < NELMTS(H5O_msg_class_g));
530     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
531     HDassert(type);
532 
533     /* Scan through the messages looking for the right one */
534     for(idx = 0; idx < oh->nmesgs; idx++)
535 	if(type == oh->mesg[idx].type)
536             break;
537     if(idx == oh->nmesgs)
538         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "message type not found")
539 
540     /*
541      * Decode the message if necessary.  If the message is shared then retrieve
542      * native message through the shared interface.
543      */
544     H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, &(oh->mesg[idx]), NULL)
545 
546     /*
547      * The object header caches the native message (along with
548      * the raw message) so we must copy the native message before
549      * returning.
550      */
551     if(NULL == (ret_value = (type->copy)(oh->mesg[idx].native, mesg)))
552         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space")
553 
554 done:
555     FUNC_LEAVE_NOAPI(ret_value)
556 } /* end H5O_msg_read_oh() */
557 
558 
559 /*-------------------------------------------------------------------------
560  * Function:	H5O_msg_reset
561  *
562  * Purpose:	Some message data structures have internal fields that
563  *		need to be freed.  This function does that if appropriate
564  *		but doesn't free NATIVE.
565  *
566  * Return:	Non-negative on success/Negative on failure
567  *
568  * Programmer:	Robb Matzke
569  *		matzke@llnl.gov
570  *		Aug 12 1997
571  *
572  *-------------------------------------------------------------------------
573  */
574 herr_t
H5O_msg_reset(unsigned type_id,void * native)575 H5O_msg_reset(unsigned type_id, void *native)
576 {
577     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
578     herr_t ret_value = SUCCEED;         /* Return value */
579 
580     FUNC_ENTER_NOAPI(FAIL)
581 
582     /* check args */
583     HDassert(type_id < NELMTS(H5O_msg_class_g));
584     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
585     HDassert(type);
586 
587     /* Call the "real" reset routine */
588     if(H5O__msg_reset_real(type, native) < 0)
589 	HGOTO_ERROR(H5E_OHDR, H5E_CANTRESET, FAIL, "unable to reset object header")
590 
591 done:
592     FUNC_LEAVE_NOAPI(ret_value)
593 } /* end H5O_msg_reset() */
594 
595 
596 /*-------------------------------------------------------------------------
597  * Function:	H5O__msg_reset_real
598  *
599  * Purpose:	Some message data structures have internal fields that
600  *		need to be freed.  This function does that if appropriate
601  *		but doesn't free NATIVE.
602  *
603  * Return:	Non-negative on success/Negative on failure
604  *
605  * Programmer:	Robb Matzke
606  *		matzke@llnl.gov
607  *		Aug 12 1997
608  *
609  *-------------------------------------------------------------------------
610  */
611 static herr_t
H5O__msg_reset_real(const H5O_msg_class_t * type,void * native)612 H5O__msg_reset_real(const H5O_msg_class_t *type, void *native)
613 {
614     herr_t      ret_value = SUCCEED;       /* Return value */
615 
616     FUNC_ENTER_STATIC
617 
618     /* check args */
619     HDassert(type);
620 
621     if(native) {
622 	if(type->reset) {
623 	    if((type->reset)(native) < 0)
624 		HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "reset method failed")
625 	} /* end if */
626         else
627 	    HDmemset(native, 0, type->native_size);
628     } /* end if */
629 
630 done:
631     FUNC_LEAVE_NOAPI(ret_value)
632 } /* end H5O__msg_reset_real() */
633 
634 
635 /*-------------------------------------------------------------------------
636  * Function:	H5O_msg_free
637  *
638  * Purpose:	Similar to H5O_msg_reset() except it also frees the message
639  *		pointer.
640  *
641  * Return:	Success:	NULL
642  *
643  *		Failure:	NULL
644  *
645  * Programmer:	Robb Matzke
646  *              Thursday, May 21, 1998
647  *
648  *-------------------------------------------------------------------------
649  */
650 void *
H5O_msg_free(unsigned type_id,void * mesg)651 H5O_msg_free(unsigned type_id, void *mesg)
652 {
653     const H5O_msg_class_t *type;            /* Actual H5O class type for the ID */
654     void *ret_value = NULL;             /* Return value */
655 
656     FUNC_ENTER_NOAPI_NOINIT_NOERR
657 
658     /* check args */
659     HDassert(type_id < NELMTS(H5O_msg_class_g));
660     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
661     HDassert(type);
662 
663     /* Call the "real" free routine */
664     ret_value = H5O_msg_free_real(type, mesg);
665 
666     FUNC_LEAVE_NOAPI(ret_value)
667 } /* end H5O_msg_free() */
668 
669 
670 /*-------------------------------------------------------------------------
671  * Function:	H5O_msg_free_mesg
672  *
673  * Purpose:	Call H5O_msg_free_real() on a message.
674  *
675  * Return:	Non-negative on success/Negative on failure
676  *
677  * Programmer:	Quincey Koziol
678  *              Tuesday, Sep  6, 2005
679  *
680  *-------------------------------------------------------------------------
681  */
682 herr_t
H5O_msg_free_mesg(H5O_mesg_t * mesg)683 H5O_msg_free_mesg(H5O_mesg_t *mesg)
684 {
685     FUNC_ENTER_NOAPI_NOINIT_NOERR
686 
687     /* check args */
688     HDassert(mesg);
689 
690     /* Free any native information */
691     mesg->native = H5O_msg_free_real(mesg->type, mesg->native);
692 
693     FUNC_LEAVE_NOAPI(SUCCEED)
694 } /* end H5O_msg_free_mesg() */
695 
696 
697 /*-------------------------------------------------------------------------
698  * Function:	H5O_msg_free_real
699  *
700  * Purpose:	Similar to H5O_msg_reset() except it also frees the message
701  *		pointer.
702  *
703  * Return:	Success:	NULL
704  *
705  *		Failure:	NULL
706  *
707  * Programmer:	Robb Matzke
708  *              Thursday, May 21, 1998
709  *
710  *-------------------------------------------------------------------------
711  */
712 void *
H5O_msg_free_real(const H5O_msg_class_t * type,void * msg_native)713 H5O_msg_free_real(const H5O_msg_class_t *type, void *msg_native)
714 {
715     FUNC_ENTER_NOAPI_NOINIT_NOERR
716 
717     /* check args */
718     HDassert(type);
719 
720     if(msg_native) {
721         H5O__msg_reset_real(type, msg_native);
722         if(NULL != (type->free))
723             (type->free)(msg_native);
724         else
725             H5MM_xfree(msg_native);
726     } /* end if */
727 
728     FUNC_LEAVE_NOAPI(NULL)
729 } /* end H5O_msg_free_real() */
730 
731 
732 /*-------------------------------------------------------------------------
733  * Function:	H5O_msg_copy
734  *
735  * Purpose:	Copies a message.  If MESG is is the null pointer then a null
736  *		pointer is returned with no error.
737  *
738  * Return:	Success:	Ptr to the new message
739  *
740  *		Failure:	NULL
741  *
742  * Programmer:	Robb Matzke
743  *              Thursday, May 21, 1998
744  *
745  *-------------------------------------------------------------------------
746  */
747 void *
H5O_msg_copy(unsigned type_id,const void * mesg,void * dst)748 H5O_msg_copy(unsigned type_id, const void *mesg, void *dst)
749 {
750     const H5O_msg_class_t *type;            /* Actual H5O class type for the ID */
751     void *ret_value = NULL;             /* Return value */
752 
753     FUNC_ENTER_NOAPI(NULL)
754 
755     /* check args */
756     HDassert(mesg);
757     HDassert(type_id < NELMTS(H5O_msg_class_g));
758     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
759     HDassert(type);
760 
761     /* Call the message class's copy routine */
762     if(NULL == (ret_value = (type->copy)(mesg, dst)))
763         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message")
764 
765 done:
766     FUNC_LEAVE_NOAPI(ret_value)
767 } /* end H5O_msg_copy() */
768 
769 
770 /*-------------------------------------------------------------------------
771  * Function:	H5O_msg_count
772  *
773  * Purpose:	Counts the number of messages in an object header which are a
774  *		certain type.
775  *
776  * Return:	Success:	Number of messages of specified type.
777  *
778  *		Failure:	Negative
779  *
780  * Programmer:	Robb Matzke
781  *              Tuesday, April 21, 1998
782  *
783  *-------------------------------------------------------------------------
784  */
785 int
H5O_msg_count(const H5O_loc_t * loc,unsigned type_id,hid_t dxpl_id)786 H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
787 {
788     H5O_t *oh = NULL;           /* Object header to operate on */
789     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
790     unsigned msg_count;         /* Message count */
791     int	ret_value = FAIL;       /* Return value */
792 
793     FUNC_ENTER_NOAPI(FAIL)
794 
795     /* Check args */
796     HDassert(loc);
797     HDassert(loc->file);
798     HDassert(H5F_addr_defined(loc->addr));
799     HDassert(type_id < NELMTS(H5O_msg_class_g));
800     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
801     HDassert(type);
802 
803     /* Load the object header */
804     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
805 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
806 
807     /* Count the messages of the correct type */
808     msg_count = H5O_msg_count_real(oh, type);
809     H5_CHECKED_ASSIGN(ret_value, int, msg_count, unsigned);
810 
811 done:
812     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
813 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
814 
815     FUNC_LEAVE_NOAPI(ret_value)
816 } /* end H5O_msg_count() */
817 
818 
819 /*-------------------------------------------------------------------------
820  * Function:	H5O_msg_count_real
821  *
822  * Purpose:	Counts the number of messages in an object header which are a
823  *		certain type.
824  *
825  * Return:	Success:	Number of messages of specified type.
826  *
827  *		Failure:	(can't fail)
828  *
829  * Programmer:	Quincey Koziol
830  *              Tuesday, February  6, 2007
831  *
832  *-------------------------------------------------------------------------
833  */
834 unsigned
H5O_msg_count_real(const H5O_t * oh,const H5O_msg_class_t * type)835 H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type)
836 {
837     unsigned u;                 /* Local index variable */
838     unsigned ret_value = 0;     /* Return value */
839 
840     FUNC_ENTER_NOAPI_NOINIT_NOERR
841 
842     /* Check args */
843     HDassert(oh);
844     HDassert(type);
845 
846     /* Loop over all messages, counting the ones of the type looked for */
847     for(u = ret_value = 0; u < oh->nmesgs; u++)
848 	if(oh->mesg[u].type == type)
849             ret_value++;
850 
851     FUNC_LEAVE_NOAPI(ret_value)
852 } /* end H5O_msg_count_real() */
853 
854 
855 /*-------------------------------------------------------------------------
856  * Function:	H5O_msg_exists
857  *
858  * Purpose:	Determines if a particular message exists in an object
859  *		header without trying to decode the message.
860  *
861  * Return:	Success:	FALSE if the message does not exist; TRUE if
862  *				th message exists.
863  *
864  *		Failure:	FAIL if the existence of the message could
865  *				not be determined due to some error such as
866  *				not being able to read the object header.
867  *
868  * Programmer:	Robb Matzke
869  *              Monday, November  2, 1998
870  *
871  *-------------------------------------------------------------------------
872  */
873 htri_t
H5O_msg_exists(const H5O_loc_t * loc,unsigned type_id,hid_t dxpl_id)874 H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
875 {
876     H5O_t	*oh = NULL;             /* Object header for location */
877     htri_t      ret_value = FAIL;       /* Return value */
878 
879     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
880 
881     HDassert(loc);
882     HDassert(loc->file);
883     HDassert(type_id < NELMTS(H5O_msg_class_g));
884 
885     /* Load the object header */
886     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
887 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
888 
889     /* Call the "real" exists routine */
890     if((ret_value = H5O_msg_exists_oh(oh, type_id)) < 0)
891 	HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to verify object header message")
892 
893 done:
894     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
895 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
896 
897     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
898 } /* end H5O_msg_exists() */
899 
900 
901 /*-------------------------------------------------------------------------
902  * Function:	H5O_msg_exists_oh
903  *
904  * Purpose:	Determines if a particular message exists in an object
905  *		header without trying to decode the message.
906  *
907  * Return:	Success:	FALSE if the message does not exist; TRUE if
908  *				th message exists.
909  *
910  *		Failure:	FAIL if the existence of the message could
911  *				not be determined due to some error such as
912  *				not being able to read the object header.
913  *
914  * Programmer:	Robb Matzke
915  *              Monday, November  2, 1998
916  *
917  *-------------------------------------------------------------------------
918  */
919 htri_t
H5O_msg_exists_oh(const H5O_t * oh,unsigned type_id)920 H5O_msg_exists_oh(const H5O_t *oh, unsigned type_id)
921 {
922     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
923     unsigned	u;                      /* Local index variable */
924     htri_t      ret_value = FALSE;      /* Return value */
925 
926     FUNC_ENTER_NOAPI_NOINIT_NOERR
927 
928     HDassert(oh);
929     HDassert(type_id < NELMTS(H5O_msg_class_g));
930     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
931     HDassert(type);
932 
933     /* Scan through the messages looking for the right one */
934     for(u = 0; u < oh->nmesgs; u++)
935 	if(type == oh->mesg[u].type)
936             HGOTO_DONE(TRUE)
937 
938 done:
939     FUNC_LEAVE_NOAPI(ret_value)
940 } /* end H5O_msg_exists_oh() */
941 
942 
943 /*-------------------------------------------------------------------------
944  * Function:	H5O_msg_remove
945  *
946  * Purpose:	Removes the specified message from the object header.
947  *		If sequence is H5O_ALL (-1) then all messages of the
948  *		specified type are removed.  Removing a message causes
949  *		the sequence numbers to change for subsequent messages of
950  *		the same type.
951  *
952  *		No attempt is made to join adjacent free areas of the
953  *		object header into a single larger free area.
954  *
955  * Return:	Non-negative on success/Negative on failure
956  *
957  * Programmer:	Robb Matzke
958  *		matzke@llnl.gov
959  *		Aug 28 1997
960  *
961  *-------------------------------------------------------------------------
962  */
963 herr_t
H5O_msg_remove(const H5O_loc_t * loc,unsigned type_id,int sequence,hbool_t adj_link,hid_t dxpl_id)964 H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link,
965     hid_t dxpl_id)
966 {
967     H5O_t *oh = NULL;                   /* Pointer to actual object header */
968     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
969     herr_t ret_value = FAIL;            /* Return value */
970 
971     FUNC_ENTER_NOAPI(FAIL)
972 
973     /* check args */
974     HDassert(loc);
975     HDassert(loc->file);
976     HDassert(H5F_addr_defined(loc->addr));
977     HDassert(H5O_ATTR_ID != type_id);   /* Attributes are modified in another routine */
978     HDassert(type_id < NELMTS(H5O_msg_class_g));
979     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
980     HDassert(type);
981 
982     /* Pin the object header */
983     if(NULL == (oh = H5O_pin(loc, dxpl_id)))
984 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
985 
986     /* Call the "real" remove routine */
987     if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0)
988 	HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
989 
990 done:
991     if(oh && H5O_unpin(oh) < 0)
992         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
993 
994     FUNC_LEAVE_NOAPI(ret_value)
995 } /* end H5O_msg_remove() */
996 
997 
998 /*-------------------------------------------------------------------------
999  * Function:	H5O_msg_remove_op
1000  *
1001  * Purpose:	Removes messages from the object header that a callback
1002  *              routine indicates should be removed.
1003  *
1004  *		No attempt is made to join adjacent free areas of the
1005  *		object header into a single larger free area.
1006  *
1007  * Return:	Non-negative on success/Negative on failure
1008  *
1009  * Programmer:	Quincey Koziol
1010  *		koziol@ncsa.uiuc.edu
1011  *		Sep  6 2005
1012  *
1013  *-------------------------------------------------------------------------
1014  */
1015 herr_t
H5O_msg_remove_op(const H5O_loc_t * loc,unsigned type_id,int sequence,H5O_operator_t op,void * op_data,hbool_t adj_link,hid_t dxpl_id)1016 H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
1017     H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id)
1018 {
1019     H5O_t *oh = NULL;                   /* Pointer to actual object header */
1020     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
1021     herr_t ret_value = FAIL;            /* Return value */
1022 
1023     FUNC_ENTER_NOAPI(FAIL)
1024 
1025     /* check args */
1026     HDassert(loc);
1027     HDassert(loc->file);
1028     HDassert(H5F_addr_defined(loc->addr));
1029     HDassert(H5O_ATTR_ID != type_id);   /* Attributes are modified in another routine */
1030     HDassert(type_id < NELMTS(H5O_msg_class_g));
1031     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1032     HDassert(type);
1033 
1034     /* Pin the object header */
1035     if(NULL == (oh = H5O_pin(loc, dxpl_id)))
1036 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
1037 
1038     /* Call the "real" remove routine */
1039     if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, op, op_data, adj_link, dxpl_id)) < 0)
1040 	HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
1041 
1042 done:
1043     if(oh && H5O_unpin(oh) < 0)
1044         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1045 
1046     FUNC_LEAVE_NOAPI(ret_value)
1047 } /* end H5O_msg_remove_op() */
1048 
1049 
1050 /*-------------------------------------------------------------------------
1051  * Function:	H5O__msg_remove_cb
1052  *
1053  * Purpose:	Object header iterator callback routine to remove messages
1054  *              of a particular type that match a particular sequence number,
1055  *              or all messages if the sequence number is H5O_ALL (-1).
1056  *
1057  * Return:	Non-negative on success/Negative on failure
1058  *
1059  * Programmer:	Quincey Koziol
1060  *		koziol@ncsa.uiuc.edu
1061  *		Sep  6 2005
1062  *
1063  *-------------------------------------------------------------------------
1064  */
1065 static herr_t
H5O__msg_remove_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned sequence,unsigned * oh_modified,void * _udata)1066 H5O__msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
1067     unsigned *oh_modified, void *_udata/*in,out*/)
1068 {
1069     H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata;   /* Operator user data */
1070     htri_t try_remove = FALSE;         /* Whether to try removing a message */
1071     herr_t ret_value = H5_ITER_CONT;   /* Return value */
1072 
1073     FUNC_ENTER_STATIC
1074 
1075     /* check args */
1076     HDassert(mesg);
1077 
1078     /* Check for callback routine */
1079     if(udata->op) {
1080         /* Call the iterator callback */
1081         if((try_remove = (udata->op)(mesg->native, sequence, udata->op_data)) < 0)
1082             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "object header message deletion callback failed")
1083     } /* end if */
1084     else {
1085         /* If there's no callback routine, does the sequence # match? */
1086         if((int)sequence == udata->sequence || H5O_ALL == udata->sequence)
1087             try_remove = TRUE;
1088     } /* end else */
1089 
1090     /* Try removing the message, if indicated */
1091     if(try_remove) {
1092         /*
1093          * Keep track of how many times we failed trying to remove constant
1094          * messages.
1095          * (OK to remove constant messages - QAK)
1096          */
1097         /* Convert message into a null message */
1098         if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, udata->adj_link) < 0)
1099             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release message")
1100 
1101         /* Indicate that the object header was modified */
1102         *oh_modified = H5O_MODIFY_CONDENSE;
1103 
1104         /* Break out now, if we've found the correct message */
1105         if(udata->sequence == H5O_FIRST || udata->sequence != H5O_ALL)
1106             HGOTO_DONE(H5_ITER_STOP)
1107     } /* end if */
1108 
1109 done:
1110     FUNC_LEAVE_NOAPI(ret_value)
1111 } /* end H5O__msg_remove_cb() */
1112 
1113 
1114 /*-------------------------------------------------------------------------
1115  * Function:	H5O_msg_remove_real
1116  *
1117  * Purpose:	Removes the specified message from the object header.
1118  *		If sequence is H5O_ALL (-1) then all messages of the
1119  *		specified type are removed.  Removing a message causes
1120  *		the sequence numbers to change for subsequent messages of
1121  *		the same type.
1122  *
1123  * Return:	Non-negative on success/Negative on failure
1124  *
1125  * Programmer:	Robb Matzke
1126  *		matzke@llnl.gov
1127  *		Aug 28 1997
1128  *
1129  *-------------------------------------------------------------------------
1130  */
1131 herr_t
H5O_msg_remove_real(H5F_t * f,H5O_t * oh,const H5O_msg_class_t * type,int sequence,H5O_operator_t app_op,void * op_data,hbool_t adj_link,hid_t dxpl_id)1132 H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
1133     int sequence, H5O_operator_t app_op, void *op_data, hbool_t adj_link,
1134     hid_t dxpl_id)
1135 {
1136     H5O_iter_rm_t udata;                /* User data for iterator */
1137     H5O_mesg_operator_t op;             /* Wrapper for operator */
1138     herr_t ret_value = SUCCEED;         /* Return value */
1139 
1140     FUNC_ENTER_NOAPI(FAIL)
1141 
1142     /* check args */
1143     HDassert(f);
1144     HDassert(oh);
1145     HDassert(type);
1146 
1147     /* Make certain we are allowed to modify the file */
1148     if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
1149 	HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
1150 
1151     /* Set up iterator operator data */
1152     udata.f = f;
1153     udata.dxpl_id = dxpl_id;
1154     udata.sequence = sequence;
1155     udata.nfailed = 0;
1156     udata.op = app_op;
1157     udata.op_data = op_data;
1158     udata.adj_link = adj_link;
1159 
1160     /* Iterate over the messages, deleting appropriate one(s) */
1161     op.op_type = H5O_MESG_OP_LIB;
1162     op.u.lib_op = H5O__msg_remove_cb;
1163     if(H5O_msg_iterate_real(f, oh, type, &op, &udata, dxpl_id) < 0)
1164         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error iterating over messages")
1165 
1166     /* Fail if we tried to remove any constant messages */
1167     if(udata.nfailed)
1168 	HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)")
1169 
1170 done:
1171     FUNC_LEAVE_NOAPI(ret_value)
1172 } /* end H5O_msg_remove_real() */
1173 
1174 
1175 /*-------------------------------------------------------------------------
1176  * Function:	H5O_msg_iterate
1177  *
1178  * Purpose:	Iterate through object headers of a certain type.
1179  *
1180  * Return:	Returns a negative value if something is wrong, the return
1181  *      value of the last operator if it was non-zero, or zero if all
1182  *      object headers were processed.
1183  *
1184  * Programmer:	Quincey Koziol
1185  *		koziol@ncsa.uiuc.edu
1186  *		Nov 19 2004
1187  *
1188  * Description:
1189  *      This function interates over the object headers of an object
1190  *  specified with 'loc' of type 'type_id'.  For each object header of the
1191  *  object, the 'op_data' and some additional information (specified below) are
1192  *  passed to the 'op' function.
1193  *      The operation receives a pointer to the object header message for the
1194  *  object being iterated over ('mesg'), and the pointer to the operator data
1195  *  passed in to H5O_msg_iterate ('op_data').  The return values from an operator
1196  *  are:
1197  *      A. Zero causes the iterator to continue, returning zero when all
1198  *          object headers of that type have been processed.
1199  *      B. Positive causes the iterator to immediately return that positive
1200  *          value, indicating short-circuit success.
1201  *      C. Negative causes the iterator to immediately return that value,
1202  *          indicating failure.
1203  *
1204  *-------------------------------------------------------------------------
1205  */
1206 herr_t
H5O_msg_iterate(const H5O_loc_t * loc,unsigned type_id,const H5O_mesg_operator_t * op,void * op_data,hid_t dxpl_id)1207 H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
1208     const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id)
1209 {
1210     H5O_t *oh = NULL;               /* Pointer to actual object header */
1211     const H5O_msg_class_t *type;    /* Actual H5O class type for the ID */
1212     herr_t ret_value = FAIL;        /* Return value */
1213 
1214     FUNC_ENTER_NOAPI(FAIL)
1215 
1216     /* check args */
1217     HDassert(loc);
1218     HDassert(loc->file);
1219     HDassert(H5F_addr_defined(loc->addr));
1220     HDassert(type_id < NELMTS(H5O_msg_class_g));
1221     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1222     HDassert(type);
1223     HDassert(op);
1224 
1225     /* Protect the object header to iterate over */
1226     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
1227 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
1228 
1229     /* Call the "real" iterate routine */
1230     if((ret_value = H5O_msg_iterate_real(loc->file, oh, type, op, op_data, dxpl_id)) < 0)
1231         HERROR(H5E_OHDR, H5E_BADITER, "unable to iterate over object header messages");
1232 
1233 done:
1234     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1235         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
1236 
1237     FUNC_LEAVE_NOAPI(ret_value)
1238 } /* end H5O_msg_iterate() */
1239 
1240 
1241 /*-------------------------------------------------------------------------
1242  * Function:	H5O_msg_iterate_real
1243  *
1244  * Purpose:	Iterate through object headers of a certain type.
1245  *
1246  * Return:	Returns a negative value if something is wrong, the return
1247  *      value of the last operator if it was non-zero, or zero if all
1248  *      object headers were processed.
1249  *
1250  * Programmer:	Quincey Koziol
1251  *		koziol@ncsa.uiuc.edu
1252  *		Sep  6 2005
1253  *
1254  * Description:
1255  *      This function interates over the object headers of an object
1256  *  specified with 'ent' of type 'type_id'.  For each object header of the
1257  *  object, the 'op_data' and some additional information (specified below) are
1258  *  passed to the 'op' function.
1259  *      The operation receives a pointer to the object header message for the
1260  *  object being iterated over ('mesg'), and the pointer to the operator data
1261  *  passed in to H5O_msg_iterate ('op_data').  The return values from an operator
1262  *  are:
1263  *      A. Zero causes the iterator to continue, returning zero when all
1264  *          object headers of that type have been processed.
1265  *      B. Positive causes the iterator to immediately return that positive
1266  *          value, indicating short-circuit success.
1267  *      C. Negative causes the iterator to immediately return that value,
1268  *          indicating failure.
1269  *
1270  *-------------------------------------------------------------------------
1271  */
1272 herr_t
H5O_msg_iterate_real(H5F_t * f,H5O_t * oh,const H5O_msg_class_t * type,const H5O_mesg_operator_t * op,void * op_data,hid_t dxpl_id)1273 H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
1274     const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id)
1275 {
1276     H5O_mesg_t         *idx_msg;        /* Pointer to current message */
1277     unsigned		idx;            /* Absolute index of current message in all messages */
1278     unsigned		sequence;       /* Relative index of current message for messages of type */
1279     unsigned 		oh_modified = 0;    	/* Whether the callback modified the object header */
1280     herr_t              ret_value = H5_ITER_CONT;      /* Return value */
1281 
1282     FUNC_ENTER_NOAPI_NOINIT
1283 
1284     /* check args */
1285     HDassert(f);
1286     HDassert(oh);
1287     HDassert(type);
1288     HDassert(op);
1289     HDassert(op->u.app_op);
1290 
1291     /* Iterate over messages */
1292     for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
1293 	if(type == idx_msg->type) {
1294             /* Decode the message if necessary.  */
1295             H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, idx_msg, FAIL)
1296 
1297             /* Check for making an "internal" (i.e. within the H5O package) callback */
1298             if(op->op_type == H5O_MESG_OP_LIB)
1299                 ret_value = (op->u.lib_op)(oh, idx_msg, sequence, &oh_modified, op_data);
1300             else
1301                 ret_value = (op->u.app_op)(idx_msg->native, sequence, op_data);
1302 
1303             /* Check for iterator callback indicating to get out of loop */
1304             if(ret_value != 0)
1305                 break;
1306 
1307             /* Increment sequence value for message type */
1308             sequence++;
1309         } /* end if */
1310     } /* end for */
1311 
1312     /* Check for error from iterator */
1313     if(ret_value < 0)
1314         HERROR(H5E_OHDR, H5E_CANTLIST, "iterator function failed");
1315 
1316 done:
1317     /* Check if object message was modified */
1318     if(oh_modified) {
1319         /* Try to condense object header info */
1320         /* (Since this routine is used to remove messages from an
1321          *  object header, the header will be condensed after each
1322          *  message removal)
1323          */
1324 	if(oh_modified & H5O_MODIFY_CONDENSE)
1325 	    if(H5O_condense_header(f, oh, dxpl_id) < 0)
1326 		HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
1327 
1328         /* Mark object header as changed */
1329         if(H5O_touch_oh(f, dxpl_id, oh, FALSE) < 0)
1330             HDONE_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
1331 
1332         /* Mark object header as dirty in cache */
1333         if(H5AC_mark_entry_dirty(oh) < 0)
1334             HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
1335     } /* end if */
1336 
1337     FUNC_LEAVE_NOAPI(ret_value)
1338 } /* end H5O_msg_iterate_real() */
1339 
1340 
1341 /*-------------------------------------------------------------------------
1342  * Function:	H5O_msg_raw_size
1343  *
1344  * Purpose:	Call the 'raw_size' method for a
1345  *              particular class of object header.
1346  *
1347  * Return:	Size of message on success, 0 on failure
1348  *
1349  * Programmer:	Quincey Koziol
1350  *		koziol@ncsa.uiuc.edu
1351  *		Feb 13 2003
1352  *
1353  *-------------------------------------------------------------------------
1354  */
1355 size_t
H5O_msg_raw_size(const H5F_t * f,unsigned type_id,hbool_t disable_shared,const void * mesg)1356 H5O_msg_raw_size(const H5F_t *f, unsigned type_id, hbool_t disable_shared,
1357     const void *mesg)
1358 {
1359     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
1360     size_t ret_value = 0;               /* Return value */
1361 
1362     FUNC_ENTER_NOAPI(0)
1363 
1364     /* Check args */
1365     HDassert(type_id < NELMTS(H5O_msg_class_g));
1366     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1367     HDassert(type);
1368     HDassert(type->raw_size);
1369     HDassert(f);
1370     HDassert(mesg);
1371 
1372     /* Compute the raw data size for the mesg */
1373     if(0 == (ret_value = (type->raw_size)(f, disable_shared, mesg)))
1374         HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
1375 
1376 done:
1377     FUNC_LEAVE_NOAPI(ret_value)
1378 } /* end H5O_msg_raw_size() */
1379 
1380 
1381 /*-------------------------------------------------------------------------
1382  * Function:	H5O_msg_size_f
1383  *
1384  * Purpose:	Calculate the final size of an encoded message in an object
1385  *              header.
1386  *
1387  * Note:	This routine assumes that the message size will be used in the
1388  *              creation of a new object header.
1389  *
1390  * Return:	Size of message on success, 0 on failure
1391  *
1392  * Programmer:	Quincey Koziol
1393  *		koziol@ncsa.uiuc.edu
1394  *		Sep  6 2005
1395  *
1396  *-------------------------------------------------------------------------
1397  */
1398 size_t
H5O_msg_size_f(const H5F_t * f,hid_t ocpl_id,unsigned type_id,const void * mesg,size_t extra_raw)1399 H5O_msg_size_f(const H5F_t *f, hid_t ocpl_id, unsigned type_id,
1400     const void *mesg, size_t extra_raw)
1401 {
1402     const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
1403     H5P_genplist_t *ocpl;       /* Object Creation Property list */
1404     uint8_t oh_flags;           /* Object header status flags */
1405     size_t ret_value = 0;       /* Return value */
1406 
1407     FUNC_ENTER_NOAPI(0)
1408 
1409     /* Check args */
1410     HDassert(type_id < NELMTS(H5O_msg_class_g));
1411     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1412     HDassert(type);
1413     HDassert(type->raw_size);
1414     HDassert(f);
1415     HDassert(mesg);
1416 
1417     /* Get the property list */
1418     if(NULL == (ocpl = (H5P_genplist_t *)H5I_object(ocpl_id)))
1419         HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, 0, "not a property list")
1420 
1421     /* Get any object header status flags set by properties */
1422     if(H5P_get(ocpl, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
1423         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "can't get object header flags")
1424 
1425 
1426     /* Compute the raw data size for the mesg */
1427     if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
1428         HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
1429 
1430     /* Add in "extra" raw space */
1431     ret_value += extra_raw;
1432 
1433     /* Adjust size for alignment, if necessary */
1434     ret_value = (size_t)H5O_ALIGN_F(f, ret_value);
1435 
1436     /* Add space for message header */
1437     ret_value += (size_t)H5O_SIZEOF_MSGHDR_F(f,
1438             (H5F_STORE_MSG_CRT_IDX(f) || oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED));
1439 
1440 done:
1441     FUNC_LEAVE_NOAPI(ret_value)
1442 } /* end H5O_msg_size_f() */
1443 
1444 
1445 /*-------------------------------------------------------------------------
1446  * Function:	H5O_msg_size_oh
1447  *
1448  * Purpose:	Calculate the final size of an encoded message in an object
1449  *              header.
1450  *
1451  * Note:	This routine assumes that the message is already used in
1452  *              an object header.
1453  *
1454  * Return:	Size of message on success, 0 on failure
1455  *
1456  * Programmer:	Quincey Koziol
1457  *		koziol@hdfgroup.org
1458  *		Mar  7 2007
1459  *
1460  *-------------------------------------------------------------------------
1461  */
1462 size_t
H5O_msg_size_oh(const H5F_t * f,const H5O_t * oh,unsigned type_id,const void * mesg,size_t extra_raw)1463 H5O_msg_size_oh(const H5F_t *f, const H5O_t *oh, unsigned type_id,
1464     const void *mesg, size_t extra_raw)
1465 {
1466     const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
1467     size_t ret_value = 0;       /* Return value */
1468 
1469     FUNC_ENTER_NOAPI(0)
1470 
1471     /* Check args */
1472     HDassert(type_id < NELMTS(H5O_msg_class_g));
1473     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1474     HDassert(type);
1475     HDassert(type->raw_size);
1476     HDassert(f);
1477     HDassert(mesg);
1478 
1479     /* Compute the raw data size for the mesg */
1480     if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
1481         HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
1482 
1483     /* Add in "extra" raw space */
1484     ret_value += extra_raw;
1485 
1486     /* Adjust size for alignment, if necessary */
1487     ret_value = (size_t)H5O_ALIGN_OH(oh, ret_value);
1488 
1489     /* Add space for message header */
1490     ret_value += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
1491 
1492 done:
1493     FUNC_LEAVE_NOAPI(ret_value)
1494 } /* end H5O_msg_size_oh() */
1495 
1496 
1497 /*-------------------------------------------------------------------------
1498  * Function:    H5O_msg_can_share
1499  *
1500  * Purpose:     Call the 'can share' method for a
1501  *              particular class of object header.  This returns TRUE
1502  *              if the message is allowed to be put in the shared message
1503  *              heap and false otherwise (e.g., for committed or immutable
1504  *              datatypes).
1505  *
1506  * Return:      Object can be shared:        TRUE
1507  *              Object cannot be shared:    FALSE
1508  *
1509  * Programmer:  James Laird
1510  *              January 12 2007
1511  *
1512  *-------------------------------------------------------------------------
1513  */
1514 htri_t
H5O_msg_can_share(unsigned type_id,const void * mesg)1515 H5O_msg_can_share(unsigned type_id, const void *mesg)
1516 {
1517     const H5O_msg_class_t *type;    /* Actual H5O class type for the ID */
1518     htri_t ret_value = FAIL;        /* Return value */
1519 
1520     FUNC_ENTER_NOAPI_NOINIT_NOERR
1521 
1522     /* Check args */
1523     HDassert(type_id < NELMTS(H5O_msg_class_g));
1524     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1525     HDassert(type);
1526     HDassert(mesg);
1527 
1528     /* If there is a can_share callback, use it */
1529     if(type->can_share)
1530         ret_value = (type->can_share)(mesg);
1531     else {
1532         /* Otherwise, the message can be shared if messages of this type are
1533          * shareable in general; i.e., if they have the "is_sharable" flag
1534          * in the "share_flags" class member set.
1535          */
1536         ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE;
1537     } /* end else */
1538 
1539     /* If the message is shareable, both copy_file and post_copy_file must be
1540      * defined */
1541     HDassert((type->post_copy_file && type->copy_file) || ret_value == FALSE);
1542 
1543     FUNC_LEAVE_NOAPI(ret_value)
1544 } /* end H5O_msg_can_share() */
1545 
1546 
1547 /*-------------------------------------------------------------------------
1548  * Function:    H5O_msg_can_share_in_ohdr
1549  *
1550  * Purpose:     Check if the message class allows its messages to be shared
1551  *              in the object's header.
1552  *
1553  * Return:      Object can be shared:        TRUE
1554  *              Object cannot be shared:    FALSE
1555  *
1556  * Programmer:  Quincey Koziol
1557  *              March 15 2007
1558  *
1559  *-------------------------------------------------------------------------
1560  */
1561 htri_t
H5O_msg_can_share_in_ohdr(unsigned type_id)1562 H5O_msg_can_share_in_ohdr(unsigned type_id)
1563 {
1564     const H5O_msg_class_t *type;    /* Actual H5O class type for the ID */
1565     htri_t ret_value = FAIL;        /* Return value */
1566 
1567     FUNC_ENTER_NOAPI_NOINIT_NOERR
1568 
1569     /* Check args */
1570     HDassert(type_id < NELMTS(H5O_msg_class_g));
1571     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1572     HDassert(type);
1573 
1574     /* Otherwise, the message can be shared if messages of this type are
1575      * shareable in general; i.e., if they have the "is_sharable" flag
1576      * in the "share_flags" class member set.
1577      */
1578     ret_value = (type->share_flags & H5O_SHARE_IN_OHDR) ? TRUE : FALSE;
1579 
1580     FUNC_LEAVE_NOAPI(ret_value)
1581 } /* end H5O_msg_can_share_in_ohdr() */
1582 
1583 
1584 /*-------------------------------------------------------------------------
1585  * Function:    H5O_msg_is_shared
1586  *
1587  * Purpose:     Call the 'is_shared' method for a
1588  *              particular class of object header.
1589  *
1590  * Return:      Object is shared:        TRUE
1591  *              Object is not shared:    FALSE
1592  *
1593  * Programmer:  James Laird
1594  *              jlaird@ncsa.uiuc.edu
1595  *              April 5 2006
1596  *
1597  *-------------------------------------------------------------------------
1598  */
1599 htri_t
H5O_msg_is_shared(unsigned type_id,const void * mesg)1600 H5O_msg_is_shared(unsigned type_id, const void *mesg)
1601 {
1602     const H5O_msg_class_t *type;    /* Actual H5O class type for the ID */
1603     htri_t ret_value = FAIL;        /* Return value */
1604 
1605     FUNC_ENTER_NOAPI_NOINIT_NOERR
1606 
1607     /* Check args */
1608     HDassert(type_id < NELMTS(H5O_msg_class_g));
1609     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1610     HDassert(type);
1611     HDassert(mesg);
1612 
1613     /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */
1614     if(type->share_flags & H5O_SHARE_IS_SHARABLE)
1615         ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type);
1616     else
1617         ret_value = FALSE;
1618 
1619     FUNC_LEAVE_NOAPI(ret_value)
1620 } /* end H5O_msg_is_shared() */
1621 
1622 
1623 /*-------------------------------------------------------------------------
1624  * Function:	H5O_msg_set_share
1625  *
1626  * Purpose:	Set the shared information for an object header message.
1627  *
1628  * Return:	Success:	Non-negative
1629  *		Failure:	Negative
1630  *
1631  * Programmer:	James Laird
1632  *		jlaird@hdfgroup.org
1633  *		November 1 2006
1634  *
1635  *-------------------------------------------------------------------------
1636  */
1637 herr_t
H5O_msg_set_share(unsigned type_id,const H5O_shared_t * share,void * mesg)1638 H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg)
1639 {
1640     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
1641     herr_t ret_value = SUCCEED;         /* Return value */
1642 
1643     FUNC_ENTER_NOAPI(FAIL)
1644 
1645     /* Check args */
1646     HDassert(type_id < NELMTS(H5O_msg_class_g));
1647     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1648     HDassert(type);
1649     HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
1650     HDassert(mesg);
1651     HDassert(share);
1652     HDassert(share->type != H5O_SHARE_TYPE_UNSHARED);
1653 
1654     /* If there's a special action for this class that needs to be performed
1655      *  when setting the shared component, do that
1656      */
1657     if(type->set_share) {
1658         if((type->set_share)(mesg, share) < 0)
1659             HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
1660     } /* end if */
1661     else {
1662         /* Set this message as the shared component for the message, wiping out
1663          * any information that was there before
1664          */
1665         if(H5O_set_shared((H5O_shared_t *)mesg, share) < 0)
1666             HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
1667     } /* end else */
1668 
1669 done:
1670     FUNC_LEAVE_NOAPI(ret_value)
1671 } /* end H5O_msg_set_share() */
1672 
1673 
1674 /*-------------------------------------------------------------------------
1675  * Function:	H5O_msg_reset_share
1676  *
1677  * Purpose:	Reset the shared information for an object header message.
1678  *
1679  * Return:	Success:	Non-negative
1680  *		Failure:	Negative
1681  *
1682  * Programmer:	James Laird
1683  *		jlaird@hdfgroup.org
1684  *		Oct 17 2006
1685  *
1686  *-------------------------------------------------------------------------
1687  */
1688 herr_t
H5O_msg_reset_share(unsigned type_id,void * mesg)1689 H5O_msg_reset_share(unsigned type_id, void *mesg)
1690 {
1691     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
1692 
1693     FUNC_ENTER_NOAPI_NOINIT_NOERR
1694 
1695     /* Check args */
1696     HDassert(type_id < NELMTS(H5O_msg_class_g));
1697     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1698     HDassert(type);
1699     HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
1700     HDassert(mesg);
1701 
1702     /* Reset the shared component in the message to zero. */
1703     HDmemset((H5O_shared_t *)mesg, 0, sizeof(H5O_shared_t));
1704 
1705     FUNC_LEAVE_NOAPI(SUCCEED)
1706 } /* end H5O_msg_reset_share() */
1707 
1708 
1709 /*-------------------------------------------------------------------------
1710  * Function:    H5O_msg_get_crt_index
1711  *
1712  * Purpose:     Call the 'get creation index' method for a message.
1713  *
1714  * Return:	Success:	Non-negative
1715  *		Failure:	Negative
1716  *
1717  * Programmer:  Quincey Koziol
1718  *              March 15 2007
1719  *
1720  *-------------------------------------------------------------------------
1721  */
1722 herr_t
H5O_msg_get_crt_index(unsigned type_id,const void * mesg,H5O_msg_crt_idx_t * crt_idx)1723 H5O_msg_get_crt_index(unsigned type_id, const void *mesg, H5O_msg_crt_idx_t *crt_idx)
1724 {
1725     const H5O_msg_class_t *type;    /* Actual H5O class type for the ID */
1726     herr_t ret_value = SUCCEED;
1727 
1728     FUNC_ENTER_NOAPI(FAIL)
1729 
1730     /* Check args */
1731     HDassert(type_id < NELMTS(H5O_msg_class_g));
1732     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1733     HDassert(type);
1734     HDassert(mesg);
1735     HDassert(crt_idx);
1736 
1737     /* If there is a "get_crt_index callback, use it */
1738     if(type->get_crt_index) {
1739         /* Retrieve the creation index from the native message */
1740         if((type->get_crt_index)(mesg, crt_idx) < 0)
1741             HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
1742     } /* end if */
1743     else
1744         *crt_idx = 0;
1745 
1746 done:
1747     FUNC_LEAVE_NOAPI(ret_value)
1748 } /* end H5O_msg_get_crt_index() */
1749 
1750 
1751 /*-------------------------------------------------------------------------
1752  * Function:	H5O_msg_encode
1753  *
1754  * Purpose:	Encode an object(data type and simple data space only)
1755  *              description into a buffer.
1756  *
1757  * Return:	Success:	Non-negative
1758  *
1759  *		Failure:	Negative
1760  *
1761  * Programmer:	Raymond Lu
1762  *		slu@ncsa.uiuc.edu
1763  *		July 13, 2004
1764  *
1765  *-------------------------------------------------------------------------
1766  */
1767 herr_t
H5O_msg_encode(H5F_t * f,unsigned type_id,hbool_t disable_shared,unsigned char * buf,const void * mesg)1768 H5O_msg_encode(H5F_t *f, unsigned type_id, hbool_t disable_shared,
1769     unsigned char *buf, const void *mesg)
1770 {
1771     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
1772     herr_t ret_value = SUCCEED;         /* Return value */
1773 
1774     FUNC_ENTER_NOAPI(FAIL)
1775 
1776     /* check args */
1777     HDassert(f);
1778     HDassert(type_id < NELMTS(H5O_msg_class_g));
1779     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1780     HDassert(type);
1781 
1782     /* Encode */
1783     if((type->encode)(f, disable_shared, buf, mesg) < 0)
1784         HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode message")
1785 
1786 done:
1787     FUNC_LEAVE_NOAPI(ret_value)
1788 } /* end H5O_msg_encode() */
1789 
1790 
1791 /*-------------------------------------------------------------------------
1792  * Function:	H5O_msg_decode
1793  *
1794  * Purpose:	Decode a binary object description and return a new
1795  *              object handle.
1796  *
1797  * Return:	Success:        Pointer to object(data type or space)
1798  *
1799  *		Failure:	NULL
1800  *
1801  * Programmer:	Raymond Lu
1802  *		slu@ncsa.uiuc.edu
1803  *		July 14, 2004
1804  *
1805  * Modifications: Neil Fortner
1806  *              Feb 4 2009
1807  *              Added open_oh parameter.  This parameter is optional and
1808  *              contains this message's protected object header
1809  *
1810  *-------------------------------------------------------------------------
1811  */
1812 void *
H5O_msg_decode(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,unsigned type_id,const unsigned char * buf)1813 H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
1814     const unsigned char *buf)
1815 {
1816     const H5O_msg_class_t   *type;      /* Actual H5O class type for the ID */
1817     unsigned ioflags = 0;               /* Flags for decode routine */
1818     void *ret_value = NULL;             /* Return value */
1819 
1820     FUNC_ENTER_NOAPI(NULL)
1821 
1822     /* check args */
1823     HDassert(f);
1824     HDassert(type_id < NELMTS(H5O_msg_class_g));
1825     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
1826     HDassert(type);
1827 
1828     /* decode */
1829     if((ret_value = (type->decode)(f, dxpl_id, open_oh, 0, &ioflags, buf)) == NULL)
1830         HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message")
1831 
1832 done:
1833     FUNC_LEAVE_NOAPI(ret_value)
1834 } /* end H5O_msg_decode() */
1835 
1836 
1837 /*-------------------------------------------------------------------------
1838  * Function:    H5O_msg_copy_file
1839  *
1840  * Purpose:     Copies a message to file.  If MESG is is the null pointer then a null
1841  *              pointer is returned with no error.
1842  *
1843  *              Attempts to share the message in the destination and sets
1844  *              SHARED to TRUE or FALSE depending on whether this succeeds.
1845  *
1846  * Return:      Success:        Ptr to the new message
1847  *
1848  *              Failure:        NULL
1849  *
1850  * Programmer:  Peter Cao
1851  *              June 4, 2005
1852  *
1853  *-------------------------------------------------------------------------
1854  */
1855 void *
H5O_msg_copy_file(const H5O_msg_class_t * type,H5F_t * file_src,void * native_src,H5F_t * file_dst,hbool_t * recompute_size,unsigned * mesg_flags,H5O_copy_t * cpy_info,void * udata,hid_t dxpl_id)1856 H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
1857     void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
1858     unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
1859 {
1860     void *ret_value = NULL;             /* Return value */
1861 
1862     FUNC_ENTER_NOAPI_NOINIT
1863 
1864     /* check args */
1865     HDassert(type);
1866     HDassert(type->copy_file);
1867     HDassert(file_src);
1868     HDassert(native_src);
1869     HDassert(file_dst);
1870     HDassert(recompute_size);
1871     HDassert(cpy_info);
1872 
1873     /* The copy_file callback will return an H5O_shared_t only if the message
1874      * to be copied is a committed datatype.
1875      */
1876     if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata, dxpl_id)))
1877         HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file")
1878 
1879 done:
1880     FUNC_LEAVE_NOAPI(ret_value)
1881 } /* end H5O_msg_copy_file() */
1882 
1883 
1884 /*-------------------------------------------------------------------------
1885  * Function:	H5O_msg_alloc
1886  *
1887  * Purpose:	Create a new message in an object header
1888  *
1889  * Return:	Success:	Index of message
1890  *		Failure:	Negative
1891  *
1892  * Programmer:	Quincey Koziol
1893  *              Friday, September  3, 2003
1894  *
1895  *-------------------------------------------------------------------------
1896  */
1897 herr_t
H5O_msg_alloc(H5F_t * f,hid_t dxpl_id,H5O_t * oh,const H5O_msg_class_t * type,unsigned * mesg_flags,void * native,size_t * mesg_idx)1898 H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
1899     unsigned *mesg_flags, void *native, size_t *mesg_idx)
1900 {
1901     size_t new_idx;             /* New index for message */
1902     htri_t shared_mesg;         /* Should this message be stored in the Shared Message table? */
1903     herr_t ret_value = SUCCEED; /* Return value */
1904 
1905     FUNC_ENTER_NOAPI_NOINIT
1906 
1907     /* check args */
1908     HDassert(f);
1909     HDassert(oh);
1910     HDassert(mesg_flags);
1911     HDassert(!(*mesg_flags & H5O_MSG_FLAG_SHARED));
1912     HDassert(type);
1913     HDassert(native);
1914     HDassert(mesg_idx);
1915 
1916     /* Check if message is already shared */
1917     if((shared_mesg = H5O_msg_is_shared(type->id, native)) < 0)
1918         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "error determining if message is shared")
1919     else if(shared_mesg > 0) {
1920         /* Increment message's reference count */
1921         if(type->link && (type->link)(f, dxpl_id, oh, native) < 0)
1922             HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared message ref count")
1923         *mesg_flags |= H5O_MSG_FLAG_SHARED;
1924     } /* end if */
1925     else {
1926         /* Attempt to share message */
1927         if(H5SM_try_share(f, dxpl_id, oh, 0, type->id, native, mesg_flags) < 0)
1928             HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
1929     } /* end else */
1930 
1931     /* Allocate space in the object header for the message */
1932     if(H5O_alloc(f, dxpl_id, oh, type, native, &new_idx) < 0)
1933         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message")
1934 
1935     /* Get the message's "creation index", if it has one */
1936     if(type->get_crt_index) {
1937         /* Retrieve the creation index from the native message */
1938         if((type->get_crt_index)(native, &oh->mesg[new_idx].crt_idx) < 0)
1939             HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
1940     } /* end if */
1941 
1942     /* Set new message index */
1943     *mesg_idx = new_idx;
1944 
1945 done:
1946     FUNC_LEAVE_NOAPI(ret_value)
1947 } /* end H5O_msg_alloc() */
1948 
1949 
1950 /*-------------------------------------------------------------------------
1951  * Function:	H5O__copy_mesg
1952  *
1953  * Purpose:	Make a copy of the native object for an object header's
1954  *              native message info
1955  *
1956  * Return:	Non-negative on success/Negative on failure
1957  *
1958  * Programmer:	Quincey Koziol
1959  *              Friday, September  3, 2003
1960  *
1961  *-------------------------------------------------------------------------
1962  */
1963 static herr_t
H5O__copy_mesg(H5F_t * f,hid_t dxpl_id,H5O_t * oh,size_t idx,const H5O_msg_class_t * type,const void * mesg,unsigned mesg_flags,unsigned update_flags)1964 H5O__copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t idx,
1965     const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
1966     unsigned update_flags)
1967 {
1968     H5O_chunk_proxy_t *chk_proxy = NULL;        /* Chunk that message is in */
1969     H5O_mesg_t *idx_msg = &oh->mesg[idx];       /* Pointer to message to modify */
1970     hbool_t chk_dirtied = FALSE;                /* Flag for unprotecting chunk */
1971     herr_t      ret_value = SUCCEED;            /* Return value */
1972 
1973     FUNC_ENTER_STATIC
1974 
1975     /* check args */
1976     HDassert(f);
1977     HDassert(oh);
1978     HDassert(type);
1979     HDassert(type->copy);
1980     HDassert(mesg);
1981 
1982     /* Protect chunk */
1983     if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, idx_msg->chunkno)))
1984 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
1985 
1986     /* Reset existing native information for the header's message */
1987     H5O__msg_reset_real(type, idx_msg->native);
1988 
1989     /* Copy the native object for the message */
1990     if(NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native)))
1991         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header")
1992 
1993     /* Update the message flags */
1994     idx_msg->flags = (uint8_t)mesg_flags;
1995 
1996     /* Mark the message as modified */
1997     idx_msg->dirty = TRUE;
1998     chk_dirtied = TRUE;
1999 
2000     /* Release chunk */
2001     if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, chk_dirtied) < 0)
2002         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
2003     chk_proxy = NULL;
2004 
2005     /* Update the modification time, if requested */
2006     if(update_flags & H5O_UPDATE_TIME)
2007         if(H5O_touch_oh(f, dxpl_id, oh, FALSE) < 0)
2008             HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
2009 
2010 done:
2011     /* Release chunk, if not already released */
2012     if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, chk_proxy, chk_dirtied) < 0)
2013         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
2014 
2015     FUNC_LEAVE_NOAPI(ret_value)
2016 } /* end H5O__copy_mesg() */
2017 
2018 
2019 /*-------------------------------------------------------------------------
2020  * Function:    H5O_msg_delete
2021  *
2022  * Purpose:     Calls a message's delete callback.
2023  *
2024  *              This is mostly redundant with H5O_delete_mesg below,
2025  *              but H5O_delete_mesg only works on messages in object headers
2026  *              (while the shared message code needs to delete messages in
2027  *              the heap).
2028  *
2029  *              open_oh is a pointer to a currently open object header so
2030  *              that the library doesn't try to re-protect it.  If there is
2031  *              no such object header, it should be NULL.
2032  *
2033  * Return:      Success:        Non-negative
2034  *              Failure:        Negative
2035  *
2036  * Programmer:  James Laird
2037  *              December 21, 2006
2038  *
2039  *-------------------------------------------------------------------------
2040  */
2041 herr_t
H5O_msg_delete(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,unsigned type_id,void * mesg)2042 H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
2043     void *mesg)
2044 {
2045     const H5O_msg_class_t   *type;      /* Actual H5O class type for the ID */
2046     herr_t ret_value = SUCCEED;                    /* Return value */
2047 
2048     FUNC_ENTER_NOAPI(FAIL)
2049 
2050     /* check args */
2051     HDassert(f);
2052     HDassert(type_id < NELMTS(H5O_msg_class_g));
2053     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
2054     HDassert(type);
2055 
2056     /* delete */
2057     if((type->del) && (type->del)(f, dxpl_id, open_oh, mesg) < 0)
2058         HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
2059 
2060 done:
2061     FUNC_LEAVE_NOAPI(ret_value)
2062 } /* end H5O_msg_delete() */
2063 
2064 
2065 /*-------------------------------------------------------------------------
2066  * Function:	H5O_delete_mesg
2067  *
2068  * Purpose:	Internal function to:
2069  *              Delete an object header message from a file.  This frees the file
2070  *              space used for anything referred to in the object header message.
2071  *
2072  * Return:	Non-negative on success/Negative on failure
2073  *
2074  * Programmer:	Quincey Koziol
2075  *		koziol@ncsa.uiuc.edu
2076  *		September 26 2003
2077  *
2078  *-------------------------------------------------------------------------
2079  */
2080 herr_t
H5O_delete_mesg(H5F_t * f,hid_t dxpl_id,H5O_t * oh,H5O_mesg_t * mesg)2081 H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg)
2082 {
2083     const H5O_msg_class_t *type = mesg->type;  /* Type of object to free */
2084     herr_t ret_value = SUCCEED;   /* Return value */
2085 
2086     FUNC_ENTER_NOAPI(FAIL)
2087 
2088     /* Check args */
2089     HDassert(f);
2090     HDassert(mesg);
2091     HDassert(oh);
2092 
2093     /* Check if there is a file space deletion callback for this type of message */
2094     if(type->del) {
2095         /* Decode the message if necessary. */
2096         H5O_LOAD_NATIVE(f, dxpl_id, H5O_DECODEIO_NOCHANGE, oh, mesg, FAIL)
2097 
2098         if((type->del)(f, dxpl_id, oh, mesg->native) < 0)
2099             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
2100     } /* end if */
2101 
2102 done:
2103     FUNC_LEAVE_NOAPI(ret_value)
2104 } /* end H5O_delete_mesg() */
2105 
2106 
2107 /*-------------------------------------------------------------------------
2108  * Function:	H5O_msg_flush
2109  *
2110  * Purpose:	Flushes a message for an object header.
2111  *
2112  * Return:	Non-negative on success/Negative on failure
2113  *
2114  * Programmer:	Quincey Koziol
2115  *		koziol@hdfgroup.org
2116  *		May 14 2007
2117  *
2118  *-------------------------------------------------------------------------
2119  */
2120 herr_t
H5O_msg_flush(H5F_t * f,H5O_t * oh,H5O_mesg_t * mesg)2121 H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg)
2122 {
2123     uint8_t	*p;             /* Temporary pointer to encode with */
2124     unsigned    msg_id;         /* ID for message */
2125     herr_t      ret_value = SUCCEED;       /* Return value */
2126 
2127     FUNC_ENTER_NOAPI(FAIL)
2128 
2129     /* check args */
2130     HDassert(f);
2131     HDassert(oh);
2132 
2133     /* Point into message's chunk's image */
2134     p = mesg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
2135 
2136     /* Retrieve actual message ID, for unknown messages */
2137     if(mesg->type == H5O_MSG_UNKNOWN)
2138         msg_id = *(H5O_unknown_t *)(mesg->native);
2139     else
2140         msg_id = (uint8_t)mesg->type->id;
2141 
2142     /* Encode the message prefix */
2143     if(oh->version == H5O_VERSION_1)
2144         UINT16ENCODE(p, msg_id)
2145     else
2146         *p++ = (uint8_t)msg_id;
2147     HDassert(mesg->raw_size < H5O_MESG_MAX_SIZE);
2148     UINT16ENCODE(p, mesg->raw_size);
2149     *p++ = mesg->flags;
2150 
2151     /* Only encode reserved bytes for version 1 of format */
2152     if(oh->version == H5O_VERSION_1) {
2153         *p++ = 0; /*reserved*/
2154         *p++ = 0; /*reserved*/
2155         *p++ = 0; /*reserved*/
2156     } /* end for */
2157     /* Only encode creation index for version 2+ of format */
2158     else {
2159         /* Only encode creation index if they are being tracked */
2160         if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
2161             UINT16ENCODE(p, mesg->crt_idx);
2162     } /* end else */
2163     HDassert(p == mesg->raw);
2164 
2165 #ifndef NDEBUG
2166     /* Make certain that null messages aren't in chunks w/gaps */
2167     if(H5O_NULL_ID == msg_id)
2168         HDassert(oh->chunk[mesg->chunkno].gap == 0);
2169     else
2170         /* Non-null messages should always have a native pointer */
2171         HDassert(mesg->native);
2172 #endif /* NDEBUG */
2173 
2174     /* Encode the message itself, if it's not an "unknown" message */
2175     if(mesg->native && mesg->type != H5O_MSG_UNKNOWN) {
2176         /*
2177          * Encode the message.  If the message is shared then we
2178          * encode a Shared Object message instead of the object
2179          * which is being shared.
2180          */
2181         HDassert(mesg->raw >= oh->chunk[mesg->chunkno].image);
2182         HDassert(mesg->raw_size == H5O_ALIGN_OH(oh, mesg->raw_size));
2183         HDassert(mesg->raw + mesg->raw_size <=
2184                oh->chunk[mesg->chunkno].image + (oh->chunk[mesg->chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)));
2185 #ifndef NDEBUG
2186 /* Sanity check that the message won't overwrite past it's allocated space */
2187 {
2188     size_t msg_size;
2189 
2190     msg_size = mesg->type->raw_size(f, FALSE, mesg->native);
2191     msg_size = H5O_ALIGN_OH(oh, msg_size);
2192     HDassert(msg_size <= mesg->raw_size);
2193 }
2194 #endif /* NDEBUG */
2195         HDassert(mesg->type->encode);
2196         if((mesg->type->encode)(f, FALSE, mesg->raw, mesg->native) < 0)
2197             HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
2198     } /* end if */
2199 
2200     /* Mark the message as clean now */
2201     mesg->dirty = FALSE;
2202 
2203 done:
2204     FUNC_LEAVE_NOAPI(ret_value)
2205 } /* end H5O_msg_flush() */
2206 
2207 
2208 /*-------------------------------------------------------------------------
2209  * Function:	H5O_flush_msgs
2210  *
2211  * Purpose:	Flushes messages for object header.
2212  *
2213  * Return:	Non-negative on success/Negative on failure
2214  *
2215  * Programmer:	Quincey Koziol
2216  *		koziol@ncsa.uiuc.edu
2217  *		Nov 21 2005
2218  *
2219  *-------------------------------------------------------------------------
2220  */
2221 herr_t
H5O_flush_msgs(H5F_t * f,H5O_t * oh)2222 H5O_flush_msgs(H5F_t *f, H5O_t *oh)
2223 {
2224     H5O_mesg_t *curr_msg;       /* Pointer to current message being operated on */
2225     unsigned	u;              /* Local index variable */
2226     herr_t      ret_value = SUCCEED;       /* Return value */
2227 
2228     FUNC_ENTER_NOAPI(FAIL)
2229 
2230     /* check args */
2231     HDassert(f);
2232     HDassert(oh);
2233 
2234     /* Encode any dirty messages */
2235     for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
2236         if(curr_msg->dirty)
2237             if(H5O_msg_flush(f, oh, curr_msg) < 0)
2238                 HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
2239 
2240     /* Sanity check for the correct # of messages in object header */
2241     if(oh->nmesgs != u)
2242         HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "corrupt object header - too few messages")
2243 
2244 #ifndef NDEBUG
2245         /* Reset the number of messages dirtied by decoding, as they have all
2246          * been flushed */
2247         oh->ndecode_dirtied = 0;
2248 #endif /* NDEBUG */
2249 
2250 done:
2251     FUNC_LEAVE_NOAPI(ret_value)
2252 } /* end H5O_flush_msgs() */
2253 
2254 
2255 /*-------------------------------------------------------------------------
2256  * Function:	H5O_msg_get_flags
2257  *
2258  * Purpose:	Queries a message's message flags in the object header
2259  *
2260  * Return:	Non-negative on success/Negative on failure
2261  *
2262  * Programmer:	Vailin; Jan 2013
2263  *
2264  *-------------------------------------------------------------------------
2265  */
2266 herr_t
H5O_msg_get_flags(const H5O_loc_t * loc,unsigned type_id,hid_t dxpl_id,uint8_t * flags)2267 H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id, uint8_t *flags)
2268 {
2269     H5O_t *oh = NULL;                   /* Object header to use */
2270     const H5O_msg_class_t *type;        /* Actual H5O class type for the ID */
2271     H5O_mesg_t *idx_msg;                /* Pointer to message to modify */
2272     unsigned idx;                       /* Index of message to modify */
2273     herr_t ret_value = SUCCEED;         /* Return value */
2274 
2275     FUNC_ENTER_NOAPI(FAIL)
2276 
2277     /* check args */
2278     HDassert(loc);
2279     HDassert(loc->file);
2280     HDassert(H5F_addr_defined(loc->addr));
2281     HDassert(type_id < NELMTS(H5O_msg_class_g));
2282     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
2283     HDassert(type);
2284 
2285     /* Get the object header */
2286     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
2287         HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
2288 
2289     /* Locate message of correct type */
2290     for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
2291         if(type == idx_msg->type)
2292             break;
2293 
2294     if(idx == oh->nmesgs)
2295         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
2296 
2297     /* Set return value */
2298     *flags = idx_msg->flags;
2299 
2300 done:
2301     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2302         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
2303 
2304     FUNC_LEAVE_NOAPI(ret_value)
2305 } /* end H5O_msg_get_flags() */
2306