summaryrefslogtreecommitdiffstats
path: root/src/H5AC.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5AC.c')
-rw-r--r--src/H5AC.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
new file mode 100644
index 0000000..a0123b1
--- /dev/null
+++ b/src/H5AC.c
@@ -0,0 +1,315 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: hdf5cache.c
+ * Jul 9 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Functions in this file implement a cache for
+ * things which exist on disk. All "things" associated
+ * with a particular HDF file share the same cache; each
+ * HDF file has it's own cache.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include "hdf5.h"
+
+#include "H5ACprivate.h"
+
+#define HASH(addr) ((unsigned)(addr) % H5AC_NSLOTS)
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_new
+ *
+ * Purpose: Initialize the cache just after a file is opened.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_new (hdf5_file_t *f)
+{
+ f->cache = HDcalloc (H5AC_NSLOTS, sizeof (H5AC_cache_t));
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_dest
+ *
+ * Purpose: Flushes all data to disk and destroys the cache.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_dest (hdf5_file_t *f)
+{
+ if (H5AC_flush (f, NULL, 0, TRUE)<0) return -1;
+ HDfree (f->cache);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_find
+ *
+ * Purpose: Given an object type and the address at which that object
+ * is located in the file, return a pointer to the object.
+ * The optional UDATA structure is passed down to the function
+ * that is responsible for loading the object into memory.
+ *
+ * Return: Success: Pointer to the object. The pointer is
+ * valid until some other cache function
+ * is called.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ const void *udata)
+{
+ unsigned idx = HASH(addr);
+ herr_t status;
+ void *thing = NULL;
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ assert (type);
+ assert (type->load);
+ assert (type->flush);
+
+ /*
+ * Return right away if the item is in the cache.
+ */
+ if (f->cache[idx].type==type && f->cache[idx].addr==addr) {
+ return f->cache[idx].thing;
+ }
+
+ /*
+ * Load a new thing. If it can't be loaded, then return an error
+ * without preempting anything.
+ */
+ if (NULL==(thing=(type->load)(f, addr, udata))) {
+ return NULL;
+ }
+
+ /*
+ * Free the previous cache entry if there is one.
+ */
+ if (f->cache[idx].type) {
+ flush = f->cache[idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing);
+ if (status<0) {
+ /*
+ * The old thing could not be removed from the stack.
+ * Release the new thing and fail.
+ */
+ status = (type->flush)(f, TRUE, addr, thing);
+ assert (status>=0);
+ return NULL;
+ }
+ }
+
+ /*
+ * Make the cache point to the new thing.
+ */
+ f->cache[idx].type = type;
+ f->cache[idx].addr = addr;
+ f->cache[idx].thing = thing;
+
+ return thing;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_flush
+ *
+ * Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
+ * entry from the cache. If the entry type is CACHE_FREE then
+ * all types of entries are flushed. If the ADDR is zero then
+ * all entries of the specified type are flushed.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ hbool_t destroy)
+{
+ uintn i = HASH(addr);
+ herr_t status;
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ if (!type || 0==addr) {
+ /*
+ * Look at all cache entries.
+ */
+ for (i=0; i<H5AC_NSLOTS; i++) {
+ if (NULL==f->cache[i].type) continue;
+ if ((!type || type==f->cache[i].type) &&
+ (0==addr || addr==f->cache[i].addr)) {
+ flush = f->cache[i].type->flush;
+ status = (flush)(f, destroy, f->cache[i].addr,
+ f->cache[i].thing);
+ if (status<0) return -1;
+ if (destroy) f->cache[i].type = NULL;
+ }
+ }
+
+ } else if (f->cache[i].type==type && f->cache[i].addr==addr) {
+ /*
+ * Flush just this entry.
+ */
+ flush = f->cache[i].type->flush;
+ status = (flush) (f, destroy, f->cache[i].addr, f->cache[i].thing);
+ if (status<0) return -1;
+ if (destroy) f->cache[i].type = NULL;
+
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_set
+ *
+ * Purpose: Adds the specified thing to the cache. The thing need not
+ * exist on disk yet, but it must have an address and disk
+ * space reserved.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, void *thing)
+{
+ herr_t status;
+ uintn idx = HASH (addr);
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ assert (type);
+ assert (type->flush);
+
+ if (f->cache[idx].type) {
+ flush = f->cache[idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing);
+ if (status<0) return -1;
+ }
+
+ f->cache[idx].type = type;
+ f->cache[idx].addr = addr;
+ f->cache[idx].thing = thing;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_rename
+ *
+ * Purpose: Use this function to notify the cache that an object's
+ * file address changed.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
+ off_t old_addr, off_t new_addr)
+{
+ uintn old_idx = HASH (old_addr);
+ uintn new_idx = HASH (new_addr);
+ herr_t (*flush)(hdf5_file_t*, hbool_t, off_t, void*);
+ herr_t status;
+
+ assert (type);
+
+ if (f->cache[old_idx].type!=type || f->cache[old_idx].addr!=old_addr) {
+ return 0; /*item not in cache*/
+ }
+
+ if (old_idx==new_idx) {
+ f->cache[old_idx].addr = new_addr;
+ return 0;
+ }
+
+ /*
+ * Free the item from the destination cache line.
+ */
+ if (f->cache[new_idx].type) {
+ flush = f->cache[new_idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[new_idx].addr,
+ f->cache[new_idx].thing);
+ if (status<0) return -1;
+ }
+
+ /*
+ * Move the source to the destination (it might not be cached)
+ */
+ f->cache[new_idx].type = f->cache[old_idx].type;
+ f->cache[new_idx].addr = new_addr;
+ f->cache[new_idx].thing = f->cache[old_idx].thing;
+ f->cache[old_idx].type = NULL;
+
+ return 0;
+}
+