adios_transform_read_request * adios_transform_generate_read_reqgroup(const ADIOS_VARINFO *raw_varinfo, const ADIOS_TRANSINFO* transinfo, const ADIOS_FILE *fp, const ADIOS_SELECTION *sel, int from_steps, int nsteps, const char *param, void *data) { // Declares adios_transform_read_request *new_readreq; int blockidx, timestep, timestep_blockidx; int start_blockidx, end_blockidx; enum ADIOS_FLAG swap_endianness = (fp->endianness == get_system_endianness()) ? adios_flag_no : adios_flag_yes; // In streaming mode, ignore the user's from_steps/nsteps arguments if (fp->is_streaming) { from_steps = 0; nsteps = 1; } // Precondition checking assert(is_transform_type_valid(transinfo->transform_type)); assert(from_steps >= 0 && from_steps + nsteps <= raw_varinfo->nsteps); if (sel->type != ADIOS_SELECTION_BOUNDINGBOX && sel->type != ADIOS_SELECTION_POINTS && sel->type != ADIOS_SELECTION_WRITEBLOCK) { adios_error(err_operation_not_supported, "Only bounding box, point , and writeblock selections are currently supported for reads on transformed variables."); } // Retrieve blockinfos, if they haven't been done retrieved if (!raw_varinfo->blockinfo) common_read_inq_var_blockinfo_raw(fp, (ADIOS_VARINFO*)raw_varinfo); if (!transinfo->orig_blockinfo) common_read_inq_trans_blockinfo(fp, raw_varinfo, (ADIOS_TRANSINFO*)transinfo); // Allocate a new, empty request group new_readreq = adios_transform_read_request_new(fp, raw_varinfo, transinfo, sel, from_steps, nsteps, param, data, swap_endianness); if (is_global_selection(sel)) { populate_read_request_for_global_selection(raw_varinfo, transinfo, sel, from_steps, nsteps, new_readreq); } else { populate_read_request_for_local_selection(raw_varinfo, transinfo, sel, from_steps, nsteps, new_readreq); } // If this read request does not intersect any PGs, then clear the new read request and return NULL if (new_readreq->num_pg_reqgroups == 0) { adios_transform_read_request_free(&new_readreq); new_readreq = NULL; } return new_readreq; }
ADIOS_PG_INTERSECTIONS * adios_find_intersecting_pgs(const ADIOS_FILE *fp, int varid, const ADIOS_SELECTION *sel, const int from_step, const int nsteps) { // Declares adios_transform_read_request *new_reqgroup; int blockidx, timestep, timestep_blockidx; int curblocks, start_blockidx, end_blockidx; int intersects; ADIOS_VARBLOCK *raw_vb, *vb; enum ADIOS_FLAG swap_endianness = (fp->endianness == get_system_endianness()) ? adios_flag_no : adios_flag_yes; int to_steps = from_step + nsteps; // As long as we don't free/destroy it, using the infocache from the file will have no effect on future // operations using the file (except possibly speeding them up, so "constness" is still respected adios_infocache *infocache = common_read_get_file_infocache((ADIOS_FILE*)fp); ADIOS_PG_INTERSECTIONS *resulting_intersections = (ADIOS_PG_INTERSECTIONS *)calloc(1, sizeof(ADIOS_PG_INTERSECTIONS)); resulting_intersections->npg = 0; int intersection_capacity = INITIAL_INTERSECTION_CAPACITY; resulting_intersections->intersections = (ADIOS_PG_INTERSECTION *)calloc(intersection_capacity, sizeof(ADIOS_PG_INTERSECTION)); // Precondition checking if (sel->type != ADIOS_SELECTION_BOUNDINGBOX && sel->type != ADIOS_SELECTION_POINTS) { adios_error(err_operation_not_supported, "Only bounding box and point selections are currently supported during read on transformed variables."); } // Still respecting constness, since we're going to undo this const data_view_t old_view = adios_read_set_data_view((ADIOS_FILE*)fp, LOGICAL_DATA_VIEW); // Temporarily go to logical data view const ADIOS_VARINFO *varinfo = adios_infocache_inq_varinfo(fp, infocache, varid); assert(from_step >= 0 && to_steps <= varinfo->nsteps); // Compute the blockidx range, given the timesteps compute_blockidx_range(varinfo, from_step, to_steps, &start_blockidx, &end_blockidx); // Retrieve blockinfos, if they haven't been done retrieved if (!varinfo->blockinfo) common_read_inq_var_blockinfo(fp, (ADIOS_VARINFO *)varinfo); // Undoing view set (returning to const state) adios_read_set_data_view((ADIOS_FILE*)fp, old_view); // Reset the data view to whatever it was before // Assemble read requests for each varblock blockidx = start_blockidx; timestep = from_step; timestep_blockidx = 0; while (blockidx != end_blockidx) { //for (blockidx = startblock_idx; blockidx != endblock_idx; blockidx++) { ADIOS_SELECTION *pg_bounds_sel; ADIOS_SELECTION *pg_intersection_sel; vb = &varinfo->blockinfo[blockidx]; pg_bounds_sel = create_pg_bounds(varinfo->ndim, vb); // Find the intersection, if any pg_intersection_sel = adios_selection_intersect_global(pg_bounds_sel, sel); if (pg_intersection_sel) { // Expand the PG intersection array, if needed if (resulting_intersections->npg == intersection_capacity) { intersection_capacity *= 2; resulting_intersections->intersections = (ADIOS_PG_INTERSECTION *)realloc(resulting_intersections->intersections, intersection_capacity * sizeof(ADIOS_PG_INTERSECTION)); if (!resulting_intersections->intersections) { adios_error (err_no_memory, "Cannot allocate buffer for PG intersection results in adios_find_intersecting_pgs (required %llu bytes)\n", intersection_capacity * sizeof(ADIOS_PG_INTERSECTION)); return NULL; } } ADIOS_PG_INTERSECTION *intersection = &resulting_intersections->intersections[resulting_intersections->npg]; intersection->timestep = timestep; intersection->blockidx = blockidx; intersection->blockidx_in_timestep = timestep_blockidx; intersection->intersection_sel = pg_intersection_sel; intersection->pg_bounds_sel = pg_bounds_sel; resulting_intersections->npg++; } else { // Cleanup common_read_selection_delete(pg_bounds_sel); // OK to delete, because this function only frees the outer struct, not the arrays within } // Increment block indexes blockidx++; timestep_blockidx++; if (timestep_blockidx == varinfo->nblocks[timestep]) { timestep_blockidx = 0; timestep++; } } return resulting_intersections; }