Esempio n. 1
0
uint64_t adios_transform_worst_case_transformed_group_size(uint64_t group_size, struct adios_file_struct *fd)
{
	uint64_t transformed_group_size = group_size; // The upper bound on how much data /might/ be transformed
    struct adios_var_struct *cur_var;

    // Aggregated scaling information from all transforms
    // The end result upper bound group size is:
    // GS' = total_constant_factor + GS' * max_linear_factor + min(GS', max_capped_linear_cap) * max_capped_linear_factor
    uint64_t total_constant_factor = 0;
    double max_linear_factor = 1;
    double max_capped_linear_factor = 0;
    uint64_t max_capped_linear_cap = 0;

    // Note: the "max capped linear" component is overestimating by combining the highest factor and cap from all transforms
    // A tighter lower bound could be computed by keeping all capped linear caps/factors and doing some sort of overlap
    // computation. However, this requires O(n vars) storage and extra logic that isn't worth it, given capped factors are
    // very rare, and this method gives a tight bound when none are present.

    for (cur_var = fd->group->vars; cur_var; cur_var = cur_var->next)
    {
    	if (!cur_var->dimensions) // Scalar var
        {
    		// Remove the scalar's size from the group size that can be affected by data transforms, and add it as a constant factor
    		// Even if it's a string, we don't know the content yet, so use an empty string to get minimum size (we are computing an upper bound)
    		transformed_group_size -= adios_get_type_size(cur_var->type, "");
    		total_constant_factor += adios_get_type_size(cur_var->type, "");
        }
    	else if (cur_var->transform_type == adios_transform_none) // Non-transformed, non-scalar var
    	{
            // Do nothing
        }
    	else // Transformed var
    	{
    	    uint64_t constant_factor = 0;
    	    double linear_factor = 1;
    	    double capped_linear_factor = 0;
    	    uint64_t capped_linear_cap = 0;

    	    // Get the growth factors for this transform method/spec
    	    adios_transform_transformed_size_growth(cur_var, cur_var->transform_spec, &constant_factor, &linear_factor, &capped_linear_factor, &capped_linear_cap);

    	    // Combine these growth factors into the maximums for computing the worst case
    	    total_constant_factor += constant_factor;
    	    max_linear_factor = MAX(max_linear_factor, linear_factor);
    	    max_capped_linear_factor = MAX(max_capped_linear_factor, capped_linear_factor);
    	    max_capped_linear_cap = MAX(max_capped_linear_cap, capped_linear_cap);
    	}
    }

    const uint64_t max_transformed_group_size =
    		total_constant_factor +
    		ceil(max_linear_factor * transformed_group_size) +
    		ceil(max_capped_linear_factor * MIN(transformed_group_size, max_capped_linear_cap));

    // Return the maximum worst case for the group size
    // (which can never be less than the starting group size)
    return MAX(group_size, max_transformed_group_size);
}
adios_datablock * adios_transform_alacrity_pg_reqgroup_completed(adios_transform_read_request *reqgroup,
                                                                 adios_transform_pg_read_request *completed_pg_reqgroup)
{
    //uint64_t raw_size = (uint64_t)completed_pg_reqgroup->raw_var_length;
    void* raw_buff = completed_pg_reqgroup->subreqs->data;

    uint64_t orig_size = adios_get_type_size(reqgroup->transinfo->orig_type, "");
    int d = 0;
    for(d = 0; d < reqgroup->transinfo->orig_ndim; d++)
        orig_size *= (uint64_t)(completed_pg_reqgroup->orig_varblock->count[d]);

    void* orig_buff = malloc(orig_size);

    ALPartitionData output_partition;
    uint64_t numElements = 0;

    // Decompress into output_partition from compressed_buf
    memstream_t ms = memstreamInitReturn (raw_buff);

    // Deserialize the ALPartitionData from memstream
    ALDeserializePartitionData (&output_partition, &ms);

    // Decode ALPartitionData into decompresed buffer
    int rtn = ALDecode (&output_partition, orig_buff, &numElements);
    if (ALErrorNone != rtn)
        return NULL;

    ALPartitionDataDestroy(&output_partition);

    return adios_datablock_new(reqgroup->transinfo->orig_type,
                               completed_pg_reqgroup->timestep,
                               completed_pg_reqgroup->pg_bounds_sel,
                               orig_buff);
}
Esempio n. 3
0
adios_datablock * adios_transform_szip_pg_reqgroup_completed(adios_transform_read_request *reqgroup,
                                                                adios_transform_pg_read_request *completed_pg_reqgroup)
{
    uint64_t raw_size = (uint64_t)completed_pg_reqgroup->raw_var_length;
    void* raw_buff = completed_pg_reqgroup->subreqs->data;

    uint64_t orig_size = adios_get_type_size(reqgroup->transinfo->orig_type, "");
    int d = 0;
    for(d = 0; d < reqgroup->transinfo->orig_ndim; d++)
        orig_size *= (uint64_t)(completed_pg_reqgroup->orig_varblock->count[d]);

    void* orig_buff = malloc(orig_size);

    int ndims = 1;
    uint64_t dim[1] = {orig_size / sizeof(double)};
    int rtn = decompress_szip_pre_allocated(raw_buff, raw_size, orig_buff, &orig_size, ndims, dim);
    if(rtn != 0)
    {
        return NULL;
    }

    return adios_datablock_new(reqgroup->transinfo->orig_type,
                               completed_pg_reqgroup->timestep,
                               completed_pg_reqgroup->pg_bounds_sel,
                               orig_buff);
}
Esempio n. 4
0
// NCSU ALACRITY-ADIOS - Compute the pre-transform size of a variable, in bytes
// Precondition: var is a non-scalar that has been transformed (transform_type != none)
uint64_t adios_transform_get_pre_transform_var_size(struct adios_var_struct *var) {
    assert(var->dimensions);
    assert(var->type != adios_string);
    assert(var->transform_type != adios_transform_none);
    return adios_get_type_size(var->pre_transform_type, NULL) *
           adios_get_dimension_space_size(var,
                                          var->pre_transform_dimensions);
}
Esempio n. 5
0
static uint64_t compute_selection_size_in_bytes(const ADIOS_SELECTION *sel,
                                                enum ADIOS_DATATYPES datum_type,
                                                int timestep,
                                                const ADIOS_VARINFO *raw_varinfo,
                                                const ADIOS_TRANSINFO *transinfo) {
    int typesize = adios_get_type_size(datum_type, NULL);
    int i;
    switch (sel->type) {
    case ADIOS_SELECTION_BOUNDINGBOX:
    {
        const ADIOS_SELECTION_BOUNDINGBOX_STRUCT *bb = &sel->u.bb;
        const int ndim = bb->ndim;

        uint64_t size = typesize;
        for (i = 0; i < ndim; i++)
            size *= bb->count[i];

        return size;
    }
    case ADIOS_SELECTION_POINTS:
    {
        const ADIOS_SELECTION_POINTS_STRUCT *pts = &sel->u.points;
        return pts->ndim * pts->npoints * typesize;
    }
    case ADIOS_SELECTION_WRITEBLOCK:
    {
        const ADIOS_SELECTION_WRITEBLOCK_STRUCT *wb = &sel->u.block;

        if (wb->is_sub_pg_selection) {
            return wb->nelements * typesize;
        } else {
            const ADIOS_VARBLOCK *theblock;
            uint64_t size = typesize;
            int absolute_idx;

            if (wb->is_absolute_index) {
                absolute_idx = wb->index;
            } else {
                int timestep_start_idx = 0;
                for (i = 0; i < timestep; i++)
                    timestep_start_idx += raw_varinfo->nblocks[i];

                absolute_idx = timestep_start_idx + wb->index;
            }

            theblock = &transinfo->orig_blockinfo[absolute_idx];
            for (i = 0; i < transinfo->orig_ndim; i++)
                size *= theblock->count[i];

            return size;
        }
    }
    case ADIOS_SELECTION_AUTO:
    default:
        adios_error_at_line(err_invalid_argument, __FILE__, __LINE__, "Unsupported selection type %d in data transform read layer", sel->type);
        return 0;
    }
}
Esempio n. 6
0
/* Store a scalar variable's values temporarily while we process the 
   dimensions of the arrays in the same PG */
