diff options
Diffstat (limited to 'src/H5SMcache.c')
-rw-r--r-- | src/H5SMcache.c | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/src/H5SMcache.c b/src/H5SMcache.c new file mode 100644 index 0000000..6403dc3 --- /dev/null +++ b/src/H5SMcache.c @@ -0,0 +1,626 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/***********/ +/* Headers */ +/***********/ +/* JAMES: these need to go first or else FILE isn't defined in H5Fpkg.h */ +/* JAMES: which of these are really needed? H5Fpkg.h, even? */ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ + +#include "H5Fpkg.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5FOprivate.h" /* File objects */ +#include "H5HLprivate.h" /* Local heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ +#include "H5SMpkg.h" /* Shared object header messages */ +#include "H5FDprivate.h" /* File drivers */ + +/****************/ +/* Local Macros */ +/****************/ +#define H5F_TABLEBUF_SIZE H5SM_TABLE_SIZEOF_MAGIC + 20 + (H5SM_MAX_INDEXES * 26) +/* JAMES: should this change according to address size? */ +#define H5F_LISTBUF_SIZE H5SM_LIST_SIZEOF_MAGIC + H5SM_MAX_LIST_ELEMS * 16 + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5SM_flush_table(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table); +static H5SM_master_table_t *H5SM_load_table(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); +static herr_t H5SM_clear_table(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy); +static herr_t H5SM_dest_table(H5F_t *f, H5SM_master_table_t* table); +static herr_t H5SM_table_size(const H5F_t *f, const H5SM_master_table_t *table, size_t *size_ptr); + +static herr_t H5SM_flush_list(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list); +static H5SM_list_t *H5SM_load_list(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); +static herr_t H5SM_clear_list(H5F_t *f, H5SM_list_t *list, hbool_t destroy); +static herr_t H5SM_dest_list(H5F_t *f, H5SM_list_t* list); +static herr_t H5SM_list_size(const H5F_t *f, const H5SM_list_t UNUSED *list, size_t *size_ptr); + +/*********************/ +/* Package Variables */ +/*********************/ +/* H5SM inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_SOHM_TABLE[1] = {{ + H5AC_SOHM_TABLE_ID, + (H5AC_load_func_t) H5SM_load_table, + (H5AC_flush_func_t) H5SM_flush_table, + (H5AC_dest_func_t) H5SM_dest_table, + (H5AC_clear_func_t)H5SM_clear_table, + (H5AC_size_func_t) H5SM_table_size, +}}; + +const H5AC_class_t H5AC_SOHM_LIST[1] = {{ + H5AC_SOHM_LIST_ID, + (H5AC_load_func_t) H5SM_load_list, + (H5AC_flush_func_t) H5SM_flush_list, + (H5AC_dest_func_t) H5SM_dest_list, + (H5AC_clear_func_t)H5SM_clear_list, + (H5AC_size_func_t) H5SM_list_size, +}}; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5SM_flush_table + * + * Purpose: Flushes (and destroys) the table of Shared Object Header + * Message indexes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_flush_table(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table) +{ + herr_t ret_value=SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_flush_table, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(table); + + if (table->cache_info.is_dirty) { + uint8_t buf[H5F_TABLEBUF_SIZE]; /* Temporary buffer */ /* JAMES This is big. Do I need to use H5FL_BLK_MALLOC instead? */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Header size on disk */ + int x; /* Counter variable */ + + /* Encode the master table and all of the index headers as one big blob */ + size = H5SM_TABLE_SIZE(f) + (H5SM_INDEX_HEADER_SIZE(f) * table->num_indexes); + + /* Encode the master table */ + p = buf; + + /* Encode magic number */ + HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5SM_TABLE_SIZEOF_MAGIC); + p += H5SM_TABLE_SIZEOF_MAGIC; + + *p++ = HDF5_SOHMTABLE_VERSION; /* Version */ + + *p++ = table->num_indexes; /* Number of indexes in the table */ + + /* Encode each index header */ + for(x=0; x<table->num_indexes; ++x) { + *p++ = table->indexes[x].index_type; /* Is message index a list or a B-tree? */ + + UINT16ENCODE(p, table->indexes[x].mesg_types); /* Type of messages in the index */ + + UINT16ENCODE(p, table->indexes[x].list_to_btree); /* List cutoff; fewer than this number and index becomes a list */ + UINT16ENCODE(p, table->indexes[x].btree_to_list); /* B-tree cutoff; more than this number and index becomes a B-tree */ + UINT16ENCODE(p, table->indexes[x].num_messages); /* Number of messages shared */ + H5F_addr_encode(f, &p, table->indexes[x].index_addr); /* Address of the actual index */ + H5F_addr_encode(f, &p, table->indexes[x].heap_addr); /* Address of the index's heap */ + } + + /* Write the table to disk */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk") + + table->cache_info.is_dirty = FALSE; + } + + if(destroy) + if(H5SM_dest_table(f, table) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy sohm table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_flush_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_load_table + * + * Purpose: Loads the master table of Shared Object Header Message + * indexes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static H5SM_master_table_t * +H5SM_load_table(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) +{ + H5SM_master_table_t *table; /* The SOHM table being read in */ + size_t table_size; /* Size of SOHM master table on disk */ + size_t indexes_size; /* Size of index headers on disk */ + uint8_t *buf=NULL; /* Reading buffer */ + uint8_t *p; /* Pointer into input buffer */ + uint8_t x; /* Counter variable for index headers */ + H5SM_master_table_t *ret_value; + + FUNC_ENTER_NOAPI(H5SM_load_table, NULL) + + /* Allocate space for the SOHM table data structure */ + if(NULL == (table = H5MM_calloc(sizeof(H5SM_master_table_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Compute the size of the SOHM table header on disk. Read in just the table first */ + table_size = H5SM_TABLE_SIZE(f); + + /* Allocate temporary buffer */ + if(NULL == (buf = HDmalloc(table_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read header from disk */ + if(H5F_block_read(f, H5FD_MEM_SOHM, addr, table_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM table") + + p = buf; + + /* Check magic number */ + if(HDmemcmp(p, H5SM_TABLE_MAGIC, (size_t)H5SM_TABLE_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature"); + p += H5SM_TABLE_SIZEOF_MAGIC; + + /* Version number */ + if (HDF5_SOHMTABLE_VERSION != *p++) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unknown SOHM table version number") + + table->num_indexes = *p++; /* Number of indexes in the table */ + + HDassert((size_t)(p - buf) == table_size); + + /* Allocate space for the index headers */ + if(NULL == (table->indexes = H5FL_ARR_MALLOC(H5SM_index_header_t, table->num_indexes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for SOHM indexes") + + /* Now read in the list of index headers */ + indexes_size = table->num_indexes * H5SM_INDEX_HEADER_SIZE(f); + + /* Re-allocate temporary buffer */ + HDassert(buf); + HDfree(buf); + if(NULL == (buf = HDmalloc(indexes_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + + if(H5F_block_read(f, H5FD_MEM_SOHM, addr + table_size, indexes_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM table") + p=buf; + + for(x=0; x<table->num_indexes; ++x) { + table->indexes[x].index_type= *p++; /* type of the index (list or B-tree) */ + + UINT16DECODE(p, table->indexes[x].mesg_types); + UINT16DECODE(p, table->indexes[x].list_to_btree); + UINT16DECODE(p, table->indexes[x].btree_to_list); + UINT16DECODE(p, table->indexes[x].num_messages); + H5F_addr_decode(f, &p, &(table->indexes[x].index_addr)); + H5F_addr_decode(f, &p, &(table->indexes[x].heap_addr)); + } + + HDassert((size_t)(p - buf) == indexes_size); + ret_value = table; + +done: + /* Free buffer if it was allocated */ + if(buf) + HDfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_load_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_clear_table + * + * Purpose: Mark this table as no longer being dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_clear_table(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_clear_table) + + /* + * Check arguments. + */ + HDassert(table); + + /* Reset the dirty flag. */ + table->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5SM_dest_table(f, table) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to delete SOHM master table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_clear_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_dest_table + * + * Purpose: Frees memory used by the SOHM table. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_dest_table(H5F_t *f, H5SM_master_table_t* table) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5SM_dest_table) + + assert(table); + + assert(table->indexes); + + H5FL_ARR_FREE(H5SM_index_header_t, table->indexes); + + H5MM_free(table); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_dest_table */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_table_size + * + * Purpose: Returns the size of the table encoded on disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_table_size(const H5F_t *f, const H5SM_master_table_t *table, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_table_size) + + /* check arguments */ + HDassert(f); + HDassert(table); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = H5SM_TABLE_SIZE(f) + (table->num_indexes * H5SM_INDEX_HEADER_SIZE(f)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_table_size */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_flush_list + * + * Purpose: Flush this list index. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_flush_list(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_flush_list, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(list); + HDassert(list->header); + + if (list->cache_info.is_dirty) { + uint8_t buf[H5F_LISTBUF_SIZE]; /* Temporary buffer */ /* JAMES Do I need to use H5FL_BLK_MALLOC instead? */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Header size on disk */ + hsize_t x; + + size = H5SM_LIST_SIZE(f, list->header->num_messages); + + /* Encode the list */ + p = buf; + + /* Encode magic number */ + HDmemcpy(p, H5SM_LIST_MAGIC, (size_t)H5SM_LIST_SIZEOF_MAGIC); + p += H5SM_LIST_SIZEOF_MAGIC; + + /* Write messages from the messages array to disk */ + /* JAMES: we have to search the whole array. not the best way to do it; could go until we've written + * num_messages */ + for(x=0; x<list->header->list_to_btree; x++) { + if(list->messages[x].fheap_id != 0 && list->messages[x].hash != H5O_HASH_UNDEF) { + /* JAMES: use H5SM_message_encode here */ + UINT32ENCODE(p, list->messages[x].hash); /* Read the hash value for this message */ + UINT16ENCODE(p, list->messages[x].ref_count); /* Read the reference count for this message */ + UINT64ENCODE(p, list->messages[x].fheap_id); /* Get the heap ID for the message */ + } + } + + /* Write the list to disk */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk") + + list->cache_info.is_dirty = FALSE; + } + + if(destroy) + if(H5SM_dest_list(f, list) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_flush_list */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_load_list + * + * Purpose: Loads a list of SOHM messages. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static H5SM_list_t * +H5SM_load_list(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void *udata2) +{ + H5SM_list_t *list; /* The SOHM list being read in */ + H5SM_index_header_t *header = (H5SM_index_header_t *) udata2; /* Index header for this list */ + size_t size; /* Size of SOHM list on disk */ + uint8_t *buf = NULL; /* Reading buffer */ + uint8_t *p; /* Pointer into input buffer */ + hsize_t x; /* Counter variable for messages in list */ + H5SM_list_t *ret_value=NULL; + + FUNC_ENTER_NOAPI(H5SM_load_list, NULL) + + HDassert(header); + + /* Allocate space for the SOHM list data structure and initialize list JAMES don't need to initialize all of list */ + if(NULL == (list = H5FL_MALLOC(H5SM_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&list->cache_info, 0, sizeof(H5AC_info_t)); + + /* Allocate list in memory as an array*/ + if((list->messages = H5FL_ARR_MALLOC(H5SM_sohm_t, header->list_to_btree)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for SOHM list") + + list->header = header; + + /* Compute the size of the SOHM list on disk */ + size = H5SM_LIST_SIZE(f, header->num_messages); + + /* Allocate temporary buffer */ + /* JAMES: is BLK_MALLOC somehow better for this? */ + if(NULL == (buf = HDmalloc(size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read list from disk */ + if(H5F_block_read(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM list") + p = buf; + + /* Check magic number */ + if(HDmemcmp(p, H5SM_LIST_MAGIC, (size_t)H5SM_LIST_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM list signature"); + p += H5SM_LIST_SIZEOF_MAGIC; + + /* Read messages into the list array */ + for(x=0; x<header->num_messages; x++) + { + UINT32DECODE(p, list->messages[x].hash); /* Read the hash value for this message */ + UINT16DECODE(p, list->messages[x].ref_count); /* Read the reference count for this message */ + UINT64DECODE(p, list->messages[x].fheap_id); /* Get the heap ID for the message */ + } + + /* Initialize the rest of the array */ + for(x=header->num_messages; x<header->list_to_btree; x++) + { + list->messages[x].fheap_id = 0; /* JAMES: would making this one operation make it faster? */ + list->messages[x].hash = H5O_HASH_UNDEF; + } + + HDassert((size_t)(p - buf) == size); + + ret_value = list; +done: + if(buf) + HDfree(buf); + + if(ret_value == NULL) { + if(list) { + if(list->messages) { + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + } + H5FL_FREE(H5SM_list_t, list); + } + } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_load_list */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_clear_list + * + * Purpose: Marks a list as not dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_clear_list(H5F_t *f, H5SM_list_t *list, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_clear_list) + + /* + * Check arguments. + */ + HDassert(list); + + /* Reset the dirty flag. */ + list->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5SM_dest_list(f, list) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy SOHM list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end of H5SM_clear_list */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_dest_list + * + * Purpose: Frees all memory used by the list. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_dest_list(H5F_t *f, H5SM_list_t* list) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5SM_dest_list) + + HDassert(list); + HDassert(list->messages); + + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + + H5FL_FREE(H5SM_list_t, list); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_dest_list */ + + +/* JAMES: should this number be constant, or should it increase and decrease as + * messages are added and removed? */ +/*------------------------------------------------------------------------- + * Function: H5SM_list_size + * + * Purpose: Gets the size of a list on disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_list_size(const H5F_t *f, const H5SM_list_t *list, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_list_size) + + /* check arguments */ + HDassert(f); + HDassert(list); + HDassert(list->header); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = H5SM_LIST_SIZE(f, list->header->list_to_btree); /* JAMES: might want to have variable-sized lists */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_list_size */ + + + |