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 *
18 * Created: H5MF.c
19 * Jul 11 1997
20 * Robb Matzke <matzke@llnl.gov>
21 *
22 * Purpose: File memory management functions.
23 *
24 *-------------------------------------------------------------------------
25 */
26
27 /****************/
28 /* Module Setup */
29 /****************/
30
31 #define H5F_PACKAGE /*suppress error about including H5Fpkg */
32 #define H5MF_PACKAGE /*suppress error about including H5MFpkg */
33
34
35 /***********/
36 /* Headers */
37 /***********/
38 #include "H5private.h" /* Generic Functions */
39 #include "H5Eprivate.h" /* Error handling */
40 #include "H5Fpkg.h" /* File access */
41 #include "H5MFpkg.h" /* File memory management */
42 #include "H5VMprivate.h" /* Vectors and arrays */
43
44
45 /****************/
46 /* Local Macros */
47 /****************/
48
49 #define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
50 #define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
51
52 /* Map an allocation request type to a free list */
53 #define H5MF_ALLOC_TO_FS_TYPE(F, T) ((H5FD_MEM_DEFAULT == (F)->shared->fs_type_map[T]) \
54 ? (T) : (F)->shared->fs_type_map[T])
55
56
57 /******************/
58 /* Local Typedefs */
59 /******************/
60
61 /* Enum for kind of free space section+aggregator merging allowed for a file */
62 typedef enum {
63 H5MF_AGGR_MERGE_SEPARATE, /* Everything in separate free list */
64 H5MF_AGGR_MERGE_DICHOTOMY, /* Metadata in one free list and raw data in another */
65 H5MF_AGGR_MERGE_TOGETHER /* Metadata & raw data in one free list */
66 } H5MF_aggr_merge_t;
67
68
69 /********************/
70 /* Package Typedefs */
71 /********************/
72
73
74 /********************/
75 /* Local Prototypes */
76 /********************/
77
78 /* Allocator routines */
79 static herr_t H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type);
80 static herr_t H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type);
81
82
83 /*********************/
84 /* Package Variables */
85 /*********************/
86
87
88 /*****************************/
89 /* Library Private Variables */
90 /*****************************/
91
92
93 /*******************/
94 /* Local Variables */
95 /*******************/
96
97
98 /*-------------------------------------------------------------------------
99 * Function: H5MF_init_merge_flags
100 *
101 * Purpose: Initialize the free space section+aggregator merge flags
102 * for the file.
103 *
104 * Return: SUCCEED/FAIL
105 *
106 * Programmer: Quincey Koziol
107 * Friday, February 1, 2008
108 *
109 *-------------------------------------------------------------------------
110 */
111 herr_t
H5MF_init_merge_flags(H5F_t * f)112 H5MF_init_merge_flags(H5F_t *f)
113 {
114 H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */
115 H5FD_mem_t type; /* Memory type for iteration */
116 hbool_t all_same; /* Whether all the types map to the same value */
117 herr_t ret_value = SUCCEED; /* Return value */
118
119 FUNC_ENTER_NOAPI(FAIL)
120
121 /* check args */
122 HDassert(f);
123 HDassert(f->shared);
124 HDassert(f->shared->lf);
125
126 /* Iterate over all the free space types to determine if sections of that type
127 * can merge with the metadata or small 'raw' data aggregator
128 */
129 all_same = TRUE;
130 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
131 /* Check for any different type mappings */
132 if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_DEFAULT]) {
133 all_same = FALSE;
134 break;
135 } /* end if */
136
137 /* Check for all allocation types mapping to the same free list type */
138 if(all_same) {
139 if(f->shared->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT)
140 mapping_type = H5MF_AGGR_MERGE_SEPARATE;
141 else
142 mapping_type = H5MF_AGGR_MERGE_TOGETHER;
143 } /* end if */
144 else {
145 /* Check for raw data mapping into same list as metadata */
146 if(f->shared->fs_type_map[H5FD_MEM_DRAW] == f->shared->fs_type_map[H5FD_MEM_SUPER])
147 mapping_type = H5MF_AGGR_MERGE_SEPARATE;
148 else {
149 hbool_t all_metadata_same; /* Whether all metadata go in same free list */
150
151 /* One or more allocation type don't map to the same free list type */
152 /* Check if all the metadata allocation types map to the same type */
153 all_metadata_same = TRUE;
154 for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
155 /* Skip checking raw data free list mapping */
156 /* (global heap is treated as raw data) */
157 if(type != H5FD_MEM_DRAW && type != H5FD_MEM_GHEAP) {
158 /* Check for any different type mappings */
159 if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_SUPER]) {
160 all_metadata_same = FALSE;
161 break;
162 } /* end if */
163 } /* end if */
164
165 /* Check for all metadata on same free list */
166 if(all_metadata_same)
167 mapping_type = H5MF_AGGR_MERGE_DICHOTOMY;
168 else
169 mapping_type = H5MF_AGGR_MERGE_SEPARATE;
170 } /* end else */
171 } /* end else */
172
173 /* Based on mapping type, initialize merging flags for each free list type */
174 switch(mapping_type) {
175 case H5MF_AGGR_MERGE_SEPARATE:
176 /* Don't merge any metadata together */
177 HDmemset(f->shared->fs_aggr_merge, 0, sizeof(f->shared->fs_aggr_merge));
178
179 /* Check if merging raw data should be allowed */
180 /* (treat global heaps as raw data) */
181 if(H5FD_MEM_DRAW == f->shared->fs_type_map[H5FD_MEM_DRAW] ||
182 H5FD_MEM_DEFAULT == f->shared->fs_type_map[H5FD_MEM_DRAW]) {
183 f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
184 f->shared->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
185 } /* end if */
186 break;
187
188 case H5MF_AGGR_MERGE_DICHOTOMY:
189 /* Merge all metadata together (but not raw data) */
190 HDmemset(f->shared->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f->shared->fs_aggr_merge));
191
192 /* Allow merging raw data allocations together */
193 /* (treat global heaps as raw data) */
194 f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
195 f->shared->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA;
196 break;
197
198 case H5MF_AGGR_MERGE_TOGETHER:
199 /* Merge all allocation types together */
200 HDmemset(f->shared->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f->shared->fs_aggr_merge));
201 break;
202
203 default:
204 HGOTO_ERROR(H5E_RESOURCE, H5E_BADVALUE, FAIL, "invalid mapping type")
205 } /* end switch */
206
207 done:
208 FUNC_LEAVE_NOAPI(ret_value)
209 } /* end H5MF_init_merge_flags() */
210
211
212 /*-------------------------------------------------------------------------
213 * Function: H5MF_alloc_open
214 *
215 * Purpose: Open an existing free space manager of TYPE for file by
216 * creating a free-space structure
217 *
218 * Return: Success: non-negative
219 * Failure: negative
220 *
221 * Programmer: Quincey Koziol
222 * koziol@hdfgroup.org
223 * Jan 8 2008
224 *
225 *-------------------------------------------------------------------------
226 */
227 herr_t
H5MF_alloc_open(H5F_t * f,hid_t dxpl_id,H5FD_mem_t type)228 H5MF_alloc_open(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
229 {
230 const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
231 H5MF_FSPACE_SECT_CLS_SIMPLE};
232 herr_t ret_value = SUCCEED; /* Return value */
233
234 FUNC_ENTER_NOAPI_NOINIT
235
236 /*
237 * Check arguments.
238 */
239 HDassert(f);
240 HDassert(f->shared);
241 HDassert(type != H5FD_MEM_NOLIST);
242 HDassert(H5F_addr_defined(f->shared->fs_addr[type]));
243 HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
244
245 /* Open an existing free space structure for the file */
246 if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type],
247 NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
248 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
249
250 /* Set the state for the free space manager to "open", if it is now */
251 if(f->shared->fs_man[type])
252 f->shared->fs_state[type] = H5F_FS_STATE_OPEN;
253
254 done:
255 FUNC_LEAVE_NOAPI(ret_value)
256 } /* end H5MF_alloc_open() */
257
258
259 /*-------------------------------------------------------------------------
260 * Function: H5MF_alloc_create
261 *
262 * Purpose: Create free space manager of TYPE for the file by creating
263 * a free-space structure
264 *
265 * Return: Success: non-negative
266 * Failure: negative
267 *
268 * Programmer: Quincey Koziol
269 * koziol@hdfgroup.org
270 * Jan 8 2008
271 *
272 *-------------------------------------------------------------------------
273 */
274 static herr_t
H5MF_alloc_create(H5F_t * f,hid_t dxpl_id,H5FD_mem_t type)275 H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
276 {
277 const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
278 H5MF_FSPACE_SECT_CLS_SIMPLE};
279 herr_t ret_value = SUCCEED; /* Return value */
280 H5FS_create_t fs_create; /* Free space creation parameters */
281
282 FUNC_ENTER_NOAPI_NOINIT
283
284 /*
285 * Check arguments.
286 */
287 HDassert(f);
288 HDassert(f->shared);
289 HDassert(type != H5FD_MEM_NOLIST);
290 HDassert(!H5F_addr_defined(f->shared->fs_addr[type]));
291 HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
292
293 /* Set the free space creation parameters */
294 fs_create.client = H5FS_CLIENT_FILE_ID;
295 fs_create.shrink_percent = H5MF_FSPACE_SHRINK;
296 fs_create.expand_percent = H5MF_FSPACE_EXPAND;
297 fs_create.max_sect_addr = 1 + H5VM_log2_gen((uint64_t)f->shared->maxaddr);
298 fs_create.max_sect_size = f->shared->maxaddr;
299
300 if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL,
301 &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
302 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
303
304
305 /* Set the state for the free space manager to "open", if it is now */
306 if(f->shared->fs_man[type])
307 f->shared->fs_state[type] = H5F_FS_STATE_OPEN;
308
309 done:
310 FUNC_LEAVE_NOAPI(ret_value)
311 } /* end H5MF_alloc_create() */
312
313
314 /*-------------------------------------------------------------------------
315 * Function: H5MF_alloc_start
316 *
317 * Purpose: Open or create a free space manager of a given type
318 *
319 * Return: Success: non-negative
320 * Failure: negative
321 *
322 * Programmer: Quincey Koziol
323 * koziol@hdfgroup.org
324 * Jan 8 2008
325 *
326 *-------------------------------------------------------------------------
327 */
328 herr_t
H5MF_alloc_start(H5F_t * f,hid_t dxpl_id,H5FD_mem_t type)329 H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
330 {
331 herr_t ret_value = SUCCEED; /* Return value */
332
333 FUNC_ENTER_NOAPI_NOINIT
334
335 /*
336 * Check arguments.
337 */
338 HDassert(f);
339 HDassert(f->shared);
340 HDassert(type != H5FD_MEM_NOLIST);
341
342 /* Check if the free space manager exists already */
343 if(H5F_addr_defined(f->shared->fs_addr[type])) {
344 /* Open existing free space manager */
345 if(H5MF_alloc_open(f, dxpl_id, type) < 0)
346 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, FAIL, "can't initialize file free space")
347 } /* end if */
348 else {
349 /* Create new free space manager */
350 if(H5MF_alloc_create(f, dxpl_id, type) < 0)
351 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCREATE, FAIL, "can't initialize file free space")
352 } /* end else */
353
354 done:
355 FUNC_LEAVE_NOAPI(ret_value)
356 } /* end H5MF_alloc_start() */
357
358
359 /*-------------------------------------------------------------------------
360 * Function: H5MF_alloc_close
361 *
362 * Purpose: Close an existing free space manager of TYPE for file
363 *
364 * Return: Success: non-negative
365 * Failure: negative
366 *
367 * Programmer: Vailin Choi; July 1st, 2009
368 *
369 *-------------------------------------------------------------------------
370 */
371 static herr_t
H5MF_alloc_close(H5F_t * f,hid_t dxpl_id,H5FD_mem_t type)372 H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
373 {
374 herr_t ret_value = SUCCEED; /* Return value */
375
376 FUNC_ENTER_NOAPI_NOINIT
377
378 /*
379 * Check arguments.
380 */
381 HDassert(f);
382 HDassert(f->shared);
383 HDassert(type != H5FD_MEM_NOLIST);
384 HDassert(f->shared->fs_man[type]);
385 HDassert(f->shared->fs_state[type] != H5F_FS_STATE_CLOSED);
386
387 /* Close an existing free space structure for the file */
388 if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0)
389 HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info")
390 f->shared->fs_man[type] = NULL;
391 f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
392
393 done:
394 FUNC_LEAVE_NOAPI(ret_value)
395 } /* end H5MF_alloc_close() */
396
397
398 /*-------------------------------------------------------------------------
399 * Function: H5MF_alloc
400 *
401 * Purpose: Allocate SIZE bytes of file memory and return the relative
402 * address where that contiguous chunk of file memory exists.
403 * The TYPE argument describes the purpose for which the storage
404 * is being requested.
405 *
406 * Return: Success: The file address of new chunk.
407 * Failure: HADDR_UNDEF
408 *
409 * Programmer: Robb Matzke
410 * matzke@llnl.gov
411 * Jul 11 1997
412 *
413 *-------------------------------------------------------------------------
414 */
415 haddr_t
H5MF_alloc(H5F_t * f,H5FD_mem_t alloc_type,hid_t dxpl_id,hsize_t size)416 H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, hsize_t size)
417 {
418 H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
419 haddr_t ret_value; /* Return value */
420
421 FUNC_ENTER_NOAPI(HADDR_UNDEF)
422 #ifdef H5MF_ALLOC_DEBUG
423 HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_type, size);
424 #endif /* H5MF_ALLOC_DEBUG */
425
426 /* check arguments */
427 HDassert(f);
428 HDassert(f->shared);
429 HDassert(f->shared->lf);
430 HDassert(size > 0);
431
432 /* Get free space type from allocation type */
433 fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
434
435 /* Check if we are using the free space manager for this file */
436 if(H5F_HAVE_FREE_SPACE_MANAGER(f)) {
437 /* Check if the free space manager for the file has been initialized */
438 if(!f->shared->fs_man[fs_type] && H5F_addr_defined(f->shared->fs_addr[fs_type]))
439 if(H5MF_alloc_open(f, dxpl_id, fs_type) < 0)
440 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, HADDR_UNDEF, "can't initialize file free space")
441
442 /* Search for large enough space in the free space manager */
443 if(f->shared->fs_man[fs_type]) {
444 H5MF_free_section_t *node; /* Free space section pointer */
445 htri_t node_found = FALSE; /* Whether an existing free list node was found */
446
447 /* Try to get a section from the free space manager */
448 if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0)
449 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file")
450 #ifdef H5MF_ALLOC_DEBUG_MORE
451 HDfprintf(stderr, "%s: Check 1.5, node_found = %t\n", FUNC, node_found);
452 #endif /* H5MF_ALLOC_DEBUG_MORE */
453
454 /* Check for actually finding section */
455 if(node_found) {
456 /* Sanity check */
457 HDassert(node);
458
459 /* Retrieve return value */
460 ret_value = node->sect_info.addr;
461
462 /* Check for eliminating the section */
463 if(node->sect_info.size == size) {
464 #ifdef H5MF_ALLOC_DEBUG_MORE
465 HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC);
466 #endif /* H5MF_ALLOC_DEBUG_MORE */
467 /* Free section node */
468 if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
469 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node")
470 } /* end if */
471 else {
472 H5MF_sect_ud_t udata; /* User data for callback */
473
474 /* Adjust information for section */
475 node->sect_info.addr += size;
476 node->sect_info.size -= size;
477
478 /* Construct user data for callbacks */
479 udata.f = f;
480 udata.dxpl_id = dxpl_id;
481 udata.alloc_type = alloc_type;
482 udata.allow_sect_absorb = TRUE;
483 udata.allow_eoa_shrink_only = FALSE;
484
485 #ifdef H5MF_ALLOC_DEBUG_MORE
486 HDfprintf(stderr, "%s: Check 1.7, re-adding node, node->sect_info.size = %Hu\n", FUNC, node->sect_info.size);
487 #endif /* H5MF_ALLOC_DEBUG_MORE */
488 /* Re-insert section node into file's free space */
489 if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
490 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space")
491 } /* end else */
492
493 /* Leave now */
494 HGOTO_DONE(ret_value)
495 } /* end if */
496 } /* end if */
497 #ifdef H5MF_ALLOC_DEBUG_MORE
498 HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
499 #endif /* H5MF_ALLOC_DEBUG_MORE */
500 } /* end if */
501
502 /* Allocate from the metadata aggregator (or the VFD) */
503 if(HADDR_UNDEF == (ret_value = H5MF_aggr_vfd_alloc(f, alloc_type, dxpl_id, size)))
504 HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed from aggr/vfd")
505
506 done:
507 #ifdef H5MF_ALLOC_DEBUG
508 HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, size);
509 #endif /* H5MF_ALLOC_DEBUG */
510 #ifdef H5MF_ALLOC_DEBUG_DUMP
511 H5MF_sects_dump(f, dxpl_id, stderr);
512 #endif /* H5MF_ALLOC_DEBUG_DUMP */
513
514 FUNC_LEAVE_NOAPI(ret_value)
515 } /* end H5MF_alloc() */
516
517
518 /*-------------------------------------------------------------------------
519 * Function: H5MF_alloc_tmp
520 *
521 * Purpose: Allocate temporary space in the file
522 *
523 * Note: The address returned is non-overlapping with any other address
524 * in the file and suitable for insertion into the metadata
525 * cache.
526 *
527 * The address is _not_ suitable for actual file I/O and will
528 * cause an error if it is so used.
529 *
530 * The space allocated with this routine should _not_ be freed,
531 * it should just be abandoned. Calling H5MF_xfree() with space
532 * from this routine will cause an error.
533 *
534 * Return: Success: Temporary file address
535 * Failure: HADDR_UNDEF
536 *
537 * Programmer: Quincey Koziol
538 * Thursday, June 4, 2009
539 *
540 *-------------------------------------------------------------------------
541 */
542 haddr_t
H5MF_alloc_tmp(H5F_t * f,hsize_t size)543 H5MF_alloc_tmp(H5F_t *f, hsize_t size)
544 {
545 haddr_t eoa; /* End of allocated space in the file */
546 haddr_t ret_value; /* Return value */
547
548 FUNC_ENTER_NOAPI(HADDR_UNDEF)
549 #ifdef H5MF_ALLOC_DEBUG
550 HDfprintf(stderr, "%s: size = %Hu\n", FUNC, size);
551 #endif /* H5MF_ALLOC_DEBUG */
552
553 /* check args */
554 HDassert(f);
555 HDassert(f->shared);
556 HDassert(f->shared->lf);
557 HDassert(size > 0);
558
559 /* Retrieve the 'eoa' for the file */
560 if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
561 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "driver get_eoa request failed")
562
563 /* Compute value to return */
564 ret_value = f->shared->tmp_addr - size;
565
566 /* Check for overlap into the actual allocated space in the file */
567 if(H5F_addr_le(ret_value, eoa))
568 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "driver get_eoa request failed")
569
570 /* Adjust temporary address allocator in the file */
571 f->shared->tmp_addr = ret_value;
572
573 done:
574 FUNC_LEAVE_NOAPI(ret_value)
575 } /* end H5MF_alloc_tmp() */
576
577
578 /*-------------------------------------------------------------------------
579 * Function: H5MF_xfree
580 *
581 * Purpose: Frees part of a file, making that part of the file
582 * available for reuse.
583 *
584 * Return: Non-negative on success/Negative on failure
585 *
586 * Programmer: Robb Matzke
587 * matzke@llnl.gov
588 * Jul 17 1997
589 *
590 *-------------------------------------------------------------------------
591 */
592 herr_t
H5MF_xfree(H5F_t * f,H5FD_mem_t alloc_type,hid_t dxpl_id,haddr_t addr,hsize_t size)593 H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
594 hsize_t size)
595 {
596 H5MF_free_section_t *node = NULL; /* Free space section pointer */
597 H5MF_sect_ud_t udata; /* User data for callback */
598 H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
599 herr_t ret_value = SUCCEED; /* Return value */
600
601 FUNC_ENTER_NOAPI(FAIL)
602 #ifdef H5MF_ALLOC_DEBUG
603 HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
604 #endif /* H5MF_ALLOC_DEBUG */
605
606 /* check arguments */
607 HDassert(f);
608 if(!H5F_addr_defined(addr) || 0 == size)
609 HGOTO_DONE(SUCCEED);
610 HDassert(addr != 0); /* Can't deallocate the superblock :-) */
611
612 /* Check for attempting to free space that's a 'temporary' file address */
613 if(H5F_addr_le(f->shared->tmp_addr, addr))
614 HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "attempting to free temporary file space")
615
616 /* Check if the space to free intersects with the file's metadata accumulator */
617 if(H5F_accum_free(f, dxpl_id, alloc_type, addr, size) < 0)
618 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't check free space intersection w/metadata accumulator")
619
620 /* Get free space type from allocation type */
621 fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
622 #ifdef H5MF_ALLOC_DEBUG_MORE
623 HDfprintf(stderr, "%s: fs_type = %u\n", FUNC, (unsigned)fs_type);
624 #endif /* H5MF_ALLOC_DEBUG_MORE */
625
626 /* Check if the free space manager for the file has been initialized */
627 if(!f->shared->fs_man[fs_type]) {
628 /* If there's no free space manager for objects of this type,
629 * see if we can avoid creating one by checking if the freed
630 * space is at the end of the file
631 */
632 #ifdef H5MF_ALLOC_DEBUG_MORE
633 HDfprintf(stderr, "%s: f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)fs_type, f->shared->fs_addr[fs_type]);
634 #endif /* H5MF_ALLOC_DEBUG_MORE */
635 if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) {
636 htri_t status; /* "can absorb" status for section into */
637
638 #ifdef H5MF_ALLOC_DEBUG_MORE
639 HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC);
640 #endif /* H5MF_ALLOC_DEBUG_MORE */
641 /* Try to shrink the file or absorb the block into a block aggregator */
642 if((status = H5MF_try_shrink(f, alloc_type, dxpl_id, addr, size)) < 0)
643 HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing block")
644 else if(status > 0)
645 /* Indicate success */
646 HGOTO_DONE(SUCCEED)
647 } /* end if */
648
649 /* If we are deleting the free space manager, leave now, to avoid
650 * [re-]starting it.
651 * or if file space strategy type is not using a free space manager
652 * (H5F_FILE_SPACE_AGGR_VFD or H5F_FILE_SPACE_VFD), drop free space
653 * section on the floor.
654 *
655 * Note: this drops the space to free on the floor...
656 *
657 */
658 if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING ||
659 !H5F_HAVE_FREE_SPACE_MANAGER(f)) {
660 #ifdef H5MF_ALLOC_DEBUG_MORE
661 HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size);
662 #endif /* H5MF_ALLOC_DEBUG_MORE */
663 HGOTO_DONE(SUCCEED)
664 } /* end if */
665
666 /* There's either already a free space manager, or the freed
667 * space isn't at the end of the file, so start up (or create)
668 * the file space manager
669 */
670 if(H5MF_alloc_start(f, dxpl_id, fs_type) < 0)
671 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
672 } /* end if */
673 HDassert(f->shared->fs_man[fs_type]);
674
675 /* Create free space section for block */
676 if(NULL == (node = H5MF_sect_simple_new(addr, size)))
677 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
678
679 /* Construct user data for callbacks */
680 udata.f = f;
681 udata.dxpl_id = dxpl_id;
682 udata.alloc_type = alloc_type;
683 udata.allow_sect_absorb = TRUE;
684 udata.allow_eoa_shrink_only = FALSE;
685
686 /* Add to the free space for the file */
687 #ifdef H5MF_ALLOC_DEBUG_MORE
688 HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC);
689 #endif /* H5MF_ALLOC_DEBUG_MORE */
690 if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
691 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space")
692 node = NULL;
693 #ifdef H5MF_ALLOC_DEBUG_MORE
694 HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC);
695 #endif /* H5MF_ALLOC_DEBUG_MORE */
696
697 done:
698 /* Release section node, if allocated and not added to section list or merged */
699 if(node)
700 if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
701 HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
702
703 #ifdef H5MF_ALLOC_DEBUG
704 HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
705 #endif /* H5MF_ALLOC_DEBUG */
706 #ifdef H5MF_ALLOC_DEBUG_DUMP
707 H5MF_sects_dump(f, dxpl_id, stderr);
708 #endif /* H5MF_ALLOC_DEBUG_DUMP */
709 FUNC_LEAVE_NOAPI(ret_value)
710 } /* end H5MF_xfree() */
711
712
713 /*-------------------------------------------------------------------------
714 * Function: H5MF_try_extend
715 *
716 * Purpose: Extend a block in the file if possible.
717 *
718 * Return: Success: TRUE(1) - Block was extended
719 * FALSE(0) - Block could not be extended
720 * Failure: FAIL
721 *
722 * Programmer: Quincey Koziol
723 * Friday, June 11, 2004
724 *
725 *-------------------------------------------------------------------------
726 */
727 htri_t
H5MF_try_extend(H5F_t * f,hid_t dxpl_id,H5FD_mem_t alloc_type,haddr_t addr,hsize_t size,hsize_t extra_requested)728 H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t alloc_type, haddr_t addr,
729 hsize_t size, hsize_t extra_requested)
730 {
731 haddr_t end; /* End of block to extend */
732 H5FD_mem_t map_type; /* Mapped type */
733 htri_t ret_value; /* Return value */
734
735 FUNC_ENTER_NOAPI(FAIL)
736 #ifdef H5MF_ALLOC_DEBUG
737 HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)alloc_type, addr, size, extra_requested);
738 #endif /* H5MF_ALLOC_DEBUG */
739
740 /* Sanity check */
741 HDassert(f);
742 HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
743
744 /* Set mapped type, treating global heap as raw data */
745 map_type = (alloc_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : alloc_type;
746
747 /* Compute end of block to extend */
748 end = addr + size;
749
750 /* Check if the block is exactly at the end of the file */
751 if((ret_value = H5FD_try_extend(f->shared->lf, map_type, f, end, extra_requested)) < 0)
752 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
753 else if(ret_value == FALSE) {
754 H5F_blk_aggr_t *aggr; /* Aggregator to use */
755
756 /* Check for test block able to extend aggregation block */
757 aggr = (map_type == H5FD_MEM_DRAW) ? &(f->shared->sdata_aggr) : &(f->shared->meta_aggr);
758 if((ret_value = H5MF_aggr_try_extend(f, aggr, map_type, end, extra_requested)) < 0)
759 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block")
760 else if(ret_value == FALSE) {
761 H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
762
763 /* Get free space type from allocation type */
764 fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
765
766 /* Check if the free space for the file has been initialized */
767 if(!f->shared->fs_man[fs_type] && H5F_addr_defined(f->shared->fs_addr[fs_type]))
768 if(H5MF_alloc_open(f, dxpl_id, fs_type) < 0)
769 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
770
771 /* Check for test block able to block in free space manager */
772 if(f->shared->fs_man[fs_type])
773 if((ret_value = H5FS_sect_try_extend(f, dxpl_id, f->shared->fs_man[fs_type], addr, size, extra_requested)) < 0)
774 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager")
775 } /* end if */
776 } /* end if */
777
778 done:
779 #ifdef H5MF_ALLOC_DEBUG
780 HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value);
781 #endif /* H5MF_ALLOC_DEBUG */
782 #ifdef H5MF_ALLOC_DEBUG_DUMP
783 H5MF_sects_dump(f, dxpl_id, stderr);
784 #endif /* H5MF_ALLOC_DEBUG_DUMP */
785
786 FUNC_LEAVE_NOAPI(ret_value)
787 } /* end H5MF_try_extend() */
788
789
790 /*-------------------------------------------------------------------------
791 * Function: H5MF_get_freespace
792 *
793 * Purpose: Retrieve the amount of free space in a file.
794 *
795 * Return: Success: Amount of free space in file
796 * Failure: Negative
797 *
798 * Programmer: Quincey Koziol
799 * Monday, October 6, 2003
800 *
801 * Modifications:
802 * Vailin Choi; July 2012
803 * As the default free-list mapping is changed to H5FD_FLMAP_DICHOTOMY,
804 * checks are added to account for the last section of each free-space manager
805 * and the remaining space in the two aggregators are at EOF.
806 *-------------------------------------------------------------------------
807 */
808 herr_t
H5MF_get_freespace(H5F_t * f,hid_t dxpl_id,hsize_t * tot_space,hsize_t * meta_size)809 H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_size)
810 {
811 haddr_t eoa; /* End of allocated space in the file */
812 haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
813 hsize_t ma_size = 0; /* Size of "metadata aggregator" */
814 haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
815 hsize_t sda_size = 0; /* Size of "small data aggregator" */
816 hsize_t tot_fs_size = 0; /* Amount of all free space managed */
817 hsize_t tot_meta_size = 0; /* Amount of metadata for free space managers */
818 H5FD_mem_t type; /* Memory type for iteration */
819 H5FD_mem_t fs_started[H5FD_MEM_NTYPES]; /* Indicate whether the free-space manager has been started */
820 hbool_t eoa_shrank; /* Whether an EOA shrink occurs */
821 herr_t ret_value = SUCCEED; /* Return value */
822
823 FUNC_ENTER_NOAPI(FAIL)
824
825 /* check args */
826 HDassert(f);
827 HDassert(f->shared);
828 HDassert(f->shared->lf);
829
830 /* Retrieve the 'eoa' for the file */
831 if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
832 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
833
834 /* Retrieve metadata aggregator info, if available */
835 if(H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size) < 0)
836 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query metadata aggregator stats")
837
838 /* Retrieve 'small data' aggregator info, if available */
839 if(H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size) < 0)
840 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query small data aggregator stats")
841
842 /* Iterate over all the free space types that have managers and get each free list's space */
843 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
844
845 fs_started[type] = FALSE;
846
847 /* Check if the free space for the file has been initialized */
848 if(!f->shared->fs_man[type] && H5F_addr_defined(f->shared->fs_addr[type])) {
849 if(H5MF_alloc_open(f, dxpl_id, type) < 0)
850 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
851 HDassert(f->shared->fs_man[type]);
852 fs_started[type] = TRUE;
853 } /* end if */
854
855 /* Check if there's free space of this type */
856 if(f->shared->fs_man[type]) {
857 hsize_t type_fs_size = 0; /* Amount of free space managed for each type */
858 hsize_t type_meta_size = 0; /* Amount of free space metadata for each type */
859
860 /* Retrieve free space size from free space manager */
861 if(H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL) < 0)
862 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats")
863 if(H5FS_size(f, f->shared->fs_man[type], &type_meta_size) < 0)
864 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space metadata stats")
865
866 /* Increment total free space for types */
867 tot_fs_size += type_fs_size;
868 tot_meta_size += type_meta_size;
869 } /* end if */
870 } /* end for */
871
872 /* Iterate until no more EOA shrink occurs */
873 do {
874 eoa_shrank = FALSE;
875
876 /* Check the last section of each free-space manager */
877 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
878 haddr_t sect_addr = HADDR_UNDEF;
879 hsize_t sect_size = 0;
880
881 if(f->shared->fs_man[type]) {
882 if(H5FS_sect_query_last_sect(f->shared->fs_man[type], §_addr, §_size) < 0)
883 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query last section on merge list")
884
885 /* Deduct space from previous accumulation if the section is at EOA */
886 if(H5F_addr_eq(sect_addr + sect_size, eoa)) {
887 eoa = sect_addr;
888 eoa_shrank = TRUE;
889 tot_fs_size -= sect_size;
890 } /* end if */
891 } /* end if */
892 } /* end for */
893
894 /* Check the metadata and raw data aggregators */
895 if(ma_size > 0 && H5F_addr_eq(ma_addr + ma_size, eoa)) {
896 eoa = ma_addr;
897 eoa_shrank = TRUE;
898 ma_size = 0;
899 } /* end if */
900 if(sda_size > 0 && H5F_addr_eq(sda_addr + sda_size, eoa)) {
901 eoa = sda_addr;
902 eoa_shrank = TRUE;
903 sda_size = 0;
904 } /* end if */
905 } while(eoa_shrank);
906
907 /* Close the free-space managers if they were opened earlier in this routine */
908 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
909 if(fs_started[type])
910 if(H5MF_alloc_close(f, dxpl_id, type) < 0)
911 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't close file free space")
912 } /* end for */
913
914 /* Set the value(s) to return */
915 /* (The metadata & small data aggregators count as free space now, since they aren't at EOA) */
916 if(tot_space)
917 *tot_space = tot_fs_size + ma_size + sda_size;
918 if(meta_size)
919 *meta_size = tot_meta_size;
920
921 done:
922 FUNC_LEAVE_NOAPI(ret_value)
923 } /* end H5MF_get_freespace() */
924
925
926 /*-------------------------------------------------------------------------
927 * Function: H5MF_try_shrink
928 *
929 * Purpose: Try to shrink the size of a file with a block or absorb it
930 * into a block aggregator.
931 *
932 * Return: Non-negative on success/Negative on failure
933 *
934 * Programmer: Quincey Koziol
935 * koziol@hdfgroup.org
936 * Feb 14 2008
937 *
938 *-------------------------------------------------------------------------
939 */
940 htri_t
H5MF_try_shrink(H5F_t * f,H5FD_mem_t alloc_type,hid_t dxpl_id,haddr_t addr,hsize_t size)941 H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
942 hsize_t size)
943 {
944 H5MF_free_section_t *node = NULL; /* Free space section pointer */
945 H5MF_sect_ud_t udata; /* User data for callback */
946 htri_t ret_value; /* Return value */
947
948 FUNC_ENTER_NOAPI(FAIL)
949 #ifdef H5MF_ALLOC_DEBUG
950 HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
951 #endif /* H5MF_ALLOC_DEBUG */
952
953 /* check arguments */
954 HDassert(f);
955 HDassert(f->shared);
956 HDassert(f->shared->lf);
957 HDassert(H5F_addr_defined(addr));
958 HDassert(size > 0);
959
960 /* Create free space section for block */
961 if(NULL == (node = H5MF_sect_simple_new(addr, size)))
962 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
963
964 /* Construct user data for callbacks */
965 udata.f = f;
966 udata.dxpl_id = dxpl_id;
967 udata.alloc_type = alloc_type;
968 udata.allow_sect_absorb = FALSE; /* Force section to be absorbed into aggregator */
969 udata.allow_eoa_shrink_only = FALSE;
970
971 /* Call the "can shrink" callback for the section */
972 if((ret_value = H5MF_sect_simple_can_shrink((const H5FS_section_info_t *)node, &udata)) < 0)
973 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container")
974 else if(ret_value > 0) {
975 /* Shrink or absorb the section */
976 if(H5MF_sect_simple_shrink((H5FS_section_info_t **)&node, &udata) < 0)
977 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container")
978 } /* end if */
979
980 done:
981 /* Free section node allocated */
982 if(node && H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
983 HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
984
985 #ifdef H5MF_ALLOC_DEBUG
986 HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
987 #endif /* H5MF_ALLOC_DEBUG */
988 FUNC_LEAVE_NOAPI(ret_value)
989 } /* end H5MF_try_shrink() */
990
991
992 /*-------------------------------------------------------------------------
993 * Function: H5MF_close_shrink_eoa
994 *
995 * Purpose: Shrink the EOA while closing
996 *
997 * Return: SUCCEED/FAIL
998 *
999 * Programmer: Quincey Koziol
1000 * Saturday, July 7, 2012
1001 *
1002 *-------------------------------------------------------------------------
1003 */
1004 static herr_t
H5MF_close_shrink_eoa(H5F_t * f,hid_t dxpl_id)1005 H5MF_close_shrink_eoa(H5F_t *f, hid_t dxpl_id)
1006 {
1007 H5FD_mem_t type; /* Memory type for iteration */
1008 hbool_t eoa_shrank; /* Whether an EOA shrink occurs */
1009 htri_t status; /* Status value */
1010 H5MF_sect_ud_t udata; /* User data for callback */
1011 herr_t ret_value = SUCCEED; /* Return value */
1012
1013 FUNC_ENTER_NOAPI_NOINIT
1014
1015 /* check args */
1016 HDassert(f);
1017 HDassert(f->shared);
1018
1019 /* Construct user data for callbacks */
1020 udata.f = f;
1021 udata.dxpl_id = dxpl_id;
1022 udata.allow_sect_absorb = FALSE;
1023 udata.allow_eoa_shrink_only = TRUE;
1024
1025 /* Iterate until no more EOA shrinking occurs */
1026 do {
1027 eoa_shrank = FALSE;
1028
1029 /* Check the last section of each free-space manager */
1030 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
1031 if(f->shared->fs_man[type]) {
1032 udata.alloc_type = type;
1033 if((status = H5FS_sect_try_shrink_eoa(f, dxpl_id, f->shared->fs_man[type], &udata)) < 0)
1034 HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
1035 else if(status > 0)
1036 eoa_shrank = TRUE;
1037 } /* end if */
1038 } /* end for */
1039
1040 /* check the two aggregators */
1041 if((status = H5MF_aggrs_try_shrink_eoa(f, dxpl_id)) < 0)
1042 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
1043 else if(status > 0)
1044 eoa_shrank = TRUE;
1045 } while(eoa_shrank);
1046
1047 done:
1048 FUNC_LEAVE_NOAPI(ret_value)
1049 } /* end H5MF_close_shrink_eoa() */
1050
1051
1052 /*-------------------------------------------------------------------------
1053 * Function: H5MF_close
1054 *
1055 * Purpose: Close the free space tracker(s) for a file
1056 *
1057 * Return: SUCCEED/FAIL
1058 *
1059 * Programmer: Quincey Koziol
1060 * Tuesday, January 22, 2008
1061 *
1062 * Modifications:
1063 * Vailin Choi; July 2012
1064 * As the default free-list mapping is changed to H5FD_FLMAP_DICHOTOMY,
1065 * modifications are needed to shrink EOA if the last section of each free-space manager
1066 * and the remaining space in the two aggregators are at EOA.
1067
1068 *-------------------------------------------------------------------------
1069 */
1070 herr_t
H5MF_close(H5F_t * f,hid_t dxpl_id)1071 H5MF_close(H5F_t *f, hid_t dxpl_id)
1072 {
1073 H5FD_mem_t type; /* Memory type for iteration */
1074 herr_t ret_value = SUCCEED; /* Return value */
1075
1076 FUNC_ENTER_NOAPI(FAIL)
1077 #ifdef H5MF_ALLOC_DEBUG
1078 HDfprintf(stderr, "%s: Entering\n", FUNC);
1079 #endif /* H5MF_ALLOC_DEBUG */
1080
1081 /* check args */
1082 HDassert(f);
1083 HDassert(f->shared);
1084 HDassert(f->shared->lf);
1085
1086 /* Free the space in aggregators */
1087 /* (for space not at EOF, it may be put into free space managers) */
1088 if(H5MF_free_aggrs(f, dxpl_id) < 0)
1089 HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators")
1090
1091 /* Trying shrinking the EOA for the file */
1092 if(H5MF_close_shrink_eoa(f, dxpl_id) < 0)
1093 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
1094
1095 /* Iterate over all the free space types that have managers and get each free list's space */
1096 for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
1097 #ifdef H5MF_ALLOC_DEBUG_MORE
1098 HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
1099 #endif /* H5MF_ALLOC_DEBUG_MORE */
1100 /* If the free space manager for this type is open, close it */
1101 if(f->shared->fs_man[type]) {
1102 #ifdef H5MF_ALLOC_DEBUG_MORE
1103 HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC);
1104 #endif /* H5MF_ALLOC_DEBUG_MORE */
1105 if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0)
1106 HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info")
1107 f->shared->fs_man[type] = NULL;
1108 f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
1109 } /* end if */
1110 #ifdef H5MF_ALLOC_DEBUG_MORE
1111 HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
1112 #endif /* H5MF_ALLOC_DEBUG_MORE */
1113
1114 /* If there is free space manager info for this type, delete it */
1115 /* (XXX: Make this optional when free space for a file can be persistant) */
1116 if(H5F_addr_defined(f->shared->fs_addr[type])) {
1117 haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */
1118
1119 /* Put address into temporary variable and reset it */
1120 /* (Avoids loopback in file space freeing routine) */
1121 tmp_fs_addr = f->shared->fs_addr[type];
1122 f->shared->fs_addr[type] = HADDR_UNDEF;
1123
1124 /* Shift to "deleting" state, to make certain we don't track any
1125 * file space freed as a result of deleting the free space manager.
1126 */
1127 f->shared->fs_state[type] = H5F_FS_STATE_DELETING;
1128
1129 #ifdef H5MF_ALLOC_DEBUG_MORE
1130 HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC);
1131 #endif /* H5MF_ALLOC_DEBUG_MORE */
1132 /* Delete free space manager for this type */
1133 if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0)
1134 HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't delete free space manager")
1135
1136 /* Shift [back] to closed state */
1137 HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING);
1138 f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
1139
1140 /* Sanity check that the free space manager for this type wasn't started up again */
1141 HDassert(!H5F_addr_defined(f->shared->fs_addr[type]));
1142 } /* end if */
1143 } /* end for */
1144
1145 /* Free the space in aggregators (again) */
1146 /* (in case any free space information re-started them) */
1147 if(H5MF_free_aggrs(f, dxpl_id) < 0)
1148 HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators")
1149
1150 /* Trying shrinking the EOA for the file */
1151 /* (in case any free space is now at the EOA) */
1152 if(H5MF_close_shrink_eoa(f, dxpl_id) < 0)
1153 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
1154
1155 done:
1156 #ifdef H5MF_ALLOC_DEBUG
1157 HDfprintf(stderr, "%s: Leaving\n", FUNC);
1158 #endif /* H5MF_ALLOC_DEBUG */
1159 FUNC_LEAVE_NOAPI(ret_value)
1160 } /* end H5MF_close() */
1161
1162