Commit 4f459f61 authored by mdurant's avatar mdurant

Major update to vizschema database plugin. Fixes several bugs and drastically...

Major update to vizschema database plugin.  Fixes several bugs and drastically restructures the code.  Equivalent to txcorp vizschema repository revision #723.

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@11914 18c085ea-50e0-402c-830e-de6fd14e8384
parent d8b4d787
......@@ -15,9 +15,26 @@ VsMDServerPluginInfo.C
${COMMON_SOURCES}
avtVsFileFormat.C
VsFilter.C
VsH5Attribute.C
VsH5Dataset.C
VsH5File.C
VsH5Group.C
VsH5Object.C
VsH5Reader.C
VsLog.C
VsMDMesh.C
VsMDVariable.C
VsMesh.C
VsRectilinearMesh.C
VsSchema.C
VsStructuredMesh.C
VsUniformMesh.C
VsUnstructuredMesh.C
VsUtils.C
VsVariable.C
VsVariableWithMesh.C
VsRegistry.C
VsRegistryObject.C
)
SET(LIBE_SOURCES
......@@ -25,9 +42,26 @@ VsEnginePluginInfo.C
${COMMON_SOURCES}
avtVsFileFormat.C
VsFilter.C
VsH5Attribute.C
VsH5Dataset.C
VsH5File.C
VsH5Group.C
VsH5Object.C
VsH5Reader.C
VsLog.C
VsMDMesh.C
VsMDVariable.C
VsMesh.C
VsRectilinearMesh.C
VsSchema.C
VsStructuredMesh.C
VsUniformMesh.C
VsUnstructuredMesh.C
VsUtils.C
VsVariable.C
VsVariableWithMesh.C
VsRegistry.C
VsRegistryObject.C
)
INCLUDE_DIRECTORIES(
......
<?xml version="@VERSION@"?>
<Plugin name="Vs" type="database" label="Vs Files" version="@VERSION@" enabled="true" mdspecificcode="false" engspecificcode="false" onlyengine="false" noengine="false" dbtype="STSD" haswriter="false" hasoptions="false">
<Plugin name="Vs" type="database" label="Vs Files" version="@VERSION@" enabled="true" mdspecificcode="false" engspecificcode="false" onlyengine="false" noengine="false" dbtype="STMD" haswriter="false" hasoptions="false">
<Files components="M">
avtVsFileFormat.C
VsFilter.C
VsH5Attribute.C
VsH5Dataset.C
VsH5File.C
VsH5Group.C
VsH5Object.C
VsH5Reader.C
VsLog.C
VsMDMesh.C
VsMDVariable.C
VsMesh.C
VsRectilinearMesh.C
VsSchema.C
VsStructuredMesh.C
VsUniformMesh.C
VsUnstructuredMesh.C
VsUtils.C
VsVariable.C
VsVariableWithMesh.C
VsRegistry.C
VsRegistryObject.C
</Files>
<Files components="E">
avtVsFileFormat.C
VsFilter.C
VsH5Attribute.C
VsH5Dataset.C
VsH5File.C
VsH5Group.C
VsH5Object.C
VsH5Reader.C
VsLog.C
VsMDMesh.C
VsMDVariable.C
VsMesh.C
VsRectilinearMesh.C
VsSchema.C
VsStructuredMesh.C
VsUniformMesh.C
VsUnstructuredMesh.C
VsUtils.C
VsVariable.C
VsVariableWithMesh.C
VsRegistry.C
VsRegistryObject.C
</Files>
<CXXFLAGS>
${HDF5_INCLUDE_DIR}
</CXXFLAGS>
......
......@@ -20,47 +20,40 @@
#include <VsUtils.h>
#include <hdf5.h>
#include <stdlib.h>
#include "VsLog.h"
#include "VsH5File.h"
#include "VsH5Object.h"
#include "VsH5Dataset.h"
#include "VsH5Attribute.h"
#include "VsRegistry.h"
struct RECURSION_DATA {
VsH5Meta* meta;
std::ostream* debugStream;
int depth;
std::string path;
VsRegistry* registry;
VsH5Object* parent;
};
VsFilter::VsFilter(std::ostream& dbgstrm) : debugStrmRef(dbgstrm) {
}
VsFilter::VsFilter(hid_t fId, std::ostream& dbgstrm) :
debugStrmRef(dbgstrm), fileId(fId) {
makeH5Meta();
}
void VsFilter::makeH5Meta() {
h5meta.ptr = 0;
// Create the list of vs datasets and groups
// corresponding to variables, variables with mesh and meshes.
VsH5File* VsFilter::readFile(VsRegistry* registry, std::string fileName) {
hid_t fileId = H5Fopen(fileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
if (fileId < 0) {
VsLog::errorLog() << "VsH5File::readFile(): HDF5 error opening the file '"
<< fileName << "'." << std::endl;
return NULL;
}
VsH5File* file = new VsH5File(registry, fileName, fileId);
RECURSION_DATA data;
data.debugStream = &debugStrmRef;
data.meta = &h5meta;
data.depth = 0;
data.path = "";
data.registry = registry;
data.parent = NULL;
H5Literate(fileId, H5_INDEX_NAME, H5_ITER_INC, 0, visitLinks, &data);
return file;
}
herr_t VsFilter::visitLinks(hid_t locId, const char* name,
const H5L_info_t *linfo, void* opdata) {
RECURSION_DATA* data = static_cast< RECURSION_DATA* >(opdata);
VsH5Meta* metaPtr = data->meta;
std::ostream& osRef = *(data->debugStream);
// for(int i=0;i<data->depth; ++i ) std::cerr << " ";
// std::cerr << "Link " << name << " " << locId << std::endl;
//the fully qualified name of this object
std::string fullName = makeCanonicalName(data->path, name);//data->path + "/" + name;
VsLog::debugLog() <<"VsFilter::visitLinks() - looking at object " <<name <<std::endl;
switch (linfo->type) {
case H5L_TYPE_HARD: {
......@@ -68,7 +61,9 @@ herr_t VsFilter::visitLinks(hid_t locId, const char* name,
/* Stat the object */
if(H5Oget_info_by_name(locId, name, &objinfo, H5P_DEFAULT) < 0) {
// DO TO - THROW AN ERROR
VsLog::errorLog() <<"VsFilter::visitLinks() - unable to open object with name " <<name <<std::endl;
VsLog::errorLog() <<"VsFilter::visitLinks() - this object and all children will be dropped." <<std::endl;
return 0;
}
switch(objinfo.type)
......@@ -81,325 +76,181 @@ herr_t VsFilter::visitLinks(hid_t locId, const char* name,
break;
default:
osRef << "VsFilter::visitLinks: node '" << name <<
VsLog::debugLog() << "VsFilter::visitLinks: node '" << name <<
"' has an unknown type " << objinfo.type << std::endl;
break;
}
break;
}
break;
//end of case H5L_TYPE_HARD
case H5L_TYPE_EXTERNAL: {
char *targbuf = (char*) malloc( linfo->u.val_size );
if(H5Lget_val(locId, name, targbuf, linfo->u.val_size,
H5P_DEFAULT) < 0) {
// DO TO - THROW AN ERROR
} else {
const char *filename;
const char *targname;
if(H5Lunpack_elink_val(targbuf, linfo->u.val_size, 0,
&filename, &targname) < 0) {
// DO TO - THROW AN ERROR
} else {
osRef << "VsFilter::visitLinks: node '" << name << "' is an external link." << std::endl;
if (H5Lget_val(locId, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) {
VsLog::errorLog() <<"VsFilter::visitLinks() - unable to open external link with name " <<targbuf <<std::endl;
VsLog::errorLog() <<"VsFilter::visitLinks() - this object and all children will be dropped." <<std::endl;
return 0;
}
const char *filename;
const char *targname;
if (H5Lunpack_elink_val(targbuf, linfo->u.val_size, 0, &filename, &targname) < 0) {
VsLog::errorLog() <<"VsFilter::visitLinks() - unable to open external file with name " <<filename <<std::endl;
VsLog::errorLog() <<"VsFilter::visitLinks() - this object and all children will be dropped." <<std::endl;
return 0;
}
VsLog::debugLog() << "VsFilter::visitLinks(): node '" << name << "' is an external link." << std::endl;
VsLog::debugLog() << "VsFilter::visitLinks(): node '" << targname << "' is an external target group." << std::endl;
free(targbuf);
targbuf = NULL;
// Get info of the linked object.
H5O_info_t objinfo;
#ifndef H5_USE_16_API
hid_t obj_id = H5Oopen(locId, name, H5P_DEFAULT);
#else
hid_t obj_id = H5Oopen(locId, name);
#endif
if (obj_id < 0) {
VsLog::errorLog() <<"VsFilter::visitLinks() - unable to get id for external object " <<name <<std::endl;
VsLog::errorLog() <<"VsFilter::visitLinks() - this object and all children will be dropped." <<std::endl;
return 0;
}
osRef << "VsFilter::visitLinks: node '" << targname << "' the is an external target group." << std::endl;
//Test-open the linked object
if (H5Oget_info (obj_id, &objinfo) < 0) {
VsLog::errorLog() <<"VsFilter::visitLinks() - unable to open external object " <<name <<std::endl;
VsLog::errorLog() <<"VsFilter::visitLinks() - this object and all children will be dropped." <<std::endl;
return 0;
}
//Close the linked object to release hdf5 id
H5Oclose( obj_id );
free(targbuf);
//Finally, decide what to do depending on what type of object this is
switch(objinfo.type)
{
case H5O_TYPE_GROUP:
return visitGroup( locId, name, opdata );
break;
case H5O_TYPE_DATASET:
return visitDataset( locId, name, opdata );
break;
// Open the linked object.
H5O_info_t objinfo;
hid_t obj_id = H5Oopen(locId, name
#ifndef H5_USE_16_API
, H5P_DEFAULT
#endif
);
if ( obj_id < 0 ) {
// DO TO - THROW AN ERROR
}
else if ( H5Oget_info ( obj_id, &objinfo ) < 0 ) {
// DO TO - THROW AN ERROR
}
else {
H5Oclose( obj_id );
switch(objinfo.type)
{
case H5O_TYPE_GROUP:
return visitGroup( locId, name, opdata );
break;
case H5O_TYPE_DATASET:
return visitDataset( locId, name, opdata );
break;
default:
osRef << "VsFilter::visitLinks: node '" << name <<
"' has an unknown type " << objinfo.type << std::endl;
break;
}
}
}
default:
VsLog::debugLog() << "VsFilter::visitLinks: node '" << name <<
"' has an unknown type " << objinfo.type << std::endl;
break;
}
}
break;
//END OF CASE H5L_TYPE_EXTERNAL
default:
osRef << "VsFilter::visitLinks: node '" << name <<
VsLog::debugLog() << "VsFilter::visitLinks: node '" << name <<
"' has an unknown object type " << linfo->type << std::endl;
break;
}
// for( int i=0;i<data->depth; ++i ) std::cerr << " ";
// std::cerr << "Out Link " << name << std::endl;
return 0;
}
herr_t VsFilter::visitGroup(hid_t locId, const char* name, void* opdata) {
RECURSION_DATA* data = static_cast< RECURSION_DATA* >(opdata);
VsH5Meta* metaPtr = data->meta;
std::ostream& osRef = *(data->debugStream);
//the fully qualified name of this object
std::string fullName = makeCanonicalName(data->path, name);//data->path + "/" + name;
// for( int i=0;i<data->depth; ++i ) std::cerr << " ";
// std::cerr << "Group " << name << " " << locId << std::endl;
osRef << "VsFilter::visitGroup: node '" << name
<< "' is a group." << std::endl;
VsH5Group* parent = static_cast< VsH5Group*> (data->parent);
VsRegistry* registry = data->registry;
VsLog::debugLog() << "VsFilter::visitGroup: node '" << name
<< "' is a group." << std::endl;
hid_t groupId = H5Gopen(locId, name, H5P_DEFAULT);
if ( groupId < 0 ) {
// DO TO - THROW AN ERROR
}
osRef << "VsFilter::visitGroup: node '" << name <<
"' opened." << std::endl;
// Metadata for this group
VsGMeta* gm = new VsGMeta();
gm->name = name;
gm->depth = data->depth + 1;
gm->path = data->path;
gm->iid = groupId;
// Collect attributes of the group
std::pair<VsIMeta*, std::ostream*> gpd(gm, &osRef);
H5Aiterate(groupId, H5_INDEX_NAME, H5_ITER_INC, NULL, visitAttrib, &gpd);
// Check is gm's isMesh is true and add to meshes
// Check if the group is a mesh and register. Move the ptr to the mesh
if (gm->isMesh) {
osRef << "VsFilter::visitGroup: node '" << name << "' is a mesh."
<< std::endl;
std::pair<std::string, VsGMeta*> el(fullName, gm);
metaPtr->gMeshes.insert(el);
metaPtr->ptr = gm;
//If unable to get a handle to the hdf5 object, we just drop the object
//But return 0 to continue iterating over objects
if (groupId < 0) {
VsLog::errorLog() <<"VsFilter::visitGroup() - Unable to open group with name " <<name <<std::endl;
VsLog::errorLog() <<"VsFilter::visitGroup() - This object and all children will be dropped." <<std::endl;
return 0;
}
else if (gm->isVsVars) {
osRef << "VsFilter::visitGroup: node '" << name << "' is vsVars." <<
std::endl;
std::pair<std::string, VsGMeta*> el(fullName, gm);
metaPtr->vsVars.insert(el);
metaPtr->ptr = gm;
}
else {
// If group is not a mesh - delete it - needs to be changed to work with groups
// which are variables
osRef << "VsFilter::visitGroup: node '" << name << "' is not a mesh."
<< " Deleting." << std::endl;
delete gm;
gm = 0;
// When deleting the meta data the group is closed so reopen.
// THIS PRACTICE OF HAVING ONE FUNCTION OPEN A GROUP BUT THEN
// HAVE A STRUCTURE STORING IT AND THEN CLOSE IT ON
// DESTRUCTION IS NOT A GOOD PRACTIC
groupId = H5Gopen(locId, name, H5P_DEFAULT);
}
// recurse to examine child groups
VsH5Group* newGroup = new VsH5Group(registry, parent, name, groupId);
RECURSION_DATA nextLevelData;
nextLevelData.debugStream = data->debugStream;
nextLevelData.depth = data->depth + 1;
nextLevelData.path = fullName;
nextLevelData.meta = data->meta;
osRef <<"VsFilter::visitGroup(...): Recursing with path " <<fullName <<" and depth " <<nextLevelData.depth <<"." <<std::endl;
nextLevelData.registry = registry;
nextLevelData.parent = newGroup;
// Recurse over all attributes of the group
VsLog::debugLog() <<"VsFilter::visitGroup(): Recursing on attributes of group " <<newGroup->getFullName() <<std::endl;
H5Aiterate(groupId, H5_INDEX_NAME, H5_ITER_INC, NULL, visitAttrib, &nextLevelData);
// Recurse to examine child groups
VsLog::debugLog() <<"VsFilter::visitGroup(): Recursing on children of group " <<newGroup->getFullName() <<std::endl;
H5Literate(groupId, H5_INDEX_NAME, H5_ITER_INC, NULL, visitLinks, &nextLevelData);
// Just a group so close it.
if( gm == 0 )
H5Gclose( groupId );
osRef <<"VsFilter::visitGroup: Returned from recursion" <<std::endl;
// Not needed because the newly declared VsH5Group takes ownership of the id
// And will do the H5GClose when it is deleted
// H5Gclose(groupId);
VsLog::debugLog() <<"VsFilter::visitGroup(): Returning." <<std::endl;
return 0;
}
herr_t VsFilter::visitDataset(hid_t locId, const char* name, void* opdata) {
RECURSION_DATA* data = static_cast< RECURSION_DATA* >(opdata);
VsH5Meta* metaPtr = data->meta;
std::ostream& osRef = *(data->debugStream);
VsH5Group* parent = static_cast< VsH5Group*>(data->parent);
VsRegistry* registry = data->registry;
//the fully qualified name of this object
std::string fullName = makeCanonicalName(data->path, name);//data->path + "/" + name;
// for( int i=0;i<data->depth; ++i ) std::cerr << " ";
// std::cerr << "Group " << name << " " << locId << std::endl;
osRef << "VsFilter::visitDataset: node '" << name <<
"' is a dataset." << std::endl;
VsLog::debugLog() << "VsFilter::visitDataset: node '" << name
<<"' is a dataset." << std::endl;
hid_t datasetId = H5Dopen(locId, name, H5P_DEFAULT);
if ( datasetId < 0 ) {
// DO TO - THROW AN ERROR
VsH5Dataset* newDataset = new VsH5Dataset(registry, parent, name, datasetId);
//If unable to get a handle to the hdf5 object, we just drop the object
//But return 0 to continue iterating over objects
if (datasetId < 0) {
VsLog::errorLog() <<"VsFilter::visitDataset() - Unable to open dataset with name " <<name <<std::endl;
VsLog::errorLog() <<"VsFilter::visitDataset() - This object and all children will be dropped." <<std::endl;
return 0;
}
osRef << "VsFilter::visitDataset: node '" << name <<
"' opened." << std::endl;
// Metadata for this dataset
VsDMeta* vm = new VsDMeta();
std::string sname = name;
vm->name = sname;
vm->path = data->path;
vm->depth = data->depth + 1;
vm->type = H5Tget_native_type(H5Dget_type(datasetId), H5T_DIR_DEFAULT);
vm->iid = datasetId;
getDims(datasetId, true, vm->dims);
// Collect attributes of this dataset
std::pair<VsIMeta*, std::ostream*> gpd(vm, &osRef);
H5Aiterate(datasetId, H5_INDEX_NAME, H5_ITER_INC, NULL, visitAttrib,
&gpd);
//all datasets get registered in a general list
std::pair<std::string, VsDMeta*> el(fullName, vm);
metaPtr->datasets.insert(el);
// Test isVariable etc and add register
if (vm->isVariable) {
std::pair<std::string, VsDMeta*> el2(fullName, vm);
metaPtr->vars.insert(el2);
osRef <<"VsFilter::visitDataset: node '" <<name <<
"' is a Variable." <<std::endl;
}
else if (vm->isVariableWithMesh) {
std::pair<std::string, VsDMeta*> el2(fullName, vm);
metaPtr->varsWithMesh.insert(el2);
osRef <<"VsFilter::visitDataset: node '" <<name <<
"' is a variable with mesh." <<std::endl;
}
else if (vm->isMesh) {
std::pair<std::string, VsDMeta*> el2(fullName, vm);
metaPtr->dMeshes.insert(el2);
osRef <<"VsFilter::visitDataset: node '" <<name <<
"' is a dataset mesh." <<std::endl;
} else {
//This dataset is neither a var, a mesh, or a varWithMesh
//If it exists inside a Mesh group, then it might still be used
// (e.g. as a vsPoints dataset)
//However, if it's not in a mesh group, it's not used
// so it gets deleted
if (metaPtr->ptr) {
//we have a parent - is it a Mesh group?
VsGMeta* parent = static_cast<VsGMeta*>(metaPtr->ptr);
if (parent && (parent->isMesh)) {
parent->datasets.push_back(vm);
} else {
osRef <<"VsFilter::visitDataset: node '" <<name <<"' is not recognized as a Vs object. Remembering for later." <<std::endl;
metaPtr->orphanDatasets.push_back(vm);
// delete vm;
}
} else {
osRef <<"VsFilter::visitDataset: node '" <<name <<"' is not recognized as a Vs object. Remembering for later." <<std::endl;
metaPtr->orphanDatasets.push_back(vm);
// delete vm;
}
}
osRef <<"VsFilter::visitDataset: Returning from recursion" <<std::endl;
RECURSION_DATA nextLevelData;
nextLevelData.registry = registry;
nextLevelData.parent = newDataset;
// Recurse over attributes
H5Aiterate(datasetId, H5_INDEX_NAME, H5_ITER_INC, NULL, visitAttrib, &nextLevelData);
VsLog::debugLog() <<"VsFilter::visitDataset: Returning." <<std::endl;
return 0;
}
herr_t VsFilter::visitAttrib(hid_t dId, const char* name,
const H5A_info_t* ai, void* opdata) {
RECURSION_DATA* data = static_cast< RECURSION_DATA* >(opdata);
VsH5Object* parent = data->parent;
VsRegistry* registry = data->registry;
VsLog::debugLog() << "VsFilter::visitAttrib(...): getting attribute '" <<
name << "'." << std::endl;
if (!parent) {
VsLog::errorLog() <<"VsFilter::visitAttrib(): Parent is NULL?" <<std::endl;
return 0;
}
std::pair<VsIMeta*, std::ostream*>* gpdPtr =
static_cast<std::pair<VsIMeta*, std::ostream*>*>(opdata);
// VsIMeta* iMetaPtr = static_cast<VsIMeta*>(opdata);
VsIMeta* iMetaPtr = gpdPtr->first;
std::ostream& osRef = *gpdPtr->second;
osRef << "VsFilter::visitAttrib(...): getting attribute '" <<
name << "'." << std::endl;
//TODO - actually load & cache string attribute values here
hid_t attId = H5Aopen_name(dId, name);
// Metadata for this attribute
VsAMeta* am = new VsAMeta();
am->type = H5Tget_native_type(H5Aget_type(attId), H5T_DIR_DEFAULT);
am->aid = attId;
am->name = name;
// 0 shows that it is attribute
getDims(am->aid, false, am->dims);
// add attrib metadata
am->depth = iMetaPtr->depth+1;
iMetaPtr->attribs.push_back(am);
// check for type attribute
std::string aname = name;
if (aname.compare(VsSchema::typeAtt) == 0) {
std::string attValue;
herr_t err = getAttributeHelper(attId, &attValue, 0, 0);
if (err == 0) {
osRef << "VsFilter::visitAttrib(...): attribute '" << name <<
"' is '" << attValue << "'." << std::endl;
// See if this dataset or group is a mesh