i am struggling with creating an unlimted 1 dimensional dataset that I write in chunks.
the following Mimimal Working Example, works correctly for the initial chunk write, but fails for subsequent chunks, with the following error.
HDF5-DIAG: Error detected in HDF5 (1.10.7) thread 1:
#000: ../../../src/H5Dio.c line 319 in H5Dwrite(): could not get a validated dataspace from mem_space_id
major: Invalid arguments to routine
minor: Bad value
#001: ../../../src/H5S.c line 257 in H5S_get_validated_dataspace(): selection + offset not within extent
major: Dataspace
minor: Out of range
terminate called after throwing an instance of 'H5::DataSetIException'
[1] 426631 IOT instruction (core dumped)
I am sure what I am doing wrong is simple, but I cant for the life of me see it, any help / code corrections are gratefully received.
Code below compiles correctly on Ubuntu Linux, with ubuntu bundled HDF5 dev libraries
#include <iostream>
#include <string>
#include <vector>
#include "H5Cpp.h"
using namespace H5;
const H5std_string FILE_NAME("custom_data.h5");
// Define a struct to represent a data record
struct DataRecord {
int id;
double latitude;
double longitude;
double confidence;
std::string csquare;
};
int main() {
// Create a new HDF5 file
std::string dataset_name = "my_dataset";
hsize_t record_count = 100;
H5File file(FILE_NAME, H5F_ACC_TRUNC);
std::cout << " created hdf5" << std::endl;
hsize_t chunk_dims[] = {record_count};
hsize_t dims[] = {0};
hsize_t max_dims[] = {H5S_UNLIMITED};
DataSpace dataspace(1, dims, max_dims);
std::cout << " created dataspace" << std::endl;
std::cout << " created data" << std::endl;
CompType datatype(sizeof(DataRecord));
datatype.insertMember("id", HOFFSET(DataRecord, id), PredType::NATIVE_INT);
datatype.insertMember("latitude", HOFFSET(DataRecord, latitude), PredType::NATIVE_DOUBLE);
datatype.insertMember("longitude", HOFFSET(DataRecord, longitude), PredType::NATIVE_DOUBLE);
datatype.insertMember("confidence", HOFFSET(DataRecord, confidence), PredType::NATIVE_DOUBLE);
datatype.insertMember("csquare", HOFFSET(DataRecord, csquare), StrType(PredType::C_S1, H5T_VARIABLE));
std::cout << " created datatype" << std::endl;
DSetCreatPropList create_params;
hsize_t chunk_size[] = {100};
create_params.setChunk(1,chunk_size);
// Create the dataset
DataSet dataset = file.createDataSet(dataset_name, datatype, dataspace, create_params);
std::cout << " created dataset" << std::endl;
// Stream the records to the dataset
int num_records {0};
hsize_t current_size[] = {0};
hsize_t offset[] = {0};
int chunk_num = 0;
std::vector<DataRecord> data(record_count);
for (int i = 0; i < 1000; i++) {
// Generate some fake data
data[i%100].id = i;
data[i%100].latitude = i +((double) 1/i);
data[i%100].longitude = i + ((double) 1/i);
data[i%100].confidence = 1/((double) i);
data[i%100].csquare = "0123456789012345678";
// Add the record to the buffer
// Write the buffer to the dataset if it is full
if (num_records == record_count) {
current_size[0] = (chunk_num+1) * record_count; // make sure we allways have lots of space
dataset.extend(current_size);
std::cout << " extended ok "<<std::endl;
// Select the portion of the file dataspace and memory dataspace
// that correspond to the data buffer
offset[0] = chunk_num * record_count;
DataSpace memspace(1, &record_count);
std::cout << " created memspace"<<std::endl;
memspace.selectHyperslab(H5S_SELECT_SET, &record_count, offset);
std::cout << "selected Hyperslab"<<std::endl;
DataSpace filespace = dataset.getSpace();
std::cout << "created filespace"<<std::endl;
filespace.selectHyperslab(H5S_SELECT_SET, &record_count, offset);
std::cout << "selected Hyperslab"<<std::endl;
// Write the data buffer to the dataset
dataset.write(data.data(), datatype, memspace, filespace);
chunk_num++;
num_records = 0;
std::cout << "written "<<i<<" onto chunk "<< chunk_num<< std::endl;
// lets wipe the vector
data.clear();
data.resize(record_count);
} else {
num_records++;
}
}
dataset.close();
file.close();
return 0;
}