osgDB Wrapper Associates Revision Tagging

This commit is contained in:
Julien Valentin 2016-06-14 11:43:45 +01:00 committed by Robert Osfield
parent dcac0c1611
commit 2ac8379cfc
6 changed files with 186 additions and 65 deletions

View File

@ -50,12 +50,21 @@ struct FinishedObjectReadCallback : public osg::Referenced
virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) = 0; virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) = 0;
}; };
struct OSGDB_EXPORT ObjectWrapperAssociate
{
ObjectWrapperAssociate(std::string name):_firstVersion(0),_lastVersion(INT_MAX),_name(name){}
int _firstVersion;
int _lastVersion;
std::string _name;
};
class OSGDB_EXPORT ObjectWrapper : public osg::Referenced class OSGDB_EXPORT ObjectWrapper : public osg::Referenced
{ {
public: public:
typedef std::vector< BaseSerializer::Type > TypeList; typedef std::vector< BaseSerializer::Type > TypeList;
typedef std::vector< osg::ref_ptr<BaseSerializer> > SerializerList; typedef std::vector< osg::ref_ptr<BaseSerializer> > SerializerList;
typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList; typedef std::vector< osg::ref_ptr<FinishedObjectReadCallback> > FinishedObjectReadCallbackList;
typedef std::list<ObjectWrapperAssociate> RevisionAssociateList;
typedef osg::Object* CreateInstanceFunc(); typedef osg::Object* CreateInstanceFunc();
ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name, ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
@ -69,7 +78,8 @@ public:
osg::Object* createInstance() const { return _createInstanceFunc(); } osg::Object* createInstance() const { return _createInstanceFunc(); }
const std::string& getDomain() const { return _domain; } const std::string& getDomain() const { return _domain; }
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
const StringList& getAssociates() const { return _associates; }
const RevisionAssociateList& getAssociates() const { return _associates; }
SerializerList& getSerializerList() { return _serializers; } SerializerList& getSerializerList() { return _serializers; }
const SerializerList& getSerializerList() const { return _serializers; } const SerializerList& getSerializerList() const { return _serializers; }
@ -79,6 +89,10 @@ public:
void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED ); void addSerializer( BaseSerializer* s, BaseSerializer::Type t=BaseSerializer::RW_UNDEFINED );
void markSerializerAsRemoved( const std::string& name ); void markSerializerAsRemoved( const std::string& name );
void markAssociateAsRemoved(const std::string& name);
void markAssociateAsAdded(const std::string& name);
BaseSerializer* getLastSerializer() { return _serializers.empty() ? 0 : _serializers.back().get(); } BaseSerializer* getLastSerializer() { return _serializers.empty() ? 0 : _serializers.back().get(); }
BaseSerializer* getSerializer( const std::string& name ); BaseSerializer* getSerializer( const std::string& name );
BaseSerializer* getSerializer( const std::string& name, BaseSerializer::Type& type); BaseSerializer* getSerializer( const std::string& name, BaseSerializer::Type& type);
@ -99,6 +113,8 @@ public:
MethodObjectMap& getMethodObjectMap() { return _methodObjectMap; } MethodObjectMap& getMethodObjectMap() { return _methodObjectMap; }
const MethodObjectMap& getMethodObjectMap() const { return _methodObjectMap; } const MethodObjectMap& getMethodObjectMap() const { return _methodObjectMap; }
void setupAssociatesRevisionsInheritanceIfRequired();
protected: protected:
ObjectWrapper() : _version(0) {} ObjectWrapper() : _version(0) {}
virtual ~ObjectWrapper() {} virtual ~ObjectWrapper() {}
@ -106,13 +122,16 @@ protected:
CreateInstanceFunc* _createInstanceFunc; CreateInstanceFunc* _createInstanceFunc;
std::string _domain; std::string _domain;
std::string _name; std::string _name;
StringList _associates; RevisionAssociateList _associates;
SerializerList _serializers; SerializerList _serializers;
SerializerList _backupSerializers; SerializerList _backupSerializers;
TypeList _typeList; TypeList _typeList;
FinishedObjectReadCallbackList _finishedObjectReadCallbacks; FinishedObjectReadCallbackList _finishedObjectReadCallbacks;
MethodObjectMap _methodObjectMap; MethodObjectMap _methodObjectMap;
int _version; // Last updated version of the wrapper int _version; // Last updated version of the wrapper
//simulate associate revisions inheritance
bool _isAssociatesRevisionsInheritanceDone;
static void splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator=' ' );
}; };
struct UpdateWrapperVersionProxy struct UpdateWrapperVersionProxy

