Example #1
0
// Note: assumes one or more of datablock->bounds or output_sel is local
static uint64_t apply_datablock_to_buffer_nonlocal_selections(
		const ADIOS_VARINFO *raw_varinfo, const ADIOS_TRANSINFO *transinfo,
		adios_datablock *datablock,
        void **output_buffer, const ADIOS_SELECTION *output_sel,
        ADIOS_SELECTION **out_inter_sel, int want_out_inter_sel,
        enum ADIOS_FLAG swap_endianness)
{
	int may_have_intersection = 1;
	uint64_t used_count = 0;

	const ADIOS_SELECTION *global_output_buffer_sel = output_sel;
	const ADIOS_SELECTION *global_datablock_bounds = datablock->bounds;

	// Promote output buffer selection and/or datablock selection to global if needed
	if (!is_global_selection(global_output_buffer_sel))
		global_output_buffer_sel = create_writeblock_bounds(&global_output_buffer_sel->u.block, datablock->timestep, raw_varinfo, transinfo);
	if (!is_global_selection(global_datablock_bounds))
		global_datablock_bounds = create_writeblock_bounds(&global_datablock_bounds->u.block, datablock->timestep, raw_varinfo, transinfo);

    // Compute the intersection explicitly if it is requested, or
    // if we need to allocate a fitting output buffer
    if (want_out_inter_sel || !*output_buffer) {
    	*out_inter_sel = adios_selection_intersect_global(global_datablock_bounds, global_output_buffer_sel);
    	may_have_intersection = (*out_inter_sel ? 1 : 0);
    }

    // We can stop immediately if it is known there is no intersection
    if (may_have_intersection) {
    	// Allocate the output buffer if needed (inter_sel is populated by previous if statement)
    	if (!*output_buffer) {
    		const uint64_t chunk_buffer_size = compute_selection_size_in_bytes(*out_inter_sel, datablock->elem_type, datablock->timestep, raw_varinfo, transinfo);
    		*output_buffer = malloc(chunk_buffer_size);

    		// Refitting the output selection to the intersection region, since we
    		// just allocated a buffer for that smaller region
    		if (global_output_buffer_sel != output_sel)
    			a2sel_free((ADIOS_SELECTION *)global_output_buffer_sel);
    		output_sel = *out_inter_sel;
    		global_output_buffer_sel = *out_inter_sel;
    	}

    	// Perform the actual data patching, now that everything is in the global space
    	used_count = adios_patch_data_to_global(
    			*output_buffer, (uint64_t)0, global_output_buffer_sel,
    			datablock->data, datablock->ragged_offset, global_datablock_bounds,
    			datablock->elem_type, swap_endianness);
    }

	// Clean up
	if (global_output_buffer_sel != output_sel)
		a2sel_free((ADIOS_SELECTION *)global_output_buffer_sel);
	if (global_datablock_bounds != datablock->bounds)
		a2sel_free((ADIOS_SELECTION *)global_datablock_bounds);

	return used_count;
}
Example #2
0
/*
 * Takes a datablock and applies its data to the user buffer for the given
 * read request group, then frees the given datablock. Assumes there is, in
 * fact, a user buffer (i.e., it is not NULL).
 *
 * Assumes that the datablock selection is of type bounding box.
 *
 * NOTE: also frees the data buffer within the datablock
 *
 * @return non-zero if some data in the datablock intersected the read
 *         request's selection, and was applied; returns 0 otherwise.
 */
