summaryrefslogtreecommitdiffstats
path: root/src/H5FD.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5FD.c')
-rw-r--r--src/H5FD.c122
1 files changed, 69 insertions, 53 deletions
diff --git a/src/H5FD.c b/src/H5FD.c
index e6f83d4..cec4ae8 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -1930,72 +1930,67 @@ H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t siz
/* Check if this information is in the metadata accumulator */
if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
- /* Current read overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr,size,file->accum_loc,file->accum_size)) {
- unsigned char *read_buf=(unsigned char *)buf; /* Pointer to the buffer being read in */
- size_t amount_read; /* Amount to read at a time */
-#ifndef NDEBUG
- hsize_t tempamount_read; /* Amount to read at a time */
-#endif /* NDEBUG */
- hsize_t read_off; /* Offset to read from */
-
- /* Double check that we aren't reading raw data */
- assert(type!=H5FD_MEM_DRAW);
+ /* Current read adjoins or overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)
+ || ((addr + size) == file->accum_loc)
+ || (file->accum_loc + file->accum_size) == addr) {
+ size_t amount_before; /* Amount to read before current accumulator */
+ haddr_t new_addr; /* New address of the accumulator buffer */
+ size_t new_size; /* New size of the accumulator buffer */
+
+ /* Compute new values for accumulator */
+ new_addr = MIN(addr, file->accum_loc);
+ new_size = (size_t)(MAX((addr + size), (file->accum_loc + file->accum_size))
+ - new_addr);
+
+ /* Check if we need more buffer space */
+ if(new_size > file->accum_buf_size) {
+ /* Adjust the buffer size, by doubling it */
+ file->accum_buf_size = MAX(file->accum_buf_size * 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (file->meta_accum = H5FL_BLK_REALLOC(meta_accum, file->meta_accum, file->accum_buf_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
/* Read the part before the metadata accumulator */
- if(addr<file->accum_loc) {
+ if(addr < file->accum_loc) {
/* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_read,file->accum_loc-addr,hsize_t,size_t);
+ H5_ASSIGN_OVERFLOW(amount_before, (file->accum_loc - addr), hsize_t, size_t);
+
+ /* Make room for the metadata to read in */
+ HDmemmove(file->meta_accum + amount_before, file->meta_accum, file->accum_size);
/* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, amount_read, read_buf) < 0)
+ if((file->cls->read)(file, type, dxpl_id, addr, amount_before, file->meta_accum) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Adjust the buffer, address & size */
- read_buf+=amount_read;
- addr+=amount_read;
- size-=amount_read;
- } /* end if */
-
- /* Copy 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" */
-#ifndef NDEBUG
- tempamount_read = file->accum_size-read_off;
- H5_CHECK_OVERFLOW(tempamount_read,hsize_t,size_t);
- amount_read = MIN(size, (size_t)tempamount_read);
-#else /* NDEBUG */
- amount_read = MIN(size, (size_t)(file->accum_size-read_off));
-#endif /* NDEBUG */
-
- /* 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 */
+ else
+ amount_before = 0;
/* Read the part after the metadata accumulator */
- if(size>0 && addr>=(file->accum_loc+file->accum_size)) {
+ if((addr + size) > (file->accum_loc + file->accum_size)) {
+ size_t amount_after; /* Amount to read at a time */
+
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (file->accum_loc + file->accum_size)), hsize_t, size_t);
+
/* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, read_buf) < 0)
+ if((file->cls->read)(file, type, dxpl_id, (file->accum_loc + file->accum_size), amount_after, (file->meta_accum + file->accum_size + amount_before)) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, 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);
+ /* Copy the data out of the buffer */
+ HDmemcpy(buf, file->meta_accum + (addr - new_addr), size);
+
+ /* Adjust the accumulator address & size */
+ file->accum_loc = new_addr;
+ file->accum_size = new_size;
} /* end if */
- /* Current read doesn't overlap with metadata accumulator, read it into accumulator */
+ /* Current read doesn't adjoin or overlap with metadata accumulator, read it into accumulator */
else {
/* Only update the metadata accumulator if it is not dirty or if
* we are allowed to write the accumulator out during reads (when
@@ -2288,8 +2283,29 @@ HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->a
/* Mark it as written to */
file->accum_dirty=TRUE;
} /* end if */
+ /* New metadata overlaps both ends of the current accumulator */
else {
- assert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
+ /* Check if we need more buffer space */
+ if(size>file->accum_buf_size) {
+ /* Adjust the buffer size, by doubling it */
+ file->accum_buf_size = MAX(file->accum_buf_size * 2, size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (file->meta_accum = H5FL_BLK_REALLOC(meta_accum, file->meta_accum, file->accum_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(file->meta_accum + size, 0, (file->accum_buf_size - size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the buffer */
+ HDmemcpy(file->meta_accum, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ file->accum_size = size;
+
+ /* Mark it as written to */
+ file->accum_dirty = TRUE;
} /* end else */
} /* end if */
/* New piece of metadata doesn't adjoin or overlap the existing accumulator */