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 | | /* Module Setup */ |
15 | | /****************/ |
16 | | |
17 | | #include "H5Gmodule.h" /* This source code file is part of the H5G module */ |
18 | | #define H5O_FRIEND /*suppress error about including H5Opkg */ |
19 | | |
20 | | /***********/ |
21 | | /* Headers */ |
22 | | /***********/ |
23 | | #include "H5private.h" /* Generic Functions */ |
24 | | #include "H5Eprivate.h" /* Error handling */ |
25 | | #include "H5FLprivate.h" /* Free Lists */ |
26 | | #include "H5Gpkg.h" /* Groups */ |
27 | | #include "H5Iprivate.h" /* IDs */ |
28 | | #include "H5Opkg.h" /* Object headers */ |
29 | | #include "H5VLprivate.h" /* Virtual Object Layer */ |
30 | | |
31 | | /****************/ |
32 | | /* Local Macros */ |
33 | | /****************/ |
34 | | |
35 | | /******************/ |
36 | | /* Local Typedefs */ |
37 | | /******************/ |
38 | | |
39 | | /********************/ |
40 | | /* Local Prototypes */ |
41 | | /********************/ |
42 | | |
43 | | static void *H5O__group_get_copy_file_udata(void); |
44 | | static void H5O__group_free_copy_file_udata(void *udata); |
45 | | static htri_t H5O__group_isa(const H5O_t *loc); |
46 | | static void *H5O__group_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type); |
47 | | static void *H5O__group_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc); |
48 | | static H5O_loc_t *H5O__group_get_oloc(hid_t obj_id); |
49 | | static herr_t H5O__group_bh_info(const H5O_loc_t *loc, H5O_t *oh, H5_ih_info_t *bh_info); |
50 | | |
51 | | /*********************/ |
52 | | /* Package Variables */ |
53 | | /*********************/ |
54 | | |
55 | | /*****************************/ |
56 | | /* Library Private Variables */ |
57 | | /*****************************/ |
58 | | |
59 | | /*******************/ |
60 | | /* Local Variables */ |
61 | | /*******************/ |
62 | | |
63 | | /* This message derives from H5O object class */ |
64 | | const H5O_obj_class_t H5O_OBJ_GROUP[1] = {{ |
65 | | H5O_TYPE_GROUP, /* object type */ |
66 | | "group", /* object name, for debugging */ |
67 | | H5O__group_get_copy_file_udata, /* get 'copy file' user data */ |
68 | | H5O__group_free_copy_file_udata, /* free 'copy file' user data */ |
69 | | H5O__group_isa, /* "isa" message */ |
70 | | H5O__group_open, /* open an object of this class */ |
71 | | H5O__group_create, /* create an object of this class */ |
72 | | H5O__group_get_oloc, /* get an object header location for an object */ |
73 | | H5O__group_bh_info, /* get the index & heap info for an object */ |
74 | | NULL /* flush an opened object of this class */ |
75 | | }}; |
76 | | |
77 | | /* Declare the external free list to manage the H5O_ginfo_t struct */ |
78 | | H5FL_DEFINE(H5G_copy_file_ud_t); |
79 | | |
80 | | /*------------------------------------------------------------------------- |
81 | | * Function: H5O__group_get_copy_file_udata |
82 | | * |
83 | | * Purpose: Allocates the user data needed for copying a group's |
84 | | * object header from file to file. |
85 | | * |
86 | | * Return: Success: Non-NULL pointer to user data |
87 | | * |
88 | | * Failure: NULL |
89 | | * |
90 | | *------------------------------------------------------------------------- |
91 | | */ |
92 | | static void * |
93 | | H5O__group_get_copy_file_udata(void) |
94 | 0 | { |
95 | 0 | void *ret_value = NULL; /* Return value */ |
96 | |
|
97 | 0 | FUNC_ENTER_PACKAGE |
98 | | |
99 | | /* Allocate space for the 'copy file' user data for copying groups. |
100 | | * Currently this is only a ginfo, so there is no specific struct type for |
101 | | * this operation. */ |
102 | 0 | if (NULL == (ret_value = H5FL_CALLOC(H5G_copy_file_ud_t))) |
103 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
104 | | |
105 | 0 | done: |
106 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
107 | 0 | } /* end H5O__group_get_copy_file_udata() */ |
108 | | |
109 | | /*------------------------------------------------------------------------- |
110 | | * Function: H5O__group_free_copy_file_udata |
111 | | * |
112 | | * Purpose: Release the user data needed for copying a group's |
113 | | * object header from file to file. |
114 | | * |
115 | | * Return: <none> |
116 | | * |
117 | | *------------------------------------------------------------------------- |
118 | | */ |
119 | | static void |
120 | | H5O__group_free_copy_file_udata(void *_udata) |
121 | 0 | { |
122 | 0 | H5G_copy_file_ud_t *udata = (H5G_copy_file_ud_t *)_udata; |
123 | |
|
124 | 0 | FUNC_ENTER_PACKAGE_NOERR |
125 | | |
126 | | /* Sanity check */ |
127 | 0 | assert(udata); |
128 | | |
129 | | /* Free the ginfo struct (including nested data structs) */ |
130 | 0 | H5O_msg_free(H5O_PLINE_ID, udata->common.src_pline); |
131 | | |
132 | | /* Release space for 'copy file' user data (ginfo struct) */ |
133 | 0 | udata = H5FL_FREE(H5G_copy_file_ud_t, udata); |
134 | |
|
135 | 0 | FUNC_LEAVE_NOAPI_VOID |
136 | 0 | } /* end H5O__group_free_copy_file_udata() */ |
137 | | |
138 | | /*------------------------------------------------------------------------- |
139 | | * Function: H5O__group_isa |
140 | | * |
141 | | * Purpose: Determines if an object has the requisite messages for being |
142 | | * a group. |
143 | | * |
144 | | * Return: Success: true if the required group messages are |
145 | | * present; false otherwise. |
146 | | * |
147 | | * Failure: FAIL if the existence of certain messages |
148 | | * cannot be determined. |
149 | | * |
150 | | *------------------------------------------------------------------------- |
151 | | */ |
152 | | static htri_t |
153 | | H5O__group_isa(const H5O_t *oh) |
154 | 13.4k | { |
155 | 13.4k | htri_t stab_exists; /* Whether the 'stab' message is in the object header */ |
156 | 13.4k | htri_t linfo_exists; /* Whether the 'linfo' message is in the object header */ |
157 | 13.4k | htri_t ret_value = FAIL; /* Return value */ |
158 | | |
159 | 13.4k | FUNC_ENTER_PACKAGE |
160 | | |
161 | 13.4k | assert(oh); |
162 | | |
163 | | /* Check for any of the messages that indicate a group */ |
164 | 13.4k | if ((stab_exists = H5O_msg_exists_oh(oh, H5O_STAB_ID)) < 0) |
165 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header"); |
166 | 13.4k | if ((linfo_exists = H5O_msg_exists_oh(oh, H5O_LINFO_ID)) < 0) |
167 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header"); |
168 | | |
169 | 13.4k | ret_value = (stab_exists > 0 || linfo_exists > 0); |
170 | | |
171 | 13.4k | done: |
172 | 13.4k | FUNC_LEAVE_NOAPI(ret_value) |
173 | 13.4k | } /* end H5O__group_isa() */ |
174 | | |
175 | | /*------------------------------------------------------------------------- |
176 | | * Function: H5O__group_open |
177 | | * |
178 | | * Purpose: Open a group at a particular location |
179 | | * |
180 | | * Return: Success: Pointer to group data |
181 | | * Failure: NULL |
182 | | * |
183 | | *------------------------------------------------------------------------- |
184 | | */ |
185 | | static void * |
186 | | H5O__group_open(const H5G_loc_t *obj_loc, H5I_type_t *opened_type) |
187 | 249 | { |
188 | 249 | H5G_t *grp = NULL; /* Group opened */ |
189 | 249 | void *ret_value = NULL; /* Return value */ |
190 | | |
191 | 249 | FUNC_ENTER_PACKAGE |
192 | | |
193 | 249 | assert(obj_loc); |
194 | | |
195 | 249 | *opened_type = H5I_GROUP; |
196 | | |
197 | | /* Open the group */ |
198 | 249 | if (NULL == (grp = H5G_open(obj_loc))) |
199 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group"); |
200 | | |
201 | 249 | ret_value = (void *)grp; |
202 | | |
203 | 249 | done: |
204 | 249 | if (NULL == ret_value) |
205 | 0 | if (grp && H5G_close(grp) < 0) |
206 | 0 | HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release group"); |
207 | | |
208 | 249 | FUNC_LEAVE_NOAPI(ret_value) |
209 | 249 | } /* end H5O__group_open() */ |
210 | | |
211 | | /*------------------------------------------------------------------------- |
212 | | * Function: H5O__group_create |
213 | | * |
214 | | * Purpose: Create a group in a file |
215 | | * |
216 | | * Return: Success: Pointer to the group data structure |
217 | | * Failure: NULL |
218 | | * |
219 | | *------------------------------------------------------------------------- |
220 | | */ |
221 | | static void * |
222 | | H5O__group_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc) |
223 | 0 | { |
224 | 0 | H5G_obj_create_t *crt_info = (H5G_obj_create_t *)_crt_info; /* Group creation parameters */ |
225 | 0 | H5G_t *grp = NULL; /* New group created */ |
226 | 0 | void *ret_value = NULL; /* Return value */ |
227 | |
|
228 | 0 | FUNC_ENTER_PACKAGE |
229 | | |
230 | | /* Sanity checks */ |
231 | 0 | assert(f); |
232 | 0 | assert(crt_info); |
233 | 0 | assert(obj_loc); |
234 | | |
235 | | /* Create the group */ |
236 | 0 | if (NULL == (grp = H5G__create(f, crt_info))) |
237 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group"); |
238 | | |
239 | | /* Set up the new group's location */ |
240 | 0 | if (NULL == (obj_loc->oloc = H5G_oloc(grp))) |
241 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get object location of group"); |
242 | 0 | if (NULL == (obj_loc->path = H5G_nameof(grp))) |
243 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get path of group"); |
244 | | |
245 | | /* Set the return value */ |
246 | 0 | ret_value = grp; |
247 | |
|
248 | 0 | done: |
249 | 0 | if (ret_value == NULL) |
250 | 0 | if (grp && H5G_close(grp) < 0) |
251 | 0 | HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release group"); |
252 | |
|
253 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
254 | 0 | } /* end H5O__group_create() */ |
255 | | |
256 | | /*------------------------------------------------------------------------- |
257 | | * Function: H5O__group_get_oloc |
258 | | * |
259 | | * Purpose: Retrieve the object header location for an open object |
260 | | * |
261 | | * Return: Success: Pointer to object header location |
262 | | * Failure: NULL |
263 | | * |
264 | | *------------------------------------------------------------------------- |
265 | | */ |
266 | | static H5O_loc_t * |
267 | | H5O__group_get_oloc(hid_t obj_id) |
268 | 0 | { |
269 | 0 | H5G_t *grp; /* Group opened */ |
270 | 0 | H5O_loc_t *ret_value = NULL; /* Return value */ |
271 | |
|
272 | 0 | FUNC_ENTER_PACKAGE |
273 | | |
274 | | /* Get the group */ |
275 | 0 | if (NULL == (grp = (H5G_t *)H5VL_object(obj_id))) |
276 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_BADID, NULL, "couldn't get object from ID"); |
277 | | |
278 | | /* Get the group's object header location */ |
279 | 0 | if (NULL == (ret_value = H5G_oloc(grp))) |
280 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from object"); |
281 | | |
282 | 0 | done: |
283 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
284 | 0 | } /* end H5O__group_get_oloc() */ |
285 | | |
286 | | /*------------------------------------------------------------------------- |
287 | | * Function: H5O__group_bh_info |
288 | | * |
289 | | * Purpose: Retrieve storage for 1.8 btree and heap |
290 | | * Retrieve storage for 1.6 btree and heap via H5G_stab_bh_info() |
291 | | * |
292 | | * Return: Non-negative on success/Negative on failure |
293 | | * |
294 | | *------------------------------------------------------------------------- |
295 | | */ |
296 | | static herr_t |
297 | | H5O__group_bh_info(const H5O_loc_t *loc, H5O_t *oh, H5_ih_info_t *bh_info) |
298 | 0 | { |
299 | 0 | htri_t exists; /* Flag if header message of interest exists */ |
300 | 0 | H5HF_t *fheap = NULL; /* Fractal heap handle */ |
301 | 0 | H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ |
302 | 0 | H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order index */ |
303 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
304 | |
|
305 | 0 | FUNC_ENTER_PACKAGE |
306 | | |
307 | | /* Sanity check */ |
308 | 0 | assert(loc); |
309 | 0 | assert(loc->file); |
310 | 0 | assert(H5_addr_defined(loc->addr)); |
311 | 0 | assert(oh); |
312 | 0 | assert(bh_info); |
313 | | |
314 | | /* Check for "new style" group info */ |
315 | 0 | if ((exists = H5O_msg_exists_oh(oh, H5O_LINFO_ID)) < 0) |
316 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header"); |
317 | 0 | if (exists > 0) { |
318 | 0 | H5O_linfo_t linfo; /* Link info message */ |
319 | | |
320 | | /* Get "new style" group info */ |
321 | 0 | if (NULL == H5O_msg_read_oh(loc->file, oh, H5O_LINFO_ID, &linfo)) |
322 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't read LINFO message"); |
323 | | |
324 | | /* Check if name index available */ |
325 | 0 | if (H5_addr_defined(linfo.name_bt2_addr)) { |
326 | | /* Open the name index v2 B-tree */ |
327 | 0 | if (NULL == (bt2_name = H5B2_open(loc->file, linfo.name_bt2_addr, NULL))) |
328 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index"); |
329 | | |
330 | | /* Get name index B-tree size */ |
331 | 0 | if (H5B2_size(bt2_name, &bh_info->index_size) < 0) |
332 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve B-tree storage info for name index"); |
333 | 0 | } /* end if */ |
334 | | |
335 | | /* Check if creation order index available */ |
336 | 0 | if (H5_addr_defined(linfo.corder_bt2_addr)) { |
337 | | /* Open the creation order index v2 B-tree */ |
338 | 0 | if (NULL == (bt2_corder = H5B2_open(loc->file, linfo.corder_bt2_addr, NULL))) |
339 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, |
340 | 0 | "unable to open v2 B-tree for creation order index"); |
341 | | |
342 | | /* Get creation order index B-tree size */ |
343 | 0 | if (H5B2_size(bt2_corder, &bh_info->index_size) < 0) |
344 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, |
345 | 0 | "can't retrieve B-tree storage info for creation order index"); |
346 | 0 | } /* end if */ |
347 | | |
348 | | /* Get fractal heap size, if available */ |
349 | 0 | if (H5_addr_defined(linfo.fheap_addr)) { |
350 | | /* Open the fractal heap for links */ |
351 | 0 | if (NULL == (fheap = H5HF_open(loc->file, linfo.fheap_addr))) |
352 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap"); |
353 | | |
354 | | /* Get heap storage size */ |
355 | 0 | if (H5HF_size(fheap, &bh_info->heap_size) < 0) |
356 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve fractal heap storage info"); |
357 | 0 | } /* end if */ |
358 | 0 | } /* end if */ |
359 | 0 | else { |
360 | 0 | H5O_stab_t stab; /* Info about symbol table */ |
361 | | |
362 | | /* Must be "old style" group, get symbol table message */ |
363 | 0 | if (NULL == H5O_msg_read_oh(loc->file, oh, H5O_STAB_ID, &stab)) |
364 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't find LINFO nor STAB messages"); |
365 | | |
366 | | /* Get symbol table size info */ |
367 | 0 | if (H5G__stab_bh_size(loc->file, &stab, bh_info) < 0) |
368 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve symbol table size info"); |
369 | 0 | } /* end else */ |
370 | | |
371 | 0 | done: |
372 | | /* Release resources */ |
373 | 0 | if (fheap && H5HF_close(fheap) < 0) |
374 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap"); |
375 | 0 | if (bt2_name && H5B2_close(bt2_name) < 0) |
376 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index"); |
377 | 0 | if (bt2_corder && H5B2_close(bt2_corder) < 0) |
378 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for creation order index"); |
379 | |
|
380 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
381 | 0 | } /* end H5O__group_bh_info() */ |