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