LCOV - code coverage report
Current view: top level - eq/fabric - node.ipp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 128 155 82.6 %
Date: 2017-12-16 05:07:20 Functions: 35 80 43.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2014, Stefan Eilemann <eile@eyescale.ch>
       3             :  *                    2010, Cedric Stalder <cedric.stalder@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 "node.h"
      20             : 
      21             : #include "elementVisitor.h"
      22             : #include "leafVisitor.h"
      23             : #include "log.h"
      24             : #include "paths.h"
      25             : 
      26             : #include <co/dataIStream.h>
      27             : #include <co/dataOStream.h>
      28             : 
      29             : namespace eq
      30             : {
      31             : namespace fabric
      32             : {
      33             : namespace
      34             : {
      35             : #define MAKE_ATTR_STRING(attr) (std::string("EQ_NODE_") + #attr)
      36             : 
      37         200 : std::string _iAttributeStrings[] = {MAKE_ATTR_STRING(IATTR_THREAD_MODEL),
      38         100 :                                     MAKE_ATTR_STRING(IATTR_LAUNCH_TIMEOUT),
      39         250 :                                     MAKE_ATTR_STRING(IATTR_HINT_AFFINITY)};
      40             : }
      41             : 
      42             : template <class C, class N, class P, class V>
      43         829 : Node<C, N, P, V>::Node(C* parent)
      44             :     : _config(parent)
      45         829 :     , _isAppNode(false)
      46             : {
      47         829 :     parent->_addNode(static_cast<N*>(this));
      48         829 :     LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
      49         829 : }
      50             : 
      51             : template <class C, class N, class P, class V>
      52         827 : Node<C, N, P, V>::~Node()
      53             : {
      54         827 :     LBLOG(LOG_INIT) << "Delete " << lunchbox::className(this) << std::endl;
      55        3123 :     while (!_pipes.empty())
      56             :     {
      57        1148 :         P* pipe = _pipes.back();
      58        1148 :         LBASSERT(pipe->getNode() == static_cast<N*>(this));
      59        1148 :         _removePipe(pipe);
      60        1148 :         delete pipe;
      61             :     }
      62             : 
      63         827 :     _config->_removeNode(static_cast<N*>(this));
      64        1654 : }
      65             : 
      66             : template <class C, class N, class P, class V>
      67        1658 : Node<C, N, P, V>::BackupData::BackupData()
      68             : {
      69        1658 :     memset(iAttributes, 0xff, IATTR_ALL * sizeof(int32_t));
      70        1658 : }
      71             : 
      72             : template <class C, class N, class P, class V>
      73           2 : void Node<C, N, P, V>::backup()
      74             : {
      75           2 :     Object::backup();
      76           2 :     _backup = _data;
      77           2 : }
      78             : 
      79             : template <class C, class N, class P, class V>
      80           0 : void Node<C, N, P, V>::restore()
      81             : {
      82           0 :     _data = _backup;
      83           0 :     Object::restore();
      84           0 : }
      85             : 
      86             : template <class C, class N, class P, class V>
      87          10 : uint128_t Node<C, N, P, V>::commit(const uint32_t incarnation)
      88             : {
      89          10 :     if (Serializable::isDirty(DIRTY_PIPES))
      90           8 :         commitChildren(_pipes, incarnation);
      91          10 :     return Object::commit(incarnation);
      92             : }
      93             : 
      94             : template <class C, class N, class P, class V>
      95           9 : void Node<C, N, P, V>::serialize(co::DataOStream& os, const uint64_t dirtyBits)
      96             : {
      97           9 :     Object::serialize(os, dirtyBits);
      98           9 :     if (dirtyBits & DIRTY_ATTRIBUTES)
      99           5 :         os << co::Array<int32_t>(_data.iAttributes, IATTR_ALL);
     100           9 :     if (dirtyBits & DIRTY_PIPES && isMaster())
     101             :     {
     102           8 :         os << _mapNodeObjects();
     103           8 :         os.serializeChildren(_pipes);
     104             :     }
     105           9 :     if (dirtyBits & DIRTY_MEMBER)
     106           2 :         os << _isAppNode;
     107           9 : }
     108             : 
     109             : template <class C, class N, class P, class V>
     110           5 : void Node<C, N, P, V>::deserialize(co::DataIStream& is,
     111             :                                    const uint64_t dirtyBits)
     112             : {
     113           5 :     Object::deserialize(is, dirtyBits);
     114           5 :     if (dirtyBits & DIRTY_ATTRIBUTES)
     115           4 :         is >> co::Array<int32_t>(_data.iAttributes, IATTR_ALL);
     116           5 :     if (dirtyBits & DIRTY_PIPES)
     117             :     {
     118           3 :         if (isMaster())
     119           0 :             syncChildren(_pipes);
     120             :         else
     121             :         {
     122           3 :             const bool useChildren = is.read<bool>();
     123           3 :             if (useChildren && _mapNodeObjects())
     124             :             {
     125           0 :                 Pipes result;
     126           0 :                 is.deserializeChildren(this, _pipes, result);
     127           0 :                 _pipes.swap(result);
     128           0 :                 LBASSERT(_pipes.size() == result.size());
     129             :             }
     130             :             else // consume unused ObjectVersions
     131           3 :                 is.read<co::ObjectVersions>();
     132             :         }
     133             :     }
     134           5 :     if (dirtyBits & DIRTY_MEMBER)
     135           1 :         is >> _isAppNode;
     136           5 : }
     137             : 
     138             : template <class C, class N, class P, class V>
     139       61434 : void Node<C, N, P, V>::setDirty(const uint64_t dirtyBits)
     140             : {
     141       61434 :     Object::setDirty(dirtyBits);
     142       61434 :     _config->setDirty(C::DIRTY_NODES);
     143       61434 : }
     144             : 
     145             : template <class C, class N, class P, class V>
     146           3 : void Node<C, N, P, V>::notifyDetach()
     147             : {
     148           3 :     Object::notifyDetach();
     149           3 :     while (!_pipes.empty())
     150             :     {
     151           2 :         P* pipe = _pipes.back();
     152           2 :         if (!pipe->isAttached())
     153             :         {
     154           2 :             LBASSERT(isMaster());
     155           2 :             return;
     156             :         }
     157             : 
     158           0 :         LBASSERT(!isMaster());
     159           0 :         getLocalNode()->unmapObject(pipe);
     160           0 :         _removePipe(pipe);
     161           0 :         _config->getServer()->getNodeFactory()->releasePipe(pipe);
     162             :     }
     163             : }
     164             : 
     165             : template <class C, class N, class P, class V>
     166           0 : void Node<C, N, P, V>::create(P** pipe)
     167             : {
     168           0 :     *pipe = _config->getServer()->getNodeFactory()->createPipe(
     169             :         static_cast<N*>(this));
     170           0 : }
     171             : 
     172             : template <class C, class N, class P, class V>
     173           0 : void Node<C, N, P, V>::release(P* pipe)
     174             : {
     175           0 :     _config->getServer()->getNodeFactory()->releasePipe(pipe);
     176           0 : }
     177             : 
     178             : namespace
     179             : {
     180             : template <class N, class V>
     181       20886 : VisitorResult _accept(N* node, V& visitor)
     182             : {
     183       20886 :     VisitorResult result = visitor.visitPre(node);
     184       20886 :     if (result != TRAVERSE_CONTINUE)
     185         382 :         return result;
     186             : 
     187       20504 :     const typename N::Pipes& pipes = node->getPipes();
     188       48446 :     for (typename N::Pipes::const_iterator i = pipes.begin(); i != pipes.end();
     189             :          ++i)
     190             :     {
     191       33354 :         switch ((*i)->accept(visitor))
     192             :         {
     193             :         case TRAVERSE_TERMINATE:
     194        5412 :             return TRAVERSE_TERMINATE;
     195             : 
     196             :         case TRAVERSE_PRUNE:
     197           0 :             result = TRAVERSE_PRUNE;
     198           0 :             break;
     199             : 
     200             :         case TRAVERSE_CONTINUE:
     201             :         default:
     202       27942 :             break;
     203             :         }
     204             :     }
     205             : 
     206       15092 :     switch (visitor.visitPost(node))
     207             :     {
     208             :     case TRAVERSE_TERMINATE:
     209           0 :         return TRAVERSE_TERMINATE;
     210             : 
     211             :     case TRAVERSE_PRUNE:
     212           0 :         return TRAVERSE_PRUNE;
     213             : 
     214             :     case TRAVERSE_CONTINUE:
     215             :     default:
     216       15092 :         break;
     217             :     }
     218             : 
     219       15092 :     return result;
     220             : }
     221             : }
     222             : 
     223             : template <class C, class N, class P, class V>
     224       20886 : VisitorResult Node<C, N, P, V>::accept(V& visitor)
     225             : {
     226       20886 :     return _accept(static_cast<N*>(this), visitor);
     227             : }
     228             : 
     229             : template <class C, class N, class P, class V>
     230           0 : VisitorResult Node<C, N, P, V>::accept(V& visitor) const
     231             : {
     232           0 :     return _accept(static_cast<const N*>(this), visitor);
     233             : }
     234             : 
     235             : template <class C, class N, class P, class V>
     236           4 : NodePath Node<C, N, P, V>::getPath() const
     237             : {
     238           4 :     const C* config = static_cast<const N*>(this)->getConfig();
     239           4 :     LBASSERT(config);
     240             : 
     241           4 :     const typename std::vector<N*>& nodes = config->getNodes();
     242             :     typename std::vector<N*>::const_iterator i =
     243           4 :         std::find(nodes.begin(), nodes.end(), this);
     244           4 :     LBASSERT(i != nodes.end());
     245             : 
     246           4 :     NodePath path;
     247           4 :     path.nodeIndex = std::distance(nodes.begin(), i);
     248           4 :     return path;
     249             : }
     250             : 
     251             : template <class C, class N, class P, class V>
     252         404 : void Node<C, N, P, V>::setApplicationNode(const bool isAppNode)
     253             : {
     254         404 :     if (_isAppNode == isAppNode)
     255           0 :         return;
     256         404 :     _isAppNode = isAppNode;
     257         404 :     setDirty(DIRTY_MEMBER);
     258             : }
     259             : 
     260             : template <class C, class N, class P, class V>
     261        2485 : void Node<C, N, P, V>::setIAttribute(const IAttribute attr, const int32_t value)
     262             : {
     263        2485 :     if (_data.iAttributes[attr] == value)
     264         828 :         return;
     265        1657 :     _data.iAttributes[attr] = value;
     266        1657 :     setDirty(DIRTY_ATTRIBUTES);
     267             : }
     268             : 
     269             : template <class C, class N, class P, class V>
     270        1262 : int32_t Node<C, N, P, V>::getIAttribute(const IAttribute attr) const
     271             : {
     272        1262 :     return _data.iAttributes[attr];
     273             : }
     274             : 
     275             : template <class C, class N, class P, class V>
     276        1834 : const std::string& Node<C, N, P, V>::getIAttributeString(const IAttribute attr)
     277             : {
     278        1834 :     return _iAttributeStrings[attr];
     279             : }
     280             : 
     281             : template <class C, class N, class P, class V>
     282        1152 : void Node<C, N, P, V>::_addPipe(P* pipe)
     283             : {
     284        1152 :     LBASSERT(pipe->getNode() == this);
     285        1152 :     _pipes.push_back(pipe);
     286        1152 : }
     287             : 
     288             : template <class C, class N, class P, class V>
     289        2298 : bool Node<C, N, P, V>::_removePipe(P* pipe)
     290             : {
     291        2298 :     typename Pipes::iterator i = lunchbox::find(_pipes, pipe);
     292        2298 :     if (i == _pipes.end())
     293        1148 :         return false;
     294             : 
     295        1150 :     _pipes.erase(i);
     296        1150 :     return true;
     297             : }
     298             : 
     299             : template <class C, class N, class P, class V>
     300           2 : P* Node<C, N, P, V>::findPipe(const uint128_t& id)
     301             : {
     302           2 :     for (typename Pipes::const_iterator i = _pipes.begin(); i != _pipes.end();
     303             :          ++i)
     304             :     {
     305           2 :         P* pipe = *i;
     306           2 :         if (pipe->getID() == id)
     307           2 :             return pipe;
     308             :     }
     309           0 :     return 0;
     310             : }
     311             : 
     312             : template <class C, class N, class P, class V>
     313         416 : std::ostream& operator<<(std::ostream& os, const Node<C, N, P, V>& node)
     314             : {
     315         416 :     os << lunchbox::disableFlush << lunchbox::disableHeader;
     316         416 :     if (node.isApplicationNode())
     317         204 :         os << "appNode" << std::endl;
     318             :     else
     319         212 :         os << "node" << std::endl;
     320             : 
     321         416 :     os << "{" << std::endl << lunchbox::indent;
     322             : 
     323         416 :     const std::string& name = node.getName();
     324         416 :     if (!name.empty())
     325          22 :         os << "name     \"" << name << "\"" << std::endl;
     326             : 
     327         416 :     node.output(os);
     328             : 
     329         416 :     const typename N::Pipes& pipes = node.getPipes();
     330         996 :     for (typename N::Pipes::const_iterator i = pipes.begin(); i != pipes.end();
     331             :          ++i)
     332             :     {
     333         580 :         os << **i;
     334             :     }
     335         832 :     os << lunchbox::exdent << "}" << std::endl
     336         416 :        << lunchbox::enableHeader << lunchbox::enableFlush;
     337         416 :     return os;
     338             : }
     339             : }
     340             : }

Generated by: LCOV version 1.11