void store_scalar_dimensions (
        struct adios_var_header_struct_v1 * var_header,
        struct adios_var_payload_struct_v1 * var_payload)
{
    if (var_header->is_dim == adios_flag_yes)
    {
        if (var_header->id < MAX_DIMENSION_INDEX) {
            uint64_t size = adios_get_type_size (var_header->type, var_payload->payload);
            uint64_t d = 0L;
            switch (var_header->type)
            {
                case adios_byte:
                    d = *(signed char *) var_payload->payload;
                    break;
                case adios_unsigned_byte:
                    d = *(unsigned char *) var_payload->payload;
                    break;
                case adios_short:
                    d = *(signed short *) var_payload->payload;
                    break;
                case adios_unsigned_short:
                    d = *(unsigned short *) var_payload->payload;
                    break;
                case adios_integer:
                    d = *(signed int *) var_payload->payload;
                    break;
                case adios_unsigned_integer:
                    d = *(unsigned int *) var_payload->payload;
                    break;
                case adios_long:
                    d = *(signed long long *) var_payload->payload;
                    break;
                case adios_unsigned_long:
                    d = *(unsigned long long *) var_payload->payload;
                    break;

                default:
                    printf ("  !!! ERROR !!! The variable %s/%s appears to be used "
                            "as dimension but it has non-integer type.\n",
                           var_header->path, var_header->name);
                    break;
            }
            dim_value [var_header->id] = *(unsigned int *) var_payload->payload;


        } else {
            printf ("  !!! ERROR !!! This tool can only handle scalar variables"
                    " used as dimensions if they appear as the first %d variables. "
                    "Here we encountered a scalar named %s/%s with id=%d\n",
                    MAX_DIMENSION_INDEX, var_header->path, var_header->name, var_header->id);
        }
    }
}
Esempio n. 7
0
static uint64_t compute_groupsize(uint64_t base_groupsize, const dataset_xml_spec_t *xml_spec, const dataset_pg_spec_t *pg) {
	int var, dim;

	// Compute the number of points contained in this PG
	uint64_t pg_gridsize = dim_prod(xml_spec->ndim, pg->pg_dim);

	// Compute the sum of the datatype sizes across all variables defined in this PG
	uint64_t total_var_datatypes_size = 0;
	for (var = 0; var < xml_spec->nvar; ++var)
		total_var_datatypes_size += adios_get_type_size(xml_spec->vartypes[var], NULL);

	// The final group size is the product of the number of points and the number of bytes per point, plus the base groupsize
	return base_groupsize + pg_gridsize * total_var_datatypes_size;
}
Esempio n. 8
0
adios_datablock * adios_transform_bzip2_pg_reqgroup_completed(adios_transform_read_request *reqgroup,
                                                                adios_transform_pg_read_request *completed_pg_reqgroup)
{
    uint64_t compressed_size = (uint64_t)completed_pg_reqgroup->raw_var_length;
    void* compressed_data = completed_pg_reqgroup->subreqs->data;
    
    uint64_t uncompressed_size_meta = *((uint64_t*)reqgroup->transinfo->transform_metadata);
    char compress_ok = *((char*)(reqgroup->transinfo->transform_metadata + sizeof(uint64_t)));

    uint64_t uncompressed_size = adios_get_type_size(reqgroup->transinfo->orig_type, "");
    int d = 0;
    for(d = 0; d < reqgroup->transinfo->orig_ndim; d++)
    {
        uncompressed_size *= (uint64_t)(completed_pg_reqgroup->orig_varblock->count[d]);
    }
    
    if(uncompressed_size_meta != uncompressed_size)
    {
        printf("WARNING: possible wrong data size or corrupted metadata\n");
    }
    
    void* uncompressed_data = malloc(uncompressed_size);
    if(!uncompressed_data)
    {
        return NULL;
    }

    if(compress_ok == 1)    // compression is successful
    {
        
        int rtn = decompress_bzip2_pre_allocated(compressed_data, compressed_size, uncompressed_data, &uncompressed_size);
        if(rtn != 0)
        {
            return NULL;
        }
    }
    else    // just copy the buffer since data is not compressed
    {
        // printf("compression failed before, fall back to memory copy\n");
        memcpy(uncompressed_data, compressed_data, compressed_size);
    }

    return adios_datablock_new(reqgroup->transinfo->orig_type,
                               completed_pg_reqgroup->timestep,
                               completed_pg_reqgroup->pg_bounds_sel,
                               uncompressed_data);
}
Esempio n. 9
0
// NOTE: varblocks_by_var is actually a 1D array varblocks_by_var[var] of 3D "arrays" varblockdata[ts][pg][point_in_pg] of type xml_spec->vartypes[var] (however, points per PG varies)
static void collect_varblocks_by_pg(
		const dataset_xml_spec_t *xml_spec,
		const dataset_global_spec_t *global_spec,
		int num_ts, int num_pgs_per_ts, int ndim, int nvar,
		const uint64_t pg_dims[num_ts][num_pgs_per_ts][ndim],
		const void **varblocks_by_var,
		const void *out_varblocks_by_pg[num_ts][num_pgs_per_ts][nvar])
{
	int ts, pg, var;

	// Some maths
	const uint64_t varblocks_per_ts = nvar * num_pgs_per_ts;

	// Cache the datatype size for each variable, and create a data pointer that we can advance
	int var_typesizes[nvar];
	const char *varblock_datas[nvar];
	for (var = 0; var < nvar; ++var) {
		var_typesizes[var] = adios_get_type_size(xml_spec->vartypes[var], NULL);
		varblock_datas[var] = (const char *)varblocks_by_var[var];
	}

	// Iterate over all varblocks (var in pg in timestep), get a pointer to the data buffer for that
	// varblock, and assign it to the proper place in the output array of PG data buffers
	for (ts = 0; ts < num_ts; ++ts) {
		for (pg = 0; pg < num_pgs_per_ts; ++pg) {
			// Compute the points per varblock in this PG
			const uint64_t points_per_varblock = dim_prod(ndim, pg_dims[ts][pg]);

			for (var = 0; var < nvar; ++var) {
				const int var_typesize = var_typesizes[var];
				const uint64_t varblock_size = points_per_varblock * var_typesize;

				// Get the data for this varblock, and advance the pointer by one varblock
				const char *data_for_varblock = varblock_datas[var];
				varblock_datas[var] += varblock_size;

				// Finally, assign the pointer
				out_varblocks_by_pg[ts][pg][var] = data_for_varblock;
			}
		}
	}
}
Esempio n. 10
0
inline static uint64_t adios_patch_data_wb_to_wb(void *dst, uint64_t dst_ragged_offset, const ADIOS_SELECTION_WRITEBLOCK_STRUCT *dst_wb,
                                                 void *src, uint64_t src_ragged_offset, const ADIOS_SELECTION_WRITEBLOCK_STRUCT *src_wb,
                                                 const ADIOS_SELECTION_BOUNDINGBOX_STRUCT *vb_bounds,
                                                 enum ADIOS_DATATYPES datum_type,
                                                 enum ADIOS_FLAG swap_endianness)
{
	uint64_t copy_elem_offset, copy_nelems;
	const uint64_t vb_size_in_elements = compute_volume(vb_bounds->ndim, vb_bounds->count);

