Line data Source code
1 :
2 : /* Copyright (c) 2010-2013, Stefan Eilemann <eile@eyescale.ch>
3 : * 2012, Daniel Nachbaur <danielnachbaur@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 "server.h"
20 :
21 : #include "configVisitor.h"
22 : #include "elementVisitor.h"
23 : #include "leafVisitor.h"
24 : #include "log.h"
25 :
26 : #include <co/connectionDescription.h>
27 : #include <co/global.h>
28 : #include <co/iCommand.h>
29 :
30 : namespace eq
31 : {
32 : namespace fabric
33 : {
34 : #define CmdFunc co::CommandFunc<Server<CL, S, CFG, NF, N, V>>
35 :
36 : template <class CL, class S, class CFG, class NF, class N, class V>
37 405 : Server<CL, S, CFG, NF, N, V>::Server(NF* nodeFactory)
38 : : N(NODETYPE_SERVER)
39 405 : , _nodeFactory(nodeFactory)
40 : {
41 405 : LBASSERT(nodeFactory);
42 405 : LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
43 405 : }
44 :
45 : template <class CL, class S, class CFG, class NF, class N, class V>
46 403 : Server<CL, S, CFG, NF, N, V>::~Server()
47 : {
48 403 : LBLOG(LOG_INIT) << "Delete " << lunchbox::className(this) << std::endl;
49 403 : _client = 0;
50 403 : LBASSERT(_configs.empty());
51 806 : }
52 :
53 : template <class CL, class S, class CFG, class NF, class N, class V>
54 2 : void Server<CL, S, CFG, NF, N, V>::setClient(ClientPtr client)
55 : {
56 2 : _client = client;
57 2 : if (!client)
58 1 : return;
59 :
60 1 : co::CommandQueue* queue = static_cast<S*>(this)->getMainThreadQueue();
61 1 : this->registerCommand(CMD_SERVER_CREATE_CONFIG,
62 : CmdFunc(this, &Server::_cmdCreateConfig), queue);
63 1 : this->registerCommand(CMD_SERVER_DESTROY_CONFIG,
64 : CmdFunc(this, &Server::_cmdDestroyConfig), queue);
65 : }
66 :
67 : template <class CL, class S, class CFG, class NF, class N, class V>
68 405 : void Server<CL, S, CFG, NF, N, V>::_addConfig(CFG* config)
69 : {
70 405 : LBASSERT(config->getServer() == static_cast<S*>(this));
71 405 : LBASSERT(lunchbox::find(_configs, config) == _configs.end());
72 405 : _configs.push_back(config);
73 405 : }
74 :
75 : template <class CL, class S, class CFG, class NF, class N, class V>
76 803 : bool Server<CL, S, CFG, NF, N, V>::_removeConfig(CFG* config)
77 : {
78 803 : typename Configs::iterator i = lunchbox::find(_configs, config);
79 803 : if (i == _configs.end())
80 400 : return false;
81 :
82 403 : _configs.erase(i);
83 403 : return true;
84 : }
85 :
86 : namespace
87 : {
88 : template <class S, class V>
89 809 : VisitorResult _accept(S* server, V& visitor)
90 : {
91 809 : VisitorResult result = visitor.visitPre(server);
92 809 : if (result != TRAVERSE_CONTINUE)
93 0 : return result;
94 :
95 809 : const typename S::Configs& configs = server->getConfigs();
96 4827 : for (typename S::Configs::const_iterator i = configs.begin();
97 3218 : i != configs.end(); ++i)
98 : {
99 800 : switch ((*i)->accept(visitor))
100 : {
101 : case TRAVERSE_TERMINATE:
102 0 : return TRAVERSE_TERMINATE;
103 :
104 : case TRAVERSE_PRUNE:
105 788 : result = TRAVERSE_PRUNE;
106 788 : break;
107 :
108 : case TRAVERSE_CONTINUE:
109 : default:
110 12 : break;
111 : }
112 : }
113 :
114 809 : switch (visitor.visitPost(server))
115 : {
116 : case TRAVERSE_TERMINATE:
117 0 : return TRAVERSE_TERMINATE;
118 :
119 : case TRAVERSE_PRUNE:
120 0 : return TRAVERSE_PRUNE;
121 :
122 : case TRAVERSE_CONTINUE:
123 : default:
124 809 : break;
125 : }
126 :
127 809 : return result;
128 : }
129 : }
130 :
131 : template <class CL, class S, class CFG, class NF, class N, class V>
132 809 : VisitorResult Server<CL, S, CFG, NF, N, V>::accept(V& visitor)
133 : {
134 809 : return _accept(static_cast<S*>(this), visitor);
135 : }
136 :
137 : template <class CL, class S, class CFG, class NF, class N, class V>
138 0 : VisitorResult Server<CL, S, CFG, NF, N, V>::accept(V& visitor) const
139 : {
140 0 : return _accept(static_cast<const S*>(this), visitor);
141 : }
142 :
143 : //---------------------------------------------------------------------------
144 : // command handlers
145 : //---------------------------------------------------------------------------
146 : template <class CL, class S, class CFG, class NF, class N, class V>
147 1 : bool Server<CL, S, CFG, NF, N, V>::_cmdCreateConfig(co::ICommand& command)
148 : {
149 1 : const co::ObjectVersion& configVersion = command.read<co::ObjectVersion>();
150 1 : const uint32_t requestID = command.read<uint32_t>();
151 :
152 1 : LBVERB << "Handle create config " << command << " config version "
153 0 : << configVersion << " request " << requestID << std::endl;
154 :
155 1 : CFG* config = _nodeFactory->createConfig(static_cast<S*>(this));
156 2 : co::LocalNodePtr localNode = command.getLocalNode();
157 1 : if (!localNode->mapObject(config, configVersion))
158 : {
159 0 : LBUNREACHABLE;
160 0 : LBERROR << "Can't map chosen config" << std::endl;
161 :
162 0 : _nodeFactory->releaseConfig(config);
163 0 : return true;
164 : }
165 :
166 1 : co::Global::setIAttribute(co::Global::IATTR_ROBUSTNESS,
167 : config->getIAttribute(CFG::IATTR_ROBUSTNESS));
168 1 : if (requestID != LB_UNDEFINED_UINT32)
169 0 : config->send(command.getRemoteNode(), CMD_CONFIG_CREATE_REPLY)
170 0 : << requestID;
171 :
172 1 : return true;
173 : }
174 :
175 : template <class CL, class S, class CFG, class NF, class N, class V>
176 1 : bool Server<CL, S, CFG, NF, N, V>::_cmdDestroyConfig(co::ICommand& command)
177 : {
178 1 : LBVERB << "Handle destroy config " << command << std::endl;
179 :
180 2 : co::LocalNodePtr localNode = command.getLocalNode();
181 1 : const uint128_t& configID = command.read<uint128_t>();
182 1 : const uint32_t requestID = command.read<uint32_t>();
183 :
184 1 : CFG* config = 0;
185 3 : for (typename Configs::const_iterator i = _configs.begin();
186 2 : i != _configs.end(); ++i)
187 : {
188 1 : if ((*i)->getID() == configID)
189 : {
190 1 : config = *i;
191 1 : break;
192 : }
193 : }
194 1 : LBASSERT(config);
195 :
196 1 : localNode->unmapObject(config);
197 1 : _nodeFactory->releaseConfig(config);
198 :
199 1 : if (requestID != LB_UNDEFINED_UINT32)
200 2 : command.getRemoteNode()->send(CMD_SERVER_DESTROY_CONFIG_REPLY)
201 2 : << requestID;
202 :
203 2 : return true;
204 : }
205 :
206 : template <class CL, class S, class CFG, class NF, class N, class V>
207 206 : std::ostream& operator<<(std::ostream& os,
208 : const Server<CL, S, CFG, NF, N, V>& server)
209 : {
210 206 : os << lunchbox::disableFlush << lunchbox::disableHeader << "server "
211 : << std::endl;
212 206 : os << "{" << std::endl << lunchbox::indent;
213 :
214 412 : const co::ConnectionDescriptions& cds = server.getConnectionDescriptions();
215 1176 : for (co::ConnectionDescriptions::const_iterator i = cds.begin();
216 784 : i != cds.end(); ++i)
217 : {
218 372 : co::ConnectionDescriptionPtr desc = *i;
219 186 : os << *desc;
220 : }
221 :
222 206 : const std::vector<CFG*>& configs = server.getConfigs();
223 1230 : for (typename std::vector<CFG*>::const_iterator i = configs.begin();
224 820 : i != configs.end(); ++i)
225 : {
226 204 : const CFG* config = *i;
227 204 : os << *config;
228 : }
229 :
230 412 : os << lunchbox::exdent << "}" << lunchbox::enableHeader
231 206 : << lunchbox::enableFlush << std::endl;
232 :
233 412 : return os;
234 : }
235 : }
236 : }
|