LCOV - code coverage report
Current view: top level - co - object.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 130 174 74.7 %
Date: 2014-10-06 Functions: 31 42 73.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *               2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This file is part of Collage <https://github.com/Eyescale/Collage>
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or modify it under
       8             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       9             :  * by the Free Software Foundation.
      10             :  *
      11             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      13             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      14             :  * details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             :  */
      20             : 
      21             : #include "object.h"
      22             : 
      23             : #include "dataIStream.h"
      24             : #include "dataOStream.h"
      25             : #include "deltaMasterCM.h"
      26             : #include "fullMasterCM.h"
      27             : #include "global.h"
      28             : #include "log.h"
      29             : #include "nodeCommand.h"
      30             : #include "nullCM.h"
      31             : #include "objectCM.h"
      32             : #include "objectOCommand.h"
      33             : #include "staticMasterCM.h"
      34             : #include "staticSlaveCM.h"
      35             : #include "types.h"
      36             : #include "unbufferedMasterCM.h"
      37             : #include "versionedSlaveCM.h"
      38             : 
      39             : #include <lunchbox/compressor.h>
      40             : #include <lunchbox/scopedMutex.h>
      41             : #include <lunchbox/plugins/compressor.h>
      42             : #include <iostream>
      43             : 
      44             : namespace co
      45             : {
      46             : namespace detail
      47             : {
      48          61 : class Object
      49             : {
      50             : public:
      51          61 :     Object()
      52             :         : id( lunchbox::make_UUID( ))
      53             :         , instanceID( CO_INSTANCE_INVALID )
      54          61 :         , cm( ObjectCM::ZERO )
      55          61 :         {}
      56             : 
      57             :     /** The session-unique object identifier. */
      58             :     uint128_t id;
      59             : 
      60             :     /** The node where this object is attached. */
      61             :     LocalNodePtr localNode;
      62             : 
      63             :     /** A session-unique identifier of the concrete instance. */
      64             :     uint32_t instanceID;
      65             : 
      66             :     /** The object's change manager. */
      67             :     ObjectCMPtr cm;
      68             : };
      69             : }
      70             : 
      71          61 : Object::Object()
      72          61 :     : impl_( new detail::Object )
      73          61 : {}
      74             : 
      75           0 : Object::Object( const Object& object )
      76             :     : Dispatcher( object )
      77           0 :     , impl_( new detail::Object )
      78           0 : {}
      79             : 
      80         122 : Object::~Object()
      81             : {
      82          61 :     LBASSERTINFO( !isAttached(),
      83             :                   "Object " << impl_->id << " is still attached to node " <<
      84             :                   impl_->localNode->getNodeID());
      85             : 
      86          61 :     if( impl_->localNode )
      87           0 :         impl_->localNode->releaseObject( this );
      88             : 
      89          61 :     impl_->localNode = 0;
      90          61 :     impl_->cm = 0;
      91          61 :     delete impl_;
      92          61 : }
      93             : 
      94         974 : bool Object::isAttached() const
      95             : {
      96         974 :     return impl_->instanceID != CO_INSTANCE_INVALID;
      97             : }
      98             : 
      99        1113 : LocalNodePtr Object::getLocalNode()
     100             : {
     101        1113 :     return impl_->localNode;
     102             : }
     103             : 
     104           0 : void Object::setID( const uint128_t& identifier )
     105             : {
     106           0 :     LBASSERT( !isAttached( ));
     107           0 :     LBASSERT( identifier.isUUID( ));
     108           0 :     impl_->id = identifier;
     109           0 : }
     110             : 
     111         405 : const uint128_t& Object::getID() const
     112             : {
     113         405 :     return impl_->id;
     114             : }
     115             : 
     116         385 : uint32_t Object::getInstanceID() const
     117             : {
     118         385 :     return impl_->instanceID;
     119             : }
     120             : 
     121          61 : void Object::attach( const uint128_t& id, const uint32_t instanceID )
     122             : {
     123          61 :     LBASSERT( !isAttached() );
     124          61 :     LBASSERT( impl_->localNode );
     125          61 :     LBASSERT( instanceID <= CO_INSTANCE_MAX );
     126             : 
     127          61 :     impl_->id         = id;
     128          61 :     impl_->instanceID = instanceID;
     129          61 :     LBLOG( LOG_OBJECTS )
     130          61 :         << impl_->id << '.' << impl_->instanceID << ": " << lunchbox::className( this )
     131         183 :         << (isMaster() ? " master" : " slave") << std::endl;
     132          61 : }
     133             : 
     134          61 : void Object::detach()
     135             : {
     136          61 :     impl_->instanceID = CO_INSTANCE_INVALID;
     137          61 :     impl_->localNode = 0;
     138          61 : }
     139             : 
     140          60 : void Object::notifyDetach()
     141             : {
     142          60 :     if( !isMaster( ))
     143          98 :         return;
     144             : 
     145             :     // unmap slaves
     146          20 :     const Nodes slaves = impl_->cm->getSlaveNodes();
     147          20 :     if( slaves.empty( ))
     148          18 :         return;
     149             : 
     150           6 :     LBWARN << slaves.size() << " slaves subscribed during deregisterObject of "
     151           8 :            << lunchbox::className( this ) << " id " << impl_->id << std::endl;
     152             : 
     153           4 :     for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
     154             :     {
     155           2 :         NodePtr node = *i;
     156           2 :         node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
     157           4 :     }
     158             : }
     159             : 
     160           0 : void Object::transfer( Object* from )
     161             : {
     162           0 :     impl_->id           = from->impl_->id;
     163           0 :     impl_->instanceID   = from->getInstanceID();
     164           0 :     impl_->cm           = from->impl_->cm;
     165           0 :     impl_->localNode    = from->impl_->localNode;
     166           0 :     impl_->cm->setObject( this );
     167             : 
     168           0 :     from->impl_->cm = ObjectCM::ZERO;
     169           0 :     from->impl_->localNode = 0;
     170           0 :     from->impl_->instanceID = CO_INSTANCE_INVALID;
     171           0 : }
     172             : 
     173          89 : void Object::_setChangeManager( ObjectCMPtr cm )
     174             : {
     175          89 :     if( impl_->cm != ObjectCM::ZERO )
     176             :     {
     177          28 :         LBVERB
     178           0 :             << "Overriding existing object change manager, obj "
     179          28 :             << lunchbox::className( this ) << ", old cm "
     180          28 :             << lunchbox::className( impl_->cm ) << ", new cm "
     181          84 :             << lunchbox::className( cm ) << std::endl;
     182             :     }
     183             : 
     184          89 :     impl_->cm->exit();
     185          89 :     impl_->cm = cm;
     186          89 :     cm->init();
     187         178 :     LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
     188         267 :                          << lunchbox::className( this ) << std::endl;
     189          89 : }
     190             : 
     191          45 : ObjectCMPtr Object::_getChangeManager()
     192             : {
     193          45 :     return impl_->cm;
     194             : }
     195             : 
     196         390 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
     197             :                              const uint32_t instanceID )
     198             : {
     199         390 :     Connections connections( 1, node->getConnection( ));
     200             :     return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
     201         390 :                            instanceID );
     202             : }
     203             : 
     204           4 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
     205             :                    const Nodes& nodes )
     206             : {
     207           4 :     impl_->cm->push( groupID, typeID, nodes );
     208           4 : }
     209             : 
     210         114 : uint128_t Object::commit( const uint32_t incarnation )
     211             : {
     212         114 :     return impl_->cm->commit( incarnation );
     213             : }
     214             : 
     215             : 
     216          89 : void Object::setupChangeManager( const Object::ChangeType type,
     217             :                                  const bool master, LocalNodePtr localNode,
     218             :                                  const uint32_t masterInstanceID )
     219             : {
     220          89 :     impl_->localNode = localNode;
     221             : 
     222          89 :     switch( type )
     223             :     {
     224             :         case Object::NONE:
     225          28 :             LBASSERT( !localNode );
     226          28 :             _setChangeManager( ObjectCM::ZERO );
     227          28 :             break;
     228             : 
     229             :         case Object::STATIC:
     230          16 :             LBASSERT( impl_->localNode );
     231          16 :             if( master )
     232           8 :                 _setChangeManager( new StaticMasterCM( this ));
     233             :             else
     234           8 :                 _setChangeManager( new StaticSlaveCM( this ));
     235          16 :             break;
     236             : 
     237             :         case Object::INSTANCE:
     238           6 :             LBASSERT( impl_->localNode );
     239           6 :             if( master )
     240           3 :                 _setChangeManager( new FullMasterCM( this ));
     241             :             else
     242             :                 _setChangeManager( new VersionedSlaveCM( this,
     243           3 :                                                          masterInstanceID ));
     244           6 :             break;
     245             : 
     246             :         case Object::DELTA:
     247          35 :             LBASSERT( impl_->localNode );
     248          35 :             if( master )
     249           7 :                 _setChangeManager( new DeltaMasterCM( this ));
     250             :             else
     251             :                 _setChangeManager( new VersionedSlaveCM( this,
     252          28 :                                                          masterInstanceID ));
     253          35 :             break;
     254             : 
     255             :         case Object::UNBUFFERED:
     256           4 :             LBASSERT( impl_->localNode );
     257           4 :             if( master )
     258           2 :                 _setChangeManager( new UnbufferedMasterCM( this ));
     259             :             else
     260             :                 _setChangeManager( new VersionedSlaveCM( this,
     261           2 :                                                          masterInstanceID ));
     262           4 :             break;
     263             : 
     264           0 :         default: LBUNIMPLEMENTED;
     265             :     }
     266          89 : }
     267             : 
     268             : //---------------------------------------------------------------------------
     269             : // ChangeManager forwarders
     270             : //---------------------------------------------------------------------------
     271          41 : void Object::applyMapData( const uint128_t& version )
     272             : {
     273          41 :     impl_->cm->applyMapData( version );
     274          41 : }
     275             : 
     276           0 : void Object::sendInstanceData( Nodes& nodes )
     277             : {
     278           0 :     impl_->cm->sendInstanceData( nodes );
     279           0 : }
     280             : 
     281           0 : bool Object::isBuffered() const
     282             : {
     283           0 :     return impl_->cm->isBuffered();
     284             : }
     285             : 
     286         424 : bool Object::isMaster() const
     287             : {
     288         424 :     return impl_->cm->isMaster();
     289             : }
     290             : 
     291          32 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
     292             : {
     293          32 :     impl_->cm->removeSlave( node, instanceID );
     294          32 : }
     295             : 
     296          25 : void Object::removeSlaves( NodePtr node )
     297             : {
     298          25 :     impl_->cm->removeSlaves( node );
     299          25 : }
     300             : 
     301          41 : void Object::setMasterNode( NodePtr node )
     302             : {
     303          41 :     impl_->cm->setMasterNode( node );
     304          41 : }
     305             : 
     306           0 : void Object::addInstanceDatas( const ObjectDataIStreamDeque& cache,
     307             :                                const uint128_t& version )
     308             : {
     309           0 :     impl_->cm->addInstanceDatas( cache, version );
     310           0 : }
     311             : 
     312           1 : void Object::setAutoObsolete( const uint32_t count )
     313             : {
     314           1 :     impl_->cm->setAutoObsolete( count );
     315           1 : }
     316             : 
     317           0 : uint32_t Object::getAutoObsolete() const
     318             : {
     319           0 :     return impl_->cm->getAutoObsolete();
     320             : }
     321             : 
     322         308 : uint128_t Object::sync( const uint128_t& version )
     323             : {
     324         308 :     if( version == VERSION_NONE )
     325           0 :         return getVersion();
     326         308 :     return impl_->cm->sync( version );
     327             : }
     328             : 
     329           0 : uint128_t Object::getHeadVersion() const
     330             : {
     331           0 :     return impl_->cm->getHeadVersion();
     332             : }
     333             : 
     334        1559 : uint128_t Object::getVersion() const
     335             : {
     336        1559 :     return impl_->cm->getVersion();
     337             : }
     338             : 
     339         145 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
     340             : {
     341         145 :     LBASSERTINFO( getVersion() == VERSION_NONE ||
     342             :                   version < getVersion() + 100,
     343             :                   lunchbox::className( this ));
     344         145 : }
     345             : 
     346         178 : uint32_t Object::chooseCompressor() const
     347             : {
     348         178 :     return lunchbox::Compressor::choose( Global::getPluginRegistry(),
     349             :                                          EQ_COMPRESSOR_DATATYPE_BYTE, 1.f,
     350         178 :                                          false );
     351             : }
     352             : 
     353          40 : uint32_t Object::getMasterInstanceID() const
     354             : {
     355          40 :     return impl_->cm->getMasterInstanceID();
     356             : }
     357             : 
     358          34 : NodePtr Object::getMasterNode()
     359             : {
     360          34 :     return impl_->cm->getMasterNode();
     361             : }
     362             : 
     363           0 : std::ostream& operator << ( std::ostream& os, const Object& object )
     364             : {
     365           0 :     os << lunchbox::className( &object ) << " " << object.getID() << "."
     366           0 :        << object.getInstanceID() << " v" << object.getVersion();
     367           0 :     return os;
     368             : }
     369             : 
     370           0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
     371             : {
     372           0 :     return os << ( type == Object::NONE ? "none" :
     373           0 :                    type == Object::STATIC ? "static" :
     374           0 :                    type == Object::INSTANCE ? "instance" :
     375           0 :                    type == Object::DELTA ? "delta" :
     376           0 :                    type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
     377             : }
     378             : 
     379          60 : }

Generated by: LCOV version 1.10