/*------------------------------------------------------------------------- * Function: diff_datasetid * * Purpose: check for comparable datasets and read into a compatible * memory type * * Return: Number of differences found * * Programmer: Pedro Vicente, [email protected] * * Date: May 9, 2003 * * Modifications: * * * October 2006: Read by hyperslabs for big datasets. * * A threshold of H5TOOLS_MALLOCSIZE (128 MB) is the limit upon which I/O hyperslab is done * i.e., if the memory needed to read a dataset is greater than this limit, * then hyperslab I/O is done instead of one operation I/O * For each dataset, the memory needed is calculated according to * * memory needed = number of elements * size of each element * * if the memory needed is lower than H5TOOLS_MALLOCSIZE, then the following operations * are done * * H5Dread( input_dataset1 ) * H5Dread( input_dataset2 ) * * with all elements in the datasets selected. If the memory needed is greater than * H5TOOLS_MALLOCSIZE, then the following operations are done instead: * * a strip mine is defined for each dimension k (a strip mine is defined as a * hyperslab whose size is memory manageable) according to the formula * * (1) strip_mine_size[k ] = MIN(dimension[k ], H5TOOLS_BUFSIZE / size of memory type) * * where H5TOOLS_BUFSIZE is a constant currently defined as 1MB. This formula assures * that for small datasets (small relative to the H5TOOLS_BUFSIZE constant), the strip * mine size k is simply defined as its dimension k, but for larger datasets the * hyperslab size is still memory manageable. * a cycle is done until the number of elements in the dataset is reached. In each * iteration, two parameters are defined for the function H5Sselect_hyperslab, * the start and size of each hyperslab, according to * * (2) hyperslab_size [k] = MIN(dimension[k] - hyperslab_offset[k], strip_mine_size [k]) * * where hyperslab_offset [k] is initially set to zero, and later incremented in * hyperslab_size[k] offsets. The reason for the operation * * dimension[k] - hyperslab_offset[k] * * in (2) is that, when using the strip mine size, it assures that the "remaining" part * of the dataset that does not fill an entire strip mine is processed. * *------------------------------------------------------------------------- */ hsize_t diff_datasetid( hid_t did1, hid_t did2, const char *obj1_name, const char *obj2_name, diff_opt_t *options) { hid_t sid1=-1; hid_t sid2=-1; hid_t f_tid1=-1; hid_t f_tid2=-1; hid_t m_tid1=-1; hid_t m_tid2=-1; size_t m_size1; size_t m_size2; H5T_sign_t sign1; H5T_sign_t sign2; int rank1; int rank2; hsize_t nelmts1; hsize_t nelmts2; hsize_t dims1[H5S_MAX_RANK]; hsize_t dims2[H5S_MAX_RANK]; hsize_t maxdim1[H5S_MAX_RANK]; hsize_t maxdim2[H5S_MAX_RANK]; const char *name1=NULL; /* relative names */ const char *name2=NULL; hsize_t storage_size1; hsize_t storage_size2; hsize_t nfound=0; /* number of differences found */ int can_compare=1; /* do diff or not */ void *buf1=NULL; void *buf2=NULL; void *sm_buf1=NULL; void *sm_buf2=NULL; hid_t sm_space; /*stripmine data space */ size_t need; /* bytes needed for malloc */ int i; unsigned int vl_data = 0; /*contains VL datatypes */ /* Get the dataspace handle */ if ( (sid1 = H5Dget_space(did1)) < 0 ) goto error; /* Get rank */ if ( (rank1 = H5Sget_simple_extent_ndims(sid1)) < 0 ) goto error; /* Get the dataspace handle */ if ( (sid2 = H5Dget_space(did2)) < 0 ) goto error; /* Get rank */ if ( (rank2 = H5Sget_simple_extent_ndims(sid2)) < 0 ) goto error; /* Get dimensions */ if ( H5Sget_simple_extent_dims(sid1,dims1,maxdim1) < 0 ) goto error; /* Get dimensions */ if ( H5Sget_simple_extent_dims(sid2,dims2,maxdim2) < 0 ) { goto error; } /*------------------------------------------------------------------------- * get the file data type *------------------------------------------------------------------------- */ /* Get the data type */ if ( (f_tid1 = H5Dget_type(did1)) < 0 ) goto error; /* Get the data type */ if ( (f_tid2 = H5Dget_type(did2)) < 0 ) { goto error; } /*------------------------------------------------------------------------- * check for empty datasets *------------------------------------------------------------------------- */ storage_size1=H5Dget_storage_size(did1); storage_size2=H5Dget_storage_size(did2); if (storage_size1==0 || storage_size2==0) { if ( (options->m_verbose||options->m_list_not_cmp) && obj1_name && obj2_name) parallel_print("Not comparable: <%s> or <%s> is an empty dataset\n", obj1_name, obj2_name); can_compare=0; options->not_cmp=1; } /*------------------------------------------------------------------------- * check for comparable TYPE and SPACE *------------------------------------------------------------------------- */ if (diff_can_type(f_tid1, f_tid2, rank1, rank2, dims1, dims2, maxdim1, maxdim2, obj1_name, obj2_name, options, 0)!=1) { can_compare=0; } /*------------------------------------------------------------------------- * memory type and sizes *------------------------------------------------------------------------- */ if ((m_tid1=h5tools_get_native_type(f_tid1)) < 0) goto error; if ((m_tid2=h5tools_get_native_type(f_tid2)) < 0) goto error; m_size1 = H5Tget_size( m_tid1 ); m_size2 = H5Tget_size( m_tid2 ); /*------------------------------------------------------------------------- * check for different signed/unsigned types *------------------------------------------------------------------------- */ if (can_compare) { sign1=H5Tget_sign(m_tid1); sign2=H5Tget_sign(m_tid2); if ( sign1 != sign2 ) { if ((options->m_verbose||options->m_list_not_cmp) && obj1_name && obj2_name) { parallel_print("Not comparable: <%s> has sign %s ", obj1_name, get_sign(sign1)); parallel_print("and <%s> has sign %s\n", obj2_name, get_sign(sign2)); } can_compare=0; options->not_cmp=1; } } /* Check if type is either VLEN-data or VLEN-string to reclaim any * VLEN memory buffer later */ if( TRUE == h5tools_detect_vlen(m_tid1) ) vl_data = TRUE; /*------------------------------------------------------------------------ * only attempt to compare if possible *------------------------------------------------------------------------- */ if(can_compare) /* it is possible to compare */ { /*----------------------------------------------------------------- * get number of elements *------------------------------------------------------------------ */ nelmts1 = 1; for(i = 0; i < rank1; i++) nelmts1 *= dims1[i]; nelmts2 = 1; for(i = 0; i < rank2; i++) nelmts2 *= dims2[i]; HDassert(nelmts1 == nelmts2); /*----------------------------------------------------------------- * "upgrade" the smaller memory size *------------------------------------------------------------------ */ if (FAIL == match_up_memsize (f_tid1, f_tid2, &m_tid1, &m_tid2, &m_size1, &m_size2)) goto error; /* print names */ if(obj1_name) name1 = diff_basename(obj1_name); if(obj2_name) name2 = diff_basename(obj2_name); /*---------------------------------------------------------------- * read/compare *----------------------------------------------------------------- */ need = (size_t)(nelmts1 * m_size1); /* bytes needed */ if(need < H5TOOLS_MALLOCSIZE) { buf1 = HDmalloc(need); buf2 = HDmalloc(need); } /* end if */ if(buf1 != NULL && buf2 != NULL) { if(H5Dread(did1, m_tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf1) < 0) goto error; if(H5Dread(did2, m_tid2, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf2) < 0) goto error; /* array diff */ nfound = diff_array(buf1, buf2, nelmts1, (hsize_t)0, rank1, dims1, options, name1, name2, m_tid1, did1, did2); /* reclaim any VL memory, if necessary */ if(vl_data) { H5Dvlen_reclaim(m_tid1, sid1, H5P_DEFAULT, buf1); H5Dvlen_reclaim(m_tid2, sid2, H5P_DEFAULT, buf2); } /* end if */ } /* end if */ else /* possibly not enough memory, read/compare by hyperslabs */ { size_t p_type_nbytes = m_size1; /*size of memory type */ hsize_t p_nelmts = nelmts1; /*total selected elmts */ hsize_t elmtno; /*counter */ int carry; /*counter carry value */ /* stripmine info */ hsize_t sm_size[H5S_MAX_RANK]; /*stripmine size */ hsize_t sm_nbytes; /*bytes per stripmine */ hsize_t sm_nelmts; /*elements per stripmine*/ /* hyperslab info */ hsize_t hs_offset[H5S_MAX_RANK]; /*starting offset */ hsize_t hs_size[H5S_MAX_RANK]; /*size this pass */ hsize_t hs_nelmts; /*elements in request */ hsize_t zero[8]; /*vector of zeros */ /* * determine the strip mine size and allocate a buffer. The strip mine is * a hyperslab whose size is manageable. */ sm_nbytes = p_type_nbytes; for(i = rank1; i > 0; --i) { hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes; if(size == 0) /* datum size > H5TOOLS_BUFSIZE */ size = 1; sm_size[i - 1] = MIN(dims1[i - 1], size); sm_nbytes *= sm_size[i - 1]; HDassert(sm_nbytes > 0); } /* end for */ /* malloc return code should be verified. * If fail, need to handle the error. * This else branch should be recoded as a separate function. * Note that there are many "goto error" within this branch * that fails to address freeing other objects created here. * E.g., sm_space. */ sm_buf1 = HDmalloc((size_t)sm_nbytes); HDassert(sm_buf1); sm_buf2 = HDmalloc((size_t)sm_nbytes); HDassert(sm_buf2); sm_nelmts = sm_nbytes / p_type_nbytes; sm_space = H5Screate_simple(1, &sm_nelmts, NULL); /* the stripmine loop */ HDmemset(hs_offset, 0, sizeof hs_offset); HDmemset(zero, 0, sizeof zero); for(elmtno = 0; elmtno < p_nelmts; elmtno += hs_nelmts) { /* calculate the hyperslab size */ if(rank1 > 0) { for(i = 0, hs_nelmts = 1; i < rank1; i++) { hs_size[i] = MIN(dims1[i] - hs_offset[i], sm_size[i]); hs_nelmts *= hs_size[i]; } /* end for */ if(H5Sselect_hyperslab(sid1, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0) goto error; if(H5Sselect_hyperslab(sid2, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL) < 0) goto error; if(H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &hs_nelmts, NULL) < 0) goto error; } /* end if */ else hs_nelmts = 1; if(H5Dread(did1,m_tid1,sm_space,sid1,H5P_DEFAULT,sm_buf1) < 0) goto error; if(H5Dread(did2,m_tid2,sm_space,sid2,H5P_DEFAULT,sm_buf2) < 0) goto error; /* get array differences. in the case of hyperslab read, increment the number of differences found in each hyperslab and pass the position at the beggining for printing */ nfound += diff_array(sm_buf1, sm_buf2, hs_nelmts, elmtno, rank1, dims1, options, name1, name2, m_tid1, did1, did2); /* reclaim any VL memory, if necessary */ if(vl_data) { H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf1); H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf2); } /* end if */ /* calculate the next hyperslab offset */ for(i = rank1, carry = 1; i > 0 && carry; --i) { hs_offset[i - 1] += hs_size[i - 1]; if(hs_offset[i - 1] == dims1[i - 1]) hs_offset[i - 1] = 0; else carry = 0; } /* i */ } /* elmtno */ H5Sclose(sm_space); } /* hyperslab read */ } /*can_compare*/ /*------------------------------------------------------------------------- * close *------------------------------------------------------------------------- */ /* free */ if(buf1 != NULL) { HDfree(buf1); buf1 = NULL; } /* end if */ if(buf2 != NULL) { HDfree(buf2); buf2 = NULL; } /* end if */ if(sm_buf1 != NULL) { HDfree(sm_buf1); sm_buf1 = NULL; } /* end if */ if(sm_buf2 != NULL) { HDfree(sm_buf2); sm_buf2 = NULL; } /* end if */ H5E_BEGIN_TRY { H5Sclose(sid1); H5Sclose(sid2); H5Tclose(f_tid1); H5Tclose(f_tid2); H5Tclose(m_tid1); H5Tclose(m_tid2); } H5E_END_TRY; return nfound; error: options->err_stat=1; /* free */ if (buf1!=NULL) { /* reclaim any VL memory, if necessary */ if(vl_data) H5Dvlen_reclaim(m_tid1, sid1, H5P_DEFAULT, buf1); HDfree(buf1); buf1=NULL; } if (buf2!=NULL) { /* reclaim any VL memory, if necessary */ if(vl_data) H5Dvlen_reclaim(m_tid2, sid2, H5P_DEFAULT, buf2); HDfree(buf2); buf2=NULL; } if (sm_buf1!=NULL) { /* reclaim any VL memory, if necessary */ if(vl_data) H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf1); HDfree(sm_buf1); sm_buf1=NULL; } if (sm_buf2!=NULL) { /* reclaim any VL memory, if necessary */ if(vl_data) H5Dvlen_reclaim(m_tid1, sm_space, H5P_DEFAULT, sm_buf2); HDfree(sm_buf2); sm_buf2=NULL; } /* disable error reporting */ H5E_BEGIN_TRY { H5Sclose(sid1); H5Sclose(sid2); H5Tclose(f_tid1); H5Tclose(f_tid2); H5Tclose(m_tid1); H5Tclose(m_tid2); /* enable error reporting */ } H5E_END_TRY; return nfound; }
hsize_t diff_attr(hid_t loc1_id, hid_t loc2_id, const char *path1, const char *path2, diff_opt_t *options) { hid_t attr1_id=-1; /* attr ID */ hid_t attr2_id=-1; /* attr ID */ hid_t space1_id=-1; /* space ID */ hid_t space2_id=-1; /* space ID */ hid_t ftype1_id=-1; /* file data type ID */ hid_t ftype2_id=-1; /* file data type ID */ int vstrtype1=0; /* ftype1 is a variable string */ int vstrtype2=0; /* ftype2 is a variable string */ hid_t mtype1_id=-1; /* memory data type ID */ hid_t mtype2_id=-1; /* memory data type ID */ size_t msize1; /* memory size of memory type */ size_t msize2; /* memory size of memory type */ void *buf1=NULL; /* data buffer */ void *buf2=NULL; /* data buffer */ int buf1hasdata=0; /* buffer has data */ int buf2hasdata=0; /* buffer has data */ hsize_t nelmts1; /* number of elements in dataset */ int rank1; /* rank of dataset */ int rank2; /* rank of dataset */ hsize_t dims1[H5S_MAX_RANK];/* dimensions of dataset */ hsize_t dims2[H5S_MAX_RANK];/* dimensions of dataset */ char *name1; char *name2; char np1[512]; char np2[512]; unsigned u; /* Local index variable */ hsize_t nfound = 0; hsize_t nfound_total = 0; int j; table_attrs_t * match_list_attrs = NULL; if( build_match_list_attrs(loc1_id, loc2_id, &match_list_attrs, options) < 0) goto error; /* if detect any unique extra attr */ if(match_list_attrs->nattrs_only1 || match_list_attrs->nattrs_only2) { /* exit will be 1 */ options->contents = 0; } for(u = 0; u < (unsigned)match_list_attrs->nattrs; u++) { if( (match_list_attrs->attrs[u].exist[0]) && (match_list_attrs->attrs[u].exist[1]) ) { name1 = name2 = match_list_attrs->attrs[u].name; /*-------------- * attribute 1 */ if((attr1_id = H5Aopen(loc1_id, name1, H5P_DEFAULT)) < 0) goto error; /*-------------- * attribute 2 */ if((attr2_id = H5Aopen(loc2_id, name2, H5P_DEFAULT)) < 0) goto error; /* get the datatypes */ if((ftype1_id = H5Aget_type(attr1_id)) < 0) goto error; vstrtype1 = H5Tis_variable_str(ftype1_id); if((ftype2_id = H5Aget_type(attr2_id)) < 0) goto error; vstrtype2 = H5Tis_variable_str(ftype2_id); /* no compare if either one but not both are variable string type */ if (vstrtype1 != vstrtype2){ if ((options->m_verbose||options->m_list_not_cmp)) parallel_print("Not comparable: one of attribute <%s/%s> or <%s/%s> is of variable length type\n", path1, name1, path2, name2); options->not_cmp = 1; return 0; } if((mtype1_id = h5tools_get_native_type(ftype1_id))<0) goto error; if((mtype2_id = h5tools_get_native_type(ftype2_id))<0) goto error; if((msize1 = H5Tget_size(mtype1_id))==0) goto error; if((msize2 = H5Tget_size(mtype2_id))==0) goto error; /* get the dataspace */ if((space1_id = H5Aget_space(attr1_id)) < 0) goto error; if((space2_id = H5Aget_space(attr2_id)) < 0) goto error; /* get dimensions */ if((rank1 = H5Sget_simple_extent_dims(space1_id, dims1, NULL)) < 0) goto error; if((rank2 = H5Sget_simple_extent_dims(space2_id, dims2, NULL)) < 0) goto error; /*---------------------------------------------------------------------- * check for comparable TYPE and SPACE *---------------------------------------------------------------------- */ /* pass dims1 and dims2 for maxdims as well since attribute's maxdims * are always same */ if( diff_can_type(ftype1_id, ftype2_id, rank1, rank2, dims1, dims2, dims1, dims2, name1, name2, options, 0) != 1 ) { if(H5Tclose(ftype1_id) < 0) goto error; if(H5Tclose(ftype2_id) < 0) goto error; if(H5Sclose(space1_id) < 0) goto error; if(H5Sclose(space2_id) < 0) goto error; if(H5Aclose(attr1_id) < 0) goto error; if(H5Aclose(attr2_id) < 0) goto error; if(H5Tclose(mtype1_id) < 0) goto error; if(H5Tclose(mtype2_id) < 0) goto error; continue; } /*----------------------------------------------------------------- * "upgrade" the smaller memory size *------------------------------------------------------------------ */ if (FAIL == match_up_memsize (ftype1_id, ftype2_id, &mtype1_id, &mtype2_id, &msize1, &msize2)) goto error; /*--------------------------------------------------------------------- * read *---------------------------------------------------------------------- */ nelmts1 = 1; for(j = 0; j < rank1; j++) nelmts1 *= dims1[j]; buf1 = (void *)HDmalloc((size_t)(nelmts1 * msize1)); buf2 = (void *)HDmalloc((size_t)(nelmts1 * msize2)); if(buf1 == NULL || buf2 == NULL){ parallel_print( "cannot read into memory\n" ); goto error; } if(H5Aread(attr1_id,mtype1_id,buf1) < 0){ parallel_print("Failed reading attribute1 %s/%s\n", path1, name1); goto error; }else buf1hasdata = 1; if(H5Aread(attr2_id,mtype2_id,buf2) < 0){ parallel_print("Failed reading attribute2 %s/%s\n", path2, name2); goto error; }else buf2hasdata = 1; /* format output string */ HDsnprintf(np1, sizeof(np1), "%s of <%s>", name1, path1); HDsnprintf(np2, sizeof(np1), "%s of <%s>", name2, path2); /*--------------------------------------------------------------------- * array compare *---------------------------------------------------------------------- */ /* always print name */ /* verbose (-v) and report (-r) mode */ if(options->m_verbose || options->m_report) { do_print_attrname("attribute", np1, np2); nfound = diff_array(buf1, buf2, nelmts1, (hsize_t)0, rank1, dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id); print_found(nfound); } /* quiet mode (-q), just count differences */ else if(options->m_quiet) { nfound = diff_array(buf1, buf2, nelmts1, (hsize_t)0, rank1, dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id); } /* the rest (-c, none, ...) */ else { nfound = diff_array(buf1, buf2, nelmts1, (hsize_t)0, rank1, dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id); /* print info if compatible and difference found */ if(nfound) { do_print_attrname("attribute", np1, np2); print_found(nfound); } /* end if */ } /* end else */ /*---------------------------------------------------------------------- * close *---------------------------------------------------------------------- */ /* Free buf1 and buf2, check both VLEN-data VLEN-string to reclaim any * VLEN memory first */ if(TRUE == h5tools_detect_vlen(mtype1_id)) H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1); HDfree(buf1); buf1 = NULL; if(TRUE == h5tools_detect_vlen(mtype2_id)) H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2); HDfree(buf2); buf2 = NULL; if(H5Tclose(ftype1_id) < 0) goto error; if(H5Tclose(ftype2_id) < 0) goto error; if(H5Sclose(space1_id) < 0) goto error; if(H5Sclose(space2_id) < 0) goto error; if(H5Aclose(attr1_id) < 0) goto error; if(H5Aclose(attr2_id) < 0) goto error; if(H5Tclose(mtype1_id) < 0) goto error; if(H5Tclose(mtype2_id) < 0) goto error; nfound_total += nfound; } } /* u */ table_attrs_free(match_list_attrs); return nfound_total; error: H5E_BEGIN_TRY { if(buf1) { if(buf1hasdata && TRUE == h5tools_detect_vlen(mtype1_id)) H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1); HDfree(buf1); } /* end if */ if(buf2) { if(buf2hasdata && TRUE == h5tools_detect_vlen(mtype2_id)) H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2); HDfree(buf2); } /* end if */ table_attrs_free(match_list_attrs); H5Tclose(ftype1_id); H5Tclose(ftype2_id); H5Tclose(mtype1_id); H5Tclose(mtype2_id); H5Sclose(space1_id); H5Sclose(space2_id); H5Aclose(attr1_id); H5Aclose(attr2_id); } H5E_END_TRY; options->err_stat = 1; return nfound_total; }
/*------------------------------------------------------------------------- * Function: copy_attr * * Purpose: copy attributes located in LOC_IN, which is obtained either from * loc_id = H5Gopen2( fid, name); * loc_id = H5Dopen2( fid, name); * loc_id = H5Topen2( fid, name); * * Return: 0, ok, -1 no *------------------------------------------------------------------------- */ int copy_attr(hid_t loc_in, hid_t loc_out, named_dt_t **named_dt_head_p, trav_table_t *travt, pack_opt_t *options) { int ret_value = 0; hid_t attr_id = -1; /* attr ID */ hid_t attr_out = -1; /* attr ID */ hid_t space_id = -1; /* space ID */ hid_t ftype_id = -1; /* file type ID */ hid_t wtype_id = -1; /* read/write type ID */ size_t msize; /* size of type */ void *buf = NULL; /* data buffer */ hsize_t nelmts; /* number of elements in dataset */ int rank; /* rank of dataset */ htri_t is_named; /* Whether the datatype is named */ hsize_t dims[H5S_MAX_RANK];/* dimensions of dataset */ char name[255]; H5O_info_t oinfo; /* object info */ int j; unsigned u; hbool_t is_ref = 0; H5T_class_t type_class = -1; if (H5Oget_info(loc_in, &oinfo) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info failed"); /*------------------------------------------------------------------------- * copy all attributes *------------------------------------------------------------------------- */ for (u = 0; u < (unsigned) oinfo.num_attrs; u++) { /* open attribute */ if ((attr_id = H5Aopen_by_idx(loc_in, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t) u, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx failed"); /* get name */ if (H5Aget_name(attr_id, (size_t) 255, name) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); /* get the file datatype */ if ((ftype_id = H5Aget_type(attr_id)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_type failed"); /* Check if the datatype is committed */ if ((is_named = H5Tcommitted(ftype_id)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tcommitted failed"); if (is_named && travt) { hid_t fidout = -1; /* Create out file id */ if ((fidout = H5Iget_file_id(loc_out)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Iget_file_id failed"); /* Copy named dt */ if ((wtype_id = copy_named_datatype(ftype_id, fidout, named_dt_head_p, travt, options)) < 0) { H5Fclose(fidout); HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_named_datatype failed"); } /* end if */ if (H5Fclose(fidout) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fclose failed"); } /* end if */ else { if (options->use_native == 1) wtype_id = H5Tget_native_type(ftype_id, H5T_DIR_DEFAULT); else wtype_id = H5Tcopy(ftype_id); } /* end else */ /* get the dataspace handle */ if ((space_id = H5Aget_space(attr_id)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_space failed"); /* get dimensions */ if ((rank = H5Sget_simple_extent_dims(space_id, dims, NULL)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed"); nelmts = 1; for (j = 0; j < rank; j++) nelmts *= dims[j]; if ((msize = H5Tget_size(wtype_id)) == 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed"); /*------------------------------------------------------------------------- * object references are a special case. We cannot just copy the buffers, * but instead we recreate the reference. * This is done on a second sweep of the file that just copies the referenced * objects at copy_refs_attr() *------------------------------------------------------------------------- */ type_class = H5Tget_class(wtype_id); is_ref = (type_class == H5T_REFERENCE); if (type_class == H5T_VLEN || type_class == H5T_ARRAY) { hid_t base_type = -1; base_type = H5Tget_super(ftype_id); is_ref = (is_ref || (H5Tget_class(base_type) == H5T_REFERENCE)); if (H5Tclose(base_type) < 0) H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose base_type failed"); } if (type_class == H5T_COMPOUND) { int nmembers = H5Tget_nmembers(wtype_id); for (j = 0; j < nmembers; j++) { hid_t mtid = H5Tget_member_type(wtype_id, (unsigned)j); H5T_class_t mtclass = H5Tget_class(mtid); if (H5Tclose(mtid) < 0) H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose mtid failed"); if (mtclass == H5T_REFERENCE) { is_ref = 1; break; } } /* for (j=0; i<nmembers; j++) */ } /* if (type_class == H5T_COMPOUND) */ if (!is_ref) { /*------------------------------------------------------------------------- * read to memory *------------------------------------------------------------------------- */ buf = (void *)HDmalloc((size_t)(nelmts * msize)); if (buf == NULL) { HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); } /* end if */ if (H5Aread(attr_id, wtype_id, buf) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); /*------------------------------------------------------------------------- * copy *------------------------------------------------------------------------- */ if ((attr_out = H5Acreate2(loc_out, name, wtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Acreate2 failed on ,%s>", name); if (H5Awrite(attr_out, wtype_id, buf) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Awrite failed"); /*close*/ if (H5Aclose(attr_out) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); /* Check if we have VL data and string in the attribute's datatype that must * be reclaimed */ if (TRUE == h5tools_detect_vlen(wtype_id)) H5Dvlen_reclaim(wtype_id, space_id, H5P_DEFAULT, buf); HDfree(buf); buf = NULL; } /*H5T_REFERENCE*/ if (options->verbose) printf(FORMAT_OBJ_ATTR, "attr", name); /*------------------------------------------------------------------------- * close *------------------------------------------------------------------------- */ if (H5Sclose(space_id) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); space_id = -1; if (H5Tclose(wtype_id) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); wtype_id = -1; if (H5Tclose(ftype_id) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); ftype_id = -1; if (H5Aclose(attr_id) < 0) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); attr_id = -1; } /* for u */ done: H5E_BEGIN_TRY { if (buf) { /* Check if we have VL data and string in the attribute's datatype that must * be reclaimed */ if (TRUE == h5tools_detect_vlen(wtype_id)) H5Dvlen_reclaim(wtype_id, space_id, H5P_DEFAULT, buf); /* Free buf */ HDfree(buf); } /* end if */ H5Aclose(attr_out); H5Sclose(space_id); H5Tclose(wtype_id); H5Tclose(ftype_id); H5Aclose(attr_id); } H5E_END_TRY; return ret_value; } /* end copy_attr() */