Line data Source code
1 :
2 : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2010, Cedric Stalder <cedric Stalder@gmail.com>
4 : * 2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "config.h"
21 :
22 : #include "paths.h"
23 :
24 : #include "configVisitor.h"
25 :
26 : #include <co/global.h>
27 : #include <co/objectICommand.h>
28 :
29 : #include "layout.ipp" // Layout::_removeObserver template impl
30 :
31 : namespace eq
32 : {
33 : namespace fabric
34 : {
35 :
36 : #define MAKE_ATTR_STRING( attr ) ( std::string("EQ_CONFIG_") + #attr )
37 :
38 : namespace
39 : {
40 42 : std::string _fAttributeStrings[] =
41 : {
42 : MAKE_ATTR_STRING( FATTR_EYE_BASE ),
43 : MAKE_ATTR_STRING( FATTR_VERSION ),
44 21 : };
45 42 : std::string _iAttributeStrings[] =
46 : {
47 : MAKE_ATTR_STRING( IATTR_ROBUSTNESS ),
48 21 : };
49 : }
50 :
51 : template< class S, class C, class O, class L, class CV, class N, class V >
52 235 : Config< S, C, O, L, CV, N, V >::Config( lunchbox::RefPtr< S > server )
53 : : Object()
54 235 : , _server( server )
55 : {
56 235 : server->_addConfig( static_cast< C* >( this ));
57 235 : LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
58 235 : }
59 :
60 : template< class S, class C, class O, class L, class CV, class N, class V >
61 224 : Config< S, C, O, L, CV, N, V >::~Config()
62 : {
63 224 : LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
64 224 : _appNodeID = 0;
65 :
66 670 : while( !_canvases.empty( ))
67 : {
68 222 : CV* canvas = _canvases.back();
69 222 : _removeCanvas( canvas );
70 222 : delete canvas;
71 : }
72 :
73 827 : while( !_layouts.empty( ))
74 : {
75 379 : L* layout = _layouts.back();
76 379 : _removeLayout( layout );
77 379 : delete layout;
78 : }
79 :
80 664 : while( !_observers.empty( ))
81 : {
82 216 : O* observer = _observers.back();
83 216 : _removeObserver( observer );
84 216 : delete observer;
85 : }
86 :
87 885 : while( !_nodes.empty( ))
88 : {
89 437 : N* node = _nodes.back();
90 437 : _removeNode( node );
91 437 : delete node;
92 : }
93 :
94 224 : _server->_removeConfig( static_cast< C* >( this ));
95 224 : _server = 0;
96 :
97 448 : }
98 :
99 : template< class S, class C, class O, class L, class CV, class N, class V >
100 20 : void Config< S, C, O, L, CV, N, V >::attach( const uint128_t& id,
101 : const uint32_t instanceID )
102 : {
103 20 : Object::attach( id, instanceID );
104 :
105 20 : co::CommandQueue* queue = _server->getMainThreadQueue();
106 20 : LBASSERT( queue );
107 :
108 20 : registerCommand( CMD_CONFIG_NEW_LAYOUT,
109 : CmdFunc( this, &Config< S, C, O, L, CV, N, V >::_cmdNewLayout ),
110 : queue );
111 20 : registerCommand( CMD_CONFIG_NEW_CANVAS,
112 : CmdFunc( this, &Config< S, C, O, L, CV, N, V >::_cmdNewCanvas ),
113 : queue);
114 20 : registerCommand( CMD_CONFIG_NEW_OBSERVER,
115 : CmdFunc( this, &Config< S, C, O, L, CV, N, V >::_cmdNewObserver ),
116 : queue);
117 20 : registerCommand( CMD_CONFIG_NEW_ENTITY_REPLY,
118 : CmdFunc( this, &Config< S, C, O, L, CV, N, V >::_cmdNewEntityReply ),
119 : 0);
120 20 : }
121 :
122 : template< class C, class V >
123 6957 : VisitorResult _acceptImpl( C* config, V& visitor )
124 : {
125 6957 : VisitorResult result = visitor.visitPre( config );
126 6957 : if( result != TRAVERSE_CONTINUE )
127 317 : return result;
128 :
129 6640 : const typename C::Nodes& nodes = config->getNodes();
130 47817 : for( typename C::Nodes::const_iterator i = nodes.begin();
131 31878 : i != nodes.end(); ++i )
132 : {
133 12227 : switch( (*i)->accept( visitor ))
134 : {
135 : case TRAVERSE_TERMINATE:
136 2928 : return TRAVERSE_TERMINATE;
137 :
138 : case TRAVERSE_PRUNE:
139 251 : result = TRAVERSE_PRUNE;
140 251 : break;
141 :
142 : case TRAVERSE_CONTINUE:
143 : default:
144 9048 : break;
145 : }
146 : }
147 :
148 3712 : const typename C::Observers& observers = config->getObservers();
149 20724 : for( typename C::Observers::const_iterator i = observers.begin();
150 13816 : i != observers.end(); ++i )
151 : {
152 3727 : switch( (*i)->accept( visitor ))
153 : {
154 : case TRAVERSE_TERMINATE:
155 531 : return TRAVERSE_TERMINATE;
156 :
157 : case TRAVERSE_PRUNE:
158 0 : result = TRAVERSE_PRUNE;
159 0 : break;
160 :
161 : case TRAVERSE_CONTINUE:
162 : default:
163 3196 : break;
164 : }
165 : }
166 :
167 3181 : const typename C::Layouts& layouts = config->getLayouts();
168 50931 : for( typename C::Layouts::const_iterator i = layouts.begin();
169 33954 : i != layouts.end(); ++i )
170 : {
171 14880 : switch( (*i)->accept( visitor ))
172 : {
173 : case TRAVERSE_TERMINATE:
174 1084 : return TRAVERSE_TERMINATE;
175 :
176 : case TRAVERSE_PRUNE:
177 0 : result = TRAVERSE_PRUNE;
178 0 : break;
179 :
180 : case TRAVERSE_CONTINUE:
181 : default:
182 13796 : break;
183 : }
184 : }
185 :
186 2097 : const typename C::Canvases& canvases = config->getCanvases();
187 11592 : for( typename C::Canvases::const_iterator i = canvases.begin();
188 7728 : i != canvases.end(); ++i )
189 : {
190 1783 : switch( (*i)->accept( visitor ))
191 : {
192 : case TRAVERSE_TERMINATE:
193 16 : return TRAVERSE_TERMINATE;
194 :
195 : case TRAVERSE_PRUNE:
196 0 : result = TRAVERSE_PRUNE;
197 0 : break;
198 :
199 : case TRAVERSE_CONTINUE:
200 : default:
201 1767 : break;
202 : }
203 : }
204 :
205 2081 : switch( config->_acceptCompounds( visitor ))
206 : {
207 : case TRAVERSE_TERMINATE:
208 213 : return TRAVERSE_TERMINATE;
209 :
210 : case TRAVERSE_PRUNE:
211 394 : result = TRAVERSE_PRUNE;
212 394 : break;
213 :
214 : case TRAVERSE_CONTINUE:
215 : default:
216 1474 : break;
217 : }
218 :
219 1868 : switch( visitor.visitPost( config ))
220 : {
221 : case TRAVERSE_TERMINATE:
222 0 : return TRAVERSE_TERMINATE;
223 :
224 : case TRAVERSE_PRUNE:
225 0 : result = TRAVERSE_PRUNE;
226 0 : break;
227 :
228 : case TRAVERSE_CONTINUE:
229 : default:
230 1868 : break;
231 : }
232 :
233 1868 : return result;
234 : }
235 :
236 : template< class S, class C, class O, class L, class CV, class N, class V >
237 4910 : VisitorResult Config< S, C, O, L, CV, N, V >::accept( V& visitor )
238 : {
239 4910 : return _acceptImpl( static_cast< C* >( this ), visitor );
240 : }
241 :
242 : template< class S, class C, class O, class L, class CV, class N, class V >
243 2047 : VisitorResult Config< S, C, O, L, CV, N, V >::accept( V& visitor ) const
244 : {
245 2047 : return _acceptImpl( static_cast< const C* >( this ), visitor );
246 : }
247 :
248 : template< class S, class C, class O, class L, class CV, class N, class V >
249 21745 : lunchbox::RefPtr< S > Config< S, C, O, L, CV, N, V >::getServer()
250 : {
251 21745 : return _server;
252 : }
253 :
254 : template< class S, class C, class O, class L, class CV, class N, class V >
255 122 : lunchbox::RefPtr< const S > Config< S, C, O, L, CV, N, V >::getServer() const
256 : {
257 122 : return _server;
258 : }
259 :
260 : namespace
261 : {
262 : template< typename T, typename V > class IDFinder : public V
263 : {
264 : public:
265 136 : IDFinder( const uint128_t& id ) : _id( id ), _result( 0 ) {}
266 136 : virtual ~IDFinder(){}
267 :
268 266 : virtual VisitorResult visitPre( T* node ) { return visit( node ); }
269 329 : virtual VisitorResult visit( T* node )
270 : {
271 329 : if( node->getID() == _id )
272 : {
273 126 : _result = node;
274 126 : return TRAVERSE_TERMINATE;
275 : }
276 203 : return TRAVERSE_CONTINUE;
277 : }
278 :
279 136 : T* getResult() { return _result; }
280 :
281 : private:
282 : const uint128_t _id;
283 : T* _result;
284 : };
285 : }
286 :
287 :
288 : template< class S, class C, class O, class L, class CV, class N, class V >
289 : template< typename T >
290 136 : void Config< S, C, O, L, CV, N, V >::find( const uint128_t& id, T** result )
291 : {
292 136 : IDFinder< T, V > finder( id );
293 136 : static_cast< C* >( this )->accept( finder );
294 136 : *result = finder.getResult();
295 136 : }
296 :
297 : template< class S, class C, class O, class L, class CV, class N, class V >
298 : template< typename T >
299 577 : void Config< S, C, O, L, CV, N, V >::find( const std::string& name,
300 : const T** result ) const
301 : {
302 577 : NameFinder< T, V > finder( name );
303 577 : static_cast< const C* >( this )->accept( finder );
304 577 : *result = finder.getResult();
305 577 : }
306 :
307 : template< class S, class C, class O, class L, class CV, class N, class V >
308 : template< typename T >
309 0 : T* Config< S, C, O, L, CV, N, V >::find( const uint128_t& id )
310 : {
311 0 : IDFinder< T, V > finder( id );
312 0 : static_cast< C* >( this )->accept( finder );
313 0 : return finder.getResult();
314 : }
315 :
316 : template< class S, class C, class O, class L, class CV, class N, class V >
317 : template< typename T >
318 0 : const T* Config< S, C, O, L, CV, N, V >::find( const uint128_t& id ) const
319 : {
320 0 : IDFinder< const T, V > finder( id );
321 0 : static_cast< const C* >( this )->accept( finder );
322 0 : return finder.getResult();
323 : }
324 :
325 : template< class S, class C, class O, class L, class CV, class N, class V >
326 : template< typename T >
327 1870 : T* Config< S, C, O, L, CV, N, V >::find( const std::string& name )
328 : {
329 1870 : NameFinder< T, V > finder( name );
330 1870 : static_cast< C* >( this )->accept( finder );
331 1870 : return finder.getResult();
332 : }
333 :
334 : template< class S, class C, class O, class L, class CV, class N, class V >
335 : template< typename T >
336 1470 : const T* Config< S, C, O, L, CV, N, V >::find( const std::string& name ) const
337 : {
338 1470 : NameFinder< const T, V > finder( name );
339 1470 : static_cast< const C* >( this )->accept( finder );
340 1470 : return finder.getResult();
341 : }
342 :
343 :
344 : template< class S, class C, class O, class L, class CV, class N, class V >
345 153 : O* Config< S, C, O, L, CV, N, V >::getObserver( const ObserverPath& path )
346 : {
347 153 : LBASSERTINFO( _observers.size() > path.observerIndex,
348 : _observers.size() << " <= " << path.observerIndex );
349 :
350 153 : if( _observers.size() <= path.observerIndex )
351 0 : return 0;
352 :
353 153 : return _observers[ path.observerIndex ];
354 : }
355 :
356 : template< class S, class C, class O, class L, class CV, class N, class V >
357 712 : const std::string& Config< S, C, O, L, CV, N, V >::getFAttributeString(
358 : const FAttribute attr )
359 : {
360 712 : return _fAttributeStrings[ attr ];
361 : }
362 :
363 : template< class S, class C, class O, class L, class CV, class N, class V >
364 360 : const std::string& Config< S, C, O, L, CV, N, V >::getIAttributeString(
365 : const IAttribute attr )
366 : {
367 360 : return _iAttributeStrings[ attr ];
368 : }
369 :
370 : template< class S, class C, class O, class L, class CV, class N, class V >
371 9 : uint32_t Config< S, C, O, L, CV, N, V >::getTimeout() const
372 : {
373 9 : if( getIAttribute( IATTR_ROBUSTNESS ) == OFF )
374 3 : return LB_TIMEOUT_INDEFINITE;
375 6 : return co::Global::getIAttribute( co::Global::IATTR_TIMEOUT_DEFAULT );
376 : }
377 :
378 : template< class S, class C, class O, class L, class CV, class N, class V >
379 863 : L* Config< S, C, O, L, CV, N, V >::getLayout( const LayoutPath& path )
380 : {
381 863 : LBASSERTINFO( _layouts.size() > path.layoutIndex,
382 : _layouts.size() << " <= " << path.layoutIndex );
383 :
384 863 : if( _layouts.size() <= path.layoutIndex )
385 0 : return 0;
386 :
387 863 : return _layouts[ path.layoutIndex ];
388 : }
389 :
390 : template< class S, class C, class O, class L, class CV, class N, class V >
391 1001 : CV* Config< S, C, O, L, CV, N, V >::getCanvas( const CanvasPath& path )
392 : {
393 1001 : LBASSERTINFO( _canvases.size() > path.canvasIndex,
394 : _canvases.size() << " <= " << path.canvasIndex );
395 :
396 1001 : if( _canvases.size() <= path.canvasIndex )
397 0 : return 0;
398 :
399 1001 : return _canvases[ path.canvasIndex ];
400 : }
401 :
402 : template< class S, class C, class O, class L, class CV, class N, class V >
403 227 : void Config< S, C, O, L, CV, N, V >::_addObserver( O* observer )
404 : {
405 227 : LBASSERT( observer->getConfig() == this );
406 227 : _observers.push_back( observer );
407 227 : setDirty( DIRTY_OBSERVERS );
408 227 : }
409 :
410 : template< class S, class C, class O, class L, class CV, class N, class V >
411 452 : bool Config< S, C, O, L, CV, N, V >::_removeObserver( O* observer )
412 : {
413 : typename Observers::iterator i = std::find( _observers.begin(),
414 452 : _observers.end(), observer );
415 452 : if( i == _observers.end( ))
416 226 : return false;
417 :
418 : // remove from views
419 678 : for( typename Layouts::const_iterator j = _layouts.begin();
420 452 : j != _layouts.end(); ++j )
421 : {
422 0 : (*j)->_removeObserver( observer );
423 : }
424 :
425 226 : LBASSERT( observer->getConfig() == this );
426 226 : _observers.erase( i );
427 226 : setDirty( DIRTY_OBSERVERS );
428 226 : if( !isMaster( ))
429 226 : postRemove( observer );
430 226 : return true;
431 : }
432 :
433 : template< class S, class C, class O, class L, class CV, class N, class V >
434 443 : void Config< S, C, O, L, CV, N, V >::_addLayout( L* layout )
435 : {
436 443 : LBASSERT( layout->getConfig() == this );
437 443 : _layouts.push_back( layout );
438 443 : setDirty( DIRTY_LAYOUTS );
439 443 : }
440 :
441 : template< class S, class C, class O, class L, class CV, class N, class V >
442 884 : bool Config< S, C, O, L, CV, N, V >::_removeLayout( L* layout )
443 : {
444 : typename Layouts::iterator i = std::find( _layouts.begin(),
445 884 : _layouts.end(), layout );
446 884 : if( i == _layouts.end( ))
447 442 : return false;
448 :
449 : // remove from canvases
450 1326 : for( typename Canvases::const_iterator j = _canvases.begin();
451 884 : j != _canvases.end(); ++j )
452 : {
453 0 : (*j)->removeLayout( layout );
454 : }
455 :
456 442 : LBASSERT( layout->getConfig() == this );
457 442 : _layouts.erase( i );
458 442 : setDirty( DIRTY_LAYOUTS );
459 442 : if( !isMaster( ))
460 442 : postRemove( layout );
461 442 : return true;
462 : }
463 :
464 : template< class S, class C, class O, class L, class CV, class N, class V >
465 233 : void Config< S, C, O, L, CV, N, V >::_addCanvas( CV* canvas )
466 : {
467 233 : LBASSERT( canvas->getConfig() == this );
468 233 : _canvases.push_back( canvas );
469 233 : setDirty( DIRTY_CANVASES );
470 233 : }
471 :
472 : template< class S, class C, class O, class L, class CV, class N, class V >
473 10 : void Config< S, C, O, L, CV, N, V >::create( O** observer )
474 : {
475 10 : *observer = getServer()->getNodeFactory()->createObserver(
476 : static_cast< C* >( this ));
477 10 : }
478 :
479 : template< class S, class C, class O, class L, class CV, class N, class V >
480 0 : void Config< S, C, O, L, CV, N, V >::release( O* observer )
481 : {
482 0 : getServer()->getNodeFactory()->releaseObserver( observer );
483 0 : }
484 :
485 : template< class S, class C, class O, class L, class CV, class N, class V >
486 63 : void Config< S, C, O, L, CV, N, V >::create( L** layout )
487 : {
488 63 : *layout = getServer()->getNodeFactory()->createLayout(
489 : static_cast< C* >( this ));
490 63 : }
491 :
492 : template< class S, class C, class O, class L, class CV, class N, class V >
493 0 : void Config< S, C, O, L, CV, N, V >::release( L* layout )
494 : {
495 0 : getServer()->getNodeFactory()->releaseLayout( layout );
496 0 : }
497 :
498 : template< class S, class C, class O, class L, class CV, class N, class V >
499 10 : void Config< S, C, O, L, CV, N, V >::create( CV** canvas )
500 : {
501 10 : *canvas = getServer()->getNodeFactory()->createCanvas(
502 : static_cast< C* >( this ));
503 10 : }
504 :
505 : template< class S, class C, class O, class L, class CV, class N, class V >
506 0 : void Config< S, C, O, L, CV, N, V >::release( CV* canvas )
507 : {
508 0 : getServer()->getNodeFactory()->releaseCanvas( canvas );
509 0 : }
510 :
511 : template< class S, class C, class O, class L, class CV, class N, class V >
512 0 : void Config< S, C, O, L, CV, N, V >::create( N** node )
513 : {
514 0 : *node = getServer()->getNodeFactory()->createNode(
515 : static_cast< C* >( this ));
516 0 : }
517 :
518 : template< class S, class C, class O, class L, class CV, class N, class V >
519 0 : void Config< S, C, O, L, CV, N, V >::release( N* node )
520 : {
521 0 : getServer()->getNodeFactory()->releaseNode( node );
522 0 : }
523 :
524 : template< class S, class C, class O, class L, class CV, class N, class V >
525 464 : bool Config< S, C, O, L, CV, N, V >::_removeCanvas( CV* canvas )
526 : {
527 : typename Canvases::iterator i = std::find( _canvases.begin(),
528 464 : _canvases.end(), canvas );
529 464 : if( i == _canvases.end( ))
530 232 : return false;
531 :
532 232 : LBASSERT( canvas->getConfig() == this );
533 232 : _canvases.erase( i );
534 232 : setDirty( DIRTY_CANVASES );
535 232 : if( !isMaster( ))
536 232 : postRemove( canvas );
537 232 : return true;
538 : }
539 :
540 : template< class S, class C, class O, class L, class CV, class N, class V >
541 19 : void Config< S, C, O, L, CV, N, V >::setLatency( const uint32_t latency )
542 : {
543 19 : if( _data.latency == latency )
544 20 : return;
545 :
546 18 : _data.latency = latency;
547 18 : setDirty( DIRTY_LATENCY );
548 : }
549 :
550 : template< class S, class C, class O, class L, class CV, class N, class V >
551 12 : void Config< S, C, O, L, CV, N, V >::setAppNodeID( const co::NodeID& nodeID )
552 : {
553 12 : if( _appNodeID == nodeID )
554 12 : return;
555 :
556 12 : _appNodeID = nodeID;
557 12 : setDirty( DIRTY_MEMBER );
558 : }
559 :
560 : template< class S, class C, class O, class L, class CV, class N, class V >
561 6 : EventOCommand Config< S, C, O, L, CV, N, V >::sendError( co::NodePtr node,
562 : const uint32_t event, const uint128_t& originator, const uint32_t error )
563 : {
564 18 : LBWARN << "Emit " << Error( error ) << " at "
565 24 : << lunchbox::backtrace( 2 /*cut boring stack frames*/ ) << std::endl;
566 6 : EventOCommand cmd( send( node, CMD_CONFIG_EVENT ));
567 6 : cmd << event << originator << error;
568 6 : return cmd;
569 : }
570 :
571 : template< class S, class C, class O, class L, class CV, class N, class V >
572 2 : void Config< S, C, O, L, CV, N, V >::restore()
573 : {
574 2 : Object::restore();
575 2 : if( _data.latency != _backup.latency )
576 : {
577 0 : _data = _backup;
578 0 : changeLatency( _data.latency );
579 : }
580 : else
581 2 : _data = _backup;
582 2 : setDirty( DIRTY_MEMBER | DIRTY_LATENCY );
583 2 : }
584 :
585 : template< class S, class C, class O, class L, class CV, class N, class V >
586 476 : void Config< S, C, O, L, CV, N, V >::_addNode( N* node )
587 : {
588 476 : LBASSERT( node->getConfig() == this );
589 476 : _nodes.push_back( node );
590 476 : }
591 :
592 : template< class S, class C, class O, class L, class CV, class N, class V >
593 882 : bool Config< S, C, O, L, CV, N, V >::_removeNode( N* node )
594 : {
595 : typename Nodes::iterator i = std::find( _nodes.begin(),
596 882 : _nodes.end(), node );
597 882 : if( i == _nodes.end( ))
598 437 : return false;
599 :
600 445 : LBASSERT( node->getConfig() == this );
601 445 : _nodes.erase( i );
602 445 : return true;
603 : }
604 :
605 : template< class S, class C, class O, class L, class CV, class N, class V >
606 24 : N* Config< S, C, O, L, CV, N, V >::findAppNode()
607 : {
608 72 : for( typename Nodes::const_iterator i = _nodes.begin();
609 48 : i != _nodes.end(); ++i )
610 : {
611 24 : N* node = *i;
612 24 : if( node->isApplicationNode( ))
613 24 : return node;
614 : }
615 0 : return 0;
616 : }
617 :
618 : template< class S, class C, class O, class L, class CV, class N, class V >
619 0 : const N* Config< S, C, O, L, CV, N, V >::findAppNode() const
620 : {
621 0 : for( typename Nodes::const_iterator i = _nodes.begin();
622 0 : i != _nodes.end(); ++i )
623 : {
624 0 : const N* node = *i;
625 0 : if( node->isApplicationNode( ))
626 0 : return node;
627 : }
628 0 : return 0;
629 : }
630 :
631 : template< class S, class C, class O, class L, class CV, class N, class V >
632 8 : N* Config< S, C, O, L, CV, N, V >::_findNode( const uint128_t& id )
633 : {
634 24 : for( typename Nodes::const_iterator i = _nodes.begin();
635 16 : i != _nodes.end(); ++i )
636 : {
637 8 : N* node = *i;
638 8 : if( node->getID() == id )
639 8 : return node;
640 : }
641 0 : return 0;
642 : }
643 :
644 : template< class S, class C, class O, class L, class CV, class N, class V >
645 9200 : uint128_t Config< S, C, O, L, CV, N, V >::commit( const uint32_t incarnation )
646 : {
647 9200 : if( Serializable::isDirty( DIRTY_NODES ))
648 21 : commitChildren< N >( _nodes, incarnation );
649 9200 : if( Serializable::isDirty( DIRTY_OBSERVERS ))
650 18 : commitChildren< O, C >( _observers, static_cast< C* >( this ),
651 18 : CMD_CONFIG_NEW_OBSERVER, incarnation );
652 :
653 : // Always traverse layouts and canvases: view/segment objects may be dirty
654 9200 : commitChildren< L, C >( _layouts, static_cast<C*>( this ),
655 9200 : CMD_CONFIG_NEW_LAYOUT, incarnation );
656 9200 : commitChildren< CV, C >( _canvases, static_cast<C*>( this ),
657 9200 : CMD_CONFIG_NEW_CANVAS, incarnation );
658 :
659 9200 : if( Serializable::isDirty( DIRTY_CANVASES ))
660 19 : commitChildren< CV, C >( _canvases, static_cast< C* >( this ),
661 19 : CMD_CONFIG_NEW_CANVAS, incarnation );
662 9200 : return Object::commit( incarnation );
663 : }
664 :
665 : template< class S, class C, class O, class L, class CV, class N, class V >
666 69 : void Config< S, C, O, L, CV, N, V >::serialize( co::DataOStream& os,
667 : const uint64_t dirtyBits )
668 : {
669 69 : Object::serialize( os, dirtyBits );
670 :
671 69 : if( dirtyBits & Config::DIRTY_MEMBER )
672 41 : os << _appNodeID;
673 69 : if( dirtyBits & Config::DIRTY_ATTRIBUTES )
674 41 : os << co::Array< float >( _fAttributes, C::FATTR_ALL )
675 82 : << co::Array< int32_t >( _iAttributes, C::IATTR_ALL );
676 69 : if( isMaster( ) )
677 : {
678 60 : if( dirtyBits & Config::DIRTY_NODES )
679 60 : os.serializeChildren( _nodes );
680 60 : if( dirtyBits & Config::DIRTY_OBSERVERS )
681 49 : os.serializeChildren( _observers );
682 60 : if( dirtyBits & Config::DIRTY_LAYOUTS )
683 57 : os.serializeChildren( _layouts );
684 60 : if( dirtyBits & Config::DIRTY_CANVASES )
685 50 : os.serializeChildren( _canvases );
686 : }
687 69 : if( dirtyBits & Config::DIRTY_LATENCY )
688 41 : os << _data.latency;
689 69 : }
690 :
691 : template< class S, class C, class O, class L, class CV, class N, class V >
692 38 : void Config< S, C, O, L, CV, N, V >::deserialize( co::DataIStream& is,
693 : const uint64_t dirtyBits )
694 : {
695 38 : Object::deserialize( is, dirtyBits );
696 :
697 38 : if( dirtyBits & Config::DIRTY_MEMBER )
698 10 : is >> _appNodeID;
699 38 : if( dirtyBits & Config::DIRTY_ATTRIBUTES )
700 10 : is >> co::Array< float >( _fAttributes, C::FATTR_ALL )
701 20 : >> co::Array< int32_t >( _iAttributes, C::IATTR_ALL );
702 38 : if( isMaster( ))
703 : {
704 9 : if( dirtyBits & Config::DIRTY_NODES )
705 0 : syncChildren( _nodes );
706 9 : if( dirtyBits & Config::DIRTY_OBSERVERS )
707 8 : syncChildren( _observers );
708 9 : if( dirtyBits & Config::DIRTY_LAYOUTS )
709 9 : syncChildren( _layouts );
710 9 : if( dirtyBits & Config::DIRTY_CANVASES )
711 8 : syncChildren( _canvases );
712 : }
713 : else
714 : {
715 29 : if( dirtyBits & Config::DIRTY_NODES )
716 : {
717 29 : if( mapNodeObjects( ))
718 : {
719 0 : typename C::Nodes result;
720 0 : is.deserializeChildren( this, _nodes, result );
721 0 : _nodes.swap( result );
722 0 : LBASSERT( _nodes.size() == result.size( ));
723 : }
724 : else // consume unused ObjectVersions
725 : {
726 29 : co::ObjectVersions childIDs;
727 29 : is >> childIDs;
728 : }
729 : }
730 :
731 29 : if( mapViewObjects( )) // depends on _config._appNodeID !
732 : {
733 29 : if( dirtyBits & Config::DIRTY_OBSERVERS )
734 : {
735 18 : typename C::Observers result;
736 18 : is.deserializeChildren( this, _observers, result );
737 18 : _observers.swap( result );
738 18 : LBASSERT( _observers.size() == result.size( ));
739 : }
740 29 : if( dirtyBits & Config::DIRTY_LAYOUTS )
741 : {
742 26 : typename C::Layouts result;
743 26 : is.deserializeChildren( this, _layouts, result );
744 26 : _layouts.swap( result );
745 26 : LBASSERT( _layouts.size() == result.size( ));
746 : }
747 29 : if( dirtyBits & Config::DIRTY_CANVASES )
748 : {
749 19 : typename C::Canvases result;
750 19 : is.deserializeChildren( this, _canvases, result );
751 19 : _canvases.swap( result );
752 19 : LBASSERT( _canvases.size() == result.size( ));
753 : }
754 : }
755 : else // consume unused ObjectVersions
756 : {
757 0 : co::ObjectVersions childIDs;
758 0 : if( dirtyBits & Config::DIRTY_OBSERVERS )
759 0 : is >> childIDs;
760 0 : if( dirtyBits & Config::DIRTY_LAYOUTS )
761 0 : is >> childIDs;
762 0 : if( dirtyBits & Config::DIRTY_CANVASES )
763 0 : is >> childIDs;
764 : }
765 : }
766 :
767 38 : if( dirtyBits & Config::DIRTY_LATENCY )
768 : {
769 10 : uint32_t latency = 0;
770 10 : is >> latency;
771 10 : if( _data.latency != latency )
772 : {
773 0 : _data.latency = latency;
774 0 : changeLatency( latency );
775 : }
776 : }
777 38 : }
778 :
779 : template< class S, class C, class O, class L, class CV, class N, class V >
780 20 : void Config< S, C, O, L, CV, N, V >::notifyDetach()
781 : {
782 20 : Object::notifyDetach();
783 20 : if( isMaster( ))
784 30 : return;
785 :
786 10 : typename S::NodeFactory* nodeFactory = getServer()->getNodeFactory();
787 :
788 10 : co::LocalNodePtr localNode = getLocalNode();
789 20 : while( !_nodes.empty( ))
790 : {
791 0 : LBASSERT( mapNodeObjects( ));
792 0 : N* node = _nodes.back();
793 0 : localNode->unmapObject( node );
794 0 : _removeNode( node );
795 0 : nodeFactory->releaseNode( node );
796 : }
797 :
798 30 : while( !_canvases.empty( ))
799 : {
800 10 : LBASSERT( mapViewObjects( ));
801 10 : CV* canvas = _canvases.back();
802 10 : localNode->unmapObject( canvas );
803 10 : _removeCanvas( canvas );
804 10 : nodeFactory->releaseCanvas( canvas );
805 : }
806 :
807 83 : while( !_layouts.empty( ))
808 : {
809 63 : LBASSERT( mapViewObjects( ));
810 63 : L* layout = _layouts.back();
811 63 : localNode->unmapObject( layout );
812 63 : _removeLayout( layout );
813 63 : nodeFactory->releaseLayout( layout );
814 : }
815 :
816 30 : while( !_observers.empty( ))
817 : {
818 10 : LBASSERT( mapViewObjects( ));
819 10 : O* observer = _observers.back();
820 10 : localNode->unmapObject( observer );
821 10 : _removeObserver( observer );
822 10 : nodeFactory->releaseObserver( observer );
823 10 : }
824 : }
825 :
826 : //----------------------------------------------------------------------
827 : // ICommand handlers
828 : //----------------------------------------------------------------------
829 : template< class S, class C, class O, class L, class CV, class N, class V >
830 0 : bool Config< S, C, O, L, CV, N, V >::_cmdNewLayout( co::ICommand& cmd )
831 : {
832 0 : co::ObjectICommand command( cmd );
833 :
834 0 : L* layout = 0;
835 0 : create( &layout );
836 0 : LBASSERT( layout );
837 :
838 0 : getLocalNode()->registerObject( layout );
839 0 : layout->setAutoObsolete( _data.latency + 1 );
840 0 : LBASSERT( layout->isAttached() );
841 :
842 0 : send( command.getRemoteNode(), CMD_CONFIG_NEW_ENTITY_REPLY )
843 0 : << command.read< uint32_t >() << layout->getID();
844 0 : return true;
845 : }
846 :
847 : template< class S, class C, class O, class L, class CV, class N, class V >
848 0 : bool Config< S, C, O, L, CV, N, V >::_cmdNewCanvas( co::ICommand& cmd )
849 : {
850 0 : co::ObjectICommand command( cmd );
851 :
852 0 : CV* canvas = 0;
853 0 : create( &canvas );
854 0 : LBASSERT( canvas );
855 :
856 0 : getLocalNode()->registerObject( canvas );
857 0 : canvas->setAutoObsolete( _data.latency + 1 );
858 0 : LBASSERT( canvas->isAttached() );
859 :
860 0 : send( command.getRemoteNode(), CMD_CONFIG_NEW_ENTITY_REPLY )
861 0 : << command.read< uint32_t >() << canvas->getID();
862 0 : return true;
863 : }
864 :
865 : template< class S, class C, class O, class L, class CV, class N, class V >
866 0 : bool Config< S, C, O, L, CV, N, V >::_cmdNewObserver( co::ICommand& cmd )
867 : {
868 0 : co::ObjectICommand command( cmd );
869 :
870 0 : O* observer = 0;
871 0 : create( &observer );
872 0 : LBASSERT( observer );
873 :
874 0 : getLocalNode()->registerObject( observer );
875 0 : observer->setAutoObsolete( _data.latency + 1 );
876 0 : LBASSERT( observer->isAttached() );
877 :
878 0 : send( command.getRemoteNode(), CMD_CONFIG_NEW_ENTITY_REPLY )
879 0 : << command.read< uint32_t >() << observer->getID();
880 0 : return true;
881 : }
882 :
883 : template< class S, class C, class O, class L, class CV, class N, class V >
884 0 : bool Config< S, C, O, L, CV, N, V >::_cmdNewEntityReply( co::ICommand& cmd )
885 : {
886 0 : co::ObjectICommand command( cmd );
887 :
888 0 : const uint32_t requestID = command.read< uint32_t >();
889 0 : const uint128_t& result = command.read< uint128_t >();
890 :
891 0 : getLocalNode()->serveRequest( requestID, result );
892 :
893 0 : return true;
894 : }
895 :
896 : template< class S, class C, class O, class L, class CV, class N, class V >
897 120 : std::ostream& operator << ( std::ostream& os,
898 : const Config< S, C, O, L, CV, N, V >& config )
899 : {
900 120 : os << lunchbox::disableFlush << lunchbox::disableHeader << "config "
901 : << std::endl;
902 120 : os << "{" << std::endl << lunchbox::indent;
903 :
904 120 : if( !config.getName().empty( ))
905 120 : os << "name \"" << config.getName() << '"' << std::endl;
906 :
907 120 : if( config.getLatency() != 1 )
908 9 : os << "latency " << config.getLatency() << std::endl;
909 120 : os << std::endl;
910 :
911 240 : os << "attributes" << std::endl << "{" << std::endl << lunchbox::indent
912 120 : << "robustness "
913 240 : << IAttribute( config.getIAttribute( C::IATTR_ROBUSTNESS )) << std::endl
914 240 : << "eye_base " << config.getFAttribute( C::FATTR_EYE_BASE )
915 120 : << std::endl
916 120 : << lunchbox::exdent << "}" << std::endl;
917 :
918 120 : const typename C::Nodes& nodes = config.getNodes();
919 1077 : for( typename C::Nodes::const_iterator i = nodes.begin();
920 718 : i != nodes.end(); ++i )
921 : {
922 239 : os << **i;
923 : }
924 120 : os << std::endl;
925 :
926 120 : const typename C::Observers& observers = config.getObservers();
927 723 : for( typename C::Observers::const_iterator i = observers.begin();
928 482 : i !=observers.end(); ++i )
929 : {
930 121 : os << **i;
931 : }
932 120 : const typename C::Layouts& layouts = config.getLayouts();
933 1206 : for( typename C::Layouts::const_iterator i = layouts.begin();
934 804 : i !=layouts.end(); ++i )
935 : {
936 282 : os << **i;
937 : }
938 120 : const typename C::Canvases& canvases = config.getCanvases();
939 732 : for( typename C::Canvases::const_iterator i = canvases.begin();
940 488 : i != canvases.end(); ++i )
941 : {
942 124 : os << **i;
943 : }
944 :
945 120 : config.output( os );
946 :
947 120 : os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
948 : << lunchbox::enableFlush;
949 :
950 120 : return os;
951 : }
952 :
953 : }
954 : }
|