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