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: H5Oainfo.c
17 * Mar 6 2007
18 * Quincey Koziol <koziol@hdfgroup.org>
19 *
20 * Purpose: Attribute Information messages.
21 *
22 *-------------------------------------------------------------------------
23 */
24
25 #define H5A_FRIEND /*suppress error about including H5Apkg */
26 #include "H5Omodule.h" /* This source code file is part of the H5O module */
27
28
29 #include "H5private.h" /* Generic Functions */
30 #include "H5Apkg.h" /* Attributes */
31 #include "H5Eprivate.h" /* Error handling */
32 #include "H5FLprivate.h" /* Free lists */
33 #include "H5Opkg.h" /* Object headers */
34
35
36 /* PRIVATE PROTOTYPES */
37 static void *H5O__ainfo_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
38 unsigned *ioflags, size_t p_size, const uint8_t *p);
39 static herr_t H5O_ainfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
40 static void *H5O_ainfo_copy(const void *_mesg, void *_dest);
41 static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
42 static herr_t H5O__ainfo_free(void *_mesg);
43 static herr_t H5O__ainfo_delete(H5F_t *f, H5O_t *open_oh, void *_mesg);
44 static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src,
45 hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
46 static void *H5O__ainfo_copy_file(H5F_t *file_src, void *mesg_src,
47 H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
48 H5O_copy_t *cpy_info, void *udata);
49 static herr_t H5O__ainfo_post_copy_file(const H5O_loc_t *src_oloc,
50 const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
51 unsigned *mesg_flags, H5O_copy_t *cpy_info);
52 static herr_t H5O__ainfo_debug(H5F_t *f, const void *_mesg, FILE * stream,
53 int indent, int fwidth);
54
55 /* This message derives from H5O message class */
56 const H5O_msg_class_t H5O_MSG_AINFO[1] = {{
57 H5O_AINFO_ID, /*message id number */
58 "ainfo", /*message name for debugging */
59 sizeof(H5O_ainfo_t), /*native message size */
60 0, /* messages are sharable? */
61 H5O__ainfo_decode, /*decode message */
62 H5O_ainfo_encode, /*encode message */
63 H5O_ainfo_copy, /*copy the native value */
64 H5O_ainfo_size, /*size of symbol table entry */
65 NULL, /*default reset method */
66 H5O__ainfo_free, /* free method */
67 H5O__ainfo_delete, /* file delete method */
68 NULL, /* link method */
69 NULL, /*set share method */
70 NULL, /*can share method */
71 H5O_ainfo_pre_copy_file, /* pre copy native value to file */
72 H5O__ainfo_copy_file, /* copy native value to file */
73 H5O__ainfo_post_copy_file, /* post copy native value to file */
74 NULL, /* get creation index */
75 NULL, /* set creation index */
76 H5O__ainfo_debug /*debug the message */
77 }};
78
79 /* Current version of attribute info information */
80 #define H5O_AINFO_VERSION 0
81
82 /* Flags for attribute info flag encoding */
83 #define H5O_AINFO_TRACK_CORDER 0x01
84 #define H5O_AINFO_INDEX_CORDER 0x02
85 #define H5O_AINFO_ALL_FLAGS (H5O_AINFO_TRACK_CORDER | H5O_AINFO_INDEX_CORDER)
86
87 /* Declare a free list to manage the H5O_ainfo_t struct */
88 H5FL_DEFINE_STATIC(H5O_ainfo_t);
89
90
91 /*-------------------------------------------------------------------------
92 * Function: H5O__ainfo_decode
93 *
94 * Purpose: Decode a message and return a pointer to a newly allocated one.
95 *
96 * Return: Success: Ptr to new message in native form.
97 * Failure: NULL
98 *
99 * Programmer: Quincey Koziol
100 * koziol@hdfgroup.org
101 * Mar 6 2007
102 *
103 *-------------------------------------------------------------------------
104 */
105 static void *
H5O__ainfo_decode(H5F_t * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t H5_ATTR_UNUSED p_size,const uint8_t * p)106 H5O__ainfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
107 unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
108 size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
109 {
110 H5O_ainfo_t *ainfo = NULL; /* Attribute info */
111 unsigned char flags; /* Flags for encoding attribute info */
112 void *ret_value = NULL; /* Return value */
113
114 FUNC_ENTER_STATIC
115
116 /* check args */
117 HDassert(f);
118 HDassert(p);
119
120 /* Version of message */
121 if(*p++ != H5O_AINFO_VERSION)
122 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")
123
124 /* Allocate space for message */
125 if(NULL == (ainfo = H5FL_MALLOC(H5O_ainfo_t)))
126 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
127
128 /* Get the flags for the message */
129 flags = *p++;
130 if(flags & ~H5O_AINFO_ALL_FLAGS)
131 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad flag value for message")
132 ainfo->track_corder = (flags & H5O_AINFO_TRACK_CORDER) ? TRUE : FALSE;
133 ainfo->index_corder = (flags & H5O_AINFO_INDEX_CORDER) ? TRUE : FALSE;
134
135 /* Set the number of attributes on the object to an invalid value, so we query it later */
136 ainfo->nattrs = HSIZET_MAX;
137
138 /* Max. creation order value for the object */
139 if(ainfo->track_corder)
140 UINT16DECODE(p, ainfo->max_crt_idx)
141 else
142 ainfo->max_crt_idx = H5O_MAX_CRT_ORDER_IDX;
143
144 /* Address of fractal heap to store "dense" attributes */
145 H5F_addr_decode(f, &p, &(ainfo->fheap_addr));
146
147 /* Address of v2 B-tree to index names of attributes (names are always indexed) */
148 H5F_addr_decode(f, &p, &(ainfo->name_bt2_addr));
149
150 /* Address of v2 B-tree to index creation order of links, if there is one */
151 if(ainfo->index_corder)
152 H5F_addr_decode(f, &p, &(ainfo->corder_bt2_addr));
153 else
154 ainfo->corder_bt2_addr = HADDR_UNDEF;
155
156 /* Set return value */
157 ret_value = ainfo;
158
159 done:
160 if(ret_value == NULL && ainfo != NULL)
161 ainfo = H5FL_FREE(H5O_ainfo_t, ainfo);
162
163 FUNC_LEAVE_NOAPI(ret_value)
164 } /* end H5O__ainfo_decode() */
165
166
167 /*-------------------------------------------------------------------------
168 * Function: H5O_ainfo_encode
169 *
170 * Purpose: Encodes a message.
171 *
172 * Return: Non-negative on success/Negative on failure
173 *
174 * Programmer: Quincey Koziol
175 * koziol@hdfgroup.org
176 * Mar 6 2007
177 *
178 *-------------------------------------------------------------------------
179 */
180 static herr_t
H5O_ainfo_encode(H5F_t * f,hbool_t H5_ATTR_UNUSED disable_shared,uint8_t * p,const void * _mesg)181 H5O_ainfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg)
182 {
183 const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg;
184 unsigned char flags; /* Flags for encoding attribute info */
185
186 FUNC_ENTER_NOAPI_NOINIT_NOERR
187
188 /* check args */
189 HDassert(f);
190 HDassert(p);
191 HDassert(ainfo);
192
193 /* Message version */
194 *p++ = H5O_AINFO_VERSION;
195
196 /* The flags for the attribute indices */
197 flags = ainfo->track_corder ? H5O_AINFO_TRACK_CORDER : 0;
198 flags = (unsigned char)(flags | (ainfo->index_corder ? H5O_AINFO_INDEX_CORDER : 0));
199 *p++ = flags;
200
201 /* Max. creation order value for the object */
202 if(ainfo->track_corder)
203 UINT16ENCODE(p, ainfo->max_crt_idx);
204
205 /* Address of fractal heap to store "dense" attributes */
206 H5F_addr_encode(f, &p, ainfo->fheap_addr);
207
208 /* Address of v2 B-tree to index names of attributes */
209 H5F_addr_encode(f, &p, ainfo->name_bt2_addr);
210
211 /* Address of v2 B-tree to index creation order of attributes, if they are indexed */
212 if(ainfo->index_corder)
213 H5F_addr_encode(f, &p, ainfo->corder_bt2_addr);
214 else
215 HDassert(!H5F_addr_defined(ainfo->corder_bt2_addr));
216
217 FUNC_LEAVE_NOAPI(SUCCEED)
218 } /* end H5O_ainfo_encode() */
219
220
221 /*-------------------------------------------------------------------------
222 * Function: H5O_ainfo_copy
223 *
224 * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
225 * necessary.
226 *
227 * Return: Success: Ptr to _DEST
228 * Failure: NULL
229 *
230 * Programmer: Quincey Koziol
231 * koziol@hdfgroup.org
232 * Mar 6 2007
233 *
234 *-------------------------------------------------------------------------
235 */
236 static void *
H5O_ainfo_copy(const void * _mesg,void * _dest)237 H5O_ainfo_copy(const void *_mesg, void *_dest)
238 {
239 const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg;
240 H5O_ainfo_t *dest = (H5O_ainfo_t *) _dest;
241 void *ret_value = NULL; /* Return value */
242
243 FUNC_ENTER_NOAPI_NOINIT
244
245 /* check args */
246 HDassert(ainfo);
247 if(!dest && NULL == (dest = H5FL_MALLOC(H5O_ainfo_t)))
248 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
249
250 /* copy */
251 *dest = *ainfo;
252
253 /* Set return value */
254 ret_value = dest;
255
256 done:
257 FUNC_LEAVE_NOAPI(ret_value)
258 } /* end H5O_ainfo_copy() */
259
260
261 /*-------------------------------------------------------------------------
262 * Function: H5O_ainfo_size
263 *
264 * Purpose: Returns the size of the raw message in bytes not counting
265 * the message type or size fields, but only the data fields.
266 * This function doesn't take into account alignment.
267 *
268 * Return: Success: Message data size in bytes without alignment.
269 * Failure: zero
270 *
271 * Programmer: Quincey Koziol
272 * koziol@hdfgroup.org
273 * Mar 6 2007
274 *
275 *-------------------------------------------------------------------------
276 */
277 static size_t
H5O_ainfo_size(const H5F_t * f,hbool_t H5_ATTR_UNUSED disable_shared,const void * _mesg)278 H5O_ainfo_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void *_mesg)
279 {
280 const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg;
281 size_t ret_value = 0; /* Return value */
282
283 FUNC_ENTER_NOAPI_NOINIT_NOERR
284
285 /* Set return value */
286 ret_value = (size_t)(1 /* Version */
287 + 1 /* Index flags */
288 + (ainfo->track_corder ? 2 : 0) /* Curr. max. creation order value */
289 + H5F_SIZEOF_ADDR(f) /* Address of fractal heap to store "dense" attributes */
290 + H5F_SIZEOF_ADDR(f) /* Address of v2 B-tree for indexing names of attributes */
291 + (ainfo->index_corder ? H5F_SIZEOF_ADDR(f) : 0)); /* Address of v2 B-tree for indexing creation order values of attributes */
292
293 FUNC_LEAVE_NOAPI(ret_value)
294 } /* end H5O_ainfo_size() */
295
296
297 /*-------------------------------------------------------------------------
298 * Function: H5O__ainfo_free
299 *
300 * Purpose: Frees the message
301 *
302 * Return: Non-negative on success/Negative on failure
303 *
304 * Programmer: Quincey Koziol
305 * Tuesday, March 6, 2007
306 *
307 *-------------------------------------------------------------------------
308 */
309 static herr_t
H5O__ainfo_free(void * mesg)310 H5O__ainfo_free(void *mesg)
311 {
312 FUNC_ENTER_STATIC_NOERR
313
314 HDassert(mesg);
315
316 mesg = H5FL_FREE(H5O_ainfo_t, mesg);
317
318 FUNC_LEAVE_NOAPI(SUCCEED)
319 } /* end H5O__ainfo_free() */
320
321
322 /*-------------------------------------------------------------------------
323 * Function: H5O__ainfo_delete
324 *
325 * Purpose: Free file space referenced by message. Note that open_oh
326 * *must* be non-NULL - this means that calls to
327 * H5O_msg_delete must include an oh if the type is ainfo.
328 *
329 * Return: Non-negative on success/Negative on failure
330 *
331 * Programmer: Quincey Koziol
332 * Tuesday, March 6, 2007
333 *
334 *-------------------------------------------------------------------------
335 */
336 static herr_t
H5O__ainfo_delete(H5F_t * f,H5O_t * open_oh,void * _mesg)337 H5O__ainfo_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
338 {
339 H5O_ainfo_t *ainfo = (H5O_ainfo_t *)_mesg;
340 herr_t ret_value = SUCCEED; /* Return value */
341
342 FUNC_ENTER_STATIC
343
344 /* check args */
345 HDassert(f);
346 HDassert(ainfo);
347 HDassert(open_oh);
348
349 /* If the object is using "dense" attribute storage, delete it */
350 if(H5F_addr_defined(ainfo->fheap_addr))
351 /* Delete the attribute */
352 if(H5A__dense_delete(f, ainfo) < 0)
353 HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage")
354
355 done:
356 FUNC_LEAVE_NOAPI(ret_value)
357 } /* end H5O__ainfo_delete() */
358
359
360 /*-------------------------------------------------------------------------
361 * Function: H5O_ainfo_pre_copy_file
362 *
363 * Purpose: Perform any necessary actions before copying message between
364 * files.
365 *
366 * Return: Success: Non-negative
367 * Failure: Negative
368 *
369 * Programmer: Quincey Koziol
370 * Friday, March 9, 2007
371 *
372 *-------------------------------------------------------------------------
373 */
374 static herr_t
H5O_ainfo_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void H5_ATTR_UNUSED * native_src,hbool_t * deleted,const H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)375 H5O_ainfo_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void H5_ATTR_UNUSED *native_src,
376 hbool_t *deleted, const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
377 {
378 FUNC_ENTER_NOAPI_NOINIT_NOERR
379
380 /* check args */
381 HDassert(deleted);
382 HDassert(cpy_info);
383
384 /* If we are not copying attributes into the destination file, indicate
385 * that this message should be deleted.
386 */
387 if(cpy_info->copy_without_attr)
388 *deleted = TRUE;
389
390 FUNC_LEAVE_NOAPI(SUCCEED)
391 } /* end H5O_ainfo_pre_copy_file() */
392
393
394 /*-------------------------------------------------------------------------
395 * Function: H5O__ainfo_copy_file
396 *
397 * Purpose: Copies a message from _MESG to _DEST in file
398 *
399 * Return: Success: Ptr to _DEST
400 * Failure: NULL
401 *
402 * Programmer: Peter Cao
403 * July 18, 2007
404 *
405 *-------------------------------------------------------------------------
406 */
407 static void *
H5O__ainfo_copy_file(H5F_t * file_src,void * mesg_src,H5F_t * file_dst,hbool_t H5_ATTR_UNUSED * recompute_size,unsigned H5_ATTR_UNUSED * mesg_flags,H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)408 H5O__ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
409 hbool_t H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags,
410 H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
411 {
412 H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
413 H5O_ainfo_t *ainfo_dst = NULL;
414 void *ret_value = NULL; /* Return value */
415
416 FUNC_ENTER_STATIC
417
418 /* check args */
419 HDassert(file_src);
420 HDassert(ainfo_src);
421 HDassert(file_dst);
422 HDassert(cpy_info);
423 HDassert(!cpy_info->copy_without_attr);
424
425 /* Allocate space for the destination message */
426 if(NULL == (ainfo_dst = H5FL_MALLOC(H5O_ainfo_t)))
427 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
428
429 /* Copy the top level of the information */
430 *ainfo_dst = *ainfo_src;
431
432 if(H5F_addr_defined(ainfo_src->fheap_addr)) {
433 /* Prepare to copy dense attributes - actual copy in post_copy */
434
435 /* Set copied metadata tag */
436 H5_BEGIN_TAG(H5AC__COPIED_TAG);
437
438 if(H5A__dense_create(file_dst, ainfo_dst) < 0)
439 HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")
440
441 /* Reset metadata tag */
442 H5_END_TAG
443 } /* end if */
444
445 /* Set return value */
446 ret_value = ainfo_dst;
447
448 done:
449 /* Release destination attribute information on failure */
450 if(!ret_value && ainfo_dst)
451 ainfo_dst = H5FL_FREE(H5O_ainfo_t, ainfo_dst);
452
453 FUNC_LEAVE_NOAPI(ret_value)
454 } /* H5O__ainfo_copy_file() */
455
456
457 /*-------------------------------------------------------------------------
458 * Function: H5O__ainfo_post_copy_file
459 *
460 * Purpose: Finish copying a message from between files.
461 * We have to copy the values of a reference attribute in the
462 * post copy because H5O_post_copy_file() fails in the case that
463 * an object may have a reference attribute that points to the
464 * object itself.
465 *
466 * Return: Non-negative on success/Negative on failure
467 *
468 * Programmer: Peter Cao
469 * July 25, 2007
470 *
471 *-------------------------------------------------------------------------
472 */
473 static herr_t
H5O__ainfo_post_copy_file(const H5O_loc_t * src_oloc,const void * mesg_src,H5O_loc_t * dst_oloc,void * mesg_dst,unsigned H5_ATTR_UNUSED * mesg_flags,H5O_copy_t * cpy_info)474 H5O__ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
475 H5O_loc_t *dst_oloc, void *mesg_dst, unsigned H5_ATTR_UNUSED *mesg_flags,
476 H5O_copy_t *cpy_info)
477 {
478 const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src;
479 herr_t ret_value = SUCCEED; /* Return value */
480
481 FUNC_ENTER_STATIC
482
483 HDassert(ainfo_src);
484
485 if(H5F_addr_defined(ainfo_src->fheap_addr))
486 if(H5A__dense_post_copy_file_all(src_oloc, ainfo_src, dst_oloc, (H5O_ainfo_t *)mesg_dst, cpy_info) < 0)
487 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
488
489 done:
490 FUNC_LEAVE_NOAPI(ret_value)
491 } /* H5O__ainfo_post_copy_file() */
492
493
494 /*-------------------------------------------------------------------------
495 * Function: H5O__ainfo_debug
496 *
497 * Purpose: Prints debugging info for a message.
498 *
499 * Return: Non-negative on success/Negative on failure
500 *
501 * Programmer: Quincey Koziol
502 * koziol@hdfgroup.org
503 * Mar 6 2007
504 *
505 *-------------------------------------------------------------------------
506 */
507 static herr_t
H5O__ainfo_debug(H5F_t H5_ATTR_UNUSED * f,const void * _mesg,FILE * stream,int indent,int fwidth)508 H5O__ainfo_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE * stream,
509 int indent, int fwidth)
510 {
511 const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *) _mesg;
512
513 FUNC_ENTER_STATIC_NOERR
514
515 /* check args */
516 HDassert(f);
517 HDassert(ainfo);
518 HDassert(stream);
519 HDassert(indent >= 0);
520 HDassert(fwidth >= 0);
521
522 HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
523 "Number of attributes:", ainfo->nattrs);
524 HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
525 "Track creation order of attributes:", ainfo->track_corder);
526 HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
527 "Index creation order of attributes:", ainfo->index_corder);
528 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
529 "Max. creation index value:", (unsigned)ainfo->max_crt_idx);
530 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
531 "'Dense' attribute storage fractal heap address:", ainfo->fheap_addr);
532 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
533 "'Dense' attribute storage name index v2 B-tree address:", ainfo->name_bt2_addr);
534 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
535 "'Dense' attribute storage creation order index v2 B-tree address:", ainfo->corder_bt2_addr);
536
537
538 FUNC_LEAVE_NOAPI(SUCCEED)
539 } /* end H5O__ainfo_debug() */
540
541