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