static int apply_datablock_to_result_and_free(adios_datablock *datablock,
                                              adios_transform_read_request *reqgroup)
{
    assert(datablock); assert(reqgroup);
    assert(reqgroup->orig_sel);
    assert(reqgroup->orig_data);

    void *output_buffer;
    if (is_global_selection(reqgroup->orig_sel)) {
    	// All timestep results have the same size in bytes, so offset the
    	// output pointer by however many timesteps precede this timestep
    	const int timestep_within_request = datablock->timestep - reqgroup->from_steps;
		output_buffer = (char*)reqgroup->orig_data + timestep_within_request * reqgroup->orig_sel_timestep_size;
    } else if (reqgroup->orig_sel->type == ADIOS_SELECTION_WRITEBLOCK) {
    	// For writeblock selections, computing the output buffer position for
    	// the current timestep is a bit trickier, since varblocks may be
    	// different sizes in different timesteps
    	const ADIOS_SELECTION_WRITEBLOCK_STRUCT *orig_sel_wb = &reqgroup->orig_sel->u.block;

    	// Compute the offset into the output buffer at which the current timestep's output should go
    	// For absolute writeblocks, it's always 0, since there is only 1 timestep involved. For
    	// timestep-relative writeblock selections, we add the size of the writeblock (i.e. varblock)
    	// for all previous timesteps in the user's read request.
    	uint64_t output_buffer_offset = 0;
    	if (!orig_sel_wb->is_absolute_index) {
    		int timestep;
    		for (timestep = reqgroup->from_steps; timestep < datablock->timestep; timestep++) {
        		// Compute the size of the writeblock at this timestep and add it to our offset
        		output_buffer_offset += compute_selection_size_in_bytes(reqgroup->orig_sel, reqgroup->transinfo->orig_type, timestep, reqgroup->raw_varinfo, reqgroup->transinfo);
        	}
    	}

    	// Offset the output pointer by the computed amount
    	output_buffer = (char*)reqgroup->orig_data + output_buffer_offset;
    } else {
    	adios_error_at_line(err_unspecified, __FILE__, __LINE__, "Internal error: unexpected selection type %d, this should not be possible here\n", reqgroup->orig_sel->type);
    }

    // Now that we have the output buffer pointer, actually perform the patch operation
    const uint64_t used_count =
            apply_datablock_to_buffer_and_free(
                    reqgroup->raw_varinfo, reqgroup->transinfo,
                    datablock,
                    &output_buffer, reqgroup->orig_sel, NULL /* don't need the intersection */,
                    reqgroup->swap_endianness);

    return used_count != 0;
}
Example #3
0
static uint64_t apply_datablock_to_buffer_local_selections(
		const ADIOS_VARINFO *raw_varinfo, const ADIOS_TRANSINFO *transinfo,
		adios_datablock *datablock,
        void **output_buffer, const ADIOS_SELECTION *output_sel,
        ADIOS_SELECTION **out_inter_sel, int want_out_inter_sel,
        enum ADIOS_FLAG swap_endianness)
{
	int may_have_intersection = 1;

	// For writeblock selections, we can use adios_patch_data_to_local,
	// but first we must determine the bounding box of the writeblock selection
    const ADIOS_SELECTION *vb_bounds_sel = create_writeblock_bounds(&output_sel->u.block, datablock->timestep, raw_varinfo, transinfo);

    // Compute the intersection explicitly if it is requested, or
    // if we need to allocate a fitting output buffer
    if (want_out_inter_sel || !*output_buffer) {
        *out_inter_sel = adios_selection_intersect_local(datablock->bounds, output_sel, datablock->timestep, raw_varinfo, transinfo);
        may_have_intersection = (*out_inter_sel ? 1 : 0);
    }

    // Allocate the output buffer if needed (inter_sel is populated by previous if statement)
    if (!*output_buffer) {
    	const uint64_t chunk_buffer_size = compute_selection_size_in_bytes(*out_inter_sel, datablock->elem_type, datablock->timestep, raw_varinfo, transinfo);
		*output_buffer = malloc(chunk_buffer_size);

		// Refitting the output selection to the intersection region, since we
		// just allocated a buffer for that smaller region
		output_sel = *out_inter_sel;
    }

	// Invoke adios_patch_data_to_local to perform the actual patching
	const uint64_t used_count =
			adios_patch_data_to_local(
				*output_buffer, (uint64_t)0, output_sel,
				datablock->data, datablock->ragged_offset, datablock->bounds,
				&vb_bounds_sel->u.bb,
				datablock->elem_type, swap_endianness);

	// Clean up
	common_read_selection_delete((ADIOS_SELECTION *)vb_bounds_sel);
	return used_count;
}