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