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 237 : Server< CL, S, CFG, NF, N, V >::Server( NF* nodeFactory )
39 : : N( NODETYPE_SERVER )
40 237 : , _nodeFactory( nodeFactory )
41 : {
42 237 : LBASSERT( nodeFactory );
43 237 : LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
44 237 : }
45 :
46 : template< class CL, class S, class CFG, class NF, class N, class V >
47 226 : Server< CL, S, CFG, NF, N, V >::~Server()
48 : {
49 226 : LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
50 226 : _client = 0;
51 226 : LBASSERT( _configs.empty( ));
52 452 : }
53 :
54 : template< class CL, class S, class CFG, class NF, class N, class V >
55 32 : void Server< CL, S, CFG, NF, N, V >::setClient( ClientPtr client )
56 : {
57 32 : _client = client;
58 32 : if( !client )
59 48 : return;
60 :
61 16 : co::CommandQueue* queue = static_cast< S* >( this )->getMainThreadQueue();
62 16 : this->registerCommand( CMD_SERVER_CREATE_CONFIG,
63 : CmdFunc( this, &Server::_cmdCreateConfig ), queue );
64 16 : 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 235 : void Server< CL, S, CFG, NF, N, V >::_addConfig( CFG* config )
70 : {
71 235 : LBASSERT( config->getServer() == static_cast< S* >( this ));
72 235 : LBASSERT( lunchbox::find( _configs, config ) == _configs.end( ));
73 235 : _configs.push_back( config );
74 235 : }
75 :
76 : template< class CL, class S, class CFG, class NF, class N, class V >
77 430 : bool Server< CL, S, CFG, NF, N, V >::_removeConfig( CFG* config )
78 : {
79 430 : typename Configs::iterator i = lunchbox::find( _configs, config );
80 430 : if( i == _configs.end( ))
81 206 : return false;
82 :
83 224 : _configs.erase( i );
84 224 : return true;
85 : }
86 :
87 : namespace
88 : {
89 : template< class S, class V >
90 488 : VisitorResult _accept( S* server, V& visitor )
91 : {
92 488 : VisitorResult result = visitor.visitPre( server );
93 488 : if( result != TRAVERSE_CONTINUE )
94 0 : return result;
95 :
96 488 : const typename S::Configs& configs = server->getConfigs();
97 2742 : for( typename S::Configs::const_iterator i = configs.begin();
98 1828 : i != configs.end(); ++i )
99 : {
100 426 : switch( (*i)->accept( visitor ))
101 : {
102 : case TRAVERSE_TERMINATE:
103 0 : return TRAVERSE_TERMINATE;
104 :
105 : case TRAVERSE_PRUNE:
106 410 : result = TRAVERSE_PRUNE;
107 410 : break;
108 :
109 : case TRAVERSE_CONTINUE:
110 : default:
111 16 : break;
112 : }
113 : }
114 :
115 488 : 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 488 : break;
126 : }
127 :
128 488 : return result;
129 : }
130 : }
131 :
132 : template< class CL, class S, class CFG, class NF, class N, class V >
133 488 : VisitorResult Server< CL, S, CFG, NF, N, V >::accept( V& visitor )
134 : {
135 488 : 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 10 : Server< CL, S, CFG, NF, N, V >::_cmdCreateConfig( co::ICommand& command )
149 : {
150 10 : const co::ObjectVersion& configVersion = command.read< co::ObjectVersion >();
151 10 : const uint32_t requestID = command.read< uint32_t >();
152 :
153 10 : LBVERB << "Handle create config " << command << " config version "
154 0 : << configVersion << " request " << requestID << std::endl;
155 :
156 10 : CFG* config = _nodeFactory->createConfig( static_cast< S* >( this ));
157 10 : co::LocalNodePtr localNode = command.getLocalNode();
158 10 : 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 10 : co::Global::setIAttribute( co::Global::IATTR_ROBUSTNESS,
168 10 : config->getIAttribute( CFG::IATTR_ROBUSTNESS ));
169 10 : if( requestID != LB_UNDEFINED_UINT32 )
170 0 : config->send( command.getRemoteNode(), CMD_CONFIG_CREATE_REPLY )
171 0 : << requestID;
172 :
173 10 : return true;
174 : }
175 :
176 : template< class CL, class S, class CFG, class NF, class N, class V > bool
177 10 : Server< CL, S, CFG, NF, N, V >::_cmdDestroyConfig( co::ICommand& command )
178 : {
179 10 : LBVERB << "Handle destroy config " << command << std::endl;
180 :
181 10 : co::LocalNodePtr localNode = command.getLocalNode();
182 10 : const uint128_t& configID = command.read< uint128_t >();
183 10 : const uint32_t requestID = command.read< uint32_t >();
184 :
185 10 : CFG* config = 0;
186 30 : for( typename Configs::const_iterator i = _configs.begin();
187 20 : i != _configs.end(); ++i )
188 : {
189 10 : if( (*i)->getID() == configID )
190 : {
191 10 : config = *i;
192 10 : break;
193 : }
194 : }
195 10 : LBASSERT( config );
196 :
197 10 : localNode->unmapObject( config );
198 10 : _nodeFactory->releaseConfig( config );
199 :
200 10 : if( requestID != LB_UNDEFINED_UINT32 )
201 20 : command.getRemoteNode()->send( CMD_SERVER_DESTROY_CONFIG_REPLY )
202 20 : << requestID;
203 :
204 10 : return true;
205 : }
206 :
207 : template< class CL, class S, class CFG, class NF, class N, class V >
208 134 : std::ostream& operator << ( std::ostream& os,
209 : const Server< CL, S, CFG, NF, N, V >& server )
210 : {
211 134 : os << lunchbox::disableFlush << lunchbox::disableHeader << "server "
212 : << std::endl;
213 134 : os << "{" << std::endl << lunchbox::indent;
214 :
215 : const co::ConnectionDescriptions& cds =
216 134 : server.getConnectionDescriptions();
217 729 : for( co::ConnectionDescriptions::const_iterator i = cds.begin();
218 486 : i != cds.end(); ++i )
219 : {
220 109 : co::ConnectionDescriptionPtr desc = *i;
221 109 : os << *desc;
222 : }
223 :
224 134 : const std::vector< CFG* >& configs = server.getConfigs();
225 762 : for( typename std::vector< CFG* >::const_iterator i = configs.begin();
226 508 : i != configs.end(); ++i )
227 : {
228 120 : const CFG* config = *i;
229 120 : os << *config;
230 : }
231 :
232 268 : os << lunchbox::exdent << "}" << lunchbox::enableHeader
233 134 : << lunchbox::enableFlush << std::endl;
234 :
235 134 : return os;
236 : }
237 :
238 : }
239 : }
|