Line | Count | Source (jump to first uncovered line) |
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 COPYING 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: H5HFhuge.c |
16 | | * |
17 | | * Purpose: Routines for "huge" objects in fractal heap |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5HFmodule.h" /* This source code file is part of the H5HF module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5HFpkg.h" /* Fractal heaps */ |
34 | | #include "H5MFprivate.h" /* File memory management */ |
35 | | #include "H5MMprivate.h" /* Memory management */ |
36 | | |
37 | | /****************/ |
38 | | /* Local Macros */ |
39 | | /****************/ |
40 | | |
41 | | /* v2 B-tree creation macros */ |
42 | 0 | #define H5HF_HUGE_BT2_NODE_SIZE 512 |
43 | 0 | #define H5HF_HUGE_BT2_SPLIT_PERC 100 |
44 | 0 | #define H5HF_HUGE_BT2_MERGE_PERC 40 |
45 | | |
46 | | /******************/ |
47 | | /* Local Typedefs */ |
48 | | /******************/ |
49 | | |
50 | | /********************/ |
51 | | /* Package Typedefs */ |
52 | | /********************/ |
53 | | |
54 | | /********************/ |
55 | | /* Local Prototypes */ |
56 | | /********************/ |
57 | | |
58 | | /* Local v2 B-tree operations */ |
59 | | static herr_t H5HF__huge_bt2_create(H5HF_hdr_t *hdr); |
60 | | |
61 | | /* Local 'huge' object support routines */ |
62 | | static hsize_t H5HF__huge_new_id(H5HF_hdr_t *hdr); |
63 | | static herr_t H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, bool is_read, H5HF_operator_t op, |
64 | | void *op_data); |
65 | | |
66 | | /*********************/ |
67 | | /* Package Variables */ |
68 | | /*********************/ |
69 | | |
70 | | /*****************************/ |
71 | | /* Library Private Variables */ |
72 | | /*****************************/ |
73 | | |
74 | | /*******************/ |
75 | | /* Local Variables */ |
76 | | /*******************/ |
77 | | |
78 | | /*------------------------------------------------------------------------- |
79 | | * Function: H5HF__huge_bt2_create |
80 | | * |
81 | | * Purpose: Create the v2 B-tree for tracking the huge objects in the heap |
82 | | * |
83 | | * Return: SUCCEED/FAIL |
84 | | * |
85 | | *------------------------------------------------------------------------- |
86 | | */ |
87 | | static herr_t |
88 | | H5HF__huge_bt2_create(H5HF_hdr_t *hdr) |
89 | 0 | { |
90 | 0 | H5B2_create_t bt2_cparam; /* v2 B-tree creation parameters */ |
91 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
92 | |
|
93 | 0 | FUNC_ENTER_PACKAGE |
94 | | |
95 | | /* |
96 | | * Check arguments. |
97 | | */ |
98 | 0 | assert(hdr); |
99 | | |
100 | | /* Compute the size of 'raw' records on disk */ |
101 | | /* (Note: the size for huge IDs could be set to 'huge_id_size', instead |
102 | | * of 'sizeof_size', but that would make the v2 B-tree callback routines |
103 | | * depend on the heap header, which makes the v2 B-tree flush routines |
104 | | * difficult to write. "Waste" an extra byte or for small heaps (where |
105 | | * the 'huge_id_size' is < 'sizeof_size' in order to make this easier -QAK) |
106 | | */ |
107 | 0 | if (hdr->huge_ids_direct) { |
108 | 0 | if (hdr->filter_len > 0) { |
109 | 0 | bt2_cparam.rrec_size = |
110 | 0 | (uint32_t)((unsigned)hdr->sizeof_addr /* Address of object */ |
111 | 0 | + (unsigned)hdr->sizeof_size /* Length of object */ |
112 | 0 | + (unsigned)4 /* Filter mask for filtered object */ |
113 | 0 | + (unsigned)hdr->sizeof_size); /* Size of de-filtered object in memory */ |
114 | 0 | bt2_cparam.cls = H5HF_HUGE_BT2_FILT_DIR; |
115 | 0 | } /* end if */ |
116 | 0 | else { |
117 | 0 | bt2_cparam.rrec_size = (uint32_t)((unsigned)hdr->sizeof_addr /* Address of object */ |
118 | 0 | + (unsigned)hdr->sizeof_size); /* Length of object */ |
119 | 0 | bt2_cparam.cls = H5HF_HUGE_BT2_DIR; |
120 | 0 | } /* end else */ |
121 | 0 | } /* end if */ |
122 | 0 | else { |
123 | 0 | if (hdr->filter_len > 0) { |
124 | 0 | bt2_cparam.rrec_size = |
125 | 0 | (uint32_t)((unsigned)hdr->sizeof_addr /* Address of filtered object */ |
126 | 0 | + (unsigned)hdr->sizeof_size /* Length of filtered object */ |
127 | 0 | + (unsigned)4 /* Filter mask for filtered object */ |
128 | 0 | + (unsigned)hdr->sizeof_size /* Size of de-filtered object in memory */ |
129 | 0 | + (unsigned)hdr->sizeof_size); /* Unique ID for object */ |
130 | 0 | bt2_cparam.cls = H5HF_HUGE_BT2_FILT_INDIR; |
131 | 0 | } /* end if */ |
132 | 0 | else { |
133 | 0 | bt2_cparam.rrec_size = (uint32_t)((unsigned)hdr->sizeof_addr /* Address of object */ |
134 | 0 | + (unsigned)hdr->sizeof_size /* Length of object */ |
135 | 0 | + (unsigned)hdr->sizeof_size); /* Unique ID for object */ |
136 | 0 | bt2_cparam.cls = H5HF_HUGE_BT2_INDIR; |
137 | 0 | } /* end else */ |
138 | 0 | } /* end else */ |
139 | 0 | bt2_cparam.node_size = (size_t)H5HF_HUGE_BT2_NODE_SIZE; |
140 | 0 | bt2_cparam.split_percent = H5HF_HUGE_BT2_SPLIT_PERC; |
141 | 0 | bt2_cparam.merge_percent = H5HF_HUGE_BT2_MERGE_PERC; |
142 | | |
143 | | /* Create v2 B-tree for tracking 'huge' objects */ |
144 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_create(hdr->f, &bt2_cparam, hdr->f))) |
145 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, |
146 | 0 | "can't create v2 B-tree for tracking 'huge' heap objects"); |
147 | | |
148 | | /* Retrieve the v2 B-tree's address in the file */ |
149 | 0 | if (H5B2_get_addr(hdr->huge_bt2, &hdr->huge_bt2_addr) < 0) |
150 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, |
151 | 0 | "can't get v2 B-tree address for tracking 'huge' heap objects"); |
152 | | |
153 | 0 | done: |
154 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
155 | 0 | } /* end H5HF__huge_bt2_create() */ |
156 | | |
157 | | /*------------------------------------------------------------------------- |
158 | | * Function: H5HF__huge_init |
159 | | * |
160 | | * Purpose: Initialize information for tracking 'huge' objects |
161 | | * |
162 | | * Return: SUCCEED/FAIL |
163 | | * |
164 | | *------------------------------------------------------------------------- |
165 | | */ |
166 | | herr_t |
167 | | H5HF__huge_init(H5HF_hdr_t *hdr) |
168 | 0 | { |
169 | 0 | FUNC_ENTER_PACKAGE_NOERR |
170 | | |
171 | | /* |
172 | | * Check arguments. |
173 | | */ |
174 | 0 | assert(hdr); |
175 | | |
176 | | /* Compute information about 'huge' objects for the heap */ |
177 | | |
178 | | /* Check if we can completely hold the 'huge' object's offset & length in |
179 | | * the file in the heap ID (which will speed up accessing it) and we don't |
180 | | * have any I/O pipeline filters. |
181 | | */ |
182 | 0 | if (hdr->filter_len > 0) { |
183 | 0 | if ((hdr->id_len - 1) >= (unsigned)(hdr->sizeof_addr + hdr->sizeof_size + 4 + hdr->sizeof_size)) { |
184 | | /* Indicate that v2 B-tree doesn't have to be used to locate object */ |
185 | 0 | hdr->huge_ids_direct = true; |
186 | | |
187 | | /* Set the size of 'huge' object IDs */ |
188 | 0 | hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size + hdr->sizeof_size); |
189 | 0 | } /* end if */ |
190 | 0 | else |
191 | | /* Indicate that v2 B-tree must be used to access object */ |
192 | 0 | hdr->huge_ids_direct = false; |
193 | 0 | } /* end if */ |
194 | 0 | else { |
195 | 0 | if ((hdr->sizeof_addr + hdr->sizeof_size) <= (hdr->id_len - 1)) { |
196 | | /* Indicate that v2 B-tree doesn't have to be used to locate object */ |
197 | 0 | hdr->huge_ids_direct = true; |
198 | | |
199 | | /* Set the size of 'huge' object IDs */ |
200 | 0 | hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size); |
201 | 0 | } /* end if */ |
202 | 0 | else |
203 | | /* Indicate that v2 B-tree must be used to locate object */ |
204 | 0 | hdr->huge_ids_direct = false; |
205 | 0 | } /* end else */ |
206 | 0 | if (!hdr->huge_ids_direct) { |
207 | | /* Set the size and maximum value of 'huge' object ID */ |
208 | 0 | if ((hdr->id_len - 1) < sizeof(hsize_t)) { |
209 | 0 | hdr->huge_id_size = (uint8_t)(hdr->id_len - 1); |
210 | 0 | hdr->huge_max_id = ((hsize_t)1 << (hdr->huge_id_size * 8)) - 1; |
211 | 0 | } /*end if */ |
212 | 0 | else { |
213 | 0 | hdr->huge_id_size = sizeof(hsize_t); |
214 | 0 | hdr->huge_max_id = HSIZET_MAX; |
215 | 0 | } /* end else */ |
216 | 0 | } /* end if */ |
217 | 0 | hdr->huge_bt2 = NULL; |
218 | |
|
219 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
220 | 0 | } /* end H5HF__huge_init() */ |
221 | | |
222 | | /*------------------------------------------------------------------------- |
223 | | * Function: H5HF__huge_new_id |
224 | | * |
225 | | * Purpose: Determine a new ID for an indirectly accessed 'huge' object |
226 | | * (either filtered or not) |
227 | | * |
228 | | * Return: SUCCEED/FAIL |
229 | | * |
230 | | *------------------------------------------------------------------------- |
231 | | */ |
232 | | static hsize_t |
233 | | H5HF__huge_new_id(H5HF_hdr_t *hdr) |
234 | 0 | { |
235 | 0 | hsize_t new_id; /* New object's ID */ |
236 | 0 | hsize_t ret_value = 0; /* Return value */ |
237 | |
|
238 | 0 | FUNC_ENTER_PACKAGE |
239 | | |
240 | | /* |
241 | | * Check arguments. |
242 | | */ |
243 | 0 | assert(hdr); |
244 | | |
245 | | /* Check for wrapping around 'huge' object ID space */ |
246 | 0 | if (hdr->huge_ids_wrapped) |
247 | | /* Fail for now - eventually should iterate through v2 B-tree, looking for available ID */ |
248 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, 0, "wrapping 'huge' object IDs not supported yet"); |
249 | 0 | else { |
250 | | /* Get new 'huge' object ID to use for object */ |
251 | | /* (avoids using ID 0) */ |
252 | 0 | new_id = ++hdr->huge_next_id; |
253 | | |
254 | | /* Check for wrapping 'huge' object IDs around */ |
255 | 0 | if (hdr->huge_next_id == hdr->huge_max_id) |
256 | 0 | hdr->huge_ids_wrapped = true; |
257 | 0 | } /* end else */ |
258 | | |
259 | | /* Set return value */ |
260 | 0 | ret_value = new_id; |
261 | |
|
262 | 0 | done: |
263 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
264 | 0 | } /* end H5HF__huge_new_id() */ |
265 | | |
266 | | /*------------------------------------------------------------------------- |
267 | | * Function: H5HF__huge_insert |
268 | | * |
269 | | * Purpose: Insert a 'huge' object into the file and track it |
270 | | * |
271 | | * Return: SUCCEED/FAIL |
272 | | * |
273 | | *------------------------------------------------------------------------- |
274 | | */ |
275 | | herr_t |
276 | | H5HF__huge_insert(H5HF_hdr_t *hdr, size_t obj_size, void *obj, void *_id) |
277 | 0 | { |
278 | 0 | uint8_t *id = (uint8_t *)_id; /* Pointer to ID buffer */ |
279 | 0 | haddr_t obj_addr; /* Address of object in the file */ |
280 | 0 | void *write_buf; /* Pointer to buffer to write */ |
281 | 0 | size_t write_size; /* Size of [possibly filtered] object written to file */ |
282 | 0 | unsigned filter_mask = 0; /* Filter mask for object (only used for filtered objects) */ |
283 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
284 | |
|
285 | 0 | FUNC_ENTER_PACKAGE |
286 | | |
287 | | /* |
288 | | * Check arguments. |
289 | | */ |
290 | 0 | assert(hdr); |
291 | 0 | assert(obj_size > hdr->max_man_size); |
292 | 0 | assert(obj); |
293 | 0 | assert(id); |
294 | | |
295 | | /* Check if the v2 B-tree for tracking 'huge' heap objects has been created yet */ |
296 | 0 | if (!H5_addr_defined(hdr->huge_bt2_addr)) { |
297 | | /* Go create (& open) v2 B-tree */ |
298 | 0 | if (H5HF__huge_bt2_create(hdr) < 0) |
299 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, |
300 | 0 | "can't create v2 B-tree for tracking 'huge' heap objects"); |
301 | 0 | } /* end if */ |
302 | 0 | else { |
303 | | /* Check if v2 B-tree is open yet */ |
304 | 0 | if (NULL == hdr->huge_bt2) { |
305 | | /* Open existing v2 B-tree */ |
306 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
307 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
308 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
309 | 0 | } /* end if */ |
310 | 0 | } /* end else */ |
311 | 0 | assert(hdr->huge_bt2); |
312 | | |
313 | | /* Check for I/O pipeline filter on heap */ |
314 | 0 | if (hdr->filter_len > 0) { |
315 | 0 | H5Z_cb_t filter_cb; /* Filter callback structure */ |
316 | 0 | size_t nbytes; /* Number of bytes used */ |
317 | | |
318 | | /* Initialize the filter callback struct */ |
319 | 0 | filter_cb.op_data = NULL; |
320 | 0 | filter_cb.func = NULL; /* no callback function when failed */ |
321 | | |
322 | | /* Allocate buffer to perform I/O filtering on */ |
323 | 0 | write_size = obj_size; |
324 | 0 | if (NULL == (write_buf = H5MM_malloc(write_size))) |
325 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer"); |
326 | 0 | H5MM_memcpy(write_buf, obj, write_size); |
327 | | |
328 | | /* Push direct block data through I/O filter pipeline */ |
329 | 0 | nbytes = write_size; |
330 | 0 | if (H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &write_size, |
331 | 0 | &write_buf) < 0) |
332 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed"); |
333 | | |
334 | | /* Update size of object on disk */ |
335 | 0 | write_size = nbytes; |
336 | 0 | } /* end if */ |
337 | 0 | else { |
338 | 0 | write_buf = obj; |
339 | 0 | write_size = obj_size; |
340 | 0 | } /* end else */ |
341 | | |
342 | | /* Allocate space in the file for storing the 'huge' object */ |
343 | 0 | if (HADDR_UNDEF == (obj_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, (hsize_t)write_size))) |
344 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap huge object"); |
345 | | |
346 | | /* Write the object's data to disk */ |
347 | 0 | if (H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, write_size, write_buf) < 0) |
348 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed"); |
349 | | |
350 | | /* Release buffer for writing, if we had one */ |
351 | 0 | if (write_buf != obj) { |
352 | 0 | assert(hdr->filter_len > 0); |
353 | 0 | H5MM_xfree(write_buf); |
354 | 0 | } /* end if */ |
355 | | |
356 | | /* Perform different actions for directly & indirectly accessed 'huge' objects */ |
357 | 0 | if (hdr->huge_ids_direct) { |
358 | 0 | if (hdr->filter_len > 0) { |
359 | 0 | H5HF_huge_bt2_filt_dir_rec_t obj_rec; /* Record for tracking object */ |
360 | | |
361 | | /* Initialize record for tracking object in v2 B-tree */ |
362 | 0 | obj_rec.addr = obj_addr; |
363 | 0 | obj_rec.len = write_size; |
364 | 0 | obj_rec.filter_mask = filter_mask; |
365 | 0 | obj_rec.obj_size = obj_size; |
366 | | |
367 | | /* Insert record for object in v2 B-tree */ |
368 | 0 | if (H5B2_insert(hdr->huge_bt2, &obj_rec) < 0) |
369 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, |
370 | 0 | "couldn't insert object tracking record in v2 B-tree"); |
371 | | |
372 | | /* Encode ID for user */ |
373 | 0 | *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE; |
374 | 0 | H5F_addr_encode(hdr->f, &id, obj_addr); |
375 | 0 | H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size); |
376 | 0 | UINT32ENCODE(id, filter_mask); |
377 | 0 | H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)obj_size); |
378 | 0 | } /* end if */ |
379 | 0 | else { |
380 | 0 | H5HF_huge_bt2_dir_rec_t obj_rec; /* Record for tracking object */ |
381 | | |
382 | | /* Initialize record for tracking object in v2 B-tree */ |
383 | 0 | obj_rec.addr = obj_addr; |
384 | 0 | obj_rec.len = write_size; |
385 | | |
386 | | /* Insert record for object in v2 B-tree */ |
387 | 0 | if (H5B2_insert(hdr->huge_bt2, &obj_rec) < 0) |
388 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, |
389 | 0 | "couldn't insert object tracking record in v2 B-tree"); |
390 | | |
391 | | /* Encode ID for user */ |
392 | 0 | *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE; |
393 | 0 | H5F_addr_encode(hdr->f, &id, obj_addr); |
394 | 0 | H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size); |
395 | 0 | } /* end if */ |
396 | 0 | } /* end if */ |
397 | 0 | else { |
398 | 0 | H5HF_huge_bt2_filt_indir_rec_t filt_indir_rec; /* Record for tracking filtered object */ |
399 | 0 | H5HF_huge_bt2_indir_rec_t indir_rec; /* Record for tracking non-filtered object */ |
400 | 0 | void *ins_rec; /* Pointer to record to insert */ |
401 | 0 | hsize_t new_id; /* New ID for object */ |
402 | | |
403 | | /* Get new ID for object */ |
404 | 0 | if (0 == (new_id = H5HF__huge_new_id(hdr))) |
405 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't generate new ID for object"); |
406 | | |
407 | 0 | if (hdr->filter_len > 0) { |
408 | | /* Initialize record for object in v2 B-tree */ |
409 | 0 | filt_indir_rec.addr = obj_addr; |
410 | 0 | filt_indir_rec.len = write_size; |
411 | 0 | filt_indir_rec.filter_mask = filter_mask; |
412 | 0 | filt_indir_rec.obj_size = obj_size; |
413 | 0 | filt_indir_rec.id = new_id; |
414 | | |
415 | | /* Set pointer to record to insert */ |
416 | 0 | ins_rec = &filt_indir_rec; |
417 | 0 | } /* end if */ |
418 | 0 | else { |
419 | | /* Initialize record for object in v2 B-tree */ |
420 | 0 | indir_rec.addr = obj_addr; |
421 | 0 | indir_rec.len = write_size; |
422 | 0 | indir_rec.id = new_id; |
423 | | |
424 | | /* Set pointer to record to insert */ |
425 | 0 | ins_rec = &indir_rec; |
426 | 0 | } /* end else */ |
427 | | |
428 | | /* Insert record for tracking object in v2 B-tree */ |
429 | 0 | if (H5B2_insert(hdr->huge_bt2, ins_rec) < 0) |
430 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, |
431 | 0 | "couldn't insert object tracking record in v2 B-tree"); |
432 | | |
433 | | /* Encode ID for user */ |
434 | 0 | *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE; |
435 | 0 | UINT64ENCODE_VAR(id, new_id, hdr->huge_id_size); |
436 | 0 | } /* end else */ |
437 | | |
438 | | /* Update statistics about heap */ |
439 | 0 | hdr->huge_size += obj_size; |
440 | 0 | hdr->huge_nobjs++; |
441 | | |
442 | | /* Mark heap header as modified */ |
443 | 0 | if (H5HF__hdr_dirty(hdr) < 0) |
444 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty"); |
445 | | |
446 | 0 | done: |
447 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
448 | 0 | } /* end H5HF__huge_insert() */ |
449 | | |
450 | | /*------------------------------------------------------------------------- |
451 | | * Function: H5HF__huge_get_obj_len |
452 | | * |
453 | | * Purpose: Get the size of a 'huge' object in a fractal heap |
454 | | * |
455 | | * Return: SUCCEED/FAIL |
456 | | * |
457 | | *------------------------------------------------------------------------- |
458 | | */ |
459 | | herr_t |
460 | | H5HF__huge_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p) |
461 | 0 | { |
462 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
463 | |
|
464 | 0 | FUNC_ENTER_PACKAGE |
465 | | |
466 | | /* |
467 | | * Check arguments. |
468 | | */ |
469 | 0 | assert(hdr); |
470 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
471 | 0 | assert(id); |
472 | 0 | assert(obj_len_p); |
473 | | |
474 | | /* Skip over the flag byte */ |
475 | 0 | id++; |
476 | | |
477 | | /* Check if 'huge' object ID encodes address & length directly */ |
478 | 0 | if (hdr->huge_ids_direct) { |
479 | 0 | if (hdr->filter_len > 0) { |
480 | | /* Skip over filtered object info */ |
481 | 0 | id += hdr->sizeof_addr + hdr->sizeof_size + 4; |
482 | | |
483 | | /* Retrieve the object's length */ |
484 | 0 | H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p); |
485 | 0 | } /* end if */ |
486 | 0 | else { |
487 | | /* Skip over object offset in file */ |
488 | 0 | id += hdr->sizeof_addr; |
489 | | |
490 | | /* Retrieve the object's length */ |
491 | 0 | H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p); |
492 | 0 | } /* end else */ |
493 | 0 | } /* end if */ |
494 | 0 | else { |
495 | 0 | bool found = false; /* Whether entry was found */ |
496 | | |
497 | | /* Check if v2 B-tree is open yet */ |
498 | 0 | if (NULL == hdr->huge_bt2) { |
499 | | /* Open existing v2 B-tree */ |
500 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
501 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
502 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
503 | 0 | } /* end if */ |
504 | | |
505 | 0 | if (hdr->filter_len > 0) { |
506 | 0 | H5HF_huge_bt2_filt_indir_rec_t found_rec; /* Record found from tracking object */ |
507 | 0 | H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */ |
508 | | |
509 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
510 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
511 | | |
512 | | /* Look up object in v2 B-tree */ |
513 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < |
514 | 0 | 0) |
515 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
516 | 0 | if (!found) |
517 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
518 | | |
519 | | /* Retrieve the object's length */ |
520 | 0 | *obj_len_p = (size_t)found_rec.obj_size; |
521 | 0 | } /* end if */ |
522 | 0 | else { |
523 | 0 | H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ |
524 | 0 | H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ |
525 | | |
526 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
527 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
528 | | |
529 | | /* Look up object in v2 B-tree */ |
530 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) |
531 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
532 | 0 | if (!found) |
533 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
534 | | |
535 | | /* Retrieve the object's length */ |
536 | 0 | *obj_len_p = (size_t)found_rec.len; |
537 | 0 | } /* end else */ |
538 | 0 | } /* end else */ |
539 | | |
540 | 0 | done: |
541 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
542 | 0 | } /* end H5HF__huge_get_obj_len() */ |
543 | | |
544 | | /*------------------------------------------------------------------------- |
545 | | * Function: H5HF__huge_get_obj_off |
546 | | * |
547 | | * Purpose: Get the offset of a 'huge' object in a fractal heap |
548 | | * |
549 | | * Return: SUCCEED/FAIL |
550 | | * |
551 | | *------------------------------------------------------------------------- |
552 | | */ |
553 | | herr_t |
554 | | H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p) |
555 | 0 | { |
556 | 0 | haddr_t obj_addr; /* Object's address in the file */ |
557 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
558 | |
|
559 | 0 | FUNC_ENTER_PACKAGE |
560 | | |
561 | | /* |
562 | | * Check arguments. |
563 | | */ |
564 | 0 | assert(hdr); |
565 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
566 | 0 | assert(id); |
567 | 0 | assert(obj_off_p); |
568 | | |
569 | | /* Skip over the flag byte */ |
570 | 0 | id++; |
571 | | |
572 | | /* Check if 'huge' object ID encodes address & length directly */ |
573 | 0 | if (hdr->huge_ids_direct) { |
574 | | /* Retrieve the object's address (common) */ |
575 | 0 | H5F_addr_decode(hdr->f, &id, &obj_addr); |
576 | 0 | } /* end if */ |
577 | 0 | else { |
578 | 0 | bool found = false; /* Whether entry was found */ |
579 | | |
580 | | /* Sanity check */ |
581 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
582 | | |
583 | | /* Check if v2 B-tree is open yet */ |
584 | 0 | if (NULL == hdr->huge_bt2) { |
585 | | /* Open existing v2 B-tree */ |
586 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
587 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
588 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
589 | 0 | } /* end if */ |
590 | | |
591 | 0 | if (hdr->filter_len > 0) { |
592 | 0 | H5HF_huge_bt2_filt_indir_rec_t found_rec; /* Record found from tracking object */ |
593 | 0 | H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */ |
594 | | |
595 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
596 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
597 | | |
598 | | /* Look up object in v2 B-tree */ |
599 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < |
600 | 0 | 0) |
601 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
602 | 0 | if (!found) |
603 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
604 | | |
605 | | /* Retrieve the object's address & length */ |
606 | 0 | obj_addr = found_rec.addr; |
607 | 0 | } /* end if */ |
608 | 0 | else { |
609 | 0 | H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ |
610 | 0 | H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ |
611 | | |
612 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
613 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
614 | | |
615 | | /* Look up object in v2 B-tree */ |
616 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) |
617 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
618 | 0 | if (!found) |
619 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
620 | | |
621 | | /* Retrieve the object's address & length */ |
622 | 0 | obj_addr = found_rec.addr; |
623 | 0 | } /* end else */ |
624 | 0 | } /* end else */ |
625 | | |
626 | | /* Set the value to return */ |
627 | 0 | *obj_off_p = (hsize_t)obj_addr; |
628 | |
|
629 | 0 | done: |
630 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
631 | 0 | } /* end H5HF__huge_get_obj_off() */ |
632 | | |
633 | | /*------------------------------------------------------------------------- |
634 | | * Function: H5HF__huge_op_real |
635 | | * |
636 | | * Purpose: Internal routine to perform an operation on a 'huge' object |
637 | | * |
638 | | * Return: SUCCEED/FAIL |
639 | | * |
640 | | *------------------------------------------------------------------------- |
641 | | */ |
642 | | static herr_t |
643 | | H5HF__huge_op_real(H5HF_hdr_t *hdr, const uint8_t *id, bool is_read, H5HF_operator_t op, void *op_data) |
644 | 0 | { |
645 | 0 | void *read_buf = NULL; /* Pointer to buffer for reading */ |
646 | 0 | haddr_t obj_addr; /* Object's address in the file */ |
647 | 0 | size_t obj_size = 0; /* Object's size in the file */ |
648 | 0 | unsigned filter_mask = 0; /* Filter mask for object (only used for filtered objects) */ |
649 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
650 | |
|
651 | 0 | FUNC_ENTER_PACKAGE |
652 | | |
653 | | /* |
654 | | * Check arguments. |
655 | | */ |
656 | 0 | assert(hdr); |
657 | 0 | assert(id); |
658 | 0 | assert(is_read || op); |
659 | | |
660 | | /* Skip over the flag byte */ |
661 | 0 | id++; |
662 | | |
663 | | /* Check for 'huge' object ID that encodes address & length directly */ |
664 | 0 | if (hdr->huge_ids_direct) { |
665 | | /* Retrieve the object's address and length (common) */ |
666 | 0 | H5F_addr_decode(hdr->f, &id, &obj_addr); |
667 | 0 | H5F_DECODE_LENGTH(hdr->f, id, obj_size); |
668 | | |
669 | | /* Retrieve extra information needed for filtered objects */ |
670 | 0 | if (hdr->filter_len > 0) |
671 | 0 | UINT32DECODE(id, filter_mask); |
672 | 0 | } /* end if */ |
673 | 0 | else { |
674 | 0 | bool found = false; /* Whether entry was found */ |
675 | | |
676 | | /* Sanity check */ |
677 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
678 | | |
679 | | /* Check if v2 B-tree is open yet */ |
680 | 0 | if (NULL == hdr->huge_bt2) { |
681 | | /* Open existing v2 B-tree */ |
682 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
683 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
684 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
685 | 0 | } /* end if */ |
686 | | |
687 | 0 | if (hdr->filter_len > 0) { |
688 | 0 | H5HF_huge_bt2_filt_indir_rec_t found_rec; /* Record found from tracking object */ |
689 | 0 | H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */ |
690 | | |
691 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
692 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
693 | | |
694 | | /* Look up object in v2 B-tree */ |
695 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_filt_indir_found, &found_rec) < |
696 | 0 | 0) |
697 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
698 | 0 | if (!found) |
699 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
700 | | |
701 | | /* Retrieve the object's address & length */ |
702 | 0 | obj_addr = found_rec.addr; |
703 | 0 | H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t); |
704 | 0 | filter_mask = found_rec.filter_mask; |
705 | 0 | } /* end if */ |
706 | 0 | else { |
707 | 0 | H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ |
708 | 0 | H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ |
709 | | |
710 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
711 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
712 | | |
713 | | /* Look up object in v2 B-tree */ |
714 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) |
715 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
716 | 0 | if (!found) |
717 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
718 | | |
719 | | /* Retrieve the object's address & length */ |
720 | 0 | obj_addr = found_rec.addr; |
721 | 0 | H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t); |
722 | 0 | } /* end else */ |
723 | 0 | } /* end else */ |
724 | | |
725 | | /* Set up buffer for reading */ |
726 | 0 | if (hdr->filter_len > 0 || !is_read) { |
727 | 0 | if (NULL == (read_buf = H5MM_malloc((size_t)obj_size))) |
728 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer"); |
729 | 0 | } /* end if */ |
730 | 0 | else |
731 | 0 | read_buf = op_data; |
732 | | |
733 | | /* Read the object's (possibly filtered) data from the file */ |
734 | | /* (reads directly into application's buffer if no filters are present) */ |
735 | 0 | if (H5F_block_read(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, (size_t)obj_size, read_buf) < 0) |
736 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_READERROR, FAIL, "can't read 'huge' object's data from the file"); |
737 | | |
738 | | /* Check for I/O pipeline filter on heap */ |
739 | 0 | if (hdr->filter_len > 0) { |
740 | 0 | H5Z_cb_t filter_cb; /* Filter callback structure */ |
741 | 0 | size_t read_size; /* Object's size in the file */ |
742 | 0 | size_t nbytes; /* Number of bytes used */ |
743 | | |
744 | | /* Initialize the filter callback struct */ |
745 | 0 | filter_cb.op_data = NULL; |
746 | 0 | filter_cb.func = NULL; /* no callback function when failed */ |
747 | | |
748 | | /* De-filter the object */ |
749 | 0 | read_size = nbytes = obj_size; |
750 | 0 | if (H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, |
751 | 0 | &read_size, &read_buf) < 0) |
752 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "input filter failed"); |
753 | 0 | obj_size = nbytes; |
754 | 0 | } /* end if */ |
755 | | |
756 | | /* Perform correct operation on buffer read in */ |
757 | 0 | if (is_read) { |
758 | | /* Copy object to user's buffer if there's filters on heap data */ |
759 | | /* (if there's no filters, the object was read directly into the user's buffer) */ |
760 | 0 | if (hdr->filter_len > 0) |
761 | 0 | H5MM_memcpy(op_data, read_buf, (size_t)obj_size); |
762 | 0 | } /* end if */ |
763 | 0 | else { |
764 | | /* Call the user's 'op' callback */ |
765 | 0 | if (op(read_buf, (size_t)obj_size, op_data) < 0) { |
766 | | /* Release buffer */ |
767 | 0 | read_buf = H5MM_xfree(read_buf); |
768 | | |
769 | | /* Indicate error */ |
770 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed"); |
771 | 0 | } /* end if */ |
772 | 0 | } /* end if */ |
773 | | |
774 | 0 | done: |
775 | | /* Release the buffer for reading */ |
776 | 0 | if (read_buf && read_buf != op_data) |
777 | 0 | read_buf = H5MM_xfree(read_buf); |
778 | |
|
779 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
780 | 0 | } /* end H5HF__huge_op_real() */ |
781 | | |
782 | | /*------------------------------------------------------------------------- |
783 | | * Function: H5HF__huge_write |
784 | | * |
785 | | * Purpose: Write a 'huge' object to the heap |
786 | | * |
787 | | * Note: This implementation somewhat limited: it doesn't handle |
788 | | * heaps with filters, which would require re-compressing the |
789 | | * huge object and probably changing the address of the object |
790 | | * on disk (and possibly the heap ID for "direct" huge IDs). |
791 | | * |
792 | | * Return: SUCCEED/FAIL |
793 | | * |
794 | | *------------------------------------------------------------------------- |
795 | | */ |
796 | | herr_t |
797 | | H5HF__huge_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj) |
798 | 0 | { |
799 | 0 | haddr_t obj_addr = HADDR_UNDEF; /* Object's address in the file */ |
800 | 0 | size_t obj_size = 0; /* Object's size in the file */ |
801 | 0 | herr_t ret_value = SUCCEED; |
802 | |
|
803 | 0 | FUNC_ENTER_PACKAGE |
804 | |
|
805 | 0 | assert(hdr); |
806 | 0 | assert(id); |
807 | 0 | assert(obj); |
808 | | |
809 | | /* Check for filters on the heap */ |
810 | 0 | if (hdr->filter_len > 0) |
811 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, |
812 | 0 | "modifying 'huge' object with filters not supported yet"); |
813 | | |
814 | | /* Skip over the flag byte */ |
815 | 0 | id++; |
816 | | |
817 | | /* Check for 'huge' object ID that encodes address & length directly */ |
818 | 0 | if (hdr->huge_ids_direct) { |
819 | | /* Retrieve the object's address and length (common) */ |
820 | 0 | H5F_addr_decode(hdr->f, &id, &obj_addr); |
821 | 0 | H5F_DECODE_LENGTH(hdr->f, id, obj_size); |
822 | 0 | } |
823 | 0 | else { |
824 | 0 | H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ |
825 | 0 | H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ |
826 | 0 | bool found = false; /* Whether entry was found */ |
827 | | |
828 | | /* Sanity check */ |
829 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
830 | | |
831 | | /* Check if v2 B-tree is open yet */ |
832 | 0 | if (NULL == hdr->huge_bt2) { |
833 | | /* Open existing v2 B-tree */ |
834 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
835 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
836 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
837 | 0 | } |
838 | | |
839 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
840 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
841 | | |
842 | | /* Look up object in v2 B-tree */ |
843 | 0 | if (H5B2_find(hdr->huge_bt2, &search_rec, &found, H5HF__huge_bt2_indir_found, &found_rec) < 0) |
844 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTFIND, FAIL, "can't check for object in v2 B-tree"); |
845 | 0 | if (!found) |
846 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in v2 B-tree"); |
847 | | |
848 | | /* Retrieve the object's address & length */ |
849 | 0 | obj_addr = found_rec.addr; |
850 | 0 | H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t); |
851 | 0 | } |
852 | | |
853 | | /* Write the object's data to the file */ |
854 | | /* (writes directly from application's buffer) */ |
855 | 0 | if (H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, obj_size, obj) < 0) |
856 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed"); |
857 | | |
858 | 0 | done: |
859 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
860 | 0 | } /* end H5HF__huge_write() */ |
861 | | |
862 | | /*------------------------------------------------------------------------- |
863 | | * Function: H5HF__huge_read |
864 | | * |
865 | | * Purpose: Read a 'huge' object from the heap |
866 | | * |
867 | | * Return: SUCCEED/FAIL |
868 | | * |
869 | | *------------------------------------------------------------------------- |
870 | | */ |
871 | | herr_t |
872 | | H5HF__huge_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj) |
873 | 0 | { |
874 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
875 | |
|
876 | 0 | FUNC_ENTER_PACKAGE |
877 | | |
878 | | /* |
879 | | * Check arguments. |
880 | | */ |
881 | 0 | assert(hdr); |
882 | 0 | assert(id); |
883 | 0 | assert(obj); |
884 | | |
885 | | /* Call the internal 'op' routine */ |
886 | 0 | if (H5HF__huge_op_real(hdr, id, true, NULL, obj) < 0) |
887 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object"); |
888 | | |
889 | 0 | done: |
890 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
891 | 0 | } /* end H5HF__huge_read() */ |
892 | | |
893 | | /*------------------------------------------------------------------------- |
894 | | * Function: H5HF__huge_op |
895 | | * |
896 | | * Purpose: Operate directly on a 'huge' object |
897 | | * |
898 | | * Return: SUCCEED/FAIL |
899 | | * |
900 | | *------------------------------------------------------------------------- |
901 | | */ |
902 | | herr_t |
903 | | H5HF__huge_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op, void *op_data) |
904 | 0 | { |
905 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
906 | |
|
907 | 0 | FUNC_ENTER_PACKAGE |
908 | | |
909 | | /* |
910 | | * Check arguments. |
911 | | */ |
912 | 0 | assert(hdr); |
913 | 0 | assert(id); |
914 | 0 | assert(op); |
915 | | |
916 | | /* Call the internal 'op' routine routine */ |
917 | 0 | if (H5HF__huge_op_real(hdr, id, false, op, op_data) < 0) |
918 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object"); |
919 | | |
920 | 0 | done: |
921 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
922 | 0 | } /* end H5HF__huge_op() */ |
923 | | |
924 | | /*------------------------------------------------------------------------- |
925 | | * Function: H5HF__huge_remove |
926 | | * |
927 | | * Purpose: Remove a 'huge' object from the file and the v2 B-tree tracker |
928 | | * |
929 | | * Return: SUCCEED/FAIL |
930 | | * |
931 | | *------------------------------------------------------------------------- |
932 | | */ |
933 | | herr_t |
934 | | H5HF__huge_remove(H5HF_hdr_t *hdr, const uint8_t *id) |
935 | 0 | { |
936 | 0 | H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */ |
937 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
938 | |
|
939 | 0 | FUNC_ENTER_PACKAGE |
940 | | |
941 | | /* |
942 | | * Check arguments. |
943 | | */ |
944 | 0 | assert(hdr); |
945 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
946 | 0 | assert(id); |
947 | | |
948 | | /* Check if v2 B-tree is open yet */ |
949 | 0 | if (NULL == hdr->huge_bt2) { |
950 | | /* Open existing v2 B-tree */ |
951 | 0 | if (NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, hdr->huge_bt2_addr, hdr->f))) |
952 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, |
953 | 0 | "unable to open v2 B-tree for tracking 'huge' heap objects"); |
954 | 0 | } /* end if */ |
955 | | |
956 | | /* Skip over the flag byte */ |
957 | 0 | id++; |
958 | | |
959 | | /* Set up the common callback info */ |
960 | 0 | udata.hdr = hdr; |
961 | | |
962 | | /* Check for 'huge' object ID that encodes address & length directly */ |
963 | 0 | if (hdr->huge_ids_direct) { |
964 | 0 | if (hdr->filter_len > 0) { |
965 | 0 | H5HF_huge_bt2_filt_dir_rec_t search_rec; /* Record for searching for object */ |
966 | | |
967 | | /* Retrieve the object's address and length */ |
968 | | /* (used as key in v2 B-tree record) */ |
969 | 0 | H5F_addr_decode(hdr->f, &id, &search_rec.addr); |
970 | 0 | H5F_DECODE_LENGTH(hdr->f, id, search_rec.len); |
971 | | |
972 | | /* Remove the record for tracking the 'huge' object from the v2 B-tree */ |
973 | | /* (space in the file for the object is freed in the 'remove' callback) */ |
974 | 0 | if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_dir_remove, &udata) < 0) |
975 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree"); |
976 | 0 | } /* end if */ |
977 | 0 | else { |
978 | 0 | H5HF_huge_bt2_dir_rec_t search_rec; /* Record for searching for object */ |
979 | | |
980 | | /* Retrieve the object's address and length */ |
981 | | /* (used as key in v2 B-tree record) */ |
982 | 0 | H5F_addr_decode(hdr->f, &id, &search_rec.addr); |
983 | 0 | H5F_DECODE_LENGTH(hdr->f, id, search_rec.len); |
984 | | |
985 | | /* Remove the record for tracking the 'huge' object from the v2 B-tree */ |
986 | | /* (space in the file for the object is freed in the 'remove' callback) */ |
987 | 0 | if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_dir_remove, &udata) < 0) |
988 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree"); |
989 | 0 | } /* end else */ |
990 | 0 | } /* end if */ |
991 | 0 | else { |
992 | 0 | if (hdr->filter_len > 0) { |
993 | 0 | H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */ |
994 | | |
995 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
996 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
997 | | |
998 | | /* Remove the record for tracking the 'huge' object from the v2 B-tree */ |
999 | | /* (space in the file for the object is freed in the 'remove' callback) */ |
1000 | 0 | if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_filt_indir_remove, &udata) < 0) |
1001 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree"); |
1002 | 0 | } /* end if */ |
1003 | 0 | else { |
1004 | 0 | H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ |
1005 | | |
1006 | | /* Get ID for looking up 'huge' object in v2 B-tree */ |
1007 | 0 | UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size); |
1008 | | |
1009 | | /* Remove the record for tracking the 'huge' object from the v2 B-tree */ |
1010 | | /* (space in the file for the object is freed in the 'remove' callback) */ |
1011 | 0 | if (H5B2_remove(hdr->huge_bt2, &search_rec, H5HF__huge_bt2_indir_remove, &udata) < 0) |
1012 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree"); |
1013 | 0 | } /* end else */ |
1014 | 0 | } /* end else */ |
1015 | | |
1016 | | /* Update statistics about heap */ |
1017 | 0 | hdr->huge_size -= udata.obj_len; |
1018 | 0 | hdr->huge_nobjs--; |
1019 | | |
1020 | | /* Mark heap header as modified */ |
1021 | 0 | if (H5HF__hdr_dirty(hdr) < 0) |
1022 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty"); |
1023 | | |
1024 | 0 | done: |
1025 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1026 | 0 | } /* end H5HF__huge_remove() */ |
1027 | | |
1028 | | /*------------------------------------------------------------------------- |
1029 | | * Function: H5HF__huge_term |
1030 | | * |
1031 | | * Purpose: Shut down the information for tracking 'huge' objects |
1032 | | * |
1033 | | * Return: SUCCEED/FAIL |
1034 | | * |
1035 | | *------------------------------------------------------------------------- |
1036 | | */ |
1037 | | herr_t |
1038 | | H5HF__huge_term(H5HF_hdr_t *hdr) |
1039 | 0 | { |
1040 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1041 | |
|
1042 | 0 | FUNC_ENTER_PACKAGE |
1043 | | |
1044 | | /* |
1045 | | * Check arguments. |
1046 | | */ |
1047 | 0 | assert(hdr); |
1048 | | |
1049 | | /* Check if v2 B-tree index is open */ |
1050 | 0 | if (hdr->huge_bt2) { |
1051 | | /* Sanity check */ |
1052 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
1053 | | |
1054 | | /* Close v2 B-tree index */ |
1055 | 0 | if (H5B2_close(hdr->huge_bt2) < 0) |
1056 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree"); |
1057 | 0 | hdr->huge_bt2 = NULL; |
1058 | 0 | } /* end if */ |
1059 | | |
1060 | | /* Check if there are no more 'huge' objects in the heap and delete the |
1061 | | * v2 B-tree that tracks them, if so |
1062 | | */ |
1063 | 0 | if (H5_addr_defined(hdr->huge_bt2_addr) && hdr->huge_nobjs == 0) { |
1064 | | /* Sanity check */ |
1065 | 0 | assert(hdr->huge_size == 0); |
1066 | | |
1067 | | /* Delete the v2 B-tree */ |
1068 | | /* (any v2 B-tree class will work here) */ |
1069 | 0 | if (H5B2_delete(hdr->f, hdr->huge_bt2_addr, hdr->f, NULL, NULL) < 0) |
1070 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree"); |
1071 | | |
1072 | | /* Reset the information about 'huge' objects in the file */ |
1073 | 0 | hdr->huge_bt2_addr = HADDR_UNDEF; |
1074 | 0 | hdr->huge_next_id = 0; |
1075 | 0 | hdr->huge_ids_wrapped = false; |
1076 | | |
1077 | | /* Mark heap header as modified */ |
1078 | 0 | if (H5HF__hdr_dirty(hdr) < 0) |
1079 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty"); |
1080 | 0 | } /* end if */ |
1081 | | |
1082 | 0 | done: |
1083 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1084 | 0 | } /* end H5HF__huge_term() */ |
1085 | | |
1086 | | /*------------------------------------------------------------------------- |
1087 | | * Function: H5HF__huge_delete |
1088 | | * |
1089 | | * Purpose: Delete all the 'huge' objects in the heap, and the v2 B-tree |
1090 | | * tracker for them |
1091 | | * |
1092 | | * Return: SUCCEED/FAIL |
1093 | | * |
1094 | | *------------------------------------------------------------------------- |
1095 | | */ |
1096 | | herr_t |
1097 | | H5HF__huge_delete(H5HF_hdr_t *hdr) |
1098 | 0 | { |
1099 | 0 | H5HF_huge_remove_ud_t udata; /* User callback data for v2 B-tree remove call */ |
1100 | 0 | H5B2_remove_t op; /* Callback for v2 B-tree removal */ |
1101 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1102 | |
|
1103 | 0 | FUNC_ENTER_PACKAGE |
1104 | | |
1105 | | /* |
1106 | | * Check arguments. |
1107 | | */ |
1108 | 0 | assert(hdr); |
1109 | 0 | assert(H5_addr_defined(hdr->huge_bt2_addr)); |
1110 | 0 | assert(hdr->huge_nobjs); |
1111 | 0 | assert(hdr->huge_size); |
1112 | | |
1113 | | /* Set up the callback info */ |
1114 | 0 | udata.hdr = hdr; |
1115 | | |
1116 | | /* Set the v2 B-tree callback operator */ |
1117 | 0 | if (hdr->huge_ids_direct) { |
1118 | 0 | if (hdr->filter_len > 0) |
1119 | 0 | op = H5HF__huge_bt2_filt_dir_remove; |
1120 | 0 | else |
1121 | 0 | op = H5HF__huge_bt2_dir_remove; |
1122 | 0 | } /* end if */ |
1123 | 0 | else { |
1124 | 0 | if (hdr->filter_len > 0) |
1125 | 0 | op = H5HF__huge_bt2_filt_indir_remove; |
1126 | 0 | else |
1127 | 0 | op = H5HF__huge_bt2_indir_remove; |
1128 | 0 | } /* end else */ |
1129 | | |
1130 | | /* Delete the v2 B-tree */ |
1131 | 0 | if (H5B2_delete(hdr->f, hdr->huge_bt2_addr, hdr->f, op, &udata) < 0) |
1132 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree"); |
1133 | | |
1134 | 0 | done: |
1135 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1136 | 0 | } /* end H5HF__huge_delete() */ |