Files
hdf5/test/cache_common.c
Neil Fortner adc36c3b4b [svn-r23095] Purpose: Refactor flush dependency code, add support for multiple parents
Description:
Reworked how flush dependencies worked internally, allowing multiple flush
dependency parents, and removing the notion of flush dependency heights, instead
keeping track of the number of dirty descendents to determine if parents can be
flushed.  Also removed the requirement that cache clients destroy flush
dependencies before eviction (this is now handled by the cache) and removed the
maximum number of passes (the cache should detect infinite loops elsewhere).
Added test cases for this.

Tested: durandal
2012-12-12 16:31:27 -05:00

5657 lines
165 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: John Mainzer
* 10/27/05
*
* This file contains common code for tests of the cache
* implemented in H5C.c
*/
#include "H5private.h" /* Put this first, so H5open() isn't invoked in public macros */
#include "h5test.h"
#include "H5Cprivate.h"
#include "H5Iprivate.h"
#include "H5MFprivate.h"
#include "cache_common.h"
/* global variable declarations: */
const char *FILENAME[] = {
"cache_test",
"cache_api_test",
NULL
};
hid_t saved_fapl_id = H5P_DEFAULT; /* store the fapl id here between
* cache setup and takedown. Note
* that if saved_fapl_id == H5P_DEFAULT,
* we assume that there is no fapl to
* close.
*/
hid_t saved_fid = -1; /* store the file id here between cache setup
* and takedown.
*/
H5C_t * saved_cache = NULL; /* store the pointer to the instance of
* of H5C_t created by H5Fcreate()
* here between test cache setup and
* shutdown.
*/
haddr_t saved_actual_base_addr = HADDR_UNDEF; /* Store the address of the
space allocated for cache items in the file between
cache setup & takedown */
hbool_t write_permitted = TRUE;
hbool_t pass = TRUE; /* set to false on error */
hbool_t skip_long_tests = TRUE;
hbool_t run_full_test = TRUE;
hbool_t try_core_file_driver = FALSE;
hbool_t core_file_driver_failed = FALSE;
const char *failure_mssg = NULL;
static test_entry_t pico_entries[NUM_PICO_ENTRIES], orig_pico_entries[NUM_PICO_ENTRIES];
static test_entry_t nano_entries[NUM_NANO_ENTRIES], orig_nano_entries[NUM_NANO_ENTRIES];
static test_entry_t micro_entries[NUM_MICRO_ENTRIES], orig_micro_entries[NUM_MICRO_ENTRIES];
static test_entry_t tiny_entries[NUM_TINY_ENTRIES], orig_tiny_entries[NUM_TINY_ENTRIES];
static test_entry_t small_entries[NUM_SMALL_ENTRIES], orig_small_entries[NUM_SMALL_ENTRIES];
static test_entry_t medium_entries[NUM_MEDIUM_ENTRIES], orig_medium_entries[NUM_MEDIUM_ENTRIES];
static test_entry_t large_entries[NUM_LARGE_ENTRIES], orig_large_entries[NUM_LARGE_ENTRIES];
static test_entry_t huge_entries[NUM_HUGE_ENTRIES], orig_huge_entries[NUM_HUGE_ENTRIES];
static test_entry_t monster_entries[NUM_MONSTER_ENTRIES], orig_monster_entries[NUM_MONSTER_ENTRIES];
static test_entry_t variable_entries[NUM_VARIABLE_ENTRIES], orig_variable_entries[NUM_VARIABLE_ENTRIES];
static test_entry_t notify_entries[NUM_NOTIFY_ENTRIES], orig_notify_entries[NUM_NOTIFY_ENTRIES];
hbool_t orig_entry_arrays_init = FALSE;
static herr_t pico_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t nano_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t micro_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t tiny_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t small_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t medium_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t large_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t huge_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t monster_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t variable_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t notify_clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t pico_dest(H5F_t * f, void * thing);
static herr_t nano_dest(H5F_t * f, void * thing);
static herr_t micro_dest(H5F_t * f, void * thing);
static herr_t tiny_dest(H5F_t * f, void * thing);
static herr_t small_dest(H5F_t * f, void * thing);
static herr_t medium_dest(H5F_t * f, void * thing);
static herr_t large_dest(H5F_t * f, void * thing);
static herr_t huge_dest(H5F_t * f, void * thing);
static herr_t monster_dest(H5F_t * f, void * thing);
static herr_t variable_dest(H5F_t * f, void * thing);
static herr_t notify_dest(H5F_t * f, void * thing);
static herr_t pico_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t nano_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t micro_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t tiny_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t small_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t medium_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t large_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t huge_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t variable_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static herr_t notify_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned * flags_ptr);
static void * pico_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * nano_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * micro_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * tiny_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * small_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * medium_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * large_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * huge_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * monster_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * variable_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static void * notify_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static herr_t pico_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t nano_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t micro_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t tiny_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t small_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t medium_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t large_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t huge_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t monster_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t variable_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t notify_size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t notify_notify(H5C_notify_action_t action, void *thing);
static void mark_flush_dep_dirty(test_entry_t * entry_ptr);
static void mark_flush_dep_clean(test_entry_t * entry_ptr);
test_entry_t * entries[NUMBER_OF_ENTRY_TYPES] =
{
pico_entries,
nano_entries,
micro_entries,
tiny_entries,
small_entries,
medium_entries,
large_entries,
huge_entries,
monster_entries,
variable_entries,
notify_entries
};
test_entry_t * orig_entries[NUMBER_OF_ENTRY_TYPES] =
{
orig_pico_entries,
orig_nano_entries,
orig_micro_entries,
orig_tiny_entries,
orig_small_entries,
orig_medium_entries,
orig_large_entries,
orig_huge_entries,
orig_monster_entries,
orig_variable_entries,
orig_notify_entries
};
const int32_t max_indices[NUMBER_OF_ENTRY_TYPES] =
{
NUM_PICO_ENTRIES - 1,
NUM_NANO_ENTRIES - 1,
NUM_MICRO_ENTRIES - 1,
NUM_TINY_ENTRIES - 1,
NUM_SMALL_ENTRIES - 1,
NUM_MEDIUM_ENTRIES - 1,
NUM_LARGE_ENTRIES - 1,
NUM_HUGE_ENTRIES - 1,
NUM_MONSTER_ENTRIES - 1,
NUM_VARIABLE_ENTRIES - 1,
NUM_NOTIFY_ENTRIES - 1
};
const size_t entry_sizes[NUMBER_OF_ENTRY_TYPES] =
{
PICO_ENTRY_SIZE,
NANO_ENTRY_SIZE,
MICRO_ENTRY_SIZE,
TINY_ENTRY_SIZE,
SMALL_ENTRY_SIZE,
MEDIUM_ENTRY_SIZE,
LARGE_ENTRY_SIZE,
HUGE_ENTRY_SIZE,
MONSTER_ENTRY_SIZE,
VARIABLE_ENTRY_SIZE,
NOTIFY_ENTRY_SIZE
};
const haddr_t base_addrs[NUMBER_OF_ENTRY_TYPES] =
{
PICO_BASE_ADDR,
NANO_BASE_ADDR,
MICRO_BASE_ADDR,
TINY_BASE_ADDR,
SMALL_BASE_ADDR,
MEDIUM_BASE_ADDR,
LARGE_BASE_ADDR,
HUGE_BASE_ADDR,
MONSTER_BASE_ADDR,
VARIABLE_BASE_ADDR,
NOTIFY_BASE_ADDR
};
const haddr_t alt_base_addrs[NUMBER_OF_ENTRY_TYPES] =
{
PICO_ALT_BASE_ADDR,
NANO_ALT_BASE_ADDR,
MICRO_ALT_BASE_ADDR,
TINY_ALT_BASE_ADDR,
SMALL_ALT_BASE_ADDR,
MEDIUM_ALT_BASE_ADDR,
LARGE_ALT_BASE_ADDR,
HUGE_ALT_BASE_ADDR,
MONSTER_ALT_BASE_ADDR,
VARIABLE_ALT_BASE_ADDR,
NOTIFY_ALT_BASE_ADDR
};
const char * entry_type_names[NUMBER_OF_ENTRY_TYPES] =
{
"pico entries -- 1 B",
"nano entries -- 4 B",
"micro entries -- 16 B",
"tiny entries -- 64 B",
"small entries -- 256 B",
"medium entries -- 1 KB",
"large entries -- 4 KB",
"huge entries -- 16 KB",
"monster entries -- 64 KB",
"variable entries -- 1B - 10KB",
"notify entries -- 1B"
};
/* callback table declaration */
const H5C_class_t types[NUMBER_OF_ENTRY_TYPES] =
{
{
PICO_ENTRY_TYPE,
(H5C_load_func_t)pico_load,
(H5C_flush_func_t)pico_flush,
(H5C_dest_func_t)pico_dest,
(H5C_clear_func_t)pico_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)pico_size
},
{
NANO_ENTRY_TYPE,
(H5C_load_func_t)nano_load,
(H5C_flush_func_t)nano_flush,
(H5C_dest_func_t)nano_dest,
(H5C_clear_func_t)nano_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)nano_size
},
{
MICRO_ENTRY_TYPE,
(H5C_load_func_t)micro_load,
(H5C_flush_func_t)micro_flush,
(H5C_dest_func_t)micro_dest,
(H5C_clear_func_t)micro_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)micro_size
},
{
TINY_ENTRY_TYPE,
(H5C_load_func_t)tiny_load,
(H5C_flush_func_t)tiny_flush,
(H5C_dest_func_t)tiny_dest,
(H5C_clear_func_t)tiny_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)tiny_size
},
{
SMALL_ENTRY_TYPE,
(H5C_load_func_t)small_load,
(H5C_flush_func_t)small_flush,
(H5C_dest_func_t)small_dest,
(H5C_clear_func_t)small_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)small_size
},
{
MEDIUM_ENTRY_TYPE,
(H5C_load_func_t)medium_load,
(H5C_flush_func_t)medium_flush,
(H5C_dest_func_t)medium_dest,
(H5C_clear_func_t)medium_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)medium_size
},
{
LARGE_ENTRY_TYPE,
(H5C_load_func_t)large_load,
(H5C_flush_func_t)large_flush,
(H5C_dest_func_t)large_dest,
(H5C_clear_func_t)large_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)large_size
},
{
HUGE_ENTRY_TYPE,
(H5C_load_func_t)huge_load,
(H5C_flush_func_t)huge_flush,
(H5C_dest_func_t)huge_dest,
(H5C_clear_func_t)huge_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)huge_size
},
{
MONSTER_ENTRY_TYPE,
(H5C_load_func_t)monster_load,
(H5C_flush_func_t)monster_flush,
(H5C_dest_func_t)monster_dest,
(H5C_clear_func_t)monster_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)monster_size
},
{
VARIABLE_ENTRY_TYPE,
(H5C_load_func_t)variable_load,
(H5C_flush_func_t)variable_flush,
(H5C_dest_func_t)variable_dest,
(H5C_clear_func_t)variable_clear,
(H5C_notify_func_t)NULL,
(H5C_size_func_t)variable_size
},
{
NOTIFY_ENTRY_TYPE,
(H5C_load_func_t)notify_load,
(H5C_flush_func_t)notify_flush,
(H5C_dest_func_t)notify_dest,
(H5C_clear_func_t)notify_clear,
(H5C_notify_func_t)notify_notify,
(H5C_size_func_t)notify_size
}
};
static herr_t clear(H5F_t * f, void * thing, hbool_t dest);
static herr_t destroy(H5F_t * f, void * thing);
static herr_t flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
haddr_t addr, void *thing, unsigned UNUSED * flags_ptr);
static void * load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static herr_t size(H5F_t * f, void * thing, size_t * size_ptr);
static herr_t notify(H5C_notify_action_t action, void *thing);
static void execute_flush_op(H5F_t *file_ptr, struct test_entry_t *entry_ptr,
struct flush_op *op_ptr, unsigned *flags_ptr);
/* address translation funtions: */
/*-------------------------------------------------------------------------
* Function: addr_to_type_and_index
*
* Purpose: Given an address, compute the type and index of the
* associated entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
addr_to_type_and_index(haddr_t addr,
int32_t * type_ptr,
int32_t * index_ptr)
{
int i;
int32_t type;
int32_t idx;
HDassert( type_ptr );
HDassert( index_ptr );
/* we only have a small number of entry types, so just do a
* linear search. If NUMBER_OF_ENTRY_TYPES grows, we may want
* to do a binary search instead.
*/
i = 1;
if ( addr >= PICO_ALT_BASE_ADDR ) {
while ( ( i < NUMBER_OF_ENTRY_TYPES ) &&
( addr >= alt_base_addrs[i] ) )
{
i++;
}
} else {
while ( ( i < NUMBER_OF_ENTRY_TYPES ) &&
( addr >= base_addrs[i] ) )
{
i++;
}
}
type = i - 1;
HDassert( ( type >= 0 ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
if ( addr >= PICO_ALT_BASE_ADDR ) {
idx = (int32_t)((addr - alt_base_addrs[type]) / entry_sizes[type]);
HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) );
HDassert( !((entries[type])[idx].at_main_addr) );
HDassert( addr == (entries[type])[idx].alt_addr );
} else {
idx = (int32_t)((addr - base_addrs[type]) / entry_sizes[type]);
HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) );
HDassert( (entries[type])[idx].at_main_addr );
HDassert( addr == (entries[type])[idx].main_addr );
}
HDassert( addr == (entries[type])[idx].addr );
*type_ptr = type;
*index_ptr = idx;
return;
} /* addr_to_type_and_index() */
#if 0 /* This function has never been used, but we may want it
* some time. Lets keep it for now.
*/
/*-------------------------------------------------------------------------
* Function: type_and_index_to_addr
*
* Purpose: Given a type and index of an entry, compute the associated
* addr and return that value.
*
* Return: computed addr
*
* Programmer: John Mainzer
* 6/10/04
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
haddr_t
type_and_index_to_addr(int32_t type,
int32_t idx)
{
haddr_t addr;
HDassert( ( type >= 0 ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( idx >= 0 ) && ( idx <= max_indices[type] ) );
addr = base_addrs[type] + (((haddr_t)idx) * entry_sizes[type]);
HDassert( addr == (entries[type])[idx].addr );
if ( (entries[type])[idx].at_main_addr ) {
HDassert( addr == (entries[type])[idx].main_addr );
} else {
HDassert( addr == (entries[type])[idx].alt_addr );
}
return(addr);
} /* type_and_index_to_addr() */
#endif
/*-------------------------------------------------------------------------
*
* Function: check_if_write_permitted
*
* Purpose: Determine if a write is permitted under the current
* circumstances, and set *write_permitted_ptr accordingly.
* As a general rule it is, but when we are running in parallel
* mode with collective I/O, we must ensure that a read cannot
* cause a write.
*
* In the event of failure, the value of *write_permitted_ptr
* is undefined.
*
* Return: Non-negative on success/Negative on failure.
*
* Programmer: John Mainzer, 5/15/04
*
*-------------------------------------------------------------------------
*/
herr_t
check_write_permitted(const H5F_t UNUSED * f,
hid_t UNUSED dxpl_id,
hbool_t * write_permitted_ptr)
{
HDassert( write_permitted_ptr );
*write_permitted_ptr = write_permitted;
return(SUCCEED);
} /* check_write_permitted() */
/*-------------------------------------------------------------------------
* Function: clear & friends
*
* Purpose: clear the entry. The helper functions verify that the
* correct version of clear is being called, and then call
* clear proper.
*
* Return: SUCCEED
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
herr_t
clear(H5F_t * f,
void * thing,
hbool_t dest)
{
test_entry_t * entry_ptr;
test_entry_t * base_addr;
hbool_t was_dirty;
HDassert( thing );
entry_ptr = (test_entry_t *)thing;
base_addr = entries[entry_ptr->type];
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[entry_ptr->type] );
HDassert( entry_ptr == &(base_addr[entry_ptr->index]) );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.addr == entry_ptr->addr );
HDassert( entry_ptr->header.size == entry_ptr->size );
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) ||
( entry_ptr->size == entry_sizes[entry_ptr->type] ) );
entry_ptr->header.is_dirty = FALSE;
was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = FALSE;
if(entry_ptr->flush_dep_npar > 0 && was_dirty) {
HDassert(entry_ptr->flush_dep_ndirty_chd == 0);
mark_flush_dep_clean(entry_ptr);
} /* end if */
entry_ptr->cleared = TRUE;
if ( dest ) {
destroy(f, thing);
}
return(SUCCEED);
} /* clear() */
herr_t
pico_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == PICO_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
nano_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == NANO_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
micro_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == MICRO_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
tiny_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == TINY_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
small_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == SMALL_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
medium_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == MEDIUM_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
large_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == LARGE_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
huge_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == HUGE_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
monster_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == MONSTER_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
variable_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE );
return(clear(f, thing, dest));
}
herr_t
notify_clear(H5F_t * f, void * thing, hbool_t dest)
{
HDassert ( ((test_entry_t *)thing)->type == NOTIFY_ENTRY_TYPE );
return(clear(f, thing, dest));
}
/*-------------------------------------------------------------------------
* Function: dest & friends
*
* Purpose: Destroy the entry. The helper functions verify that the
* correct version of dest is being called, and then call
* dest proper.
*
* Return: SUCCEED
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
herr_t
destroy(H5F_t UNUSED * f,
void * thing)
{
int i;
test_entry_t * entry_ptr;
test_entry_t * base_addr;
test_entry_t * pinned_entry_ptr;
test_entry_t * pinned_base_addr;
HDassert( thing );
entry_ptr = (test_entry_t *)thing;
base_addr = entries[entry_ptr->type];
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[entry_ptr->type] );
HDassert( entry_ptr == &(base_addr[entry_ptr->index]) );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->cache_ptr != NULL );
HDassert( entry_ptr->cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( ( entry_ptr->header.destroy_in_progress ) ||
( entry_ptr->header.addr == entry_ptr->addr ) );
HDassert( entry_ptr->header.size == entry_ptr->size );
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) ||
( entry_ptr->size == entry_sizes[entry_ptr->type] ) );
HDassert( !(entry_ptr->is_dirty) );
HDassert( !(entry_ptr->header.is_dirty) );
if ( entry_ptr->num_pins > 0 ) {
for ( i = 0; i < entry_ptr->num_pins; i++ )
{
pinned_base_addr = entries[entry_ptr->pin_type[i]];
pinned_entry_ptr = &(pinned_base_addr[entry_ptr->pin_idx[i]]);
HDassert( 0 <= pinned_entry_ptr->type );
HDassert( pinned_entry_ptr->type < NUMBER_OF_ENTRY_TYPES );
HDassert( pinned_entry_ptr->type == entry_ptr->pin_type[i] );
HDassert( pinned_entry_ptr->index >= 0 );
HDassert( pinned_entry_ptr->index <=
max_indices[pinned_entry_ptr->type] );
HDassert( pinned_entry_ptr->index == entry_ptr->pin_idx[i] );
HDassert( pinned_entry_ptr == pinned_entry_ptr->self );
HDassert( pinned_entry_ptr->header.is_pinned );
HDassert( pinned_entry_ptr->is_pinned );
HDassert( pinned_entry_ptr->pinning_ref_count > 0 );
pinned_entry_ptr->pinning_ref_count--;
if ( pinned_entry_ptr->pinning_ref_count <= 0 ) {
unpin_entry(pinned_entry_ptr->type,
pinned_entry_ptr->index);
}
entry_ptr->pin_type[i] = -1;
entry_ptr->pin_idx[i] = -1;
}
entry_ptr->num_pins = 0;
}
entry_ptr->destroyed = TRUE;
entry_ptr->cache_ptr = NULL;
return(SUCCEED);
} /* dest() */
herr_t
pico_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == PICO_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
nano_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == NANO_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
micro_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == MICRO_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
tiny_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == TINY_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
small_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == SMALL_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
medium_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == MEDIUM_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
large_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == LARGE_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
huge_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == HUGE_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
monster_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == MONSTER_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
variable_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE );
return(destroy(f, thing));
}
herr_t
notify_dest(H5F_t * f, void * thing)
{
HDassert ( ((test_entry_t *)thing)->type == NOTIFY_ENTRY_TYPE );
return(destroy(f, thing));
}
/*-------------------------------------------------------------------------
* Function: flush & friends
*
* Purpose: flush the entry and mark it as clean. The helper functions
* verify that the correct version of flush is being called,
* and then call flush proper.
*
* Return: SUCCEED
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
herr_t
flush(H5F_t *f,
hid_t UNUSED dxpl_id,
hbool_t dest,
haddr_t
#ifdef NDEBUG
UNUSED
#endif /* NDEBUG */
addr,
void *thing,
unsigned * flags_ptr)
{
int i;
test_entry_t * entry_ptr;
test_entry_t * base_addr;
HDassert( thing );
entry_ptr = (test_entry_t *)thing;
base_addr = entries[entry_ptr->type];
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[entry_ptr->type] );
HDassert( entry_ptr == &(base_addr[entry_ptr->index]) );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.addr == entry_ptr->addr );
HDassert( entry_ptr->addr == addr );
HDassert( entry_ptr->header.size == entry_ptr->size );
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) ||
( entry_ptr->size == entry_sizes[entry_ptr->type] ) );
HDassert( entry_ptr->header.is_dirty == entry_ptr->is_dirty );
HDassert( entry_ptr->cache_ptr != NULL );
HDassert( entry_ptr->cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( entry_ptr->num_flush_ops >= 0 );
HDassert( entry_ptr->num_flush_ops < MAX_FLUSH_OPS );
if ( entry_ptr->num_flush_ops > 0 ) {
for ( i = 0; i < entry_ptr->num_flush_ops; i++ )
{
execute_flush_op(f,
entry_ptr,
&((entry_ptr->flush_ops)[i]),
flags_ptr);
}
entry_ptr->num_flush_ops = 0;
entry_ptr->flush_op_self_resize_in_progress = FALSE;
}
entry_ptr->flushed = TRUE;
if ( ( ! write_permitted ) && ( entry_ptr->is_dirty ) ) {
pass = FALSE;
failure_mssg = "called flush when write_permitted is FALSE.";
}
if ( entry_ptr->is_dirty ) {
(entry_ptr->writes)++;
entry_ptr->is_dirty = FALSE;
entry_ptr->header.is_dirty = FALSE;
if(entry_ptr->flush_dep_npar > 0) {
HDassert(entry_ptr->flush_dep_ndirty_chd == 0);
mark_flush_dep_clean(entry_ptr);
} /* end if */
}
if ( dest ) {
destroy(f, thing);
}
return(SUCCEED);
} /* flush() */
herr_t
pico_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == PICO_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
nano_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == NANO_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
micro_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MICRO_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
tiny_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == TINY_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
small_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == SMALL_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
medium_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MEDIUM_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
large_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == LARGE_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
huge_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == HUGE_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
monster_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MONSTER_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
variable_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
herr_t
notify_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
void *thing, unsigned * flags_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == NOTIFY_ENTRY_TYPE );
return(flush(f, dxpl_id, dest, addr, thing, flags_ptr));
}
/*-------------------------------------------------------------------------
* Function: load & friends
*
* Purpose: "load" the requested entry and mark it as clean. The
* helper functions verify that the correct version of load
* is being called, and then call load proper.
*
* Return: SUCCEED
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void *
load(H5F_t UNUSED *f,
hid_t UNUSED dxpl_id,
haddr_t addr,
void UNUSED *udata)
{
int32_t type;
int32_t idx;
test_entry_t * entry_ptr;
test_entry_t * base_addr;
addr_to_type_and_index(addr, &type, &idx);
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->type == type );
HDassert( entry_ptr->type >= 0 );
HDassert( entry_ptr->type < NUMBER_OF_ENTRY_TYPES );
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[type] );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->addr == addr );
HDassert( entry_ptr->flush_dep_npar == 0 );
HDassert( entry_ptr->flush_dep_nchd == 0 );
#if 1 /* JRM */
if ( ! ( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) ||
( entry_ptr->size == entry_sizes[type] ) ) ) {
HDfprintf(stdout, "entry type/index/size = %d/%d/%ld\n",
(int)(entry_ptr->type),
(int)(entry_ptr->index),
(long)(entry_ptr->size));
}
#endif /* JRM */
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) ||
( entry_ptr->size == entry_sizes[type] ) );
entry_ptr->loaded = TRUE;
entry_ptr->header.is_dirty = FALSE;
entry_ptr->is_dirty = FALSE;
(entry_ptr->reads)++;
return(entry_ptr);
} /* load() */
void *
pico_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
nano_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
micro_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
tiny_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
small_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
medium_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
large_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
huge_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
monster_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
variable_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
void *
notify_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata)
{
return(load(f, dxpl_id, addr, udata));
}
/*-------------------------------------------------------------------------
* Function: size & friends
*
* Purpose: Get the size of the specified entry. The helper functions
* verify that the correct version of size is being called,
* and then call size proper.
*
* Return: SUCCEED
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
herr_t
size(H5F_t UNUSED * f,
void * thing,
size_t * size_ptr)
{
test_entry_t * entry_ptr;
test_entry_t * base_addr;
HDassert( size_ptr );
HDassert( thing );
entry_ptr = (test_entry_t *)thing;
base_addr = entries[entry_ptr->type];
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[entry_ptr->type] );
HDassert( entry_ptr == &(base_addr[entry_ptr->index]) );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.addr == entry_ptr->addr );
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || \
( entry_ptr->size == entry_sizes[entry_ptr->type] ) );
*size_ptr = entry_ptr->size;
return(SUCCEED);
} /* size() */
herr_t
pico_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == PICO_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
nano_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == NANO_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
micro_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MICRO_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
tiny_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == TINY_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
small_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == SMALL_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
medium_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MEDIUM_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
large_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == LARGE_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
huge_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == HUGE_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
monster_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == MONSTER_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
variable_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == VARIABLE_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
herr_t
notify_size(H5F_t * f, void * thing, size_t * size_ptr)
{
HDassert ( ((test_entry_t *)thing)->type == NOTIFY_ENTRY_TYPE );
return(size(f, thing, size_ptr));
}
/*-------------------------------------------------------------------------
* Function: notify & friends
*
* Purpose: Record notifications of cache events for the entry.
* The helper functions verify that the correct version of notify
* is being called, and then call notify proper.
*
* Return: SUCCEED
*
* Programmer: Quincey Koziol
* 4/28/09
*
*-------------------------------------------------------------------------
*/
static herr_t
notify(H5C_notify_action_t action, void *thing)
{
test_entry_t * entry_ptr;
test_entry_t * base_addr;
HDassert( thing );
entry_ptr = (test_entry_t *)thing;
base_addr = entries[entry_ptr->type];
HDassert( entry_ptr->index >= 0 );
HDassert( entry_ptr->index <= max_indices[entry_ptr->type] );
HDassert( entry_ptr == &(base_addr[entry_ptr->index]) );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.addr == entry_ptr->addr );
HDassert( ( entry_ptr->type == VARIABLE_ENTRY_TYPE ) || \
( entry_ptr->size == entry_sizes[entry_ptr->type] ) );
/* Increment count for appropriate action */
switch(action) {
case H5C_NOTIFY_ACTION_AFTER_INSERT: /* Entry has been added to the cache */
entry_ptr->notify_after_insert_count++;
break;
case H5C_NOTIFY_ACTION_BEFORE_EVICT: /* Entry is about to be evicted from cache */
entry_ptr->notify_before_evict_count++;
break;
default:
HDassert(0 && "Unknown notify action!?!");
} /* end switch */
return(SUCCEED);
} /* notify() */
herr_t
notify_notify(H5C_notify_action_t action, void *thing)
{
HDassert ( ((test_entry_t *)thing)->type == NOTIFY_ENTRY_TYPE );
return(notify(action, thing));
}
/**************************************************************************/
/**************************************************************************/
/************************** test utility functions: ***********************/
/**************************************************************************/
/**************************************************************************/
/*-------------------------------------------------------------------------
* Function: add_flush_op
*
* Purpose: Do nothing if pass is FALSE on entry.
*
* Otherwise, add the specified flush operation to the
* target instance of test_entry_t.
*
* Return: void
*
* Programmer: John Mainzer
* 9/1/06
*
*-------------------------------------------------------------------------
*/
void
add_flush_op(int target_type,
int target_idx,
int op_code,
int type,
int idx,
hbool_t flag,
size_t new_size,
unsigned * order_ptr)
{
int i;
test_entry_t * target_base_addr;
test_entry_t * target_entry_ptr;
HDassert( ( 0 <= target_type ) && ( target_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= target_idx ) &&
( target_idx <= max_indices[target_type] ) );
HDassert( ( 0 <= op_code ) && ( op_code <= FLUSH_OP__MAX_OP ) );
HDassert( ( op_code != FLUSH_OP__RESIZE ) ||
( type == VARIABLE_ENTRY_TYPE ) );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
HDassert( ( flag == TRUE ) || ( flag == FALSE ) );
HDassert( new_size <= VARIABLE_ENTRY_SIZE );
if ( pass ) {
target_base_addr = entries[target_type];
target_entry_ptr = &(target_base_addr[target_idx]);
HDassert( target_entry_ptr->index == target_idx );
HDassert( target_entry_ptr->type == target_type );
HDassert( target_entry_ptr == target_entry_ptr->self );
HDassert( target_entry_ptr->num_flush_ops < MAX_FLUSH_OPS );
i = (target_entry_ptr->num_flush_ops)++;
(target_entry_ptr->flush_ops)[i].op_code = op_code;
(target_entry_ptr->flush_ops)[i].type = type;
(target_entry_ptr->flush_ops)[i].idx = idx;
(target_entry_ptr->flush_ops)[i].flag = flag;
(target_entry_ptr->flush_ops)[i].size = new_size;
(target_entry_ptr->flush_ops)[i].order_ptr = order_ptr;
}
return;
} /* add_flush_op() */
/*-------------------------------------------------------------------------
* Function: create_pinned_entry_dependency
*
* Purpose: Do nothing if pass is FALSE on entry.
*
* Otherwise, set up a pinned entry dependency so we can
* test the pinned entry modifications to the flush routine.
*
* Given the types and indicies of the pinned and pinning
* entries, add the pinned entry to the list of pinned
* entries in the pinning entry, increment the
* pinning reference count of the pinned entry, and
* if that count was zero initially, pin the entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
create_pinned_entry_dependency(H5F_t * file_ptr,
int pinning_type,
int pinning_idx,
int pinned_type,
int pinned_idx)
{
test_entry_t * pinning_base_addr;
test_entry_t * pinning_entry_ptr;
test_entry_t * pinned_base_addr;
test_entry_t * pinned_entry_ptr;
if ( pass ) {
HDassert( ( 0 <= pinning_type ) &&
( pinning_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= pinning_idx ) &&
( pinning_idx <= max_indices[pinning_type] ) );
HDassert( ( 0 <= pinned_type ) &&
( pinned_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= pinned_idx ) &&
( pinned_idx <= max_indices[pinned_type] ) );
pinning_base_addr = entries[pinning_type];
pinning_entry_ptr = &(pinning_base_addr[pinning_idx]);
pinned_base_addr = entries[pinned_type];
pinned_entry_ptr = &(pinned_base_addr[pinned_idx]);
HDassert( pinning_entry_ptr->index == pinning_idx );
HDassert( pinning_entry_ptr->type == pinning_type );
HDassert( pinning_entry_ptr == pinning_entry_ptr->self );
HDassert( pinning_entry_ptr->num_pins < MAX_PINS );
HDassert( pinning_entry_ptr->index == pinning_idx );
HDassert( pinning_entry_ptr->type == pinning_type );
HDassert( pinning_entry_ptr == pinning_entry_ptr->self );
HDassert( ! ( pinning_entry_ptr->is_protected ) );
pinning_entry_ptr->pin_type[pinning_entry_ptr->num_pins] = pinned_type;
pinning_entry_ptr->pin_idx[pinning_entry_ptr->num_pins] = pinned_idx;
(pinning_entry_ptr->num_pins)++;
if ( pinned_entry_ptr->pinning_ref_count == 0 ) {
protect_entry(file_ptr, pinned_type, pinned_idx);
unprotect_entry(file_ptr, pinned_type, pinned_idx, H5C__PIN_ENTRY_FLAG);
}
(pinned_entry_ptr->pinning_ref_count)++;
}
return;
} /* create_pinned_entry_dependency() */
/*-------------------------------------------------------------------------
* Function: dirty_entry
*
* Purpose: Given a pointer to a cache, an entry type, and an index,
* dirty the target entry.
*
* If the dirty_pin parameter is true, verify that the
* target entry is in the cache and is pinned. If it
* isn't, scream and die. If it is, use the
* H5C_mark_entry_dirty() call to dirty it.
*
* Do nothing if pass is false on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
dirty_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx,
hbool_t dirty_pin)
{
test_entry_t * base_addr;
test_entry_t * entry_ptr;
HDassert( file_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
if ( pass ) {
if ( dirty_pin ) {
H5C_t *cache_ptr = file_ptr->shared->cache;
HDassert(cache_ptr);
if ( ! entry_in_cache(cache_ptr, type, idx) ) {
pass = FALSE;
failure_mssg = "entry to be dirty pinned is not in cache.";
} else {
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
if ( ! ( (entry_ptr->header).is_pinned ) ) {
pass = FALSE;
failure_mssg = "entry to be dirty pinned is not pinned.";
} else {
mark_entry_dirty(type, idx);
}
}
} else {
protect_entry(file_ptr, type, idx);
unprotect_entry(file_ptr, type, idx, H5C__DIRTIED_FLAG);
}
}
return;
} /* dirty_entry() */
/*-------------------------------------------------------------------------
* Function: execute_flush_op
*
* Purpose: Given a pointer to an instance of struct flush_op, execute
* it.
*
* Do nothing if pass is false on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 9/1/06
*
*-------------------------------------------------------------------------
*/
void
execute_flush_op(H5F_t * file_ptr,
struct test_entry_t * entry_ptr,
struct flush_op * op_ptr,
unsigned * flags_ptr)
{
H5C_t * cache_ptr;
HDassert( file_ptr );
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
HDassert( entry_ptr != NULL );
HDassert( entry_ptr = entry_ptr->self );
HDassert( entry_ptr->header.addr == entry_ptr->addr );
HDassert( ( entry_ptr->flush_op_self_resize_in_progress ) ||
( entry_ptr->header.size == entry_ptr->size ) );
HDassert( op_ptr != NULL );
HDassert( ( 0 <= entry_ptr->type ) &&
( entry_ptr->type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= entry_ptr->index ) &&
( entry_ptr->index <= max_indices[entry_ptr->type] ) );
HDassert( ( 0 <= op_ptr->type ) &&
( op_ptr->type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= op_ptr->idx ) &&
( op_ptr->idx <= max_indices[op_ptr->type] ) );
HDassert( ( op_ptr->flag == FALSE ) || ( op_ptr->flag == TRUE ) );
HDassert( flags_ptr != NULL );
if ( pass ) {
switch ( op_ptr->op_code )
{
case FLUSH_OP__NO_OP:
break;
case FLUSH_OP__DIRTY:
HDassert( ( entry_ptr->type != op_ptr->type ) ||
( entry_ptr->index != op_ptr->idx ) );
dirty_entry(file_ptr, op_ptr->type, op_ptr->idx, op_ptr->flag);
break;
case FLUSH_OP__RESIZE:
if ( ( entry_ptr->type == op_ptr->type ) &&
( entry_ptr->index == op_ptr->idx ) ) {
/* the flush operation is acting on the entry to
* which it is attached. Handle this here:
*/
HDassert( entry_ptr->type == VARIABLE_ENTRY_TYPE );
HDassert( op_ptr->size > 0 );
HDassert( op_ptr->size <= VARIABLE_ENTRY_SIZE );
entry_ptr->size = op_ptr->size;
(*flags_ptr) |= H5C_CALLBACK__SIZE_CHANGED_FLAG;
entry_ptr->flush_op_self_resize_in_progress = TRUE;
/* if the entry is in the process of being destroyed,
* set the header size to match the entry size so as
* to avoid a spurious failure in the destroy callback.
*/
if ( entry_ptr->header.destroy_in_progress ) {
entry_ptr->header.size = entry_ptr->size;
}
} else {
/* change the size of some other entry */
resize_entry(file_ptr, op_ptr->type, op_ptr->idx,
op_ptr->size, op_ptr->flag);
}
break;
case FLUSH_OP__MOVE:
move_entry(cache_ptr, op_ptr->type, op_ptr->idx,
op_ptr->flag);
break;
case FLUSH_OP__ORDER:
HDassert( op_ptr->order_ptr );
entry_ptr->flush_order = *op_ptr->order_ptr;
(*op_ptr->order_ptr)++;
break;
default:
pass = FALSE;
failure_mssg = "Undefined flush op code.";
break;
}
}
return;
} /* execute_flush_op() */
/*-------------------------------------------------------------------------
* Function: entry_in_cache
*
* Purpose: Given a pointer to a cache, an entry type, and an index,
* determine if the entry is currently in the cache.
*
* Return: TRUE if the entry is in the cache, and FALSE otherwise.
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
hbool_t
entry_in_cache(H5C_t * cache_ptr,
int32_t type,
int32_t idx)
{
hbool_t in_cache = FALSE; /* will set to TRUE if necessary */
test_entry_t * base_addr;
test_entry_t * entry_ptr;
H5C_cache_entry_t * test_ptr = NULL;
HDassert( cache_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
H5C_TEST__SEARCH_INDEX(cache_ptr, entry_ptr->addr, test_ptr)
if ( test_ptr != NULL ) {
in_cache = TRUE;
HDassert( test_ptr == (H5C_cache_entry_t *)entry_ptr );
HDassert( entry_ptr->addr == entry_ptr->header.addr );
}
return(in_cache);
} /* entry_in_cache() */
/*-------------------------------------------------------------------------
* Function: reset_entries
*
* Purpose: reset the contents of the entries arrays to known values.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
reset_entries(void)
{
int i;
int32_t max_index;
test_entry_t * base_addr;
test_entry_t * orig_base_addr;
if( !orig_entry_arrays_init)
{
haddr_t addr = PICO_BASE_ADDR;
haddr_t alt_addr = PICO_ALT_BASE_ADDR;
size_t entry_size;
for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ )
{
int j;
max_index = max_indices[i];
entry_size = entry_sizes[i];
base_addr = entries[i];
orig_base_addr = orig_entries[i];
HDassert( base_addr );
HDassert( orig_base_addr );
for ( j = 0; j <= max_index; j++ )
{
int k;
/* one can argue that we should fill the header with garbage.
* If this is desired, we can simply comment out the header
* initialization - the headers will be full of garbage soon
* enough.
*/
base_addr[j].header.addr = (haddr_t)0;
base_addr[j].header.size = (size_t)0;
base_addr[j].header.type = NULL;
base_addr[j].header.is_dirty = FALSE;
base_addr[j].header.is_protected = FALSE;
base_addr[j].header.is_read_only = FALSE;
base_addr[j].header.ro_ref_count = FALSE;
base_addr[j].header.next = NULL;
base_addr[j].header.prev = NULL;
base_addr[j].header.aux_next = NULL;
base_addr[j].header.aux_prev = NULL;
base_addr[j].self = &(base_addr[j]);
base_addr[j].cache_ptr = NULL;
base_addr[j].addr = addr;
base_addr[j].at_main_addr = TRUE;
base_addr[j].main_addr = addr;
base_addr[j].alt_addr = alt_addr;
base_addr[j].size = entry_size;
base_addr[j].type = i;
base_addr[j].index = j;
base_addr[j].reads = 0;
base_addr[j].writes = 0;
base_addr[j].is_dirty = FALSE;
base_addr[j].is_protected = FALSE;
base_addr[j].is_read_only = FALSE;
base_addr[j].ro_ref_count = FALSE;
base_addr[j].is_pinned = FALSE;
base_addr[j].pinning_ref_count = 0;
base_addr[j].num_pins = 0;
for ( k = 0; k < MAX_PINS; k++ )
{
base_addr[j].pin_type[k] = -1;
base_addr[j].pin_idx[k] = -1;
}
base_addr[j].num_flush_ops = 0;
for ( k = 0; k < MAX_FLUSH_OPS; k++ )
{
base_addr[j].flush_ops[k].op_code = FLUSH_OP__NO_OP;
base_addr[j].flush_ops[k].type = -1;
base_addr[j].flush_ops[k].idx = -1;
base_addr[j].flush_ops[k].flag = FALSE;
base_addr[j].flush_ops[k].size = 0;
}
base_addr[j].flush_op_self_resize_in_progress = FALSE;
base_addr[j].loaded = FALSE;
base_addr[j].cleared = FALSE;
base_addr[j].flushed = FALSE;
base_addr[j].destroyed = FALSE;
base_addr[j].flush_dep_npar = 0;
base_addr[j].flush_dep_nchd = 0;
base_addr[j].flush_dep_ndirty_chd = 0;
base_addr[j].pinned_from_client = FALSE;
base_addr[j].pinned_from_cache = FALSE;
base_addr[j].flush_order = 0;
base_addr[j].notify_after_insert_count = 0;
base_addr[j].notify_before_evict_count = 0;
addr += (haddr_t)entry_size;
alt_addr += (haddr_t)entry_size;
} /* end for */
/* Make copy of entries in base_addr for later */
HDmemcpy(orig_base_addr, base_addr, (size_t)(max_index + 1) * sizeof( *base_addr ));
} /* end for */
/* Indicate that we've made a copy for later */
orig_entry_arrays_init = TRUE;
} /* end if */
else {
for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ )
{
max_index = max_indices[i];
base_addr = entries[i];
orig_base_addr = orig_entries[i];
/* Make copy of entries in base_addr for later */
HDmemcpy(base_addr, orig_base_addr, (size_t)(max_index + 1) * sizeof( *base_addr ));
} /* end for */
} /* end else */
return;
} /* reset_entries() */
/*-------------------------------------------------------------------------
* Function: resize_entry
*
* Purpose: Given a pointer to a cache, an entry type, an index, and
* a new size, set the size of the target entry to the new size.
*
* Note that at present, the type of the entry must be
* VARIABLE_ENTRY_TYPE.
*
* Do nothing if pass is false on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 1/11/08
*
*-------------------------------------------------------------------------
*/
void
resize_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx,
size_t new_size,
hbool_t in_cache)
{
test_entry_t * base_addr;
test_entry_t * entry_ptr;
herr_t result;
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( type == VARIABLE_ENTRY_TYPE );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
HDassert( ( 0 < new_size ) && ( new_size <= entry_sizes[type] ) );
if ( pass ) {
if ( in_cache ) {
H5C_t *cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr );
if ( ! entry_in_cache(cache_ptr, type, idx) ) {
pass = FALSE;
failure_mssg = "entry to be resized pinned is not in cache.";
} else {
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr->cache_ptr == cache_ptr );
HDassert( entry_ptr == entry_ptr->self );
if ( ! ( entry_ptr->header.is_pinned || entry_ptr->header.is_protected ) ) {
pass = FALSE;
failure_mssg = "entry to be resized is not pinned or protected.";
} else {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->size = new_size;
result = H5C_resize_entry((void *)entry_ptr, new_size);
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0
&& entry_ptr->flush_dep_ndirty_chd == 0
&& !was_dirty)
mark_flush_dep_dirty(entry_ptr);
if ( result != SUCCEED ) {
pass = FALSE;
failure_mssg = "error(s) in H5C_resize_entry().";
} else {
HDassert( entry_ptr->size = (entry_ptr->header).size );
}
}
}
} else {
protect_entry(file_ptr, type, idx);
resize_entry(file_ptr, type, idx, new_size, TRUE);
unprotect_entry(file_ptr, type, idx, H5C__DIRTIED_FLAG);
}
}
return;
} /* resize_entry() */
/*-------------------------------------------------------------------------
* Function: verify_clean
*
* Purpose: Verify that all cache entries are marked as clean. If any
* are not, set pass to FALSE.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
verify_clean(void)
{
int i;
int j;
int dirty_count = 0;
int32_t max_index;
test_entry_t * base_addr;
if ( pass ) {
for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ )
{
max_index = max_indices[i];
base_addr = entries[i];
HDassert( base_addr );
for ( j = 0; j <= max_index; j++ )
{
if ( ( base_addr[j].header.is_dirty ) ||
( base_addr[j].is_dirty ) ) {
dirty_count++;
}
}
}
if ( dirty_count > 0 ) {
pass = FALSE;
failure_mssg = "verify_clean() found dirty entry(s).";
}
}
return;
} /* verify_clean() */
/*-------------------------------------------------------------------------
* Function: verify_entry_status
*
* Purpose: Verify that a list of entries have the expected status.
* If any discrepencies are found, set the failure message
* and set pass to FALSE.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 10/8/04
*
*-------------------------------------------------------------------------
*/
void
verify_entry_status(H5C_t * cache_ptr,
int tag,
int num_entries,
struct expected_entry_status expected[])
{
static char msg[256];
int i;
i = 0;
while ( ( pass ) && ( i < num_entries ) )
{
test_entry_t * base_addr = entries[expected[i].entry_type];
test_entry_t * entry_ptr = &(base_addr[expected[i].entry_index]);
hbool_t in_cache = FALSE; /* will set to TRUE if necessary */
unsigned u; /* Local index variable */
if ( ( ! expected[i].in_cache ) &&
( ( expected[i].is_dirty ) ||
( expected[i].is_protected ) ||
( expected[i].is_pinned ) ) ) {
pass = FALSE;
sprintf(msg, "%d: Contradictory data in expected[%d].\n", tag, i);
failure_mssg = msg;
}
if ( pass ) {
in_cache = entry_in_cache(cache_ptr, expected[i].entry_type,
expected[i].entry_index);
if ( in_cache != expected[i].in_cache ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) in cache actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)in_cache,
(int)expected[i].in_cache);
failure_mssg = msg;
}
}
if ( pass ) {
if ( entry_ptr->size != expected[i].size ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) size actual/expected = %ld/%ld.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(long)(entry_ptr->size),
(long)expected[i].size);
failure_mssg = msg;
}
}
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.size != expected[i].size ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header size actual/expected = %ld/%ld.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(long)(entry_ptr->header.size),
(long)expected[i].size);
failure_mssg = msg;
}
}
if ( pass ) {
if ( entry_ptr->at_main_addr != expected[i].at_main_addr ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) at main addr actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->at_main_addr),
(int)expected[i].at_main_addr);
failure_mssg = msg;
}
}
if ( pass ) {
if ( entry_ptr->is_dirty != expected[i].is_dirty ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) is_dirty actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->is_dirty),
(int)expected[i].is_dirty);
failure_mssg = msg;
}
}
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.is_dirty != expected[i].is_dirty ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header is_dirty actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->header.is_dirty),
(int)expected[i].is_dirty);
failure_mssg = msg;
}
}
if ( pass ) {
if ( entry_ptr->is_protected != expected[i].is_protected ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) is_protected actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->is_protected),
(int)expected[i].is_protected);
failure_mssg = msg;
}
}
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.is_protected != expected[i].is_protected ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header is_protected actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->header.is_protected),
(int)expected[i].is_protected);
failure_mssg = msg;
}
}
if ( pass ) {
if ( entry_ptr->is_pinned != expected[i].is_pinned ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) is_pinned actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->is_pinned),
(int)expected[i].is_pinned);
failure_mssg = msg;
}
}
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.is_pinned != expected[i].is_pinned ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header is_pinned actual/expected = %d/%d.\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->header.is_pinned),
(int)expected[i].is_pinned);
failure_mssg = msg;
}
}
if ( pass ) {
if ( ( entry_ptr->loaded != expected[i].loaded ) ||
( entry_ptr->cleared != expected[i].cleared ) ||
( entry_ptr->flushed != expected[i].flushed ) ||
( entry_ptr->destroyed != expected[i].destroyed ) ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d,%d) loaded = %d(%d), clrd = %d(%d), flshd = %d(%d), dest = %d(%d)\n",
tag,
(int)expected[i].entry_type,
(int)expected[i].entry_index,
(int)(entry_ptr->loaded),
(int)(expected[i].loaded),
(int)(entry_ptr->cleared),
(int)(expected[i].cleared),
(int)(entry_ptr->flushed),
(int)(expected[i].flushed),
(int)(entry_ptr->destroyed),
(int)(expected[i].destroyed));
failure_mssg = msg;
}
}
/* Check flush dependency fields */
/* # of flush dependency parents */
if ( pass ) {
if ( entry_ptr->flush_dep_npar != expected[i].flush_dep_npar ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_npar actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_npar,
expected[i].flush_dep_npar);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_nparents != expected[i].flush_dep_npar ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_nparents actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_nparents,
expected[i].flush_dep_npar);
failure_mssg = msg;
} /* end if */
} /* end if */
/* Flush dependency parent type & index. Note this algorithm assumes
* that the parents in both arrays are in the same order. */
if ( pass ) {
for ( u = 0; u < entry_ptr->flush_dep_npar; u++ ) {
if ( entry_ptr->flush_dep_par_type[u] != expected[i].flush_dep_par_type[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_type[%u] actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
entry_ptr->flush_dep_par_type[u],
expected[i].flush_dep_par_type[u]);
failure_mssg = msg;
} /* end if */
} /* end for */
} /* end if */
if ( pass ) {
for ( u = 0; u < entry_ptr->flush_dep_npar; u++ ) {
if ( entry_ptr->flush_dep_par_idx[u] != expected[i].flush_dep_par_idx[u] ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_par_idx[%u] actual/expected = %d/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
u,
entry_ptr->flush_dep_par_idx[u],
expected[i].flush_dep_par_idx[u]);
failure_mssg = msg;
} /* end if */
} /* end for */
} /* end if */
/* # of flush dependency children and dirty children */
if ( pass ) {
if ( entry_ptr->flush_dep_nchd != expected[i].flush_dep_nchd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_nchd actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_nchd,
expected[i].flush_dep_nchd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_nchildren != expected[i].flush_dep_nchd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_nchildren actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_nchildren,
expected[i].flush_dep_nchd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( pass ) {
if ( entry_ptr->flush_dep_ndirty_chd != expected[i].flush_dep_ndirty_chd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_dep_ndirty_chd actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_dep_ndirty_chd,
expected[i].flush_dep_ndirty_chd);
failure_mssg = msg;
} /* end if */
} /* end if */
if ( ( pass ) && ( in_cache ) ) {
if ( entry_ptr->header.flush_dep_ndirty_children != expected[i].flush_dep_ndirty_chd ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) header flush_dep_ndirty_children actual/expected = %u/%u.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->header.flush_dep_ndirty_children,
expected[i].flush_dep_ndirty_chd);
failure_mssg = msg;
} /* end if */
} /* end if */
/* Flush dependency flush order */
if ( pass ) {
if ( expected[i].flush_order >= 0 && entry_ptr->flush_order != (unsigned)expected[i].flush_order ) {
pass = FALSE;
sprintf(msg,
"%d entry (%d, %d) flush_order actual/expected = %u/%d.\n",
tag,
expected[i].entry_type,
expected[i].entry_index,
entry_ptr->flush_order,
expected[i].flush_order);
failure_mssg = msg;
} /* end if */
} /* end if */
i++;
} /* while */
return;
} /* verify_entry_status() */
/*-------------------------------------------------------------------------
* Function: verify_unprotected
*
* Purpose: Verify that no cache entries are marked as protected. If
* any are, set pass to FALSE.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/10/04
*
*-------------------------------------------------------------------------
*/
void
verify_unprotected(void)
{
int i;
int j;
int protected_count = 0;
int32_t max_index;
test_entry_t * base_addr;
if ( pass ) {
for ( i = 0; i < NUMBER_OF_ENTRY_TYPES; i++ )
{
max_index = max_indices[i];
base_addr = entries[i];
HDassert( base_addr );
for ( j = 0; j <= max_index; j++ )
{
HDassert( base_addr[j].header.is_protected ==
base_addr[j].is_protected );
if ( ( base_addr[j].header.is_protected ) ||
( base_addr[j].is_protected ) ) {
protected_count++;
}
}
}
if ( protected_count > 0 ) {
pass = FALSE;
failure_mssg = "verify_unprotected() found protected entry(s).";
}
}
return;
} /* verify_unprotected() */
/*-------------------------------------------------------------------------
* Function: setup_cache()
*
* Purpose: Allocate a cache of the desired size and configure it for
* use in the test bed. Return a pointer to the new cache
* structure.
*
* Return: Pointer to new cache, or NULL on failure.
*
* Programmer: John Mainzer
* 6/11/04
*
*-------------------------------------------------------------------------
*/
H5F_t *
setup_cache(size_t max_cache_size,
size_t min_clean_size)
{
const char * fcn_name = "setup_cache()";
char filename[512];
hbool_t show_progress = FALSE;
hbool_t verbose = TRUE;
int mile_stone = 1;
hid_t fid = -1;
H5F_t * file_ptr = NULL;
H5C_t * cache_ptr = NULL;
H5F_t * ret_val = NULL;
haddr_t actual_base_addr;
hid_t fapl_id = H5P_DEFAULT;
if ( show_progress ) /* 1 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
saved_fid = -1;
/* setup the file name */
if ( pass ) {
if ( h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename))
== NULL ) {
pass = FALSE;
failure_mssg = "h5_fixname() failed.\n";
}
}
if ( show_progress ) /* 2 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( ( pass ) && ( try_core_file_driver ) ) {
if ( (fapl_id = H5Pcreate(H5P_FILE_ACCESS)) == FAIL ) {
pass = FALSE;
failure_mssg = "H5Pcreate(H5P_FILE_ACCESS) failed.\n";
}
else if ( H5Pset_fapl_core(fapl_id, MAX_ADDR, FALSE) < 0 ) {
H5Pclose(fapl_id);
fapl_id = H5P_DEFAULT;
pass = FALSE;
failure_mssg = "H5P_set_fapl_core() failed.\n";
}
else if ( (fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))
< 0 ) {
core_file_driver_failed = TRUE;
if ( verbose ) {
HDfprintf(stdout, "%s: H5Fcreate() with CFD failed.\n", fcn_name);
}
} else {
saved_fapl_id = fapl_id;
}
}
if ( show_progress ) /* 3 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
/* if we either aren't using the core file driver, or a create
* with the core file driver failed, try again with a regular file.
* If this fails, we are cooked.
*/
if ( ( pass ) && ( fid < 0 ) ) {
fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id);
saved_fid = fid;
if ( fid < 0 ) {
pass = FALSE;
failure_mssg = "H5Fcreate() failed.";
if ( verbose ) {
HDfprintf(stdout, "%s: H5Fcreate() failed.\n", fcn_name);
}
}
}
if ( show_progress ) /* 4 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( pass ) {
HDassert( fid >= 0 );
saved_fid = fid;
if ( H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0 ) {
pass = FALSE;
failure_mssg = "H5Fflush() failed.";
if ( verbose ) {
HDfprintf(stdout, "%s: H5Fflush() failed.\n", fcn_name);
}
} else {
file_ptr = (H5F_t *)H5I_object_verify(fid, H5I_FILE);
if ( file_ptr == NULL ) {
pass = FALSE;
failure_mssg = "Can't get file_ptr.";
if ( verbose ) {
HDfprintf(stdout, "%s: H5Fflush() failed.\n", fcn_name);
}
}
}
}
if ( show_progress ) /* 5 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( pass ) {
/* A bit of fancy footwork here:
*
* The call to H5Fcreate() allocates an instance of H5C_t,
* initializes it, and stores its address in f->shared->cache.
*
* We don't want to use this cache, as it has a bunch of extra
* initialization that may change over time, and in any case
* it will not in general be configured the way we want it.
*
* We used to deal with this problem by storing the file pointer
* in another instance of H5C_t, and then ignoring the original
* version. However, this strategy doesn't work any more, as
* we can't store the file pointer in the instance of H5C_t,
* and we have modified many cache routines to use a file
* pointer to look up the target cache.
*
* Thus we now make note of the address of the instance of
* H5C_t created by the call to H5Fcreate(), set
* file_ptr->shared->cache to NULL, call H5C_create()
* to allocate a new instance of H5C_t for test purposes,
* and store than new instance's address in
* file_ptr->shared->cache.
*
* On shut down, we call H5C_dest on our instance of H5C_t,
* set file_ptr->shared->cache to point to the original
* instance, and then close the file normally.
*/
HDassert( saved_cache == NULL );
saved_cache = file_ptr->shared->cache;
file_ptr->shared->cache = NULL;
cache_ptr = H5C_create(max_cache_size,
min_clean_size,
(NUMBER_OF_ENTRY_TYPES - 1),
(const char **)entry_type_names,
check_write_permitted,
TRUE,
NULL,
NULL);
file_ptr->shared->cache = cache_ptr;
}
if ( show_progress ) /* 6 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( pass ) {
if ( cache_ptr == NULL ) {
pass = FALSE;
failure_mssg = "H5C_create() failed.";
if ( verbose ) {
HDfprintf(stdout, "%s: H5C_create() failed.\n", fcn_name);
}
} else if ( cache_ptr->magic != H5C__H5C_T_MAGIC ) {
pass = FALSE;
failure_mssg = "Bad cache_ptr magic.";
if ( verbose ) {
HDfprintf(stdout, "%s: Bad cache_ptr magic.\n", fcn_name);
}
}
}
if ( show_progress ) /* 7 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( pass ) { /* allocate space for test entries */
actual_base_addr = H5MF_alloc(file_ptr, H5FD_MEM_DEFAULT, H5P_DEFAULT,
(hsize_t)(ADDR_SPACE_SIZE + BASE_ADDR));
if ( actual_base_addr == HADDR_UNDEF ) {
pass = FALSE;
failure_mssg = "H5MF_alloc() failed.";
if ( verbose ) {
HDfprintf(stdout, "%s: H5MF_alloc() failed.\n", fcn_name);
}
} else if ( actual_base_addr > BASE_ADDR ) {
/* If this happens, must increase BASE_ADDR so that the
* actual_base_addr is <= BASE_ADDR. This should only happen
* if the size of the superblock is increase.
*/
pass = FALSE;
failure_mssg = "actual_base_addr > BASE_ADDR";
if ( verbose ) {
HDfprintf(stdout, "%s: actual_base_addr > BASE_ADDR.\n",
fcn_name);
}
}
saved_actual_base_addr = actual_base_addr;
}
if ( show_progress ) /* 8 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
if ( pass ) {
/* Need to set this else all cache tests will fail */
cache_ptr->ignore_tags = TRUE;
H5C_stats__reset(cache_ptr);
ret_val = file_ptr;
}
if ( show_progress ) /* 9 */
HDfprintf(stdout, "%s() - %0d -- pass = %d\n",
fcn_name, mile_stone++, (int)pass);
return(ret_val);
} /* setup_cache() */
/*-------------------------------------------------------------------------
* Function: takedown_cache()
*
* Purpose: Flush the specified cache and disable it. If requested,
* dump stats first. If pass is FALSE, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 9/14/07
*
*-------------------------------------------------------------------------
*/
void
takedown_cache(H5F_t * file_ptr,
hbool_t dump_stats,
hbool_t dump_detailed_stats)
{
char filename[512];
if ( file_ptr != NULL ) {
H5C_t * cache_ptr = file_ptr->shared->cache;
if ( dump_stats ) {
H5C_stats(cache_ptr, "test cache", dump_detailed_stats);
}
flush_cache(file_ptr, TRUE, FALSE, FALSE);
H5C_dest(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT);
if ( saved_cache != NULL ) {
file_ptr->shared->cache = saved_cache;
saved_cache = NULL;
}
}
if ( saved_fapl_id != H5P_DEFAULT ) {
H5Pclose(saved_fapl_id);
saved_fapl_id = H5P_DEFAULT;
}
if ( saved_fid != -1 ) {
if ( H5F_addr_defined(saved_actual_base_addr) ) {
if ( NULL == file_ptr ) {
file_ptr = (H5F_t *)H5I_object_verify(saved_fid, H5I_FILE);
HDassert ( file_ptr );
}
H5MF_xfree(file_ptr, H5FD_MEM_DEFAULT, H5P_DEFAULT, saved_actual_base_addr,
(hsize_t)(ADDR_SPACE_SIZE + BASE_ADDR));
saved_actual_base_addr = HADDR_UNDEF;
}
if ( H5Fclose(saved_fid) < 0 ) {
pass = FALSE;
failure_mssg = "couldn't close test file.";
} else {
saved_fid = -1;
}
if ( ( ! try_core_file_driver ) || ( core_file_driver_failed ) ) {
if ( h5_fixname(FILENAME[0], H5P_DEFAULT, filename, sizeof(filename))
== NULL ) {
pass = FALSE;
failure_mssg = "h5_fixname() failed.\n";
}
if ( HDremove(filename) < 0 ) {
pass = FALSE;
failure_mssg = "couldn't delete test file.";
}
}
}
return;
} /* takedown_cache() */
/*-------------------------------------------------------------------------
* Function: expunge_entry()
*
* Purpose: Expunge the entry indicated by the type and index.
*
*
* Return: void
*
* Programmer: John Mainzer
* 7/6/06
*
*-------------------------------------------------------------------------
*/
void
expunge_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx)
{
/* const char * fcn_name = "expunge_entry()"; */
herr_t result;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
if ( pass ) {
#ifndef NDEBUG
H5C_t * cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr );
#endif /* NDEBUG */
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->cache_ptr == cache_ptr );
HDassert( ! ( entry_ptr->header.is_protected ) );
HDassert( ! ( entry_ptr->is_protected ) );
HDassert( ! ( entry_ptr->header.is_pinned ) );
HDassert( ! ( entry_ptr->is_pinned ) );
result = H5C_expunge_entry(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT,
&(types[type]), entry_ptr->addr, H5C__NO_FLAGS_SET);
if ( result < 0 ) {
pass = FALSE;
failure_mssg = "error in H5C_expunge_entry().";
}
}
return;
} /* expunge_entry() */
/*-------------------------------------------------------------------------
* Function: flush_cache()
*
* Purpose: Flush the specified cache, destroying all entries if
requested. If requested, dump stats first.
*
* Return: void
*
* Programmer: John Mainzer
* 6/23/04
*
*-------------------------------------------------------------------------
*/
void
flush_cache(H5F_t * file_ptr,
hbool_t destroy_entries,
hbool_t dump_stats,
hbool_t dump_detailed_stats)
{
const char * fcn_name = "flush_cache()";
hbool_t verbose = FALSE;
verify_unprotected();
if(pass) {
H5C_t * cache_ptr = NULL;
herr_t result = 0;
HDassert(file_ptr);
cache_ptr = file_ptr->shared->cache;
if(destroy_entries) {
result = H5C_flush_cache(file_ptr, H5P_DATASET_XFER_DEFAULT,
H5P_DATASET_XFER_DEFAULT, H5C__FLUSH_INVALIDATE_FLAG);
}
else {
result = H5C_flush_cache(file_ptr, H5P_DATASET_XFER_DEFAULT,
H5P_DATASET_XFER_DEFAULT, H5C__NO_FLAGS_SET);
}
if(dump_stats) {
H5C_stats(cache_ptr, "test cache", dump_detailed_stats);
}
if(result < 0) {
pass = FALSE;
failure_mssg = "error in H5C_flush_cache().";
}
else if((destroy_entries) && ((cache_ptr->index_len != 0)
|| (cache_ptr->index_size != 0)
|| (cache_ptr->clean_index_size != 0)
|| (cache_ptr->dirty_index_size != 0))) {
if(verbose) {
HDfprintf(stdout,
"%s: unexpected il/is/cis/dis = %lld/%lld/%lld/%lld.\n",
fcn_name,
(long long)(cache_ptr->index_len),
(long long)(cache_ptr->index_size),
(long long)(cache_ptr->clean_index_size),
(long long)(cache_ptr->dirty_index_size));
}
pass = FALSE;
failure_mssg = "non zero index len/sizes after H5C_flush_cache() with invalidate.";
}
}
return;
} /* flush_cache() */
/*-------------------------------------------------------------------------
* Function: insert_entry()
*
* Purpose: Insert the entry indicated by the type and index.
*
* Do nothing if pass is false.
*
* Return: void
*
* Programmer: John Mainzer
* 6/16/04
*
*-------------------------------------------------------------------------
*/
void
insert_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx,
unsigned int flags)
{
H5C_t * cache_ptr;
herr_t result;
hbool_t insert_pinned;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( !(entry_ptr->is_protected) );
HDassert( entry_ptr->flush_dep_npar == 0 );
HDassert( entry_ptr->flush_dep_nchd == 0 );
insert_pinned = (hbool_t)((flags & H5C__PIN_ENTRY_FLAG) != 0 );
entry_ptr->is_dirty = TRUE;
result = H5C_insert_entry(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT,
&(types[type]), entry_ptr->addr, (void *)entry_ptr, flags);
if ( ( result < 0 ) ||
( entry_ptr->header.is_protected ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
pass = FALSE;
failure_mssg = "error in H5C_insert().";
#if 0 /* This is useful debugging code. Lets keep it around. */
HDfprintf(stdout, "result = %d\n", (int)result);
HDfprintf(stdout, "entry_ptr->header.is_protected = %d\n",
(int)(entry_ptr->header.is_protected));
HDfprintf(stdout,
"entry_ptr->header.type != &(types[type]) = %d\n",
(int)(entry_ptr->header.type != &(types[type])));
HDfprintf(stdout,
"entry_ptr->size != entry_ptr->header.size = %d\n",
(int)(entry_ptr->size != entry_ptr->header.size));
HDfprintf(stdout,
"entry_ptr->addr != entry_ptr->header.addr = %d\n",
(int)(entry_ptr->addr != entry_ptr->header.addr));
#endif
}
HDassert( entry_ptr->cache_ptr == NULL );
entry_ptr->cache_ptr = cache_ptr;
if ( insert_pinned ) {
HDassert( entry_ptr->header.is_pinned );
} else {
HDassert( ! ( entry_ptr->header.is_pinned ) );
}
entry_ptr->is_pinned = insert_pinned;
entry_ptr->pinned_from_client = insert_pinned;
HDassert( entry_ptr->header.is_dirty );
HDassert( ((entry_ptr->header).type)->id == type );
}
return;
} /* insert_entry() */
/*-------------------------------------------------------------------------
* Function: mark_entry_dirty()
*
* Purpose: Mark the specified entry as dirty.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 3/28/06
*
*-------------------------------------------------------------------------
*/
void
mark_entry_dirty(int32_t type,
int32_t idx)
{
herr_t result;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
hbool_t was_dirty;
if ( pass ) {
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.is_protected ||
entry_ptr->header.is_pinned );
was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0
&& entry_ptr->flush_dep_ndirty_chd == 0
&& !was_dirty)
mark_flush_dep_dirty(entry_ptr);
result = H5C_mark_entry_dirty((void *)entry_ptr);
if ( ( result < 0 ) ||
( !entry_ptr->header.is_protected && !entry_ptr->header.is_pinned ) ||
( entry_ptr->header.is_protected && !entry_ptr->header.dirtied ) ||
( !entry_ptr->header.is_protected && !entry_ptr->header.is_dirty ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
pass = FALSE;
failure_mssg = "error in H5C_mark_entry_dirty().";
}
HDassert( ((entry_ptr->header).type)->id == type );
}
return;
} /* mark_entry_dirty() */
/*-------------------------------------------------------------------------
* Function: move_entry()
*
* Purpose: Move the entry indicated by the type and index to its
* main or alternate address as indicated. If the entry is
* already at the desired entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 6/21/04
*
*-------------------------------------------------------------------------
*/
void
move_entry(H5C_t * cache_ptr,
int32_t type,
int32_t idx,
hbool_t main_addr)
{
herr_t result;
hbool_t done = TRUE; /* will set to FALSE if we have work to do */
haddr_t old_addr = HADDR_UNDEF;
haddr_t new_addr = HADDR_UNDEF;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
if ( pass ) {
HDassert( cache_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->cache_ptr == cache_ptr );
HDassert( !(entry_ptr->is_protected) );
HDassert( !(entry_ptr->header.is_protected) );
if ( entry_ptr->at_main_addr && !main_addr ) {
/* move to alt addr */
HDassert( entry_ptr->addr == entry_ptr->main_addr );
done = FALSE;
old_addr = entry_ptr->addr;
new_addr = entry_ptr->alt_addr;
} else if ( !(entry_ptr->at_main_addr) && main_addr ) {
/* move to main addr */
HDassert( entry_ptr->addr == entry_ptr->alt_addr );
done = FALSE;
old_addr = entry_ptr->addr;
new_addr = entry_ptr->main_addr;
}
if ( ! done ) {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0
&& entry_ptr->flush_dep_ndirty_chd == 0
&& !was_dirty)
mark_flush_dep_dirty(entry_ptr);
result = H5C_move_entry(cache_ptr, &(types[type]),
old_addr, new_addr);
}
if ( ! done ) {
if ( ( result < 0 ) ||
( ( ! ( entry_ptr->header.destroy_in_progress ) ) &&
( entry_ptr->header.addr != new_addr ) ) ) {
pass = FALSE;
failure_mssg = "error in H5C_move_entry().";
} else {
entry_ptr->addr = new_addr;
entry_ptr->at_main_addr = main_addr;
}
}
HDassert( ((entry_ptr->header).type)->id == type );
HDassert( entry_ptr->header.is_dirty );
HDassert( entry_ptr->is_dirty );
}
return;
} /* move_entry() */
/*-------------------------------------------------------------------------
* Function: protect_entry()
*
* Purpose: Protect the entry indicated by the type and index.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/11/04
*
*-------------------------------------------------------------------------
*/
void
protect_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx)
{
H5C_t * cache_ptr;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
H5C_cache_entry_t * cache_entry_ptr;
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( !(entry_ptr->is_protected) );
cache_entry_ptr = (H5C_cache_entry_t *)H5C_protect(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT,
&(types[type]), entry_ptr->addr, NULL, H5C__NO_FLAGS_SET);
if ( ( cache_entry_ptr != (void *)entry_ptr ) ||
( !(entry_ptr->header.is_protected) ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
#if 0
/* I've written the following debugging code several times
* now. Lets keep it around so I don't have to write it
* again.
* - JRM
*/
HDfprintf(stdout, "( cache_entry_ptr != (void *)entry_ptr ) = %d\n",
(int)( cache_entry_ptr != (void *)entry_ptr ));
HDfprintf(stdout, "cache_entry_ptr = 0x%lx, entry_ptr = 0x%lx\n",
(long)cache_entry_ptr, (long)entry_ptr);
HDfprintf(stdout, "entry_ptr->header.is_protected = %d\n",
(int)(entry_ptr->header.is_protected));
HDfprintf(stdout,
"( entry_ptr->header.type != &(types[type]) ) = %d\n",
(int)( entry_ptr->header.type != &(types[type]) ));
HDfprintf(stdout,
"entry_ptr->size = %d, entry_ptr->header.size = %d\n",
(int)(entry_ptr->size), (int)(entry_ptr->header.size));
HDfprintf(stdout,
"entry_ptr->addr = %d, entry_ptr->header.addr = %d\n",
(int)(entry_ptr->addr), (int)(entry_ptr->header.addr));
#endif
pass = FALSE;
failure_mssg = "error in H5C_protect().";
} else {
HDassert( ( entry_ptr->cache_ptr == NULL ) ||
( entry_ptr->cache_ptr == cache_ptr ) );
entry_ptr->cache_ptr = cache_ptr;
entry_ptr->is_protected = TRUE;
}
HDassert( ((entry_ptr->header).type)->id == type );
}
return;
} /* protect_entry() */
/*-------------------------------------------------------------------------
* Function: protect_entry_ro()
*
* Purpose: Do a read only protect the entry indicated by the type
* and index.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 4/1/07
*
*-------------------------------------------------------------------------
*/
void
protect_entry_ro(H5F_t * file_ptr,
int32_t type,
int32_t idx)
{
H5C_t *cache_ptr;
test_entry_t *base_addr;
test_entry_t *entry_ptr;
H5C_cache_entry_t * cache_entry_ptr;
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr );
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( ( ! ( entry_ptr->is_protected ) ) ||
( ( entry_ptr->is_read_only ) &&
( entry_ptr->ro_ref_count > 0 ) ) );
cache_entry_ptr = (H5C_cache_entry_t *)H5C_protect(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT,
&(types[type]), entry_ptr->addr, NULL, H5C__READ_ONLY_FLAG);
if ( ( cache_entry_ptr != (void *)entry_ptr ) ||
( !(entry_ptr->header.is_protected) ) ||
( !(entry_ptr->header.is_read_only) ) ||
( entry_ptr->header.ro_ref_count <= 0 ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
pass = FALSE;
failure_mssg = "error in read only H5C_protect().";
} else {
HDassert( ( entry_ptr->cache_ptr == NULL ) ||
( entry_ptr->cache_ptr == cache_ptr ) );
entry_ptr->cache_ptr = cache_ptr;
entry_ptr->is_protected = TRUE;
entry_ptr->is_read_only = TRUE;
entry_ptr->ro_ref_count++;
}
HDassert( ((entry_ptr->header).type)->id == type );
}
return;
} /* protect_entry_ro() */
/*-------------------------------------------------------------------------
* Function: pin_entry()
*
* Purpose: Pin the entry indicated by the type and index.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: Quincey Koziol
* 3/17/09
*
*-------------------------------------------------------------------------
*/
void
pin_entry(int32_t type,
int32_t idx)
{
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
if ( pass ) {
test_entry_t * base_addr;
test_entry_t * entry_ptr;
herr_t result;
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->is_protected );
HDassert( !(entry_ptr->pinned_from_client) );
result = H5C_pin_protected_entry((void *)entry_ptr);
if ( result < 0 ) {
pass = FALSE;
failure_mssg = "H5C_pin_protected_entry() reports failure.";
} else if ( ! ( entry_ptr->header.is_pinned ) ) {
pass = FALSE;
failure_mssg = "entry not pinned when it should be.";
} else {
entry_ptr->pinned_from_client = TRUE;
entry_ptr->is_pinned = TRUE;
}
} /* end if */
return;
} /* pin_entry() */
/*-------------------------------------------------------------------------
* Function: unpin_entry()
*
* Purpose: Unpin the entry indicated by the type and index.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 3/28/06
*
*-------------------------------------------------------------------------
*/
void
unpin_entry(int32_t type,
int32_t idx)
{
herr_t result;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
if ( pass ) {
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.is_pinned );
HDassert( entry_ptr->header.pinned_from_client );
HDassert( entry_ptr->is_pinned );
HDassert( entry_ptr->pinned_from_client );
result = H5C_unpin_entry(entry_ptr);
if ( ( result < 0 ) ||
( entry_ptr->header.pinned_from_client ) ||
( entry_ptr->header.is_pinned && !entry_ptr->header.pinned_from_cache ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
pass = FALSE;
failure_mssg = "error in H5C_unpin().";
}
entry_ptr->pinned_from_client = FALSE;
entry_ptr->is_pinned = entry_ptr->pinned_from_cache;
HDassert( ((entry_ptr->header).type)->id == type );
}
return;
} /* unpin_entry() */
/*-------------------------------------------------------------------------
* Function: unprotect_entry()
*
* Purpose: Unprotect the entry indicated by the type and index.
*
* Do nothing if pass is FALSE on entry.
*
* Return: void
*
* Programmer: John Mainzer
* 6/12/04
*
*-------------------------------------------------------------------------
*/
void
unprotect_entry(H5F_t * file_ptr,
int32_t type,
int32_t idx,
unsigned int flags)
{
herr_t result;
hbool_t pin_flag_set;
hbool_t unpin_flag_set;
test_entry_t * base_addr;
test_entry_t * entry_ptr;
if ( pass ) {
HDassert( ( 0 <= type ) && ( type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= idx ) && ( idx <= max_indices[type] ) );
base_addr = entries[type];
entry_ptr = &(base_addr[idx]);
HDassert( entry_ptr->index == idx );
HDassert( entry_ptr->type == type );
HDassert( entry_ptr == entry_ptr->self );
HDassert( entry_ptr->header.is_protected );
HDassert( entry_ptr->is_protected );
pin_flag_set = (hbool_t)((flags & H5C__PIN_ENTRY_FLAG) != 0 );
unpin_flag_set = (hbool_t)((flags & H5C__UNPIN_ENTRY_FLAG) != 0 );
HDassert ( ! ( pin_flag_set && unpin_flag_set ) );
HDassert ( ( ! pin_flag_set ) || ( ! (entry_ptr->is_pinned) ) );
HDassert ( ( ! unpin_flag_set ) || ( entry_ptr->is_pinned ) );
if(flags & H5C__DIRTIED_FLAG) {
hbool_t was_dirty = entry_ptr->is_dirty;
entry_ptr->is_dirty = TRUE;
if(entry_ptr->flush_dep_npar > 0
&& entry_ptr->flush_dep_ndirty_chd == 0
&& !was_dirty)
mark_flush_dep_dirty(entry_ptr);
} /* end if */
result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, H5P_DATASET_XFER_DEFAULT,
&(types[type]), entry_ptr->addr, (void *)entry_ptr, flags);
if ( ( result < 0 ) ||
( ( entry_ptr->header.is_protected ) &&
( ( ! ( entry_ptr->is_read_only ) ) ||
( entry_ptr->ro_ref_count <= 0 ) ) ) ||
( entry_ptr->header.type != &(types[type]) ) ||
( entry_ptr->size != entry_ptr->header.size ) ||
( entry_ptr->addr != entry_ptr->header.addr ) ) {
pass = FALSE;
failure_mssg = "error in H5C_unprotect().";
}
else
{
if ( entry_ptr->ro_ref_count > 1 ) {
entry_ptr->ro_ref_count--;
} else if ( entry_ptr->ro_ref_count == 1 ) {
entry_ptr->is_protected = FALSE;
entry_ptr->is_read_only = FALSE;
entry_ptr->ro_ref_count = 0;
} else {
entry_ptr->is_protected = FALSE;
}
if ( pin_flag_set ) {
HDassert ( entry_ptr->header.is_pinned );
entry_ptr->pinned_from_client = TRUE;
entry_ptr->is_pinned = TRUE;
} else if ( unpin_flag_set ) {
HDassert ( entry_ptr->header.is_pinned == entry_ptr->header.pinned_from_cache );
entry_ptr->pinned_from_client = FALSE;
entry_ptr->is_pinned = entry_ptr->pinned_from_cache;
}
}
HDassert( ((entry_ptr->header).type)->id == type );
if ( ( flags & H5C__DIRTIED_FLAG ) != 0
&& ( (flags & H5C__DELETED_FLAG) == 0 ) ) {
HDassert( entry_ptr->header.is_dirty );
HDassert( entry_ptr->is_dirty );
}
HDassert( entry_ptr->header.is_protected == entry_ptr->is_protected );
HDassert( entry_ptr->header.is_read_only == entry_ptr->is_read_only );
HDassert( entry_ptr->header.ro_ref_count == entry_ptr->ro_ref_count );
}
return;
} /* unprotect_entry() */
/*-------------------------------------------------------------------------
* Function: row_major_scan_forward()
*
* Purpose: Do a sequence of inserts, protects, unprotects, moves,
* destroys while scanning through the set of entries. If
* pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 6/12/04
*
*-------------------------------------------------------------------------
*/
void
row_major_scan_forward(H5F_t * file_ptr,
int32_t lag,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
hbool_t do_moves,
hbool_t move_to_main_addr,
hbool_t do_destroys,
hbool_t do_mult_ro_protects,
int dirty_destroys,
int dirty_unprotects)
{
const char * fcn_name = "row_major_scan_forward";
H5C_t * cache_ptr;
int32_t type = 0;
int32_t idx;
if ( verbose )
HDfprintf(stdout, "%s(): entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag >= 10 );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
while ( ( pass ) && ( type < NUMBER_OF_ENTRY_TYPES ) )
{
idx = -lag;
while ( ( pass ) && ( idx <= (max_indices[type] + lag) ) )
{
if ( verbose ) {
HDfprintf(stdout, "%d:%d: ", type, idx);
}
if ( ( pass ) && ( do_inserts ) && ( (idx + lag) >= 0 ) &&
( (idx + lag) <= max_indices[type] ) &&
( ((idx + lag) % 2) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, (idx + lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag));
insert_entry(file_ptr, type, (idx + lag), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx + lag - 1) >= 0 ) &&
( (idx + lag - 1) <= max_indices[type] ) &&
( ( (idx + lag - 1) % 3 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx + lag - 1));
protect_entry(file_ptr, type, (idx + lag - 1));
}
if ( ( pass ) && ( (idx + lag - 2) >= 0 ) &&
( (idx + lag - 2) <= max_indices[type] ) &&
( ( (idx + lag - 2) % 3 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag - 2));
unprotect_entry(file_ptr, type, idx+lag-2, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( do_moves ) && ( (idx + lag - 2) >= 0 ) &&
( (idx + lag - 2) <= max_indices[type] ) &&
( ( (idx + lag - 2) % 3 ) == 0 ) ) {
move_entry(cache_ptr, type, (idx + lag - 2),
move_to_main_addr);
}
if ( ( pass ) && ( (idx + lag - 3) >= 0 ) &&
( (idx + lag - 3) <= max_indices[type] ) &&
( ( (idx + lag - 3) % 5 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx + lag - 3));
protect_entry(file_ptr, type, (idx + lag - 3));
}
if ( ( pass ) && ( (idx + lag - 5) >= 0 ) &&
( (idx + lag - 5) <= max_indices[type] ) &&
( ( (idx + lag - 5) % 5 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag - 5));
unprotect_entry(file_ptr, type, idx+lag-5, H5C__NO_FLAGS_SET);
}
if ( do_mult_ro_protects )
{
if ( ( pass ) && ( (idx + lag - 5) >= 0 ) &&
( (idx + lag - 5) < max_indices[type] ) &&
( (idx + lag - 5) % 9 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx + lag - 5));
protect_entry_ro(file_ptr, type, (idx + lag - 5));
}
if ( ( pass ) && ( (idx + lag - 6) >= 0 ) &&
( (idx + lag - 6) < max_indices[type] ) &&
( (idx + lag - 6) % 11 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx + lag - 6));
protect_entry_ro(file_ptr, type, (idx + lag - 6));
}
if ( ( pass ) && ( (idx + lag - 7) >= 0 ) &&
( (idx + lag - 7) < max_indices[type] ) &&
( (idx + lag - 7) % 13 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx + lag - 7));
protect_entry_ro(file_ptr, type, (idx + lag - 7));
}
if ( ( pass ) && ( (idx + lag - 7) >= 0 ) &&
( (idx + lag - 7) < max_indices[type] ) &&
( (idx + lag - 7) % 9 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx + lag - 7));
unprotect_entry(file_ptr, type, (idx + lag - 7), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx + lag - 8) >= 0 ) &&
( (idx + lag - 8) < max_indices[type] ) &&
( (idx + lag - 8) % 11 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx + lag - 8));
unprotect_entry(file_ptr, type, (idx + lag - 8), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx + lag - 9) >= 0 ) &&
( (idx + lag - 9) < max_indices[type] ) &&
( (idx + lag - 9) % 13 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx + lag - 9));
unprotect_entry(file_ptr, type, (idx + lag - 9), H5C__NO_FLAGS_SET);
}
} /* if ( do_mult_ro_protects ) */
if ( ( pass ) && ( idx >= 0 ) && ( idx <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, idx);
protect_entry(file_ptr, type, idx);
}
if ( ( pass ) && ( (idx - lag + 2) >= 0 ) &&
( (idx - lag + 2) <= max_indices[type] ) &&
( ( (idx - lag + 2) % 7 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 2));
unprotect_entry(file_ptr, type, idx-lag+2, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx - lag + 1) >= 0 ) &&
( (idx - lag + 1) <= max_indices[type] ) &&
( ( (idx - lag + 1) % 7 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 1));
protect_entry(file_ptr, type, (idx - lag + 1));
}
if ( do_destroys ) {
if ( ( pass ) && ( (idx - lag) >= 0 ) &&
( ( idx - lag) <= max_indices[type] ) ) {
switch ( (idx - lag) %4 ) {
case 0: /* we just did an insert */
unprotect_entry(file_ptr, type, idx - lag, H5C__NO_FLAGS_SET);
break;
case 1:
if ( (entries[type])[idx-lag].is_dirty ) {
unprotect_entry(file_ptr, type, idx - lag, H5C__NO_FLAGS_SET);
} else {
unprotect_entry(file_ptr, type, idx - lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
break;
case 2: /* we just did an insrt */
unprotect_entry(file_ptr, type, idx - lag, H5C__DELETED_FLAG);
break;
case 3:
if ( (entries[type])[idx-lag].is_dirty ) {
unprotect_entry(file_ptr, type, idx - lag, H5C__DELETED_FLAG);
} else {
unprotect_entry(file_ptr, type, idx - lag,
(dirty_destroys ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET)
| H5C__DELETED_FLAG);
}
break;
default:
HDassert(0); /* this can't happen... */
break;
}
}
} else {
if ( ( pass ) && ( (idx - lag) >= 0 ) &&
( ( idx - lag) <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag));
unprotect_entry(file_ptr, type, idx - lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
}
if ( verbose )
HDfprintf(stdout, "\n");
idx++;
}
type++;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* row_major_scan_forward() */
/*-------------------------------------------------------------------------
* Function: hl_row_major_scan_forward()
*
* Purpose: Do a high locality sequence of inserts, protects, and
* unprotects while scanning through the set of entries.
* If pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 10/21/04
*
*-------------------------------------------------------------------------
*/
void
hl_row_major_scan_forward(H5F_t * file_ptr,
int32_t max_index,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts)
{
const char * fcn_name = "hl_row_major_scan_forward";
H5C_t * cache_ptr;
int32_t type = 0;
int32_t idx;
int32_t i;
int32_t lag = 100;
int32_t local_max_index;
if ( verbose )
HDfprintf(stdout, "%s(): entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag > 5 );
HDassert( max_index >= 200 );
HDassert( max_index <= MAX_ENTRIES );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
while ( ( pass ) && ( type < NUMBER_OF_ENTRY_TYPES ) )
{
idx = -lag;
local_max_index = MIN(max_index, max_indices[type]);
while ( ( pass ) && ( idx <= (local_max_index + lag) ) )
{
if ( ( pass ) && ( do_inserts ) && ( (idx + lag) >= 0 ) &&
( (idx + lag) <= max_indices[type] ) &&
( ((idx + lag) % 2) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, (idx + lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag));
insert_entry(file_ptr, type, (idx + lag), H5C__NO_FLAGS_SET);
}
i = idx;
while ( ( pass ) && ( i >= idx - lag ) && ( i >= 0 ) )
{
if ( ( pass ) && ( i >= 0 ) && ( i <= local_max_index ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, i);
protect_entry(file_ptr, type, i);
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, i);
unprotect_entry(file_ptr, type, i, H5C__NO_FLAGS_SET);
}
i--;
}
if ( verbose )
HDfprintf(stdout, "\n");
idx++;
}
type++;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* hl_row_major_scan_forward() */
/*-------------------------------------------------------------------------
* Function: row_major_scan_backward()
*
* Purpose: Do a sequence of inserts, protects, unprotects, moves,
* destroys while scanning backwards through the set of
* entries. If pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 6/12/04
*
*-------------------------------------------------------------------------
*/
void
row_major_scan_backward(H5F_t * file_ptr,
int32_t lag,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
hbool_t do_moves,
hbool_t move_to_main_addr,
hbool_t do_destroys,
hbool_t do_mult_ro_protects,
int dirty_destroys,
int dirty_unprotects)
{
const char * fcn_name = "row_major_scan_backward";
H5C_t * cache_ptr;
int32_t type = NUMBER_OF_ENTRY_TYPES - 1;
int32_t idx;
if ( verbose )
HDfprintf(stdout, "%s(): Entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag >= 10 );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
while ( ( pass ) && ( type >= 0 ) )
{
idx = max_indices[type] + lag;
while ( ( pass ) && ( idx >= -lag ) )
{
if ( ( pass ) && ( do_inserts ) && ( (idx - lag) >= 0 ) &&
( (idx - lag) <= max_indices[type] ) &&
( ((idx - lag) % 2) == 1 ) &&
( ! entry_in_cache(cache_ptr, type, (idx - lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag));
insert_entry(file_ptr, type, (idx - lag), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx - lag + 1) >= 0 ) &&
( (idx - lag + 1) <= max_indices[type] ) &&
( ( (idx - lag + 1) % 3 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 1));
protect_entry(file_ptr, type, (idx - lag + 1));
}
if ( ( pass ) && ( (idx - lag + 2) >= 0 ) &&
( (idx - lag + 2) <= max_indices[type] ) &&
( ( (idx - lag + 2) % 3 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 2));
unprotect_entry(file_ptr, type, idx-lag+2, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( do_moves ) && ( (idx - lag + 2) >= 0 ) &&
( (idx - lag + 2) <= max_indices[type] ) &&
( ( (idx - lag + 2) % 3 ) == 0 ) ) {
move_entry(cache_ptr, type, (idx - lag + 2),
move_to_main_addr);
}
if ( ( pass ) && ( (idx - lag + 3) >= 0 ) &&
( (idx - lag + 3) <= max_indices[type] ) &&
( ( (idx - lag + 3) % 5 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx - lag + 3));
protect_entry(file_ptr, type, (idx - lag + 3));
}
if ( ( pass ) && ( (idx - lag + 5) >= 0 ) &&
( (idx - lag + 5) <= max_indices[type] ) &&
( ( (idx - lag + 5) % 5 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag + 5));
unprotect_entry(file_ptr, type, idx-lag+5, H5C__NO_FLAGS_SET);
}
if ( do_mult_ro_protects )
{
if ( ( pass ) && ( (idx - lag + 5) >= 0 ) &&
( (idx - lag + 5) < max_indices[type] ) &&
( (idx - lag + 5) % 9 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx - lag + 5));
protect_entry_ro(file_ptr, type, (idx - lag + 5));
}
if ( ( pass ) && ( (idx - lag + 6) >= 0 ) &&
( (idx - lag + 6) < max_indices[type] ) &&
( (idx - lag + 6) % 11 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx - lag + 6));
protect_entry_ro(file_ptr, type, (idx - lag + 6));
}
if ( ( pass ) && ( (idx - lag + 7) >= 0 ) &&
( (idx - lag + 7) < max_indices[type] ) &&
( (idx - lag + 7) % 13 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p-ro, %d, %d) ", type,
(idx - lag + 7));
protect_entry_ro(file_ptr, type, (idx - lag + 7));
}
if ( ( pass ) && ( (idx - lag + 7) >= 0 ) &&
( (idx - lag + 7) < max_indices[type] ) &&
( (idx - lag + 7) % 9 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx - lag + 7));
unprotect_entry(file_ptr, type, (idx - lag + 7), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx - lag + 8) >= 0 ) &&
( (idx - lag + 8) < max_indices[type] ) &&
( (idx - lag + 8) % 11 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx - lag + 8));
unprotect_entry(file_ptr, type, (idx - lag + 8), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx - lag + 9) >= 0 ) &&
( (idx - lag + 9) < max_indices[type] ) &&
( (idx - lag + 9) % 13 == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u-ro, %d, %d) ", type,
(idx - lag + 9));
unprotect_entry(file_ptr, type, (idx - lag + 9), H5C__NO_FLAGS_SET);
}
} /* if ( do_mult_ro_protects ) */
if ( ( pass ) && ( idx >= 0 ) && ( idx <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, idx);
protect_entry(file_ptr, type, idx);
}
if ( ( pass ) && ( (idx + lag - 2) >= 0 ) &&
( (idx + lag - 2) <= max_indices[type] ) &&
( ( (idx + lag - 2) % 7 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag - 2));
unprotect_entry(file_ptr, type, idx+lag-2, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( (idx + lag - 1) >= 0 ) &&
( (idx + lag - 1) <= max_indices[type] ) &&
( ( (idx + lag - 1) % 7 ) == 0 ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, (idx + lag - 1));
protect_entry(file_ptr, type, (idx + lag - 1));
}
if ( do_destroys ) {
if ( ( pass ) && ( (idx + lag) >= 0 ) &&
( ( idx + lag) <= max_indices[type] ) ) {
switch ( (idx + lag) %4 ) {
case 0:
if ( (entries[type])[idx+lag].is_dirty ) {
unprotect_entry(file_ptr, type, idx + lag, H5C__NO_FLAGS_SET);
} else {
unprotect_entry(file_ptr, type, idx + lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
break;
case 1: /* we just did an insert */
unprotect_entry(file_ptr, type, idx + lag, H5C__NO_FLAGS_SET);
break;
case 2:
if ( (entries[type])[idx + lag].is_dirty ) {
unprotect_entry(file_ptr, type, idx + lag, H5C__DELETED_FLAG);
} else {
unprotect_entry(file_ptr, type, idx + lag,
(dirty_destroys ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET)
| H5C__DELETED_FLAG);
}
break;
case 3: /* we just did an insrt */
unprotect_entry(file_ptr, type, idx + lag, H5C__DELETED_FLAG);
break;
default:
HDassert(0); /* this can't happen... */
break;
}
}
} else {
if ( ( pass ) && ( (idx + lag) >= 0 ) &&
( ( idx + lag) <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag));
unprotect_entry(file_ptr, type, idx + lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
}
if ( verbose )
HDfprintf(stdout, "\n");
idx--;
}
type--;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* row_major_scan_backward() */
/*-------------------------------------------------------------------------
* Function: hl_row_major_scan_backward()
*
* Purpose: Do a high locality sequence of inserts, protects, and
* unprotects while scanning through the set of entries.
* If pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 10/21/04
*
*-------------------------------------------------------------------------
*/
void
hl_row_major_scan_backward(H5F_t * file_ptr,
int32_t max_index,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts)
{
const char * fcn_name = "hl_row_major_scan_backward";
H5C_t * cache_ptr;
int32_t type = NUMBER_OF_ENTRY_TYPES - 1;
int32_t idx;
int32_t i;
int32_t lag = 100;
int32_t local_max_index;
if ( verbose )
HDfprintf(stdout, "%s(): entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag > 5 );
HDassert( max_index >= 200 );
HDassert( max_index <= MAX_ENTRIES );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
while ( ( pass ) && ( type >= 0 ) )
{
idx = max_indices[type] + lag;
local_max_index = MIN(max_index, max_indices[type]);
while ( ( pass ) && ( idx >= -lag ) )
{
if ( ( pass ) && ( do_inserts ) && ( (idx + lag) >= 0 ) &&
( (idx + lag) <= local_max_index ) &&
( ((idx + lag) % 2) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, (idx + lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag));
insert_entry(file_ptr, type, (idx + lag), H5C__NO_FLAGS_SET);
}
i = idx;
while ( ( pass ) && ( i >= idx - lag ) && ( i >= 0 ) )
{
if ( ( pass ) && ( i >= 0 ) && ( i <= local_max_index ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, i);
protect_entry(file_ptr, type, i);
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, i);
unprotect_entry(file_ptr, type, i, H5C__NO_FLAGS_SET);
}
i--;
}
if ( verbose )
HDfprintf(stdout, "\n");
idx--;
}
type--;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* hl_row_major_scan_backward() */
/*-------------------------------------------------------------------------
* Function: col_major_scan_forward()
*
* Purpose: Do a sequence of inserts, protects, and unprotects
* while scanning through the set of entries. If
* pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 6/23/04
*
*-------------------------------------------------------------------------
*/
void
col_major_scan_forward(H5F_t * file_ptr,
int32_t lag,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
int dirty_unprotects)
{
const char * fcn_name = "col_major_scan_forward()";
H5C_t * cache_ptr;
int32_t type = 0;
int32_t idx;
if ( verbose )
HDfprintf(stdout, "%s: entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( lag > 5 );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
idx = -lag;
while ( ( pass ) && ( (idx - lag) <= MAX_ENTRIES ) )
{
type = 0;
while ( ( pass ) && ( type < NUMBER_OF_ENTRY_TYPES ) )
{
if ( ( pass ) && ( do_inserts ) && ( (idx + lag) >= 0 ) &&
( (idx + lag) <= max_indices[type] ) &&
( ((idx + lag) % 3) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, (idx + lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx + lag));
insert_entry(file_ptr, type, (idx + lag), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( idx >= 0 ) && ( idx <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, idx);
protect_entry(file_ptr, type, idx);
}
if ( ( pass ) && ( (idx - lag) >= 0 ) &&
( (idx - lag) <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx - lag));
unprotect_entry(file_ptr, type, idx - lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
if ( verbose )
HDfprintf(stdout, "\n");
type++;
}
idx++;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* col_major_scan_forward() */
/*-------------------------------------------------------------------------
* Function: hl_col_major_scan_forward()
*
* Purpose: Do a high locality sequence of inserts, protects, and
* unprotects while scanning through the set of entries. If
* pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 19/25/04
*
*-------------------------------------------------------------------------
*/
void
hl_col_major_scan_forward(H5F_t * file_ptr,
int32_t max_index,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
int dirty_unprotects)
{
const char * fcn_name = "hl_col_major_scan_forward()";
H5C_t * cache_ptr;
int32_t type = 0;
int32_t idx;
int32_t lag = 200;
int32_t i;
int32_t local_max_index;
if ( verbose )
HDfprintf(stdout, "%s: entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag > 5 );
HDassert( max_index >= 500 );
HDassert( max_index <= MAX_ENTRIES );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
idx = 0;
local_max_index = MIN(max_index, MAX_ENTRIES);
while ( ( pass ) && ( idx <= local_max_index ) )
{
i = idx;
while ( ( pass ) && ( i >= 0 ) && ( i >= (idx - lag) ) ) {
type = 0;
while ( ( pass ) && ( type < NUMBER_OF_ENTRY_TYPES ) )
{
if ( ( pass ) && ( do_inserts ) && ( i == idx ) &&
( i <= local_max_index ) &&
( (i % 3) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, i) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, i);
insert_entry(file_ptr, type, i, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( i >= 0 ) && ( i <= local_max_index ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, i);
protect_entry(file_ptr, type, i);
}
if ( ( pass ) && ( i >= 0 ) &&
( i <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, i);
unprotect_entry(file_ptr, type, i,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
if ( verbose )
HDfprintf(stdout, "\n");
type++;
}
i--;
}
idx++;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* hl_col_major_scan_forward() */
/*-------------------------------------------------------------------------
* Function: col_major_scan_backward()
*
* Purpose: Do a sequence of inserts, protects, and unprotects
* while scanning backwards through the set of
* entries. If pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 6/23/04
*
*-------------------------------------------------------------------------
*/
void
col_major_scan_backward(H5F_t * file_ptr,
int32_t lag,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
int dirty_unprotects)
{
const char * fcn_name = "col_major_scan_backward()";
H5C_t * cache_ptr;
int mile_stone = 1;
int32_t type;
int32_t idx;
if ( verbose )
HDfprintf(stdout, "%s: entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag > 5 );
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
}
idx = MAX_ENTRIES + lag;
if ( verbose ) /* 1 */
HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++);
while ( ( pass ) && ( (idx + lag) >= 0 ) )
{
type = NUMBER_OF_ENTRY_TYPES - 1;
while ( ( pass ) && ( type >= 0 ) )
{
if ( ( pass ) && ( do_inserts) && ( (idx - lag) >= 0 ) &&
( (idx - lag) <= max_indices[type] ) &&
( ((idx - lag) % 3) == 0 ) &&
( ! entry_in_cache(cache_ptr, type, (idx - lag)) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, (idx - lag));
insert_entry(file_ptr, type, (idx - lag), H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( idx >= 0 ) && ( idx <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, idx);
protect_entry(file_ptr, type, idx);
}
if ( ( pass ) && ( (idx + lag) >= 0 ) &&
( (idx + lag) <= max_indices[type] ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, (idx + lag));
unprotect_entry(file_ptr, type, idx + lag,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
if ( verbose )
HDfprintf(stdout, "\n");
type--;
}
idx--;
}
if ( verbose ) /* 2 */
HDfprintf(stdout, "%s: point %d.\n", fcn_name, mile_stone++);
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
if ( verbose )
HDfprintf(stdout, "%s: exiting.\n", fcn_name);
return;
} /* col_major_scan_backward() */
/*-------------------------------------------------------------------------
* Function: hl_col_major_scan_backward()
*
* Purpose: Do a high locality sequence of inserts, protects, and
* unprotects while scanning backwards through the set of
* entries. If pass is false on entry, do nothing.
*
* Return: void
*
* Programmer: John Mainzer
* 10/25/04
*
*-------------------------------------------------------------------------
*/
void
hl_col_major_scan_backward(H5F_t * file_ptr,
int32_t max_index,
hbool_t verbose,
hbool_t reset_stats,
hbool_t display_stats,
hbool_t display_detailed_stats,
hbool_t do_inserts,
int dirty_unprotects)
{
const char * fcn_name = "hl_col_major_scan_backward()";
H5C_t * cache_ptr;
int32_t type = 0;
int32_t idx;
int32_t lag = 50;
int32_t i;
int32_t local_max_index;
if ( verbose )
HDfprintf(stdout, "%s: entering.\n", fcn_name);
if ( pass ) {
cache_ptr = file_ptr->shared->cache;
HDassert( cache_ptr != NULL );
HDassert( lag > 5 );
HDassert( max_index >= 500 );
HDassert( max_index <= MAX_ENTRIES );
local_max_index = MIN(max_index, MAX_ENTRIES);
if ( reset_stats ) {
H5C_stats__reset(cache_ptr);
}
idx = local_max_index;
}
while ( ( pass ) && ( idx >= 0 ) )
{
i = idx;
while ( ( pass ) && ( i <= local_max_index ) && ( i <= (idx + lag) ) ) {
type = 0;
while ( ( pass ) && ( type < NUMBER_OF_ENTRY_TYPES ) )
{
if ( ( pass ) && ( do_inserts ) && ( i == idx ) &&
( i <= local_max_index ) &&
( ! entry_in_cache(cache_ptr, type, i) ) ) {
if ( verbose )
HDfprintf(stdout, "(i, %d, %d) ", type, i);
insert_entry(file_ptr, type, i, H5C__NO_FLAGS_SET);
}
if ( ( pass ) && ( i >= 0 ) && ( i <= local_max_index ) ) {
if ( verbose )
HDfprintf(stdout, "(p, %d, %d) ", type, i);
protect_entry(file_ptr, type, i);
}
if ( ( pass ) && ( i >= 0 ) &&
( i <= local_max_index ) ) {
if ( verbose )
HDfprintf(stdout, "(u, %d, %d) ", type, i);
unprotect_entry(file_ptr, type, i,
(dirty_unprotects ? H5C__DIRTIED_FLAG : H5C__NO_FLAGS_SET));
}
if ( verbose )
HDfprintf(stdout, "\n");
type++;
}
i++;
}
idx--;
}
if ( ( pass ) && ( display_stats ) ) {
H5C_stats(cache_ptr, "test cache", display_detailed_stats);
}
return;
} /* hl_col_major_scan_backward() */
/*-------------------------------------------------------------------------
* Function: create_flush_dependency()
*
* Purpose: Create a 'flush dependency' between two entries.
*
* Do nothing if pass is false.
*
* Return: void
*
* Programmer: Quincey Koziol
* 3/16/09
*
*-------------------------------------------------------------------------
*/
void
create_flush_dependency(int32_t par_type,
int32_t par_idx,
int32_t chd_type,
int32_t chd_idx)
{
HDassert( ( 0 <= par_type ) && ( par_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= par_idx ) && ( par_idx <= max_indices[par_type] ) );
HDassert( ( 0 <= chd_type ) && ( chd_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= chd_idx ) && ( chd_idx <= max_indices[chd_type] ) );
if ( pass ) {
test_entry_t * par_base_addr; /* Base entry of parent's entry array */
test_entry_t * par_entry_ptr; /* Parent entry */
test_entry_t * chd_base_addr; /* Base entry of child's entry array */
test_entry_t * chd_entry_ptr; /* Child entry */
hbool_t par_is_pinned; /* Whether parent is already pinned */
herr_t result; /* API routine status */
/* Get parent entry */
par_base_addr = entries[par_type];
par_entry_ptr = &(par_base_addr[par_idx]);
par_is_pinned = par_entry_ptr->header.is_pinned;
/* Sanity check parent entry */
HDassert( par_entry_ptr->index == par_idx );
HDassert( par_entry_ptr->type == par_type );
HDassert( par_entry_ptr->header.is_protected );
HDassert( par_entry_ptr == par_entry_ptr->self );
/* Get parent entry */
chd_base_addr = entries[chd_type];
chd_entry_ptr = &(chd_base_addr[chd_idx]);
/* Sanity check child entry */
HDassert( chd_entry_ptr->index == chd_idx );
HDassert( chd_entry_ptr->type == chd_type );
HDassert( chd_entry_ptr == chd_entry_ptr->self );
result = H5C_create_flush_dependency(par_entry_ptr, chd_entry_ptr);
if ( ( result < 0 ) ||
( !par_entry_ptr->header.is_pinned ) ||
( !(par_entry_ptr->header.flush_dep_nchildren > 0) ) ) {
pass = FALSE;
failure_mssg = "error in H5C_create_flush_dependency().";
} /* end if */
/* Update information about entries */
HDassert( chd_entry_ptr->flush_dep_npar < MAX_FLUSH_DEP_PARS );
chd_entry_ptr->flush_dep_par_type[chd_entry_ptr->flush_dep_npar] = par_type;
chd_entry_ptr->flush_dep_par_idx[chd_entry_ptr->flush_dep_npar] = par_idx;
chd_entry_ptr->flush_dep_npar++;
par_entry_ptr->flush_dep_nchd++;
if(chd_entry_ptr->is_dirty || chd_entry_ptr->flush_dep_ndirty_chd > 0) {
HDassert(par_entry_ptr->flush_dep_ndirty_chd < par_entry_ptr->flush_dep_nchd);
par_entry_ptr->flush_dep_ndirty_chd++;
if(!par_entry_ptr->is_dirty
&& par_entry_ptr->flush_dep_ndirty_chd == 1)
mark_flush_dep_dirty(par_entry_ptr);
} /* end if */
par_entry_ptr->pinned_from_cache = TRUE;
if( !par_is_pinned )
par_entry_ptr->is_pinned = TRUE;
} /* end if */
return;
} /* create_flush_dependency() */
/*-------------------------------------------------------------------------
* Function: destroy_flush_dependency()
*
* Purpose: Destroy a 'flush dependency' between two entries.
*
* Do nothing if pass is false.
*
* Return: void
*
* Programmer: Quincey Koziol
* 3/16/09
*
*-------------------------------------------------------------------------
*/
void
destroy_flush_dependency(int32_t par_type,
int32_t par_idx,
int32_t chd_type,
int32_t chd_idx)
{
HDassert( ( 0 <= par_type ) && ( par_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= par_idx ) && ( par_idx <= max_indices[par_type] ) );
HDassert( ( 0 <= chd_type ) && ( chd_type < NUMBER_OF_ENTRY_TYPES ) );
HDassert( ( 0 <= chd_idx ) && ( chd_idx <= max_indices[chd_type] ) );
if ( pass ) {
test_entry_t * par_base_addr; /* Base entry of parent's entry array */
test_entry_t * par_entry_ptr; /* Parent entry */
test_entry_t * chd_base_addr; /* Base entry of child's entry array */
test_entry_t * chd_entry_ptr; /* Child entry */
unsigned i; /* Local index variable */
/* Get parent entry */
par_base_addr = entries[par_type];
par_entry_ptr = &(par_base_addr[par_idx]);
/* Sanity check parent entry */
HDassert( par_entry_ptr->is_pinned );
HDassert( par_entry_ptr->pinned_from_cache );
HDassert( par_entry_ptr->flush_dep_nchd > 0 );
HDassert( par_entry_ptr == par_entry_ptr->self );
/* Get parent entry */
chd_base_addr = entries[chd_type];
chd_entry_ptr = &(chd_base_addr[chd_idx]);
/* Sanity check child entry */
HDassert( chd_entry_ptr->index == chd_idx );
HDassert( chd_entry_ptr->type == chd_type );
HDassert( chd_entry_ptr->flush_dep_npar > 0 );
HDassert( chd_entry_ptr == chd_entry_ptr->self );
if ( H5C_destroy_flush_dependency(par_entry_ptr, chd_entry_ptr) < 0 ) {
pass = FALSE;
failure_mssg = "error in H5C_destroy_flush_dependency().";
} /* end if */
/* Update information about entries */
for(i=0; i<chd_entry_ptr->flush_dep_npar; i++)
if(chd_entry_ptr->flush_dep_par_type[i] == par_type
&& chd_entry_ptr->flush_dep_par_idx[i] == par_idx)
break;
HDassert(i < chd_entry_ptr->flush_dep_npar);
if(i < chd_entry_ptr->flush_dep_npar - 1)
HDmemmove(&chd_entry_ptr->flush_dep_par_type[i],
&chd_entry_ptr->flush_dep_par_type[i+1],
(chd_entry_ptr->flush_dep_npar - i - 1)
* sizeof(chd_entry_ptr->flush_dep_par_type[0]));
if(i < chd_entry_ptr->flush_dep_npar - 1)
HDmemmove(&chd_entry_ptr->flush_dep_par_idx[i],
&chd_entry_ptr->flush_dep_par_idx[i+1],
(chd_entry_ptr->flush_dep_npar - i - 1)
* sizeof(chd_entry_ptr->flush_dep_par_idx[0]));
chd_entry_ptr->flush_dep_npar--;
par_entry_ptr->flush_dep_nchd--;
if(par_entry_ptr->flush_dep_nchd == 0) {
par_entry_ptr->pinned_from_cache = FALSE;
par_entry_ptr->is_pinned = par_entry_ptr->pinned_from_client;
} /* end if */
if(chd_entry_ptr->is_dirty || chd_entry_ptr->flush_dep_ndirty_chd > 0) {
HDassert(par_entry_ptr->flush_dep_ndirty_chd > 0);
par_entry_ptr->flush_dep_ndirty_chd--;
if(!par_entry_ptr->is_dirty
&& par_entry_ptr->flush_dep_ndirty_chd == 0)
mark_flush_dep_clean(par_entry_ptr);
} /* end if */
} /* end if */
return;
} /* destroy_flush_dependency() */
/*-------------------------------------------------------------------------
* Function: mark_flush_dep_dirty()
*
* Purpose: Recursively propagate the flush_dep_ndirty_children flag
* up the dependency chain in response to entry either
* becoming dirty or having its flush_dep_ndirty_children
* increased from 0.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
* 12/4/12
*
*-------------------------------------------------------------------------
*/
static void
mark_flush_dep_dirty(test_entry_t * entry_ptr)
{
test_entry_t * par_base_addr; /* Base entry of parent's entry array */
test_entry_t * par_entry_ptr; /* Parent entry */
unsigned i; /* Local index variable */
/* Sanity checks */
HDassert(entry_ptr);
HDassert((entry_ptr->is_dirty && entry_ptr->flush_dep_ndirty_chd == 0)
|| (!entry_ptr->is_dirty && entry_ptr->flush_dep_ndirty_chd == 1));
/* Iterate over the parent entries */
if(entry_ptr->flush_dep_npar) {
for(i=0; i<entry_ptr->flush_dep_npar; i++) {
/* Get parent entry */
par_base_addr = entries[entry_ptr->flush_dep_par_type[i]];
par_entry_ptr = &(par_base_addr[entry_ptr->flush_dep_par_idx[i]]);
/* Sanity check */
HDassert(par_entry_ptr->flush_dep_ndirty_chd
< par_entry_ptr->flush_dep_nchd);
/* Adjust the parent's number of dirty children */
par_entry_ptr->flush_dep_ndirty_chd++;
/* Propagate the flush dep dirty flag up the chain if necessary */
if(!par_entry_ptr->is_dirty
&& par_entry_ptr->flush_dep_ndirty_chd == 1)
mark_flush_dep_dirty(par_entry_ptr);
} /* end for */
} /* end if */
return;
} /* mark_flush_dep_dirty() */
/*-------------------------------------------------------------------------
* Function: mark_flush_dep_clean()
*
* Purpose: Recursively propagate the flush_dep_ndirty_children flag
* up the dependency chain in response to entry either
* becoming clean or having its flush_dep_ndirty_children
* reduced to 0.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
* 12/4/12
*
*-------------------------------------------------------------------------
*/
static void
mark_flush_dep_clean(test_entry_t * entry_ptr)
{
test_entry_t * par_base_addr; /* Base entry of parent's entry array */
test_entry_t * par_entry_ptr; /* Parent entry */
unsigned i; /* Local index variable */
/* Sanity checks */
HDassert(entry_ptr);
HDassert(!entry_ptr->is_dirty && entry_ptr->flush_dep_ndirty_chd == 0);
/* Iterate over the parent entries */
if(entry_ptr->flush_dep_npar) {
for(i=0; i<entry_ptr->flush_dep_npar; i++) {
/* Get parent entry */
par_base_addr = entries[entry_ptr->flush_dep_par_type[i]];
par_entry_ptr = &(par_base_addr[entry_ptr->flush_dep_par_idx[i]]);
/* Sanity check */
HDassert(par_entry_ptr->flush_dep_ndirty_chd > 0);
/* Adjust the parent's number of dirty children */
par_entry_ptr->flush_dep_ndirty_chd--;
/* Propagate the flush dep dirty flag up the chain if necessary */
if(!par_entry_ptr->is_dirty
&& par_entry_ptr->flush_dep_ndirty_chd == 0)
mark_flush_dep_clean(par_entry_ptr);
} /* end for */
} /* end if */
return;
} /* mark_flush_dep_clean() */
/*** H5AC level utility functions ***/
/*-------------------------------------------------------------------------
* Function: check_and_validate_cache_hit_rate()
*
* Purpose: Use the API functions to get and reset the cache hit rate.
* Verify that the value returned by the API call agrees with
* the cache internal data structures.
*
* If the number of cache accesses exceeds the value provided
* in the min_accesses parameter, and the hit rate is less than
* min_hit_rate, set pass to FALSE, and set failure_mssg to
* a string indicating that hit rate was unexpectedly low.
*
* Return hit rate in *hit_rate_ptr, and print the data to
* stdout if requested.
*
* If an error is detected, set pass to FALSE, and set
* failure_mssg to an appropriate value.
*
* Return: void
*
* Programmer: John Mainzer
* 4/18/04
*
*-------------------------------------------------------------------------
*/
void
check_and_validate_cache_hit_rate(hid_t file_id,
double * hit_rate_ptr,
hbool_t dump_data,
int64_t min_accesses,
double min_hit_rate)
{
/* const char * fcn_name = "check_and_validate_cache_hit_rate()"; */
herr_t result;
int64_t cache_hits = 0;
int64_t cache_accesses = 0;
double expected_hit_rate;
double hit_rate;
H5F_t * file_ptr = NULL;
H5C_t * cache_ptr = NULL;
/* get a pointer to the files internal data structure */
if ( pass ) {
file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE);
if ( file_ptr == NULL ) {
pass = FALSE;
failure_mssg = "Can't get file_ptr.";
} else {
cache_ptr = file_ptr->shared->cache;
}
}
/* verify that we can access the cache data structure */
if ( pass ) {
if ( ( cache_ptr == NULL ) ||
( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) {
pass = FALSE;
failure_mssg = "Can't access cache resize_ctl.";
}
}
/* compare the cache's internal configuration with the expected value */
if ( pass ) {
cache_hits = cache_ptr->cache_hits;
cache_accesses = cache_ptr->cache_accesses;
if ( cache_accesses > 0 ) {
expected_hit_rate = ((double)cache_hits) / ((double)cache_accesses);
} else {
expected_hit_rate = 0.0;
}
result = H5Fget_mdc_hit_rate(file_id, &hit_rate);
if ( result < 0 ) {
pass = FALSE;
failure_mssg = "H5Fget_mdc_hit_rate() failed.";
} else if ( ! DBL_REL_EQUAL(hit_rate, expected_hit_rate, 0.00001) ) {
pass = FALSE;
failure_mssg = "unexpected hit rate.";
}
}
if ( pass ) { /* reset the hit rate */
result = H5Freset_mdc_hit_rate_stats(file_id);
if ( result < 0 ) {
pass = FALSE;
failure_mssg = "H5Freset_mdc_hit_rate_stats() failed.";
}
}
/* set *hit_rate_ptr if appropriate */
if ( ( pass ) && ( hit_rate_ptr != NULL ) ) {
*hit_rate_ptr = hit_rate;
}
/* dump data to stdout if requested */
if ( ( pass ) && ( dump_data ) ) {
HDfprintf(stdout,
"cache_hits: %ld, cache_accesses: %ld, hit_rate: %lf\n",
(long)cache_hits, (long)cache_accesses, hit_rate);
}
if ( ( pass ) &&
( cache_accesses > min_accesses ) &&
( hit_rate < min_hit_rate ) ) {
pass = FALSE;
failure_mssg = "Unexpectedly low hit rate.";
}
return;
} /* check_and_validate_cache_hit_rate() */
/*-------------------------------------------------------------------------
* Function: check_and_validate_cache_size()
*
* Purpose: Use the API function to get the cache size data. Verify
* that the values returned by the API call agree with
* the cache internal data structures.
*
* Return size data in the locations specified by the pointer
* parameters if these parameters are not NULL. Print the
* data to stdout if requested.
*
* If an error is detected, set pass to FALSE, and set
* failure_mssg to an appropriate value.
*
* Return: void
*
* Programmer: John Mainzer
* 4/18/04
*
*-------------------------------------------------------------------------
*/
void
check_and_validate_cache_size(hid_t file_id,
size_t * max_size_ptr,
size_t * min_clean_size_ptr,
size_t * cur_size_ptr,
int32_t * cur_num_entries_ptr,
hbool_t dump_data)
{
/* const char * fcn_name = "check_and_validate_cache_size()"; */
herr_t result;
size_t expected_max_size;
size_t max_size;
size_t expected_min_clean_size;
size_t min_clean_size;
size_t expected_cur_size;
size_t cur_size;
int32_t expected_cur_num_entries;
int cur_num_entries;
H5F_t * file_ptr = NULL;
H5C_t * cache_ptr = NULL;
/* get a pointer to the files internal data structure */
if ( pass ) {
file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE);
if ( file_ptr == NULL ) {
pass = FALSE;
failure_mssg = "Can't get file_ptr.";
} else {
cache_ptr = file_ptr->shared->cache;
}
}
/* verify that we can access the cache data structure */
if ( pass ) {
if ( ( cache_ptr == NULL ) ||
( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) {
pass = FALSE;
failure_mssg = "Can't access cache data structure.";
}
}
/* compare the cache's internal configuration with the expected value */
if ( pass ) {
expected_max_size = cache_ptr->max_cache_size;
expected_min_clean_size = cache_ptr->min_clean_size;
expected_cur_size = cache_ptr->index_size;
expected_cur_num_entries = cache_ptr->index_len;
result = H5Fget_mdc_size(file_id,
&max_size,
&min_clean_size,
&cur_size,
&cur_num_entries);
if ( result < 0 ) {
pass = FALSE;
failure_mssg = "H5Fget_mdc_size() failed.";
} else if ( ( max_size != expected_max_size ) ||
( min_clean_size != expected_min_clean_size ) ||
( cur_size != expected_cur_size ) ||
( cur_num_entries != (int)expected_cur_num_entries ) ) {
pass = FALSE;
failure_mssg = "H5Fget_mdc_size() returned unexpected value(s).";
}
}
/* return size values if requested */
if ( ( pass ) && ( max_size_ptr != NULL ) ) {
*max_size_ptr = max_size;
}
if ( ( pass ) && ( min_clean_size_ptr != NULL ) ) {
*min_clean_size_ptr = min_clean_size;
}
if ( ( pass ) && ( cur_size_ptr != NULL ) ) {
*cur_size_ptr = cur_size;
}
if ( ( pass ) && ( cur_num_entries_ptr != NULL ) ) {
*cur_num_entries_ptr = cur_num_entries;
}
/* dump data to stdout if requested */
if ( ( pass ) && ( dump_data ) ) {
HDfprintf(stdout,
"max_sz: %ld, min_clean_sz: %ld, cur_sz: %ld, cur_ent: %ld\n",
(long)max_size, (long)min_clean_size, (long)cur_size,
(long)cur_num_entries);
}
return;
} /* check_and_validate_cache_size() */
hbool_t
resize_configs_are_equal(const H5C_auto_size_ctl_t *a,
const H5C_auto_size_ctl_t *b,
hbool_t compare_init)
{
if(a->version != b->version)
return(FALSE);
else if(a->rpt_fcn != b->rpt_fcn)
return(FALSE);
else if(compare_init && (a->set_initial_size != b->set_initial_size))
return(FALSE);
else if(compare_init && (a->initial_size != b->initial_size))
return(FALSE);
else if(HDfabs(a->min_clean_fraction - b->min_clean_fraction) > FP_EPSILON)
return(FALSE);
else if(a->max_size != b->max_size)
return(FALSE);
else if(a->min_size != b->min_size)
return(FALSE);
else if(a->epoch_length != b->epoch_length)
return(FALSE);
else if(a->incr_mode != b->incr_mode)
return(FALSE);
else if(HDfabs(a->lower_hr_threshold - b->lower_hr_threshold) > FP_EPSILON)
return(FALSE);
else if(HDfabs(a->increment - b->increment) > FP_EPSILON)
return(FALSE);
else if(a->apply_max_increment != b->apply_max_increment)
return(FALSE);
else if(a->max_increment != b->max_increment)
return(FALSE);
else if(a->flash_incr_mode != b->flash_incr_mode)
return(FALSE);
else if(HDfabs(a->flash_multiple - b->flash_multiple) > FP_EPSILON)
return(FALSE);
else if(HDfabs(a->flash_threshold - b->flash_threshold) > FP_EPSILON)
return(FALSE);
else if(a->decr_mode != b->decr_mode)
return(FALSE);
else if(HDfabs(a->upper_hr_threshold - b->upper_hr_threshold) > FP_EPSILON)
return(FALSE);
else if(HDfabs(a->decrement - b->decrement) > FP_EPSILON)
return(FALSE);
else if(a->apply_max_decrement != b->apply_max_decrement)
return(FALSE);
else if(a->max_decrement != b->max_decrement)
return(FALSE);
else if(a->epochs_before_eviction != b->epochs_before_eviction)
return(FALSE);
else if(a->apply_empty_reserve != b->apply_empty_reserve)
return(FALSE);
else if(HDfabs(a->empty_reserve - b->empty_reserve) > FP_EPSILON)
return(FALSE);
return(TRUE);
}
/*-------------------------------------------------------------------------
* Function: validate_mdc_config()
*
* Purpose: Verify that the file indicated by the file_id parameter
* has both internal and external configuration matching
* *config_ptr.
*
* Do nothin on success. On failure, set pass to FALSE, and
* load an error message into failue_mssg. Note that
* failure_msg is assumed to be at least 128 bytes in length.
*
* Return: void
*
* Programmer: John Mainzer
* 4/14/04
*
*-------------------------------------------------------------------------
*/
void
validate_mdc_config(hid_t file_id,
H5AC_cache_config_t * ext_config_ptr,
hbool_t compare_init,
int test_num)
{
/* const char * fcn_name = "validate_mdc_config()"; */
static char msg[256];
H5F_t * file_ptr = NULL;
H5C_t * cache_ptr = NULL;
H5AC_cache_config_t scratch;
H5C_auto_size_ctl_t int_config;
XLATE_EXT_TO_INT_MDC_CONFIG(int_config, (*ext_config_ptr))
/* get a pointer to the files internal data structure */
if ( pass ) {
file_ptr = (H5F_t *)H5I_object_verify(file_id, H5I_FILE);
if ( file_ptr == NULL ) {
pass = FALSE;
HDsnprintf(msg, (size_t)128, "Can't get file_ptr #%d.", test_num);
failure_mssg = msg;
} else {
cache_ptr = file_ptr->shared->cache;
}
}
/* verify that we can access the internal version of the cache config */
if ( pass ) {
if ( ( cache_ptr == NULL ) ||
( cache_ptr->magic != H5C__H5C_T_MAGIC ) ||
( cache_ptr->resize_ctl.version != H5C__CURR_AUTO_SIZE_CTL_VER ) ){
pass = FALSE;
HDsnprintf(msg, (size_t)128,
"Can't access cache resize_ctl #%d.", test_num);
failure_mssg = msg;
}
}
/* compare the cache's internal configuration with the expected value */
if ( pass ) {
if ( ! resize_configs_are_equal(&int_config, &cache_ptr->resize_ctl,
compare_init) ) {
pass = FALSE;
HDsnprintf(msg, (size_t)128,
"Unexpected internal config #%d.", test_num);
failure_mssg = msg;
}
}
/* obtain external cache config */
if ( pass ) {
scratch.version = H5AC__CURR_CACHE_CONFIG_VERSION;
if ( H5Fget_mdc_config(file_id, &scratch) < 0 ) {
pass = FALSE;
HDsnprintf(msg, (size_t)128,
"H5Fget_mdc_config() failed #%d.", test_num);
failure_mssg = msg;
}
}
if ( pass ) {
/* Recall that in any configuration supplied by the cache
* at run time, the set_initial_size field will always
* be FALSE, regardless of the value passed in. Thus we
* always presume that this field need not match that of
* the supplied external configuration.
*
* The cache also sets the initial_size field to the current
* cache max size instead of the value initialy supplied.
* Depending on circumstances, this may or may not match
* the original. Hence the compare_init parameter.
*/
if ( ! CACHE_CONFIGS_EQUAL((*ext_config_ptr), scratch, \
FALSE, compare_init) ) {
pass = FALSE;
HDsnprintf(msg, (size_t)128,
"Unexpected external config #%d.", test_num);
failure_mssg = msg;
}
}
return;
} /* validate_mdc_config() */