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 : }
|