LCOV - code coverage report
Current view: top level - eq/fabric - object.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 94 181 51.9 %
Date: 2016-07-30 05:04:55 Functions: 25 32 78.1 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "object.h"
      20             : 
      21             : #include "task.h"
      22             : 
      23             : #include <co/iCommand.h>
      24             : #include <co/dataIStream.h>
      25             : #include <co/dataOStream.h>
      26             : #include <co/types.h>
      27             : 
      28             : namespace eq
      29             : {
      30             : namespace fabric
      31             : {
      32             : namespace detail
      33             : {
      34       44028 : struct BackupData
      35             : {
      36             :     /** The application-defined name of the object. */
      37             :     std::string name;
      38             : 
      39             :     /** The user data parameters if no _userData object is set. */
      40             :     co::ObjectVersion userData;
      41             : };
      42             : 
      43        9764 : class Object
      44             : {
      45             : public:
      46       11032 :     Object()
      47             :         : userData( 0 )
      48             :         , tasks( TASK_NONE )
      49       11032 :         , serial( CO_INSTANCE_INVALID )
      50       11032 :     {}
      51             : 
      52        1174 :     Object( const Object& from )
      53             :         : data( from.data )
      54             :         , backup()
      55             :         , userData( from.userData )
      56             :         , tasks( from.tasks )
      57        1174 :         , serial( from.serial )
      58        1174 :     {}
      59             : 
      60             :     // cppcheck-suppress operatorEqVarError
      61           0 :     Object& operator = ( const Object& from )
      62             :     {
      63           0 :         if( this == &from )
      64           0 :             return *this;
      65             : 
      66           0 :         data = from.data;
      67           0 :         userData = from.userData;
      68           0 :         tasks = from.tasks;
      69           0 :         serial = from.serial;
      70           0 :         return *this;
      71             :     }
      72             : 
      73             :     BackupData data; //!< Active data
      74             :     BackupData backup; //!< Backed up version (from .eqc)
      75             : 
      76             :     co::Object* userData; //!< User data object
      77             :     uint32_t tasks; //!< Worst-case set of tasks
      78             :     uint32_t serial; //!< Server-unique serial number
      79             : 
      80             :     /** The identifiers of removed children since the last slave commit. */
      81             :     std::vector< uint128_t > removedChildren;
      82             : };
      83             : }
      84             : 
      85       11032 : Object::Object()
      86       11032 :     : _impl( new detail::Object )
      87       11032 : {}
      88             : 
      89        1174 : Object::Object( const Object& from )
      90             :     : co::Serializable( from )
      91        1174 :     , _impl( new detail::Object( *from._impl ))
      92        1174 : {}
      93             : 
      94       19528 : Object::~Object()
      95             : {
      96        9764 :     LBASSERTINFO( !isAttached(), "Object " << getID() << " is still attached" );
      97        9764 :     LBASSERTINFO( !_impl->userData,
      98             :                   "Unset user data before destruction to allow clean release" )
      99             : 
     100        9764 :     co::LocalNodePtr node = getLocalNode();
     101        9764 :     if( node.isValid() )
     102           0 :         node->releaseObject( this );
     103        9764 :     delete _impl;
     104        9764 : }
     105             : 
     106           0 : Object& Object::operator = ( const Object& from )
     107             : {
     108           0 :     if( this == &from )
     109           0 :         return *this;
     110             : 
     111           0 :     co::Serializable::operator = ( from );
     112           0 :     *_impl = *from._impl;
     113           0 :     return *this;
     114             : }
     115             : 
     116        1310 : bool Object::isDirty() const
     117             : {
     118        1310 :     if( _impl->userData && _impl->userData->isAttached( ))
     119             :     {
     120           0 :         if( _impl->userData->isMaster( ))
     121           0 :             _impl->userData->sync(); // apply slave object commits
     122           0 :         return Serializable::isDirty() || _impl->userData->isDirty();
     123             :     }
     124             : 
     125             :     // else
     126        1310 :     return Serializable::isDirty();
     127             : }
     128             : 
     129         114 : uint128_t Object::commit( const uint32_t incarnation )
     130             : {
     131         114 :     if( !_impl->userData )
     132         114 :         return Serializable::commit( incarnation );
     133             : 
     134           0 :     if( !_impl->userData->isAttached() && hasMasterUserData( ))
     135             :     {
     136           0 :         getLocalNode()->registerObject( _impl->userData );
     137           0 :         _impl->userData->setAutoObsolete( getUserDataLatency() + 1 );
     138           0 :         _impl->data.userData = _impl->userData;
     139           0 :         setDirty( DIRTY_USERDATA );
     140             :     }
     141             : 
     142           0 :     if( _impl->userData->isDirty() && _impl->userData->isAttached( ))
     143             :     {
     144           0 :         const uint128_t& version = _impl->userData->commit( incarnation );
     145           0 :         LBASSERT( version != co::VERSION_NONE );
     146           0 :         LBASSERT( !_impl->userData->isDirty( ));
     147           0 :         LBASSERT( _impl->data.userData.identifier != _impl->userData->getID() ||
     148             :                   _impl->data.userData.version <= version );
     149             : 
     150           0 :         if( _impl->userData->isMaster() &&
     151           0 :             _impl->data.userData != co::ObjectVersion( _impl->userData ))
     152             :         {
     153           0 :             LBASSERTINFO( _impl->data.userData.identifier !=
     154             :                           _impl->userData->getID() ||
     155             :                           _impl->data.userData.version <
     156             :                           _impl->userData->getVersion(),
     157             :                           _impl->data.userData << " >= " <<
     158             :                           co::ObjectVersion( _impl->userData ));
     159             : 
     160           0 :             _impl->data.userData.identifier = _impl->userData->getID();
     161           0 :             _impl->data.userData.version = version;
     162           0 :             setDirty( DIRTY_USERDATA );
     163             :         }
     164             :     }
     165             : 
     166           0 :     return Serializable::commit( incarnation );
     167             : }
     168             : 
     169          76 : void Object::notifyDetach()
     170             : {
     171          76 :     Serializable::notifyDetach();
     172          76 :     if( !_impl->userData )
     173         152 :         return;
     174             : 
     175           0 :     LBASSERT( !_impl->userData->isAttached() ||
     176             :               _impl->userData->isMaster() == hasMasterUserData( ));
     177             : 
     178           0 :     if( _impl->userData->isMaster( ))
     179           0 :         _impl->data.userData = co::ObjectVersion( 0 );
     180             : 
     181           0 :     getLocalNode()->releaseObject( _impl->userData );
     182             : }
     183             : 
     184          44 : void Object::backup()
     185             : {
     186          44 :     LBASSERT( !_impl->userData );
     187          44 :     _impl->backup = _impl->data;
     188          44 : }
     189             : 
     190          44 : void Object::restore()
     191             : {
     192          44 :     LBASSERT( !_impl->userData );
     193          44 :     _impl->data = _impl->backup;
     194          44 :     setDirty( DIRTY_NAME | DIRTY_USERDATA );
     195          44 : }
     196             : 
     197          86 : void Object::serialize( co::DataOStream& os, const uint64_t dirtyBits )
     198             : {
     199          86 :     if( dirtyBits & DIRTY_NAME )
     200          72 :         os << _impl->data.name;
     201          86 :     if( dirtyBits & DIRTY_USERDATA )
     202          72 :         os << _impl->data.userData;
     203          86 :     if( dirtyBits & DIRTY_TASKS )
     204          72 :         os << _impl->tasks;
     205          86 :     if( dirtyBits & DIRTY_REMOVED )
     206             :     {
     207          72 :         LBASSERT( !isMaster() ||
     208             :                   ( _impl->removedChildren.empty() && dirtyBits == DIRTY_ALL ))
     209          72 :         os << _impl->removedChildren;
     210          72 :         _impl->removedChildren.clear();
     211             :     }
     212          86 :     if( (dirtyBits & DIRTY_SERIAL) && isMaster( ))
     213             :     {
     214          72 :         _impl->serial = getInstanceID();
     215          72 :         os << _impl->serial;
     216             :     }
     217          86 : }
     218             : 
     219          46 : void Object::deserialize( co::DataIStream& is, const uint64_t dirtyBits )
     220             : {
     221          46 :     if( dirtyBits & DIRTY_NAME )
     222          32 :         is >> _impl->data.name;
     223          46 :     if( dirtyBits & DIRTY_USERDATA )
     224             :     {
     225          32 :         is >> _impl->data.userData;
     226             :         // map&sync below to allow early exits
     227             :     }
     228          46 :     if( dirtyBits & DIRTY_TASKS )
     229          32 :         is >> _impl->tasks;
     230          46 :     if( dirtyBits & DIRTY_REMOVED )
     231             :     {
     232          32 :         std::vector< uint128_t > removed;
     233          32 :         is >> removed;
     234          32 :         if( !removed.empty( ))
     235             :         {
     236           0 :             LBASSERT( isMaster( ));
     237           0 :             std::vector< uint128_t >::const_iterator i = removed.begin();
     238           0 :             for( ; i != removed.end(); ++i )
     239             :             {
     240           0 :                 removeChild( *i );
     241             :             }
     242          32 :         }
     243             :     }
     244          46 :     if( (dirtyBits & DIRTY_SERIAL) && !isMaster( ))
     245          32 :         is >> _impl->serial;
     246             : 
     247          46 :     if( isMaster( )) // redistribute changes
     248           2 :         setDirty( dirtyBits & getRedistributableBits( ));
     249             : 
     250             :     // Update user data state
     251          46 :     if( !(dirtyBits & DIRTY_USERDATA) || !_impl->userData )
     252          46 :         return;
     253             : 
     254           0 :     LBASSERTINFO( _impl->data.userData.identifier != _impl->userData->getID() ||
     255             :                   _impl->data.userData.version>=_impl->userData->getVersion() ||
     256             :                   _impl->userData->isMaster(),
     257             :                   "Incompatible version, new " << _impl->data.userData
     258             :                   << " old " << co::ObjectVersion( _impl->userData ));
     259             : 
     260           0 :     if( _impl->data.userData.identifier == 0 )
     261             :     {
     262           0 :         if( _impl->userData->isAttached() && !_impl->userData->isMaster( ))
     263             :         {
     264           0 :             LBASSERT( !hasMasterUserData( ));
     265           0 :             getLocalNode()->unmapObject( _impl->userData );
     266             :         }
     267           0 :         return;
     268             :     }
     269             : 
     270           0 :     if( !_impl->userData->isAttached() && _impl->data.userData.identifier != 0 )
     271             :     {
     272           0 :         LBASSERT( !hasMasterUserData( ));
     273           0 :         if( !getLocalNode()->mapObject( _impl->userData, _impl->data.userData ))
     274             :         {
     275           0 :             LBWARN << "Mapping of " << lunchbox::className( _impl->userData )
     276           0 :                    << " user data failed" << std::endl;
     277           0 :             LBUNREACHABLE;
     278           0 :             return;
     279             :         }
     280             :     }
     281             : 
     282           0 :     if( !_impl->userData->isMaster() && _impl->userData->isAttached( ))
     283             :     {
     284           0 :         LBASSERTINFO( _impl->userData->getID() ==
     285             :                       _impl->data.userData.identifier,
     286             :                       _impl->userData->getID() << " != "
     287             :                       << _impl->data.userData.identifier );
     288           0 :         _impl->userData->sync( _impl->data.userData.version );
     289             :     }
     290             : }
     291             : 
     292        3350 : void Object::setName( const std::string& name )
     293             : {
     294        3350 :     if( _impl->data.name == name )
     295        3350 :         return;
     296        3350 :     _impl->data.name = name;
     297        3350 :     setDirty( DIRTY_NAME );
     298             : }
     299             : 
     300           0 : void Object::setUserData( co::Object* userData )
     301             : {
     302           0 :     LBASSERT( !userData || !userData->isAttached() );
     303             : 
     304           0 :     if( _impl->userData == userData )
     305           0 :         return;
     306             : 
     307           0 :     if( _impl->userData && _impl->userData->isAttached( ))
     308             :     {
     309           0 :         LBASSERT( _impl->userData->isMaster() == hasMasterUserData( ));
     310           0 :         _impl->userData->getLocalNode()->releaseObject( _impl->userData );
     311             :     }
     312             : 
     313           0 :     _impl->userData = userData;
     314             : 
     315           0 :     if( hasMasterUserData( ))
     316           0 :         setDirty( DIRTY_USERDATA );
     317           0 :     else if( _impl->data.userData.identifier != 0 )
     318             :     {
     319           0 :         co::LocalNodePtr node = getLocalNode();
     320           0 :         if( node.isValid() )
     321           0 :             node->mapObject( _impl->userData, _impl->data.userData );
     322             :     }
     323             : }
     324             : 
     325           0 : co::Object* Object::getUserData()
     326             : {
     327           0 :     return _impl->userData;
     328             : }
     329             : 
     330           0 : const co::Object* Object::getUserData() const
     331             : {
     332           0 :     return _impl->userData;
     333             : }
     334             : 
     335          16 : uint32_t Object::getTasks() const
     336             : {
     337          16 :     return _impl->tasks;
     338             : }
     339             : 
     340           2 : uint32_t Object::getSerial() const
     341             : {
     342           2 :     return _impl->serial;
     343             : }
     344             : 
     345       51978 : const std::string& Object::getName() const
     346             : {
     347       51978 :     return _impl->data.name;
     348             : }
     349             : 
     350          20 : void Object::setTasks( const uint32_t tasks )
     351             : {
     352          20 :     if( _impl->tasks == tasks )
     353          28 :         return;
     354          12 :     _impl->tasks = tasks;
     355          12 :     setDirty( DIRTY_TASKS );
     356             : }
     357             : 
     358        6576 : void Object::postRemove( Object* child )
     359             : {
     360        6576 :     LBASSERT( child );
     361        6576 :     if( !child->isAttached( ))
     362       13152 :         return;
     363             : 
     364           0 :     LBASSERT( !child->isMaster( ));
     365           0 :     LBASSERT( !isMaster( ));
     366             : 
     367           0 :     _impl->removedChildren.push_back( child->getID( ));
     368           0 :     setDirty( DIRTY_REMOVED );
     369             : 
     370           0 :     co::LocalNodePtr localNode = child->getLocalNode();
     371           0 :     localNode->releaseObject( child );
     372             : }
     373             : 
     374           0 : bool Object::_cmdSync( co::ICommand& )
     375             : {
     376           0 :     LBASSERT( isMaster( ));
     377           0 :     sync( co::VERSION_HEAD );
     378           0 :     return true;
     379             : }
     380             : 
     381             : }
     382          84 : }

Generated by: LCOV version 1.11