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: H5HFman.c |
16 | | * |
17 | | * Purpose: "Managed" object routines for fractal heaps. |
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 "H5MMprivate.h" /* Memory management */ |
35 | | |
36 | | /****************/ |
37 | | /* Local Macros */ |
38 | | /****************/ |
39 | | |
40 | | /* Macro to check if we can apply all filters in the pipeline. Use whenever |
41 | | * performing a modification operation */ |
42 | | #define H5HF_MAN_WRITE_CHECK_PLINE(HDR) \ |
43 | 0 | { \ |
44 | 0 | if (!((HDR)->checked_filters)) { \ |
45 | 0 | if ((HDR)->pline.nused) \ |
46 | 0 | if (H5Z_can_apply_direct(&((HDR)->pline)) < 0) \ |
47 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "I/O filters can't operate on this heap"); \ |
48 | 0 | \ |
49 | 0 | (HDR)->checked_filters = true; \ |
50 | 0 | } /* end if */ \ |
51 | 0 | } |
52 | | |
53 | | /******************/ |
54 | | /* Local Typedefs */ |
55 | | /******************/ |
56 | | |
57 | | /********************/ |
58 | | /* Package Typedefs */ |
59 | | /********************/ |
60 | | |
61 | | /********************/ |
62 | | /* Local Prototypes */ |
63 | | /********************/ |
64 | | static herr_t H5HF__man_op_real(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op, void *op_data, |
65 | | unsigned op_flags); |
66 | | |
67 | | /*********************/ |
68 | | /* Package Variables */ |
69 | | /*********************/ |
70 | | |
71 | | /*****************************/ |
72 | | /* Library Private Variables */ |
73 | | /*****************************/ |
74 | | |
75 | | /*******************/ |
76 | | /* Local Variables */ |
77 | | /*******************/ |
78 | | |
79 | | /*------------------------------------------------------------------------- |
80 | | * Function: H5HF__man_insert |
81 | | * |
82 | | * Purpose: Insert an object in a managed direct block |
83 | | * |
84 | | * Return: SUCCEED/FAIL |
85 | | * |
86 | | *------------------------------------------------------------------------- |
87 | | */ |
88 | | herr_t |
89 | | H5HF__man_insert(H5HF_hdr_t *hdr, size_t obj_size, const void *obj, void *_id) |
90 | 0 | { |
91 | 0 | H5HF_free_section_t *sec_node = NULL; /* Pointer to free space section */ |
92 | 0 | H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */ |
93 | 0 | haddr_t dblock_addr = HADDR_UNDEF; /* Direct block address */ |
94 | 0 | size_t dblock_size; /* Direct block size */ |
95 | 0 | uint8_t *id = (uint8_t *)_id; /* Pointer to ID buffer */ |
96 | 0 | size_t blk_off; /* Offset of object within block */ |
97 | 0 | htri_t node_found; /* Whether an existing free list node was found */ |
98 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
99 | |
|
100 | 0 | FUNC_ENTER_PACKAGE |
101 | | |
102 | | /* |
103 | | * Check arguments. |
104 | | */ |
105 | 0 | assert(hdr); |
106 | 0 | assert(obj_size > 0); |
107 | 0 | assert(obj); |
108 | 0 | assert(id); |
109 | | |
110 | | /* Check pipeline */ |
111 | 0 | H5HF_MAN_WRITE_CHECK_PLINE(hdr) |
112 | | |
113 | | /* Look for free space */ |
114 | 0 | if ((node_found = H5HF__space_find(hdr, (hsize_t)obj_size, &sec_node)) < 0) |
115 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap"); |
116 | | |
117 | | /* If we didn't find a node, go create a direct block big enough to hold the requested block */ |
118 | 0 | if (!node_found) |
119 | | /* Allocate direct block big enough to hold requested size */ |
120 | 0 | if (H5HF__man_dblock_new(hdr, obj_size, &sec_node) < 0) |
121 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block"); |
122 | | |
123 | | /* Check for row section */ |
124 | 0 | if (sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || |
125 | 0 | sec_node->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) { |
126 | | |
127 | | /* Allocate 'single' selection out of 'row' selection */ |
128 | 0 | if (H5HF__man_iblock_alloc_row(hdr, &sec_node) < 0) |
129 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up row section"); |
130 | 0 | } /* end if */ |
131 | 0 | assert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE); |
132 | | |
133 | | /* Check for 'single' section being serialized */ |
134 | 0 | if (sec_node->sect_info.state == H5FS_SECT_SERIALIZED) |
135 | 0 | if (H5HF__sect_single_revive(hdr, sec_node) < 0) |
136 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section"); |
137 | 0 | assert(sec_node->sect_info.state == H5FS_SECT_LIVE); |
138 | | |
139 | | /* Retrieve direct block address from section */ |
140 | 0 | if (H5HF__sect_single_dblock_info(hdr, sec_node, &dblock_addr, &dblock_size) < 0) |
141 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information"); |
142 | | |
143 | | /* Lock direct block */ |
144 | 0 | if (NULL == (dblock = H5HF__man_dblock_protect(hdr, dblock_addr, dblock_size, sec_node->u.single.parent, |
145 | 0 | sec_node->u.single.par_entry, H5AC__NO_FLAGS_SET))) |
146 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block"); |
147 | | |
148 | | /* Insert object into block */ |
149 | | |
150 | | /* Get the offset of the object within the block */ |
151 | 0 | H5_CHECK_OVERFLOW((sec_node->sect_info.addr - dblock->block_off), hsize_t, size_t); |
152 | 0 | blk_off = (size_t)(sec_node->sect_info.addr - dblock->block_off); |
153 | | |
154 | | /* Sanity checks */ |
155 | 0 | assert(sec_node->sect_info.size >= obj_size); |
156 | | |
157 | | /* Reduce (& possibly re-add) single section */ |
158 | 0 | if (H5HF__sect_single_reduce(hdr, sec_node, obj_size) < 0) |
159 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce single section node"); |
160 | 0 | sec_node = NULL; |
161 | | |
162 | | /* Encode the object in the block */ |
163 | 0 | { |
164 | 0 | uint8_t *p; /* Temporary pointer to obj info in block */ |
165 | | |
166 | | /* Point to location for object */ |
167 | 0 | p = dblock->blk + blk_off; |
168 | | |
169 | | /* Copy the object's data into the heap */ |
170 | 0 | H5MM_memcpy(p, obj, obj_size); |
171 | 0 | p += obj_size; |
172 | | |
173 | | /* Sanity check */ |
174 | 0 | assert((size_t)(p - (dblock->blk + blk_off)) == obj_size); |
175 | 0 | } /* end block */ |
176 | | |
177 | | /* Set the heap ID for the new object (heap offset & obj length) */ |
178 | 0 | H5HF_MAN_ID_ENCODE(id, hdr, (dblock->block_off + blk_off), obj_size); |
179 | | |
180 | | /* Update statistics about heap */ |
181 | 0 | hdr->man_nobjs++; |
182 | | |
183 | | /* Reduce space available in heap (marks header dirty) */ |
184 | 0 | if (H5HF__hdr_adj_free(hdr, -(ssize_t)obj_size) < 0) |
185 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap"); |
186 | | |
187 | 0 | done: |
188 | | /* Release section node on error */ |
189 | 0 | if (ret_value < 0) |
190 | 0 | if (sec_node && H5HF__sect_single_free((H5FS_section_info_t *)sec_node) < 0) |
191 | 0 | HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release section node"); |
192 | | |
193 | | /* Release the direct block (marked as dirty) */ |
194 | 0 | if (dblock && H5AC_unprotect(hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG) < 0) |
195 | 0 | HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block"); |
196 | |
|
197 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
198 | 0 | } /* end H5HF__man_insert() */ |
199 | | |
200 | | /*------------------------------------------------------------------------- |
201 | | * Function: H5HF__man_get_obj_len |
202 | | * |
203 | | * Purpose: Get the size of a managed heap object |
204 | | * |
205 | | * Return: SUCCEED (Can't fail) |
206 | | * |
207 | | *------------------------------------------------------------------------- |
208 | | */ |
209 | | herr_t |
210 | | H5HF__man_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p) |
211 | 0 | { |
212 | |
|
213 | 0 | FUNC_ENTER_PACKAGE_NOERR |
214 | | |
215 | | /* |
216 | | * Check arguments. |
217 | | */ |
218 | 0 | assert(hdr); |
219 | 0 | assert(id); |
220 | 0 | assert(obj_len_p); |
221 | | |
222 | | /* Skip over the flag byte */ |
223 | 0 | id++; |
224 | | |
225 | | /* Skip over object offset */ |
226 | 0 | id += hdr->heap_off_size; |
227 | | |
228 | | /* Retrieve the entry length */ |
229 | 0 | UINT64DECODE_VAR(id, *obj_len_p, hdr->heap_len_size); |
230 | |
|
231 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
232 | 0 | } /* end H5HF__man_get_obj_len() */ |
233 | | |
234 | | /*------------------------------------------------------------------------- |
235 | | * Function: H5HF__man_get_obj_off |
236 | | * |
237 | | * Purpose: Get the offset of a managed heap object |
238 | | * |
239 | | * Return: SUCCEED (Can't fail) |
240 | | * |
241 | | *------------------------------------------------------------------------- |
242 | | */ |
243 | | void |
244 | | H5HF__man_get_obj_off(const H5HF_hdr_t *hdr, const uint8_t *id, hsize_t *obj_off_p) |
245 | 0 | { |
246 | 0 | FUNC_ENTER_PACKAGE_NOERR |
247 | | |
248 | | /* |
249 | | * Check arguments. |
250 | | */ |
251 | 0 | assert(hdr); |
252 | 0 | assert(id); |
253 | 0 | assert(obj_off_p); |
254 | | |
255 | | /* Skip over the flag byte */ |
256 | 0 | id++; |
257 | | |
258 | | /* Skip over object offset */ |
259 | 0 | UINT64DECODE_VAR(id, *obj_off_p, hdr->heap_off_size); |
260 | |
|
261 | 0 | FUNC_LEAVE_NOAPI_VOID |
262 | 0 | } /* end H5HF__man_get_obj_off() */ |
263 | | |
264 | | /*------------------------------------------------------------------------- |
265 | | * Function: H5HF__man_op_real |
266 | | * |
267 | | * Purpose: Internal routine to perform an operation on a managed heap |
268 | | * object |
269 | | * |
270 | | * Return: SUCCEED/FAIL |
271 | | * |
272 | | *------------------------------------------------------------------------- |
273 | | */ |
274 | | static herr_t |
275 | | H5HF__man_op_real(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op, void *op_data, unsigned op_flags) |
276 | 0 | { |
277 | 0 | H5HF_direct_t *dblock = NULL; /* Pointer to direct block to query */ |
278 | 0 | unsigned dblock_access_flags; /* Access method for direct block */ |
279 | | /* must equal either |
280 | | * H5AC__NO_FLAGS_SET or |
281 | | * H5AC__READ_ONLY_FLAG |
282 | | */ |
283 | 0 | haddr_t dblock_addr = HADDR_UNDEF; /* Direct block address */ |
284 | 0 | size_t dblock_size; /* Direct block size */ |
285 | 0 | unsigned dblock_cache_flags = 0; /* Flags for unprotecting direct block */ |
286 | 0 | hsize_t obj_off; /* Object's offset in heap */ |
287 | 0 | size_t obj_len; /* Object's length in heap */ |
288 | 0 | size_t blk_off; /* Offset of object in block */ |
289 | 0 | uint8_t *p; /* Temporary pointer to obj info in block */ |
290 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
291 | |
|
292 | 0 | FUNC_ENTER_PACKAGE |
293 | | |
294 | | /* |
295 | | * Check arguments. |
296 | | */ |
297 | 0 | assert(hdr); |
298 | 0 | assert(id); |
299 | 0 | assert(op); |
300 | | |
301 | | /* Set the access mode for the direct block */ |
302 | 0 | if (op_flags & H5HF_OP_MODIFY) { |
303 | | /* Check pipeline */ |
304 | 0 | H5HF_MAN_WRITE_CHECK_PLINE(hdr) |
305 | | |
306 | 0 | dblock_access_flags = H5AC__NO_FLAGS_SET; |
307 | 0 | dblock_cache_flags = H5AC__DIRTIED_FLAG; |
308 | 0 | } /* end if */ |
309 | 0 | else { |
310 | 0 | dblock_access_flags = H5AC__READ_ONLY_FLAG; |
311 | 0 | dblock_cache_flags = H5AC__NO_FLAGS_SET; |
312 | 0 | } /* end else */ |
313 | | |
314 | | /* Skip over the flag byte */ |
315 | 0 | id++; |
316 | | |
317 | | /* Decode the object offset within the heap & its length */ |
318 | 0 | UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size); |
319 | 0 | UINT64DECODE_VAR(id, obj_len, hdr->heap_len_size); |
320 | | |
321 | | /* Check for bad offset or length */ |
322 | 0 | if (obj_off == 0) |
323 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap offset"); |
324 | 0 | if (obj_off > hdr->man_size) |
325 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large"); |
326 | 0 | if (obj_len == 0) |
327 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap object size"); |
328 | 0 | if (obj_len > hdr->man_dtable.cparam.max_direct_size) |
329 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block"); |
330 | 0 | if (obj_len > hdr->max_man_size) |
331 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone"); |
332 | | |
333 | | /* Check for root direct block */ |
334 | 0 | if (hdr->man_dtable.curr_root_rows == 0) { |
335 | | /* Set direct block info */ |
336 | 0 | dblock_addr = hdr->man_dtable.table_addr; |
337 | 0 | dblock_size = hdr->man_dtable.cparam.start_block_size; |
338 | | |
339 | | /* Lock direct block */ |
340 | 0 | if (NULL == |
341 | 0 | (dblock = H5HF__man_dblock_protect(hdr, dblock_addr, dblock_size, NULL, 0, dblock_access_flags))) |
342 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block"); |
343 | 0 | } /* end if */ |
344 | 0 | else { |
345 | 0 | H5HF_indirect_t *iblock; /* Pointer to indirect block */ |
346 | 0 | bool did_protect; /* Whether we protected the indirect block or not */ |
347 | 0 | unsigned entry; /* Entry of block */ |
348 | | |
349 | | /* Look up indirect block containing direct block */ |
350 | 0 | if (H5HF__man_dblock_locate(hdr, obj_off, &iblock, &entry, &did_protect, H5AC__READ_ONLY_FLAG) < 0) |
351 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section"); |
352 | | |
353 | | /* Set direct block info */ |
354 | 0 | dblock_addr = iblock->ents[entry].addr; |
355 | 0 | H5_CHECK_OVERFLOW((hdr->man_dtable.row_block_size[entry / hdr->man_dtable.cparam.width]), hsize_t, |
356 | 0 | size_t); |
357 | 0 | dblock_size = (size_t)hdr->man_dtable.row_block_size[entry / hdr->man_dtable.cparam.width]; |
358 | | |
359 | | /* Check for offset of invalid direct block */ |
360 | 0 | if (!H5_addr_defined(dblock_addr)) { |
361 | | /* Unlock indirect block */ |
362 | 0 | if (H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0) |
363 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, |
364 | 0 | "unable to release fractal heap indirect block"); |
365 | | |
366 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block"); |
367 | 0 | } /* end if */ |
368 | | |
369 | | /* Lock direct block */ |
370 | 0 | if (NULL == (dblock = H5HF__man_dblock_protect(hdr, dblock_addr, dblock_size, iblock, entry, |
371 | 0 | dblock_access_flags))) { |
372 | | /* Unlock indirect block */ |
373 | 0 | if (H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0) |
374 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, |
375 | 0 | "unable to release fractal heap indirect block"); |
376 | | |
377 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block"); |
378 | 0 | } /* end if */ |
379 | | |
380 | | /* Unlock indirect block */ |
381 | 0 | if (H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0) |
382 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block"); |
383 | 0 | iblock = NULL; |
384 | 0 | } /* end else */ |
385 | | |
386 | | /* Compute offset of object within block */ |
387 | 0 | assert((obj_off - dblock->block_off) < (hsize_t)dblock_size); |
388 | 0 | blk_off = (size_t)(obj_off - dblock->block_off); |
389 | | |
390 | | /* Check for object's offset in the direct block prefix information */ |
391 | 0 | if (blk_off < (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)) |
392 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object located in prefix of direct block"); |
393 | | |
394 | | /* Check for object's length overrunning the end of the direct block */ |
395 | 0 | if ((blk_off + obj_len) > dblock_size) |
396 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object overruns end of direct block"); |
397 | | |
398 | | /* Point to location for object */ |
399 | 0 | p = dblock->blk + blk_off; |
400 | | |
401 | | /* Call the user's 'op' callback */ |
402 | 0 | if (op(p, obj_len, op_data) < 0) |
403 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed"); |
404 | | |
405 | 0 | done: |
406 | | /* Unlock direct block */ |
407 | 0 | if (dblock && H5AC_unprotect(hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, dblock_cache_flags) < 0) |
408 | 0 | HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block"); |
409 | |
|
410 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
411 | 0 | } /* end H5HF__man_op_real() */ |
412 | | |
413 | | /*------------------------------------------------------------------------- |
414 | | * Function: H5HF__man_read |
415 | | * |
416 | | * Purpose: Read an object from a managed heap |
417 | | * |
418 | | * Return: SUCCEED/FAIL |
419 | | * |
420 | | *------------------------------------------------------------------------- |
421 | | */ |
422 | | herr_t |
423 | | H5HF__man_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj) |
424 | 0 | { |
425 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
426 | |
|
427 | 0 | FUNC_ENTER_PACKAGE |
428 | | |
429 | | /* |
430 | | * Check arguments. |
431 | | */ |
432 | 0 | assert(hdr); |
433 | 0 | assert(id); |
434 | 0 | assert(obj); |
435 | | |
436 | | /* Call the internal 'op' routine routine */ |
437 | 0 | if (H5HF__man_op_real(hdr, id, H5HF__op_read, obj, 0) < 0) |
438 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object"); |
439 | | |
440 | 0 | done: |
441 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
442 | 0 | } /* end H5HF__man_read() */ |
443 | | |
444 | | /*------------------------------------------------------------------------- |
445 | | * Function: H5HF__man_write |
446 | | * |
447 | | * Purpose: Write an object to a managed heap |
448 | | * |
449 | | * Return: SUCCEED/FAIL |
450 | | * |
451 | | *------------------------------------------------------------------------- |
452 | | */ |
453 | | herr_t |
454 | | H5HF__man_write(H5HF_hdr_t *hdr, const uint8_t *id, const void *obj) |
455 | 0 | { |
456 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
457 | |
|
458 | 0 | FUNC_ENTER_PACKAGE |
459 | | |
460 | | /* |
461 | | * Check arguments. |
462 | | */ |
463 | 0 | assert(hdr); |
464 | 0 | assert(id); |
465 | 0 | assert(obj); |
466 | | |
467 | | /* Call the internal 'op' routine routine |
468 | | * |
469 | | * In this case, the callback operation needs to modify the obj buffer that |
470 | | * was passed in as const. We quiet the warning here because an obj pointer |
471 | | * that was originally const should *never* arrive here. |
472 | | */ |
473 | 0 | H5_WARN_CAST_AWAY_CONST_OFF |
474 | 0 | if (H5HF__man_op_real(hdr, id, H5HF__op_write, (void *)obj, H5HF_OP_MODIFY) < 0) |
475 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object"); |
476 | 0 | H5_WARN_CAST_AWAY_CONST_ON |
477 | | |
478 | 0 | done: |
479 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
480 | 0 | } /* end H5HF__man_write() */ |
481 | | |
482 | | /*------------------------------------------------------------------------- |
483 | | * Function: H5HF__man_op |
484 | | * |
485 | | * Purpose: Operate directly on an object from a managed heap |
486 | | * |
487 | | * Return: SUCCEED/FAIL |
488 | | * |
489 | | *------------------------------------------------------------------------- |
490 | | */ |
491 | | herr_t |
492 | | H5HF__man_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op, void *op_data) |
493 | 0 | { |
494 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
495 | |
|
496 | 0 | FUNC_ENTER_PACKAGE |
497 | | |
498 | | /* |
499 | | * Check arguments. |
500 | | */ |
501 | 0 | assert(hdr); |
502 | 0 | assert(id); |
503 | 0 | assert(op); |
504 | | |
505 | | /* Call the internal 'op' routine routine */ |
506 | 0 | if (H5HF__man_op_real(hdr, id, op, op_data, 0) < 0) |
507 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object"); |
508 | | |
509 | 0 | done: |
510 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
511 | 0 | } /* end H5HF__man_op() */ |
512 | | |
513 | | /*------------------------------------------------------------------------- |
514 | | * Function: H5HF__man_remove |
515 | | * |
516 | | * Purpose: Remove an object from a managed heap |
517 | | * |
518 | | * Return: SUCCEED/FAIL |
519 | | * |
520 | | *------------------------------------------------------------------------- |
521 | | */ |
522 | | herr_t |
523 | | H5HF__man_remove(H5HF_hdr_t *hdr, const uint8_t *id) |
524 | 0 | { |
525 | 0 | H5HF_free_section_t *sec_node = NULL; /* Pointer to free space section for block */ |
526 | 0 | H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ |
527 | 0 | bool did_protect = false; /* Whether we protected the indirect block or not */ |
528 | 0 | hsize_t obj_off; /* Object's offset in heap */ |
529 | 0 | size_t obj_len; /* Object's length in heap */ |
530 | 0 | size_t dblock_size; /* Direct block size */ |
531 | 0 | hsize_t dblock_block_off; /* Offset of the direct block within the heap's address space */ |
532 | 0 | unsigned dblock_entry; /* Entry of direct block in parent indirect block */ |
533 | 0 | size_t blk_off; /* Offset of object in block */ |
534 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
535 | |
|
536 | 0 | FUNC_ENTER_PACKAGE |
537 | | |
538 | | /* |
539 | | * Check arguments. |
540 | | */ |
541 | 0 | assert(hdr); |
542 | 0 | assert(id); |
543 | | |
544 | | /* Check pipeline */ |
545 | 0 | H5HF_MAN_WRITE_CHECK_PLINE(hdr) |
546 | | |
547 | | /* Skip over the flag byte */ |
548 | 0 | id++; |
549 | | |
550 | | /* Decode the object offset within the heap & it's length */ |
551 | 0 | UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size); |
552 | 0 | UINT64DECODE_VAR(id, obj_len, hdr->heap_len_size); |
553 | | |
554 | | /* Check for bad offset or length */ |
555 | 0 | if (obj_off == 0) |
556 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap offset"); |
557 | 0 | if (obj_off > hdr->man_size) |
558 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large"); |
559 | 0 | if (obj_len == 0) |
560 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap object size"); |
561 | 0 | if (obj_len > hdr->man_dtable.cparam.max_direct_size) |
562 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block"); |
563 | 0 | if (obj_len > hdr->max_man_size) |
564 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone"); |
565 | | |
566 | | /* Check for root direct block */ |
567 | 0 | if (hdr->man_dtable.curr_root_rows == 0) { |
568 | | /* Set direct block info */ |
569 | 0 | dblock_size = hdr->man_dtable.cparam.start_block_size; |
570 | 0 | dblock_block_off = 0; |
571 | 0 | dblock_entry = 0; |
572 | 0 | } /* end if */ |
573 | 0 | else { |
574 | | /* Look up indirect block containing direct block */ |
575 | 0 | if (H5HF__man_dblock_locate(hdr, obj_off, &iblock, &dblock_entry, &did_protect, H5AC__NO_FLAGS_SET) < |
576 | 0 | 0) |
577 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section"); |
578 | | |
579 | | /* Check for offset of invalid direct block */ |
580 | 0 | if (!H5_addr_defined(iblock->ents[dblock_entry].addr)) |
581 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block"); |
582 | | |
583 | | /* Set direct block info */ |
584 | 0 | H5_CHECK_OVERFLOW((hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]), |
585 | 0 | hsize_t, size_t); |
586 | 0 | dblock_size = (size_t)(hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]); |
587 | | |
588 | | /* Compute the direct block's offset in the heap's address space */ |
589 | | /* (based on parent indirect block's block offset) */ |
590 | 0 | dblock_block_off = iblock->block_off; |
591 | 0 | dblock_block_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width]; |
592 | 0 | dblock_block_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * |
593 | 0 | (dblock_entry % hdr->man_dtable.cparam.width); |
594 | 0 | } /* end else */ |
595 | | |
596 | | /* Compute offset of object within block */ |
597 | 0 | assert((obj_off - dblock_block_off) < (hsize_t)dblock_size); |
598 | 0 | blk_off = (size_t)(obj_off - dblock_block_off); |
599 | | |
600 | | /* Check for object's offset in the direct block prefix information */ |
601 | 0 | if (blk_off < (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)) |
602 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object located in prefix of direct block"); |
603 | | |
604 | | /* Check for object's length overrunning the end of the direct block */ |
605 | 0 | if ((blk_off + obj_len) > dblock_size) |
606 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object overruns end of direct block"); |
607 | | |
608 | | /* Create free space section node */ |
609 | 0 | if (NULL == (sec_node = H5HF__sect_single_new(obj_off, obj_len, iblock, dblock_entry))) |
610 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for direct block's free space"); |
611 | | |
612 | | /* Unlock indirect block */ |
613 | 0 | if (iblock) { |
614 | 0 | if (H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0) |
615 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block"); |
616 | 0 | iblock = NULL; |
617 | 0 | } /* end if */ |
618 | | |
619 | | /* Increase space available in heap (marks header dirty) */ |
620 | 0 | if (H5HF__hdr_adj_free(hdr, (ssize_t)obj_len) < 0) |
621 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap"); |
622 | | |
623 | | /* Update statistics about heap */ |
624 | 0 | hdr->man_nobjs--; |
625 | | |
626 | | /* Return free space to the heap's list of space */ |
627 | 0 | if (H5HF__space_add(hdr, sec_node, H5FS_ADD_RETURNED_SPACE) < 0) |
628 | 0 | HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list"); |
629 | 0 | sec_node = NULL; |
630 | |
|
631 | 0 | done: |
632 | 0 | if (ret_value < 0) { |
633 | | /* Release section node */ |
634 | 0 | if (sec_node && H5HF__sect_single_free((H5FS_section_info_t *)sec_node) < 0) |
635 | 0 | HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release section node"); |
636 | 0 | } /* end if */ |
637 | | |
638 | | /* Unlock indirect block */ |
639 | 0 | if (iblock && H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0) |
640 | 0 | HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block"); |
641 | |
|
642 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
643 | 0 | } /* end H5HF__man_remove() */ |