Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5Ostab.c |
16 | | * |
17 | | * Purpose: Symbol table messages |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | #define H5G_FRIEND /*suppress error about including H5Gpkg */ |
23 | | #include "H5Omodule.h" /* This source code file is part of the H5O module */ |
24 | | |
25 | | #include "H5private.h" /* Generic Functions */ |
26 | | #include "H5Eprivate.h" /* Error handling */ |
27 | | #include "H5FLprivate.h" /* Free lists */ |
28 | | #include "H5Gpkg.h" /* Groups */ |
29 | | #include "H5HLprivate.h" /* Local Heaps */ |
30 | | #include "H5Opkg.h" /* Object headers */ |
31 | | |
32 | | /* PRIVATE PROTOTYPES */ |
33 | | static void *H5O__stab_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size, |
34 | | const uint8_t *p); |
35 | | static herr_t H5O__stab_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
36 | | const void *_mesg); |
37 | | static void *H5O__stab_copy(const void *_mesg, void *_dest); |
38 | | static size_t H5O__stab_size(const H5F_t *f, bool disable_shared, const void *_mesg); |
39 | | static herr_t H5O__stab_free(void *_mesg); |
40 | | static herr_t H5O__stab_delete(H5F_t *f, H5O_t *open_oh, void *_mesg); |
41 | | static void *H5O__stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, bool *recompute_size, |
42 | | unsigned *mesg_flags, H5O_copy_t *cpy_info, void *_udata); |
43 | | static herr_t H5O__stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, |
44 | | void *mesg_dst, unsigned *mesg_flags, H5O_copy_t *cpy_info); |
45 | | static herr_t H5O__stab_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); |
46 | | |
47 | | /* This message derives from H5O message class */ |
48 | | const H5O_msg_class_t H5O_MSG_STAB[1] = {{ |
49 | | H5O_STAB_ID, /*message id number */ |
50 | | "stab", /*message name for debugging */ |
51 | | sizeof(H5O_stab_t), /*native message size */ |
52 | | 0, /* messages are shareable? */ |
53 | | H5O__stab_decode, /*decode message */ |
54 | | H5O__stab_encode, /*encode message */ |
55 | | H5O__stab_copy, /*copy the native value */ |
56 | | H5O__stab_size, /*size of symbol table entry */ |
57 | | NULL, /*default reset method */ |
58 | | H5O__stab_free, /* free method */ |
59 | | H5O__stab_delete, /* file delete method */ |
60 | | NULL, /* link method */ |
61 | | NULL, /*set share method */ |
62 | | NULL, /*can share method */ |
63 | | NULL, /* pre copy native value to file */ |
64 | | H5O__stab_copy_file, /* copy native value to file */ |
65 | | H5O__stab_post_copy_file, /* post copy native value to file */ |
66 | | NULL, /* get creation index */ |
67 | | NULL, /* set creation index */ |
68 | | H5O__stab_debug /*debug the message */ |
69 | | }}; |
70 | | |
71 | | /* Declare a free list to manage the H5O_stab_t struct */ |
72 | | H5FL_DEFINE_STATIC(H5O_stab_t); |
73 | | |
74 | | /*------------------------------------------------------------------------- |
75 | | * Function: H5O__stab_decode |
76 | | * |
77 | | * Purpose: Decode a symbol table message and return a pointer to |
78 | | * a newly allocated one. |
79 | | * |
80 | | * Return: Success: Pointer to new message in native order |
81 | | * Failure: NULL |
82 | | *------------------------------------------------------------------------- |
83 | | */ |
84 | | static void * |
85 | | H5O__stab_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, |
86 | | unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p) |
87 | 11.7k | { |
88 | 11.7k | H5O_stab_t *stab = NULL; |
89 | 11.7k | const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */ |
90 | 11.7k | void *ret_value = NULL; |
91 | | |
92 | 11.7k | FUNC_ENTER_PACKAGE |
93 | | |
94 | 11.7k | assert(f); |
95 | 11.7k | assert(p); |
96 | | |
97 | 11.7k | if (NULL == (stab = H5FL_CALLOC(H5O_stab_t))) |
98 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
99 | | |
100 | 11.7k | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end)) |
101 | 17 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
102 | 11.6k | H5F_addr_decode(f, &p, &(stab->btree_addr)); |
103 | | |
104 | 11.6k | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end)) |
105 | 83 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
106 | 11.6k | H5F_addr_decode(f, &p, &(stab->heap_addr)); |
107 | | |
108 | 11.6k | ret_value = stab; |
109 | | |
110 | 11.7k | done: |
111 | 11.7k | if (!ret_value && stab) |
112 | 100 | H5FL_FREE(H5O_stab_t, stab); |
113 | | |
114 | 11.7k | FUNC_LEAVE_NOAPI(ret_value) |
115 | 11.7k | } /* end H5O__stab_decode() */ |
116 | | |
117 | | /*------------------------------------------------------------------------- |
118 | | * Function: H5O__stab_encode |
119 | | * |
120 | | * Purpose: Encodes a symbol table message. |
121 | | * |
122 | | * Return: Non-negative on success/Negative on failure |
123 | | * |
124 | | *------------------------------------------------------------------------- |
125 | | */ |
126 | | static herr_t |
127 | | H5O__stab_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
128 | | const void *_mesg) |
129 | 0 | { |
130 | 0 | const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; |
131 | |
|
132 | 0 | FUNC_ENTER_PACKAGE_NOERR |
133 | | |
134 | | /* check args */ |
135 | 0 | assert(f); |
136 | 0 | assert(p); |
137 | 0 | assert(stab); |
138 | | |
139 | | /* encode */ |
140 | 0 | H5F_addr_encode(f, &p, stab->btree_addr); |
141 | 0 | H5F_addr_encode(f, &p, stab->heap_addr); |
142 | |
|
143 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
144 | 0 | } /* end H5O__stab_encode() */ |
145 | | |
146 | | /*------------------------------------------------------------------------- |
147 | | * Function: H5O__stab_copy |
148 | | * |
149 | | * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if |
150 | | * necessary. |
151 | | * |
152 | | * Return: Success: Ptr to _DEST |
153 | | * |
154 | | * Failure: NULL |
155 | | * |
156 | | *------------------------------------------------------------------------- |
157 | | */ |
158 | | static void * |
159 | | H5O__stab_copy(const void *_mesg, void *_dest) |
160 | 356k | { |
161 | 356k | const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; |
162 | 356k | H5O_stab_t *dest = (H5O_stab_t *)_dest; |
163 | 356k | void *ret_value = NULL; /* Return value */ |
164 | | |
165 | 356k | FUNC_ENTER_PACKAGE |
166 | | |
167 | | /* check args */ |
168 | 356k | assert(stab); |
169 | 356k | if (!dest && NULL == (dest = H5FL_MALLOC(H5O_stab_t))) |
170 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
171 | | |
172 | | /* copy */ |
173 | 356k | *dest = *stab; |
174 | | |
175 | | /* Set return value */ |
176 | 356k | ret_value = dest; |
177 | | |
178 | 356k | done: |
179 | 356k | FUNC_LEAVE_NOAPI(ret_value) |
180 | 356k | } /* end H5O__stab_copy() */ |
181 | | |
182 | | /*------------------------------------------------------------------------- |
183 | | * Function: H5O__stab_size |
184 | | * |
185 | | * Purpose: Returns the size of the raw message in bytes not counting |
186 | | * the message type or size fields, but only the data fields. |
187 | | * This function doesn't take into account alignment. |
188 | | * |
189 | | * Return: Success: Message data size in bytes without alignment. |
190 | | * |
191 | | * Failure: zero |
192 | | * |
193 | | *------------------------------------------------------------------------- |
194 | | */ |
195 | | static size_t |
196 | | H5O__stab_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void H5_ATTR_UNUSED *_mesg) |
197 | 0 | { |
198 | 0 | size_t ret_value = 0; /* Return value */ |
199 | |
|
200 | 0 | FUNC_ENTER_PACKAGE_NOERR |
201 | | |
202 | | /* Set return value */ |
203 | 0 | ret_value = (size_t)(2 * H5F_SIZEOF_ADDR(f)); |
204 | |
|
205 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
206 | 0 | } /* end H5O__stab_size() */ |
207 | | |
208 | | /*------------------------------------------------------------------------- |
209 | | * Function: H5O__stab_free |
210 | | * |
211 | | * Purpose: Frees the message |
212 | | * |
213 | | * Return: Non-negative on success/Negative on failure |
214 | | * |
215 | | *------------------------------------------------------------------------- |
216 | | */ |
217 | | static herr_t |
218 | | H5O__stab_free(void *mesg) |
219 | 11.6k | { |
220 | 11.6k | FUNC_ENTER_PACKAGE_NOERR |
221 | | |
222 | 11.6k | assert(mesg); |
223 | | |
224 | 11.6k | mesg = H5FL_FREE(H5O_stab_t, mesg); |
225 | | |
226 | 11.6k | FUNC_LEAVE_NOAPI(SUCCEED) |
227 | 11.6k | } /* end H5O__stab_free() */ |
228 | | |
229 | | /*------------------------------------------------------------------------- |
230 | | * Function: H5O__stab_delete |
231 | | * |
232 | | * Purpose: Free file space referenced by message |
233 | | * |
234 | | * Return: Non-negative on success/Negative on failure |
235 | | * |
236 | | *------------------------------------------------------------------------- |
237 | | */ |
238 | | static herr_t |
239 | | H5O__stab_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *mesg) |
240 | 0 | { |
241 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
242 | |
|
243 | 0 | FUNC_ENTER_PACKAGE |
244 | | |
245 | | /* check args */ |
246 | 0 | assert(f); |
247 | 0 | assert(mesg); |
248 | | |
249 | | /* Free the file space for the symbol table */ |
250 | 0 | if (H5G__stab_delete(f, (const H5O_stab_t *)mesg) < 0) |
251 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free symbol table"); |
252 | | |
253 | 0 | done: |
254 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
255 | 0 | } /* end H5O__stab_delete() */ |
256 | | |
257 | | /*------------------------------------------------------------------------- |
258 | | * Function: H5O__stab_copy_file |
259 | | * |
260 | | * Purpose: Copies a message from _MESG to _DEST in file |
261 | | * |
262 | | * Return: Success: Ptr to _DEST |
263 | | * |
264 | | * Failure: NULL |
265 | | * |
266 | | *------------------------------------------------------------------------- |
267 | | */ |
268 | | static void * |
269 | | H5O__stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, bool H5_ATTR_UNUSED *recompute_size, |
270 | | unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t H5_ATTR_UNUSED *cpy_info, void *_udata) |
271 | 0 | { |
272 | 0 | H5O_stab_t *stab_src = (H5O_stab_t *)native_src; |
273 | 0 | H5O_stab_t *stab_dst = NULL; |
274 | 0 | H5G_copy_file_ud_t *udata = (H5G_copy_file_ud_t *)_udata; |
275 | 0 | size_t size_hint; /* Local heap initial size */ |
276 | 0 | void *ret_value = NULL; /* Return value */ |
277 | |
|
278 | 0 | FUNC_ENTER_PACKAGE |
279 | | |
280 | | /* check args */ |
281 | 0 | assert(stab_src); |
282 | 0 | assert(file_dst); |
283 | | |
284 | | /* Allocate space for the destination stab */ |
285 | 0 | if (NULL == (stab_dst = H5FL_MALLOC(H5O_stab_t))) |
286 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
287 | | |
288 | | /* Get the old local heap's size and use that as the hint for the new heap */ |
289 | 0 | if (H5HL_get_size(file_src, stab_src->heap_addr, &size_hint) < 0) |
290 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, NULL, "can't query local heap size"); |
291 | | |
292 | | /* Set copy metadata tag */ |
293 | 0 | H5_BEGIN_TAG(H5AC__COPIED_TAG) |
294 | | |
295 | | /* Create components of symbol table message */ |
296 | 0 | if (H5G__stab_create_components(file_dst, stab_dst, size_hint) < 0) |
297 | 0 | HGOTO_ERROR_TAG(H5E_SYM, H5E_CANTINIT, NULL, "can't create symbol table components"); |
298 | | |
299 | | /* Reset metadata tag */ |
300 | 0 | H5_END_TAG |
301 | | |
302 | | /* Cache stab in udata */ |
303 | 0 | udata->cache_type = H5G_CACHED_STAB; |
304 | 0 | udata->cache.stab.btree_addr = stab_dst->btree_addr; |
305 | 0 | udata->cache.stab.heap_addr = stab_dst->heap_addr; |
306 | | |
307 | | /* Set return value */ |
308 | 0 | ret_value = stab_dst; |
309 | |
|
310 | 0 | done: |
311 | 0 | if (!ret_value) |
312 | 0 | if (stab_dst) |
313 | 0 | stab_dst = H5FL_FREE(H5O_stab_t, stab_dst); |
314 | |
|
315 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
316 | 0 | } /* H5O__stab_copy_file() */ |
317 | | |
318 | | /*------------------------------------------------------------------------- |
319 | | * Function: H5O__stab_post_copy_file |
320 | | * |
321 | | * Purpose: Finish copying a message from between files |
322 | | * |
323 | | * Return: Non-negative on success/Negative on failure |
324 | | * |
325 | | *------------------------------------------------------------------------- |
326 | | */ |
327 | | static herr_t |
328 | | H5O__stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, |
329 | | unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t *cpy_info) |
330 | 0 | { |
331 | 0 | const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src; |
332 | 0 | H5O_stab_t *stab_dst = (H5O_stab_t *)mesg_dst; |
333 | 0 | H5G_bt_it_cpy_t udata; /* B-tree user data */ |
334 | 0 | H5HL_t *heap = NULL; /* Pointer to source group's heap */ |
335 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
336 | |
|
337 | 0 | FUNC_ENTER_PACKAGE |
338 | | |
339 | | /* check args */ |
340 | 0 | assert(stab_src); |
341 | 0 | assert(H5_addr_defined(dst_oloc->addr)); |
342 | 0 | assert(dst_oloc->file); |
343 | 0 | assert(stab_dst); |
344 | 0 | assert(cpy_info); |
345 | | |
346 | | /* If we are performing a 'shallow hierarchy' copy, get out now */ |
347 | 0 | if (cpy_info->max_depth >= 0 && cpy_info->curr_depth >= cpy_info->max_depth) |
348 | 0 | HGOTO_DONE(SUCCEED); |
349 | | |
350 | | /* Get the heap for the copy*/ |
351 | 0 | if (NULL == (heap = H5HL_protect(src_oloc->file, stab_src->heap_addr, H5AC__READ_ONLY_FLAG))) |
352 | 0 | HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect local heap"); |
353 | | |
354 | | /* Set up B-tree iteration user data */ |
355 | 0 | udata.src_oloc = src_oloc; |
356 | 0 | udata.src_heap = heap; |
357 | 0 | udata.src_block_size = H5HL_heap_get_size(heap); |
358 | 0 | udata.dst_file = dst_oloc->file; |
359 | 0 | udata.dst_stab = stab_dst; |
360 | 0 | udata.cpy_info = cpy_info; |
361 | | |
362 | | /* Iterate over objects in group, copying them */ |
363 | 0 | if ((H5B_iterate(src_oloc->file, H5B_SNODE, stab_src->btree_addr, H5G__node_copy, &udata)) < 0) |
364 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed"); |
365 | | |
366 | 0 | done: |
367 | 0 | if (heap && H5HL_unprotect(heap) < 0) |
368 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTUNPROTECT, FAIL, "unable to unprotect local heap"); |
369 | |
|
370 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
371 | 0 | } /* H5O__stab_post_copy_file() */ |
372 | | |
373 | | /*------------------------------------------------------------------------- |
374 | | * Function: H5O__stab_debug |
375 | | * |
376 | | * Purpose: Prints debugging info for a symbol table message. |
377 | | * |
378 | | * Return: Non-negative on success/Negative on failure |
379 | | * |
380 | | *------------------------------------------------------------------------- |
381 | | */ |
382 | | static herr_t |
383 | | H5O__stab_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth) |
384 | 0 | { |
385 | 0 | const H5O_stab_t *stab = (const H5O_stab_t *)_mesg; |
386 | |
|
387 | 0 | FUNC_ENTER_PACKAGE_NOERR |
388 | | |
389 | | /* check args */ |
390 | 0 | assert(f); |
391 | 0 | assert(stab); |
392 | 0 | assert(stream); |
393 | 0 | assert(indent >= 0); |
394 | 0 | assert(fwidth >= 0); |
395 | |
|
396 | 0 | fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "B-tree address:", stab->btree_addr); |
397 | |
|
398 | 0 | fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Name heap address:", stab->heap_addr); |
399 | |
|
400 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
401 | 0 | } /* end H5O__stab_debug() */ |