	const uint64_t dst_elem_offset = dst_wb->is_sub_pg_selection ? dst_wb->element_offset : 0;
	const uint64_t dst_nelems = dst_wb->is_sub_pg_selection ? dst_wb->nelements : vb_size_in_elements;
	const uint64_t src_elem_offset = src_wb->is_sub_pg_selection ? src_wb->element_offset : 0;
	const uint64_t src_nelems = src_wb->is_sub_pg_selection ? src_wb->nelements : vb_size_in_elements;

	// Find out how many elements overlap between the two
	// writeblock selections (due to the potential existence
	// of sub-PG writeblock selections; if both are whole-PG,
	// this overlap will be complete)
	int intersects = intersect_segments(
			dst_elem_offset, dst_nelems,
			src_elem_offset, src_nelems,
			&copy_elem_offset, &copy_nelems
	);

	// Copy any elements that are common to both selections
	// (for whole-PG writeblock selections, this will be all of them)
	if (intersects) {
		int typesize = adios_get_type_size(datum_type, NULL);
		void *copy_dst = (char*)dst + (copy_elem_offset - dst_elem_offset) * typesize;
		void *copy_src = (char*)src + (copy_elem_offset - src_elem_offset) * typesize;

		memcpy(copy_dst, copy_src, copy_nelems * typesize);
		if (swap_endianness == adios_flag_yes)
			change_endianness(copy_dst, copy_nelems * typesize, datum_type);

		return copy_nelems;
	} else {
		return 0;
	}
}
static void test_file_mode_reads_on_var(ADIOS_FILE *fp, const char *bp_filename, const char *varname) {
	int i;

	ADIOS_VARINFO *varinfo = adios_inq_var(fp, varname);
	MPI_Assert(COMM, varinfo);

	if (varinfo->value != NULL) {
		//if (rank == 0) fprintf(stderr, "(skipping scalar variable '%s')\n", varname);
		adios_free_varinfo(varinfo);
		return;
	}

	fprintf(stderr, "[rank %d/%d] Starting file-mode writeblock reads on %s:/%s\n", rank, size, bp_filename, varname);

	adios_inq_var_blockinfo(fp, varinfo);
	MPI_Assert(COMM, varinfo->blockinfo);

	const enum ADIOS_DATATYPES datatype = varinfo->type;
	const int datatypesize = adios_get_type_size(datatype, NULL);

	int timestep, timestep_blockidx, blockidx = 0;
	for (timestep = 0; timestep < varinfo->nsteps; ++timestep) {
		for (timestep_blockidx = 0; timestep_blockidx < varinfo->nblocks[timestep]; ++timestep_blockidx, ++blockidx) {
			if (blockidx % size != rank) continue;

			const ADIOS_VARBLOCK *vb = &varinfo->blockinfo[blockidx];

			ADIOS_SELECTION *block_bb = adios_selection_boundingbox(varinfo->ndim, vb->start, vb->count);
			ADIOS_SELECTION *block_wb = adios_selection_writeblock(timestep_blockidx);
			ADIOS_SELECTION *block_abs_wb = adios_selection_writeblock(blockidx);
			block_abs_wb->u.block.is_absolute_index = 1;

			uint64_t blocksize = datatypesize;
			for (i = 0; i < varinfo->ndim; ++i)
				blocksize *= vb->count[i];

			void *buf_bb = malloc(blocksize);
			void *buf_wb = malloc(blocksize);
			void *buf_abs_wb = malloc(blocksize);
			memset(buf_bb,     0, blocksize);
			memset(buf_wb,     1, blocksize);
			memset(buf_abs_wb, 2, blocksize);
			MPI_Assert(COMM, buf_bb && buf_wb && buf_abs_wb);

			adios_schedule_read(fp, block_bb,     varname, timestep, 1, buf_bb    );
			adios_schedule_read(fp, block_wb,     varname, timestep, 1, buf_wb    );
			adios_schedule_read(fp, block_abs_wb, varname, timestep, 1, buf_abs_wb);
			adios_perform_reads(fp, 1);

			fprintf(stderr, "[rank %d/%d] Checking file-mode blockidx %d BB vs. WB...\n", rank, size, blockidx);
			MPI_Assert(COMM, memcmp(buf_bb, buf_wb, blocksize) == 0);
			fprintf(stderr, "[rank %d/%d] Checking file-mode blockidx %d BB vs. abs-WB...\n", rank, size, blockidx);
			MPI_Assert(COMM, memcmp(buf_bb, buf_abs_wb, blocksize) == 0);

			free(buf_bb); free(buf_wb); free(buf_abs_wb);
			adios_selection_delete(block_bb);
			adios_selection_delete(block_wb);
			adios_selection_delete(block_abs_wb);
		}
	}

	adios_free_varinfo(varinfo);

	fprintf(stderr, "[rank %d/%d] Finished file-mode writeblock reads on %s:/%s\n", rank, size, bp_filename, varname);
}
Esempio n. 12
0
// Whenever we are patching between a point selection and bounding box, we
// will always iterate over the point selection, check each points for containment
// within the bounding box, and compute byte offsets for the point within the point list
// and bounding box, regardless of whether the point selection is on the source or
// destination buffer. Therefore, we include a helper function with a boolean flag
// to switch the copy direction, and just branch for a few lines during the copy
// operation. This simplifies the code a lot, and reduces the LoC in this file (although
// this comment makes up for a good bit of that savings).
inline static uint64_t adios_patch_data_bb_pts_helper(void *dst, uint64_t dst_ragged_offset, void *src, uint64_t src_ragged_offset,
                                                      const ADIOS_SELECTION_POINTS_STRUCT *pts,
                                                      const ADIOS_SELECTION_BOUNDINGBOX_STRUCT *bb,
                                                      _Bool isDestPoints, enum ADIOS_DATATYPES datum_type,
                                                      enum ADIOS_FLAG swap_endianness) {
    const int ndim = pts->ndim;
    uint64_t i;
    int j;
    uint64_t pts_copied = 0;
    uint64_t byte_offset_in_bb_buffer, byte_offset_in_pt_buffer;
    const uint64_t *cur_pt;
    uint64_t *bb_byte_strides = malloc(sizeof(uint64_t) * ndim);
    uint64_t *pt_relative_to_bb = malloc(sizeof(uint64_t) * ndim);

    // Compute the strides into the source bounding box array
    int typelen = adios_get_type_size(datum_type, NULL);
    uint64_t bb_volume = typelen;
    for (j = ndim - 1; j >= 0; j--) {
        bb_byte_strides[j] = bb_volume;
        bb_volume *= bb->count[j];
    }

    uint64_t dst_byte_ragged_offset = dst_ragged_offset * typelen;
    uint64_t src_byte_ragged_offset = src_ragged_offset * typelen;

    // Check that the selection dimensions are compatible
    assert(pts->ndim == bb->ndim);

    // Check each point; if it's in the bounding box, perform a copy
    for (i = 0; i < pts->npoints; i++) {
        cur_pt = &pts->points[i * ndim];

        for (j = 0; j < ndim; j++) {
            // If the point's coordinate in some dimension is outside the bounding box
            if (cur_pt[j] < bb->start[j] ||
                cur_pt[j] >= bb->start[j] + bb->count[j]) {
                break;
            }
        }

        // If the point is within the bounding box
        if (j == ndim) {
            vector_sub(ndim, pt_relative_to_bb, cur_pt, bb->start);

            byte_offset_in_bb_buffer = 0;
            for (j = 0; j < ndim; j++)
                byte_offset_in_bb_buffer += pt_relative_to_bb[j] * bb_byte_strides[j];

            byte_offset_in_pt_buffer = i * typelen;

            if (isDestPoints) {
                assert(byte_offset_in_pt_buffer >= dst_byte_ragged_offset);
                assert(byte_offset_in_bb_buffer >= src_byte_ragged_offset);
                memcpy((char*)dst + byte_offset_in_pt_buffer - dst_byte_ragged_offset, (char*)src + byte_offset_in_bb_buffer - src_byte_ragged_offset, typelen);
            } else {
                assert(byte_offset_in_bb_buffer >= dst_byte_ragged_offset);
                assert(byte_offset_in_pt_buffer >= src_byte_ragged_offset);
                memcpy((char*)dst + byte_offset_in_bb_buffer - dst_byte_ragged_offset, (char*)src + byte_offset_in_pt_buffer - src_byte_ragged_offset, typelen);
            }
            pts_copied++;
        }
    }

    free(bb_byte_strides);
    free(pt_relative_to_bb);

    return pts_copied;
}
Esempio n. 13
0
void add_var_to_index (
        struct adios_index_struct_v1 *  index, 
        struct adios_process_group_header_struct_v1 * pg_header, 
        struct adios_var_header_struct_v1 * var_header,
        struct adios_var_payload_struct_v1 * var_payload)
{