View File

@ -1880,6 +1880,12 @@ protected:
#define UPDATE_TO_VERSION_SCOPED(VER) \ #define UPDATE_TO_VERSION_SCOPED(VER) \
osgDB::UpdateWrapperVersionProxy uwvp(wrapper, (VER)); osgDB::UpdateWrapperVersionProxy uwvp(wrapper, (VER));
#define ADDED_ASSOCIATE(STR) \
wrapper->markAssociateAsAdded( STR );
#define REMOVED_ASSOCIATE(STR) \
wrapper->markAssociateAsRemoved( STR );
#define REMOVE_SERIALIZER(PROP) \ #define REMOVE_SERIALIZER(PROP) \
wrapper->markSerializerAsRemoved( #PROP ); wrapper->markSerializerAsRemoved( #PROP );

View File

@ -509,12 +509,12 @@ bool ClassInterface::getSupportedProperties(const osg::Object* object, PropertyM
if (searchAssociates) if (searchAssociates)
{ {
const osgDB::StringList& associates = ow->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
for(osgDB::StringList::const_iterator aitr = associates.begin(); for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
aitr != associates.end(); aitr != associates.end();
++aitr) ++aitr)
{ {
osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); osgDB::ObjectWrapper* associate_wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
if (associate_wrapper) if (associate_wrapper)
{ {
const osgDB::ObjectWrapper::SerializerList& associate_serializers = associate_wrapper->getSerializerList(); const osgDB::ObjectWrapper::SerializerList& associate_serializers = associate_wrapper->getSerializerList();
@ -560,12 +560,12 @@ bool ClassInterface::isObjectOfType(const osg::Object* object, const std::string
return false; return false;
} }
const osgDB::StringList& associates = ow->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
for(osgDB::StringList::const_iterator aitr = associates.begin(); for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
aitr != associates.end(); aitr != associates.end();
++aitr) ++aitr)
{ {
if ((*aitr)==compoundClassName) return true; if ((aitr->_name)==compoundClassName) return true;
} }
return false; return false;
} }
@ -584,12 +584,12 @@ bool ClassInterface::run(void* objectPtr, const std::string& compoundClassName,
if (mo->run(objectPtr, inputParameters, outputParameters)) return true; if (mo->run(objectPtr, inputParameters, outputParameters)) return true;
} }
const osgDB::StringList& associates = ow->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
for(osgDB::StringList::const_iterator aitr = associates.begin(); for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
aitr != associates.end(); aitr != associates.end();
++aitr) ++aitr)
{ {
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
if (aow) if (aow)
{ {
const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap(); const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap();
@ -620,12 +620,12 @@ bool ClassInterface::hasMethod(const std::string& compoundClassName, const std::
ObjectWrapper::MethodObjectMap::const_iterator oitr = ow_methodObjectMap.find(methodName); ObjectWrapper::MethodObjectMap::const_iterator oitr = ow_methodObjectMap.find(methodName);
if (oitr!=ow_methodObjectMap.end()) return true; if (oitr!=ow_methodObjectMap.end()) return true;
const osgDB::StringList& associates = ow->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = ow->getAssociates();
for(osgDB::StringList::const_iterator aitr = associates.begin(); for(ObjectWrapper::RevisionAssociateList::const_iterator aitr = associates.begin();
aitr != associates.end(); aitr != associates.end();
++aitr) ++aitr)
{ {
osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(*aitr); osgDB::ObjectWrapper* aow = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper(aitr->_name);
if (aow) if (aow)
{ {
const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap(); const ObjectWrapper::MethodObjectMap& methodObjectMap = aow->getMethodObjectMap();

View File

@ -905,26 +905,36 @@ osg::ref_ptr<osg::Object> InputStream::readObjectFields( const std::string& clas
<< className << std::endl; << className << std::endl;
return NULL; return NULL;
} }
int inputVersion = getFileVersion(wrapper->getDomain());
osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->createInstance(); osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->createInstance();
_identifierMap[id] = obj; _identifierMap[id] = obj;
if ( obj.valid() ) if ( obj.valid() )
{ {
const StringList& associates = wrapper->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates();
for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
{ {
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr); if ( itr->_firstVersion <= inputVersion &&
if ( !assocWrapper ) inputVersion <= itr->_lastVersion)
{ {
OSG_WARN << "InputStream::readObject(): Unsupported associated class " ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(itr->_name);
<< *itr << std::endl; if ( !assocWrapper )
continue; {
} OSG_WARN << "InputStream::readObject(): Unsupported associated class "
_fields.push_back( assocWrapper->getName() ); << itr->_name << std::endl;
assocWrapper->read( *this, *obj ); continue;
if ( getException() ) return NULL; }
_fields.push_back( assocWrapper->getName() );
assocWrapper->read( *this, *obj );
if ( getException() ) return NULL;
_fields.pop_back(); _fields.pop_back();
}
else
{
/* OSG_INFO << "InputStream::readObject():"<<className<<" Ignoring associated class due to version mismatch"
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for version "<<inputVersion<< std::endl;*/
}
} }
} }
return obj; return obj;

View File

@ -80,6 +80,24 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
} }
} }
void ObjectWrapper::splitAssociates( const std::string& src, ObjectWrapper::RevisionAssociateList& list, char separator )
{
std::string::size_type start = src.find_first_not_of(separator);
while ( start!=std::string::npos )
{
std::string::size_type end = src.find_first_of(separator, start);
if ( end!=std::string::npos )
{
list.push_back( ObjectWrapperAssociate(std::string(src, start, end-start)) );
start = src.find_first_not_of(separator, end);
}
else
{
list.push_back( ObjectWrapperAssociate(std::string(src, start, src.size()-start)) );
start = end;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ObjectWrapper // ObjectWrapper
@ -87,19 +105,72 @@ void osgDB::split( const std::string& src, StringList& list, char separator )
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name, ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& name,
const std::string& associates ) const std::string& associates )
: osg::Referenced(), : osg::Referenced(),
_createInstanceFunc(createInstanceFunc), _name(name), _version(0) _createInstanceFunc(createInstanceFunc), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
{ {
split( associates, _associates ); splitAssociates( associates, _associates );
} }
ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name, ObjectWrapper::ObjectWrapper( CreateInstanceFunc* createInstanceFunc, const std::string& domain, const std::string& name,
const std::string& associates ) const std::string& associates )
: osg::Referenced(), : osg::Referenced(),
_createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0) _createInstanceFunc(createInstanceFunc), _domain(domain), _name(name), _version(0),_isAssociatesRevisionsInheritanceDone(false)
{ {
split( associates, _associates ); splitAssociates( associates, _associates );
} }
void ObjectWrapper::setupAssociatesRevisionsInheritanceIfRequired()
{
if(!_isAssociatesRevisionsInheritanceDone)
{
///for each associate wrapper
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(itr->_name);
if ( assocWrapper && assocWrapper != this )
{
///crawl association revisions in associates
for ( ObjectWrapper::RevisionAssociateList::const_iterator itr2=assocWrapper->getAssociates().begin(); itr2!=assocWrapper->getAssociates().end(); ++itr2 )
{
for ( ObjectWrapper::RevisionAssociateList::iterator itr3=_associates.begin(); itr3!=_associates.end(); ++itr3 )
{
///they share associates
if(itr3->_name==itr2->_name)
{
itr3->_firstVersion=itr3->_firstVersion>itr2->_firstVersion? itr3->_firstVersion:itr2->_firstVersion;
itr3->_lastVersion=itr3->_lastVersion<itr2->_lastVersion? itr3->_lastVersion:itr2->_lastVersion;
}
}
}
}
}
_isAssociatesRevisionsInheritanceDone=true;
}
}
void ObjectWrapper::markAssociateAsAdded(const std::string& name)
{
for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{
if(itr->_name==name)
{
itr->_firstVersion=_version;
return;
}
}
OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateAddedAtVersion: Associate class "<<name<<" not defined for wrapper "<<_name<<std::endl;
}
void ObjectWrapper::markAssociateAsRemoved(const std::string& name)
{
for ( ObjectWrapper::RevisionAssociateList:: iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{
if(itr->_name==name)
{
itr->_lastVersion = _version-1;
return;
}
}
OSG_NOTIFY(osg::WARN)<<"ObjectWrapper::associateRemovedAtVersion: Associate class "<<name<<" not defined for wrapper "<<_name<<std::endl;
}
void ObjectWrapper::addSerializer( BaseSerializer* s, BaseSerializer::Type t ) void ObjectWrapper::addSerializer( BaseSerializer* s, BaseSerializer::Type t )
{ {
s->_firstVersion = _version; s->_firstVersion = _version;
@ -127,9 +198,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name )
return itr->get(); return itr->get();
} }
for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{ {
const std::string& assocName = *itr; const std::string& assocName = itr->_name;
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
if ( !assocWrapper ) if ( !assocWrapper )
{ {
@ -163,9 +234,9 @@ BaseSerializer* ObjectWrapper::getSerializer( const std::string& name, BaseSeria
} }
} }
for ( StringList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr ) for ( RevisionAssociateList::const_iterator itr=_associates.begin(); itr!=_associates.end(); ++itr )
{ {
const std::string& assocName = *itr; const std::string& assocName = itr->_name;
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
if ( !assocWrapper ) if ( !assocWrapper )
{ {
@ -681,17 +752,22 @@ ObjectWrapper* ObjectWrapperManager::findWrapper( const std::string& name )
{ {
std::string libName = std::string( name, 0, posDoubleColon ); std::string libName = std::string( name, 0, posDoubleColon );
ObjectWrapper* found=0;
std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(libName); std::string nodeKitLib = osgDB::Registry::instance()->createLibraryNameForNodeKit(libName);
if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED ) if ( osgDB::Registry::instance()->loadLibrary(nodeKitLib)==osgDB::Registry::LOADED )
return findWrapper(name); found= findWrapper(name);
std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("serializers_")+libName); std::string pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(std::string("serializers_")+libName);
if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED )
return findWrapper(name); found= findWrapper(name);
pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(libName); pluginLib = osgDB::Registry::instance()->createLibraryNameForExtension(libName);
if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED ) if ( osgDB::Registry::instance()->loadLibrary(pluginLib)==osgDB::Registry::LOADED )
return findWrapper(name); found= findWrapper(name);
if (found) found->setupAssociatesRevisionsInheritanceIfRequired();
return found;
} }
return NULL; return NULL;
} }

