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