LCOV - code coverage report
Current view: top level - co - object.cpp (source / functions) Hit Total Coverage
Test: Collage Lines: 134 177 75.7 %
Date: 2016-12-14 01:26:48 Functions: 31 42 73.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          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/data/Registry.h>
      41             : #include <iostream>
      42             : 
      43             : namespace co
      44             : {
      45             : namespace detail
      46             : {
      47          63 : class Object
      48             : {
      49             : public:
      50          63 :     Object()
      51          63 :         : id( lunchbox::make_UUID( ))
      52             :         , instanceID( CO_INSTANCE_INVALID )
      53          63 :         , cm( ObjectCM::ZERO )
      54          63 :         {}
      55             : 
      56             :     /** The session-unique object identifier. */
      57             :     uint128_t id;
      58             : 
      59             :     /** The node where this object is attached. */
      60             :     LocalNodePtr localNode;
      61             : 
      62             :     /** A session-unique identifier of the concrete instance. */
      63             :     uint32_t instanceID;
      64             : 
      65             :     /** The object's change manager. */
      66             :     ObjectCMPtr cm;
      67             : };
      68             : }
      69             : 
      70          63 : Object::Object()
      71          63 :     : impl_( new detail::Object )
      72          63 : {}
      73             : 
      74           0 : Object::Object( const Object& object )
      75             :     : Dispatcher( object )
      76           0 :     , impl_( new detail::Object )
      77           0 : {}
      78             : 
      79         126 : Object::~Object()
      80             : {
      81          63 :     LBASSERTINFO( !isAttached(),
      82             :                   "Object " << impl_->id << " is still attached to node " <<
      83             :                   impl_->localNode->getNodeID());
      84             : 
      85          63 :     if( impl_->localNode )
      86           0 :         impl_->localNode->releaseObject( this );
      87             : 
      88          63 :     impl_->localNode = 0;
      89          63 :     impl_->cm = 0;
      90          63 :     delete impl_;
      91          63 : }
      92             : 
      93         980 : bool Object::isAttached() const
      94             : {
      95         980 :     return impl_->instanceID != CO_INSTANCE_INVALID;
      96             : }
      97             : 
      98        1116 : LocalNodePtr Object::getLocalNode()
      99             : {
     100        1116 :     return impl_->localNode;
     101             : }
     102             : 
     103           0 : void Object::setID( const uint128_t& identifier )
     104             : {
     105           0 :     LBASSERT( !isAttached( ));
     106           0 :     LBASSERT( identifier.isUUID( ));
     107           0 :     impl_->id = identifier;
     108           0 : }
     109             : 
     110         414 : const uint128_t& Object::getID() const
     111             : {
     112         414 :     return impl_->id;
     113             : }
     114             : 
     115         399 : uint32_t Object::getInstanceID() const
     116             : {
     117         399 :     return impl_->instanceID;
     118             : }
     119             : 
     120          63 : void Object::attach( const uint128_t& id, const uint32_t instanceID )
     121             : {
     122          63 :     LBASSERTINFO( !isAttached(), *this );
     123          63 :     LBASSERT( impl_->localNode );
     124          63 :     LBASSERT( instanceID <= CO_INSTANCE_MAX );
     125             : 
     126          63 :     impl_->id         = id;
     127          63 :     impl_->instanceID = instanceID;
     128          63 :     LBLOG( LOG_OBJECTS )
     129          63 :         << impl_->id << '.' << impl_->instanceID << ": " << lunchbox::className( this )
     130         189 :         << (isMaster() ? " master" : " slave") << std::endl;
     131          63 : }
     132             : 
     133          63 : void Object::detach()
     134             : {
     135          63 :     impl_->instanceID = CO_INSTANCE_INVALID;
     136          63 :     impl_->localNode = 0;
     137          63 : }
     138             : 
     139          62 : void Object::notifyDetach()
     140             : {
     141          62 :     if( !isMaster( ))
     142         102 :         return;
     143             : 
     144             :     // unmap slaves
     145          22 :     const Nodes slaves = impl_->cm->getSlaveNodes();
     146          21 :     if( slaves.empty( ))
     147          20 :         return;
     148             : 
     149           3 :     LBLOG( LOG_BUG ) << slaves.size() << " slaves subscribed during "
     150           3 :                      << " deregister/unmap of " << lunchbox::className( this )
     151           4 :                      << " id " << impl_->id << std::endl;
     152             : 
     153           2 :     for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
     154             :     {
     155           2 :         NodePtr node = *i;
     156           1 :         node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
     157             :     }
     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          92 : void Object::_setChangeManager( ObjectCMPtr cm )
     174             : {
     175          92 :     if( impl_->cm != ObjectCM::ZERO )
     176             :     {
     177          29 :         LBVERB
     178             :             << "Overriding existing object change manager, obj "
     179          29 :             << lunchbox::className( this ) << ", old cm "
     180          29 :             << lunchbox::className( impl_->cm ) << ", new cm "
     181          87 :             << lunchbox::className( cm ) << std::endl;
     182             :     }
     183             : 
     184          92 :     impl_->cm->exit();
     185          92 :     impl_->cm = cm;
     186          92 :     cm->init();
     187         184 :     LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
     188         276 :                          << lunchbox::className( this ) << std::endl;
     189          92 : }
     190             : 
     191          46 : ObjectCMPtr Object::_getChangeManager()
     192             : {
     193          46 :     return impl_->cm;
     194             : }
     195             : 
     196         389 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
     197             :                              const uint32_t instanceID )
     198             : {
     199         777 :     Connections connections( 1, node->getConnection( ));
     200         390 :     return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
     201         778 :                            instanceID );
     202             : }
     203             : 
     204           5 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
     205             :                    const Nodes& nodes )
     206             : {
     207           5 :     impl_->cm->push( groupID, typeID, nodes );
     208           5 : }
     209             : 
     210         112 : uint128_t Object::commit( const uint32_t incarnation )
     211             : {
     212         112 :     return impl_->cm->commit( incarnation );
     213             : }
     214             : 
     215             : 
     216          92 : void Object::setupChangeManager( const Object::ChangeType type,
     217             :                                  const bool master, LocalNodePtr localNode,
     218             :                                  const uint32_t masterInstanceID )
     219             : {
     220          92 :     impl_->localNode = localNode;
     221             : 
     222          92 :     switch( type )
     223             :     {
     224             :         case Object::NONE:
     225          29 :             LBASSERT( !localNode );
     226          29 :             _setChangeManager( ObjectCM::ZERO );
     227          29 :             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           8 :             LBASSERT( impl_->localNode );
     239           8 :             if( master )
     240           4 :                 _setChangeManager( new FullMasterCM( this ));
     241             :             else
     242           8 :                 _setChangeManager( new VersionedSlaveCM( this,
     243           8 :                                                          masterInstanceID ));
     244           8 :             break;
     245             : 
     246             :         case Object::DELTA:
     247          35 :             LBASSERT( impl_->localNode );
     248          35 :             if( master )
     249           7 :                 _setChangeManager( new DeltaMasterCM( this ));
     250             :             else
     251          56 :                 _setChangeManager( new VersionedSlaveCM( this,
     252          56 :                                                          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           4 :                 _setChangeManager( new VersionedSlaveCM( this,
     261           4 :                                                          masterInstanceID ));
     262           4 :             break;
     263             : 
     264           0 :         default: LBUNIMPLEMENTED;
     265             :     }
     266          92 : }
     267             : 
     268             : //---------------------------------------------------------------------------
     269             : // ChangeManager forwarders
     270             : //---------------------------------------------------------------------------
     271          42 : void Object::applyMapData( const uint128_t& version )
     272             : {
     273          42 :     impl_->cm->applyMapData( version );
     274          42 : }
     275             : 
     276           0 : void Object::sendInstanceData( const 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         438 : bool Object::isMaster() const
     287             : {
     288         438 :     return impl_->cm->isMaster();
     289             : }
     290             : 
     291          33 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
     292             : {
     293          33 :     impl_->cm->removeSlave( node, instanceID );
     294          33 : }
     295             : 
     296          25 : void Object::removeSlaves( NodePtr node )
     297             : {
     298          25 :     impl_->cm->removeSlaves( node );
     299          25 : }
     300             : 
     301          42 : void Object::setMasterNode( NodePtr node )
     302             : {
     303          42 :     impl_->cm->setMasterNode( node );
     304          42 : }
     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         309 : uint128_t Object::sync( const uint128_t& version )
     323             : {
     324         309 :     if( version == VERSION_NONE )
     325           0 :         return getVersion();
     326         309 :     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         144 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
     340             : {
     341         144 :     LBASSERTINFO( getVersion() == VERSION_NONE ||
     342             :                   version < getVersion() + 100,
     343             :                   lunchbox::className( this ));
     344         144 : }
     345             : 
     346         178 : CompressorInfo Object::chooseCompressor() const
     347             : {
     348         178 :     return pression::data::Registry::getInstance().choose();
     349             : }
     350             : 
     351          41 : uint32_t Object::getMasterInstanceID() const
     352             : {
     353          41 :     return impl_->cm->getMasterInstanceID();
     354             : }
     355             : 
     356          35 : NodePtr Object::getMasterNode()
     357             : {
     358          35 :     return impl_->cm->getMasterNode();
     359             : }
     360             : 
     361           0 : std::ostream& operator << ( std::ostream& os, const Object& object )
     362             : {
     363           0 :     os << lunchbox::className( &object ) << " " << object.getID() << "."
     364           0 :        << object.getInstanceID() << " v" << object.getVersion();
     365           0 :     return os;
     366             : }
     367             : 
     368           0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
     369             : {
     370           0 :     return os << ( type == Object::NONE ? "none" :
     371           0 :                    type == Object::STATIC ? "static" :
     372           0 :                    type == Object::INSTANCE ? "instance" :
     373           0 :                    type == Object::DELTA ? "delta" :
     374           0 :                    type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
     375             : }
     376             : 
     377          66 : }

Generated by: LCOV version 1.11