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