51 #include <H5Epublic.h> 53 #include <boost/tokenizer.hpp> 54 #include <boost/utility.hpp> 84 const std::string k_mappingStr(
"mapping");
85 const std::string k_partitionName(
"partition");
86 const std::string k_versionAttrName(
"version_number");
87 const std::string k_classNameAttrName(
"class_name");
88 const std::string k_mappingTypeAttrName(
"mapping_type");
93 int k_currentFileVersion[3] =
95 int k_minFileVersion[2] = { 0, 0 };
99 std::vector<std::string> makeUnique(std::vector<std::string> vec)
101 std::vector<string> ret;
102 std::sort(vec.begin(), vec.end());
103 std::vector<std::string>::iterator newEnd =
104 std::unique(vec.begin(), vec.end());
105 ret.resize(std::distance(vec.begin(), newEnd));
106 std::copy(vec.begin(), newEnd, ret.begin());
114 class print : std::unary_function<T, void>
120 void operator()(
const T& x)
const 122 for (
int i = 0; i < indent; i++)
124 std::cout << x << std::endl;
136 void checkFile(
const std::string &filename)
140 throw NoSuchFileException(filename);
146 bool isSupportedFileVersion(
const int fileVersion[3],
147 const int minVersion[2])
149 stringstream currentVersionStr;
150 currentVersionStr << k_currentFileVersion[0] <<
"." 151 << k_currentFileVersion[1] <<
"." 152 << k_currentFileVersion[2];
153 stringstream fileVersionStr;
154 fileVersionStr << fileVersion[0] <<
"." 155 << fileVersion[1] <<
"." 157 stringstream minVersionStr;
158 minVersionStr << minVersion[0] <<
"." 161 if (fileVersion[0] > k_currentFileVersion[0] ||
162 (fileVersion[0] == k_currentFileVersion[0] &&
163 fileVersion[1] > k_currentFileVersion[1])) {
165 " is higher than the current version " +
166 currentVersionStr.str());
170 if (fileVersion[0] < minVersion[0] ||
171 (fileVersion[0] == minVersion[0] &&
172 fileVersion[1] < minVersion[1])) {
174 " is lower than the minimum supported version " +
175 minVersionStr.str());
183 static herr_t localPrintError( hid_t estack_id,
void *stream )
185 printf(
"H5E message -----------------------\n");
186 return H5Eprint2(estack_id, static_cast<FILE*>(stream));
197 std::string Partition::className()
const 199 return k_partitionName;
205 Partition::addScalarLayer(
const Layer &layer)
207 m_scalarLayers.push_back(layer);
213 Partition::addVectorLayer(
const Layer &layer)
215 m_vectorLayers.push_back(layer);
221 Partition::scalarLayer(
const std::string &name)
const 223 for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
224 i != m_scalarLayers.end(); ++i) {
234 Partition::vectorLayer(
const std::string &name)
const 236 for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
237 i != m_vectorLayers.end(); ++i) {
247 Partition::getScalarLayerNames(std::vector<std::string> &names)
const 251 for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
252 i != m_scalarLayers.end(); ++i) {
253 names.push_back(i->name);
260 Partition::getVectorLayerNames(std::vector<std::string> &names)
const 264 for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
265 i != m_vectorLayers.end(); ++i) {
266 names.push_back(i->name);
275 : m_file(-1), m_metadata(this)
282 if (getenv(
"DEBUG_HDF")) {
283 cerr <<
"Field3DFile -- HDF5 messages are on" << endl;
284 H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
286 H5Eset_auto(H5E_DEFAULT, NULL, NULL);
301 const std::string & ,
305 for (PartitionList::const_iterator i =
m_partitions.begin();
308 if ((**i).mapping->isIdentical(field->mapping())) {
333 if ((**i).name == partitionName)
345 for (PartitionList::const_iterator i =
m_partitions.begin();
347 if ((**i).name == partitionName)
359 size_t pos = partitionName.rfind(
".");
360 if (pos == partitionName.npos) {
361 return partitionName;
363 return partitionName.substr(0, pos);
374 vector<string> tempNames;
376 for (PartitionList::const_iterator i =
m_partitions.begin();
381 names = makeUnique(tempNames);
388 const string &partitionName)
const 396 part->getScalarLayerNames(names);
399 names = makeUnique(names);
406 const string &partitionName)
const 414 part->getVectorLayerNames(names);
417 names = makeUnique(names);
427 for (PartitionList::const_iterator i =
m_partitions.begin();
429 names.push_back((**i).name);
444 Msg::print(
"getIntScalarLayerNames no partition: " + intPartitionName);
448 part->getScalarLayerNames(names);
462 Msg::print(
"getIntVectorLayerNames no partition: " + intPartitionName);
466 part->getVectorLayerNames(names);
494 if (H5Fclose(
m_file) < 0) {
509 for (PartitionList::const_iterator i =
m_partitions.begin();
511 string name = (**i).name;
512 size_t pos = name.rfind(
".");
513 if (pos != name.npos) {
514 if (name.substr(0, pos) == partitionName) {
529 return partitionName +
"." + boost::lexical_cast<std::string>(i);
537 GroupMembershipMap::const_iterator i= groupMembers.begin();
538 GroupMembershipMap::const_iterator end= groupMembers.end();
540 for (; i != end; ++i) {
541 GroupMembershipMap::iterator foundGroupIter =
578 m_filename = filename;
589 m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
592 throw NoSuchFileException(filename);
599 if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
600 stringstream versionStr;
601 versionStr << fileVersion[0] <<
"." 602 << fileVersion[1] <<
"." 604 throw UnsupportedVersionException(versionStr.str());
608 catch (MissingAttributeException &) {
613 if (H5Lexists(
m_file,
"field3d_global_metadata", H5P_DEFAULT)) {
616 if (metadataGroup.
id() > 0) {
617 readMetadata(metadataGroup.
id());
623 "Unknown error when reading file metadata ");
628 if (!readPartitionAndLayerInfo()) {
632 catch (MissingGroupException &e) {
634 throw BadFileHierarchyException(filename);
636 catch (ReadMappingException &e) {
639 throw BadFileHierarchyException(filename);
644 throw BadFileHierarchyException(filename);
648 "Unknown error when reading file hierarchy. ");
649 throw BadFileHierarchyException(filename);
653 catch (NoSuchFileException &e) {
655 +
string(e.what()) );
658 catch (MissingAttributeException &e) {
660 "In file: " + filename +
" - " 661 +
string(e.what()) );
664 catch (UnsupportedVersionException &e) {
666 "In file: " + filename +
" - File version can not be read: " 670 catch (BadFileHierarchyException &) {
672 "In file: " + filename +
" - Bad file hierarchy. ");
677 "In file: " + filename +
" Unknown exception ");
698 status = H5Literate(
m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
718 string mappingPath =
"/" + (**i).name +
"/" + k_mappingStr;
722 if (mappingGroup.
id() < 0)
723 throw MissingGroupException((**i).name +
"/" + k_mappingStr);
731 throw ReadMappingException((**i).name);
735 (**i).mapping = mapping;
741 for (PartitionList::const_iterator i =
m_partitions.begin();
754 status = H5Literate(partitionGroup.
id(), H5_INDEX_NAME, H5_ITER_NATIVE,
759 for (std::vector<LayerInfo>::iterator i =
m_layerInfo.begin();
762 std::string parent = i->parentName;
767 layer.
name = i->name;
768 layer.
parent = i->parentName;
769 if (i->components == 1) {
770 part->addScalarLayer(layer);
771 }
else if (i->components == 3) {
772 part->addVectorLayer(layer);
784 const std::string itemName)
798 const std::string &partitionName,
799 const std::string &layerName)
802 if (!
readAttribute(layerGroup,
string(
"components"), 1, components)) {
804 + partitionName +
"/" + layerName);
808 LayerInfo linfo(partitionName,layerName,components);
824 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
827 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
829 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
831 char *name =
new char[len+1];
832 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
836 H5T_class_t typeClass = H5Tget_class(attrType);
838 if (typeClass == H5T_STRING) {
842 "Failed to read metadata " +
string(name));
848 field->metadata().setStrMetadata(name, value);
853 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
863 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
865 if (typeClass == H5T_INTEGER) {
871 field->metadata().setIntMetadata(name, value);
873 else if (dims[0] == 3){
878 field->metadata().setVecIntMetadata(name, value);
882 "Attribute of size " +
883 boost::lexical_cast<std::string>(dims[0])
884 +
" is not valid for metadata");
887 else if (typeClass == H5T_FLOAT) {
894 field->metadata().setFloatMetadata(name, value);
896 else if (dims[0] == 3){
901 field->metadata().setVecFloatMetadata(name, value);
905 boost::lexical_cast<std::string>(dims[0]) +
906 " is not valid for metadata");
911 +
"' has unsupported data type for metadata");
934 hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
937 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
939 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
941 char *name =
new char[len+1];
942 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
946 H5T_class_t typeClass = H5Tget_class(attrType);
948 if (typeClass == H5T_STRING) {
952 "Failed to read metadata " +
string(name));
963 if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
973 H5Sget_simple_extent_dims(attrSpace, dims, NULL);
975 if (typeClass == H5T_INTEGER) {
983 else if (dims[0] == 3){
992 "Attribute of size " +
993 boost::lexical_cast<std::string>(dims[0])
994 +
" is not valid for metadata");
997 else if (typeClass == H5T_FLOAT) {
1006 else if (dims[0] == 3){
1015 boost::lexical_cast<std::string>(dims[0]) +
1016 " is not valid for metadata");
1021 +
"' has unsupported data type for metadata");
1044 if (!H5Lexists(
m_file,
"field3d_group_membership", H5P_DEFAULT)) {
1049 if (memberGroup < 0) {
1053 typedef boost::tokenizer<boost::char_separator<char> > Tok;
1055 hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
1056 if (num_attrs > 0) {
1058 for (hsize_t idx=0; idx < num_attrs ; ++idx) {
1060 size_t len = H5Aget_name(attrIdx.
id(), 0, NULL);
1062 char *name =
new char[len+1];
1063 if (H5Aget_name(attrIdx.
id(), len+1, name) > 0) {
1065 if (
string(name) ==
"is_field3d_group_membership")
1071 H5T_class_t typeClass = H5Tget_class(attrType);
1073 if (typeClass == H5T_STRING) {
1077 "Failed to read group membership data " 1083 boost::char_separator<char> sep(
" :");
1084 Tok tok(value, sep);
1086 for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
1088 string fieldgroup = *beg; ++beg;
1090 new_value += fieldgroup +
" ";
1094 gpMembershipMap[name] = new_value;
1114 const H5L_info_t * ,
void *opdata)
1121 status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
1127 if (infobuf.type == H5O_TYPE_GROUP) {
1135 if (
string(itemName) !=
"field3d_group_membership" &&
1136 string(itemName) !=
"field3d_global_metadata")
1154 const H5L_info_t * ,
void *opdata)
1161 status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
1163 if (infobuf.type == H5O_TYPE_GROUP) {
1183 if (classType ==
string(
"field3d_layer"))
1188 catch (MissingAttributeException &) {
1228 bool success =
true;
1232 hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
1233 H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
1238 m_file = H5Fcreate(filename.c_str(),
1239 H5F_ACC_TRUNC, H5P_DEFAULT, faid);
1241 case FailOnExisting:
1242 m_file = H5Fcreate(filename.c_str(),
1243 H5F_ACC_EXCL, H5P_DEFAULT, faid);
1249 throw ErrorCreatingFileException(filename);
1253 k_currentFileVersion[0])) {
1260 catch (ErrorCreatingFileException &e) {
1264 catch (WriteAttributeException &e) {
1266 " - Couldn't add attribute " +
string(e.what()) );
1271 "Unknown error when creating file: " + filename );
1288 if (mappingGroup.
id() < 0)
1289 throw CreateGroupException(k_mappingStr);
1292 throw WriteMappingException(k_mappingStr);
1294 catch (CreateGroupException &e) {
1296 throw WriteMappingException(k_mappingStr);
1312 for (; i != end; ++i) {
1326 for (; i != end; ++i) {
1340 for (; i != end; ++i) {
1354 for (; i != end; ++i) {
1368 for (; i != end; ++i) {
1393 for (; i != end; ++i) {
1407 for (; i != end; ++i) {
1421 for (; i != end; ++i) {
1435 for (; i != end; ++i) {
1449 for (; i != end; ++i) {
1472 if (metadataGroup.
id() < 0) {
1476 if (!writeMetadata(metadataGroup.
id())) {
1489 using namespace std;
1500 "Error creating field3d_group_membership group.");
1504 if (!
writeAttribute(group,
"is_field3d_group_membership",
"1")) {
1506 "Failed to write field3d_group_membership attribute.");
1510 std::map<std::string, std::string>::const_iterator iter =
1512 std::map<std::string, std::string>::const_iterator iEnd =
1515 for (; iter != iEnd; ++iter) {
1518 "Failed to write groupMembership string: "+ iter->first);
1550 for (PartitionList::const_iterator i =
m_partitions.begin();
1552 cout <<
"Name: " << (**i).name << endl;
1554 cout <<
" Mapping: " << (**i).mapping->className() << endl;
1556 cout <<
" Mapping: NULL" << endl;
1557 cout <<
" Scalar layers: " << endl;
1558 vector<string> sNames;
1559 (**i).getScalarLayerNames(sNames);
1560 for_each(sNames.begin(), sNames.end(), print<string>(4));
1561 cout <<
" Vector layers: " << endl;
1562 vector<string> vNames;
1563 (**i).getVectorLayerNames(vNames);
1564 for_each(vNames.begin(), vNames.end(), print<string>(4));
1575 struct __stat64 statbuf;
1576 return (_stat64(filename.c_str(), &statbuf) != -1);
1578 struct stat statbuf;
1579 return (stat(filename.c_str(), &statbuf) != -1);
1593 field->className());
1599 field->className())) {
1604 return io->write(layerGroup, field);
1613 std::string className;
1615 if (!
readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1645 std::string className = mapping->className();
1647 if (!
writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1660 return io->write(mappingGroup, mapping);
Namespace for file I/O specifics.
Scoped object - opens an attribute data type on creation and closes it on destruction.
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
boost::intrusive_ptr< FieldMappingIO > Ptr
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
virtual const char * what() const
Contains utility functions and classes for Hdf5 files.
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
Contains the Field3DFile classesOSS sanitized.
boost::intrusive_ptr< Partition > Ptr
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Namespace for Exception objects.
void getIntVectorLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the vector layers in a given partition, but assumes that partition name is the ...
bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
std::map< std::string, std::string > GroupMembershipMap
void clear()
Clear the data structures and close the file.
FIELD3D_API bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
boost::intrusive_ptr< FieldBase > Ptr
static ClassFactory & singleton()
}
bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
boost::recursive_mutex::scoped_lock GlobalLock
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity. ...
boost::intrusive_ptr< FieldRes > Ptr
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
void getIntScalarLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the scalar layers in a given partition, but assumes that partition name is the ...
File::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
std::string intPartitionName(const std::string &partitionName, const std::string &layerName, FieldRes::Ptr field)
Returns a unique partition name given the requested name. This ensures that partitions with matching ...
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
Scoped object - creates a group on creation and closes it on destruction.
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
Scoped object - Opens attribute by name and closes it on destruction.
std::vector< std::string > m_partitionNames
This stores partition names.
boost::intrusive_ptr< FieldMapping > Ptr
Scoped object - Opens attribute by index and closes it on destruction.
FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
std::string name
The name of the layer (always available)
std::string makeIntPartitionName(const std::string &partitionsName, int i) const
Makes an internal partition name given the external partition name. Effectively just tacks on ...
void addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
void printHierarchy() const
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
#define FIELD3D_MINOR_VER
PartitionList m_partitions
Vector of partitions.
bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping)
Writes the mapping to the given hdf5 node. Mappings are assumed to be light-weight enough to be store...
void closeInternal()
Closes the file if open.
virtual ~Field3DFileBase()=0
Pure virtual destructor to ensure we never instantiate this class.
virtual ~Field3DOutputFile()
Scoped object - opens an attribute data space on creation and closes it on destruction.
bool close()
Closes the file. No need to call this unless you specifically want to close the file early...
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
FIELD3D_NAMESPACE_OPEN FIELD3D_API boost::recursive_mutex g_hdf5Mutex
std::vector< LayerInfo > m_layerInfo
This stores layer info.
bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
FieldMetadata< Field3DFileBase > & metadata()
accessor to the m_metadata class
Contains Field, WritableField and ResizableField classes.
Contains the ClassFactory class for registering Field3D classes.
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
boost::intrusive_ptr< FieldIO > Ptr
bool fileExists(const std::string &filename)
checks to see if a file/directory exists or not
#define FIELD3D_MICRO_VER
hid_t m_file
The hdf5 id of the current file. Will be -1 if no file is open.
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
#define FIELD3D_MAJOR_VER
Scoped object - opens a group on creation and closes it on destruction.
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
std::string incrementPartitionName(std::string &pname)
increment the partition or make it zero if there's not an integer suffix
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
std::string parent
The name of the parent partition. We need this in order to open its group.
hid_t id() const
Query the hid_t value.