hdf5/src/H5Fcwfs.c
Quincey Koziol 9c9ee2008c [svn-r21919] Description:
Refactor function name macros and simplify the FUNC_ENTER macros, to clear
away the cruft and prepare for further cleanups.

Tested on:
    Mac OSX/64 10.7.3 (amazon) w/debug, production & parallel
2012-02-08 22:13:27 -05:00

324 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Quincey Koziol <koziol@hdfgroup.org>
* Tuesday, July 19, 2011
*
* Purpose: Each file has a small cache of global heap collections called
* the CWFS list and recently accessed collections with free
* space appear on this list. As collections are accessed the
* collection is moved toward the front of the list. New
* collections are added to the front of the list while old
* collections are added to the end of the list.
*
* The collection model reduces the overhead which would be
* incurred if the global heap were a single object, and the
* CWFS list allows the library to cheaply choose a collection
* for a new object based on object size, amount of free space
* in the collection, and temporal locality.
*/
/****************/
/* Module Setup */
/****************/
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5HGprivate.h" /* Global heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
/****************/
/* Local Macros */
/****************/
/*
* Maximum length of the CWFS list, the list of remembered collections that
* have free space.
*/
#define H5F_NCWFS 16
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5F_cwfs_add
*
* Purpose: Add a global heap collection to the CWFS for a file.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Tuesday, July 19, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_cwfs_add(H5F_t *f, H5HG_heap_t *heap)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check args */
HDassert(f);
HDassert(f->shared);
HDassert(heap);
/*
* Add the new heap to the CWFS list, removing some other entry if
* necessary to make room. We remove the right-most entry that has less
* free space than this heap.
*/
if(NULL == f->shared->cwfs) {
if(NULL == (f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5F_NCWFS * sizeof(H5HG_heap_t *))))
HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate CWFS for file")
f->shared->cwfs[0] = heap;
f->shared->ncwfs = 1;
} else if(H5F_NCWFS == f->shared->ncwfs) {
int i; /* Local index variable */
for(i = H5F_NCWFS - 1; i >= 0; --i)
if(H5HG_FREE_SIZE(f->shared->cwfs[i]) < H5HG_FREE_SIZE(heap)) {
HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, (size_t)i * sizeof(H5HG_heap_t *));
f->shared->cwfs[0] = heap;
break;
} /* end if */
} else {
HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *));
f->shared->cwfs[0] = heap;
f->shared->ncwfs += 1;
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_cwfs_add() */
/*-------------------------------------------------------------------------
* Function: H5F_cwfs_find_free_heap
*
* Purpose: Find a global heap collection with free space for storing
* a new object.
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Wednesday, July 20, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_cwfs_find_free_heap(H5F_t *f, hid_t dxpl_id, size_t need, haddr_t *addr)
{
unsigned cwfsno; /* Local index for iterating over collections */
hbool_t found = FALSE; /* Flag to indicate a heap with enough space was found */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/* Check args */
HDassert(f);
HDassert(f->shared);
HDassert(addr);
/* Note that we don't have metadata cache locks on the entries in
* f->shared->cwfs.
*
* In the current situation, this doesn't matter, as we are single
* threaded, and as best I can tell, entries are added to and deleted
* from f->shared->cwfs as they are added to and deleted from the
* metadata cache.
*
* To be proper, we should either lock each entry in f->shared->cwfs
* as we examine it, or lock the whole array. However, at present
* I don't see the point as there will be significant overhead,
* and protecting and unprotecting all the collections in the global
* heap on a regular basis will skew the replacement policy.
*
* JRM - 5/24/04
*/
for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++)
if(H5HG_FREE_SIZE(f->shared->cwfs[cwfsno]) >= need) {
*addr = H5HG_ADDR(f->shared->cwfs[cwfsno]);
found = TRUE;
break;
} /* end if */
/*
* If we didn't find any collection with enough free space the check if
* we can extend any of the collections to make enough room.
*/
if(!found) {
size_t new_need;
for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++) {
new_need = need;
new_need -= H5HG_FREE_SIZE(f->shared->cwfs[cwfsno]);
new_need = MAX(H5HG_SIZE(f->shared->cwfs[cwfsno]), new_need);
if((H5HG_SIZE(f->shared->cwfs[cwfsno]) + new_need) <= H5HG_MAXSIZE) {
htri_t extended; /* Whether the heap was extended */
extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_GHEAP, H5HG_ADDR(f->shared->cwfs[cwfsno]), (hsize_t)H5HG_SIZE(f->shared->cwfs[cwfsno]), (hsize_t)new_need);
if(extended < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "error trying to extend heap")
else if(extended == TRUE) {
if(H5HG_extend(f, dxpl_id, H5HG_ADDR(f->shared->cwfs[cwfsno]), new_need) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to extend global heap collection")
*addr = H5HG_ADDR(f->shared->cwfs[cwfsno]);
found = TRUE;
break;
} /* end if */
} /* end if */
} /* end for */
} /* end if */
if(found) {
/* Move the collection forward in the CWFS list, if it's not
* already at the front
*/
if(cwfsno > 0) {
H5HG_heap_t *tmp = f->shared->cwfs[cwfsno];
f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno - 1];
f->shared->cwfs[cwfsno - 1] = tmp;
} /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_cwfs_find_free_heap() */
/*-------------------------------------------------------------------------
* Function: H5F_cwfs_advance_heap
*
* Purpose: Advance a heap in the CWFS
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Wednesday, July 20, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_cwfs_advance_heap(H5F_t *f, H5HG_heap_t *heap, hbool_t add_heap)
{
unsigned u; /* Local index variable */
FUNC_ENTER_NOAPI_NOERR
/* Check args */
HDassert(f);
HDassert(f->shared);
HDassert(heap);
for(u = 0; u < f->shared->ncwfs; u++)
if(f->shared->cwfs[u] == heap) {
if(u) {
f->shared->cwfs[u] = f->shared->cwfs[u - 1];
f->shared->cwfs[u - 1] = heap;
} /* end if */
break;
} /* end if */
if(add_heap && u >= f->shared->ncwfs) {
f->shared->ncwfs = MIN(f->shared->ncwfs + 1, H5F_NCWFS);
f->shared->cwfs[f->shared->ncwfs - 1] = heap;
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5F_cwfs_advance_heap() */
/*-------------------------------------------------------------------------
* Function: H5F_cwfs_remove_heap
*
* Purpose: Remove a heap from the CWFS
*
* Return: Success: Non-negative
* Failure: Negative
*
* Programmer: Quincey Koziol
* Wednesday, July 20, 2011
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_cwfs_remove_heap(H5F_file_t *shared, H5HG_heap_t *heap)
{
unsigned u; /* Local index variable */
FUNC_ENTER_NOAPI_NOERR
/* Check args */
HDassert(shared);
HDassert(heap);
/* Remove the heap from the CWFS list */
for(u = 0; u < shared->ncwfs; u++) {
if(shared->cwfs[u] == heap) {
shared->ncwfs -= 1;
HDmemmove(shared->cwfs + u, shared->cwfs + u + 1, (shared->ncwfs - u) * sizeof(H5HG_heap_t *));
break;
} /* end if */
} /* end for */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5F_cwfs_remove_heap() */