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_PACKAGE /*suppress error about including H5Apkg */
26 #define H5O_PACKAGE /*suppress error about including H5Opkg */
27
28 #include "H5private.h" /* Generic Functions */
29 #include "H5Apkg.h" /* Attributes */
30 #include "H5Eprivate.h" /* Error handling */
31 #include "H5FLprivate.h" /* Free lists */
32 #include "H5Opkg.h" /* Object headers */
33
34
35 /* PRIVATE PROTOTYPES */
36 static void *H5O_ainfo_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
37 unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
38 static herr_t H5O_ainfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
39 static void *H5O_ainfo_copy(const void *_mesg, void *_dest);
40 static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
41 static herr_t H5O_ainfo_free(void *_mesg);
42 static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
43 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, hid_t dxpl_id);
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, hid_t dxpl_id, H5O_copy_t *cpy_info);
52 static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
53 FILE * stream, 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,hid_t H5_ATTR_UNUSED dxpl_id,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, hid_t H5_ATTR_UNUSED dxpl_id, 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; /* Return value */
113
114 FUNC_ENTER_NOAPI_NOINIT
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; /* 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; /* 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: Free's 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_NOAPI_NOINIT_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
326 *
327 * Return: Non-negative on success/Negative on failure
328 *
329 * Programmer: Quincey Koziol
330 * Tuesday, March 6, 2007
331 *
332 *-------------------------------------------------------------------------
333 */
334 static herr_t
H5O_ainfo_delete(H5F_t * f,hid_t dxpl_id,H5O_t H5_ATTR_UNUSED * open_oh,void * _mesg)335 H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, void *_mesg)
336 {
337 H5O_ainfo_t *ainfo = (H5O_ainfo_t *)_mesg;
338 herr_t ret_value = SUCCEED; /* Return value */
339
340 FUNC_ENTER_NOAPI_NOINIT
341
342 /* check args */
343 HDassert(f);
344 HDassert(ainfo);
345
346 /* If the object is using "dense" attribute storage, delete it */
347 if(H5F_addr_defined(ainfo->fheap_addr))
348 if(H5A_dense_delete(f, dxpl_id, ainfo) < 0)
349 HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage")
350
351 done:
352 FUNC_LEAVE_NOAPI(ret_value)
353 } /* end H5O_ainfo_delete() */
354
355
356 /*-------------------------------------------------------------------------
357 * Function: H5O_ainfo_pre_copy_file
358 *
359 * Purpose: Perform any necessary actions before copying message between
360 * files.
361 *
362 * Return: Success: Non-negative
363 * Failure: Negative
364 *
365 * Programmer: Quincey Koziol
366 * Friday, March 9, 2007
367 *
368 *-------------------------------------------------------------------------
369 */
370 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)371 H5O_ainfo_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void H5_ATTR_UNUSED *native_src,
372 hbool_t *deleted, const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
373 {
374 FUNC_ENTER_NOAPI_NOINIT_NOERR
375
376 /* check args */
377 HDassert(deleted);
378 HDassert(cpy_info);
379
380 /* If we are not copying attributes into the destination file, indicate
381 * that this message should be deleted.
382 */
383 if(cpy_info->copy_without_attr)
384 *deleted = TRUE;
385
386 FUNC_LEAVE_NOAPI(SUCCEED)
387 } /* end H5O_ainfo_pre_copy_file() */
388
389
390 /*-------------------------------------------------------------------------
391 * Function: H5O_ainfo_copy_file
392 *
393 * Purpose: Copies a message from _MESG to _DEST in file
394 *
395 * Return: Success: Ptr to _DEST
396 * Failure: NULL
397 *
398 * Programmer: Peter Cao
399 * July 18, 2007
400 *
401 *-------------------------------------------------------------------------
402 */
403 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,hid_t dxpl_id)404 H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
405 hbool_t H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags,
406 H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata, hid_t dxpl_id)
407 {
408 H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
409 H5O_ainfo_t *ainfo_dst = NULL;
410 void *ret_value; /* Return value */
411
412 FUNC_ENTER_NOAPI_NOINIT
413
414 /* check args */
415 HDassert(file_src);
416 HDassert(ainfo_src);
417 HDassert(file_dst);
418 HDassert(cpy_info);
419 HDassert(!cpy_info->copy_without_attr);
420
421 /* Allocate space for the destination message */
422 if(NULL == (ainfo_dst = H5FL_MALLOC(H5O_ainfo_t)))
423 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
424
425 /* Copy the top level of the information */
426 *ainfo_dst = *ainfo_src;
427
428 if(H5F_addr_defined(ainfo_src->fheap_addr)) {
429 /* copy dense attribute */
430
431 if(H5A_dense_create(file_dst, dxpl_id, ainfo_dst) < 0)
432 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")
433 } /* end if */
434
435 /* Set return value */
436 ret_value = ainfo_dst;
437
438 done:
439 /* Release destination attribute information on failure */
440 if(!ret_value && ainfo_dst)
441 ainfo_dst = H5FL_FREE(H5O_ainfo_t, ainfo_dst);
442
443 FUNC_LEAVE_NOAPI(ret_value)
444 } /* H5O_ainfo_copy_file() */
445
446
447 /*-------------------------------------------------------------------------
448 * Function: H5O_ainfo_post_copy_file
449 *
450 * Purpose: Finish copying a message from between files.
451 * We have to copy the values of a reference attribute in the
452 * post copy because H5O_post_copy_file() fails in the case that
453 * an object may have a reference attribute that points to the
454 * object itself.
455 *
456 * Return: Non-negative on success/Negative on failure
457 *
458 * Programmer: Peter Cao
459 * July 25, 2007
460 *
461 *-------------------------------------------------------------------------
462 */
463 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,hid_t dxpl_id,H5O_copy_t * cpy_info)464 H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
465 H5O_loc_t *dst_oloc, void *mesg_dst, unsigned H5_ATTR_UNUSED *mesg_flags,
466 hid_t dxpl_id, H5O_copy_t *cpy_info)
467 {
468 const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src;
469 herr_t ret_value = SUCCEED; /* Return value */
470
471 FUNC_ENTER_NOAPI_NOINIT
472
473 HDassert(ainfo_src);
474
475 if(H5F_addr_defined(ainfo_src->fheap_addr)) {
476 if(H5A_dense_post_copy_file_all(src_oloc, ainfo_src, dst_oloc,
477 (H5O_ainfo_t *)mesg_dst, dxpl_id, cpy_info) < 0)
478 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
479 } /* end if */
480
481 done:
482 FUNC_LEAVE_NOAPI(ret_value)
483 } /* H5O_ainfo_post_copy_file() */
484
485
486 /*-------------------------------------------------------------------------
487 * Function: H5O_ainfo_debug
488 *
489 * Purpose: Prints debugging info for a message.
490 *
491 * Return: Non-negative on success/Negative on failure
492 *
493 * Programmer: Quincey Koziol
494 * koziol@hdfgroup.org
495 * Mar 6 2007
496 *
497 *-------------------------------------------------------------------------
498 */
499 static herr_t
H5O_ainfo_debug(H5F_t H5_ATTR_UNUSED * f,hid_t H5_ATTR_UNUSED dxpl_id,const void * _mesg,FILE * stream,int indent,int fwidth)500 H5O_ainfo_debug(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, const void *_mesg, FILE * stream,
501 int indent, int fwidth)
502 {
503 const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *) _mesg;
504
505 FUNC_ENTER_NOAPI_NOINIT_NOERR
506
507 /* check args */
508 HDassert(f);
509 HDassert(ainfo);
510 HDassert(stream);
511 HDassert(indent >= 0);
512 HDassert(fwidth >= 0);
513
514 HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
515 "Number of attributes:", ainfo->nattrs);
516 HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
517 "Track creation order of attributes:", ainfo->track_corder);
518 HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
519 "Index creation order of attributes:", ainfo->index_corder);
520 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
521 "Max. creation index value:", (unsigned)ainfo->max_crt_idx);
522 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
523 "'Dense' attribute storage fractal heap address:", ainfo->fheap_addr);
524 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
525 "'Dense' attribute storage name index v2 B-tree address:", ainfo->name_bt2_addr);
526 HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
527 "'Dense' attribute storage creation order index v2 B-tree address:", ainfo->corder_bt2_addr);
528
529
530 FUNC_LEAVE_NOAPI(SUCCEED)
531 } /* end H5O_ainfo_debug() */
532
533