summaryrefslogtreecommitdiffstats
path: root/src/H5FD.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2000-08-31 19:40:07 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2000-08-31 19:40:07 (GMT)
commit312cd2c57d7a8488e2a21d65c074862cba8e7663 (patch)
treef3b20ba3cdc3380f9bfb08502db0bc44934d333b /src/H5FD.c
parent2910c496e1a0e507fdb4a0e8d8978f36cca66a59 (diff)
downloadhdf5-312cd2c57d7a8488e2a21d65c074862cba8e7663.zip
hdf5-312cd2c57d7a8488e2a21d65c074862cba8e7663.tar.gz
hdf5-312cd2c57d7a8488e2a21d65c074862cba8e7663.tar.bz2
[svn-r2501] Added several free lists for commonly used & abused data structures. Also
added code to allow metadata to be allocated out of a more contiguous block ("metadata aggregation") and also code for "catching" small metadata write calls and building a buffer of the small pieces of metadata for later writing as one, larger, block ("metadata accumulation"). These features are enabled on a per VFL driver basis with the new VFL 'query' call and both currently enabled for the sec2, family and stdio drivers. The mpio VFL driver enables only the "metadata aggregation" code, not the "metadata accumulation" code. All the other drivers have these features turned off.
Diffstat (limited to 'src/H5FD.c')
-rw-r--r--src/H5FD.c645
1 files changed, 525 insertions, 120 deletions
diff --git a/src/H5FD.c b/src/H5FD.c
index eb53777..d32b179 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -17,6 +17,7 @@
#include <H5Eprivate.h> /*error handling */
#include <H5Fprivate.h> /*files */
#include <H5FDprivate.h> /*virtual file driver */
+#include <H5FLprivate.h> /*Free Lists */
#include <H5Iprivate.h> /*interface abstraction layer */
#include <H5MMprivate.h> /*memory management */
#include <H5Pprivate.h> /*property lists */
@@ -29,6 +30,10 @@ static intn interface_initialize_g = 0;
/* static prototypes */
static herr_t H5FD_init_interface(void);
static herr_t H5FD_free_cls(H5FD_class_t *cls);
+static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size);
+
+/* Declare a PQ free list to manage the metadata accumulator buffer */
+H5FL_BLK_DEFINE_STATIC(meta_accum);
/*-------------------------------------------------------------------------
@@ -782,7 +787,13 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
file->cls = driver;
file->maxaddr = maxaddr;
HDmemset(file->fl, 0, sizeof(file->fl));
+ file->def_meta_block_size = fapl->meta_block_size;
+ file->accum_loc = HADDR_UNDEF;
+ /* Retrieve the VFL driver feature flags */
+ if (H5FD_query(file, &(file->feature_flags))<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to query file driver");
+
FUNC_LEAVE(file);
}
@@ -856,6 +867,7 @@ H5FD_close(H5FD_t *file)
assert(file && file->cls);
/* Free all free-lists, leaking any memory thus described */
+ /* Also leaks file space allocated but not used when metadata aggregation is turned on */
for (i=H5FD_MEM_DEFAULT; i<H5FD_MEM_NTYPES; i++) {
for (cur=file->fl[i]; cur; cur=next) {
#ifdef H5F_DEBUG
@@ -875,6 +887,18 @@ H5FD_close(H5FD_t *file)
}
#endif
+ /* Check if we need to reset the metadata accumulator information */
+ if(file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) {
+ /* Free the buffer */
+ if(file->meta_accum!=NULL)
+ file->meta_accum=H5FL_BLK_FREE(meta_accum,file->meta_accum);
+
+ /* Reset the buffer sizes & location */
+ file->accum_buf_size=file->accum_size=0;
+ file->accum_loc=HADDR_UNDEF;
+ file->accum_dirty=0;
+ } /* end if */
+
/* Prepare to close file by clearing all public fields */
driver = file->cls;
H5I_dec_ref(file->driver_id);
@@ -973,6 +997,74 @@ H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2)
/*-------------------------------------------------------------------------
+ * Function: H5FDquery
+ *
+ * Purpose: Query a VFL driver for its feature flags. (listed in H5FDpublic.h)
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 25, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FDquery(const H5FD_t *f, unsigned long *flags)
+{
+ intn ret_value;
+
+ FUNC_ENTER(H5FDquery, FAIL);
+
+ assert(f);
+ assert(flags);
+
+ ret_value = H5FD_query(f, flags);
+
+ FUNC_LEAVE(ret_value);
+} /* end H5FDquery() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_query
+ *
+ * Purpose: Private version of H5FDquery()
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 25, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FD_query(const H5FD_t *f, unsigned long *flags)
+{
+ intn ret_value=0;
+
+ FUNC_ENTER(H5FD_query, FAIL);
+
+ assert(f);
+ assert(flags);
+
+ /* Check for query driver and call it */
+ if (f->cls->query)
+ ret_value = (f->cls->query)(f, flags);
+ else
+ *flags=0;
+
+ FUNC_LEAVE(ret_value);
+} /* end H5FD_query() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FDalloc
*
* Purpose: Allocates SIZE bytes of memory from the FILE. The memory will
@@ -1076,9 +1168,9 @@ H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size)
/* Map the allocation request to a free list */
if (H5FD_MEM_DEFAULT==file->cls->fl_map[type]) {
- mapped_type = type;
+ mapped_type = type;
} else {
- mapped_type = file->cls->fl_map[type];
+ mapped_type = file->cls->fl_map[type];
}
/*
@@ -1086,61 +1178,140 @@ H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size)
* exact match, otherwise use the best match. Only perform the search if
* the free list has the potential of satisfying the request.
*/
- if (mapped_type>=0 &&
- (0==file->maxsize || size<=file->maxsize)) {
- H5FD_free_t *prev=NULL, *best=NULL;
- H5FD_free_t *cur = file->fl[mapped_type];
- while (cur) {
- file->maxsize = MAX(file->maxsize, cur->size);
- if (cur->size==size) {
- ret_value = cur->addr;
- if (prev) prev->next = cur->next;
- else file->fl[mapped_type] = cur->next;
- H5MM_xfree(cur);
- if (size==file->maxsize) file->maxsize=0; /*unknown*/
- HRETURN(ret_value);
- } else if (cur->size>size &&
- (!best || cur->size<best->size)) {
- best = cur;
- }
- prev = cur;
- cur = cur->next;
- }
- if (best) {
- if (best->size==file->maxsize) file->maxsize=0; /*unknown*/
- ret_value = best->addr;
- best->addr += size;
- best->size -= size;
- HRETURN(ret_value);
- }
+ if (mapped_type>=0 && (0==file->maxsize || size<=file->maxsize)) {
+ H5FD_free_t *prev=NULL, *best=NULL;
+ H5FD_free_t *cur = file->fl[mapped_type];
+
+ while (cur) {
+ file->maxsize = MAX(file->maxsize, cur->size);
+ if (cur->size==size) {
+ ret_value = cur->addr;
+ if (prev)
+ prev->next = cur->next;
+ else
+ file->fl[mapped_type] = cur->next;
+ H5MM_xfree(cur);
+ if (size==file->maxsize)
+ file->maxsize=0; /*unknown*/
+ HRETURN(ret_value);
+ } else if (cur->size>size && (!best || cur->size<best->size)) {
+ best = cur;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if (best) {
+ if (best->size==file->maxsize)
+ file->maxsize=0; /*unknown*/
+ ret_value = best->addr;
+ best->addr += size;
+ best->size -= size;
+ HRETURN(ret_value);
+ }
}
/*
+ * If the metadata aggregation feature is enabled for this VFL driver,
+ * allocate "generic" metadata space and sub-allocate out of that, if
+ * possible. Otherwise just allocate through H5FD_real_alloc()
+ */
+ /* Allocate all types of metadata out of the metadata block */
+ if((file->feature_flags&H5FD_FEAT_AGGREGATE_METADATA) && type!=H5FD_MEM_DRAW) {
+ /* Check if the space requested is larger than the space left in the block */
+ if(size>file->cur_meta_block_size) {
+ /* Check if the block asked for is too large for a metadata block */
+ if(size>=file->def_meta_block_size) {
+ /* Allocate just enough room for this new block the regular way */
+ ret_value=H5FD_real_alloc(file,type,size);
+ } /* end if */
+ else {
+ /*
+ * Instead of just dropping the remainder of the block on the
+ * floor and leaving the space in the file unused, we should
+ * return this small piece of unused space to the free list
+ * management. - QAK
+ */
+
+ /* Allocate another metadata block */
+ file->eoma=H5FD_real_alloc(file,H5FD_MEM_DEFAULT,file->def_meta_block_size);
+ file->cur_meta_block_size=file->def_meta_block_size;
+
+ /* Allocate space out of the metadata block */
+ ret_value=file->eoma;
+ file->cur_meta_block_size-=size;
+ file->eoma+=size;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Allocate space out of the metadata block */
+ ret_value=file->eoma;
+ file->cur_meta_block_size-=size;
+ file->eoma+=size;
+ } /* end else */
+ } /* end if */
+ else { /* Allocate data the regular way */
+ ret_value=H5FD_real_alloc(file,type,size);
+ } /* end else */
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_real_alloc
+ *
+ * Purpose: Double private version of H5FDalloc() :-)
+ *
+ * Return: Success: The format address of the new file memory.
+ *
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 25, 2000
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF;
+
+ FUNC_ENTER(H5FD_real_alloc, HADDR_UNDEF);
+
+ /* Check args */
+ assert(file && file->cls);
+ assert(type>=0 && type<H5FD_MEM_NTYPES);
+ assert(size>0);
+
+ /*
* Dispatch to driver `alloc' callback or extend the end-of-address
* marker
*/
if (file->cls->alloc) {
- ret_value = (file->cls->alloc)(file, type, size);
- if (HADDR_UNDEF==ret_value) {
- HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
- "driver allocation request failed");
- }
+ ret_value = (file->cls->alloc)(file, type, size);
+ if (HADDR_UNDEF==ret_value) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "driver allocation request failed");
+ }
} else {
- haddr_t eoa = (file->cls->get_eoa)(file);
- if (H5F_addr_overflow(eoa, size) || eoa+size>file->maxaddr) {
- HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
- "file allocation request failed");
- }
- ret_value = eoa;
- eoa += size;
- if ((file->cls->set_eoa)(file, eoa)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
- "file allocation request failed");
- }
+ haddr_t eoa = (file->cls->get_eoa)(file);
+ if (H5F_addr_overflow(eoa, size) || eoa+size>file->maxaddr) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation request failed");
+ }
+ ret_value = eoa;
+ eoa += size;
+ if ((file->cls->set_eoa)(file, eoa)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation request failed");
+ }
}
FUNC_LEAVE(ret_value);
-}
+} /* end H5FD_real_alloc() */
+
/*-------------------------------------------------------------------------
@@ -1172,15 +1343,15 @@ H5FDfree(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size)
/* Check args */
if (!file || !file->cls) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer");
}
if (type<0 || type>=H5FD_MEM_NTYPES) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid request type");
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid request type");
}
/* Do the real work */
if (H5FD_free(file, type, addr, size)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
"file deallocation request failed");
}
@@ -1215,15 +1386,15 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size)
assert(file && file->cls);
assert(type>=0 && type<H5FD_MEM_NTYPES);
if (!H5F_addr_defined(addr) || addr>file->maxaddr || 0==size ||
- H5F_addr_overflow(addr, size) || addr+size>file->maxaddr) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region");
+ H5F_addr_overflow(addr, size) || addr+size>file->maxaddr) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region");
}
/* Map request type to free list */
if (H5FD_MEM_DEFAULT==file->cls->fl_map[type]) {
- mapped_type = type;
+ mapped_type = type;
} else {
- mapped_type = file->cls->fl_map[type];
+ mapped_type = file->cls->fl_map[type];
}
/*
@@ -1232,21 +1403,22 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size)
* driver deallocate the memory.
*/
if (mapped_type>=0) {
- H5FD_free_t *cur = H5MM_malloc(sizeof(H5FD_free_t));
- cur->addr = addr;
- cur->size = size;
- cur->next = file->fl[mapped_type];
- file->fl[mapped_type] = cur;
- if (file->maxsize && size>file->maxsize) {
- file->maxsize = size;
- }
+ H5FD_free_t *cur = H5MM_malloc(sizeof(H5FD_free_t));
+
+ cur->addr = addr;
+ cur->size = size;
+ cur->next = file->fl[mapped_type];
+ file->fl[mapped_type] = cur;
+ if (file->maxsize && size>file->maxsize) {
+ file->maxsize = size;
+ }
} else if (file->cls->free) {
- if ((file->cls->free)(file, type, addr, size)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
- "driver free request failed");
- }
+ if ((file->cls->free)(file, type, addr, size)<0) {
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
+ "driver free request failed");
+ }
} else {
- /* leak memory */
+ /* leak memory */
}
FUNC_LEAVE(SUCCEED);
@@ -1318,47 +1490,46 @@ H5FD_realloc(H5FD_t *file, H5FD_mem_t type, haddr_t old_addr, hsize_t old_size,
FUNC_ENTER(H5FD_realloc, HADDR_UNDEF);
if (new_size==old_size) {
- /*nothing to do*/
+ /*nothing to do*/
} else if (0==old_size) {
- /* allocate memory */
- assert(!H5F_addr_defined(old_addr));
- if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
- HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
- "file allocation failed");
- }
-
+ /* allocate memory */
+ assert(!H5F_addr_defined(old_addr));
+ if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
+ HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation failed");
+ }
} else if (0==new_size) {
- /* free memory */
- assert(H5F_addr_defined(old_addr));
- H5FDfree(file, type, old_addr, old_size);
- new_addr = HADDR_UNDEF;
-
+ /* free memory */
+ assert(H5F_addr_defined(old_addr));
+ H5FDfree(file, type, old_addr, old_size);
+ new_addr = HADDR_UNDEF;
+
} else if (new_size<old_size) {
- /* free the end of the block */
- H5FDfree(file, type, old_addr+old_size, old_size-new_size);
-
+ /* free the end of the block */
+ H5FDfree(file, type, old_addr+old_size, old_size-new_size);
} else {
- /* move memory to new location */
- if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
- HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
- "file allocation failed");
- }
- if (old_size>sizeof(_buf) && NULL==(buf=H5MM_malloc(old_size))) {
- H5FDfree(file, type, new_addr, new_size);
- HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF,
- "memory allocation failed");
- }
- if (H5FDread(file, H5P_DEFAULT, old_addr, old_size, buf)<0 ||
- H5FDwrite(file, H5P_DEFAULT, new_addr, old_size, buf)) {
- H5FDfree(file, type, new_addr, new_size);
- H5MM_xfree(buf);
- HRETURN_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF,
- "unable to move file block");
- }
-
- if (buf!=_buf) H5MM_xfree(buf);
- H5FDfree(file, type, old_addr, old_size);
+ /* move memory to new location */
+ if (HADDR_UNDEF==(new_addr=H5FDalloc(file, type, new_size))) {
+ HRETURN_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF,
+ "file allocation failed");
+ }
+ if (old_size>sizeof(_buf) && NULL==(buf=H5MM_malloc(old_size))) {
+ H5FDfree(file, type, new_addr, new_size);
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF,
+ "memory allocation failed");
+ }
+ if (H5FDread(file, H5P_DEFAULT, old_addr, old_size, buf)<0 ||
+ H5FDwrite(file, type, H5P_DEFAULT, new_addr, old_size, buf)) {
+ H5FDfree(file, type, new_addr, new_size);
+ H5MM_xfree(buf);
+ HRETURN_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF,
+ "unable to move file block");
+ }
+
+ if (buf!=_buf)
+ H5MM_xfree(buf);
+ H5FDfree(file, type, old_addr, old_size);
}
FUNC_LEAVE(new_addr);
@@ -1693,11 +1864,68 @@ H5FD_read(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
/* The no-op case */
if (0==size) HRETURN(SUCCEED);
- /* Dispatch to driver */
- if ((file->cls->read)(file, dxpl_id, addr, size, buf)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
- "driver read request failed");
- }
+ /* Check if this information is in the metadata accumulator */
+ if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) &&
+ ((addr>=file->accum_loc && addr <=(file->accum_loc+file->accum_size))
+ || ((addr+size)>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size))
+ || (addr<file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size)))) {
+
+ unsigned char *read_buf=(unsigned char *)buf; /* Pointer to the buffer being read in */
+ hsize_t amount_read; /* Amount to read at a time */
+ hsize_t read_off; /* Offset to read from */
+
+ /* Read the part before the metadata accumulator */
+ if(addr<file->accum_loc) {
+ /* Set the amount to read */
+ amount_read=file->accum_loc-addr;
+
+ /* Dispatch to driver */
+ if ((file->cls->read)(file, dxpl_id, addr, amount_read, read_buf)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver read request failed");
+
+ /* Adjust the buffer, address & size */
+ read_buf+=amount_read;
+ addr+=amount_read;
+ size-=amount_read;
+ } /* end if */
+
+ /* Read the part overlapping the metadata accumulator */
+ if(size>0 && (addr>=file->accum_loc && addr<(file->accum_loc+file->accum_size))) {
+ /* Set the offset to "read" from */
+ read_off=addr-file->accum_loc;
+
+ /* Set the amount to "read" */
+ amount_read=MIN((file->accum_size-read_off),size);
+
+ /* Copy the data out of the buffer */
+ HDmemcpy(read_buf,file->meta_accum+read_off,amount_read);
+
+ /* Adjust the buffer, address & size */
+ read_buf+=amount_read;
+ addr+=amount_read;
+ size-=amount_read;
+ } /* end if */
+
+ /* Read the part after the metadata accumulator */
+ if(size>0 && addr>=(file->accum_loc+file->accum_size)) {
+ /* Dispatch to driver */
+ if ((file->cls->read)(file, dxpl_id, addr, size, read_buf)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver read request failed");
+
+ /* Adjust the buffer, address & size */
+ read_buf+=size;
+ addr+=size;
+ size-=size;
+ } /* end if */
+
+ /* Make certain we've read it all */
+ assert(size==0);
+ } /* end if */
+ else {
+ /* Dispatch to driver */
+ if ((file->cls->read)(file, dxpl_id, addr, size, buf)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver read request failed");
+ } /* end else */
FUNC_LEAVE(SUCCEED);
}
@@ -1723,7 +1951,7 @@ H5FD_read(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
*-------------------------------------------------------------------------
*/
herr_t
-H5FDwrite(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size,
const void *buf)
{
FUNC_ENTER(H5FDwrite, FAIL);
@@ -1744,7 +1972,7 @@ H5FDwrite(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
}
/* The real work */
- if (H5FD_write(file, dxpl_id, addr, size, buf)<0) {
+ if (H5FD_write(file, type, dxpl_id, addr, size, buf)<0) {
HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
"file write request failed");
}
@@ -1770,9 +1998,12 @@ H5FDwrite(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_write(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
+H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size,
const void *buf)
{
+ size_t new_size; /* New size of the accumulator buffer */
+ size_t old_offset; /* Offset of old data within the accumulator buffer */
+
FUNC_ENTER(H5FD_write, FAIL);
assert(file && file->cls);
assert(H5P_DEFAULT==dxpl_id ||
@@ -1782,11 +2013,177 @@ H5FD_write(H5FD_t *file, hid_t dxpl_id, haddr_t addr, hsize_t size,
/* The no-op case */
if (0==size) HRETURN(SUCCEED);
- /* Dispatch to driver */
- if ((file->cls->write)(file, dxpl_id, addr, size, buf)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
- "driver write request failed");
- }
+ /* Check for accumulating metadata */
+ if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
+ /* Check if there is already metadata in the accumulator */
+ if(file->accum_size>0) {
+ /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */
+ if((addr>=file->accum_loc && addr <=(file->accum_loc+file->accum_size))
+ || ((addr+size)>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size))
+ || (addr<file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size))) {
+
+ /* Check if the new metadata adjoins the beginning of the current accumulator */
+ if((addr+size)==file->accum_loc) {
+ /* Check if we need more buffer space */
+ if((size+file->accum_size)>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size+file->accum_size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=size+file->accum_size;
+ } /* end if */
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(file->meta_accum+size,file->meta_accum,file->accum_size);
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(file->meta_accum,buf,size);
+
+ /* Set the new size & location of the metadata accumulator */
+ file->accum_loc=addr;
+ file->accum_size=file->accum_size+size;
+
+ /* Mark it as written to */
+ file->accum_dirty=TRUE;
+ } /* end if */
+ /* Check if the new metadata adjoins the end of the current accumulator */
+ else if(addr==(file->accum_loc+file->accum_size)) {
+ /* Check if we need more buffer space */
+ if((size+file->accum_size)>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size+file->accum_size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=size+file->accum_size;
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(file->meta_accum+file->accum_size,buf,size);
+
+ /* Set the new size of the metadata accumulator */
+ file->accum_size=file->accum_size+size;
+
+ /* Mark it as written to */
+ file->accum_dirty=TRUE;
+ } /* end if */
+ /* Check if the new metadata is entirely within the current accumulator */
+ else if(addr>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
+ /* Copy the new metadata to the proper location within the accumulator */
+ HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
+
+ /* Mark it as written to */
+ file->accum_dirty=TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the beginning of the current accumulator */
+ else if(addr<file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ new_size=(file->accum_loc-addr)+file->accum_size;
+
+ /* Check if we need more buffer space */
+ if(new_size>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=new_size;
+ } /* end if */
+
+ /* Calculate the proper offset of the existing metadata */
+ old_offset=(addr+size)-file->accum_loc;
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(file->meta_accum+size,file->meta_accum+old_offset,file->accum_size-old_offset);
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(file->meta_accum,buf,size);
+
+ /* Set the new size & location of the metadata accumulator */
+ file->accum_loc=addr;
+ file->accum_size=new_size;
+
+ /* Mark it as written to */
+ file->accum_dirty=TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the end of the current accumulator */
+ else if(addr>=file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size)) {
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ new_size=file->accum_size+((addr+size)-(file->accum_loc+file->accum_size));
+
+ /* Check if we need more buffer space */
+ if(new_size>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=new_size;
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
+
+ /* Set the new size & location of the metadata accumulator */
+ file->accum_loc=addr;
+ file->accum_size=new_size;
+
+ /* Mark it as written to */
+ file->accum_dirty=TRUE;
+ } /* end if */
+ else {
+ assert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
+ } /* end else */
+ } /* end if */
+ /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
+ else {
+ /* Write out the existing metadata accumulator, with dispatch to driver */
+ if ((file->cls->write)(file, type, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed");
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to reallocate the buffer */
+ if(size>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=size;
+ } /* end if */
+
+ /* Store the piece of metadata in the accumulator */
+ file->accum_loc=addr;
+ file->accum_size=size;
+ file->accum_dirty=TRUE;
+ HDmemcpy(file->meta_accum,buf,size);
+ } /* end else */
+ } /* end if */
+ /* No metadata in the accumulator, grab this piece and keep it */
+ else {
+ /* Check if we need to reallocate the buffer */
+ if(size>file->accum_buf_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate metadata accumulator buffer");
+
+ /* Note the new buffer size */
+ file->accum_buf_size=size;
+ } /* end if */
+
+ /* Store the piece of metadata in the accumulator */
+ file->accum_loc=addr;
+ file->accum_size=size;
+ file->accum_dirty=TRUE;
+ HDmemcpy(file->meta_accum,buf,size);
+ } /* end else */
+ } /* end if */
+ else {
+ /* Dispatch to driver */
+ if ((file->cls->write)(file, type, dxpl_id, addr, size, buf)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed");
+ } /* end else */
FUNC_LEAVE(SUCCEED);
}
@@ -1852,11 +2249,19 @@ H5FD_flush(H5FD_t *file)
FUNC_ENTER(H5FD_flush, FAIL);
assert(file && file->cls);
- if (file->cls->flush &&
- (file->cls->flush)(file)<0) {
- HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL,
- "driver flush request failed");
- }
+ /* Check if we need to flush out the metadata accumulator */
+ if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && file->accum_dirty && file->accum_size>0) {
+ /* Flush the metadata contents */
+ /* Not certain if the type and dxpl should be the way they are... -QAK */
+ if ((file->cls->write)(file, H5FD_MEM_DEFAULT, H5P_DEFAULT, file->accum_loc, file->accum_size, file->meta_accum)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed");
+
+ /* Reset the dirty flag */
+ file->accum_dirty=FALSE;
+ } /* end if */
+
+ if (file->cls->flush && (file->cls->flush)(file)<0)
+ HRETURN_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed");
FUNC_LEAVE(SUCCEED);
}