LCOV - code coverage report
Current view: top level - eq/fabric - object.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 147 181 81.2 %
Date: 2014-06-18 Functions: 29 32 90.6 %

          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       23917 : 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        5285 : class Object
      44             : {
      45             : public:
      46        5870 :     Object()
      47             :         : userData( 0 )
      48             :         , tasks( TASK_NONE )
      49        5870 :         , serial( CO_INSTANCE_INVALID )
      50        5870 :     {}
      51             : 
      52         636 :     Object( const Object& from )
      53             :         : data( from.data )
      54             :         , backup()
      55             :         , userData( from.userData )
      56             :         , tasks( from.tasks )
      57         636 :         , serial( from.serial )
      58         636 :     {}
      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        5870 : Object::Object()
      86        5870 :     : _impl( new detail::Object )
      87        5870 : {}
      88             : 
      89         636 : Object::Object( const Object& from )
      90             :     : co::Serializable( from )
      91         636 :     , _impl( new detail::Object( *from._impl ))
      92         636 : {}
      93             : 
      94       10570 : Object::~Object()
      95             : {
      96        5285 :     LBASSERTINFO( !isAttached(), "Object " << getID() << " is still attached" );
      97        5285 :     LBASSERTINFO( !_impl->userData,
      98             :                   "Unset user data before destruction to allow clean release" )
      99             : 
     100        5285 :     co::LocalNodePtr node = getLocalNode();
     101        5285 :     if( node.isValid() )
     102           0 :         node->releaseObject( this );
     103        5285 :     delete _impl;
     104        5285 : }
     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      166594 : bool Object::isDirty() const
     117             : {
     118      166594 :     if( _impl->userData && _impl->userData->isAttached( ))
     119             :     {
     120          15 :         if( _impl->userData->isMaster( ))
     121          14 :             _impl->userData->sync(); // apply slave object commits
     122          15 :         return Serializable::isDirty() || _impl->userData->isDirty();
     123             :     }
     124             : 
     125             :     // else
     126      166579 :     return Serializable::isDirty();
     127             : }
     128             : 
     129      165782 : uint128_t Object::commit( const uint32_t incarnation )
     130             : {
     131      165782 :     if( !_impl->userData )
     132      165767 :         return Serializable::commit( incarnation );
     133             : 
     134          15 :     if( !_impl->userData->isAttached() && hasMasterUserData( ))
     135             :     {
     136           7 :         getLocalNode()->registerObject( _impl->userData );
     137           7 :         _impl->userData->setAutoObsolete( getUserDataLatency() + 1 );
     138           7 :         _impl->data.userData = _impl->userData;
     139           7 :         setDirty( DIRTY_USERDATA );
     140             :     }
     141             : 
     142          15 :     if( _impl->userData->isDirty() && _impl->userData->isAttached( ))
     143             :     {
     144           2 :         const uint128_t& version = _impl->userData->commit( incarnation );
     145           2 :         LBASSERT( version != co::VERSION_NONE );
     146           2 :         LBASSERT( !_impl->userData->isDirty( ));
     147           2 :         LBASSERT( _impl->data.userData.identifier != _impl->userData->getID() ||
     148             :                   _impl->data.userData.version <= version );
     149             : 
     150           7 :         if( _impl->userData->isMaster() &&
     151           5 :             _impl->data.userData != _impl->userData )
     152             :         {
     153           1 :             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           1 :             _impl->data.userData.identifier = _impl->userData->getID();
     161           1 :             _impl->data.userData.version = version;
     162           1 :             setDirty( DIRTY_USERDATA );
     163             :         }
     164             :     }
     165             : 
     166          15 :     return Serializable::commit( incarnation );
     167             : }
     168             : 
     169         533 : void Object::notifyDetach()
     170             : {
     171         533 :     Serializable::notifyDetach();
     172         533 :     if( !_impl->userData )
     173        1058 :         return;
     174             : 
     175           8 :     LBASSERT( !_impl->userData->isAttached() ||
     176             :               _impl->userData->isMaster() == hasMasterUserData( ));
     177             : 
     178           8 :     if( _impl->userData->isMaster( ))
     179           7 :         _impl->data.userData = co::ObjectVersion( 0 );
     180             : 
     181           8 :     getLocalNode()->releaseObject( _impl->userData );
     182             : }
     183             : 
     184         313 : void Object::backup()
     185             : {
     186         313 :     LBASSERT( !_impl->userData );
     187         313 :     _impl->backup = _impl->data;
     188         313 : }
     189             : 
     190          22 : void Object::restore()
     191             : {
     192          22 :     LBASSERT( !_impl->userData );
     193          22 :     _impl->data = _impl->backup;
     194          22 :     setDirty( DIRTY_NAME | DIRTY_USERDATA );
     195          22 : }
     196             : 
     197         869 : void Object::serialize( co::DataOStream& os, const uint64_t dirtyBits )
     198             : {
     199         869 :     if( dirtyBits & DIRTY_NAME )
     200         432 :         os << _impl->data.name;
     201         869 :     if( dirtyBits & DIRTY_USERDATA )
     202         448 :         os << _impl->data.userData;
     203         869 :     if( dirtyBits & DIRTY_TASKS )
     204         485 :         os << _impl->tasks;
     205         869 :     if( dirtyBits & DIRTY_REMOVED )
     206             :     {
     207         432 :         LBASSERT( !isMaster() ||
     208             :                   ( _impl->removedChildren.empty() && dirtyBits == DIRTY_ALL ))
     209         432 :         os << _impl->removedChildren;
     210         432 :         _impl->removedChildren.clear();
     211             :     }
     212         869 :     if( (dirtyBits & DIRTY_SERIAL) && isMaster( ))
     213             :     {
     214         432 :         _impl->serial = getInstanceID();
     215         432 :         os << _impl->serial;
     216             :     }
     217         869 : }
     218             : 
     219         591 : void Object::deserialize( co::DataIStream& is, const uint64_t dirtyBits )
     220             : {
     221         591 :     if( dirtyBits & DIRTY_NAME )
     222         220 :         is >> _impl->data.name;
     223         591 :     if( dirtyBits & DIRTY_USERDATA )
     224             :     {
     225         236 :         is >> _impl->data.userData;
     226             :         // map&sync below to allow early exits
     227             :     }
     228         591 :     if( dirtyBits & DIRTY_TASKS )
     229         238 :         is >> _impl->tasks;
     230         591 :     if( dirtyBits & DIRTY_REMOVED )
     231             :     {
     232         220 :         std::vector< uint128_t > removed;
     233         220 :         is >> removed;
     234         220 :         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         220 :         }
     243             :     }
     244         591 :     if( (dirtyBits & DIRTY_SERIAL) && !isMaster( ))
     245         220 :         is >> _impl->serial;
     246             : 
     247         591 :     if( isMaster( )) // redistribute changes
     248         147 :         setDirty( dirtyBits & getRedistributableBits( ));
     249             : 
     250             :     // Update user data state
     251         591 :     if( !(dirtyBits & DIRTY_USERDATA) || !_impl->userData )
     252         575 :         return;
     253             : 
     254          16 :     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          16 :     if( _impl->data.userData.identifier == 0 )
     261             :     {
     262           7 :         if( _impl->userData->isAttached() && !_impl->userData->isMaster( ))
     263             :         {
     264           0 :             LBASSERT( !hasMasterUserData( ));
     265           0 :             getLocalNode()->unmapObject( _impl->userData );
     266             :         }
     267           7 :         return;
     268             :     }
     269             : 
     270           9 :     if( !_impl->userData->isAttached() && _impl->data.userData.identifier != 0 )
     271             :     {
     272           1 :         LBASSERT( !hasMasterUserData( ));
     273           1 :         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           9 :     if( !_impl->userData->isMaster() && _impl->userData->isAttached( ))
     283             :     {
     284           1 :         LBASSERTINFO( _impl->userData->getID() ==
     285             :                       _impl->data.userData.identifier,
     286             :                       _impl->userData->getID() << " != "
     287             :                       << _impl->data.userData.identifier );
     288           1 :         _impl->userData->sync( _impl->data.userData.version );
     289             :     }
     290             : }
     291             : 
     292        1789 : void Object::setName( const std::string& name )
     293             : {
     294        1789 :     if( _impl->data.name == name )
     295        1802 :         return;
     296        1776 :     _impl->data.name = name;
     297        1776 :     setDirty( DIRTY_NAME );
     298             : }
     299             : 
     300          16 : void Object::setUserData( co::Object* userData )
     301             : {
     302          16 :     LBASSERT( !userData || !userData->isAttached() );
     303             : 
     304          16 :     if( _impl->userData == userData )
     305          16 :         return;
     306             : 
     307          16 :     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          16 :     _impl->userData = userData;
     314             : 
     315          16 :     if( hasMasterUserData( ))
     316          14 :         setDirty( DIRTY_USERDATA );
     317           2 :     else if( _impl->data.userData.identifier != 0 )
     318             :     {
     319           1 :         co::LocalNodePtr node = getLocalNode();
     320           1 :         if( node.isValid() )
     321           0 :             node->mapObject( _impl->userData, _impl->data.userData );
     322             :     }
     323             : }
     324             : 
     325           9 : co::Object* Object::getUserData()
     326             : {
     327           9 :     return _impl->userData;
     328             : }
     329             : 
     330           1 : const co::Object* Object::getUserData() const
     331             : {
     332           1 :     return _impl->userData;
     333             : }
     334             : 
     335        1408 : uint32_t Object::getTasks() const
     336             : {
     337        1408 :     return _impl->tasks;
     338             : }
     339             : 
     340         157 : uint32_t Object::getSerial() const
     341             : {
     342         157 :     return _impl->serial;
     343             : }
     344             : 
     345       30512 : const std::string& Object::getName() const
     346             : {
     347       30512 :     return _impl->data.name;
     348             : }
     349             : 
     350        1415 : void Object::setTasks( const uint32_t tasks )
     351             : {
     352        1415 :     if( _impl->tasks == tasks )
     353        2599 :         return;
     354         231 :     _impl->tasks = tasks;
     355         231 :     setDirty( DIRTY_TASKS );
     356             : }
     357             : 
     358        3639 : void Object::postRemove( Object* child )
     359             : {
     360        3639 :     LBASSERT( child );
     361        3639 :     if( !child->isAttached( ))
     362        7278 :         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          10 : bool Object::_cmdSync( co::ICommand& )
     375             : {
     376          10 :     LBASSERT( isMaster( ));
     377          10 :     sync( co::VERSION_HEAD );
     378          10 :     return true;
     379             : }
     380             : 
     381             : }
     382          45 : }

Generated by: LCOV version 1.10