summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);
}