From 350101ed9059acde090453c5dcc5342c147dcbf6 Mon Sep 17 00:00:00 2001 From: Alan Greer Date: Wed, 11 Mar 2015 10:53:11 +0000 Subject: [PATCH 1/2] Implemented use of auto_ndattr_default tag for issue #66. Added support for setting auto_ndattr_default tag on the root group. --- ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp | 83 ++++++++++++++++++------- ADApp/pluginSrc/NDFileHDF5LayoutXML.h | 5 ++ 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp b/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp index 501e044d2..2cb5468bd 100644 --- a/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp +++ b/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp @@ -17,26 +17,28 @@ namespace hdf5 { - const std::string LayoutXML::ATTR_ELEMENT_NAME = "name"; - const std::string LayoutXML::ATTR_GROUP = "group"; - const std::string LayoutXML::ATTR_DATASET = "dataset"; - const std::string LayoutXML::ATTR_ATTRIBUTE = "attribute"; - const std::string LayoutXML::ATTR_GLOBAL = "global"; - const std::string LayoutXML::ATTR_HARDLINK = "hardlink"; - - const std::string LayoutXML::ATTR_SOURCE = "source"; - const std::string LayoutXML::ATTR_SRC_DETECTOR = "detector"; - const std::string LayoutXML::ATTR_SRC_DET_DEFAULT = "det_default"; - const std::string LayoutXML::ATTR_SRC_NDATTR = "ndattribute"; - const std::string LayoutXML::ATTR_SRC_CONST = "constant"; - const std::string LayoutXML::ATTR_SRC_CONST_VALUE = "value"; - const std::string LayoutXML::ATTR_SRC_CONST_TYPE = "type"; - const std::string LayoutXML::ATTR_GRP_NDATTR_DEFAULT = "ndattr_default"; - const std::string LayoutXML::ATTR_SRC_WHEN = "when"; - const std::string LayoutXML::ATTR_GLOBAL_NAME = "name"; - const std::string LayoutXML::ATTR_GLOBAL_VALUE = "ndattribute"; - const std::string LayoutXML::ATTR_HARDLINK_NAME = "name"; - const std::string LayoutXML::ATTR_HARDLINK_TARGET = "target"; + const std::string LayoutXML::ATTR_ELEMENT_NAME = "name"; + const std::string LayoutXML::ATTR_ROOT = "hdf5_layout"; + const std::string LayoutXML::ATTR_GROUP = "group"; + const std::string LayoutXML::ATTR_DATASET = "dataset"; + const std::string LayoutXML::ATTR_ATTRIBUTE = "attribute"; + const std::string LayoutXML::ATTR_GLOBAL = "global"; + const std::string LayoutXML::ATTR_HARDLINK = "hardlink"; + + const std::string LayoutXML::ATTR_ROOT_NDATTR_DEFAULT = "auto_ndattr_default"; + const std::string LayoutXML::ATTR_SOURCE = "source"; + const std::string LayoutXML::ATTR_SRC_DETECTOR = "detector"; + const std::string LayoutXML::ATTR_SRC_DET_DEFAULT = "det_default"; + const std::string LayoutXML::ATTR_SRC_NDATTR = "ndattribute"; + const std::string LayoutXML::ATTR_SRC_CONST = "constant"; + const std::string LayoutXML::ATTR_SRC_CONST_VALUE = "value"; + const std::string LayoutXML::ATTR_SRC_CONST_TYPE = "type"; + const std::string LayoutXML::ATTR_GRP_NDATTR_DEFAULT = "ndattr_default"; + const std::string LayoutXML::ATTR_SRC_WHEN = "when"; + const std::string LayoutXML::ATTR_GLOBAL_NAME = "name"; + const std::string LayoutXML::ATTR_GLOBAL_VALUE = "ndattribute"; + const std::string LayoutXML::ATTR_HARDLINK_NAME = "name"; + const std::string LayoutXML::ATTR_HARDLINK_TARGET = "target"; const std::string LayoutXML::DEFAULT_LAYOUT = " \ \ @@ -68,7 +70,7 @@ namespace hdf5 \ "; - LayoutXML::LayoutXML() : ptr_tree(NULL), ptr_curr_element(NULL) + LayoutXML::LayoutXML() : auto_ndattr_default(true), ptr_tree(NULL), ptr_curr_element(NULL) { log = log4cxx::Logger::getLogger("LayoutXML"); @@ -232,6 +234,11 @@ namespace hdf5 return this->globals[name]; } + bool LayoutXML::getAutoNDAttrDefault() + { + return auto_ndattr_default; + } + /** Process one XML node and create the necessary HDF5 element if necessary * */ @@ -247,13 +254,14 @@ namespace hdf5 } std::string name((const char*)xmlname); - switch( type ) { // Elements can be either 'group', 'dataset' or 'attribute' case XML_READER_TYPE_ELEMENT: //LOG4CXX_DEBUG(log, "process_node: \'" << name << "\' (" << xmlname << ")" ); - if (name == LayoutXML::ATTR_GROUP){ + if (name == LayoutXML::ATTR_ROOT){ + ret = this->parse_root(); + } else if (name == LayoutXML::ATTR_GROUP){ ret = this->new_group(); } else if (name == LayoutXML::ATTR_DATASET){ ret = this->new_dataset(); @@ -392,6 +400,35 @@ namespace hdf5 return ret; } + int LayoutXML::parse_root() + { + // First check the basics, no attributes is not an error but we should return + if (! xmlTextReaderHasAttributes(this->xmlreader) ) return 0; + + // Check for the auto_ndattr_default tag + xmlChar * root_auto = NULL; + root_auto = xmlTextReaderGetAttribute(this->xmlreader, (const xmlChar *)LayoutXML::ATTR_ROOT_NDATTR_DEFAULT.c_str()); + + // A tag has been added but it's not the one we expect, return an error + if (root_auto == NULL) return -1; + + // Get the standard string representation of the tag + std::string str_root_auto((char*)root_auto); + xmlFree(root_auto); + + // Now check if we have the correct string + if (str_root_auto == "false"){ + // Set our flag to false and return success + auto_ndattr_default = false; + return 0; + } else if (str_root_auto == "true"){ + // Do nothing but return success + return 0; + } + // Any strings other than false (or true) are not understood, return an error + return -1; + } + int LayoutXML::new_group() { // First check the basics diff --git a/ADApp/pluginSrc/NDFileHDF5LayoutXML.h b/ADApp/pluginSrc/NDFileHDF5LayoutXML.h index 7d61e4305..cff91ed7f 100644 --- a/ADApp/pluginSrc/NDFileHDF5LayoutXML.h +++ b/ADApp/pluginSrc/NDFileHDF5LayoutXML.h @@ -60,12 +60,14 @@ namespace hdf5 { public: static const std::string ATTR_ELEMENT_NAME; + static const std::string ATTR_ROOT; static const std::string ATTR_GROUP; static const std::string ATTR_DATASET; static const std::string ATTR_ATTRIBUTE; static const std::string ATTR_GLOBAL; static const std::string ATTR_HARDLINK; + static const std::string ATTR_ROOT_NDATTR_DEFAULT; static const std::string ATTR_SOURCE; static const std::string ATTR_SRC_DETECTOR; static const std::string ATTR_SRC_DET_DEFAULT; @@ -92,6 +94,7 @@ namespace hdf5 Root* get_hdftree(); std::string get_global(const std::string& name); + bool getAutoNDAttrDefault(); private: int process_node(); @@ -99,12 +102,14 @@ namespace hdf5 int process_dset_xml_attribute(DataSource& out); int process_attribute_xml_attribute(Attribute& out); + int parse_root(); int new_group(); int new_dataset(); int new_attribute(); int new_global(); int new_hardlink(); + bool auto_ndattr_default; log4cxx::LoggerPtr log; Root* ptr_tree; Element *ptr_curr_element; From 3b71280513f944f7e798e3010c5194f765cc8edf Mon Sep 17 00:00:00 2001 From: Alan Greer Date: Wed, 11 Mar 2015 13:34:57 +0000 Subject: [PATCH 2/2] Save attribute datasets to the root location as a default (Resolve #66). Attribute datasets are now saved to the root location if no default dataset group is specified. This can be overridden by setting a tag to false (auto_ndattr_default) in the hdf5_layout root element. Resolves issue #66. --- ADApp/pluginSrc/NDFileHDF5.cpp | 43 +++++++++++++++++-------- ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp | 3 ++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/ADApp/pluginSrc/NDFileHDF5.cpp b/ADApp/pluginSrc/NDFileHDF5.cpp index 52a6150e6..40272551d 100644 --- a/ADApp/pluginSrc/NDFileHDF5.cpp +++ b/ADApp/pluginSrc/NDFileHDF5.cpp @@ -1992,27 +1992,35 @@ 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; else dims[0] = this->numPerformancePoints; + if(perf_group == NULL) + { + // Check if the auto_ndattr_default tag is true, if it is then the root group is the file + if (this->layout.getAutoNDAttrDefault()){ + group_performance = this->file; + } else { + asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING, "%s::writePerformanceDataset No default attribute group defined.\n", + driverName); + return asynError; + } + } else { + group_performance = H5Gopen(this->file, perf_group->get_full_name().c_str(), H5P_DEFAULT); + } + /* Create the "timestamp" dataset */ dataspace_id = H5Screate_simple(2, dims, NULL); - group_performance = H5Gopen(this->file, perf_group->get_full_name().c_str(), H5P_DEFAULT); dataset_id = H5Dcreate2(group_performance, "timestamp", H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (!H5Iis_valid(dataset_id)) { asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING, "NDFileHDF5::writePerformanceDataset: unable to create \'timestamp\' dataset."); H5Sclose(dataspace_id); - H5Gclose(group_performance); + if(perf_group != NULL){ + H5Gclose(group_performance); + } return asynError; } /* Write the second dataset. */ @@ -2027,7 +2035,9 @@ asynStatus NDFileHDF5::writePerformanceDataset() H5Dclose(dataset_id); /* Close the group. */ - H5Gclose(group_performance); + if(perf_group != NULL){ + H5Gclose(group_performance); + } } else { return asynError; } @@ -2070,8 +2080,13 @@ asynStatus NDFileHDF5::createAttributeDataset() } } else { - asynPrint(this->pasynUserSelf, ASYN_TRACE_WARNING, "%s::%s No default attribute group defined.\n", - driverName, functionName); + // Check if the auto_ndattr_default tag is true, if it is then the root group is the file + if (this->layout.getAutoNDAttrDefault()){ + groupDefault = this->file; + } 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 @@ -2196,7 +2211,9 @@ asynStatus NDFileHDF5::createAttributeDataset() } ndAttr = this->pFileAttributes->next(ndAttr); } - H5Gclose(groupDefault); + if(def_group != NULL){ + H5Gclose(groupDefault); + } return asynSuccess; } diff --git a/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp b/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp index 2cb5468bd..37d9e1fed 100644 --- a/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp +++ b/ADApp/pluginSrc/NDFileHDF5LayoutXML.cpp @@ -91,6 +91,7 @@ namespace hdf5 int LayoutXML::load_xml() { int ret = 0; + auto_ndattr_default = true; this->xmlreader = xmlReaderForMemory(DEFAULT_LAYOUT.c_str(), (int)DEFAULT_LAYOUT.size(), "noname.xml", @@ -125,6 +126,7 @@ namespace hdf5 int LayoutXML::load_xml(const std::string& filename) { int ret = 0; + auto_ndattr_default = true; // if the file name contains xmlreader = xmlReaderForMemory(filename.c_str(), (int)filename.length(), NULL, NULL, 0); @@ -161,6 +163,7 @@ namespace hdf5 { int ret = 0; int status = 0; + auto_ndattr_default = true; // if the file name contains