1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the files COPYING and Copyright.html. COPYING can be found at the root *
9 * of the source code distribution tree; Copyright.html can be found at the *
10 * root level of an installed copy of the electronic HDF5 document set and *
11 * is linked from the top-level documents page. It can also be found at *
12 * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
13 * access to either file, you may request a copy from help@hdfgroup.org. *
14 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /*
17 * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
18 * Monday, May 1, 2006
19 *
20 * Purpose: Free space section routines for fractal heaps.
21 *
22 */
23
24 /****************/
25 /* Module Setup */
26 /****************/
27
28 #define H5HF_PACKAGE /*suppress error about including H5HFpkg */
29
30 /***********/
31 /* Headers */
32 /***********/
33 #include "H5private.h" /* Generic Functions */
34 #include "H5Eprivate.h" /* Error handling */
35 #include "H5HFpkg.h" /* Fractal heaps */
36 #include "H5MMprivate.h" /* Memory management */
37 #include "H5VMprivate.h" /* Vectors and arrays */
38
39 /****************/
40 /* Local Macros */
41 /****************/
42
43 /* Size of serialized indirect section information */
44 #define H5HF_SECT_INDIRECT_SERIAL_SIZE(h) ( \
45 (h)->heap_off_size /* Indirect block's offset in "heap space" */ \
46 + 2 /* Row */ \
47 + 2 /* Column */ \
48 + 2 /* # of entries */ \
49 )
50
51
52 /******************/
53 /* Local Typedefs */
54 /******************/
55
56 /* Typedef for "class private" information for sections */
57 typedef struct {
58 H5HF_hdr_t *hdr; /* Pointer to fractal heap header */
59 } H5HF_sect_private_t;
60
61
62 /********************/
63 /* Package Typedefs */
64 /********************/
65
66
67 /********************/
68 /* Local Prototypes */
69 /********************/
70
71 /* Shared routines */
72 static herr_t H5HF_sect_init_cls(H5FS_section_class_t *cls,
73 H5HF_hdr_t *hdr);
74 static herr_t H5HF_sect_term_cls(H5FS_section_class_t *cls);
75 static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type,
76 haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state);
77 static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect,
78 H5HF_indirect_t *parent);
79
80 /* 'single' section routines */
81 static herr_t H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id,
82 hbool_t refresh, H5HF_free_section_t *sect);
83 static herr_t H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id,
84 H5HF_free_section_t *sect);
85
86 /* 'single' section callbacks */
87 static herr_t H5HF_sect_single_add(H5FS_section_info_t *sect, unsigned *flags,
88 void *udata);
89 static H5FS_section_info_t *H5HF_sect_single_deserialize(const H5FS_section_class_t *cls,
90 hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
91 unsigned *des_flags);
92 static htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
93 const H5FS_section_info_t *sect2, void *udata);
94 static herr_t H5HF_sect_single_merge(H5FS_section_info_t *sect1,
95 H5FS_section_info_t *sect2, void *udata);
96 static htri_t H5HF_sect_single_can_shrink(const H5FS_section_info_t *sect,
97 void *udata);
98 static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **_sect,
99 void *udata);
100 static herr_t H5HF_sect_single_valid(const H5FS_section_class_t *cls,
101 const H5FS_section_info_t *sect);
102
103 /* 'row' section routines */
104 static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off,
105 hsize_t sect_size, hbool_t is_first, unsigned row, unsigned col,
106 unsigned nentries, H5HF_free_section_t *under_sect);
107 static herr_t H5HF_sect_row_first(H5HF_hdr_t *hdr, hid_t dxpl_id,
108 H5HF_free_section_t *sect);
109 static herr_t H5HF_sect_row_from_single(H5HF_hdr_t *hdr,
110 H5HF_free_section_t *sect, H5HF_direct_t *dblock);
111 static herr_t H5HF_sect_row_free_real(H5HF_free_section_t *sect);
112
113 /* 'row' section callbacks */
114 static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *udata);
115 static herr_t H5HF_sect_row_term_cls(H5FS_section_class_t *cls);
116 static herr_t H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
117 const H5FS_section_info_t *sect, uint8_t *buf);
118 static H5FS_section_info_t *H5HF_sect_row_deserialize(const H5FS_section_class_t *cls,
119 hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
120 unsigned *des_flags);
121 static htri_t H5HF_sect_row_can_merge(const H5FS_section_info_t *sect1,
122 const H5FS_section_info_t *sect2, void *udata);
123 static herr_t H5HF_sect_row_merge(H5FS_section_info_t *sect1,
124 H5FS_section_info_t *sect2, void *udata);
125 static htri_t H5HF_sect_row_can_shrink(const H5FS_section_info_t *sect,
126 void *udata);
127 static herr_t H5HF_sect_row_shrink(H5FS_section_info_t **sect,
128 void *udata);
129 static herr_t H5HF_sect_row_free(H5FS_section_info_t *sect);
130 static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls,
131 const H5FS_section_info_t *sect);
132 static herr_t H5HF_sect_row_debug(const H5FS_section_info_t *sect,
133 FILE *stream, int indent, int fwidth);
134
135 /* 'indirect' section routines */
136 static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr,
137 haddr_t sect_off, hsize_t sect_size,
138 H5HF_indirect_t *iblock, hsize_t iblock_off,
139 unsigned row, unsigned col, unsigned nentries);
140 static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
141 H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect,
142 unsigned space_flags, unsigned start_row, unsigned start_col,
143 unsigned end_row, unsigned end_col);
144 static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr,
145 H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect);
146 static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect);
147 static herr_t H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
148 H5HF_free_section_t *sect);
149 static herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
150 H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock);
151 static herr_t H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
152 H5HF_free_section_t *row_sect, hbool_t *alloc_from_start);
153 static herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
154 H5HF_free_section_t *sect, unsigned child_entry);
155 static herr_t H5HF_sect_indirect_first(H5HF_hdr_t *hdr, hid_t dxpl_id,
156 H5HF_free_section_t *sect);
157 static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect);
158 static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect);
159 static hsize_t H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect);
160 static H5HF_free_section_t * H5HF_sect_indirect_top(H5HF_free_section_t *sect);
161 static herr_t H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
162 H5HF_free_section_t *sect1, H5HF_free_section_t *sect2);
163 static herr_t H5HF_sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
164 static herr_t H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id,
165 H5HF_free_section_t *sect);
166 static herr_t H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr,
167 const H5HF_free_section_t *sect, uint8_t *buf);
168 static H5FS_section_info_t *H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr,
169 hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
170 unsigned *des_flags);
171 static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect);
172 static herr_t H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr,
173 const H5HF_free_section_t *sect);
174 static herr_t H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
175 FILE *stream, int indent, int fwidth);
176
177 /* 'indirect' section callbacks */
178 static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *udata);
179 static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls);
180
181
182 /*********************/
183 /* Package Variables */
184 /*********************/
185
186 /* Class info for "single" free space sections */
187 H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
188 /* Class variables */
189 H5HF_FSPACE_SECT_SINGLE, /* Section type */
190 0, /* Extra serialized size */
191 H5FS_CLS_MERGE_SYM, /* Class flags */
192 NULL, /* Class private info */
193
194 /* Class methods */
195 NULL, /* Initialize section class */
196 NULL, /* Terminate section class */
197
198 /* Object methods */
199 H5HF_sect_single_add, /* Add section */
200 NULL, /* Serialize section */
201 H5HF_sect_single_deserialize, /* Deserialize section */
202 H5HF_sect_single_can_merge, /* Can sections merge? */
203 H5HF_sect_single_merge, /* Merge sections */
204 H5HF_sect_single_can_shrink, /* Can section shrink container?*/
205 H5HF_sect_single_shrink, /* Shrink container w/section */
206 H5HF_sect_single_free, /* Free section */
207 H5HF_sect_single_valid, /* Check validity of section */
208 NULL, /* Split section node for alignment */
209 NULL, /* Dump debugging for section */
210 }};
211
212 /* Class info for "first row" free space sections */
213 /* (Same as "normal" row sections, except they also act as a proxy for the
214 * underlying indirect section
215 */
216 H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
217 /* Class variables */
218 H5HF_FSPACE_SECT_FIRST_ROW, /* Section type */
219 0, /* Extra serialized size */
220 H5FS_CLS_MERGE_SYM, /* Class flags */
221 NULL, /* Class private info */
222
223 /* Class methods */
224 H5HF_sect_row_init_cls, /* Initialize section class */
225 H5HF_sect_row_term_cls, /* Terminate section class */
226
227 /* Object methods */
228 NULL, /* Add section */
229 H5HF_sect_row_serialize, /* Serialize section */
230 H5HF_sect_row_deserialize, /* Deserialize section */
231 H5HF_sect_row_can_merge, /* Can sections merge? */
232 H5HF_sect_row_merge, /* Merge sections */
233 H5HF_sect_row_can_shrink, /* Can section shrink container?*/
234 H5HF_sect_row_shrink, /* Shrink container w/section */
235 H5HF_sect_row_free, /* Free section */
236 H5HF_sect_row_valid, /* Check validity of section */
237 NULL, /* Split section node for alignment */
238 H5HF_sect_row_debug, /* Dump debugging for section */
239 }};
240
241 /* Class info for "normal row" free space sections */
242 H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
243 /* Class variables */
244 H5HF_FSPACE_SECT_NORMAL_ROW, /* Section type */
245 0, /* Extra serialized size */
246 H5FS_CLS_MERGE_SYM|H5FS_CLS_SEPAR_OBJ|H5FS_CLS_GHOST_OBJ, /* Class flags */
247 NULL, /* Class private info */
248
249 /* Class methods */
250 H5HF_sect_row_init_cls, /* Initialize section class */
251 H5HF_sect_row_term_cls, /* Terminate section class */
252
253 /* Object methods */
254 NULL, /* Add section */
255 NULL, /* Serialize section */
256 NULL, /* Deserialize section */
257 NULL, /* Can sections merge? */
258 NULL, /* Merge sections */
259 NULL, /* Can section shrink container?*/
260 NULL, /* Shrink container w/section */
261 H5HF_sect_row_free, /* Free section */
262 H5HF_sect_row_valid, /* Check validity of section */
263 NULL, /* Split section node for alignment */
264 H5HF_sect_row_debug, /* Dump debugging for section */
265 }};
266
267 /* Class info for "indirect" free space sections */
268 /* (No object callbacks necessary - objects of this class should never be in
269 * section manager)
270 */
271 H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
272 /* Class variables */
273 H5HF_FSPACE_SECT_INDIRECT, /* Section type */
274 0, /* Extra serialized size */
275 H5FS_CLS_MERGE_SYM|H5FS_CLS_GHOST_OBJ, /* Class flags */
276 NULL, /* Class private info */
277
278 /* Class methods */
279 H5HF_sect_indirect_init_cls, /* Initialize section class */
280 H5HF_sect_indirect_term_cls, /* Terminate section class */
281
282 /* Object methods */
283 NULL, /* Add section */
284 NULL, /* Serialize section */
285 NULL, /* Deserialize section */
286 NULL, /* Can sections merge? */
287 NULL, /* Merge sections */
288 NULL, /* Can section shrink container?*/
289 NULL, /* Shrink container w/section */
290 NULL, /* Free section */
291 NULL, /* Check validity of section */
292 NULL, /* Split section node for alignment */
293 NULL, /* Dump debugging for section */
294 }};
295
296 /* Declare a free list to manage the H5HF_free_section_t struct */
297 H5FL_DEFINE(H5HF_free_section_t);
298
299
300 /*****************************/
301 /* Library Private Variables */
302 /*****************************/
303
304
305 /*******************/
306 /* Local Variables */
307 /*******************/
308
309
310
311 /*-------------------------------------------------------------------------
312 * Function: H5HF_sect_init_cls
313 *
314 * Purpose: Initialize the common class structure
315 *
316 * Return: Success: non-negative
317 * Failure: negative
318 *
319 * Programmer: Quincey Koziol
320 * Tuesday, July 25, 2006
321 *
322 *-------------------------------------------------------------------------
323 */
324 static herr_t
H5HF_sect_init_cls(H5FS_section_class_t * cls,H5HF_hdr_t * hdr)325 H5HF_sect_init_cls(H5FS_section_class_t *cls, H5HF_hdr_t *hdr)
326 {
327 H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
328 herr_t ret_value = SUCCEED; /* Return value */
329
330 FUNC_ENTER_NOAPI_NOINIT
331
332 /* Check arguments. */
333 HDassert(cls);
334 HDassert(!cls->cls_private);
335
336 /* Allocate & initialize the class-private (i.e. private shared) information
337 * for this type of section
338 */
339 if(NULL == (cls_prvt = (H5HF_sect_private_t *)H5MM_malloc(sizeof(H5HF_sect_private_t))))
340 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
341 cls_prvt->hdr = hdr;
342 cls->cls_private = cls_prvt;
343
344 /* Increment reference count on heap header */
345 if(H5HF_hdr_incr(hdr) < 0)
346 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
347
348 done:
349 FUNC_LEAVE_NOAPI(ret_value)
350 } /* H5HF_sect_init_cls() */
351
352
353 /*-------------------------------------------------------------------------
354 * Function: H5HF_sect_term_cls
355 *
356 * Purpose: Terminate the common class structure
357 *
358 * Return: Success: non-negative
359 * Failure: negative
360 *
361 * Programmer: Quincey Koziol
362 * Tuesday, July 25, 2006
363 *
364 *-------------------------------------------------------------------------
365 */
366 static herr_t
H5HF_sect_term_cls(H5FS_section_class_t * cls)367 H5HF_sect_term_cls(H5FS_section_class_t *cls)
368 {
369 H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
370 herr_t ret_value = SUCCEED; /* Return value */
371
372 FUNC_ENTER_NOAPI_NOINIT
373
374 /* Check arguments. */
375 HDassert(cls);
376
377 /* Get pointer to class private info */
378 cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
379
380 /* Decrement reference count on heap header */
381 if(H5HF_hdr_decr(cls_prvt->hdr) < 0)
382 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
383
384 /* Free the class private information */
385 cls->cls_private = H5MM_xfree(cls_prvt);
386
387 done:
388 FUNC_LEAVE_NOAPI(ret_value)
389 } /* H5HF_sect_term_cls() */
390
391
392 /*-------------------------------------------------------------------------
393 * Function: H5HF_sect_node_new
394 *
395 * Purpose: Allocate a free space section node of a particular type
396 *
397 * Return: Success: non-negative
398 *
399 * Failure: negative
400 *
401 * Programmer: Quincey Koziol
402 * Saturday, May 13, 2006
403 *
404 *-------------------------------------------------------------------------
405 */
406 static H5HF_free_section_t *
H5HF_sect_node_new(unsigned sect_type,haddr_t sect_addr,hsize_t sect_size,H5FS_section_state_t sect_state)407 H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
408 H5FS_section_state_t sect_state)
409 {
410 H5HF_free_section_t *new_sect; /* New section */
411 H5HF_free_section_t *ret_value; /* Return value */
412
413 FUNC_ENTER_NOAPI_NOINIT
414
415 /* Check arguments. */
416 HDassert(H5F_addr_defined(sect_addr));
417
418 /* Create free list section node */
419 if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t)))
420 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
421
422 /* Set the information passed in */
423 new_sect->sect_info.addr = sect_addr;
424 new_sect->sect_info.size = sect_size;
425
426 /* Set the section's class & state */
427 new_sect->sect_info.type = sect_type;
428 new_sect->sect_info.state = sect_state;
429
430 /* Set return value */
431 ret_value = new_sect;
432
433 done:
434 FUNC_LEAVE_NOAPI(ret_value)
435 } /* H5HF_sect_node_new() */
436
437
438 /*-------------------------------------------------------------------------
439 * Function: H5HF_sect_node_free
440 *
441 * Purpose: Free a section node
442 *
443 * Return: Success: non-negative
444 *
445 * Failure: negative
446 *
447 * Programmer: Quincey Koziol
448 * Wednesday, May 17, 2006
449 *
450 *-------------------------------------------------------------------------
451 */
452 herr_t
H5HF_sect_node_free(H5HF_free_section_t * sect,H5HF_indirect_t * iblock)453 H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock)
454 {
455 herr_t ret_value = SUCCEED; /* Return value */
456
457 FUNC_ENTER_NOAPI_NOINIT
458
459 HDassert(sect);
460
461 /* Release indirect block, if there was one */
462 if(iblock)
463 if(H5HF_iblock_decr(iblock) < 0)
464 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
465
466 /* Release the section */
467 sect = H5FL_FREE(H5HF_free_section_t, sect);
468
469 done:
470 FUNC_LEAVE_NOAPI(ret_value)
471 } /* H5HF_sect_node_free() */
472
473
474 /*-------------------------------------------------------------------------
475 * Function: H5HF_sect_single_new
476 *
477 * Purpose: Create a new 'single' section and return it to the caller
478 *
479 * Return: Pointer to new section on success/NULL on failure
480 *
481 * Programmer: Quincey Koziol
482 * koziol@ncsa.uiuc.edu
483 * May 30 2006
484 *
485 *-------------------------------------------------------------------------
486 */
487 H5HF_free_section_t *
H5HF_sect_single_new(hsize_t sect_off,size_t sect_size,H5HF_indirect_t * parent,unsigned par_entry)488 H5HF_sect_single_new(hsize_t sect_off, size_t sect_size,
489 H5HF_indirect_t *parent, unsigned par_entry)
490 {
491 H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */
492 H5HF_free_section_t *ret_value; /* Return value */
493
494 FUNC_ENTER_NOAPI_NOINIT
495
496 /*
497 * Check arguments.
498 */
499 HDassert(sect_size);
500
501 /* Create free space section node */
502 if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE)))
503 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section")
504
505 /* Set the 'single' specific fields */
506 sect->u.single.parent = parent;
507 if(sect->u.single.parent) {
508 if(H5HF_iblock_incr(sect->u.single.parent) < 0)
509 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
510 } /* end if */
511 sect->u.single.par_entry = par_entry;
512
513 /* Set return value */
514 ret_value = sect;
515
516 done:
517 if(!ret_value && sect) {
518 /* Release the section */
519 sect = H5FL_FREE(H5HF_free_section_t, sect);
520 } /* end if */
521
522 FUNC_LEAVE_NOAPI(ret_value)
523 } /* end H5HF_sect_single_new() */
524
525
526 /*-------------------------------------------------------------------------
527 * Function: H5HF_sect_single_locate_parent
528 *
529 * Purpose: Locate the parent indirect block for a single section
530 *
531 * Return: Non-negative on success/Negative on failure
532 *
533 * Programmer: Quincey Koziol
534 * koziol@hdfgroup.org
535 * October 24 2006
536 *
537 *-------------------------------------------------------------------------
538 */
539 static herr_t
H5HF_sect_single_locate_parent(H5HF_hdr_t * hdr,hid_t dxpl_id,hbool_t refresh,H5HF_free_section_t * sect)540 H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t refresh,
541 H5HF_free_section_t *sect)
542 {
543 H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
544 unsigned sec_entry; /* Entry within section indirect block */
545 hbool_t did_protect; /* Whether we protected the indirect block or not */
546 herr_t ret_value = SUCCEED; /* Return value */
547
548 FUNC_ENTER_NOAPI_NOINIT
549
550 /*
551 * Check arguments.
552 */
553 HDassert(hdr);
554 HDassert(hdr->man_dtable.curr_root_rows > 0);
555 HDassert(sect);
556
557 /* Look up indirect block containing direct blocks for range */
558 if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC_READ) < 0)
559 HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
560
561 /* Increment reference count on indirect block that free section is in */
562 if(H5HF_iblock_incr(sec_iblock) < 0)
563 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
564
565 /* Check for refreshing existing parent information */
566 if(refresh) {
567 if(sect->u.single.parent) {
568 /* Release hold on previous parent indirect block */
569 if(H5HF_iblock_decr(sect->u.single.parent) < 0)
570 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
571 } /* end if */
572 } /* end if */
573
574 /* Set the information for the section */
575 sect->u.single.parent = sec_iblock;
576 sect->u.single.par_entry = sec_entry;
577
578 /* Unlock indirect block */
579 if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
580 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
581 sec_iblock = NULL;
582
583 done:
584 FUNC_LEAVE_NOAPI(ret_value)
585 } /* end H5HF_sect_single_locate_parent() */
586
587
588 /*-------------------------------------------------------------------------
589 * Function: H5HF_sect_single_revive
590 *
591 * Purpose: Update the memory information for a 'single' free section
592 *
593 * Return: Non-negative on success/Negative on failure
594 *
595 * Programmer: Quincey Koziol
596 * koziol@ncsa.uiuc.edu
597 * May 8 2006
598 *
599 *-------------------------------------------------------------------------
600 */
601 herr_t
H5HF_sect_single_revive(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)602 H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
603 H5HF_free_section_t *sect)
604 {
605 herr_t ret_value = SUCCEED; /* Return value */
606
607 FUNC_ENTER_NOAPI_NOINIT
608
609 /*
610 * Check arguments.
611 */
612 HDassert(hdr);
613 HDassert(sect);
614 HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
615
616 /* Check for root direct block */
617 if(hdr->man_dtable.curr_root_rows == 0) {
618 /* Set the information for the section */
619 HDassert(H5F_addr_defined(hdr->man_dtable.table_addr));
620 sect->u.single.parent = NULL;
621 sect->u.single.par_entry = 0;
622 } /* end if */
623 else {
624 /* Look up indirect block information for section */
625 if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0)
626 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info")
627 } /* end else */
628
629 /* Section is "live" now */
630 sect->sect_info.state = H5FS_SECT_LIVE;
631
632 done:
633 FUNC_LEAVE_NOAPI(ret_value)
634 } /* end H5HF_sect_single_revive() */
635
636
637 /*-------------------------------------------------------------------------
638 * Function: H5HF_sect_single_dblock_info
639 *
640 * Purpose: Retrieve the direct block information for a single section
641 *
642 * Return: Non-negative on success/Negative on failure
643 *
644 * Programmer: Quincey Koziol
645 * koziol@hdfgroup.org
646 * October 24 2006
647 *
648 *-------------------------------------------------------------------------
649 */
650 herr_t
H5HF_sect_single_dblock_info(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,haddr_t * dblock_addr,size_t * dblock_size)651 H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr, hid_t dxpl_id,
652 H5HF_free_section_t *sect, haddr_t *dblock_addr, size_t *dblock_size)
653 {
654 FUNC_ENTER_NOAPI_NOERR
655
656 /*
657 * Check arguments.
658 */
659 HDassert(hdr);
660 HDassert(sect);
661 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
662 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
663 HDassert(dblock_addr);
664 HDassert(dblock_size);
665
666 /* Check for root direct block */
667 if(hdr->man_dtable.curr_root_rows == 0) {
668 /* Retrieve direct block info from heap header */
669 HDassert(H5F_addr_defined(hdr->man_dtable.table_addr));
670 *dblock_addr = hdr->man_dtable.table_addr;
671 *dblock_size = hdr->man_dtable.cparam.start_block_size;
672 } /* end if */
673 else {
674 /* Retrieve direct block info from parent indirect block */
675 *dblock_addr = sect->u.single.parent->ents[sect->u.single.par_entry].addr;
676 *dblock_size = hdr->man_dtable.row_block_size[sect->u.single.par_entry / hdr->man_dtable.cparam.width];
677 } /* end else */
678
679 FUNC_LEAVE_NOAPI(SUCCEED)
680 } /* end H5HF_sect_single_dblock_info() */
681
682
683 /*-------------------------------------------------------------------------
684 * Function: H5HF_sect_single_reduce
685 *
686 * Purpose: Reduce the size of a single section (possibly freeing it)
687 * and re-add it back to the free space manager for the heap
688 * (if it hasn't been freed)
689 *
690 * Return: Non-negative on success/Negative on failure
691 *
692 * Programmer: Quincey Koziol
693 * koziol@ncsa.uiuc.edu
694 * May 31 2006
695 *
696 *-------------------------------------------------------------------------
697 */
698 herr_t
H5HF_sect_single_reduce(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,size_t amt)699 H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
700 H5HF_free_section_t *sect, size_t amt)
701 {
702 herr_t ret_value = SUCCEED; /* Return value */
703
704 FUNC_ENTER_NOAPI_NOINIT
705
706 /*
707 * Check arguments.
708 */
709 HDassert(hdr);
710 HDassert(sect);
711 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
712 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
713
714 /* Check for eliminating the section */
715 if(sect->sect_info.size == amt) {
716 /* Free single section */
717 if(H5HF_sect_single_free((H5FS_section_info_t *)sect) < 0)
718 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node")
719 } /* end if */
720 else {
721 /* Adjust information for section */
722 sect->sect_info.addr += amt;
723 sect->sect_info.size -= amt;
724
725 /* Re-insert section node into heap's free space */
726 if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0)
727 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
728 } /* end else */
729
730 done:
731 FUNC_LEAVE_NOAPI(ret_value)
732 } /* end H5HF_sect_single_reduce() */
733
734
735 /*-------------------------------------------------------------------------
736 * Function: H5HF_sect_single_full_dblock
737 *
738 * Purpose: Checks if a single section covers the entire direct block
739 * that it resides in, and converts it to a row section if so
740 *
741 * Note: Does not convert a single section to a row section if the
742 * single section is for a root direct block
743 *
744 * Return: Success: non-negative
745 * Failure: negative
746 *
747 * Programmer: Quincey Koziol
748 * Thursday, July 27, 2006
749 *
750 *-------------------------------------------------------------------------
751 */
752 static herr_t
H5HF_sect_single_full_dblock(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)753 H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id,
754 H5HF_free_section_t *sect)
755 {
756 haddr_t dblock_addr; /* Section's direct block's address */
757 size_t dblock_size; /* Section's direct block's size */
758 size_t dblock_overhead; /* Direct block's overhead */
759 herr_t ret_value = SUCCEED; /* Return value */
760
761 FUNC_ENTER_NOAPI_NOINIT
762
763 /* Check arguments. */
764 HDassert(sect);
765 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
766 HDassert(hdr);
767
768 /* Retrieve direct block address from section */
769 if(H5HF_sect_single_dblock_info(hdr, dxpl_id, sect, &dblock_addr, &dblock_size) < 0)
770 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
771
772 /* Check for section occupying entire direct block */
773 /* (and not the root direct block) */
774 dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
775 if((dblock_size - dblock_overhead) == sect->sect_info.size &&
776 hdr->man_dtable.curr_root_rows > 0) {
777 H5HF_direct_t *dblock; /* Pointer to direct block for section */
778
779 if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_WRITE)))
780 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
781 HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
782
783 /* Convert 'single' section into 'row' section */
784 if(H5HF_sect_row_from_single(hdr, sect, dblock) < 0)
785 HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section")
786
787 /* Destroy direct block */
788 if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
789 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
790 dblock = NULL;
791 } /* end if */
792
793 done:
794 FUNC_LEAVE_NOAPI(ret_value)
795 } /* H5HF_sect_single_full_dblock() */
796
797
798 /*-------------------------------------------------------------------------
799 * Function: H5HF_sect_single_add
800 *
801 * Purpose: Perform any actions on section as it is added to free space
802 * manager
803 *
804 * Return: Success: non-negative
805 * Failure: negative
806 *
807 * Programmer: Quincey Koziol
808 * Thursday, July 27, 2006
809 *
810 *-------------------------------------------------------------------------
811 */
812 static herr_t
H5HF_sect_single_add(H5FS_section_info_t * _sect,unsigned * flags,void * _udata)813 H5HF_sect_single_add(H5FS_section_info_t *_sect, unsigned *flags, void *_udata)
814 {
815 herr_t ret_value = SUCCEED; /* Return value */
816
817 FUNC_ENTER_NOAPI_NOINIT
818
819 /* Don't need to check section if we are deserializing, because it should
820 * have already been checked when it was first added
821 */
822 if(!(*flags & H5FS_ADD_DESERIALIZING)) {
823 H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */
824 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
825 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
826 hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
827
828 /* Sanity check */
829 HDassert(sect);
830 HDassert(hdr);
831
832 /* Check if single section covers entire direct block it's in */
833 /* (converts to row section possibly) */
834 if(H5HF_sect_single_full_dblock(hdr, dxpl_id, sect) < 0)
835 HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
836
837 /* Set the "returned space" flag if the single section was changed
838 * into a row section, so the "merging & shrinking" algorithm
839 * gets executed in the free space manager
840 */
841 if(sect->sect_info.type != H5HF_FSPACE_SECT_SINGLE)
842 *flags |= H5FS_ADD_RETURNED_SPACE;
843 } /* end if */
844
845 done:
846 FUNC_LEAVE_NOAPI(ret_value)
847 } /* H5HF_sect_single_add() */
848
849
850 /*-------------------------------------------------------------------------
851 * Function: H5HF_sect_single_deserialize
852 *
853 * Purpose: Deserialize a buffer into a "live" single section
854 *
855 * Return: Success: non-negative
856 * Failure: negative
857 *
858 * Programmer: Quincey Koziol
859 * Monday, May 1, 2006
860 *
861 *-------------------------------------------------------------------------
862 */
863 static H5FS_section_info_t *
H5HF_sect_single_deserialize(const H5FS_section_class_t UNUSED * cls,hid_t UNUSED dxpl_id,const uint8_t UNUSED * buf,haddr_t sect_addr,hsize_t sect_size,unsigned UNUSED * des_flags)864 H5HF_sect_single_deserialize(const H5FS_section_class_t UNUSED *cls,
865 hid_t UNUSED dxpl_id, const uint8_t UNUSED *buf, haddr_t sect_addr,
866 hsize_t sect_size, unsigned UNUSED *des_flags)
867 {
868 H5HF_free_section_t *new_sect; /* New section */
869 H5FS_section_info_t *ret_value; /* Return value */
870
871 FUNC_ENTER_NOAPI_NOINIT
872
873 /* Check arguments. */
874 HDassert(H5F_addr_defined(sect_addr));
875 HDassert(sect_size);
876
877 /* Create free list section node */
878 if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
879 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
880
881 /* Set return value */
882 ret_value = (H5FS_section_info_t *)new_sect;
883
884 done:
885 FUNC_LEAVE_NOAPI(ret_value)
886 } /* H5HF_sect_single_deserialize() */
887
888
889 /*-------------------------------------------------------------------------
890 * Function: H5HF_sect_single_can_merge
891 *
892 * Purpose: Can two sections of this type merge?
893 *
894 * Note: Second section must be "after" first section
895 *
896 * Return: Success: non-negative (TRUE/FALSE)
897 *
898 * Failure: negative
899 *
900 * Programmer: Quincey Koziol
901 * Wednesday, May 17, 2006
902 *
903 *-------------------------------------------------------------------------
904 */
905 static htri_t
H5HF_sect_single_can_merge(const H5FS_section_info_t * _sect1,const H5FS_section_info_t * _sect2,void UNUSED * _udata)906 H5HF_sect_single_can_merge(const H5FS_section_info_t *_sect1,
907 const H5FS_section_info_t *_sect2, void UNUSED *_udata)
908 {
909 const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */
910 const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */
911 htri_t ret_value = FALSE; /* Return value */
912
913 FUNC_ENTER_NOAPI_NOINIT_NOERR
914
915 /* Check arguments. */
916 HDassert(sect1);
917 HDassert(sect2);
918 HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
919 HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
920
921 /* Check if second section adjoins first section */
922 /* (This can only occur within a direct block, due to the direct block
923 * overhead at the beginning of a block, so no need to check if sections
924 * are actually within the same direct block)
925 */
926 if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
927 HGOTO_DONE(TRUE)
928
929 done:
930 FUNC_LEAVE_NOAPI(ret_value)
931 } /* H5HF_sect_single_can_merge() */
932
933
934 /*-------------------------------------------------------------------------
935 * Function: H5HF_sect_single_merge
936 *
937 * Purpose: Merge two sections of this type
938 *
939 * Note: Second section always merges into first node
940 *
941 * Return: Success: non-negative
942 *
943 * Failure: negative
944 *
945 * Programmer: Quincey Koziol
946 * Wednesday, May 17, 2006
947 *
948 *-------------------------------------------------------------------------
949 */
950 static herr_t
H5HF_sect_single_merge(H5FS_section_info_t * _sect1,H5FS_section_info_t * _sect2,void * _udata)951 H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
952 void *_udata)
953 {
954 H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
955 H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
956 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
957 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
958 hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
959 herr_t ret_value = SUCCEED; /* Return value */
960
961 FUNC_ENTER_NOAPI_NOINIT
962
963 /* Check arguments. */
964 HDassert(sect1);
965 HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
966 HDassert(sect2);
967 HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
968 HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr));
969
970 /* Add second section's size to first section */
971 sect1->sect_info.size += sect2->sect_info.size;
972
973 /* Get rid of second section */
974 if(H5HF_sect_single_free((H5FS_section_info_t *)sect2) < 0)
975 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
976
977 /* Check to see if we should revive first section */
978 if(sect1->sect_info.state != H5FS_SECT_LIVE)
979 if(H5HF_sect_single_revive(hdr, dxpl_id, sect1) < 0)
980 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
981
982 /* Check if single section covers entire direct block it's in */
983 /* (converts to row section possibly) */
984 if(H5HF_sect_single_full_dblock(hdr, dxpl_id, sect1) < 0)
985 HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
986
987 done:
988 FUNC_LEAVE_NOAPI(ret_value)
989 } /* H5HF_sect_single_merge() */
990
991
992 /*-------------------------------------------------------------------------
993 * Function: H5HF_sect_single_can_shrink
994 *
995 * Purpose: Can this section shrink the container?
996 *
997 * Note: This isn't actually shrinking the heap (since that's already
998 * been done) as much as it's cleaning up _after_ the heap
999 * shrink.
1000 *
1001 * Return: Success: non-negative (TRUE/FALSE)
1002 *
1003 * Failure: negative
1004 *
1005 * Programmer: Quincey Koziol
1006 * Monday, June 5, 2006
1007 *
1008 *-------------------------------------------------------------------------
1009 */
1010 static htri_t
H5HF_sect_single_can_shrink(const H5FS_section_info_t * _sect,void * _udata)1011 H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
1012 {
1013 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
1014 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
1015 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
1016 htri_t ret_value = FALSE; /* Return value */
1017
1018 FUNC_ENTER_NOAPI_NOINIT_NOERR
1019
1020 /* Check arguments. */
1021 HDassert(sect);
1022
1023 /* Check for section occupying entire root direct block */
1024 /* (We shouldn't ever have a single section that occupies an entire
1025 * direct block, unless it's in the root direct block (because it
1026 * would have been converted into a row section, if there was an
1027 * indirect block that covered it)
1028 */
1029 if(hdr->man_dtable.curr_root_rows == 0) {
1030 size_t dblock_size; /* Section's direct block's size */
1031 size_t dblock_overhead; /* Direct block's overhead */
1032
1033 dblock_size = hdr->man_dtable.cparam.start_block_size;
1034 dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
1035 if((dblock_size - dblock_overhead) == sect->sect_info.size)
1036 HGOTO_DONE(TRUE)
1037 } /* end if */
1038 else {
1039 /* We shouldn't have a situation where the 'next block' iterator
1040 * is moved before a direct block that still has objects within it.
1041 */
1042 HDassert(hdr->man_iter_off > sect->sect_info.addr);
1043 HGOTO_DONE(FALSE)
1044 } /* end else */
1045
1046 done:
1047 FUNC_LEAVE_NOAPI(ret_value)
1048 } /* H5HF_sect_single_can_shrink() */
1049
1050
1051 /*-------------------------------------------------------------------------
1052 * Function: H5HF_sect_single_shrink
1053 *
1054 * Purpose: Shrink container with section
1055 *
1056 * Return: Success: non-negative
1057 *
1058 * Failure: negative
1059 *
1060 * Programmer: Quincey Koziol
1061 * Monday, July 17, 2006
1062 *
1063 *-------------------------------------------------------------------------
1064 */
1065 static herr_t
H5HF_sect_single_shrink(H5FS_section_info_t ** _sect,void UNUSED * _udata)1066 H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata)
1067 {
1068 H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
1069 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
1070 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
1071 hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
1072 H5HF_direct_t *dblock; /* Pointer to direct block for section */
1073 haddr_t dblock_addr; /* Section's direct block's address */
1074 size_t dblock_size; /* Section's direct block's size */
1075 herr_t ret_value = SUCCEED; /* Return value */
1076
1077 FUNC_ENTER_NOAPI_NOINIT
1078
1079 /* Check arguments. */
1080 HDassert(sect);
1081 HDassert(*sect);
1082 HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
1083
1084 /* Check to see if we should revive section */
1085 if((*sect)->sect_info.state != H5FS_SECT_LIVE)
1086 if(H5HF_sect_single_revive(hdr, dxpl_id, (*sect)) < 0)
1087 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
1088
1089 /* Retrieve direct block address from section */
1090 if(H5HF_sect_single_dblock_info(hdr, dxpl_id, (*sect), &dblock_addr, &dblock_size) < 0)
1091 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
1092
1093 /* Protect the direct block for the section */
1094 /* (should be a root direct block) */
1095 HDassert(dblock_addr == hdr->man_dtable.table_addr);
1096 if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
1097 dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC_WRITE)))
1098 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
1099 HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
1100
1101 /* Destroy direct block */
1102 if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
1103 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
1104 dblock = NULL;
1105
1106 /* Get rid of section */
1107 if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0)
1108 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
1109
1110 /* Indicate that the section has been released */
1111 *sect = NULL;
1112
1113 done:
1114 FUNC_LEAVE_NOAPI(ret_value)
1115 } /* H5HF_sect_single_shrink() */
1116
1117
1118 /*-------------------------------------------------------------------------
1119 * Function: H5HF_sect_single_free
1120 *
1121 * Purpose: Free a 'single' section node
1122 *
1123 * Return: Success: non-negative
1124 *
1125 * Failure: negative
1126 *
1127 * Programmer: Quincey Koziol
1128 * Wednesday, May 17, 2006
1129 *
1130 *-------------------------------------------------------------------------
1131 */
1132 herr_t
H5HF_sect_single_free(H5FS_section_info_t * _sect)1133 H5HF_sect_single_free(H5FS_section_info_t *_sect)
1134 {
1135 H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
1136 H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */
1137 herr_t ret_value = SUCCEED; /* Return value */
1138
1139 FUNC_ENTER_NOAPI_NOINIT
1140
1141 /* Check arguments. */
1142 HDassert(sect);
1143
1144 /* Check for live reference to an indirect block */
1145 if(sect->sect_info.state == H5FS_SECT_LIVE) {
1146 /* Get parent indirect block, if there was one */
1147 if(sect->u.single.parent)
1148 parent = sect->u.single.parent;
1149 } /* end if */
1150
1151 /* Release the section */
1152 if(H5HF_sect_node_free(sect, parent) < 0)
1153 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
1154
1155 done:
1156 FUNC_LEAVE_NOAPI(ret_value)
1157 } /* H5HF_sect_single_free() */
1158
1159
1160 /*-------------------------------------------------------------------------
1161 * Function: H5HF_sect_single_valid
1162 *
1163 * Purpose: Check the validity of a section
1164 *
1165 * Return: Success: non-negative
1166 * Failure: negative
1167 *
1168 * Programmer: Quincey Koziol
1169 * Friday, July 21, 2006
1170 *
1171 *-------------------------------------------------------------------------
1172 */
1173 static herr_t
H5HF_sect_single_valid(const H5FS_section_class_t UNUSED * cls,const H5FS_section_info_t * _sect)1174 H5HF_sect_single_valid(const H5FS_section_class_t UNUSED *cls, const H5FS_section_info_t *_sect)
1175 {
1176 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
1177
1178 FUNC_ENTER_NOAPI_NOINIT_NOERR
1179
1180 /* Check arguments. */
1181 HDassert(sect);
1182
1183 if(sect->sect_info.state == H5FS_SECT_LIVE) {
1184 /* Check if this section is not in a direct block that is the root direct block */
1185 /* (not enough information to check on a single section in a root direct block) */
1186 if(sect->u.single.parent != NULL) {
1187 H5HF_indirect_t *iblock; /* Indirect block that section's direct block resides in */
1188 haddr_t dblock_addr; /* Direct block address */
1189 size_t dblock_size; /* Direct block size */
1190 size_t dblock_overhead; /* Direct block's overhead */
1191 unsigned dblock_status = 0; /* Direct block's status in the metadata cache */
1192 herr_t status; /* Generic status value */
1193
1194 /* Sanity check settings for section's direct block's parent */
1195 iblock = sect->u.single.parent;
1196 HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr));
1197
1198 /* Retrieve direct block address from section */
1199 /* (Casting away const OK - QAK) */
1200 status = H5HF_sect_single_dblock_info(iblock->hdr, H5AC_dxpl_id, (H5HF_free_section_t *)sect, &dblock_addr, &dblock_size);
1201 HDassert(status >= 0);
1202 HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr, dblock_addr));
1203 HDassert(dblock_size > 0);
1204
1205 /* Check if the section is actually within the heap */
1206 HDassert(sect->sect_info.addr < iblock->hdr->man_iter_off);
1207
1208 /* Check that the direct block has been merged correctly */
1209 dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(iblock->hdr);
1210 HDassert((sect->sect_info.size + dblock_overhead) < dblock_size);
1211
1212 /* Check the direct block's status in the metadata cache */
1213 status = H5AC_get_entry_status(iblock->hdr->f, dblock_addr, &dblock_status);
1214 HDassert(status >= 0);
1215
1216 /* If the direct block for the section isn't already protected,
1217 * protect it here in order to check single section's sanity
1218 * against it.
1219 */
1220 if(!(dblock_status & H5AC_ES__IS_PROTECTED)) {
1221 H5HF_direct_t *dblock; /* Direct block for section */
1222
1223 /* Protect the direct block for the section */
1224 dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC_READ);
1225 HDassert(dblock);
1226
1227 /* Sanity check settings for section */
1228 HDassert(dblock_size == dblock->size);
1229 HDassert(dblock->size > sect->sect_info.size);
1230 HDassert(H5F_addr_lt(dblock->block_off, sect->sect_info.addr));
1231 HDassert(H5F_addr_ge((dblock->block_off + dblock->size),
1232 (sect->sect_info.addr + sect->sect_info.size)));
1233
1234 /* Release direct block */
1235 status = H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET);
1236 HDassert(status >= 0);
1237 } /* end if */
1238 } /* end if */
1239 } /* end if */
1240
1241 FUNC_LEAVE_NOAPI(SUCCEED)
1242 } /* H5HF_sect_single_valid() */
1243
1244
1245 /*-------------------------------------------------------------------------
1246 * Function: H5HF_sect_row_create
1247 *
1248 * Purpose: Create a new 'row' section
1249 *
1250 * Return: Success: pointer to new section
1251 *
1252 * Failure: NULL
1253 *
1254 * Programmer: Quincey Koziol
1255 * Thursday, July 6, 2006
1256 *
1257 *-------------------------------------------------------------------------
1258 */
1259 static H5HF_free_section_t *
H5HF_sect_row_create(haddr_t sect_off,hsize_t sect_size,hbool_t is_first,unsigned row,unsigned col,unsigned nentries,H5HF_free_section_t * under_sect)1260 H5HF_sect_row_create(haddr_t sect_off, hsize_t sect_size, hbool_t is_first,
1261 unsigned row, unsigned col, unsigned nentries, H5HF_free_section_t *under_sect)
1262 {
1263 H5HF_free_section_t *sect = NULL; /* 'Row' section created */
1264 H5HF_free_section_t *ret_value; /* Return value */
1265
1266 FUNC_ENTER_NOAPI_NOINIT
1267
1268 /* Check arguments. */
1269 HDassert(sect_size);
1270 HDassert(nentries);
1271 HDassert(under_sect);
1272
1273 /* Create 'row' free space section node */
1274 /* ("inherits" underlying indirect section's state) */
1275 if(NULL == (sect = H5HF_sect_node_new((unsigned)(is_first ? H5HF_FSPACE_SECT_FIRST_ROW : H5HF_FSPACE_SECT_NORMAL_ROW), sect_off, sect_size, under_sect->sect_info.state)))
1276 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for row section")
1277
1278 /* Set the 'row' specific fields */
1279 sect->u.row.under = under_sect;
1280 sect->u.row.row = row;
1281 sect->u.row.col = col;
1282 sect->u.row.num_entries = nentries;
1283 sect->u.row.checked_out = FALSE;
1284
1285 /* Set return value */
1286 ret_value = sect;
1287
1288 done:
1289 FUNC_LEAVE_NOAPI(ret_value)
1290 } /* H5HF_sect_row_create() */
1291
1292
1293 /*-------------------------------------------------------------------------
1294 * Function: H5HF_sect_row_from_single
1295 *
1296 * Purpose: Convert a 'single' section into a 'row' section
1297 *
1298 * Return: Non-negative on success/Negative on failure
1299 *
1300 * Programmer: Quincey Koziol
1301 * koziol@ncsa.uiuc.edu
1302 * July 6 2006
1303 *
1304 *-------------------------------------------------------------------------
1305 */
1306 static herr_t
H5HF_sect_row_from_single(H5HF_hdr_t * hdr,H5HF_free_section_t * sect,H5HF_direct_t * dblock)1307 H5HF_sect_row_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
1308 H5HF_direct_t *dblock)
1309 {
1310 herr_t ret_value = SUCCEED; /* Return value */
1311
1312 FUNC_ENTER_NOAPI_NOINIT
1313
1314 /*
1315 * Check arguments.
1316 */
1317 HDassert(hdr);
1318 HDassert(sect);
1319 HDassert(dblock);
1320
1321 /* Convert 'single' section information to 'row' section info */
1322 sect->sect_info.addr = dblock->block_off;
1323 sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
1324 sect->u.row.row = dblock->par_entry / hdr->man_dtable.cparam.width;
1325 sect->u.row.col = dblock->par_entry % hdr->man_dtable.cparam.width;
1326 sect->u.row.num_entries = 1;
1327 sect->u.row.checked_out = FALSE;
1328
1329 /* Create indirect section that underlies the row section */
1330 if(NULL == (sect->u.row.under = H5HF_sect_indirect_for_row(hdr, dblock->parent, sect)))
1331 HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "serializing row section not supported yet")
1332
1333 /* Release single section's hold on underlying indirect block */
1334 if(H5HF_iblock_decr(dblock->parent) < 0)
1335 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
1336
1337 done:
1338 FUNC_LEAVE_NOAPI(ret_value)
1339 } /* end H5HF_sect_row_from_single() */
1340
1341
1342 /*-------------------------------------------------------------------------
1343 * Function: H5HF_sect_row_revive
1344 *
1345 * Purpose: Update the memory information for a 'row' free section
1346 *
1347 * Return: Non-negative on success/Negative on failure
1348 *
1349 * Programmer: Quincey Koziol
1350 * koziol@ncsa.uiuc.edu
1351 * July 6 2006
1352 *
1353 *-------------------------------------------------------------------------
1354 */
1355 herr_t
H5HF_sect_row_revive(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)1356 H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
1357 {
1358 herr_t ret_value = SUCCEED; /* Return value */
1359
1360 FUNC_ENTER_NOAPI_NOINIT
1361
1362 /*
1363 * Check arguments.
1364 */
1365 HDassert(hdr);
1366 HDassert(sect);
1367 HDassert(sect->u.row.under);
1368 HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
1369
1370 /* Pass along "revive" request to underlying indirect section */
1371 /* (which will mark this section as "live") */
1372 if(H5HF_sect_indirect_revive_row(hdr, dxpl_id, sect->u.row.under) < 0)
1373 HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
1374
1375 done:
1376 FUNC_LEAVE_NOAPI(ret_value)
1377 } /* end H5HF_sect_row_revive() */
1378
1379
1380 /*-------------------------------------------------------------------------
1381 * Function: H5HF_sect_row_reduce
1382 *
1383 * Purpose: Reduce the size of a row section (possibly freeing it)
1384 * and re-add it back to the free space manager for the heap
1385 * (if it hasn't been freed)
1386 *
1387 * Return: Non-negative on success/Negative on failure
1388 *
1389 * Programmer: Quincey Koziol
1390 * koziol@ncsa.uiuc.edu
1391 * July 6 2006
1392 *
1393 *-------------------------------------------------------------------------
1394 */
1395 herr_t
H5HF_sect_row_reduce(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,unsigned * entry_p)1396 H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect,
1397 unsigned *entry_p)
1398 {
1399 hbool_t alloc_from_start; /* Whether to allocate from the end of the row */
1400 herr_t ret_value = SUCCEED; /* Return value */
1401
1402 FUNC_ENTER_NOAPI_NOINIT
1403
1404 /*
1405 * Check arguments.
1406 */
1407 HDassert(hdr);
1408 HDassert(sect);
1409 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
1410 sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
1411 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
1412 HDassert(entry_p);
1413
1414 /* Mark the row as checked out from the free space manager */
1415 HDassert(sect->u.row.checked_out == FALSE);
1416 sect->u.row.checked_out = TRUE;
1417
1418 /* Forward row section to indirect routines, to handle reducing underlying indirect section */
1419 alloc_from_start = FALSE;
1420 if(H5HF_sect_indirect_reduce_row(hdr, dxpl_id, sect, &alloc_from_start) < 0)
1421 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce underlying section")
1422
1423 /* Determine entry allocated */
1424 *entry_p = (sect->u.row.row * hdr->man_dtable.cparam.width) + sect->u.row.col;
1425 if(!alloc_from_start)
1426 *entry_p += (sect->u.row.num_entries - 1);
1427
1428 /* Check for eliminating the section */
1429 if(sect->u.row.num_entries == 1) {
1430 /* Free row section */
1431 if(H5HF_sect_row_free((H5FS_section_info_t *)sect) < 0)
1432 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section node")
1433 } /* end if */
1434 else {
1435 /* Check whether to allocate from the beginning or end of the row */
1436 if(alloc_from_start) {
1437 /* Adjust section start */
1438 sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.row.row];
1439 sect->u.row.col++;
1440 } /* end else */
1441
1442 /* Adjust span of blocks covered */
1443 sect->u.row.num_entries--;
1444
1445 /* Check the row back in */
1446 sect->u.row.checked_out = FALSE;
1447
1448 /* Add 'row' section back to free space list */
1449 if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0)
1450 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager")
1451 } /* end else */
1452
1453 done:
1454 FUNC_LEAVE_NOAPI(ret_value)
1455 } /* end H5HF_sect_row_reduce() */
1456
1457
1458 /*-------------------------------------------------------------------------
1459 * Function: H5HF_sect_row_first
1460 *
1461 * Purpose: Make row a "first row"
1462 *
1463 * Return: Non-negative on success/Negative on failure
1464 *
1465 * Programmer: Quincey Koziol
1466 * koziol@ncsa.uiuc.edu
1467 * July 10 2006
1468 *
1469 *-------------------------------------------------------------------------
1470 */
1471 static herr_t
H5HF_sect_row_first(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)1472 H5HF_sect_row_first(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
1473 {
1474 herr_t ret_value = SUCCEED; /* Return value */
1475
1476 FUNC_ENTER_NOAPI_NOINIT
1477
1478 /* Sanity check */
1479 HDassert(hdr);
1480 HDassert(sect);
1481 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
1482
1483 /* If the row is already checked out from the free space manager, just
1484 * change it's class directly and the free space manager will adjust when
1485 * it is checked back in.
1486 */
1487 if(sect->u.row.checked_out)
1488 sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
1489 else {
1490 /* Change row section to be the "first row" */
1491 if(H5HF_space_sect_change_class(hdr, dxpl_id, sect, H5HF_FSPACE_SECT_FIRST_ROW) < 0)
1492 HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
1493 } /* end else */
1494
1495 done:
1496 FUNC_LEAVE_NOAPI(ret_value)
1497 } /* end H5HF_sect_row_first() */
1498
1499
1500 /*-------------------------------------------------------------------------
1501 * Function: H5HF_sect_row_get_iblock
1502 *
1503 * Purpose: Retrieve the indirect block for a row section
1504 *
1505 * Return: Pointer to indirect block on success/NULL on failure
1506 *
1507 * Programmer: Quincey Koziol
1508 * koziol@ncsa.uiuc.edu
1509 * July 9 2006
1510 *
1511 *-------------------------------------------------------------------------
1512 */
1513 H5HF_indirect_t *
H5HF_sect_row_get_iblock(H5HF_free_section_t * sect)1514 H5HF_sect_row_get_iblock(H5HF_free_section_t *sect)
1515 {
1516 H5HF_indirect_t *ret_value; /* Return value */
1517
1518 FUNC_ENTER_NOAPI_NOINIT_NOERR
1519
1520 /*
1521 * Check arguments.
1522 */
1523 HDassert(sect);
1524 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
1525 sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
1526 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
1527
1528 ret_value = H5HF_sect_indirect_get_iblock(sect->u.row.under);
1529
1530 FUNC_LEAVE_NOAPI(ret_value)
1531 } /* end H5HF_sect_row_get_iblock() */
1532
1533
1534 /*-------------------------------------------------------------------------
1535 * Function: H5HF_sect_row_init_cls
1536 *
1537 * Purpose: Initialize the "row" section class structure
1538 *
1539 * Note: Since 'row' sections are proxies for 'indirect' sections, this
1540 * routine forwards call to 'indirect' class initialization
1541 *
1542 * Return: Success: non-negative
1543 *
1544 * Failure: negative
1545 *
1546 * Programmer: Quincey Koziol
1547 * Monday, July 6, 2006
1548 *
1549 *-------------------------------------------------------------------------
1550 */
1551 static herr_t
H5HF_sect_row_init_cls(H5FS_section_class_t * cls,void * _udata)1552 H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *_udata)
1553 {
1554 H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */
1555 herr_t ret_value = SUCCEED; /* Return value */
1556
1557 FUNC_ENTER_NOAPI_NOINIT
1558
1559 /* Check arguments. */
1560 HDassert(cls);
1561 HDassert(hdr);
1562
1563 /* Call common class initialization */
1564 if(H5HF_sect_init_cls(cls, hdr) < 0)
1565 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
1566
1567 /* First row sections actually are proxies for indirection sections on disk */
1568 if(cls->type == H5HF_FSPACE_SECT_FIRST_ROW)
1569 cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
1570 else
1571 cls->serial_size = 0;
1572
1573 done:
1574 FUNC_LEAVE_NOAPI(ret_value)
1575 } /* H5HF_sect_row_init_cls() */
1576
1577
1578 /*-------------------------------------------------------------------------
1579 * Function: H5HF_sect_row_term_cls
1580 *
1581 * Purpose: Terminate the "row" section class structure
1582 *
1583 * Note: Since 'row' sections are proxies for 'indirect' sections, this
1584 * routine forwards call to 'indirect' class termination
1585 *
1586 * Return: Success: non-negative
1587 *
1588 * Failure: negative
1589 *
1590 * Programmer: Quincey Koziol
1591 * Monday, July 6, 2006
1592 *
1593 *-------------------------------------------------------------------------
1594 */
1595 static herr_t
H5HF_sect_row_term_cls(H5FS_section_class_t * cls)1596 H5HF_sect_row_term_cls(H5FS_section_class_t *cls)
1597 {
1598 herr_t ret_value = SUCCEED; /* Return value */
1599
1600 FUNC_ENTER_NOAPI_NOINIT
1601
1602 /* Check arguments. */
1603 HDassert(cls);
1604
1605 /* Call common class termination */
1606 if(H5HF_sect_term_cls(cls) < 0)
1607 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
1608
1609 done:
1610 FUNC_LEAVE_NOAPI(ret_value)
1611 } /* H5HF_sect_row_term_cls() */
1612
1613
1614 /*-------------------------------------------------------------------------
1615 * Function: H5HF_sect_row_serialize
1616 *
1617 * Purpose: Serialize a "live" row section into a buffer
1618 *
1619 * Return: Success: non-negative
1620 *
1621 * Failure: negative
1622 *
1623 * Programmer: Quincey Koziol
1624 * Thursday, July 6, 2006
1625 *
1626 *-------------------------------------------------------------------------
1627 */
1628 static herr_t
H5HF_sect_row_serialize(const H5FS_section_class_t * cls,const H5FS_section_info_t * _sect,uint8_t * buf)1629 H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
1630 const H5FS_section_info_t *_sect, uint8_t *buf)
1631 {
1632 H5HF_hdr_t *hdr; /* Fractal heap header */
1633 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
1634 herr_t ret_value = SUCCEED; /* Return value */
1635
1636 FUNC_ENTER_NOAPI_NOINIT
1637
1638 /* Check arguments. */
1639 HDassert(cls);
1640 HDassert(buf);
1641 HDassert(sect);
1642 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1643 HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr);
1644
1645 /* Forward to indirect routine to serialize underlying section */
1646 hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
1647 if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0)
1648 HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section")
1649
1650 done:
1651 FUNC_LEAVE_NOAPI(ret_value)
1652 } /* H5HF_sect_row_serialize() */
1653
1654
1655 /*-------------------------------------------------------------------------
1656 * Function: H5HF_sect_row_deserialize
1657 *
1658 * Purpose: Deserialize a buffer into a "live" row section
1659 *
1660 * Note: Actually this routine just forwards to the 'indirect'
1661 * deserialize routine, which creates the row section.
1662 *
1663 * Return: Success: non-negative
1664 *
1665 * Failure: negative
1666 *
1667 * Programmer: Quincey Koziol
1668 * Saturday, July 15, 2006
1669 *
1670 *-------------------------------------------------------------------------
1671 */
1672 static H5FS_section_info_t *
H5HF_sect_row_deserialize(const H5FS_section_class_t * cls,hid_t dxpl_id,const uint8_t * buf,haddr_t sect_addr,hsize_t sect_size,unsigned * des_flags)1673 H5HF_sect_row_deserialize(const H5FS_section_class_t *cls, hid_t dxpl_id,
1674 const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
1675 unsigned *des_flags)
1676 {
1677 H5HF_hdr_t *hdr; /* Fractal heap header */
1678 H5FS_section_info_t *ret_value; /* Return value */
1679
1680 FUNC_ENTER_NOAPI_NOINIT
1681
1682 /* Check arguments. */
1683 HDassert(cls);
1684 HDassert(buf);
1685 HDassert(H5F_addr_defined(sect_addr));
1686 HDassert(sect_size);
1687
1688 /* Forward to indirect routine to deserialize underlying section */
1689 hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
1690 if(NULL == (ret_value = H5HF_sect_indirect_deserialize(hdr, dxpl_id, buf,
1691 sect_addr, sect_size, des_flags)))
1692 HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section")
1693
1694 done:
1695 FUNC_LEAVE_NOAPI(ret_value)
1696 } /* H5HF_sect_row_deserialize() */
1697
1698
1699 /*-------------------------------------------------------------------------
1700 * Function: H5HF_sect_row_can_merge
1701 *
1702 * Purpose: Can two sections of this type merge?
1703 *
1704 * Note: Second section must be "after" first section
1705 *
1706 * Return: Success: non-negative (TRUE/FALSE)
1707 *
1708 * Failure: negative
1709 *
1710 * Programmer: Quincey Koziol
1711 * Thursday, July 6, 2006
1712 *
1713 *-------------------------------------------------------------------------
1714 */
1715 static htri_t
H5HF_sect_row_can_merge(const H5FS_section_info_t * _sect1,const H5FS_section_info_t * _sect2,void UNUSED * _udata)1716 H5HF_sect_row_can_merge(const H5FS_section_info_t *_sect1,
1717 const H5FS_section_info_t *_sect2, void UNUSED *_udata)
1718 {
1719 const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */
1720 const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */
1721 H5HF_free_section_t *top_indir_sect1, *top_indir_sect2; /* Top indirect section for each row */
1722 htri_t ret_value = FALSE; /* Return value */
1723
1724 FUNC_ENTER_NOAPI_NOINIT_NOERR
1725
1726 /* Check arguments. */
1727 HDassert(sect1);
1728 HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1729 HDassert(sect2);
1730 HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
1731 HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
1732
1733 /* Get the top indirect section underlying each row */
1734 top_indir_sect1 = H5HF_sect_indirect_top(sect1->u.row.under);
1735 HDassert(top_indir_sect1);
1736 top_indir_sect2 = H5HF_sect_indirect_top(sect2->u.row.under);
1737 HDassert(top_indir_sect2);
1738
1739 /* Check if second section shares the same underlying indirect block as
1740 * the first section, but doesn't already have same underlying indirect
1741 * section.
1742 */
1743 if(top_indir_sect1 != top_indir_sect2) {
1744 if(H5HF_sect_indirect_iblock_off(top_indir_sect1) == H5HF_sect_indirect_iblock_off(top_indir_sect2)) {
1745 /* Check if second section adjoins first section */
1746 if(H5F_addr_eq((top_indir_sect1->sect_info.addr + top_indir_sect1->u.indirect.span_size), top_indir_sect2->sect_info.addr))
1747 HGOTO_DONE(TRUE)
1748 } /* end if */
1749 } /* end if */
1750
1751 done:
1752 FUNC_LEAVE_NOAPI(ret_value)
1753 } /* H5HF_sect_row_can_merge() */
1754
1755
1756 /*-------------------------------------------------------------------------
1757 * Function: H5HF_sect_row_merge
1758 *
1759 * Purpose: Merge two sections of this type
1760 *
1761 * Note: Second section always merges into first node
1762 *
1763 * Return: Success: non-negative
1764 *
1765 * Failure: negative
1766 *
1767 * Programmer: Quincey Koziol
1768 * Thursday, July 6, 2006
1769 *
1770 *-------------------------------------------------------------------------
1771 */
1772 static herr_t
H5HF_sect_row_merge(H5FS_section_info_t * _sect1,H5FS_section_info_t * _sect2,void * _udata)1773 H5HF_sect_row_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
1774 void *_udata)
1775 {
1776 H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
1777 H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
1778 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
1779 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
1780 hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
1781 herr_t ret_value = SUCCEED; /* Return value */
1782
1783 FUNC_ENTER_NOAPI_NOINIT
1784
1785 /* Check arguments. */
1786 HDassert(sect1);
1787 HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1788 HDassert(sect2);
1789 HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1790
1791 /* Check if second section is past end of "next block" iterator */
1792 if(sect2->sect_info.addr >= hdr->man_iter_off) {
1793 H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
1794
1795 /* Get the top indirect section underlying second row section */
1796 top_indir_sect = H5HF_sect_indirect_top(sect2->u.row.under);
1797
1798 /* Shrink away underlying indirect section */
1799 if(H5HF_sect_indirect_shrink(hdr, dxpl_id, top_indir_sect) < 0)
1800 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
1801 } /* end if */
1802 else {
1803 /* Check to see if we should revive first section */
1804 if(sect1->sect_info.state != H5FS_SECT_LIVE)
1805 if(H5HF_sect_row_revive(hdr, dxpl_id, sect1) < 0)
1806 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
1807
1808 /* Check to see if we should revive second section */
1809 if(sect2->sect_info.state != H5FS_SECT_LIVE)
1810 if(H5HF_sect_row_revive(hdr, dxpl_id, sect2) < 0)
1811 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
1812
1813 /* Merge rows' underlying indirect sections together */
1814 if(H5HF_sect_indirect_merge_row(hdr, dxpl_id, sect1, sect2) < 0)
1815 HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't merge underlying indirect sections")
1816 } /* end else */
1817
1818 done:
1819 FUNC_LEAVE_NOAPI(ret_value)
1820 } /* H5HF_sect_row_merge() */
1821
1822
1823 /*-------------------------------------------------------------------------
1824 * Function: H5HF_sect_row_can_shrink
1825 *
1826 * Purpose: Can this section shrink the container?
1827 *
1828 * Note: This isn't actually shrinking the heap (since that's already
1829 * been done) as much as it's cleaning up _after_ the heap
1830 * shrink.
1831 *
1832 * Return: Success: non-negative (TRUE/FALSE)
1833 *
1834 * Failure: negative
1835 *
1836 * Programmer: Quincey Koziol
1837 * Thursday, July 6, 2006
1838 *
1839 *-------------------------------------------------------------------------
1840 */
1841 static htri_t
H5HF_sect_row_can_shrink(const H5FS_section_info_t * _sect,void UNUSED * _udata)1842 H5HF_sect_row_can_shrink(const H5FS_section_info_t *_sect, void UNUSED *_udata)
1843 {
1844 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
1845 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
1846 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
1847 htri_t ret_value = FALSE; /* Return value */
1848
1849 FUNC_ENTER_NOAPI_NOINIT_NOERR
1850
1851 /* Check arguments. */
1852 HDassert(sect);
1853 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1854
1855 /* Check if section is past end of "next block" iterator */
1856 if(sect->sect_info.addr >= hdr->man_iter_off)
1857 HGOTO_DONE(TRUE)
1858
1859 done:
1860 FUNC_LEAVE_NOAPI(ret_value)
1861 } /* H5HF_sect_row_can_shrink() */
1862
1863
1864 /*-------------------------------------------------------------------------
1865 * Function: H5HF_sect_row_shrink
1866 *
1867 * Purpose: Shrink container with section
1868 *
1869 * Return: Success: non-negative
1870 *
1871 * Failure: negative
1872 *
1873 * Programmer: Quincey Koziol
1874 * Thursday, July 6, 2006
1875 *
1876 *-------------------------------------------------------------------------
1877 */
1878 static herr_t
H5HF_sect_row_shrink(H5FS_section_info_t ** _sect,void * _udata)1879 H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void *_udata)
1880 {
1881 H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
1882 H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
1883 H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
1884 H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
1885 hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
1886 herr_t ret_value = SUCCEED; /* Return value */
1887
1888 FUNC_ENTER_NOAPI_NOINIT
1889
1890 /* Check arguments. */
1891 HDassert(sect);
1892 HDassert(*sect);
1893 HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
1894
1895 /* Get the top indirect section underlying each row */
1896 top_indir_sect = H5HF_sect_indirect_top((*sect)->u.row.under);
1897
1898 /* Shrink away underlying indirect section */
1899 if(H5HF_sect_indirect_shrink(hdr, dxpl_id, top_indir_sect) < 0)
1900 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
1901
1902 /* Indicate that the section has been released */
1903 *sect = NULL;
1904
1905 done:
1906 FUNC_LEAVE_NOAPI(ret_value)
1907 } /* H5HF_sect_row_shrink() */
1908
1909
1910 /*-------------------------------------------------------------------------
1911 * Function: H5HF_sect_row_free_real
1912 *
1913 * Purpose: Free a 'row' section node
1914 *
1915 * Return: Success: non-negative
1916 *
1917 * Failure: negative
1918 *
1919 * Programmer: Quincey Koziol
1920 * Thursday, July 6, 2006
1921 *
1922 *-------------------------------------------------------------------------
1923 */
1924 static herr_t
H5HF_sect_row_free_real(H5HF_free_section_t * sect)1925 H5HF_sect_row_free_real(H5HF_free_section_t *sect)
1926 {
1927 herr_t ret_value = SUCCEED; /* Return value */
1928
1929 FUNC_ENTER_NOAPI_NOINIT
1930
1931 HDassert(sect);
1932
1933 /* Release the section */
1934 if(H5HF_sect_node_free(sect, NULL) < 0)
1935 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
1936
1937 done:
1938 FUNC_LEAVE_NOAPI(ret_value)
1939 } /* H5HF_sect_row_free_real() */
1940
1941
1942 /*-------------------------------------------------------------------------
1943 * Function: H5HF_sect_row_free
1944 *
1945 * Purpose: Free a 'row' section node
1946 *
1947 * Return: Success: non-negative
1948 *
1949 * Failure: negative
1950 *
1951 * Programmer: Quincey Koziol
1952 * Thursday, July 6, 2006
1953 *
1954 *-------------------------------------------------------------------------
1955 */
1956 static herr_t
H5HF_sect_row_free(H5FS_section_info_t * _sect)1957 H5HF_sect_row_free(H5FS_section_info_t *_sect)
1958 {
1959 H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
1960 herr_t ret_value = SUCCEED; /* Return value */
1961
1962 FUNC_ENTER_NOAPI_NOINIT
1963
1964 HDassert(sect);
1965 HDassert(sect->u.row.under);
1966
1967 /* Decrement the ref. count on the row section's underlying indirect section */
1968 if(H5HF_sect_indirect_decr(sect->u.row.under) < 0)
1969 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node")
1970
1971 /* Release the section */
1972 if(H5HF_sect_row_free_real(sect) < 0)
1973 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
1974
1975 done:
1976 FUNC_LEAVE_NOAPI(ret_value)
1977 } /* H5HF_sect_row_free() */
1978
1979
1980 /*-------------------------------------------------------------------------
1981 * Function: H5HF_sect_row_valid
1982 *
1983 * Purpose: Check the validity of a section
1984 *
1985 * Return: Success: non-negative
1986 * Failure: negative
1987 *
1988 * Programmer: Quincey Koziol
1989 * Friday, July 21, 2006
1990 *
1991 *-------------------------------------------------------------------------
1992 */
1993 static herr_t
H5HF_sect_row_valid(const H5FS_section_class_t * cls,const H5FS_section_info_t * _sect)1994 H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect)
1995 {
1996 H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
1997 const H5HF_hdr_t *hdr; /* Fractal heap header */
1998 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
1999 const H5HF_free_section_t *indir_sect; /* Pointer to underlying indirect section */
2000 unsigned indir_idx; /* Index of row in underlying indirect section's row array */
2001
2002 FUNC_ENTER_NOAPI_NOINIT_NOERR
2003
2004 /* Basic sanity check */
2005 HDassert(cls);
2006 HDassert(sect);
2007
2008 /* Retrieve class private information */
2009 cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
2010 hdr = cls_prvt->hdr;
2011
2012 /* Sanity checking on the row */
2013 HDassert(sect->u.row.under);
2014 HDassert(sect->u.row.num_entries);
2015 HDassert(sect->u.row.checked_out == FALSE);
2016 indir_sect = sect->u.row.under;
2017 indir_idx = sect->u.row.row - indir_sect->u.indirect.row;
2018 HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect);
2019
2020 /* Check if the section is actually within the heap */
2021 HDassert(sect->sect_info.addr < hdr->man_iter_off);
2022
2023 /* Different checking for different kinds of rows */
2024 if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
2025 H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
2026
2027 /* Some extra sanity checks on the row */
2028 HDassert(sect->u.row.row == indir_sect->u.indirect.row);
2029
2030 /* Get the top indirect section underlying row */
2031 top_indir_sect = H5HF_sect_indirect_top(sect->u.row.under);
2032
2033 /* Check that the row's underlying indirect section is valid */
2034 H5HF_sect_indirect_valid(hdr, top_indir_sect);
2035 } /* end if */
2036
2037 FUNC_LEAVE_NOAPI(SUCCEED)
2038 } /* H5HF_sect_row_valid() */
2039
2040
2041 /*-------------------------------------------------------------------------
2042 * Function: H5HF_sect_row_debug
2043 *
2044 * Purpose: Dump debugging information about an row free space section
2045 *
2046 * Return: Success: non-negative
2047 * Failure: negative
2048 *
2049 * Programmer: Quincey Koziol
2050 * Tuesday, July 25, 2006
2051 *
2052 *-------------------------------------------------------------------------
2053 */
2054 static herr_t
H5HF_sect_row_debug(const H5FS_section_info_t * _sect,FILE * stream,int indent,int fwidth)2055 H5HF_sect_row_debug(const H5FS_section_info_t *_sect,
2056 FILE *stream, int indent, int fwidth)
2057 {
2058 const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */
2059
2060 FUNC_ENTER_NOAPI_NOINIT_NOERR
2061
2062 /* Check arguments. */
2063 HDassert(sect);
2064
2065 /* Print indirect section information */
2066 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
2067 "Row:",
2068 sect->u.row.row);
2069 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
2070 "Column:",
2071 sect->u.row.col);
2072 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
2073 "Number of entries:",
2074 sect->u.row.num_entries);
2075
2076 /* If this is a first row section display information about underlying indirect section */
2077 if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
2078 /* Print indirect section header */
2079 HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth,
2080 "Underlying indirect section:");
2081
2082 H5HF_sect_indirect_debug(sect->u.row.under, stream, indent + 3, MAX(0, fwidth - 3));
2083 } /* end if */
2084
2085 FUNC_LEAVE_NOAPI(SUCCEED)
2086 } /* H5HF_sect_row_debug() */
2087
2088
2089 /*-------------------------------------------------------------------------
2090 * Function: H5HF_sect_indirect_iblock_off
2091 *
2092 * Purpose: Get the offset of the indirect block for the section
2093 *
2094 * Return: Offset of indirect block in "heap space" (can't fail)
2095 *
2096 * Programmer: Quincey Koziol
2097 * koziol@ncsa.uiuc.edu
2098 * July 6 2006
2099 *
2100 *-------------------------------------------------------------------------
2101 */
2102 static hsize_t
H5HF_sect_indirect_iblock_off(const H5HF_free_section_t * sect)2103 H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect)
2104 {
2105 hsize_t ret_value; /* Return value */
2106
2107 FUNC_ENTER_NOAPI_NOINIT_NOERR
2108
2109 /*
2110 * Check arguments.
2111 */
2112 HDassert(sect);
2113
2114 ret_value = sect->sect_info.state == H5FS_SECT_LIVE ? sect->u.indirect.u.iblock->block_off : sect->u.indirect.u.iblock_off;
2115
2116 FUNC_LEAVE_NOAPI(ret_value)
2117 } /* end H5HF_sect_indirect_iblock_off() */
2118
2119
2120 /*-------------------------------------------------------------------------
2121 * Function: H5HF_sect_indirect_top
2122 *
2123 * Purpose: Get the "top" indirect section
2124 *
2125 * Return: Pointer to the top indirect section (can't fail)
2126 *
2127 * Programmer: Quincey Koziol
2128 * koziol@ncsa.uiuc.edu
2129 * July 6 2006
2130 *
2131 *-------------------------------------------------------------------------
2132 */
2133 static H5HF_free_section_t *
H5HF_sect_indirect_top(H5HF_free_section_t * sect)2134 H5HF_sect_indirect_top(H5HF_free_section_t *sect)
2135 {
2136 H5HF_free_section_t *ret_value; /* Return value */
2137
2138 FUNC_ENTER_NOAPI_NOINIT_NOERR
2139
2140 /*
2141 * Check arguments.
2142 */
2143 HDassert(sect);
2144
2145 if(sect->u.indirect.parent)
2146 ret_value = H5HF_sect_indirect_top(sect->u.indirect.parent);
2147 else
2148 ret_value = sect;
2149
2150 FUNC_LEAVE_NOAPI(ret_value)
2151 } /* end H5HF_sect_indirect_top() */
2152
2153
2154 /*-------------------------------------------------------------------------
2155 * Function: H5HF_sect_indirect_init_cls
2156 *
2157 * Purpose: Initialize the "indirect" class structure
2158 *
2159 * Return: Success: non-negative
2160 *
2161 * Failure: negative
2162 *
2163 * Programmer: Quincey Koziol
2164 * Monday, July 3, 2006
2165 *
2166 *-------------------------------------------------------------------------
2167 */
2168 static herr_t
H5HF_sect_indirect_init_cls(H5FS_section_class_t * cls,void * _udata)2169 H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata)
2170 {
2171 H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */
2172 herr_t ret_value = SUCCEED; /* Return value */
2173
2174 FUNC_ENTER_NOAPI_NOINIT
2175
2176 /* Check arguments. */
2177 HDassert(cls);
2178 HDassert(hdr);
2179
2180 /* Call to common class initialization */
2181 if(H5HF_sect_init_cls(cls, hdr) < 0)
2182 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
2183
2184 /* Set the size of all serialized objects of this class of sections */
2185 cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
2186
2187 done:
2188 FUNC_LEAVE_NOAPI(ret_value)
2189 } /* H5HF_sect_indirect_init_cls() */
2190
2191
2192 /*-------------------------------------------------------------------------
2193 * Function: H5HF_sect_indirect_term_cls
2194 *
2195 * Purpose: Terminate the "indirect" class structure
2196 *
2197 * Return: Success: non-negative
2198 *
2199 * Failure: negative
2200 *
2201 * Programmer: Quincey Koziol
2202 * Monday, July 3, 2006
2203 *
2204 *-------------------------------------------------------------------------
2205 */
2206 static herr_t
H5HF_sect_indirect_term_cls(H5FS_section_class_t * cls)2207 H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls)
2208 {
2209 herr_t ret_value = SUCCEED; /* Return value */
2210
2211 FUNC_ENTER_NOAPI_NOINIT
2212
2213 /* Check arguments. */
2214 HDassert(cls);
2215
2216 /* Call common class termination */
2217 if(H5HF_sect_term_cls(cls) < 0)
2218 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
2219
2220 done:
2221 FUNC_LEAVE_NOAPI(ret_value)
2222 } /* H5HF_sect_indirect_term_cls() */
2223
2224
2225 /*-------------------------------------------------------------------------
2226 * Function: H5HF_sect_indirect_new
2227 *
2228 * Purpose: Create a new 'indirect' section for other routines to finish
2229 * initializing.
2230 *
2231 * Return: Non-negative on success/Negative on failure
2232 *
2233 * Programmer: Quincey Koziol
2234 * koziol@ncsa.uiuc.edu
2235 * July 6 2006
2236 *
2237 *-------------------------------------------------------------------------
2238 */
2239 static H5HF_free_section_t *
H5HF_sect_indirect_new(H5HF_hdr_t * hdr,haddr_t sect_off,hsize_t sect_size,H5HF_indirect_t * iblock,hsize_t iblock_off,unsigned row,unsigned col,unsigned nentries)2240 H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size,
2241 H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col,
2242 unsigned nentries)
2243 {
2244 H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
2245 H5HF_free_section_t *ret_value; /* Return value */
2246
2247 FUNC_ENTER_NOAPI_NOINIT
2248
2249 /*
2250 * Check arguments.
2251 */
2252 HDassert(hdr);
2253 HDassert(nentries);
2254
2255 /* Create free space section node */
2256 if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off,
2257 sect_size, (iblock ? H5FS_SECT_LIVE : H5FS_SECT_SERIALIZED))))
2258 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for indirect section")
2259
2260 /* Set the 'indirect' specific fields */
2261 if(iblock) {
2262 sect->u.indirect.u.iblock = iblock;
2263 sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
2264 sect->u.indirect.u.iblock->max_rows;
2265 if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0)
2266 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
2267 } /* end if */
2268 else {
2269 sect->u.indirect.u.iblock_off = iblock_off;
2270 sect->u.indirect.iblock_entries = 0;
2271 } /* end else */
2272 sect->u.indirect.row = row;
2273 sect->u.indirect.col = col;
2274 sect->u.indirect.num_entries = nentries;
2275
2276 /* Compute span size of indirect section */
2277 sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
2278 row, col, nentries);
2279 HDassert(sect->u.indirect.span_size > 0);
2280
2281 /* This indirect section doesn't (currently) have a parent */
2282 sect->u.indirect.parent = NULL;
2283 sect->u.indirect.par_entry = 0;
2284
2285 /* Set return value */
2286 ret_value = sect;
2287
2288 done:
2289 if(!ret_value && sect) {
2290 /* Release the section */
2291 sect = H5FL_FREE(H5HF_free_section_t, sect);
2292 } /* end if */
2293
2294 FUNC_LEAVE_NOAPI(ret_value)
2295 } /* end H5HF_sect_indirect_new() */
2296
2297
2298 /*-------------------------------------------------------------------------
2299 * Function: H5HF_sect_indirect_for_row
2300 *
2301 * Purpose: Create the underlying indirect section for a new row section
2302 *
2303 * Return: Non-negative on success/Negative on failure
2304 *
2305 * Programmer: Quincey Koziol
2306 * koziol@ncsa.uiuc.edu
2307 * July 6 2006
2308 *
2309 *-------------------------------------------------------------------------
2310 */
2311 static H5HF_free_section_t *
H5HF_sect_indirect_for_row(H5HF_hdr_t * hdr,H5HF_indirect_t * iblock,H5HF_free_section_t * row_sect)2312 H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
2313 H5HF_free_section_t *row_sect)
2314 {
2315 H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
2316 H5HF_free_section_t *ret_value; /* Return value */
2317
2318 FUNC_ENTER_NOAPI_NOINIT
2319
2320 /*
2321 * Check arguments.
2322 */
2323 HDassert(hdr);
2324 HDassert(iblock);
2325 HDassert(row_sect);
2326 HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
2327
2328 /* Create free space section node */
2329 if(NULL == (sect = H5HF_sect_indirect_new(hdr, row_sect->sect_info.addr,
2330 row_sect->sect_info.size, iblock, iblock->block_off,
2331 row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries)))
2332 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
2333
2334 /* Set # of direct rows covered */
2335 sect->u.indirect.dir_nrows = 1;
2336
2337 /* Allocate space for the derived row sections */
2338 if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
2339 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array")
2340
2341 /* Atatch the new row section to indirect section */
2342 sect->u.indirect.dir_rows[0] = row_sect;
2343 sect->u.indirect.rc = 1;
2344
2345 /* No indirect rows in current section */
2346 sect->u.indirect.indir_nents = 0;
2347 sect->u.indirect.indir_ents = NULL;
2348
2349 /* Set return value */
2350 ret_value = sect;
2351
2352 done:
2353 if(!ret_value && sect)
2354 if(H5HF_sect_indirect_free(sect) < 0)
2355 HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't free indirect section node")
2356
2357 FUNC_LEAVE_NOAPI(ret_value)
2358 } /* end H5HF_sect_indirect_for_row() */
2359
2360
2361 /*-------------------------------------------------------------------------
2362 * Function: H5HF_sect_indirect_init_rows
2363 *
2364 * Purpose: Initialize the derived row sections for a newly created
2365 * indirect section
2366 *
2367 * Return: Non-negative on success/Negative on failure
2368 *
2369 * Programmer: Quincey Koziol
2370 * koziol@ncsa.uiuc.edu
2371 * July 6 2006
2372 *
2373 *-------------------------------------------------------------------------
2374 */
2375 static herr_t
H5HF_sect_indirect_init_rows(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,hbool_t first_child,H5HF_free_section_t ** first_row_sect,unsigned space_flags,unsigned start_row,unsigned start_col,unsigned end_row,unsigned end_col)2376 H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
2377 H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect,
2378 unsigned space_flags, unsigned start_row, unsigned start_col,
2379 unsigned end_row, unsigned end_col)
2380 {
2381 hsize_t curr_off; /* Offset of new section in "heap space" */
2382 size_t dblock_overhead; /* Direct block's overhead */
2383 unsigned row_entries; /* # of entries in row */
2384 unsigned row_col; /* Column within current row */
2385 unsigned curr_entry; /* Current entry within indirect section */
2386 unsigned curr_indir_entry; /* Current indirect entry within indirect section */
2387 unsigned curr_row; /* Current row within indirect section */
2388 unsigned dir_nrows; /* # of direct rows in indirect section */
2389 unsigned u; /* Local index variable */
2390 herr_t ret_value = SUCCEED; /* Return value */
2391
2392 FUNC_ENTER_NOAPI_NOINIT
2393
2394 /*
2395 * Check arguments.
2396 */
2397 HDassert(sect);
2398 HDassert(sect->u.indirect.span_size > 0);
2399
2400 /* Reset reference count for indirect section */
2401 /* (Also reset the direct & indirect row pointers */
2402 sect->u.indirect.rc = 0;
2403 sect->u.indirect.dir_rows = NULL;
2404 sect->u.indirect.indir_ents = NULL;
2405
2406 /* Set up direct block information, if necessary */
2407 if(start_row < hdr->man_dtable.max_direct_rows) {
2408 unsigned max_direct_row; /* Max. direct row covered */
2409
2410 /* Compute max. direct row covered by indirect section */
2411 max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1));
2412
2413 /* Compute # of direct rows covered */
2414 dir_nrows = (max_direct_row - start_row) + 1;
2415
2416 /* Don't set the of direct rows in section yet, so sanity
2417 * checking works (enabled in free section manager, with H5FS_DEBUG
2418 * macro) correctly.
2419 */
2420 sect->u.indirect.dir_nrows = 0;
2421
2422 /* Allocate space for the derived row sections */
2423 if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows)))
2424 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
2425 } /* end if */
2426 else {
2427 /* No rows of direct blocks covered, reset direct row information */
2428 dir_nrows = 0;
2429 sect->u.indirect.dir_nrows = 0;
2430 } /* end else */
2431
2432 /* Set up indirect block information, if necessary */
2433 if(end_row >= hdr->man_dtable.max_direct_rows) {
2434 unsigned indirect_start_row; /* Row to start indirect entries on */
2435 unsigned indirect_start_col; /* Column to start indirect entries on */
2436 unsigned indirect_start_entry; /* Index of starting indirect entry */
2437 unsigned indirect_end_entry; /* Index of ending indirect entry */
2438
2439 /* Compute starting indirect entry */
2440 if(start_row < hdr->man_dtable.max_direct_rows) {
2441 indirect_start_row = hdr->man_dtable.max_direct_rows;
2442 indirect_start_col = 0;
2443 } /* end if */
2444 else {
2445 indirect_start_row = start_row;
2446 indirect_start_col = start_col;
2447 } /* end else */
2448 indirect_start_entry = (indirect_start_row * hdr->man_dtable.cparam.width)
2449 + indirect_start_col;
2450
2451 /* Compute ending indirect entry */
2452 indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) + end_col;
2453
2454 /* Compute # of indirect entries covered */
2455 sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1;
2456
2457 /* Allocate space for the child indirect sections */
2458 if(NULL == (sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
2459 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
2460 } /* end if */
2461 else {
2462 /* No indirect block entries covered, reset indirect row information */
2463 sect->u.indirect.indir_nents = 0;
2464 } /* end else */
2465
2466 /* Set up initial row information */
2467 if(start_row == end_row)
2468 row_entries = (end_col - start_col) + 1;
2469 else
2470 row_entries = hdr->man_dtable.cparam.width - start_col;
2471 row_col = start_col;
2472
2473 /* Loop over creating the sections covered by this indirect section */
2474 curr_off = sect->sect_info.addr;
2475 curr_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
2476 curr_row = 0;
2477 curr_indir_entry = 0;
2478 dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
2479 for(u = start_row; u <= end_row; u++, curr_row++) {
2480 if(u < hdr->man_dtable.max_direct_rows) {
2481 H5HF_free_section_t *row_sect = NULL; /* 'Row' free space section to add */
2482
2483 /* Create 'row' free space section node */
2484 if(NULL == (row_sect = H5HF_sect_row_create(curr_off,
2485 (hdr->man_dtable.row_block_size[u] - dblock_overhead), first_child, u, row_col,
2486 row_entries, sect)))
2487 HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "creation failed for child row section")
2488
2489 /* Add new row section to array for indirect section */
2490 sect->u.indirect.dir_rows[curr_row] = row_sect;
2491
2492 /* Check to see if we should grab the first row section instead of adding it immediately */
2493 if(first_row_sect)
2494 *first_row_sect = row_sect;
2495 else {
2496 /* Add new row section to free space manager for the heap */
2497 if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0)
2498 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
2499 } /* end else */
2500
2501 /* Increment reference count for underlying indirect section */
2502 sect->u.indirect.rc++;
2503
2504 /* Advance the offset to the next section */
2505 curr_off += row_entries * hdr->man_dtable.row_block_size[u];
2506
2507 /* Advance the current entry to the next row*/
2508 curr_entry += row_entries;
2509
2510 /* Reset the 'first child' parameters */
2511 first_child = FALSE;
2512 first_row_sect = NULL;
2513 } /* end if */
2514 else {
2515 H5HF_indirect_t *child_iblock; /* Child indirect block */
2516 H5HF_free_section_t *child_sect; /* Child 'indirect' section to add */
2517 unsigned child_nrows; /* Number of child rows in indirect blocks for this row */
2518 unsigned child_nentries; /* Number of child entries in indirect blocks for this row */
2519 unsigned v; /* Local index variable */
2520
2521 /* Compute info about row's indirect blocks for child section */
2522 child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[u]);
2523 child_nentries = child_nrows * hdr->man_dtable.cparam.width;
2524
2525 /* Add an indirect section for each indirect block in the row */
2526 for(v = 0; v < row_entries; v++) {
2527 hbool_t did_protect; /* Whether we protected the indirect block or not */
2528
2529 /* Try to get the child section's indirect block, if it's available */
2530 if(sect->sect_info.state == H5FS_SECT_LIVE) {
2531 haddr_t child_iblock_addr; /* Child indirect block's address on disk */
2532
2533 /* Get the address of the child indirect block */
2534 if(H5HF_man_iblock_entry_addr(sect->u.indirect.u.iblock, curr_entry, &child_iblock_addr) < 0)
2535 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve child indirect block's address")
2536
2537 /* If the child indirect block's address is defined, protect it */
2538 if(H5F_addr_defined(child_iblock_addr)) {
2539 if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC_WRITE, &did_protect)))
2540 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
2541 } /* end if */
2542 else
2543 child_iblock = NULL;
2544 } /* end if */
2545 else
2546 child_iblock = NULL;
2547
2548 /* Create free space section node */
2549 if(NULL == (child_sect = H5HF_sect_indirect_new(hdr, curr_off, (hsize_t)0,
2550 child_iblock, curr_off, 0, 0, child_nentries)))
2551 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
2552
2553 /* Initialize rows for new indirect section */
2554 if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, child_sect,
2555 first_child, first_row_sect, space_flags, 0, 0,
2556 (child_nrows - 1), (hdr->man_dtable.cparam.width - 1)) < 0)
2557 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
2558
2559 /* If we have a valid child indirect block, release it now */
2560 /* (will be pinned, if rows reference it) */
2561 if(child_iblock)
2562 if(H5HF_man_iblock_unprotect(child_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
2563 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
2564
2565 /* Attach child section to this section */
2566 child_sect->u.indirect.parent = sect;
2567 child_sect->u.indirect.par_entry = curr_entry;
2568 sect->u.indirect.indir_ents[curr_indir_entry] = child_sect;
2569 sect->u.indirect.rc++;
2570
2571 /* Advance the offset for the next section */
2572 curr_off += hdr->man_dtable.row_block_size[u];
2573
2574 /* Advance to the next entry */
2575 curr_entry++;
2576 curr_indir_entry++;
2577
2578 /* Reset the 'first child' parameters */
2579 first_child = FALSE;
2580 first_row_sect = NULL;
2581 } /* end for */
2582 } /* end else */
2583
2584 /* Compute the # of entries for the next row */
2585 if(u < (end_row - 1))
2586 row_entries = hdr->man_dtable.cparam.width;
2587 else
2588 row_entries = end_col + 1;
2589
2590 /* Reset column for all other rows */
2591 row_col = 0;
2592 } /* end for */
2593
2594 /* Set the final # of direct rows in section */
2595 sect->u.indirect.dir_nrows = dir_nrows;
2596
2597 /* Make certain we've tracked the section's dependents correctly */
2598 HDassert(sect->u.indirect.rc ==
2599 (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
2600
2601 done:
2602 if(ret_value < 0) {
2603 if(sect->u.indirect.indir_ents)
2604 H5MM_xfree(sect->u.indirect.indir_ents);
2605 if(sect->u.indirect.dir_rows)
2606 H5MM_xfree(sect->u.indirect.dir_rows);
2607 } /* end if */
2608
2609 FUNC_LEAVE_NOAPI(ret_value)
2610 } /* end H5HF_sect_indirect_init_rows() */
2611
2612
2613 /*-------------------------------------------------------------------------
2614 * Function: H5HF_sect_indirect_add
2615 *
2616 * Purpose: Add a new 'indirect' section to the free space manager for this
2617 * heap
2618 *
2619 * Return: Non-negative on success/Negative on failure
2620 *
2621 * Programmer: Quincey Koziol
2622 * koziol@ncsa.uiuc.edu
2623 * July 3 2006
2624 *
2625 *-------------------------------------------------------------------------
2626 */
2627 herr_t
H5HF_sect_indirect_add(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_indirect_t * iblock,unsigned start_entry,unsigned nentries)2628 H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
2629 H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries)
2630 {
2631 H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
2632 H5HF_free_section_t *first_row_sect = NULL; /* First row section in new indirect section */
2633 hsize_t sect_off; /* Offset of section in heap space */
2634 unsigned start_row; /* Start row in indirect block */
2635 unsigned start_col; /* Start column in indirect block */
2636 unsigned end_entry; /* End entry in indirect block */
2637 unsigned end_row; /* End row in indirect block */
2638 unsigned end_col; /* End column in indirect block */
2639 unsigned u; /* Local index variable */
2640 herr_t ret_value = SUCCEED; /* Return value */
2641
2642 FUNC_ENTER_NOAPI_NOINIT
2643
2644 /*
2645 * Check arguments.
2646 */
2647 HDassert(hdr);
2648 HDassert(iblock);
2649 HDassert(nentries);
2650
2651 /* Compute starting column & row */
2652 start_row = start_entry / hdr->man_dtable.cparam.width;
2653 start_col = start_entry % hdr->man_dtable.cparam.width;
2654
2655 /* Compute end column & row */
2656 end_entry = (start_entry + nentries) - 1;
2657 end_row = end_entry / hdr->man_dtable.cparam.width;
2658 end_col = end_entry % hdr->man_dtable.cparam.width;
2659
2660 /* Initialize information for rows skipped over */
2661 sect_off = iblock->block_off;
2662 for(u = 0; u < start_row; u++)
2663 sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
2664 sect_off += hdr->man_dtable.row_block_size[start_row] * start_col;
2665
2666 /* Create free space section node */
2667 if(NULL == (sect = H5HF_sect_indirect_new(hdr, sect_off, (hsize_t)0, iblock,
2668 iblock->block_off, start_row, start_col, nentries)))
2669 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
2670
2671 /* Initialize rows for new indirect section */
2672 if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, &first_row_sect,
2673 H5FS_ADD_SKIP_VALID, start_row, start_col, end_row, end_col) < 0)
2674 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
2675 HDassert(first_row_sect);
2676
2677 /* Now that underlying indirect section is consistent, add first row
2678 * section to free space manager for the heap
2679 */
2680 if(H5HF_space_add(hdr, dxpl_id, first_row_sect, H5FS_ADD_RETURNED_SPACE) < 0)
2681 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
2682
2683 done:
2684 if(ret_value < 0 && sect)
2685 if(H5HF_sect_indirect_free(sect) < 0)
2686 HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
2687
2688 FUNC_LEAVE_NOAPI(ret_value)
2689 } /* end H5HF_sect_indirect_add() */
2690
2691
2692 /*-------------------------------------------------------------------------
2693 * Function: H5HF_sect_indirect_decr
2694 *
2695 * Purpose: Decrement ref. count on indirect section
2696 *
2697 * Return: Non-negative on success/Negative on failure
2698 *
2699 * Programmer: Quincey Koziol
2700 * koziol@ncsa.uiuc.edu
2701 * July 6 2006
2702 *
2703 *-------------------------------------------------------------------------
2704 */
2705 static herr_t
H5HF_sect_indirect_decr(H5HF_free_section_t * sect)2706 H5HF_sect_indirect_decr(H5HF_free_section_t *sect)
2707 {
2708 herr_t ret_value = SUCCEED; /* Return value */
2709
2710 FUNC_ENTER_NOAPI_NOINIT
2711
2712 /*
2713 * Check arguments.
2714 */
2715 HDassert(sect);
2716 HDassert(sect->u.indirect.rc);
2717
2718 /* Decrement ref. count for indirect section */
2719 sect->u.indirect.rc--;
2720
2721 /* If the indirect section's ref. count drops to zero, free the section */
2722 if(sect->u.indirect.rc == 0) {
2723 H5HF_free_section_t *par_sect; /* Parent indirect section */
2724
2725 /* Preserve pointer to parent indirect section when freeing this section */
2726 par_sect = sect->u.indirect.parent;
2727
2728 /* Free indirect section */
2729 if(H5HF_sect_indirect_free(sect) < 0)
2730 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
2731
2732 /* Decrement ref. count on indirect section's parent */
2733 if(par_sect)
2734 if(H5HF_sect_indirect_decr(par_sect) < 0)
2735 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
2736 } /* end if */
2737
2738 done:
2739 FUNC_LEAVE_NOAPI(ret_value)
2740 } /* end H5HF_sect_indirect_decr() */
2741
2742
2743 /*-------------------------------------------------------------------------
2744 * Function: H5HF_sect_indirect_revive_row
2745 *
2746 * Purpose: Update the memory information for a 'indirect' free section
2747 *
2748 * Return: Non-negative on success/Negative on failure
2749 *
2750 * Programmer: Quincey Koziol
2751 * koziol@ncsa.uiuc.edu
2752 * July 3 2006
2753 *
2754 *-------------------------------------------------------------------------
2755 */
2756 static herr_t
H5HF_sect_indirect_revive_row(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)2757 H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
2758 {
2759 H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
2760 hbool_t did_protect; /* Whether we protected the indirect block or not */
2761 unsigned u; /* Local index variable */
2762 herr_t ret_value = SUCCEED; /* Return value */
2763
2764 FUNC_ENTER_NOAPI_NOINIT
2765
2766 /*
2767 * Check arguments.
2768 */
2769 HDassert(hdr);
2770 HDassert(sect);
2771 HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
2772
2773 /* Look up indirect block containing indirect blocks for section */
2774 if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC_READ) < 0)
2775 HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
2776
2777 /* Increment reference count on indirect block that free section is in */
2778 if(H5HF_iblock_incr(sec_iblock) < 0)
2779 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
2780
2781 /* Set the pointer to the section's indirect block */
2782 sect->u.indirect.u.iblock = sec_iblock;
2783
2784 /* Set the number of entries in the indirect block */
2785 sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
2786 sect->u.indirect.u.iblock->max_rows;
2787
2788 /* Unlock indirect block */
2789 if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
2790 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
2791 sec_iblock = NULL;
2792
2793 /* Section is "live" now */
2794 sect->sect_info.state = H5FS_SECT_LIVE;
2795
2796 /* Loop over derived row sections and mark them all as 'live' now */
2797 for(u = 0; u < sect->u.indirect.dir_nrows; u++)
2798 sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
2799
2800 /* Revive parent indirect section, if there is one */
2801 if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
2802 if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
2803 HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
2804
2805 done:
2806 FUNC_LEAVE_NOAPI(ret_value)
2807 } /* end H5HF_sect_indirect_revive_row() */
2808
2809
2810 /*-------------------------------------------------------------------------
2811 * Function: H5HF_sect_indirect_revive
2812 *
2813 * Purpose: Update the memory information for a 'indirect' free section
2814 *
2815 * Return: Non-negative on success/Negative on failure
2816 *
2817 * Programmer: Quincey Koziol
2818 * koziol@ncsa.uiuc.edu
2819 * July 10 2006
2820 *
2821 *-------------------------------------------------------------------------
2822 */
2823 static herr_t
H5HF_sect_indirect_revive(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,H5HF_indirect_t * sect_iblock)2824 H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
2825 H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock)
2826 {
2827 unsigned u; /* Local index variable */
2828 herr_t ret_value = SUCCEED; /* Return value */
2829
2830 FUNC_ENTER_NOAPI_NOINIT
2831
2832 /*
2833 * Check arguments.
2834 */
2835 HDassert(hdr);
2836 HDassert(sect);
2837 HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
2838 HDassert(sect_iblock);
2839
2840 /* Increment reference count on indirect block that free section is in */
2841 if(H5HF_iblock_incr(sect_iblock) < 0)
2842 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
2843
2844 /* Set the pointer to the section's indirect block */
2845 sect->u.indirect.u.iblock = sect_iblock;
2846
2847 /* Set the number of entries in the indirect block */
2848 sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
2849 sect->u.indirect.u.iblock->max_rows;
2850
2851 /* Section is "live" now */
2852 sect->sect_info.state = H5FS_SECT_LIVE;
2853
2854 /* Loop over derived row sections and mark them all as 'live' now */
2855 for(u = 0; u < sect->u.indirect.dir_nrows; u++)
2856 sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
2857
2858 /* Revive parent indirect section, if there is one */
2859 if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
2860 if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
2861 HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
2862
2863 done:
2864 FUNC_LEAVE_NOAPI(ret_value)
2865 } /* end H5HF_sect_indirect_revive() */
2866
2867
2868 /*-------------------------------------------------------------------------
2869 * Function: H5HF_sect_indirect_reduce_row
2870 *
2871 * Purpose: Remove a block from an indirect section (possibly freeing it)
2872 * and re-add it back to the free space manager for the heap
2873 * (if it hasn't been freed)
2874 *
2875 * Return: Non-negative on success/Negative on failure
2876 *
2877 * Programmer: Quincey Koziol
2878 * koziol@ncsa.uiuc.edu
2879 * July 10 2006
2880 *
2881 *-------------------------------------------------------------------------
2882 */
2883 static herr_t
H5HF_sect_indirect_reduce_row(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * row_sect,hbool_t * alloc_from_start)2884 H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *row_sect,
2885 hbool_t *alloc_from_start)
2886 {
2887 H5HF_free_section_t *sect; /* Indirect section underlying row section */
2888 unsigned row_start_entry; /* Entry for first block covered in row section */
2889 unsigned row_end_entry; /* Entry for last block covered in row section */
2890 unsigned row_entry; /* Entry to allocate in row section */
2891 unsigned start_entry; /* Entry for first block covered */
2892 unsigned start_row; /* Start row in indirect block */
2893 unsigned start_col; /* Start column in indirect block */
2894 unsigned end_entry; /* Entry for last block covered */
2895 unsigned end_row; /* End row in indirect block */
2896 H5HF_free_section_t *peer_sect = NULL; /* Peer indirect section */
2897 herr_t ret_value = SUCCEED; /* Return value */
2898
2899 FUNC_ENTER_NOAPI_NOINIT
2900
2901 /*
2902 * Check arguments.
2903 */
2904 HDassert(hdr);
2905 HDassert(row_sect);
2906
2907 /* Compute starting & ending information for row section */
2908 row_start_entry = (row_sect->u.row.row * hdr->man_dtable.cparam.width) + row_sect->u.row.col;
2909 row_end_entry = (row_start_entry + row_sect->u.row.num_entries) - 1;
2910
2911 /* Compute starting & ending information for indirect section */
2912 sect = row_sect->u.row.under;
2913 start_row = sect->u.indirect.row;
2914 start_col = sect->u.indirect.col;
2915 start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
2916 end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
2917 end_row = end_entry / hdr->man_dtable.cparam.width;
2918
2919 /* Additional sanity check */
2920 HDassert(sect->u.indirect.span_size > 0);
2921 HDassert(sect->u.indirect.iblock_entries > 0);
2922 HDassert(sect->u.indirect.dir_nrows > 0);
2923 HDassert(sect->u.indirect.dir_rows);
2924 HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect);
2925
2926 /* Check if we should allocate from end of indirect section */
2927 if(row_end_entry == end_entry && start_row != end_row) {
2928 *alloc_from_start = FALSE;
2929 row_entry = row_end_entry;
2930 } /* end if */
2931 else {
2932 *alloc_from_start = TRUE;
2933 row_entry = row_start_entry;
2934 } /* end else */
2935
2936 /* Check if we have a parent section to be detached from */
2937 if(sect->u.indirect.parent) {
2938 hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
2939
2940 /* Check if this section is the first section */
2941 is_first = H5HF_sect_indirect_is_first(sect);
2942
2943 /* Remove this indirect section from parent indirect section */
2944 if(H5HF_sect_indirect_reduce(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
2945 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
2946 sect->u.indirect.parent = NULL;
2947 sect->u.indirect.par_entry = 0;
2948
2949 /* If we weren't the first section, set "first row" for this indirect section */
2950 if(!is_first)
2951 if(H5HF_sect_indirect_first(hdr, dxpl_id, sect) < 0)
2952 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
2953 } /* end if */
2954
2955 /* Adjust indirect section's span size */
2956 sect->u.indirect.span_size -= row_sect->sect_info.size;
2957
2958 /* Check how to adjust section for allocated entry */
2959 if(sect->u.indirect.num_entries > 1) {
2960 if(row_entry == start_entry) {
2961 /* Adjust section start */
2962 sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
2963
2964 /* Adjust block coordinates of span */
2965 sect->u.indirect.col++;
2966 if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
2967 HDassert(row_sect->u.row.num_entries == 1);
2968
2969 /* Adjust section's span information */
2970 sect->u.indirect.row++;
2971 sect->u.indirect.col = 0;
2972
2973 /* Adjust direct row information */
2974 sect->u.indirect.dir_nrows--;
2975
2976 /* Adjust direct row sections for indirect section */
2977 if(sect->u.indirect.dir_nrows > 0) {
2978 HDassert(sect->u.indirect.dir_rows);
2979 HDmemmove(§->u.indirect.dir_rows[0],
2980 §->u.indirect.dir_rows[1],
2981 sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *));
2982 HDassert(sect->u.indirect.dir_rows[0]);
2983
2984 /* Make new "first row" in indirect section */
2985 if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
2986 if(H5HF_sect_row_first(hdr, dxpl_id, sect->u.indirect.dir_rows[0]) < 0)
2987 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
2988 } /* end if */
2989 else {
2990 /* Sanity check */
2991 HDassert(sect->u.indirect.indir_nents > 0);
2992 HDassert(sect->u.indirect.indir_ents);
2993
2994 /* Eliminate direct rows for this section */
2995 sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
2996
2997 /* Make new "first row" in indirect section */
2998 if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
2999 if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
3000 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
3001 } /* end else */
3002 } /* end if */
3003
3004 /* Adjust number of entries covered */
3005 sect->u.indirect.num_entries--;
3006 } /* end if */
3007 else if(row_entry == end_entry) {
3008 unsigned new_end_row; /* New end row for entries */
3009
3010 /* Sanity check */
3011 HDassert(sect->u.indirect.indir_nents == 0);
3012 HDassert(sect->u.indirect.indir_ents == NULL);
3013
3014 /* Adjust number of entries covered */
3015 sect->u.indirect.num_entries--;
3016
3017 /* Check for eliminating a direct row */
3018 new_end_row = ((start_entry + sect->u.indirect.num_entries) - 1) / hdr->man_dtable.cparam.width;
3019 HDassert(new_end_row <= end_row);
3020 if(new_end_row < end_row) {
3021 HDassert(new_end_row == (end_row - 1));
3022 sect->u.indirect.dir_nrows--;
3023 } /* end if */
3024 } /* end if */
3025 else {
3026 H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
3027 hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
3028 unsigned peer_nentries; /* Number of entries in new peer indirect section */
3029 unsigned peer_dir_nrows; /* Number of direct rows in new peer indirect section */
3030 unsigned new_start_row; /* New starting row for current indirect section */
3031 unsigned u; /* Local index variable */
3032
3033 /* Sanity checks */
3034 HDassert(row_sect->u.row.col == 0);
3035 HDassert(row_sect->u.row.row > 0);
3036 HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
3037 HDassert(row_sect->u.row.num_entries == hdr->man_dtable.cparam.width);
3038 HDassert(row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
3039
3040 /* Compute basic information about peer & current indirect sections */
3041 new_start_row = row_sect->u.row.row;
3042 peer_nentries = row_entry - start_entry;
3043 peer_dir_nrows = new_start_row - start_row;
3044
3045 /* Get indirect block information for peer */
3046 if(sect->sect_info.state == H5FS_SECT_LIVE) {
3047 iblock = sect->u.indirect.u.iblock;
3048 iblock_off = sect->u.indirect.u.iblock->block_off;
3049 } /* end if */
3050 else {
3051 iblock = NULL;
3052 iblock_off = sect->u.indirect.u.iblock_off;
3053 } /* end else */
3054
3055 /* Create peer indirect section */
3056 if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
3057 sect->sect_info.size, iblock, iblock_off, start_row, start_col,
3058 peer_nentries)))
3059 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
3060
3061 /* Set up direct row & indirect entry information for peer section */
3062 peer_sect->u.indirect.indir_nents = 0;
3063 peer_sect->u.indirect.indir_ents = NULL;
3064 peer_sect->u.indirect.dir_nrows = peer_dir_nrows;
3065 if(NULL == (peer_sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
3066 HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for row section pointer array")
3067
3068 /* Transfer row sections between current & peer sections */
3069 HDmemcpy(&peer_sect->u.indirect.dir_rows[0],
3070 §->u.indirect.dir_rows[0],
3071 (sizeof(H5HF_free_section_t *) * peer_dir_nrows));
3072 HDmemmove(§->u.indirect.dir_rows[0],
3073 §->u.indirect.dir_rows[peer_dir_nrows],
3074 (sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows)));
3075 sect->u.indirect.dir_nrows -= peer_dir_nrows;
3076 HDassert(row_sect == sect->u.indirect.dir_rows[0]);
3077
3078 /* Re-target transferred row sections to point to new underlying indirect section */
3079 for(u = 0; u < peer_dir_nrows; u++)
3080 peer_sect->u.indirect.dir_rows[u]->u.row.under = peer_sect;
3081
3082 /* Change first row section in indirect section to be the "first row" */
3083 /* (But we don't have to tell the free space manager about it,
3084 * because the row section is "checked out" from the free space
3085 * manager currently.
3086 */
3087 row_sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
3088
3089 /* Adjust reference counts for current & peer sections */
3090 peer_sect->u.indirect.rc = peer_dir_nrows;
3091 sect->u.indirect.rc -= peer_dir_nrows;
3092
3093 /* Transfer/update cached information about indirect block */
3094 peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
3095 peer_sect->u.indirect.span_size = row_sect->sect_info.addr - peer_sect->sect_info.addr;
3096
3097 /* Update information for current section */
3098 sect->sect_info.addr = row_sect->sect_info.addr + hdr->man_dtable.row_block_size[new_start_row];
3099 sect->u.indirect.span_size -= peer_sect->u.indirect.span_size; /* (span for row section has already been removed) */
3100 sect->u.indirect.row = new_start_row;
3101 sect->u.indirect.col = row_sect->u.row.col + 1;
3102 sect->u.indirect.num_entries -= (peer_nentries + 1); /* Transferred entries, plus the entry allocated out of the row */
3103
3104 /* Make certain we've tracked the sections' dependents correctly */
3105 HDassert(sect->u.indirect.rc ==
3106 (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
3107 HDassert(peer_sect->u.indirect.rc ==
3108 (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
3109
3110 /* Reset the peer_sect variable, to indicate that it has been hooked into the data structures correctly and shouldn't be freed */
3111 peer_sect = NULL;
3112 } /* end else */
3113 } /* end if */
3114 else {
3115 /* Decrement count of entries & rows */
3116 sect->u.indirect.num_entries--;
3117 sect->u.indirect.dir_nrows--;
3118 HDassert(sect->u.indirect.dir_nrows == 0);
3119
3120 /* Eliminate direct rows for this section */
3121 sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
3122 } /* end else */
3123
3124 done:
3125 /* Free allocated peer_sect. Note that this is necessary for all failures until peer_sect is linked
3126 * into the main free space structures (via the direct blocks), and the reference count is updated. */
3127 if(peer_sect) {
3128 /* Sanity check - we should only be here if an error occurred */
3129 HDassert(ret_value < 0);
3130
3131 if(H5HF_sect_indirect_free(peer_sect) < 0)
3132 HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
3133 } /* end if */
3134
3135 FUNC_LEAVE_NOAPI(ret_value)
3136 } /* end H5HF_sect_indirect_reduce_row() */
3137
3138
3139 /*-------------------------------------------------------------------------
3140 * Function: H5HF_sect_indirect_reduce
3141 *
3142 * Purpose: Reduce the size of a indirect section (possibly freeing it)
3143 * and re-add it back to the free space manager for the heap
3144 * (if it hasn't been freed)
3145 *
3146 * Return: Non-negative on success/Negative on failure
3147 *
3148 * Programmer: Quincey Koziol
3149 * koziol@ncsa.uiuc.edu
3150 * July 10 2006
3151 *
3152 *-------------------------------------------------------------------------
3153 */
3154 static herr_t
H5HF_sect_indirect_reduce(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect,unsigned child_entry)3155 H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect,
3156 unsigned child_entry)
3157 {
3158 unsigned start_entry; /* Entry for first block covered */
3159 unsigned start_row; /* Start row in indirect block */
3160 unsigned start_col; /* Start column in indirect block */
3161 unsigned end_entry; /* Entry for last block covered */
3162 unsigned end_row; /* End row in indirect block */
3163 H5HF_free_section_t *peer_sect = NULL; /* Peer indirect section */
3164 herr_t ret_value = SUCCEED; /* Return value */
3165
3166 FUNC_ENTER_NOAPI_NOINIT
3167
3168 /*
3169 * Check arguments.
3170 */
3171 HDassert(hdr);
3172 HDassert(sect);
3173 HDassert(sect->u.indirect.span_size > 0);
3174 HDassert(sect->u.indirect.iblock_entries > 0);
3175
3176 /* Compute starting & ending information for indirect section */
3177 start_row = sect->u.indirect.row;
3178 start_col = sect->u.indirect.col;
3179 start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
3180 end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
3181 end_row = end_entry / hdr->man_dtable.cparam.width;
3182
3183 /* Check how to adjust section for allocated entry */
3184 if(sect->u.indirect.num_entries > 1) {
3185 /* Check if we have a parent section to be detached from */
3186 if(sect->u.indirect.parent) {
3187 hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
3188
3189 /* Check if this section is the first section */
3190 is_first = H5HF_sect_indirect_is_first(sect);
3191
3192 /* Reduce parent indirect section */
3193 if(H5HF_sect_indirect_reduce(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
3194 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
3195 sect->u.indirect.parent = NULL;
3196 sect->u.indirect.par_entry = 0;
3197
3198 /* If we weren't the first section, set "first row" for this indirect section */
3199 if(!is_first)
3200 if(H5HF_sect_indirect_first(hdr, dxpl_id, sect) < 0)
3201 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
3202 } /* end if */
3203
3204 /* Check if we can allocate from start of indirect section */
3205 if(child_entry == start_entry) {
3206 /* Sanity check */
3207 HDassert(sect->u.indirect.dir_nrows == 0);
3208 HDassert(sect->u.indirect.dir_rows == NULL);
3209 HDassert(sect->u.indirect.indir_nents > 0);
3210 HDassert(sect->u.indirect.indir_ents);
3211
3212 /* Adjust section start */
3213 sect->sect_info.addr += hdr->man_dtable.row_block_size[start_row];
3214
3215 /* Adjust span of blocks covered */
3216 sect->u.indirect.col++;
3217 if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
3218 sect->u.indirect.row++;
3219 sect->u.indirect.col = 0;
3220 } /* end if */
3221 sect->u.indirect.num_entries--;
3222 sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row];
3223
3224 /* Adjust indirect entry information */
3225 sect->u.indirect.indir_nents--;
3226 HDmemmove(§->u.indirect.indir_ents[0],
3227 §->u.indirect.indir_ents[1],
3228 sect->u.indirect.indir_nents * sizeof(H5HF_free_section_t *));
3229 HDassert(sect->u.indirect.indir_ents[0]);
3230
3231 /* Make new "first row" in new first indirect child section */
3232 if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
3233 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
3234 } /* end if */
3235 else if(child_entry == end_entry) {
3236 /* Sanity check */
3237 HDassert(sect->u.indirect.indir_nents > 0);
3238 HDassert(sect->u.indirect.indir_ents);
3239
3240 /* Adjust span of blocks covered */
3241 sect->u.indirect.num_entries--;
3242 sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row];
3243
3244 /* Adjust indirect entry information */
3245 sect->u.indirect.indir_nents--;
3246 if(sect->u.indirect.indir_nents == 0)
3247 sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
3248 } /* end if */
3249 else {
3250 H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
3251 hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
3252 haddr_t peer_sect_addr; /* Address of new peer section in "heap space" */
3253 unsigned peer_nentries; /* Number of entries in new peer indirect section */
3254 unsigned peer_start_row; /* Starting row for new peer indirect section */
3255 unsigned peer_start_col; /* Starting column for new peer indirect section */
3256 unsigned child_row; /* Row where child entry is located */
3257 unsigned new_nentries; /* New number of entries for current indirect section */
3258 unsigned u; /* Local index variable */
3259
3260 /* Sanity check */
3261 HDassert(sect->u.indirect.indir_nents > 0);
3262 HDassert(sect->u.indirect.indir_ents);
3263
3264 /* Compute basic information about peer & current indirect sections */
3265 peer_nentries = end_entry - child_entry;
3266 peer_start_row = (child_entry + 1) / hdr->man_dtable.cparam.width;
3267 peer_start_col = (child_entry + 1) % hdr->man_dtable.cparam.width;
3268 child_row = child_entry / hdr->man_dtable.cparam.width;
3269 new_nentries = sect->u.indirect.num_entries - (peer_nentries + 1);
3270 HDassert(child_row >= hdr->man_dtable.max_direct_rows);
3271
3272 /* Get indirect block information for peer */
3273 if(sect->sect_info.state == H5FS_SECT_LIVE) {
3274 iblock = sect->u.indirect.u.iblock;
3275 iblock_off = sect->u.indirect.u.iblock->block_off;
3276 } /* end if */
3277 else {
3278 iblock = NULL;
3279 iblock_off = sect->u.indirect.u.iblock_off;
3280 } /* end else */
3281
3282 /* Update the number of entries in current section & calculate it's span size */
3283 /* (Will use this to compute the section address for the peer section */
3284 sect->u.indirect.num_entries = new_nentries;
3285 sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
3286 sect->u.indirect.row, sect->u.indirect.col, new_nentries);
3287 HDassert(sect->u.indirect.span_size > 0);
3288
3289 /* Compute address of peer indirect section */
3290 peer_sect_addr = sect->sect_info.addr;
3291 peer_sect_addr += sect->u.indirect.span_size;
3292 peer_sect_addr += hdr->man_dtable.row_block_size[child_row];
3293
3294 /* Create peer indirect section */
3295 if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, peer_sect_addr,
3296 sect->sect_info.size, iblock, iblock_off, peer_start_row,
3297 peer_start_col, peer_nentries)))
3298 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
3299
3300 /* Set up direct row & indirect entry information for peer section */
3301 peer_sect->u.indirect.dir_nrows = 0;
3302 peer_sect->u.indirect.dir_rows = NULL;
3303 peer_sect->u.indirect.indir_nents = peer_nentries;
3304 if(NULL == (peer_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
3305 HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for indirect section pointer array")
3306
3307 /* Transfer child indirect sections between current & peer sections */
3308 HDmemcpy(&peer_sect->u.indirect.indir_ents[0],
3309 §->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
3310 (sizeof(H5HF_free_section_t *) * peer_nentries));
3311 sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */
3312
3313 /* Eliminate indirect entries for this section, if appropriate */
3314 if(sect->u.indirect.indir_nents == 0)
3315 sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
3316
3317 /* Re-target transferred row sections to point to new underlying indirect section */
3318 for(u = 0; u < peer_nentries; u++)
3319 peer_sect->u.indirect.indir_ents[u]->u.indirect.parent = peer_sect;
3320
3321 /* Adjust reference counts for current & peer sections */
3322 peer_sect->u.indirect.rc = peer_nentries;
3323 sect->u.indirect.rc -= peer_nentries;
3324
3325 /* Transfer cached information about indirect block */
3326 peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
3327
3328 /* Make certain we've tracked the sections' dependents correctly */
3329 /* (Note modified on current section's ref. count, since we haven't
3330 * detached the child section yet)
3331 */
3332 HDassert((sect->u.indirect.rc - 1) ==
3333 (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
3334 HDassert(peer_sect->u.indirect.rc ==
3335 (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
3336
3337 /* Make new "first row" in peer section */
3338 if(H5HF_sect_indirect_first(hdr, dxpl_id, peer_sect->u.indirect.indir_ents[0]) < 0)
3339 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for peer indirect section")
3340
3341 /* Reset the peer_sect variable, to indicate that it has been hooked into the data structures correctly and shouldn't be freed */
3342 peer_sect = NULL;
3343 } /* end else */
3344 } /* end if */
3345 else {
3346 /* Decrement count of entries & indirect entries */
3347 sect->u.indirect.num_entries--;
3348 sect->u.indirect.indir_nents--;
3349 HDassert(sect->u.indirect.indir_nents == 0);
3350
3351 /* Eliminate indirect entries for this section */
3352 sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
3353 } /* end else */
3354
3355 /* Decrement # of sections which depend on this row */
3356 /* (Must be last as section can be freed) */
3357 if(H5HF_sect_indirect_decr(sect) < 0)
3358 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement section's ref. count ")
3359
3360 done:
3361 /* Free allocated peer_sect. Note that this is necessary for all failures until peer_sect is linked
3362 * into the main free space structures (via the direct blocks), and the reference count is updated. */
3363 if(peer_sect) {
3364 /* Sanity check - we should only be here if an error occurred */
3365 HDassert(ret_value < 0);
3366
3367 if(H5HF_sect_indirect_free(peer_sect) < 0)
3368 HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
3369 } /* end if */
3370
3371 FUNC_LEAVE_NOAPI(ret_value)
3372 } /* end H5HF_sect_indirect_reduce() */
3373
3374
3375 /*-------------------------------------------------------------------------
3376 * Function: H5HF_sect_indirect_is_first
3377 *
3378 * Purpose: Check if indirect section is first in all parents
3379 *
3380 * Return: Non-negative (TRUE/FALSE) on success/<can't fail>
3381 *
3382 * Programmer: Quincey Koziol
3383 * koziol@ncsa.uiuc.edu
3384 * July 17 2006
3385 *
3386 *-------------------------------------------------------------------------
3387 */
3388 static hbool_t
H5HF_sect_indirect_is_first(H5HF_free_section_t * sect)3389 H5HF_sect_indirect_is_first(H5HF_free_section_t *sect)
3390 {
3391 hbool_t ret_value = FALSE; /* Return value */
3392
3393 FUNC_ENTER_NOAPI_NOINIT_NOERR
3394
3395 /* Sanity check */
3396 HDassert(sect);
3397
3398 /* Recurse to parent */
3399 if(sect->u.indirect.parent) {
3400 if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
3401 ret_value = H5HF_sect_indirect_is_first(sect->u.indirect.parent);
3402 } /* end if */
3403 else
3404 ret_value = TRUE;
3405
3406 FUNC_LEAVE_NOAPI(ret_value)
3407 } /* end H5HF_sect_indirect_is_first() */
3408
3409
3410 /*-------------------------------------------------------------------------
3411 * Function: H5HF_sect_indirect_first
3412 *
3413 * Purpose: Make new 'first row' for indirect section
3414 *
3415 * Return: Non-negative on success/Negative on failure
3416 *
3417 * Programmer: Quincey Koziol
3418 * koziol@ncsa.uiuc.edu
3419 * July 10 2006
3420 *
3421 *-------------------------------------------------------------------------
3422 */
3423 static herr_t
H5HF_sect_indirect_first(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)3424 H5HF_sect_indirect_first(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
3425 {
3426 herr_t ret_value = SUCCEED; /* Return value */
3427
3428 FUNC_ENTER_NOAPI_NOINIT
3429
3430 /* Sanity check */
3431 HDassert(hdr);
3432 HDassert(sect);
3433
3434 /* Check if this indirect section has direct block rows */
3435 if(sect->u.indirect.dir_nrows > 0) {
3436 /* Sanity checks */
3437 HDassert(sect->u.indirect.row == 0);
3438 HDassert(sect->u.indirect.col == 0);
3439 HDassert(sect->u.indirect.dir_rows);
3440 HDassert(sect->u.indirect.dir_rows[0]);
3441
3442 /* Change first row section in indirect section to be the "first row" */
3443 if(H5HF_sect_row_first(hdr, dxpl_id, sect->u.indirect.dir_rows[0]) < 0)
3444 HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
3445 } /* end if */
3446 else {
3447 /* Sanity checks */
3448 HDassert(sect->u.indirect.indir_nents > 0);
3449 HDassert(sect->u.indirect.indir_ents);
3450 HDassert(sect->u.indirect.indir_ents[0]);
3451
3452 /* Forward to first child indirect section */
3453 if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
3454 HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set child indirect section to be first row")
3455 } /* end else */
3456
3457 done:
3458 FUNC_LEAVE_NOAPI(ret_value)
3459 } /* end H5HF_sect_indirect_first() */
3460
3461
3462 /*-------------------------------------------------------------------------
3463 * Function: H5HF_sect_indirect_get_iblock
3464 *
3465 * Purpose: Retrieve the indirect block for a indirect section
3466 *
3467 * Return: Pointer to indirect block on success/NULL on failure
3468 *
3469 * Programmer: Quincey Koziol
3470 * koziol@ncsa.uiuc.edu
3471 * July 9 2006
3472 *
3473 *-------------------------------------------------------------------------
3474 */
3475 static H5HF_indirect_t *
H5HF_sect_indirect_get_iblock(H5HF_free_section_t * sect)3476 H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect)
3477 {
3478 FUNC_ENTER_NOAPI_NOINIT_NOERR
3479
3480 /*
3481 * Check arguments.
3482 */
3483 HDassert(sect);
3484 HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
3485 HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
3486
3487 FUNC_LEAVE_NOAPI(sect->u.indirect.u.iblock)
3488 } /* end H5HF_sect_indirect_get_iblock() */
3489
3490
3491 /*-------------------------------------------------------------------------
3492 * Function: H5HF_sect_indirect_merge_row
3493 *
3494 * Purpose: Merge two sections of this type
3495 *
3496 * Note: Second section always merges into first node
3497 *
3498 * Return: Success: non-negative
3499 *
3500 * Failure: negative
3501 *
3502 * Programmer: Quincey Koziol
3503 * Tuesday, July 18, 2006
3504 *
3505 *-------------------------------------------------------------------------
3506 */
3507 static herr_t
H5HF_sect_indirect_merge_row(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * row_sect1,H5HF_free_section_t * row_sect2)3508 H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
3509 H5HF_free_section_t *row_sect1, H5HF_free_section_t *row_sect2)
3510 {
3511 H5HF_free_section_t *sect1, *sect2; /* Indirect sections underlying row sections */
3512 unsigned start_entry1; /* Start entry for section #1 */
3513 unsigned start_row1, start_col1; /* Starting row & column for section #1 */
3514 unsigned end_entry1; /* End entry for section #1 */
3515 unsigned end_row1; /* Ending row for section #1 */
3516 unsigned start_row2; /* Starting row for section #2 */
3517 hbool_t merged_rows; /* Flag to indicate that rows was merged together */
3518 unsigned u; /* Local index variable */
3519 herr_t ret_value = SUCCEED; /* Return value */
3520
3521 FUNC_ENTER_NOAPI_NOINIT
3522
3523 /* Sanity check parameters */
3524 HDassert(hdr);
3525 HDassert(row_sect1);
3526 HDassert(row_sect1->u.row.under);
3527 HDassert(row_sect1->sect_info.state == H5FS_SECT_LIVE);
3528 HDassert(row_sect2);
3529 HDassert(row_sect2->u.row.under);
3530 HDassert(row_sect2->sect_info.state == H5FS_SECT_LIVE);
3531 HDassert(row_sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
3532
3533 /* Set up indirect section information */
3534 sect1 = H5HF_sect_indirect_top(row_sect1->u.row.under);
3535 HDassert(sect1);
3536 sect2 = H5HF_sect_indirect_top(row_sect2->u.row.under);
3537 HDassert(sect2);
3538
3539 /* Sanity check some assumptions about the indirect sections */
3540 HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
3541 HDassert(sect1->u.indirect.span_size > 0);
3542 HDassert(sect1->u.indirect.iblock_entries > 0);
3543 HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
3544 HDassert(sect2->u.indirect.span_size > 0);
3545 HDassert(sect2->u.indirect.iblock_entries > 0);
3546 HDassert(sect1->u.indirect.iblock_entries == sect2->u.indirect.iblock_entries);
3547
3548 /* Set up span information */
3549 start_row1 = sect1->u.indirect.row;
3550 start_col1 = sect1->u.indirect.col;
3551 start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1;
3552 end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1;
3553 end_row1 = end_entry1 / hdr->man_dtable.cparam.width;
3554 start_row2 = sect2->u.indirect.row;
3555
3556 /* Check for direct sections in second section */
3557 /* (second indirect section can be parent of indirect section for second
3558 * row, and thus have no row sections of it's own)
3559 */
3560 if(sect2->u.indirect.dir_nrows > 0) {
3561 unsigned new_dir_nrows1; /* New value for number of direct rows in first section */
3562 unsigned src_row2; /* Source row for copying from second section */
3563 unsigned nrows_moved2; /* Number of rows to move from second section to first */
3564
3565 /* Sanity check child row assumptions */
3566 /* (second indirect section should be at top of equal or deeper
3567 * hier. of row/indirect sections, so if second indirect section
3568 * has child row sections, first indirect section _must_ have
3569 * them also)
3570 */
3571 HDassert(sect1->u.indirect.dir_nrows > 0);
3572 HDassert(sect1->u.indirect.dir_rows);
3573
3574 /* Check for sections sharing a row in the same underlying indirect block */
3575 if(row_sect1->u.row.under->u.indirect.u.iblock->block_off == row_sect2->u.row.under->u.indirect.u.iblock->block_off
3576 && end_row1 == start_row2) {
3577 H5HF_free_section_t *last_row_sect1; /* Last row in first indirect section */
3578
3579 /* Locate the last row section in first indirect section, if we don't already have it */
3580 if(row_sect1->u.row.row != end_row1)
3581 last_row_sect1 = sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows - 1];
3582 else
3583 last_row_sect1 = row_sect1;
3584 HDassert(last_row_sect1);
3585 HDassert(last_row_sect1->u.row.row == end_row1);
3586
3587 /* Adjust info for first row section, to absorb second row section */
3588 HDassert((last_row_sect1->u.row.col + last_row_sect1->u.row.num_entries) == row_sect2->u.row.col);
3589 last_row_sect1->u.row.num_entries += row_sect2->u.row.num_entries;
3590
3591 /* Set up parameters for transfer of rows */
3592 src_row2 = 1;
3593 nrows_moved2 = sect2->u.indirect.dir_nrows - 1;
3594 new_dir_nrows1 = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1;
3595
3596 /* Indicate that the rows were merged */
3597 merged_rows = TRUE;
3598 } /* end if */
3599 else {
3600
3601 /* Set up parameters for transfer of rows */
3602 src_row2 = 0;
3603 nrows_moved2 = sect2->u.indirect.dir_nrows;
3604 new_dir_nrows1 = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows;
3605
3606 /* Indicate that the rows were _not_ merged */
3607 merged_rows = FALSE;
3608 } /* end else */
3609
3610 /* Check if we need to move additional rows */
3611 if(nrows_moved2 > 0) {
3612 H5HF_free_section_t **new_dir_rows; /* Pointer to new array of direct row pointers */
3613
3614 /* Extend the first section's row array */
3615 if(NULL == (new_dir_rows = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1)))
3616 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
3617 sect1->u.indirect.dir_rows = new_dir_rows;
3618
3619 /* Transfer the second section's rows to first section */
3620 HDmemcpy(§1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
3621 §2->u.indirect.dir_rows[src_row2],
3622 (sizeof(H5HF_free_section_t *) * nrows_moved2));
3623
3624 /* Re-target the row sections moved from second section */
3625 for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows1; u++)
3626 sect1->u.indirect.dir_rows[u]->u.row.under = sect1;
3627
3628 /* Adjust reference counts to account for transferred rows */
3629 sect1->u.indirect.rc += nrows_moved2;
3630 sect2->u.indirect.rc -= nrows_moved2;
3631
3632 /* Update information for first section */
3633 sect1->u.indirect.dir_nrows = new_dir_nrows1;
3634 } /* end if */
3635 } /* end if */
3636 else
3637 /* Indicate that the rows were _not_ merged */
3638 merged_rows = FALSE;
3639
3640 /* Check for indirect sections in second section */
3641 if(sect2->u.indirect.indir_nents > 0) {
3642 unsigned new_indir_nents1; /* New value for number of indirect entries in first section */
3643
3644 /* Some sanity checks on second indirect section */
3645 HDassert(sect2->u.indirect.rc > 0);
3646 HDassert(sect2->u.indirect.indir_nents > 0);
3647 HDassert(sect2->u.indirect.indir_ents);
3648
3649 /* Set up parameters for transfer of entries */
3650 new_indir_nents1 = sect1->u.indirect.indir_nents + sect2->u.indirect.indir_nents;
3651
3652 /* Check if first section can just take over second section's memory buffer */
3653 if(sect1->u.indirect.indir_ents == NULL) {
3654 sect1->u.indirect.indir_ents = sect2->u.indirect.indir_ents;
3655 sect2->u.indirect.indir_ents = NULL;
3656 } /* end if */
3657 else {
3658 H5HF_free_section_t **new_indir_ents; /* Pointer to new array of indirect entries */
3659
3660 /* Extend the first section's entry array */
3661 if(NULL == (new_indir_ents = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1)))
3662 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
3663 sect1->u.indirect.indir_ents = new_indir_ents;
3664
3665 /* Transfer the second section's entries to first section */
3666 HDmemcpy(§1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
3667 §2->u.indirect.indir_ents[0],
3668 (sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents));
3669 } /* end else */
3670
3671 /* Re-target the child indirect sections moved from second section */
3672 for(u = sect1->u.indirect.indir_nents; u < new_indir_nents1; u++)
3673 sect1->u.indirect.indir_ents[u]->u.indirect.parent = sect1;
3674
3675 /* Adjust reference counts for transferred child indirect sections */
3676 sect1->u.indirect.rc += sect2->u.indirect.indir_nents;
3677 sect2->u.indirect.rc -= sect2->u.indirect.indir_nents;
3678
3679 /* Update information for first section */
3680 sect1->u.indirect.indir_nents = new_indir_nents1;
3681 } /* end if */
3682
3683 /* Update information for first section */
3684 sect1->u.indirect.num_entries += sect2->u.indirect.num_entries;
3685 sect1->u.indirect.span_size += sect2->u.indirect.span_size;
3686
3687 /* Make certain we've tracked the first section's dependents correctly */
3688 HDassert(sect1->u.indirect.rc ==
3689 (sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows));
3690
3691 /* Wrap up, freeing or re-inserting second row section */
3692 /* (want this to be after the first indirection section is consistent again) */
3693 if(merged_rows) {
3694 /* Release second row section */
3695 /* (indirectly releases second indirect section, since all of it's
3696 * other dependents are gone)
3697 */
3698 HDassert(sect2->u.indirect.rc == 1);
3699 if(H5HF_sect_row_free((H5FS_section_info_t *)row_sect2) < 0)
3700 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section")
3701 } /* end if */
3702 else {
3703 /* Decrement ref. count on second indirect section's parent */
3704 HDassert(sect2->u.indirect.rc == 0);
3705 if(sect2->u.indirect.parent)
3706 if(H5HF_sect_indirect_decr(sect2->u.indirect.parent) < 0)
3707 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
3708
3709 /* Free second indirect section */
3710 if(H5HF_sect_indirect_free(sect2) < 0)
3711 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
3712
3713 /* Re-add the second section's first row */
3714 /* (it's already been added to first indirect section, but it's been removed
3715 * from the free space manager and needs to be re-added)
3716 */
3717 row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW;
3718 if(H5HF_space_add(hdr, dxpl_id, row_sect2, H5FS_ADD_SKIP_VALID) < 0)
3719 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add second row section to free space")
3720 } /* end else */
3721
3722 /* Check if we can create parent indirect section for first section */
3723 /* (i.e. merged indirect sections cover an entire indirect block) */
3724 if(sect1->u.indirect.iblock_entries == sect1->u.indirect.num_entries) {
3725 /* Build parent section for fully populated indirect section */
3726 HDassert(sect1->u.indirect.parent == NULL);
3727 if(H5HF_sect_indirect_build_parent(hdr, sect1) < 0)
3728 HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create parent for full indirect section")
3729 } /* end if */
3730
3731 done:
3732 FUNC_LEAVE_NOAPI(ret_value)
3733 } /* end H5HF_sect_indirect_merge_row() */
3734
3735
3736 /*-------------------------------------------------------------------------
3737 * Function: H5HF_sect_indirect_build_parent
3738 *
3739 * Purpose: Build a parent indirect section for a full indirect section
3740 *
3741 * Return: Success: non-negative
3742 * Failure: negative
3743 *
3744 * Programmer: Quincey Koziol
3745 * Friday, July 21, 2006
3746 *
3747 *-------------------------------------------------------------------------
3748 */
3749 static herr_t
H5HF_sect_indirect_build_parent(H5HF_hdr_t * hdr,H5HF_free_section_t * sect)3750 H5HF_sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
3751 {
3752 H5HF_indirect_t *par_iblock; /* Indirect block for parent section */
3753 H5HF_free_section_t *par_sect = NULL; /* Parent indirect section */
3754 unsigned par_row, par_col; /* Row & column in parent indirect section */
3755 unsigned par_entry; /* Entry within parent indirect section */
3756 herr_t ret_value = SUCCEED; /* Return value */
3757
3758 FUNC_ENTER_NOAPI_NOINIT
3759
3760 /* Sanity check parameters */
3761 HDassert(hdr);
3762 HDassert(sect);
3763 HDassert(sect->u.indirect.span_size > 0);
3764 HDassert(sect->u.indirect.iblock_entries > 0);
3765 HDassert(sect->u.indirect.iblock_entries == sect->u.indirect.num_entries);
3766 HDassert(sect->u.indirect.u.iblock);
3767 HDassert(sect->u.indirect.parent == NULL);
3768
3769 /* Get information for creating parent indirect section */
3770 par_entry = sect->u.indirect.u.iblock->par_entry;
3771 par_row = par_entry / hdr->man_dtable.cparam.width;
3772 par_col = par_entry % hdr->man_dtable.cparam.width;
3773 HDassert(par_row >= hdr->man_dtable.max_direct_rows);
3774 par_iblock = sect->u.indirect.u.iblock->parent;
3775 HDassert(par_iblock);
3776
3777 /* Create parent indirect section */
3778 if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
3779 sect->sect_info.size, par_iblock, par_iblock->block_off,
3780 par_row, par_col, 1)))
3781 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
3782
3783 /* No rows of direct blocks covered in parent, reset direct row information */
3784 par_sect->u.indirect.dir_nrows = 0;
3785 par_sect->u.indirect.dir_rows = NULL;
3786
3787 /* Allocate space for the child indirect sections */
3788 par_sect->u.indirect.indir_nents = 1;
3789 if(NULL == (par_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
3790 HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
3791
3792 /* Attach sections together */
3793 sect->u.indirect.parent = par_sect;
3794 sect->u.indirect.par_entry = par_entry;
3795 par_sect->u.indirect.indir_ents[0] = sect;
3796 par_sect->u.indirect.rc = 1;
3797
3798 done:
3799 if(ret_value < 0)
3800 if(par_sect && H5HF_sect_indirect_free(par_sect) < 0)
3801 HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
3802
3803 FUNC_LEAVE_NOAPI(ret_value)
3804 } /* end H5HF_sect_indirect_build_parent() */
3805
3806
3807 /*-------------------------------------------------------------------------
3808 * Function: H5HF_sect_indirect_shrink
3809 *
3810 * Purpose: "Shrink" container w/section
3811 *
3812 * Return: Success: non-negative
3813 * Failure: negative
3814 *
3815 * Programmer: Quincey Koziol
3816 * Monday, July 24, 2006
3817 *
3818 *-------------------------------------------------------------------------
3819 */
3820 static herr_t
H5HF_sect_indirect_shrink(H5HF_hdr_t * hdr,hid_t dxpl_id,H5HF_free_section_t * sect)3821 H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
3822 {
3823 unsigned u; /* Local index variable */
3824 herr_t ret_value = SUCCEED; /* Return value */
3825
3826 FUNC_ENTER_NOAPI_NOINIT
3827
3828 /* Sanity check parameters */
3829 HDassert(hdr);
3830 HDassert(sect);
3831
3832 /* Sanity check some assumptions about the indirect section */
3833 HDassert(sect->u.indirect.dir_nrows > 0 || sect->u.indirect.indir_nents > 0);
3834
3835 /* Walk through direct rows, freeing them */
3836 for(u = 0; u < sect->u.indirect.dir_nrows; u++) {
3837 /* Remove the normal rows from free space manager */
3838 if(sect->u.indirect.dir_rows[u]->sect_info.type != H5HF_FSPACE_SECT_FIRST_ROW) {
3839 HDassert(sect->u.indirect.dir_rows[u]->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
3840 if(H5HF_space_remove(hdr, dxpl_id, sect->u.indirect.dir_rows[u]) < 0)
3841 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove section from heap free space")
3842 } /* end if */
3843
3844 /* Release the row section */
3845 if(H5HF_sect_row_free_real(sect->u.indirect.dir_rows[u]) < 0)
3846 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
3847 } /* end for */
3848
3849 /* Walk through indirect entries, freeing them (recursively) */
3850 for(u = 0; u < sect->u.indirect.indir_nents; u++)
3851 if(H5HF_sect_indirect_shrink(hdr, dxpl_id, sect->u.indirect.indir_ents[u]) < 0)
3852 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
3853
3854 /* Free the indirect section itself */
3855 if(H5HF_sect_indirect_free(sect) < 0)
3856 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
3857
3858 done:
3859 FUNC_LEAVE_NOAPI(ret_value)
3860 } /* end H5HF_sect_indirect_shrink() */
3861
3862
3863 /*-------------------------------------------------------------------------
3864 * Function: H5HF_sect_indirect_serialize
3865 *
3866 * Purpose: Serialize a "live" indirect section into a buffer
3867 *
3868 * Return: Success: non-negative
3869 *
3870 * Failure: negative
3871 *
3872 * Programmer: Quincey Koziol
3873 * Monday, July 3, 2006
3874 *
3875 *-------------------------------------------------------------------------
3876 */
3877 static herr_t
H5HF_sect_indirect_serialize(H5HF_hdr_t * hdr,const H5HF_free_section_t * sect,uint8_t * buf)3878 H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect,
3879 uint8_t *buf)
3880 {
3881 herr_t ret_value = SUCCEED; /* Return value */
3882
3883 FUNC_ENTER_NOAPI_NOINIT
3884
3885 /* Check arguments. */
3886 HDassert(hdr);
3887 HDassert(sect);
3888 HDassert(buf);
3889
3890 /* Check if this indirect section has a parent & forward if this section is first */
3891 if(sect->u.indirect.parent) {
3892 if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
3893 if(H5HF_sect_indirect_serialize(hdr, sect->u.indirect.parent, buf) < 0)
3894 HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize indirect section's parent indirect section")
3895 } /* end if */
3896 else {
3897 /* Indirect range's indirect block's block offset */
3898 if(sect->sect_info.state == H5FS_SECT_LIVE) {
3899 HDassert(sect->u.indirect.u.iblock);
3900 UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock->block_off, hdr->heap_off_size);
3901 } /* end if */
3902 else
3903 UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock_off, hdr->heap_off_size);
3904
3905 /* Indirect range's row */
3906 UINT16ENCODE(buf, sect->u.indirect.row);
3907
3908 /* Indirect range's column */
3909 UINT16ENCODE(buf, sect->u.indirect.col);
3910
3911 /* Indirect range's # of entries */
3912 UINT16ENCODE(buf, sect->u.indirect.num_entries);
3913 } /* end else */
3914
3915 done:
3916 FUNC_LEAVE_NOAPI(ret_value)
3917 } /* H5HF_sect_indirect_serialize() */
3918
3919
3920 /*-------------------------------------------------------------------------
3921 * Function: H5HF_sect_indirect_deserialize
3922 *
3923 * Purpose: Deserialize a buffer into a "live" indirect section
3924 *
3925 * Return: Success: non-negative
3926 *
3927 * Failure: negative
3928 *
3929 * Programmer: Quincey Koziol
3930 * Monday, July 3, 2006
3931 *
3932 *-------------------------------------------------------------------------
3933 */
3934 static H5FS_section_info_t *
H5HF_sect_indirect_deserialize(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * buf,haddr_t sect_addr,hsize_t sect_size,unsigned * des_flags)3935 H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id,
3936 const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
3937 unsigned *des_flags)
3938 {
3939 H5HF_free_section_t *new_sect; /* New indirect section */
3940 hsize_t iblock_off; /* Indirect block's offset */
3941 unsigned start_row; /* Indirect section's start row */
3942 unsigned start_col; /* Indirect section's start column */
3943 unsigned nentries; /* Indirect section's number of entries */
3944 unsigned start_entry; /* Start entry in indirect block */
3945 unsigned end_entry; /* End entry in indirect block */
3946 unsigned end_row; /* End row in indirect block */
3947 unsigned end_col; /* End column in indirect block */
3948 H5FS_section_info_t *ret_value; /* Return value */
3949
3950 FUNC_ENTER_NOAPI_NOINIT
3951
3952 /* Check arguments. */
3953 HDassert(hdr);
3954 HDassert(buf);
3955 HDassert(H5F_addr_defined(sect_addr));
3956 HDassert(sect_size);
3957
3958 /* Indirect range's indirect block's block offset */
3959 UINT64DECODE_VAR(buf, iblock_off, hdr->heap_off_size);
3960
3961 /* Indirect section's row */
3962 UINT16DECODE(buf, start_row);
3963
3964 /* Indirect section's column */
3965 UINT16DECODE(buf, start_col);
3966
3967 /* Indirect section's # of entries */
3968 UINT16DECODE(buf, nentries);
3969
3970 /* Create free space section node */
3971 if(NULL == (new_sect = H5HF_sect_indirect_new(hdr, sect_addr, sect_size,
3972 NULL, iblock_off, start_row, start_col, nentries)))
3973 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
3974
3975 /* Compute start entry */
3976 start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
3977
3978 /* Compute end column & row */
3979 end_entry = (start_entry + nentries) - 1;
3980 end_row = end_entry / hdr->man_dtable.cparam.width;
3981 end_col = end_entry % hdr->man_dtable.cparam.width;
3982
3983 /* Initialize rows for new indirect section */
3984 if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, NULL,
3985 H5FS_ADD_DESERIALIZING, new_sect->u.indirect.row, new_sect->u.indirect.col,
3986 end_row, end_col) < 0)
3987 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section")
3988
3989 /* Indicate that this section shouldn't be added to free space manager's list */
3990 *des_flags |= H5FS_DESERIALIZE_NO_ADD;
3991
3992 /* Set return value */
3993 ret_value = (H5FS_section_info_t *)new_sect;
3994
3995 done:
3996 FUNC_LEAVE_NOAPI(ret_value)
3997 } /* H5HF_sect_indirect_deserialize() */
3998
3999
4000 /*-------------------------------------------------------------------------
4001 * Function: H5HF_sect_indirect_free
4002 *
4003 * Purpose: Free a 'indirect' section node
4004 *
4005 * Return: Success: non-negative
4006 *
4007 * Failure: negative
4008 *
4009 * Programmer: Quincey Koziol
4010 * Monday, July 3, 2006
4011 *
4012 *-------------------------------------------------------------------------
4013 */
4014 static herr_t
H5HF_sect_indirect_free(H5HF_free_section_t * sect)4015 H5HF_sect_indirect_free(H5HF_free_section_t *sect)
4016 {
4017 H5HF_indirect_t *iblock = NULL; /* Indirect block for section */
4018 herr_t ret_value = SUCCEED; /* Return value */
4019
4020 FUNC_ENTER_NOAPI_NOINIT
4021
4022 HDassert(sect);
4023
4024 /* Release the memory for tracking direct rows */
4025 sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
4026
4027 /* Release the memory for tracking indirect entries */
4028 sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
4029
4030 /* Check for live reference to an indirect block */
4031 if(sect->sect_info.state == H5FS_SECT_LIVE) {
4032 /* Get indirect block, if there was one */
4033 if(sect->u.indirect.u.iblock)
4034 iblock = sect->u.indirect.u.iblock;
4035 } /* end if */
4036
4037 /* Release the sections */
4038 if(H5HF_sect_node_free(sect, iblock) < 0)
4039 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
4040
4041 done:
4042 FUNC_LEAVE_NOAPI(ret_value)
4043 } /* H5HF_sect_indirect_free() */
4044
4045
4046 /*-------------------------------------------------------------------------
4047 * Function: H5HF_sect_indirect_valid
4048 *
4049 * Purpose: Check the validity of a section
4050 *
4051 * Return: Success: non-negative
4052 * Failure: negative
4053 *
4054 * Programmer: Quincey Koziol
4055 * Friday, July 21, 2006
4056 *
4057 *-------------------------------------------------------------------------
4058 */
4059 static herr_t
H5HF_sect_indirect_valid(const H5HF_hdr_t * hdr,const H5HF_free_section_t * sect)4060 H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, const H5HF_free_section_t *sect)
4061 {
4062 unsigned start_row; /* Row for first block covered */
4063 unsigned start_col; /* Column for first block covered */
4064 unsigned start_entry; /* Entry for first block covered */
4065 unsigned end_row; /* Row for last block covered */
4066 unsigned end_entry; /* Entry for last block covered */
4067 unsigned u; /* Local index variable */
4068
4069 FUNC_ENTER_NOAPI_NOINIT_NOERR
4070
4071 /* Sanity check arguments */
4072 HDassert(hdr);
4073 HDassert(sect);
4074
4075 /* Compute starting entry, column & row */
4076 start_row = sect->u.indirect.row;
4077 start_col = sect->u.indirect.col;
4078 start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
4079
4080 /* Compute ending entry, column & row */
4081 end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
4082 end_row = end_entry / hdr->man_dtable.cparam.width;
4083
4084 /* Sanity check any direct rows */
4085 if(sect->u.indirect.dir_nrows > 0) {
4086 unsigned dir_nrows; /* Number of direct rows in section */
4087 unsigned max_dir_row; /* Maximum direct row in section */
4088
4089 /* Check for indirect rows in section */
4090 if(end_row >= hdr->man_dtable.max_direct_rows)
4091 max_dir_row = hdr->man_dtable.max_direct_rows - 1;
4092 else
4093 max_dir_row = end_row;
4094
4095 /* Iterate over direct rows, checking pointer references */
4096 dir_nrows = (max_dir_row - start_row) + 1;
4097 HDassert(dir_nrows == sect->u.indirect.dir_nrows);
4098 for(u = 0; u < dir_nrows; u++) {
4099 const H5HF_free_section_t *tmp_row_sect; /* Pointer to row section */
4100
4101 tmp_row_sect = sect->u.indirect.dir_rows[u];
4102 HDassert(tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW
4103 || tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
4104 HDassert(tmp_row_sect->u.row.under == sect);
4105 HDassert(tmp_row_sect->u.row.row == (start_row + u));
4106 if(u > 0) {
4107 const H5HF_free_section_t *tmp_row_sect2; /* Pointer to row section */
4108
4109 tmp_row_sect2 = sect->u.indirect.dir_rows[u - 1];
4110 HDassert(tmp_row_sect2->u.row.row < tmp_row_sect->u.row.row);
4111 HDassert(H5F_addr_lt(tmp_row_sect2->sect_info.addr, tmp_row_sect->sect_info.addr));
4112 HDassert(tmp_row_sect2->sect_info.size <= tmp_row_sect->sect_info.size);
4113 } /* end if */
4114 } /* end for */
4115 } /* end if */
4116
4117 /* Sanity check any indirect entries */
4118 if(sect->u.indirect.indir_nents > 0) {
4119 /* Basic sanity checks */
4120 if(sect->sect_info.state == H5FS_SECT_LIVE) {
4121 HDassert(sect->u.indirect.iblock_entries);
4122 HDassert(sect->u.indirect.indir_nents <= sect->u.indirect.iblock_entries);
4123 } /* end if */
4124 HDassert(sect->u.indirect.indir_ents);
4125
4126 /* Sanity check each child indirect section */
4127 for(u = 0; u < sect->u.indirect.indir_nents; u++) {
4128 const H5HF_free_section_t *tmp_child_sect; /* Pointer to child indirect section */
4129
4130 tmp_child_sect = sect->u.indirect.indir_ents[u];
4131 HDassert(tmp_child_sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
4132 HDassert(tmp_child_sect->u.indirect.parent == sect);
4133 if(u > 0) {
4134 const H5HF_free_section_t *tmp_child_sect2; /* Pointer to child indirect section */
4135
4136 tmp_child_sect2 = sect->u.indirect.indir_ents[u - 1];
4137 HDassert(H5F_addr_lt(tmp_child_sect2->sect_info.addr, tmp_child_sect->sect_info.addr));
4138 } /* end if */
4139
4140 /* Recursively check child indirect section */
4141 H5HF_sect_indirect_valid(hdr, tmp_child_sect);
4142 } /* end for */
4143 } /* end if */
4144
4145 FUNC_LEAVE_NOAPI(SUCCEED)
4146 } /* H5HF_sect_indirect_valid() */
4147
4148
4149 /*-------------------------------------------------------------------------
4150 * Function: H5HF_sect_indirect_debug
4151 *
4152 * Purpose: Dump debugging information about an indirect free space section
4153 *
4154 * Return: Success: non-negative
4155 *
4156 * Failure: negative
4157 *
4158 * Programmer: Quincey Koziol
4159 * Monday, July 3, 2006
4160 *
4161 *-------------------------------------------------------------------------
4162 */
4163 static herr_t
H5HF_sect_indirect_debug(const H5HF_free_section_t * sect,FILE * stream,int indent,int fwidth)4164 H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
4165 FILE *stream, int indent, int fwidth)
4166 {
4167 FUNC_ENTER_NOAPI_NOINIT_NOERR
4168
4169 /* Check arguments. */
4170 HDassert(sect);
4171
4172 /* Print indirect section information */
4173 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
4174 "Row:",
4175 sect->u.indirect.row);
4176 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
4177 "Column:",
4178 sect->u.indirect.col);
4179 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
4180 "Number of entries:",
4181 sect->u.indirect.num_entries);
4182
4183 FUNC_LEAVE_NOAPI(SUCCEED)
4184 } /* H5HF_sect_indirect_debug() */
4185
4186