LCOV - code coverage report
Current view: top level - co - object.cpp (source / functions) Hit Total Coverage
Test: Collage Lines: 131 175 74.9 %
Date: 2015-11-03 13:48:53 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/scopedMutex.h>
      40             : #include <pression/compressor.h>
      41             : #include <pression/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         973 : bool Object::isAttached() const
      95             : {
      96         973 :     return impl_->instanceID != CO_INSTANCE_INVALID;
      97             : }
      98             : 
      99        1114 : LocalNodePtr Object::getLocalNode()
     100             : {
     101        1114 :     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 :     LBLOG( LOG_BUG ) << slaves.size() << " slaves subscribed during "
     151           8 :                      << " deregister/unmap of " << lunchbox::className( this )
     152           8 :                      << " id " << impl_->id << std::endl;
     153             : 
     154           4 :     for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
     155             :     {
     156           2 :         NodePtr node = *i;
     157           2 :         node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
     158           4 :     }
     159             : }
     160             : 
     161           0 : void Object::transfer( Object* from )
     162             : {
     163           0 :     impl_->id           = from->impl_->id;
     164           0 :     impl_->instanceID   = from->getInstanceID();
     165           0 :     impl_->cm           = from->impl_->cm;
     166           0 :     impl_->localNode    = from->impl_->localNode;
     167           0 :     impl_->cm->setObject( this );
     168             : 
     169           0 :     from->impl_->cm = ObjectCM::ZERO;
     170           0 :     from->impl_->localNode = 0;
     171           0 :     from->impl_->instanceID = CO_INSTANCE_INVALID;
     172           0 : }
     173             : 
     174          89 : void Object::_setChangeManager( ObjectCMPtr cm )
     175             : {
     176          89 :     if( impl_->cm != ObjectCM::ZERO )
     177             :     {
     178          28 :         LBVERB
     179           0 :             << "Overriding existing object change manager, obj "
     180          28 :             << lunchbox::className( this ) << ", old cm "
     181          28 :             << lunchbox::className( impl_->cm ) << ", new cm "
     182          84 :             << lunchbox::className( cm ) << std::endl;
     183             :     }
     184             : 
     185          89 :     impl_->cm->exit();
     186          89 :     impl_->cm = cm;
     187          89 :     cm->init();
     188         178 :     LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
     189         267 :                          << lunchbox::className( this ) << std::endl;
     190          89 : }
     191             : 
     192          45 : ObjectCMPtr Object::_getChangeManager()
     193             : {
     194          45 :     return impl_->cm;
     195             : }
     196             : 
     197         390 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
     198             :                              const uint32_t instanceID )
     199             : {
     200         390 :     Connections connections( 1, node->getConnection( ));
     201             :     return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
     202         386 :                            instanceID );
     203             : }
     204             : 
     205           4 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
     206             :                    const Nodes& nodes )
     207             : {
     208           4 :     impl_->cm->push( groupID, typeID, nodes );
     209           4 : }
     210             : 
     211         114 : uint128_t Object::commit( const uint32_t incarnation )
     212             : {
     213         114 :     return impl_->cm->commit( incarnation );
     214             : }
     215             : 
     216             : 
     217          89 : void Object::setupChangeManager( const Object::ChangeType type,
     218             :                                  const bool master, LocalNodePtr localNode,
     219             :                                  const uint32_t masterInstanceID )
     220             : {
     221          89 :     impl_->localNode = localNode;
     222             : 
     223          89 :     switch( type )
     224             :     {
     225             :         case Object::NONE:
     226          28 :             LBASSERT( !localNode );
     227          28 :             _setChangeManager( ObjectCM::ZERO );
     228          28 :             break;
     229             : 
     230             :         case Object::STATIC:
     231          16 :             LBASSERT( impl_->localNode );
     232          16 :             if( master )
     233           8 :                 _setChangeManager( new StaticMasterCM( this ));
     234             :             else
     235           8 :                 _setChangeManager( new StaticSlaveCM( this ));
     236          16 :             break;
     237             : 
     238             :         case Object::INSTANCE:
     239           6 :             LBASSERT( impl_->localNode );
     240           6 :             if( master )
     241           3 :                 _setChangeManager( new FullMasterCM( this ));
     242             :             else
     243             :                 _setChangeManager( new VersionedSlaveCM( this,
     244           3 :                                                          masterInstanceID ));
     245           6 :             break;
     246             : 
     247             :         case Object::DELTA:
     248          35 :             LBASSERT( impl_->localNode );
     249          35 :             if( master )
     250           7 :                 _setChangeManager( new DeltaMasterCM( this ));
     251             :             else
     252             :                 _setChangeManager( new VersionedSlaveCM( this,
     253          28 :                                                          masterInstanceID ));
     254          35 :             break;
     255             : 
     256             :         case Object::UNBUFFERED:
     257           4 :             LBASSERT( impl_->localNode );
     258           4 :             if( master )
     259           2 :                 _setChangeManager( new UnbufferedMasterCM( this ));
     260             :             else
     261             :                 _setChangeManager( new VersionedSlaveCM( this,
     262           2 :                                                          masterInstanceID ));
     263           4 :             break;
     264             : 
     265           0 :         default: LBUNIMPLEMENTED;
     266             :     }
     267          89 : }
     268             : 
     269             : //---------------------------------------------------------------------------
     270             : // ChangeManager forwarders
     271             : //---------------------------------------------------------------------------
     272          41 : void Object::applyMapData( const uint128_t& version )
     273             : {
     274          41 :     impl_->cm->applyMapData( version );
     275          41 : }
     276             : 
     277           0 : void Object::sendInstanceData( Nodes& nodes )
     278             : {
     279           0 :     impl_->cm->sendInstanceData( nodes );
     280           0 : }
     281             : 
     282           0 : bool Object::isBuffered() const
     283             : {
     284           0 :     return impl_->cm->isBuffered();
     285             : }
     286             : 
     287         424 : bool Object::isMaster() const
     288             : {
     289         424 :     return impl_->cm->isMaster();
     290             : }
     291             : 
     292          32 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
     293             : {
     294          32 :     impl_->cm->removeSlave( node, instanceID );
     295          32 : }
     296             : 
     297          25 : void Object::removeSlaves( NodePtr node )
     298             : {
     299          25 :     impl_->cm->removeSlaves( node );
     300          25 : }
     301             : 
     302          41 : void Object::setMasterNode( NodePtr node )
     303             : {
     304          41 :     impl_->cm->setMasterNode( node );
     305          41 : }
     306             : 
     307           0 : void Object::addInstanceDatas( const ObjectDataIStreamDeque& cache,
     308             :                                const uint128_t& version )
     309             : {
     310           0 :     impl_->cm->addInstanceDatas( cache, version );
     311           0 : }
     312             : 
     313           1 : void Object::setAutoObsolete( const uint32_t count )
     314             : {
     315           1 :     impl_->cm->setAutoObsolete( count );
     316           1 : }
     317             : 
     318           0 : uint32_t Object::getAutoObsolete() const
     319             : {
     320           0 :     return impl_->cm->getAutoObsolete();
     321             : }
     322             : 
     323         308 : uint128_t Object::sync( const uint128_t& version )
     324             : {
     325         308 :     if( version == VERSION_NONE )
     326           0 :         return getVersion();
     327         308 :     return impl_->cm->sync( version );
     328             : }
     329             : 
     330           0 : uint128_t Object::getHeadVersion() const
     331             : {
     332           0 :     return impl_->cm->getHeadVersion();
     333             : }
     334             : 
     335        1562 : uint128_t Object::getVersion() const
     336             : {
     337        1562 :     return impl_->cm->getVersion();
     338             : }
     339             : 
     340         145 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
     341             : {
     342         145 :     LBASSERTINFO( getVersion() == VERSION_NONE ||
     343             :                   version < getVersion() + 100,
     344             :                   lunchbox::className( this ));
     345         145 : }
     346             : 
     347         178 : uint32_t Object::chooseCompressor() const
     348             : {
     349         178 :     return pression::Compressor::choose( Global::getPluginRegistry(),
     350             :                                          EQ_COMPRESSOR_DATATYPE_BYTE, 1.f,
     351         178 :                                          false );
     352             : }
     353             : 
     354          40 : uint32_t Object::getMasterInstanceID() const
     355             : {
     356          40 :     return impl_->cm->getMasterInstanceID();
     357             : }
     358             : 
     359          34 : NodePtr Object::getMasterNode()
     360             : {
     361          34 :     return impl_->cm->getMasterNode();
     362             : }
     363             : 
     364           0 : std::ostream& operator << ( std::ostream& os, const Object& object )
     365             : {
     366           0 :     os << lunchbox::className( &object ) << " " << object.getID() << "."
     367           0 :        << object.getInstanceID() << " v" << object.getVersion();
     368           0 :     return os;
     369             : }
     370             : 
     371           0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
     372             : {
     373           0 :     return os << ( type == Object::NONE ? "none" :
     374           0 :                    type == Object::STATIC ? "static" :
     375           0 :                    type == Object::INSTANCE ? "instance" :
     376           0 :                    type == Object::DELTA ? "delta" :
     377           0 :                    type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
     378             : }
     379             : 
     380          63 : }

Generated by: LCOV version 1.11