    /* similar to code from adios_internals.c:adios_build_index_v1() */
    struct adios_index_var_struct_v1 * v_index;
    v_index = malloc (sizeof (struct adios_index_var_struct_v1));
    v_index->characteristics = malloc (
            sizeof (struct adios_index_characteristic_struct_v1)
            );

    v_index->id = var_header->id;
    v_index->group_name = strdup (pg_header->name);
    v_index->var_name = (var_header->name ? strdup (var_header->name) : 0L);
    v_index->var_path = (var_header->path ? strdup (var_header->path) : 0L);
    v_index->type = var_header->type;

    v_index->characteristics_count = 1;
    v_index->characteristics_allocated = 1;
    v_index->characteristics [0].offset = var_header->characteristics.offset;
    v_index->characteristics [0].payload_offset = var_header->characteristics.payload_offset;

    v_index->characteristics [0].file_index = -1; // It works only with single BP files
    v_index->characteristics [0].time_index = pg_header->time_index;

    v_index->characteristics [0].value = 0;

    /* Determine the dimensions from actual values or references of scalars */
    process_dimensions (var_header, v_index);


    // NCSU - Initializing stat related info in index
    v_index->characteristics [0].bitmap = 0;
    v_index->characteristics [0].stats = 0;

    memcpy (&v_index->characteristics[0].transform,
            &var_header->characteristics.transform,
            sizeof (struct adios_index_characteristic_transform_struct));

    // Save scalar's value
    if (var_payload->payload)
    {
        uint64_t size = adios_get_type_size (var_header->type, var_payload->payload);
        if (var_header->type == adios_string) {
            v_index->characteristics [0].value = malloc (size + 1);
            memcpy (v_index->characteristics [0].value, var_payload->payload, size);
            ((char *) (v_index->characteristics [0].value)) [size] = 0;
        } else {
            v_index->characteristics [0].value = malloc (size);
            memcpy (v_index->characteristics [0].value, var_payload->payload, size);
        }
    }

    /* FIXME: Missing statistics and transformation statistics */

    v_index->next = 0;

    // this fn will either take ownership for free
    //printf ("  add index var %s/%s\n", v_index->var_path, v_index->var_name);
    index_append_var_v1 (index, v_index, 1);
}