1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000,2001,2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
47 #include "OSGClusterNetwork.h"
48 #include "OSGConnection.h"
49 #include "OSGConnectionFactory.h"
50 #include "OSGRemoteAspect.h"
54 /*! \class OSG::ClusterNetwork
55 \ingroup GrpSystemCluster
56 \brief Refcounted structure to hold all cluster connections
58 The ClusterNetwork holds all Connections between servers and client.
59 Main reason for this class is to enable cross-connections between
60 servers that are neccessary to implement e.g. Hybrid sort-first
62 This class is a container for all connections between cluster nodes.
63 The cluster network is not part of the cluster window or the cluster
64 server because it is used on the client and the server side and it
65 is accessable from all aspects.
66 If all connections are established, then getMainConnection provides
67 the connection from client to all servers. getConnection(n) is the
68 connection to the server with id n. If n is the current server id
69 then this connection is connected to all other servers.
72 /*-------------------------------------------------------------------------*/
75 /*! Constructor documentation
77 ClusterNetwork::ClusterNetwork(UInt32 id
) :
80 _mainConnection(NULL
),
86 /*-------------------------------------------------------------------------*/
89 /*! Destructor documentation
92 ClusterNetwork::~ClusterNetwork(void)
98 delete _mainConnection
;
100 _mainConnection
= NULL
;
102 for(ConnectionsT::iterator c
= _connection
.begin();
103 c
!= _connection
.end ();
113 ConnectionInfoMapT::iterator ci
= _map
.find(_id
);
121 /*-------------------------------------------------------------------------*/
124 /*! get main connection. The main connection is used to sync
128 Connection
*ClusterNetwork::getMainConnection(void)
130 return _mainConnection
;
133 /*! get main connection as group connection. If main connection
134 is a point connection, then NULL is returned
137 GroupConnection
*ClusterNetwork::getMainGroupConnection(void)
139 return dynamic_cast<GroupConnection
*>(_mainConnection
);
142 /*! get main connection as point connection. If main connection
143 is a group connection, then NULL is returned
146 PointConnection
*ClusterNetwork::getMainPointConnection(void)
148 return dynamic_cast<PointConnection
*>(_mainConnection
);
151 /*! get connection with the given id
154 Connection
*ClusterNetwork::getConnection(UInt32 id
)
156 if(id
<_connection
.size())
158 return _connection
[id
];
166 /*! get connection as group connection. If main connection
167 is a point connection, then NULL is returned
170 GroupConnection
*ClusterNetwork::getGroupConnection(UInt32 id
)
172 return dynamic_cast<GroupConnection
*>(getConnection(id
));
175 /*! get main connection as point connection. If main connection
176 is a group connection, then NULL is returned
179 PointConnection
*ClusterNetwork::getPointConnection(UInt32 id
)
181 return dynamic_cast<PointConnection
*>(getConnection(id
));
184 /*! get remote aspect
187 RemoteAspect
*ClusterNetwork::getAspect(void)
192 ClusterNetwork::ConnectionsT
&ClusterNetwork::getConnection(void)
197 /*-------------------------------------------------------------------------*/
200 /*! Set remote Aspect
203 void ClusterNetwork::setAspect(RemoteAspect
*aspect
)
208 /*! Set main connection. This is the connection for aspect sync
211 void ClusterNetwork::setMainConnection(Connection
*connection
)
213 _mainConnection
=connection
;
219 void ClusterNetwork::setConnection(UInt32 id
,Connection
*connection
)
221 if(id
>= _connection
.size())
223 _connection
.resize(id
+ 1, NULL
);
226 _connection
[id
] = connection
;
229 /*-------------------------------------------------------------------------*/
230 /* establish connection */
232 /*! crossconnect servers and the client.
234 * Each Server is connected with all other servers with a point to
235 * point connection. Thre connection number N is used to read from
236 * node N and to write to node N. If N is equal to the servers id
237 * then the connection is used to exchange data with the client.
238 * The client gathers all connections in a GroupConnection. So all
239 * Server-Server communication is done with point to point connections
240 * and if N=server id then a point to group connection is used to
241 * communicate with the client.
243 void ClusterNetwork::connectAllPointToPoint(
245 const std::string
&connectionType
)
250 std::map
<UInt32
,std::string
> address
;
251 std::vector
<UInt32
> fromId
;
252 std::vector
<UInt32
> toId
;
253 std::vector
<std::string
> toAddr
;
255 Connection::Channel channel
;
256 std::string clientAddress
;
258 // determine if this is a server
259 if(dynamic_cast<GroupConnection
*>(_mainConnection
))
268 // communicate server count
271 servers
= getMainGroupConnection()->getChannelCount();
273 _mainConnection
->putValue(servers
);
274 _mainConnection
->flush();
278 _mainConnection
->getValue(servers
);
281 addrCount
= (servers
+ 1) * servers
/ 2;
283 fromId
.resize(addrCount
);
284 toId
.resize (addrCount
);
285 toAddr
.resize(addrCount
);
287 _connection
.resize(servers
+ 1);
288 // send all addresses
290 for(id
= 0; id
<= servers
; ++id
)
292 if(isClient
&& id
== thisId
)
295 ConnectionFactory::the()->createGroup(connectionType
);
300 ConnectionFactory::the()->createPoint(connectionType
);
305 _mainConnection
->putValue(id
);
306 _mainConnection
->putValue(thisId
);
307 _mainConnection
->putValue(_connection
[id
]->bind());
308 _mainConnection
->flush();
311 // read and retransmit all addresses
314 for(c
= 0 ; c
< addrCount
; ++c
)
316 channel
= getMainGroupConnection()->selectChannel();
318 getMainGroupConnection()->getValue(fromId
[c
]);
319 getMainGroupConnection()->getValue(toId
[c
]);
320 getMainGroupConnection()->getValue(toAddr
[c
]);
322 // remember client to server
323 if(fromId
[c
] == thisId
)
325 address
[toId
[c
]] = toAddr
[c
];
326 getMainGroupConnection()->subSelection(channel
);
330 getMainGroupConnection()->resetSelection();
332 for(c
= 0 ; c
< addrCount
; ++c
)
334 _mainConnection
->putValue(fromId
[c
]);
335 _mainConnection
->putValue(toId
[c
]);
336 _mainConnection
->putValue(toAddr
[c
]);
339 _mainConnection
->flush();
342 // receive all addresses
345 _mainConnection
->selectChannel();
347 for(c
= 0 ; c
< (servers
+1) * servers
/ 2 ; ++c
)
349 _mainConnection
->getValue(fromId
[c
]);
350 _mainConnection
->getValue(toId
[c
]);
351 _mainConnection
->getValue(toAddr
[c
]);
353 if(fromId
[c
] == thisId
)
354 address
[toId
[c
]] = toAddr
[c
];
358 for(id
= 0; id
<= servers
; ++id
)
362 _connection
[id
]->acceptPoint();
371 _connection
[id
]->connectPoint(address
[id
]);
382 // connect all servers with the client.
385 _mainConnection
->putValue(_connection
[thisId
]->bind());
386 _mainConnection
->flush();
388 for(id
=0 ; id
< servers
; ++id
)
390 getGroupConnection(thisId
)->acceptPoint();
395 _mainConnection
->getValue(clientAddress
);
401 getPointConnection(thisId
)->connectGroup(clientAddress
);
411 /*! crossconnect servers and the client.
413 * Each server is connected over a GroupConnection with all other
414 * servers. Connection N is used to read and write to the server
415 * with id N. If N is equal to the current server id, then write
416 * operations are passed to all other servers and read collects
417 * data from all other servers. The client connection is stored
418 * in the index equal to the number of servers.
422 void ClusterNetwork::connectAllGroupToPoint(
424 const std::string
&connectionType
)
429 std::map
<UInt32
,std::string
> address
;
430 Connection::Channel channel
;
431 std::string groupAddress
;
433 // determine if this is a server
434 if(dynamic_cast<GroupConnection
*>(_mainConnection
))
443 // communicate server count
446 servers
= getMainGroupConnection()->getChannelCount();
447 _mainConnection
->putValue(servers
);
448 _mainConnection
->flush();
452 _mainConnection
->getValue(servers
);
455 // create all connections
456 _connection
.resize(servers
+1);
457 for(id
= 0; id
<= servers
; ++id
)
462 ConnectionFactory::the()->createGroup(connectionType
);
464 groupAddress
= _connection
[id
]->bind();
469 ConnectionFactory::the()->createPoint(connectionType
);
475 address
[thisId
] = groupAddress
;
477 while(getMainGroupConnection()->getSelectionCount())
479 channel
= _mainConnection
->selectChannel();
480 getMainGroupConnection()->subSelection(channel
);
481 getMainGroupConnection()->getValue(groupAddress
);
483 address
[channel
] = groupAddress
;
486 getMainGroupConnection()->resetSelection();
488 for(id
= 0; id
<= servers
; ++id
)
490 _mainConnection
->putValue(address
[id
]);
493 _mainConnection
->flush();
497 _mainConnection
->putValue(groupAddress
);
498 _mainConnection
->flush();
500 for(id
= 0; id
<= servers
; ++id
)
502 _mainConnection
->getValue(groupAddress
);
503 address
[id
] = groupAddress
;
507 for(id
= 1; id
<= servers
; ++id
)
509 toId
= (thisId
+id
)%(servers
+1);
513 getGroupConnection(thisId
)->acceptPoint();
514 getPointConnection(toId
)->connectGroup(address
[toId
]);
518 getPointConnection(toId
)->connectGroup(address
[toId
]);
519 getGroupConnection(thisId
)->acceptPoint();
524 /*-------------------------------------------------------------------------*/
527 /*! Get an instance of the ClusterNetwork with the given container id
529 ClusterNetwork
*ClusterNetwork::getInstance(UInt32 clusterWindowId
)
531 ConnectionInfoMapT::iterator ci
=_map
.find(clusterWindowId
);
534 ClusterNetwork
*ciP
= new ClusterNetwork(clusterWindowId
);
535 _map
[clusterWindowId
]=ciP
;
544 /*-------------------------------------------------------------------------*/
545 /* static elements */
547 ClusterNetwork::ConnectionInfoMapT
ClusterNetwork::_map
;