/src/hdf5/src/H5Ocopy_ref.c
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: H5Ocopy_ref.c |
16 | | * |
17 | | * Purpose: Object with references copying routines |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5Omodule.h" /* This source code file is part of the H5O module */ |
27 | | #define H5R_FRIEND /* Suppress error about including H5Rpkg */ |
28 | | |
29 | | /***********/ |
30 | | /* Headers */ |
31 | | /***********/ |
32 | | #include "H5private.h" /* Generic Functions */ |
33 | | #include "H5Eprivate.h" /* Error handling */ |
34 | | #include "H5Fprivate.h" /* File */ |
35 | | #include "H5FLprivate.h" /* Free Lists */ |
36 | | #include "H5Iprivate.h" /* IDs */ |
37 | | #include "H5Lprivate.h" /* Links */ |
38 | | #include "H5MMprivate.h" /* Memory management */ |
39 | | #include "H5Opkg.h" /* Object headers */ |
40 | | #include "H5Rpkg.h" /* References */ |
41 | | |
42 | | #include "H5VLnative_private.h" /* Native VOL connector */ |
43 | | |
44 | | /****************/ |
45 | | /* Local Macros */ |
46 | | /****************/ |
47 | | |
48 | | /******************/ |
49 | | /* Local Typedefs */ |
50 | | /******************/ |
51 | | |
52 | | /********************/ |
53 | | /* Package Typedefs */ |
54 | | /********************/ |
55 | | |
56 | | /********************/ |
57 | | /* Local Prototypes */ |
58 | | /********************/ |
59 | | |
60 | | static herr_t H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, |
61 | | H5O_copy_t *cpy_info); |
62 | | static herr_t H5O__copy_expand_ref_object1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t *dst_oloc, |
63 | | H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, |
64 | | H5O_copy_t *cpy_info); |
65 | | static herr_t H5O__copy_expand_ref_region1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t *dst_oloc, |
66 | | H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, |
67 | | H5O_copy_t *cpy_info); |
68 | | static herr_t H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, const H5T_t *dt_src, const void *buf_src, |
69 | | size_t nbytes_src, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, |
70 | | void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info); |
71 | | |
72 | | /*********************/ |
73 | | /* Package Variables */ |
74 | | /*********************/ |
75 | | |
76 | | /* Declare extern the free list to manage blocks of type conversion data */ |
77 | | H5FL_BLK_EXTERN(type_conv); |
78 | | |
79 | | /*****************************/ |
80 | | /* Library Private Variables */ |
81 | | /*****************************/ |
82 | | |
83 | | /*******************/ |
84 | | /* Local Variables */ |
85 | | /*******************/ |
86 | | |
87 | | /*------------------------------------------------------------------------- |
88 | | * Function: H5O__copy_obj_by_ref |
89 | | * |
90 | | * Purpose: Copy the object pointed to by src_oloc. |
91 | | * |
92 | | * Return: Non-negative on success/Negative on failure |
93 | | * |
94 | | *------------------------------------------------------------------------- |
95 | | */ |
96 | | static herr_t |
97 | | H5O__copy_obj_by_ref(H5O_loc_t *src_oloc, H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info) |
98 | 0 | { |
99 | 0 | herr_t ret_value = SUCCEED; |
100 | |
|
101 | 0 | FUNC_ENTER_PACKAGE |
102 | |
|
103 | 0 | assert(src_oloc); |
104 | 0 | assert(dst_oloc); |
105 | | |
106 | | /* Perform the copy, or look up existing copy */ |
107 | 0 | if ((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, cpy_info, false, NULL, NULL)) < 0) |
108 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object"); |
109 | | |
110 | | /* Check if a new valid object is copied to the destination */ |
111 | 0 | if (H5_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) { |
112 | 0 | char tmp_obj_name[80]; |
113 | 0 | H5G_name_t new_path; |
114 | 0 | H5O_loc_t new_oloc; |
115 | 0 | H5G_loc_t new_loc; |
116 | | |
117 | | /* Set up group location for new object */ |
118 | 0 | new_loc.oloc = &new_oloc; |
119 | 0 | new_loc.path = &new_path; |
120 | 0 | H5G_loc_reset(&new_loc); |
121 | 0 | new_oloc.file = dst_oloc->file; |
122 | 0 | new_oloc.addr = dst_oloc->addr; |
123 | | |
124 | | /* Pick a default name for the new object */ |
125 | 0 | snprintf(tmp_obj_name, sizeof(tmp_obj_name), "~obj_pointed_by_%llu", |
126 | 0 | (unsigned long long)dst_oloc->addr); |
127 | | |
128 | | /* Create a link to the newly copied object */ |
129 | | /* Note: since H5O_copy_header_map actually copied the target object, it |
130 | | * must exist either in cache or on disk, therefore it is safe to not |
131 | | * pass the obj_type and udata fields returned by H5O_copy_header_map. |
132 | | * This could be changed in the future to slightly improve performance |
133 | | * --NAF */ |
134 | 0 | if (H5L_link(dst_root_loc, tmp_obj_name, &new_loc, cpy_info->lcpl_id) < 0) |
135 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link"); |
136 | | |
137 | 0 | H5G_loc_free(&new_loc); |
138 | 0 | } /* if (H5_addr_defined(dst_oloc.addr)) */ |
139 | | |
140 | 0 | done: |
141 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
142 | 0 | } /* end H5O__copy_obj_by_ref() */ |
143 | | |
144 | | /*------------------------------------------------------------------------- |
145 | | * Function: H5O__copy_expand_ref_object1 |
146 | | * |
147 | | * Purpose: Copy the object pointed by a deprecated object reference. |
148 | | * |
149 | | * Return: Non-negative on success/Negative on failure |
150 | | * |
151 | | *------------------------------------------------------------------------- |
152 | | */ |
153 | | static herr_t |
154 | | H5O__copy_expand_ref_object1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t *dst_oloc, |
155 | | H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info) |
156 | 0 | { |
157 | 0 | const hobj_ref_t *src_ref = (const hobj_ref_t *)buf_src; |
158 | 0 | hobj_ref_t *dst_ref = (hobj_ref_t *)buf_dst; |
159 | 0 | const unsigned char zeros[H5R_OBJ_REF_BUF_SIZE] = {0}; |
160 | 0 | size_t buf_size = H5R_OBJ_REF_BUF_SIZE; |
161 | 0 | size_t i; /* Local index variable */ |
162 | 0 | size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file); |
163 | 0 | herr_t ret_value = SUCCEED; |
164 | |
|
165 | 0 | FUNC_ENTER_PACKAGE |
166 | | |
167 | | /* Making equivalent references in the destination file */ |
168 | 0 | for (i = 0; i < ref_count; i++) { |
169 | 0 | const unsigned char *src_buf = (const unsigned char *)&src_ref[i]; |
170 | 0 | unsigned char *dst_buf = (unsigned char *)&dst_ref[i]; |
171 | 0 | H5O_token_t tmp_token = {0}; |
172 | | |
173 | | /* If data is not initialized, copy zeros and skip */ |
174 | 0 | if (0 == memcmp(src_buf, zeros, buf_size)) |
175 | 0 | memset(dst_buf, 0, buf_size); |
176 | 0 | else { |
177 | | /* Set up for the object copy for the reference */ |
178 | 0 | if (H5R__decode_token_obj_compat(src_buf, &buf_size, &tmp_token, token_size) < 0) |
179 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode src object address"); |
180 | 0 | if (H5VL_native_token_to_addr(src_oloc->file, H5I_FILE, tmp_token, &src_oloc->addr) < 0) |
181 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, |
182 | 0 | "can't deserialize object token into address"); |
183 | | |
184 | 0 | if (!H5_addr_defined(src_oloc->addr) || src_oloc->addr == 0) |
185 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer"); |
186 | 0 | dst_oloc->addr = HADDR_UNDEF; |
187 | | |
188 | | /* Attempt to copy object from source to destination file */ |
189 | 0 | if (H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) |
190 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object"); |
191 | | |
192 | | /* Set the object reference info for the destination file */ |
193 | 0 | if (H5VL_native_addr_to_token(dst_oloc->file, H5I_FILE, dst_oloc->addr, &tmp_token) < 0) |
194 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "can't serialize address into object token"); |
195 | 0 | if (H5R__encode_token_obj_compat((const H5O_token_t *)&tmp_token, token_size, dst_buf, |
196 | 0 | &buf_size) < 0) |
197 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to encode dst object address"); |
198 | 0 | } /* end else */ |
199 | 0 | } /* end for */ |
200 | | |
201 | 0 | done: |
202 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
203 | 0 | } /* end H5O__copy_expand_ref_object1() */ |
204 | | |
205 | | /*------------------------------------------------------------------------- |
206 | | * Function: H5O__copy_expand_ref_region1 |
207 | | * |
208 | | * Purpose: Copy the object pointed by a deprecated region reference. |
209 | | * |
210 | | * Return: Non-negative on success/Negative on failure |
211 | | * |
212 | | *------------------------------------------------------------------------- |
213 | | */ |
214 | | static herr_t |
215 | | H5O__copy_expand_ref_region1(H5O_loc_t *src_oloc, const void *buf_src, H5O_loc_t *dst_oloc, |
216 | | H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, H5O_copy_t *cpy_info) |
217 | 0 | { |
218 | 0 | const hdset_reg_ref_t *src_ref = (const hdset_reg_ref_t *)buf_src; |
219 | 0 | hdset_reg_ref_t *dst_ref = (hdset_reg_ref_t *)buf_dst; |
220 | 0 | const unsigned char zeros[H5R_DSET_REG_REF_BUF_SIZE] = {0}; |
221 | 0 | size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE; |
222 | 0 | size_t i; /* Local index variable */ |
223 | 0 | herr_t ret_value = SUCCEED; |
224 | |
|
225 | 0 | FUNC_ENTER_PACKAGE |
226 | | |
227 | | /* Making equivalent references in the destination file */ |
228 | 0 | for (i = 0; i < ref_count; i++) { |
229 | 0 | const unsigned char *src_buf = (const unsigned char *)&src_ref[i]; |
230 | 0 | unsigned char *dst_buf = (unsigned char *)&dst_ref[i]; |
231 | 0 | unsigned char *data = NULL; |
232 | 0 | size_t data_size; |
233 | 0 | const uint8_t *p; |
234 | 0 | uint8_t *q; |
235 | | |
236 | | /* If data is not initialized, copy zeros and skip */ |
237 | 0 | if (0 == memcmp(src_buf, zeros, buf_size)) |
238 | 0 | memset(dst_buf, 0, buf_size); |
239 | 0 | else { |
240 | | /* Read from heap */ |
241 | 0 | if (H5R__decode_heap(src_oloc->file, src_buf, &buf_size, &data, &data_size) < 0) |
242 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode dataset region information"); |
243 | | |
244 | | /* Get object address */ |
245 | 0 | p = (const uint8_t *)data; |
246 | 0 | H5F_addr_decode(src_oloc->file, &p, &src_oloc->addr); |
247 | 0 | if (!H5_addr_defined(src_oloc->addr) || src_oloc->addr == 0) { |
248 | 0 | H5MM_free(data); |
249 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "undefined reference pointer"); |
250 | 0 | } |
251 | 0 | dst_oloc->addr = HADDR_UNDEF; |
252 | | |
253 | | /* Attempt to copy object from source to destination file */ |
254 | 0 | if (H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) { |
255 | 0 | H5MM_free(data); |
256 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object"); |
257 | 0 | } /* end if */ |
258 | | |
259 | | /* Serialize object addr */ |
260 | 0 | q = (uint8_t *)data; |
261 | 0 | H5F_addr_encode(dst_oloc->file, &q, dst_oloc->addr); |
262 | | |
263 | | /* Write to heap */ |
264 | 0 | if (H5R__encode_heap(dst_oloc->file, dst_buf, &buf_size, data, (size_t)data_size) < 0) { |
265 | 0 | H5MM_free(data); |
266 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode dataset region information"); |
267 | 0 | } |
268 | | |
269 | | /* Free the buffer allocated in H5R__decode_heap() */ |
270 | 0 | H5MM_free(data); |
271 | 0 | } /* end else */ |
272 | 0 | } /* end for */ |
273 | | |
274 | 0 | done: |
275 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
276 | 0 | } /* end H5O__copy_expand_ref_region1() */ |
277 | | |
278 | | /*------------------------------------------------------------------------- |
279 | | * Function: H5O__copy_expand_ref_object2 |
280 | | * |
281 | | * Purpose: Copy the object pointed by a reference (object, region, attribute). |
282 | | * |
283 | | * Return: Non-negative on success/Negative on failure |
284 | | * |
285 | | *------------------------------------------------------------------------- |
286 | | */ |
287 | | static herr_t |
288 | | H5O__copy_expand_ref_object2(H5O_loc_t *src_oloc, const H5T_t *dt_src, const void *buf_src, size_t nbytes_src, |
289 | | H5O_loc_t *dst_oloc, H5G_loc_t *dst_root_loc, void *buf_dst, size_t ref_count, |
290 | | H5O_copy_t *cpy_info) |
291 | 0 | { |
292 | 0 | H5T_t *dt_mem = NULL; /* Memory datatype */ |
293 | 0 | H5T_t *dt_dst = NULL; /* Destination datatype */ |
294 | 0 | H5T_path_t *tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */ |
295 | 0 | size_t i; /* Local index variable */ |
296 | 0 | hid_t dst_loc_id = H5I_INVALID_HID; |
297 | 0 | void *conv_buf = NULL; /* Buffer for converting data */ |
298 | 0 | size_t conv_buf_size = 0; /* Buffer size */ |
299 | 0 | void *reclaim_buf = NULL; /* Buffer for reclaiming data */ |
300 | 0 | H5S_t *buf_space = NULL; /* Dataspace describing buffer */ |
301 | 0 | hsize_t buf_dim[1] = {ref_count}; /* Dimension for buffer */ |
302 | 0 | size_t token_size = H5F_SIZEOF_ADDR(src_oloc->file); |
303 | 0 | const unsigned char zeros[H5R_REF_BUF_SIZE] = {0}; |
304 | 0 | herr_t ret_value = SUCCEED; |
305 | |
|
306 | 0 | FUNC_ENTER_PACKAGE |
307 | | |
308 | | /* create a memory copy of the reference datatype */ |
309 | 0 | if (NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT))) |
310 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy"); |
311 | | |
312 | | /* create reference datatype at the destination file */ |
313 | 0 | if (NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT))) |
314 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy"); |
315 | 0 | if (H5T_set_loc(dt_dst, H5F_VOL_OBJ(dst_oloc->file), H5T_LOC_DISK) < 0) { |
316 | 0 | (void)H5T_close_real(dt_dst); |
317 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "cannot mark datatype on disk"); |
318 | 0 | } /* end if */ |
319 | | |
320 | | /* Set up the conversion functions */ |
321 | 0 | if (NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem))) |
322 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes"); |
323 | 0 | if (NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst))) |
324 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes"); |
325 | | |
326 | | /* Use extra conversion buffer (TODO we should avoid using an extra buffer once the H5Ocopy code has been |
327 | | * reworked) */ |
328 | 0 | conv_buf_size = MAX(H5T_get_size(dt_src), H5T_get_size(dt_mem)) * ref_count; |
329 | 0 | if (NULL == (conv_buf = H5FL_BLK_MALLOC(type_conv, conv_buf_size))) |
330 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer"); |
331 | 0 | H5MM_memcpy(conv_buf, buf_src, nbytes_src); |
332 | | |
333 | | /* Convert from source file to memory */ |
334 | 0 | if (H5T_convert(tpath_src_mem, dt_src, dt_mem, ref_count, (size_t)0, (size_t)0, conv_buf, NULL) < 0) |
335 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); |
336 | | |
337 | | /* Retrieve loc ID */ |
338 | 0 | if ((dst_loc_id = H5F_get_id(dst_oloc->file)) < 0) |
339 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object"); |
340 | | |
341 | | /* Making equivalent references in the destination file */ |
342 | 0 | for (i = 0; i < ref_count; i++) { |
343 | 0 | H5R_ref_t *ref_ptr = (H5R_ref_t *)conv_buf; |
344 | 0 | H5R_ref_priv_t *ref = (H5R_ref_priv_t *)&ref_ptr[i]; |
345 | | |
346 | | /* Check for null reference - only expand reference if it is not null */ |
347 | 0 | if (memcmp(ref, zeros, H5R_REF_BUF_SIZE)) { |
348 | 0 | H5O_token_t tmp_token = {0}; |
349 | | |
350 | | /* Get src object address */ |
351 | 0 | if (H5R__get_obj_token(ref, &tmp_token, &token_size) < 0) |
352 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object token"); |
353 | 0 | if (H5VL_native_token_to_addr(src_oloc->file, H5I_FILE, tmp_token, &src_oloc->addr) < 0) |
354 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, |
355 | 0 | "can't deserialize object token into address"); |
356 | | |
357 | | /* Attempt to copy object from source to destination file */ |
358 | 0 | if (H5O__copy_obj_by_ref(src_oloc, dst_oloc, dst_root_loc, cpy_info) < 0) |
359 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object"); |
360 | | |
361 | | /* Set dst object address */ |
362 | 0 | if (H5VL_native_addr_to_token(dst_oloc->file, H5I_FILE, dst_oloc->addr, &tmp_token) < 0) |
363 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "can't serialize address into object token"); |
364 | 0 | if (H5R__set_obj_token(ref, (const H5O_token_t *)&tmp_token, token_size) < 0) |
365 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set object token"); |
366 | | /* Do not set app_ref since references are released once the copy is done */ |
367 | 0 | if (H5R__set_loc_id(ref, dst_loc_id, true, false) < 0) |
368 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set destination loc id"); |
369 | 0 | } /* end if */ |
370 | 0 | } /* end for */ |
371 | | |
372 | | /* Copy into another buffer, to reclaim memory later */ |
373 | 0 | if (NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, conv_buf_size))) |
374 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer"); |
375 | 0 | H5MM_memcpy(reclaim_buf, conv_buf, conv_buf_size); |
376 | 0 | if (NULL == (buf_space = H5S_create_simple((unsigned)1, buf_dim, NULL))) |
377 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); |
378 | | |
379 | | /* Convert from memory to destination file */ |
380 | 0 | if (H5T_convert(tpath_mem_dst, dt_mem, dt_dst, ref_count, (size_t)0, (size_t)0, conv_buf, NULL) < 0) |
381 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); |
382 | 0 | H5MM_memcpy(buf_dst, conv_buf, nbytes_src); |
383 | | |
384 | | /* Reclaim space from reference data */ |
385 | 0 | if (H5T_reclaim(dt_mem, buf_space, reclaim_buf) < 0) |
386 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to reclaim reference data"); |
387 | | |
388 | 0 | done: |
389 | 0 | if (buf_space && (H5S_close(buf_space) < 0)) |
390 | 0 | HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "can't close dataspace"); |
391 | 0 | if (dt_mem && (H5T_close(dt_mem) < 0)) |
392 | 0 | HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); |
393 | 0 | if (dt_dst && (H5T_close(dt_dst) < 0)) |
394 | 0 | HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); |
395 | 0 | if (reclaim_buf) |
396 | 0 | reclaim_buf = H5FL_BLK_FREE(type_conv, reclaim_buf); |
397 | 0 | if (conv_buf) |
398 | 0 | conv_buf = H5FL_BLK_FREE(type_conv, conv_buf); |
399 | 0 | if ((dst_loc_id != H5I_INVALID_HID) && (H5I_dec_ref(dst_loc_id) < 0)) |
400 | 0 | HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement refcount on location id"); |
401 | |
|
402 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
403 | 0 | } /* end H5O__copy_expand_ref_object2() */ |
404 | | |
405 | | /*------------------------------------------------------------------------- |
406 | | * Function: H5O_copy_expand_ref |
407 | | * |
408 | | * Purpose: Copy the object pointed by a reference. |
409 | | * |
410 | | * Return: Non-negative on success/Negative on failure |
411 | | * |
412 | | *------------------------------------------------------------------------- |
413 | | */ |
414 | | herr_t |
415 | | H5O_copy_expand_ref(H5F_t *file_src, const H5T_t *dt_src, void *buf_src, size_t nbytes_src, H5F_t *file_dst, |
416 | | void *buf_dst, H5O_copy_t *cpy_info) |
417 | 0 | { |
418 | 0 | H5O_loc_t dst_oloc; /* Copied object object location */ |
419 | 0 | H5O_loc_t src_oloc; /* Temporary object location for source object */ |
420 | 0 | H5G_loc_t dst_root_loc; /* The location of root group of the destination file */ |
421 | 0 | size_t ref_count; |
422 | 0 | herr_t ret_value = SUCCEED; |
423 | |
|
424 | 0 | FUNC_ENTER_NOAPI(FAIL) |
425 | | |
426 | | /* Sanity checks */ |
427 | 0 | assert(file_src); |
428 | 0 | assert(buf_src); |
429 | 0 | assert(file_dst); |
430 | 0 | assert(buf_dst); |
431 | 0 | assert(nbytes_src); |
432 | 0 | assert(cpy_info); |
433 | | |
434 | | /* Initialize object locations */ |
435 | 0 | H5O_loc_reset(&src_oloc); |
436 | 0 | H5O_loc_reset(&dst_oloc); |
437 | 0 | src_oloc.file = file_src; |
438 | 0 | dst_oloc.file = file_dst; |
439 | | |
440 | | /* Set up the root group in the destination file */ |
441 | 0 | if (NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(file_dst)))) |
442 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group"); |
443 | 0 | if (NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(file_dst)))) |
444 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group"); |
445 | | |
446 | | /* Determine # of reference elements to copy */ |
447 | 0 | ref_count = nbytes_src / H5T_get_size(dt_src); |
448 | | |
449 | | /* Copy object references */ |
450 | 0 | switch (H5T_get_ref_type(dt_src)) { |
451 | 0 | case H5R_OBJECT1: |
452 | 0 | if (H5O__copy_expand_ref_object1(&src_oloc, buf_src, &dst_oloc, &dst_root_loc, buf_dst, ref_count, |
453 | 0 | cpy_info) < 0) |
454 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand H5R_OBJECT1 reference"); |
455 | 0 | break; |
456 | 0 | case H5R_DATASET_REGION1: |
457 | 0 | if (H5O__copy_expand_ref_region1(&src_oloc, buf_src, &dst_oloc, &dst_root_loc, buf_dst, ref_count, |
458 | 0 | cpy_info) < 0) |
459 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand H5R_DATASET_REGION1 reference"); |
460 | 0 | break; |
461 | 0 | case H5R_DATASET_REGION2: |
462 | 0 | case H5R_ATTR: |
463 | 0 | case H5R_OBJECT2: |
464 | 0 | if (H5O__copy_expand_ref_object2(&src_oloc, dt_src, buf_src, nbytes_src, &dst_oloc, &dst_root_loc, |
465 | 0 | buf_dst, ref_count, cpy_info) < 0) |
466 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to expand reference"); |
467 | 0 | break; |
468 | 0 | case H5R_BADTYPE: |
469 | 0 | case H5R_MAXTYPE: |
470 | 0 | default: |
471 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type"); |
472 | 0 | break; |
473 | 0 | } /* end switch */ |
474 | | |
475 | 0 | done: |
476 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
477 | 0 | } /* end H5O_copy_expand_ref() */ |