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