View File

@ -645,44 +645,54 @@ void OutputStream::writeObjectFields( const osg::Object* obj, const std::string&
<< name << std::endl; << name << std::endl;
return; return;
} }
int outputVersion = getFileVersion(wrapper->getDomain());
const StringList& associates = wrapper->getAssociates(); const ObjectWrapper::RevisionAssociateList& associates = wrapper->getAssociates();
for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) for ( ObjectWrapper::RevisionAssociateList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
{ {
const std::string& assocName = *itr; if ( itr->_firstVersion <= outputVersion &&
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); outputVersion <= itr->_lastVersion)
if ( !assocWrapper )
{ {
OSG_WARN << "OutputStream::writeObject(): Unsupported associated class " const std::string& assocName = itr->_name;
<< assocName << std::endl; ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
continue; if ( !assocWrapper )
}
else if ( _useSchemaData )
{
if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
{ {
StringList properties; OSG_WARN << "OutputStream::writeObject(): Unsupported associated class "
ObjectWrapper::TypeList types; << assocName << std::endl;
assocWrapper->writeSchema( properties, types ); continue;
}
unsigned int size = osg::minimum( properties.size(), types.size() ); else if ( _useSchemaData )
if ( size>0 ) {
if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
{ {
std::stringstream propertiesStream; StringList properties;
for ( unsigned int i=0; i<size; ++i ) ObjectWrapper::TypeList types;
assocWrapper->writeSchema( properties, types );
unsigned int size = osg::minimum( properties.size(), types.size() );
if ( size>0 )
{ {
propertiesStream << properties[i] << ":" << types[i] << " "; std::stringstream propertiesStream;
for ( unsigned int i=0; i<size; ++i )
{
propertiesStream << properties[i] << ":" << types[i] << " ";
}
_inbuiltSchemaMap[assocName] = propertiesStream.str();
} }
_inbuiltSchemaMap[assocName] = propertiesStream.str();
} }
} }
_fields.push_back( assocWrapper->getName() );
assocWrapper->write( *this, *obj );
if ( getException() ) return;
_fields.pop_back();
}
else
{
/*OSG_INFO << "OutputStream::writeObject():"<<name<<" Ignoring associated class due to version mismatch "
<< itr->_name<<"["<<itr->_firstVersion <<","<<itr->_lastVersion <<"]for output version "<<outputVersion<< std::endl;*/
} }
_fields.push_back( assocWrapper->getName() );
assocWrapper->write( *this, *obj );
if ( getException() ) return;
_fields.pop_back();
} }
} }