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