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