diff --git a/ADApp/pluginSrc/NDFileHDF5.cpp b/ADApp/pluginSrc/NDFileHDF5.cpp index 696420ac6..f7dcfa482 100644 --- a/ADApp/pluginSrc/NDFileHDF5.cpp +++ b/ADApp/pluginSrc/NDFileHDF5.cpp @@ -392,25 +392,29 @@ asynStatus NDFileHDF5::createTree(hdf5::Group* root, hid_t h5handle) } // Write contant datasets to file - this->writeHdfConstDatasets(new_group, root); - - getIntegerParam(NDFileHDF5_storeAttributes, &storeAttributes); - if (storeAttributes == 1){ - // Set some attributes on the group - this->writeHdfAttributes(new_group, root); - } +// this->writeHdfConstDatasets(new_group, root); // Create all the datasets in this group hdf5::Group::MapDatasets_t::iterator it_dsets; hdf5::Group::MapDatasets_t& datasets = root->get_datasets(); for (it_dsets = datasets.begin(); it_dsets != datasets.end(); ++it_dsets){ hid_t new_dset = this->createDataset(new_group, it_dsets->second); - if (new_dset <= 0) continue; // failure to create the datasets so move on to next + if (new_dset <= 0) { +//hdf5::Dataset *dset = it_dsets->second; +//asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Failed to create dataset: %s\n", driverName, functionName, dset->get_name().c_str()); + continue; // failure to create the datasets so move on to next + } // Write the hdf attributes to the dataset this->writeHdfAttributes( new_dset, it_dsets->second); // Datasets are closed after data has been written } + getIntegerParam(NDFileHDF5_storeAttributes, &storeAttributes); + if (storeAttributes == 1){ + // Set some attributes on the group + this->writeHdfAttributes(new_group, root); + } + hdf5::Group::MapGroups_t::const_iterator it_group; hdf5::Group::MapGroups_t& groups = root->get_groups(); for (it_group = groups.begin(); it_group != groups.end(); ++it_group){ @@ -503,6 +507,8 @@ void NDFileHDF5::writeHdfAttributes( hid_t h5_handle, hdf5::Element* element) this->writeH5attrInt32(h5_handle, attr.get_name(), attr.source.get_src_def()); break; default: + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::writeHdfAttributes unknown type: unable to create attribute: %s\n", + driverName, attr.get_name()); break; } } @@ -545,10 +551,35 @@ void NDFileHDF5::writeHdfConstDatasets( hid_t h5_handle, hdf5::Group* group) } } +hid_t NDFileHDF5::writeHdfConstDataset( hid_t h5_handle, hdf5::Dataset* dset) +{ + hdf5::DataType_t dtype = hdf5::string; + + if(dset != NULL && dset->data_source().is_src_constant()) + { + dtype = dset->data_source().get_datatype(); + switch ( dtype ) + { + case hdf5::string: + return this->writeH5dsetStr(h5_handle, dset->get_name(), dset->data_source().get_src_def()); + break; + case hdf5::float64: + return this->writeH5dsetFloat64(h5_handle, dset->get_name(), dset->data_source().get_src_def()); + break; + case hdf5::int32: + return this->writeH5dsetInt32(h5_handle, dset->get_name(), dset->data_source().get_src_def()); + break; + default: + return -1; + break; + } + } +} + /** * Write a string constant dataset. */ -void NDFileHDF5::writeH5dsetStr(hid_t element, const std::string &name, const std::string &str_value) const +hid_t NDFileHDF5::writeH5dsetStr(hid_t element, const std::string &name, const std::string &str_value) const { herr_t hdfstatus = -1; hid_t hdfdatatype = -1; @@ -572,7 +603,7 @@ void NDFileHDF5::writeH5dsetStr(hid_t element, const std::string &name, const st driverName, functionName, name.c_str()); H5Tclose(hdfdatatype); H5Sclose(hdfdataspace); - return; + return -1; } hdfstatus = H5Dwrite(hdfdset, hdfdatatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, str_value.c_str()); @@ -582,17 +613,17 @@ void NDFileHDF5::writeH5dsetStr(hid_t element, const std::string &name, const st H5Aclose (hdfdset); H5Tclose(hdfdatatype); H5Sclose(hdfdataspace); - return; + return -1; } - H5Dclose (hdfdset); + //H5Dclose (hdfdset); H5Tclose(hdfdatatype); H5Sclose(hdfdataspace); - return; + return hdfdset; } -void NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const std::string &str_value) const +hid_t NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const std::string &str_value) const { herr_t hdfstatus = -1; hid_t hdfdatatype = -1; @@ -624,7 +655,7 @@ void NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s unable to create dataset: %s\n", driverName, functionName, name.c_str()); H5Sclose(hdfdataspace); - return; + return -1; } epicsInt32 ival; sscanf(str_value.c_str(), "%d", &ival); @@ -634,7 +665,7 @@ void NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const driverName, functionName, name.c_str()); H5Dclose(hdfdset); H5Sclose(hdfdataspace); - return; + return -1; } } else { // Here we have an array of integer values @@ -655,7 +686,7 @@ void NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s unable to create dataset: %s\n", driverName, functionName, name.c_str()); H5Sclose(hdfdataspace); - return; + return -1; } hdfstatus = H5Dwrite(hdfdset, hdfdatatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ivalues); delete [] ivalues; @@ -664,16 +695,16 @@ void NDFileHDF5::writeH5dsetInt32(hid_t element, const std::string &name, const driverName, functionName, name.c_str()); H5Dclose (hdfdset); H5Sclose(hdfdataspace); - return; + return -1; } } - H5Dclose (hdfdset); + //H5Dclose (hdfdset); H5Sclose(hdfdataspace); - return; + return hdfdset; } -void NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, const std::string &str_value) const +hid_t NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, const std::string &str_value) const { herr_t hdfstatus = -1; hid_t hdfdatatype = -1; @@ -705,7 +736,7 @@ void NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, cons asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s unable to create dataset: %s\n", driverName, functionName, name.c_str()); H5Sclose(hdfdataspace); - return; + return -1; } double fval; sscanf(str_value.c_str(), "%lf", &fval); @@ -715,7 +746,7 @@ void NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, cons driverName, functionName, name.c_str()); H5Dclose (hdfdset); H5Sclose(hdfdataspace); - return; + return -1; } } else { // Here we have an array of integer values @@ -736,7 +767,7 @@ void NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, cons asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s unable to create dataset: %s\n", driverName, functionName, name.c_str()); H5Sclose(hdfdataspace); - return; + return -1; } hdfstatus = H5Dwrite(hdfdset, hdfdatatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, fvalues); delete [] fvalues; @@ -745,12 +776,12 @@ void NDFileHDF5::writeH5dsetFloat64(hid_t element, const std::string &name, cons driverName, functionName, name.c_str()); H5Dclose(hdfdset); H5Sclose(hdfdataspace); - return; + return -1; } } - H5Dclose (hdfdset); + //H5Dclose (hdfdset); H5Sclose(hdfdataspace); - return; + return hdfdset; } @@ -769,6 +800,9 @@ hid_t NDFileHDF5::createDataset(hid_t group, hdf5::Dataset *dset) if (dset->data_source().is_src_detector()) { return this->createDatasetDetector(group, dset); } + if(dset->data_source().is_src_constant()) { + return this->writeHdfConstDataset(group, dset); + } if (dset->data_source().is_src_ndattribute()) { // At this time we cannot create the dataset as we do not know its type yet return -1; @@ -1941,6 +1975,13 @@ asynStatus NDFileHDF5::writePerformanceDataset() } } + if(perf_group == NULL) + { + asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING, "%s::writePerformanceDataset No default attribute group defined.\n", + driverName); + return asynError; + } + getIntegerParam(NDFileNumCaptured, &numCaptured); dims[1] = 5; if (numCaptured < this->numPerformancePoints) dims[0] = numCaptured; @@ -1987,7 +2028,7 @@ asynStatus NDFileHDF5::createAttributeDataset() int extraDims; hsize_t hdfdims=1; int numCaptures = 1; - hid_t hdfgroup; + hid_t groupDefault = -1; const char *attrNames[5] = {"NDAttrName", "NDAttrDescription", "NDAttrSourceType", "NDAttrSource", NULL}; const char *attrStrings[5] = {NULL,NULL,NULL,NULL,NULL}; int i; @@ -2004,15 +2045,21 @@ asynStatus NDFileHDF5::createAttributeDataset() hdf5::Root *root = this->layout.get_hdftree(); hdf5::Group* def_group = root->find_ndattr_default_group(); - hid_t groupDefault = H5Gopen(this->file, def_group->get_full_name().c_str(), H5P_DEFAULT); - if (strlen(this->hostname) > 0) { - this->writeStringAttribute(groupDefault, "hostname", this->hostname); + //check for NULL + if(def_group != NULL) { + groupDefault = H5Gopen(this->file, def_group->get_full_name().c_str(), H5P_DEFAULT); + if (strlen(this->hostname) > 0) { + this->writeStringAttribute(groupDefault, "hostname", this->hostname); + } + } + else { + asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING, "%s::%s No default attribute group defined.\n", + driverName, functionName); } ndAttr = this->pFileAttributes->next(ndAttr); // get the first NDAttribute while(ndAttr != NULL) { - hdfgroup = groupDefault; if (ndAttr->getDataType() < NDAttrString) { @@ -2073,37 +2120,38 @@ asynStatus NDFileHDF5::createAttributeDataset() this->writeStringAttribute(hdfAttrNode->hdfdataset, attrNames[i], attrStrings[i]); } + // Add the attribute to the list + attrList.push_back(hdfAttrNode); } else { - hdfAttrNode->hdfdataspace = H5Screate_simple(hdfAttrNode->hdfrank, &hdfAttrNode->hdfdims, NULL); - // In here we need to create the dataset - hdfAttrNode->hdfdataset = H5Dcreate2(hdfgroup, hdfAttrNode->attrName, - hdfAttrNode->hdfdatatype, hdfAttrNode->hdfdataspace, - H5P_DEFAULT, hdfAttrNode->hdfcparm, H5P_DEFAULT); - - - // create a memory space of exactly one element dimension to use for writing slabs - hdfAttrNode->elementSize = 1; - hdfAttrNode->hdfmemspace = H5Screate_simple(hdfAttrNode->hdfrank, &hdfAttrNode->elementSize, NULL); - - // Write some description of the NDAttribute as a HDF attribute to the dataset - for (i=0; attrNames[i] != NULL; i++) - { - size = strlen(attrStrings[i]); - if (size <= 0) continue; - this->writeStringAttribute(hdfAttrNode->hdfdataset, attrNames[i], attrStrings[i]); + if(groupDefault > -1) { + hdfAttrNode->hdfdataspace = H5Screate_simple(hdfAttrNode->hdfrank, &hdfAttrNode->hdfdims, NULL); + // In here we need to create the dataset + hdfAttrNode->hdfdataset = H5Dcreate2(groupDefault, hdfAttrNode->attrName, + hdfAttrNode->hdfdatatype, hdfAttrNode->hdfdataspace, + H5P_DEFAULT, hdfAttrNode->hdfcparm, H5P_DEFAULT); + + + // create a memory space of exactly one element dimension to use for writing slabs + hdfAttrNode->elementSize = 1; + hdfAttrNode->hdfmemspace = H5Screate_simple(hdfAttrNode->hdfrank, &hdfAttrNode->elementSize, NULL); + + // Write some description of the NDAttribute as a HDF attribute to the dataset + for (i=0; attrNames[i] != NULL; i++) + { + size = strlen(attrStrings[i]); + if (size <= 0) continue; + this->writeStringAttribute(hdfAttrNode->hdfdataset, attrNames[i], attrStrings[i]); + } + // Add the attribute to the list + attrList.push_back(hdfAttrNode); } - } - - // Add the attribute to the list - attrList.push_back(hdfAttrNode); - } // if the NDArray attribute is a string we attach it as an HDF attribute to the meta data group. else if (ndAttr->getDataType() == NDAttrString) { - hid_t dsetgroup; + hid_t dsetgroup = -1; hdf5::Dataset *dset = NULL; int closeGroup = 0; // Search for the dataset of the NDAttribute. If it exists then we use it @@ -2114,16 +2162,19 @@ asynStatus NDFileHDF5::createAttributeDataset() // Here we must close the group after writing the attribute closeGroup = 1; } else { - dsetgroup = hdfgroup; + if(groupDefault > -1) + dsetgroup = groupDefault; } - // Write some description of the NDAttribute as a HDF attribute to the dataset - ndAttr->getValueInfo(&ndAttrDataType, &size); - char * attrDataTypeStr = (char*)calloc(size, sizeof(char)); - ndAttr->getValue(ndAttrDataType, attrDataTypeStr, size); - if (size > 0) this->writeStringAttribute(dsetgroup, ndAttr->getName(), attrDataTypeStr); - free(attrDataTypeStr); - if (closeGroup == 1){ - H5Gclose(dsetgroup); + if(dsetgroup > -1) { + // Write some description of the NDAttribute as a HDF attribute to the dataset + ndAttr->getValueInfo(&ndAttrDataType, &size); + char * attrDataTypeStr = (char*)calloc(size, sizeof(char)); + ndAttr->getValue(ndAttrDataType, attrDataTypeStr, size); + if (size > 0) this->writeStringAttribute(dsetgroup, ndAttr->getName(), attrDataTypeStr); + free(attrDataTypeStr); + if (closeGroup == 1){ + H5Gclose(dsetgroup); + } } } ndAttr = this->pFileAttributes->next(ndAttr); @@ -2161,8 +2212,10 @@ asynStatus NDFileHDF5::writeAttributeDataset(hdf5::When_t whenToSave) continue; } //check if when to save matches. - if (hdfAttrNode->whenToSave != whenToSave) + if (hdfAttrNode->whenToSave != whenToSave) { + //asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s WARNING: NDAttribute named \'%s\' when to save miss match\n", driverName, functionName, hdfAttrNode->attrName); continue; + } // find the data based on datatype ret = ndAttr->getValue(ndAttr->getDataType(), datavalue, 8); diff --git a/ADApp/pluginSrc/NDFileHDF5.h b/ADApp/pluginSrc/NDFileHDF5.h index ab402632f..104f418d9 100644 --- a/ADApp/pluginSrc/NDFileHDF5.h +++ b/ADApp/pluginSrc/NDFileHDF5.h @@ -85,9 +85,10 @@ class epicsShareClass NDFileHDF5 : public NDPluginFile asynStatus createHardLinks(hdf5::Group* root); void writeHdfConstDatasets( hid_t h5_handle, hdf5::Group* group); - void writeH5dsetStr(hid_t element, const std::string &name, const std::string &str_value) const; - void writeH5dsetInt32(hid_t element, const std::string &name, const std::string &str_value) const; - void writeH5dsetFloat64(hid_t element, const std::string &name, const std::string &str_value) const; + hid_t writeHdfConstDataset( hid_t h5_handle, hdf5::Dataset* dset); + hid_t writeH5dsetStr(hid_t element, const std::string &name, const std::string &str_value) const; + hid_t writeH5dsetInt32(hid_t element, const std::string &name, const std::string &str_value) const; + hid_t writeH5dsetFloat64(hid_t element, const std::string &name, const std::string &str_value) const; void writeHdfAttributes( hid_t h5_handle, hdf5::Element* element); hid_t createDataset(hid_t group, hdf5::Dataset *dset);