diff options
Diffstat (limited to 'src/H5Olayout.c')
-rw-r--r-- | src/H5Olayout.c | 387 |
1 files changed, 283 insertions, 104 deletions
diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 5dca442..15013ee 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -58,9 +58,11 @@ const H5O_class_t H5O_LAYOUT[1] = {{ }}; /* For forward and backward compatibility. Version is 1 when space is - * allocated; 2 when space is delayed for allocation. */ + * allocated; 2 when space is delayed for allocation; 3 + * is revised to just store information needed for each storage type. */ #define H5O_LAYOUT_VERSION_1 1 #define H5O_LAYOUT_VERSION_2 2 +#define H5O_LAYOUT_VERSION_3 3 /* Interface initialization */ #define PABLO_MASK H5O_layout_mask @@ -98,7 +100,6 @@ static void * H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) { H5O_layout_t *mesg = NULL; - int version; unsigned u; void *ret_value; /* Return value */ @@ -114,44 +115,108 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Version. 1 when space allocated; 2 when space allocation is delayed */ - version = *p++; - if (version!=H5O_LAYOUT_VERSION_1 && version!=H5O_LAYOUT_VERSION_2) + mesg->version = *p++; + if (mesg->version<H5O_LAYOUT_VERSION_1 || mesg->version>H5O_LAYOUT_VERSION_3) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for layout message"); - /* Dimensionality */ - mesg->ndims = *p++; - if (mesg->ndims>H5O_LAYOUT_NDIMS) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large"); - - /* Layout class */ - mesg->type = *p++; - assert(H5D_CONTIGUOUS == mesg->type || H5D_CHUNKED == mesg->type || H5D_COMPACT == mesg->type); - - /* Reserved bytes */ - p += 5; - - /* Address */ - if(mesg->type!=H5D_COMPACT) - H5F_addr_decode(f, &p, &(mesg->addr)); - - /* Read the size */ - for (u = 0; u < mesg->ndims; u++) - UINT32DECODE(p, mesg->dim[u]); - - if(mesg->type == H5D_COMPACT) { - UINT32DECODE(p, mesg->size); - if(mesg->size > 0) { - if(NULL==(mesg->buf=H5MM_malloc(mesg->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value"); - HDmemcpy(mesg->buf, p, mesg->size); - p += mesg->size; + if(mesg->version < H5O_LAYOUT_VERSION_3) { + unsigned ndims; /* Num dimensions in chunk */ + + /* Dimensionality */ + ndims = *p++; + if (ndims>H5O_LAYOUT_NDIMS) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large"); + + /* Layout class */ + mesg->type = *p++; + assert(H5D_CONTIGUOUS == mesg->type || H5D_CHUNKED == mesg->type || H5D_COMPACT == mesg->type); + + /* Reserved bytes */ + p += 5; + + /* Address */ + if(mesg->type==H5D_CONTIGUOUS) + H5F_addr_decode(f, &p, &(mesg->u.contig.addr)); + else if(mesg->type==H5D_CHUNKED) + H5F_addr_decode(f, &p, &(mesg->u.chunk.addr)); + + /* Read the size */ + if(mesg->type!=H5D_CHUNKED) { + mesg->unused.ndims=ndims; + + for (u = 0; u < ndims; u++) + UINT32DECODE(p, mesg->unused.dim[u]); + + /* Don't compute size of contiguous storage here, due to possible + * truncation of the dimension sizes when they were stored in this + * version of the layout message. Compute the contiguous storage + * size in the dataset code, where we've got the dataspace + * information available also. - QAK 5/26/04 + */ + } /* end if */ + else { + mesg->u.chunk.ndims=ndims; + for (u = 0; u < ndims; u++) + UINT32DECODE(p, mesg->u.chunk.dim[u]); + + /* Compute chunk size */ + for (u=1, mesg->u.chunk.size=mesg->u.chunk.dim[0]; u<ndims; u++) + mesg->u.chunk.size *= mesg->u.chunk.dim[u]; + } /* end if */ + + if(mesg->type == H5D_COMPACT) { + UINT32DECODE(p, mesg->u.compact.size); + if(mesg->u.compact.size > 0) { + if(NULL==(mesg->u.compact.buf=H5MM_malloc(mesg->u.compact.size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer"); + HDmemcpy(mesg->u.compact.buf, p, mesg->u.compact.size); + p += mesg->u.compact.size; + } } - } - else if(mesg->type == H5D_CHUNKED || mesg->type == H5D_CONTIGUOUS) { - /* Compute chunk size */ - for (u=1, mesg->chunk_size=mesg->dim[0]; u<mesg->ndims; u++) - mesg->chunk_size *= mesg->dim[u]; } /* end if */ + else { + /* Layout class */ + mesg->type = *p++; + + /* Interpret the rest of the message according to the layout class */ + switch(mesg->type) { + case H5D_CONTIGUOUS: + H5F_addr_decode(f, &p, &(mesg->u.contig.addr)); + H5F_DECODE_LENGTH(f, p, mesg->u.contig.size); + break; + + case H5D_CHUNKED: + /* Dimensionality */ + mesg->u.chunk.ndims = *p++; + if (mesg->u.chunk.ndims>H5O_LAYOUT_NDIMS) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large"); + + /* B-tree address */ + H5F_addr_decode(f, &p, &(mesg->u.chunk.addr)); + + /* Chunk dimensions */ + for (u = 0; u < mesg->u.chunk.ndims; u++) + UINT32DECODE(p, mesg->u.chunk.dim[u]); + + /* Compute chunk size */ + for (u=1, mesg->u.chunk.size=mesg->u.chunk.dim[0]; u<mesg->u.chunk.ndims; u++) + mesg->u.chunk.size *= mesg->u.chunk.dim[u]; + break; + + case H5D_COMPACT: + UINT16DECODE(p, mesg->u.compact.size); + if(mesg->u.compact.size > 0) { + if(NULL==(mesg->u.compact.buf=H5MM_malloc(mesg->u.compact.size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer"); + HDmemcpy(mesg->u.compact.buf, p, mesg->u.compact.size); + p += mesg->u.compact.size; + } /* end if */ + break; + + default: + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "Invalid layout class"); + } /* end switch */ + } /* end else */ /* Set return value */ ret_value=mesg; @@ -197,45 +262,87 @@ H5O_layout_encode(H5F_t *f, uint8_t *p, const void *_mesg) /* check args */ assert(f); assert(mesg); - assert(mesg->ndims > 0 && mesg->ndims <= H5O_LAYOUT_NDIMS); + assert(mesg->version>0); assert(p); - /* Version: 1 when space allocated; 2 when space allocation is delayed */ - if(mesg->type==H5D_CONTIGUOUS) { - if(mesg->addr==HADDR_UNDEF) - *p++ = H5O_LAYOUT_VERSION_2; - else - *p++ = H5O_LAYOUT_VERSION_1; - } else if(mesg->type==H5D_COMPACT) { - *p++ = H5O_LAYOUT_VERSION_2; - } else - *p++ = H5O_LAYOUT_VERSION_1; - - /* number of dimensions */ - *p++ = mesg->ndims; - - /* layout class */ - *p++ = mesg->type; - - /* reserved bytes should be zero */ - for (u=0; u<5; u++) - *p++ = 0; - - /* data or B-tree address */ - if(mesg->type!=H5D_COMPACT) - H5F_addr_encode(f, &p, mesg->addr); - - /* dimension size */ - for (u = 0; u < mesg->ndims; u++) - UINT32ENCODE(p, mesg->dim[u]); - - if(mesg->type==H5D_COMPACT) { - UINT32ENCODE(p, mesg->size); - if(mesg->size>0 && mesg->buf) { - HDmemcpy(p, mesg->buf, mesg->size); - p += mesg->size; + /* Version */ + *p++ = mesg->version; + + /* Check for which information to write */ + if(mesg->version<3) { + /* number of dimensions */ + assert(mesg->unused.ndims > 0 && mesg->unused.ndims <= H5O_LAYOUT_NDIMS); + *p++ = mesg->unused.ndims; + + /* layout class */ + *p++ = mesg->type; + + /* reserved bytes should be zero */ + for (u=0; u<5; u++) + *p++ = 0; + + /* data or B-tree address */ + if(mesg->type==H5D_CONTIGUOUS) + H5F_addr_encode(f, &p, mesg->u.contig.addr); + else if(mesg->type==H5D_CHUNKED) + H5F_addr_encode(f, &p, mesg->u.chunk.addr); + + /* dimension size */ + if(mesg->type!=H5D_CHUNKED) + for (u = 0; u < mesg->unused.ndims; u++) + UINT32ENCODE(p, mesg->unused.dim[u]) + else + for (u = 0; u < mesg->u.chunk.ndims; u++) + UINT32ENCODE(p, mesg->u.chunk.dim[u]); + + if(mesg->type==H5D_COMPACT) { + UINT32ENCODE(p, mesg->u.compact.size); + if(mesg->u.compact.size>0 && mesg->u.compact.buf) { + HDmemcpy(p, mesg->u.compact.buf, mesg->u.compact.size); + p += mesg->u.compact.size; + } } - } + } /* end if */ + else { + /* Layout class */ + *p++ = mesg->type; + + /* Write out layout class specific information */ + switch(mesg->type) { + case H5D_CONTIGUOUS: + H5F_addr_encode(f, &p, mesg->u.contig.addr); + H5F_ENCODE_LENGTH(f, p, mesg->u.contig.size); + break; + + case H5D_CHUNKED: + /* Number of dimensions */ + assert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); + *p++ = mesg->u.chunk.ndims; + + /* B-tree address */ + H5F_addr_encode(f, &p, mesg->u.chunk.addr); + + /* Dimension sizes */ + for (u = 0; u < mesg->u.chunk.ndims; u++) + UINT32ENCODE(p, mesg->u.chunk.dim[u]); + break; + + case H5D_COMPACT: + /* Size of raw data */ + UINT16ENCODE(p, mesg->u.compact.size); + + /* Raw data */ + if(mesg->u.compact.size>0 && mesg->u.compact.buf) { + HDmemcpy(p, mesg->u.compact.buf, mesg->u.compact.size); + p += mesg->u.compact.size; + } /* end if */ + break; + + default: + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "Invalid layout class"); + break; + } /* end switch */ + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -279,11 +386,11 @@ H5O_layout_copy(const void *_mesg, void *_dest) /* Deep copy the buffer for compact datasets also */ if(mesg->type==H5D_COMPACT) { /* Allocate memory for the raw data */ - if (NULL==(dest->buf=H5MM_malloc(dest->size))) + if (NULL==(dest->u.compact.buf=H5MM_malloc(dest->u.compact.size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for compact dataset"); /* Copy over the raw data */ - HDmemcpy(dest->buf,mesg->buf,dest->size); + HDmemcpy(dest->u.compact.buf,mesg->u.compact.buf,dest->u.compact.size); } /* end if */ /* Set return value */ @@ -315,7 +422,8 @@ done: size_t H5O_layout_meta_size(H5F_t *f, const void *_mesg) { - const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; + /* Casting away const OK - QAK */ + H5O_layout_t *mesg = (H5O_layout_t *) _mesg; size_t ret_value; FUNC_ENTER_NOAPI(H5O_layout_meta_size, 0); @@ -323,18 +431,80 @@ H5O_layout_meta_size(H5F_t *f, const void *_mesg) /* check args */ assert(f); assert(mesg); - assert(mesg->ndims > 0 && mesg->ndims <= H5O_LAYOUT_NDIMS); - ret_value = 1 + /* Version number */ - 1 + /* layout class type */ - 1 + /* dimensionality */ - 5 + /* reserved bytes */ - mesg->ndims * 4; /* size of each dimension */ + /* Check version information for new datasets */ + if(mesg->version==0) { + unsigned u; + + /* Check for dimension that would be truncated */ + assert(mesg->unused.ndims > 0 && mesg->unused.ndims <= H5O_LAYOUT_NDIMS); + for (u = 0; u < mesg->unused.ndims; u++) + if(mesg->unused.dim[u]!=(0xffffffff&mesg->unused.dim[u])) { + /* Make certain the message is encoded with the new version */ + mesg->version=3; + break; + } /* end if */ + + /* If the message doesn't _have_ to be encoded with the new version */ + if(mesg->version==0) { + /* Version: 1 when space allocated; 2 when space allocation is delayed */ + if(mesg->type==H5D_CONTIGUOUS) { + if(mesg->u.contig.addr==HADDR_UNDEF) + mesg->version = H5O_LAYOUT_VERSION_2; + else + mesg->version = H5O_LAYOUT_VERSION_1; + } else if(mesg->type==H5D_COMPACT) { + mesg->version = H5O_LAYOUT_VERSION_2; + } else + mesg->version = H5O_LAYOUT_VERSION_1; + } /* end if */ + } /* end if */ + assert(mesg->version>0); - if(mesg->type==H5D_COMPACT) - ret_value += 4; /* size field for compact dataset */ - else - ret_value += H5F_SIZEOF_ADDR(f); /* file address of data or B-tree for chunked dataset */ + if(mesg->version<H5O_LAYOUT_VERSION_3) { + ret_value = 1 + /* Version number */ + 1 + /* layout class type */ + 1 + /* dimensionality */ + 5 + /* reserved bytes */ + mesg->unused.ndims * 4; /* size of each dimension */ + + if(mesg->type==H5D_COMPACT) + ret_value += 4; /* size field for compact dataset */ + else + ret_value += H5F_SIZEOF_ADDR(f); /* file address of data or B-tree for chunked dataset */ + } /* end if */ + else { + ret_value = 1 + /* Version number */ + 1; /* layout class type */ + + switch(mesg->type) { + case H5D_CONTIGUOUS: + ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */ + ret_value += H5F_SIZEOF_SIZE(f); /* Length of data */ + break; + + case H5D_CHUNKED: + /* Number of dimensions (1 byte) */ + assert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); + ret_value++; + + /* B-tree address */ + ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */ + + /* Dimension sizes */ + ret_value += mesg->u.chunk.ndims*4; + break; + + case H5D_COMPACT: + /* Size of raw data */ + ret_value+=2; + break; + + default: + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, 0, "Invalid layout class"); + break; + } /* end switch */ + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value); @@ -370,11 +540,10 @@ H5O_layout_size(H5F_t *f, const void *_mesg) /* check args */ assert(f); assert(mesg); - assert(mesg->ndims > 0 && mesg->ndims <= H5O_LAYOUT_NDIMS); ret_value = H5O_layout_meta_size(f, mesg); if(mesg->type==H5D_COMPACT) - ret_value += mesg->size;/* data for compact dataset */ + ret_value += mesg->u.compact.size;/* data for compact dataset */ done: FUNC_LEAVE_NOAPI(ret_value); } @@ -406,10 +575,11 @@ H5O_layout_reset (void *_mesg) if(mesg) { /* Free the compact storage buffer */ if(mesg->type==H5D_COMPACT) - mesg->buf=H5MM_xfree(mesg->buf); + mesg->u.compact.buf=H5MM_xfree(mesg->u.compact.buf); /* Reset the message */ mesg->type=H5D_CONTIGUOUS; + mesg->version=0; } /* end if */ done: @@ -443,7 +613,7 @@ H5O_layout_free (void *_mesg) /* Free the compact storage buffer */ if(mesg->type==H5D_COMPACT) - mesg->buf=H5MM_xfree(mesg->buf); + mesg->u.compact.buf=H5MM_xfree(mesg->u.compact.buf); H5FL_FREE(H5O_layout_t,mesg); @@ -536,21 +706,30 @@ H5O_layout_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE assert(indent >= 0); assert(fwidth >= 0); - HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, - H5D_CHUNKED == mesg->type ? "B-tree address:" : "Data address:", - mesg->addr); - - HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, - "Number of dimensions:", - (unsigned long) (mesg->ndims)); - - /* Size */ - HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Size:"); - for (u = 0; u < mesg->ndims; u++) { - HDfprintf(stream, "%s%lu", u ? ", " : "", - (unsigned long) (mesg->dim[u])); - } - HDfprintf(stream, "}\n"); + if(mesg->type==H5D_CHUNKED) { + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "B-tree address:", mesg->u.chunk.addr); + HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Number of dimensions:", + (unsigned long) (mesg->u.chunk.ndims)); + /* Size */ + HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Size:"); + for (u = 0; u < mesg->u.chunk.ndims; u++) { + HDfprintf(stream, "%s%lu", u ? ", " : "", + (unsigned long) (mesg->u.chunk.dim[u])); + } + HDfprintf(stream, "}\n"); + } /* end if */ + else if(mesg->type==H5D_CONTIGUOUS) { + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Data address:", mesg->u.contig.addr); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Data Size:", mesg->u.contig.size); + } /* end if */ + else { + HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, + "Data Size:", mesg->u.compact.size); + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value); |