/*------------------------------------------------------------------------- * Function: main * * Purpose: h5watch * * Return: Success: 0 * Failure: 1 * * Programmer: Vailin Choi; August 2010 * *------------------------------------------------------------------------- */ int main(int argc, const char *argv[]) { char drivername[50]; char *fname = NULL; char *dname = NULL; void *edata; H5E_auto2_t func; char *x; hid_t fid = -1; hid_t fapl = -1; /* Set up tool name and exit status */ h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); /* Disable error reporting */ H5Eget_auto2(H5E_DEFAULT, &func, &edata); H5Eset_auto2(H5E_DEFAULT, NULL, NULL); /* Initialize h5tools lib */ h5tools_init(); /* parse command line options */ parse_command_line(argc, argv); if(argc <= opt_ind) { error_msg("missing dataset name\n"); usage(h5tools_getprogname()); leave(EXIT_FAILURE); } /* Mostly copied from tools/h5ls coding & modified accordingly */ /* * [OBJECT] is specified as * [<filename>/<path_to_dataset>/<dsetname>] * * Example: ../dir1/foo/bar/dset * \_________/\______/ * file obj * * The dichotomy is determined by calling H5Fopen() repeatedly until it * succeeds. The first call uses the entire name and each subsequent call * chops off the last component. If we reach the beginning of the name * then there must have been something wrong with the file (perhaps it * doesn't exist). */ if((fname = HDstrdup(argv[opt_ind])) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); h5tools_setstatus(EXIT_FAILURE); } /* Create a copy of file access property list */ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) return -1; /* Set to use the latest library format */ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return -1; do { while(fname && *fname) { fid = h5tools_fopen(fname, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl, NULL, drivername, sizeof drivername); if(fid >= 0) { HDfprintf(stdout, "Opened \"%s\" with %s driver.\n", fname, drivername); break; /*success*/ } /* end if */ /* Shorten the file name; lengthen the object name */ x = dname; dname = HDstrrchr(fname, '/'); if(x) *x = '/'; if(!dname) break; *dname = '\0'; } /* end while */ /* Try opening the file again if somehow unstable */ } while(g_retry-- > 0 && fid == FAIL); if(fid < 0) { error_msg("unable to open file \"%s\"\n", fname); if(fname) HDfree(fname); if(fapl >= 0) H5Pclose(fapl); leave(EXIT_FAILURE); } if(!dname) { error_msg("no dataset specified\n"); h5tools_setstatus(EXIT_FAILURE); } else { *dname = '/'; x = dname; if((dname = HDstrdup(dname)) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); h5tools_setstatus(EXIT_FAILURE); } else { *x = '\0'; /* Validate dataset */ if(check_dataset(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); /* Validate input "fields" */ else if(g_list_of_fields && *g_list_of_fields) if(process_cmpd_fields(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); } } /* If everything is fine, start monitoring the datset */ if(h5tools_getstatus() != EXIT_FAILURE) if(monitor_dataset(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); /* Free spaces */ if(fname) HDfree(fname); if(dname) HDfree(dname); if(g_list_of_fields) HDfree(g_list_of_fields); if(g_listv) { H5LD_clean_vector(g_listv); HDfree(g_listv); } if(g_dup_fields) HDfree(g_dup_fields); /* Close the file access property list */ if(fapl >= 0 && H5Pclose(fapl) < 0) { error_msg("unable to close file access property list\n"); h5tools_setstatus(EXIT_FAILURE); } /* Close the file */ if(H5Fclose(fid) < 0) { error_msg("unable to close file\n"); h5tools_setstatus(EXIT_FAILURE); } H5Eset_auto2(H5E_DEFAULT, func, edata); /* exit */ leave(h5tools_getstatus()); } /* main() */
/*------------------------------------------------------------------------- * Function: H5LD_get_dset_type_size * * Purpose: To return the size of the dataset's datatype in bytes * null "fields": return the size of the dataset's datatype * non-null "fields": return the size of the dataset's datatype * with respect to the selection in "fields" * * Return: Success: size of the dataset's datatype * Failure: 0 (valid datatypes are never zero size) * * Programmer: Vailin Choi; March 2010 * *------------------------------------------------------------------------- */ static size_t H5LD_get_dset_type_size(hid_t did, const char *fields) { hid_t dset_tid = -1; /* Dataset's type identifier */ hid_t tid = -1; /* Native Type identifier */ H5LD_memb_t **listv = NULL; /* Vector for storing information in "fields" */ char *dup_fields = NULL; /* A copy of "fields" */ size_t ret_value = 0; /* Return value */ /* Get the datatype of the dataset */ if((dset_tid = H5Dget_type(did)) < 0) goto done; if((tid = H5Tget_native_type(dset_tid, H5T_DIR_DEFAULT)) < 0) goto done; if(fields == NULL) /* If no "fields" is specified */ ret_value = H5Tget_size(tid); else { /* "fields" are specified */ size_t len; /* Estimate the number of comma-separated fields in "fields" */ size_t tot = 0; /* Data type size of all the fields in "fields" */ int n = 0, num = 0; /* Local index variables */ HDassert(fields && *fields); /* Should be a compound datatype if "fields" exists */ if(H5Tget_class(dset_tid) != H5T_COMPOUND) goto done; /* Get a copy of "fields" */ if(NULL == (dup_fields = HDstrdup(fields))) goto done; /* Allocate memory for a list of H5LD_memb_t pointers to store "fields" info */ len = (HDstrlen(fields) / 2) + 2; if(NULL == (listv = (H5LD_memb_t **)HDcalloc(len, sizeof(H5LD_memb_t *)))) goto done; /* Process and store info for "fields" */ if((num = H5LD_construct_vector(dup_fields, listv/*OUT*/, tid)) < 0) goto done; /* Sum up the size of all the datatypes in "fields" */ for(n = 0; n < num; n++) tot += listv[n]->last_tsize; /* Clean up the vector of H5LD_memb_t structures */ H5LD_clean_vector(listv); /* Return the total size */ ret_value = tot; } /* end else */ done: H5E_BEGIN_TRY H5Tclose(tid); H5Tclose(dset_tid); H5E_END_TRY /* Free the array of H5LD_memb_t pointers */ if(listv) HDfree(listv); /* Free memory */ if(dup_fields) HDfree(dup_fields); return(ret_value); } /* H5LD_get_dset_type_size() */
/*------------------------------------------------------------------------- * Function: H5LD_get_dset_elmts * * Purpose: To retrieve selected data from the dataset * * Return: Success: 0 * Failure: negative * * Programmer: Vailin Choi; August 2010 * *------------------------------------------------------------------------- */ static herr_t H5LD_get_dset_elmts(hid_t did, const hsize_t *prev_dims, const hsize_t *cur_dims, const char *fields, void *buf) { hid_t dtid = -1, tid = -1; /* Dataset type id */ hid_t sid = -1, mid = -1; /* Dataspace and memory space id */ hssize_t snum_elmts; /* Number of dataset elements in the selection (signed) */ hsize_t num_elmts; /* Number of dataset elements in the selection */ hsize_t start[H5S_MAX_RANK];/* Starting offset */ hsize_t count[H5S_MAX_RANK];/* ??offset */ H5LD_memb_t **listv = NULL; /* Vector for storing information in "fields" */ char *dup_fields = NULL; /* A copy of "fields" */ char *sav_buf = NULL; /* Saved pointer temporary buffer */ unsigned ctr; /* Counter for # of curr_dims > prev_dims */ int ndims; /* Number of dimensions for the dataset */ int i; /* Local index variable */ herr_t ret_value = FAIL; /* Return value */ /* Verify parameters */ if(prev_dims == NULL || cur_dims == NULL || buf == NULL) goto done; /* Get dataset's dataspace */ if((sid = H5Dget_space(did)) < 0) goto done; /* Get the number of dimensions */ if((ndims = H5Sget_simple_extent_ndims(sid)) < 0) goto done; /* Verify that cur_dims must have one dimension whose size is greater than prev_dims */ HDmemset(start, 0, sizeof start); HDmemset(count, 0, sizeof count); ctr = 0; for(i = 0; i < ndims; i++) if(cur_dims[i] > prev_dims[i]) { ++ctr; count[i] = cur_dims[i] - prev_dims[i]; start[i] = prev_dims[i]; } /* end if */ else { /* < or = */ start[i] = 0; count[i] = MIN(prev_dims[i], cur_dims[i]); } /* end else */ if(!ctr) goto done; if(ctr == 1) { /* changes for only one dimension */ /* Make the selection in the dataset based on "cur_dims" and "prev_dims" */ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0) goto done; } /* end if */ else { /* changes for more than one dimensions */ HDmemset(start, 0, sizeof start); /* Make the selection in the dataset based on "cur_dims" and "prev_dims" */ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL, cur_dims, NULL) < 0) goto done; if(H5Sselect_hyperslab(sid, H5S_SELECT_NOTB, start, NULL, prev_dims, NULL) < 0) goto done; } /* end else */ /* Get the number of elements in the selection */ if(0 == (snum_elmts = H5Sget_select_npoints(sid))) goto done; num_elmts = (hsize_t)snum_elmts; /* Create the memory space for the selection */ if((mid = H5Screate_simple(1, &num_elmts, NULL)) < 0) goto done; /* Get the native datatype size */ if((dtid = H5Dget_type(did)) < 0) goto done; if((tid = H5Tget_native_type(dtid, H5T_DIR_DEFAULT)) < 0) goto done; if(fields == NULL) { /* nothing in "fields" */ /* Read and store all the elements in "buf" */ if(H5Dread(did, tid, mid, sid, H5P_DEFAULT, buf) < 0) goto done; } /* end if */ else { /* "fields" is specified */ unsigned char *buf_p = (unsigned char *)buf; /* Pointer to the destination buffer */ char *tmp_buf; /* Temporary buffer for data read */ size_t tot_tsize; /* Total datatype size */ size_t len; /* Estimate the number of comma-separated fields in "fields" */ /* should be a compound datatype if "fields" exists */ if(H5Tget_class(tid) != H5T_COMPOUND) goto done; /* Get the total size of the dataset's datatypes */ if(0 == (tot_tsize = H5LD_get_dset_type_size(did, NULL))) goto done; /* Allocate memory for reading in the elements in the dataset selection */ if(NULL == (sav_buf = tmp_buf = (char *)HDcalloc((size_t)num_elmts, tot_tsize))) goto done; /* Read the dataset elements in the selection */ if(H5Dread(did, tid, mid, sid, H5P_DEFAULT, tmp_buf) < 0) goto done; /* Make a copy of "fields" */ if(NULL == (dup_fields = HDstrdup(fields))) goto done; /* Allocate memory for the vector of H5LD_memb_t pointers */ len = (HDstrlen(fields) / 2) + 2; if(NULL == (listv = (H5LD_memb_t **)HDcalloc(len, sizeof(H5LD_memb_t *)))) goto done; /* Process and store information for "fields" */ if(H5LD_construct_vector(dup_fields, listv, tid) < 0) goto done; /* Copy data for each dataset element in the selection */ for(i = 0; i < (int)num_elmts; i++) { int j; /* Local index variable */ /* Copy data for "fields" to the input buffer */ for(j = 0; listv[j] != NULL; j++) { HDmemcpy(buf_p, tmp_buf + listv[j]->tot_offset, listv[j]->last_tsize); buf_p += listv[j]->last_tsize; } /* end for */ tmp_buf += tot_tsize; } /* end for */ /* Clean up the vector of H5LD_memb_t structures */ H5LD_clean_vector(listv); } /* end else */ /* Indicate success */ ret_value = SUCCEED; done: H5E_BEGIN_TRY H5Tclose(dtid); H5Tclose(tid); H5Sclose(sid); H5Sclose(mid); H5E_END_TRY /* Free the array of H5LD_memb_t pointers */ if(listv) HDfree(listv); /* Free memory */ if(dup_fields) HDfree(dup_fields); if(sav_buf) HDfree(sav_buf); return(ret_value); } /* H5LD_get_dset_elmts() */
/*------------------------------------------------------------------------- * Function: H5LD_construct_vector * * Purpose: Process the comma-separated list of fields in "fields" as follows: * Example: * "fields": "a.b.c,d" * listv[0]->tot_offset = total offset of "a" & "b" & "c" * listv[0]->last_tid = type id of "c" * listv[0]->last_tsize = type size of "c" * listv[0]->names[0] = "a" * listv[0]->names[1] = "b" * listv[0]->names[2] = "c" * listv[0]->names[3] = NULL * * listv[1]->tot_offset = offset of "d" * listv[1]->last_tid = type id of "d" * listv[1]->last_tsize = type size of "d" * listv[1]->names[0] = "d" * listv[1]->names[1] = NULL * * Return: Success: # of comma-separated fields in "fields" * Failure: negative value * * Programmer: Vailin Choi; Aug 2010 * *------------------------------------------------------------------------- */ int H5LD_construct_vector(char *fields, H5LD_memb_t *listv[]/*OUT*/, hid_t par_tid) { int nfields; /* The # of comma-separated fields in "fields" */ hbool_t end_of_fields = FALSE; /* end of "fields" */ char *fields_ptr; /* Pointer to "fields" */ int ret_value = FAIL; /* Return value */ HDassert(listv); HDassert(fields); fields_ptr = fields; nfields = 0; /* Process till end of "fields" */ while(!end_of_fields) { H5LD_memb_t *memb = NULL; /* Pointer to structure for storing a field's info */ char *cur; /* Pointer to a member in a field */ size_t len; /* Estimated # of members in a field */ hbool_t gotcomma = FALSE; /* A comma encountered */ hbool_t gotmember = FALSE; /* Getting member in a field */ hbool_t valid = TRUE; /* Whether a field being processed is valid or not */ int j = 0; /* The # of members in a field */ len = (HDstrlen(fields_ptr) / 2) + 2; /* Allocate memory for an H5LD_memb_t for storing a field's info */ if(NULL == (memb = (H5LD_memb_t *)HDcalloc((size_t)1, sizeof(H5LD_memb_t)))) goto done; /* Allocate memory for an array of pointers to member names */ if(NULL == (memb->names = (char **)HDcalloc(len, sizeof(char *)))) goto done; memb->names[j] = fields_ptr; memb->last_tid = -1; cur = fields_ptr; /* Continue processing till: not valid or comma encountered or "fields" ended */ while(valid && !gotcomma && !end_of_fields) { switch(*fields_ptr) { case '\0': /* end of list */ if(gotmember) { /* getting something and end of "fields" */ *cur++ = '\0';; memb->names[++j] = NULL; } /* end if */ else /* getting nothing but end of list */ valid = FALSE; end_of_fields = TRUE; break; case '\\': /* escape character */ ++fields_ptr; /* skip it */ if(*fields_ptr == '\0') valid = FALSE; else { *cur++ = *fields_ptr++; gotmember = TRUE; } /* end else */ break; case '.': /* nested field separator */ *fields_ptr++ = *cur++ = '\0';; if(gotmember) { memb->names[++j] = cur; gotmember = FALSE; } /* end if */ else valid = FALSE; break; case ',': /* field separator */ *fields_ptr++ = *cur++ = '\0';; if(gotmember) { memb->names[++j] = NULL; gotmember = FALSE; } /* end if */ else valid = FALSE; gotcomma = TRUE; break; default: *cur++ = *fields_ptr++; gotmember = TRUE; break; } /* end switch */ } /* while (valid && !gotcomma && !end_of_fields) */ /* If valid, put into listv and continue processing further info */ if(valid) { listv[nfields++] = memb; if(H5LD_construct_info(memb, par_tid) < 0) goto done; } /* end if */ else { if(memb) HDfree(memb); goto done; } /* end else */ } /* while !end_of_fields */ /* Indicate success */ ret_value = nfields; done: listv[nfields] = NULL; if(ret_value == FAIL) H5LD_clean_vector(listv); return(ret_value); } /* H5LD_construct_vector() */