| 1 |
#include <OSGConfig.h> |
|---|
| 2 |
|
|---|
| 3 |
using namespace OSG; |
|---|
| 4 |
|
|---|
| 5 |
/*! \page PageBaseConnection Connection |
|---|
| 6 |
|
|---|
| 7 |
\section BaseConnectionOverview Overview |
|---|
| 8 |
|
|---|
| 9 |
Connections are used to provide an abstract kommunikation layer for the |
|---|
| 10 |
communication in a cluster system. The abstract framework provides functions |
|---|
| 11 |
for architecture independen encoding, unicasting, multicast and |
|---|
| 12 |
synchronisation. A concrete hardware is choosen by creating concrete |
|---|
| 13 |
instances of connections through a connection factory. New hardware can be |
|---|
| 14 |
integrated by adding new connection types to the factory. Currentliy there is |
|---|
| 15 |
support for the following ethernet communication models. |
|---|
| 16 |
|
|---|
| 17 |
* Ethernet Multicast |
|---|
| 18 |
* Stream Sockets |
|---|
| 19 |
* pipelined Stream Sockets |
|---|
| 20 |
|
|---|
| 21 |
If somebody has access to infiniband or myrinet, it would be great to have |
|---|
| 22 |
support for this networks. |
|---|
| 23 |
|
|---|
| 24 |
In a cluster system often a huge amount of data has to be sent to a lot of |
|---|
| 25 |
receivers. For example in OpenSG the change list has to be sent to all |
|---|
| 26 |
rendering nodes in each frame. As there is a wide variety to do this best |
|---|
| 27 |
with different networks, there is a special connection type that encapsulates |
|---|
| 28 |
multipoint and single point connections. |
|---|
| 29 |
|
|---|
| 30 |
Communication is the most critical point in clustering. This the |
|---|
| 31 |
communication overhead has to be as small as possible. Because of this we do |
|---|
| 32 |
no special encoding to guarantee that a receiver gets the data it expects. |
|---|
| 33 |
For example if a sender sends Real32 values and a receiver reads Int32 |
|---|
| 34 |
values, this will not be detected by any mechanism of the communication |
|---|
| 35 |
framework. So if you send data over a connection, the receiver must exactly |
|---|
| 36 |
know how many data it has to read and in wich type the data is encoded. This |
|---|
| 37 |
makes debugging of communications sometimes very difficult but the advantage |
|---|
| 38 |
is that the available bandwidth is fully available for the data transfer. |
|---|
| 39 |
|
|---|
| 40 |
There are two types of connections. A PointConnection is used to send and |
|---|
| 41 |
receive with one communication endpoint. A GroupConnection is used to send |
|---|
| 42 |
and receive from one or more communication endpoints. GroupConnections can be |
|---|
| 43 |
used to multicast data simultaniously to many destinations. It is possible to |
|---|
| 44 |
communicate between two PointConnections and between a GroupConnection and |
|---|
| 45 |
many PointConnections. |
|---|
| 46 |
|
|---|
| 47 |
\section BaseConnectionCreate Creating connections |
|---|
| 48 |
|
|---|
| 49 |
A connection is created by the ConnectionFactory or by instanciating |
|---|
| 50 |
concrete connection types. If the factory is used, then the type of |
|---|
| 51 |
connection can be configured at runtime. Connections can be destroied |
|---|
| 52 |
with the delete command. |
|---|
| 53 |
|
|---|
| 54 |
\code |
|---|
| 55 |
GroupConnection *group = ConnectionFactory::the().createGroup("Multicast"); |
|---|
| 56 |
PointConnection *point = ConnectionFactory::the().createPoint("Multicast"); |
|---|
| 57 |
PointConnection *group = new GroupSockConnection(); |
|---|
| 58 |
PointConnection *point = new PointSockConnection(); |
|---|
| 59 |
\endcode |
|---|
| 60 |
|
|---|
| 61 |
\section BaseConnectionConnect Connecting |
|---|
| 62 |
|
|---|
| 63 |
A connection is established with the connectPoint and connectGroup |
|---|
| 64 |
method. This methos has two parameters. First is the address that identifies |
|---|
| 65 |
the destination. The syntax of the addresse depends on the type of a |
|---|
| 66 |
connection. Multicast, StreamSock and SockPipeline are using the format |
|---|
| 67 |
host::port. |
|---|
| 68 |
|
|---|
| 69 |
Connecting two PointConnections: |
|---|
| 70 |
\code |
|---|
| 71 |
// Host 1 |
|---|
| 72 |
Connection::Channel c = point.connectPoint("196.168.1.22:1234"); |
|---|
| 73 |
if(c < 0) |
|---|
| 74 |
return -1; |
|---|
| 75 |
|
|---|
| 76 |
// Host 2 |
|---|
| 77 |
point.bind(":1234"); |
|---|
| 78 |
Connection::Channel c = point.acceptPoint(); |
|---|
| 79 |
if(c < 0) |
|---|
| 80 |
return -1; |
|---|
| 81 |
|
|---|
| 82 |
\endcode |
|---|
| 83 |
|
|---|
| 84 |
Connecting tree PointConnections with one GroupConnection |
|---|
| 85 |
\code |
|---|
| 86 |
// Host 1 |
|---|
| 87 |
if(point.connectGroup("196.168.1.22:1234") < 0) |
|---|
| 88 |
return -1; |
|---|
| 89 |
|
|---|
| 90 |
// Host 2 |
|---|
| 91 |
if(point.connectGroup("196.168.1.22:1234") < 0) |
|---|
| 92 |
return -1; |
|---|
| 93 |
|
|---|
| 94 |
// Host 3 |
|---|
| 95 |
if(point.connectGroup("196.168.1.22:1234") < 0) |
|---|
| 96 |
return -1; |
|---|
| 97 |
|
|---|
| 98 |
// Host 4 |
|---|
| 99 |
point.bind(":1234"); |
|---|
| 100 |
Connection::Channel c; |
|---|
| 101 |
if(point.acceptPoint() < 0) |
|---|
| 102 |
return -1 |
|---|
| 103 |
if(point.acceptPoint() < 0) |
|---|
| 104 |
return -1 |
|---|
| 105 |
if(point.acceptPoint() < 0) |
|---|
| 106 |
return -1 |
|---|
| 107 |
\endcode |
|---|
| 108 |
|
|---|
| 109 |
Connecting one GroupConnection with tree PointConnections |
|---|
| 110 |
\code |
|---|
| 111 |
// Host 1 |
|---|
| 112 |
point.bind(":1234"); |
|---|
| 113 |
if(point.acceptGroup() < 0) |
|---|
| 114 |
return -1; |
|---|
| 115 |
|
|---|
| 116 |
// Host 2 |
|---|
| 117 |
point.bind(":1234"); |
|---|
| 118 |
if(point.acceptGroup() < 0) |
|---|
| 119 |
return -1; |
|---|
| 120 |
|
|---|
| 121 |
// Host 3 |
|---|
| 122 |
point.bind(":1234"); |
|---|
| 123 |
if(point.acceptGroup() < 0) |
|---|
| 124 |
return -1; |
|---|
| 125 |
|
|---|
| 126 |
// Host 4 |
|---|
| 127 |
point.bind(":1234"); |
|---|
| 128 |
Connection::Channel c; |
|---|
| 129 |
// wait a maximum of 40 seconds for each connection |
|---|
| 130 |
if(point.connectPoint("196.168.1.30:1234",40) < 0) |
|---|
| 131 |
return -1 |
|---|
| 132 |
if(point.connectPoint("196.168.1.31:1234",40) < 0) |
|---|
| 133 |
return -1 |
|---|
| 134 |
if(point.connectPoint("196.168.1.32:1234",40) < 0) |
|---|
| 135 |
return -1 |
|---|
| 136 |
\endcode |
|---|
| 137 |
|
|---|
| 138 |
All methods that establish a connection return a Channel id or -1 on |
|---|
| 139 |
error. Channel ids can be used in GroupConnections to distinguish incomming |
|---|
| 140 |
messages. |
|---|
| 141 |
|
|---|
| 142 |
\section BaseConnectionData Data transmission |
|---|
| 143 |
|
|---|
| 144 |
Data is transferred with putValue and getValue. Per default data is buffered |
|---|
| 145 |
and will be sent if the buffer is full or the flush method is called. As a |
|---|
| 146 |
connection can be connected to more then one endpoint, a source has to be |
|---|
| 147 |
selected with selectChannel. After a channel is selected, only data from this |
|---|
| 148 |
channel is processed by getValue and getValues. |
|---|
| 149 |
|
|---|
| 150 |
\code |
|---|
| 151 |
UInt32 count; |
|---|
| 152 |
Real32 values[100]; |
|---|
| 153 |
|
|---|
| 154 |
connection->putValue(count); |
|---|
| 155 |
connection->putValues(values,100); |
|---|
| 156 |
connection->flush(); |
|---|
| 157 |
.. |
|---|
| 158 |
connection->selectChannel(); |
|---|
| 159 |
connection->getValue(count); |
|---|
| 160 |
connection->getValues(values,100); |
|---|
| 161 |
\endcode |
|---|
| 162 |
|
|---|
| 163 |
putValue, putValues, getValue and getValues are doing a network byte order |
|---|
| 164 |
encoding if both endpoints are based on different architectures. This can be |
|---|
| 165 |
switched off if a homogenious cluster is used. |
|---|
| 166 |
|
|---|
| 167 |
\code |
|---|
| 168 |
connection->setNetworkOrder(false); |
|---|
| 169 |
\endcode |
|---|
| 170 |
|
|---|
| 171 |
By default a connection tries to minimize the number of data that is |
|---|
| 172 |
copyied. To do this, for lage memory blocks only a tag is written in the |
|---|
| 173 |
output buffer. If the buffer is full or flush is called, then first the |
|---|
| 174 |
buffer is send and afterwards the large memory blocks. Thise technique |
|---|
| 175 |
provides buffering for mall data blocks and unbufferd transmission for large |
|---|
| 176 |
blocks. This is very efficient and works fine as long as the data is not |
|---|
| 177 |
modified between putValue and the actual data transmission. If this can not |
|---|
| 178 |
be guaranteed, then a copy operation can be forced. This option must be set |
|---|
| 179 |
by both communication endpoints. |
|---|
| 180 |
|
|---|
| 181 |
\code |
|---|
| 182 |
connection->forceCopy(); |
|---|
| 183 |
\endcode |
|---|
| 184 |
|
|---|
| 185 |
In forceCopy mode the whole data is bufferd. In contrast an unbuffered mode |
|---|
| 186 |
can be enabled with forceDirectIO method. |
|---|
| 187 |
|
|---|
| 188 |
\code |
|---|
| 189 |
connection->forceDirectIO(); |
|---|
| 190 |
\endcode |
|---|
| 191 |
|
|---|
| 192 |
It is not possible to change the transmission mode for connected Connections. |
|---|
| 193 |
|
|---|
| 194 |
\section BaseConnectionReadMany Reading from many sources |
|---|
| 195 |
|
|---|
| 196 |
Sometimes it is important to read some data exactly once from each endpoint |
|---|
| 197 |
of a GroupConnection. To do this a selection mechanism is available. |
|---|
| 198 |
|
|---|
| 199 |
\code |
|---|
| 200 |
Connection::Channel channel; |
|---|
| 201 |
while(group->getSelectionCount() > 0) |
|---|
| 202 |
{ |
|---|
| 203 |
channel = mConnection->selectChannel(); |
|---|
| 204 |
group->getValue(result); // Getting data |
|---|
| 205 |
group->subSelection(channel); |
|---|
| 206 |
} |
|---|
| 207 |
mConnection->resetSelection(); |
|---|
| 208 |
\endcode |
|---|
| 209 |
|
|---|
| 210 |
\section BaseConnectionSync Synchronisation |
|---|
| 211 |
|
|---|
| 212 |
In a cluster environment it is often neccessary to synchronize two ore more |
|---|
| 213 |
nodes. To do this sync and wait operations are available. |
|---|
| 214 |
|
|---|
| 215 |
\code |
|---|
| 216 |
// Host 1 |
|---|
| 217 |
point->wait(); |
|---|
| 218 |
|
|---|
| 219 |
// Host 2 |
|---|
| 220 |
point->wait(); |
|---|
| 221 |
|
|---|
| 222 |
// Host 3 |
|---|
| 223 |
point->wait(); |
|---|
| 224 |
|
|---|
| 225 |
// Host 4 |
|---|
| 226 |
group->signal(); |
|---|
| 227 |
\endcode |
|---|
| 228 |
|
|---|
| 229 |
|
|---|
| 230 |
\section BaseConnectionInterface Selecting an Interface |
|---|
| 231 |
|
|---|
| 232 |
The bind method of a connection binds a connection to a hardware ressource. |
|---|
| 233 |
If more then one ressource is available, then you have to define the |
|---|
| 234 |
interface on which incomming connections are expected. This is done mit the |
|---|
| 235 |
interface mothod. |
|---|
| 236 |
|
|---|
| 237 |
\code |
|---|
| 238 |
connectionA->setInterface("196.168.10.22"); |
|---|
| 239 |
connectionB->setInterface("134.213.21.11"); |
|---|
| 240 |
|
|---|
| 241 |
// accept from network 1 |
|---|
| 242 |
connectionA->bind(":1234"); |
|---|
| 243 |
connectionA->accept(); |
|---|
| 244 |
|
|---|
| 245 |
// accept from network 2 |
|---|
| 246 |
connectionB->bind(":1234"); |
|---|
| 247 |
connectionB->accept(); |
|---|
| 248 |
\endcode |
|---|
| 249 |
|
|---|
| 250 |
\section BaseConnectionDestination Setting the Multicast address |
|---|
| 251 |
|
|---|
| 252 |
If a group connection is based on a hardware that is able to do multicast, |
|---|
| 253 |
then the destination address is used to selection a multicast channel of the |
|---|
| 254 |
network layer. For ethernet this is the multicast address. |
|---|
| 255 |
|
|---|
| 256 |
\code |
|---|
| 257 |
group->setDestination("237.32.12.22"); |
|---|
| 258 |
group->bind(":4432") |
|---|
| 259 |
if(group->acceptPoint() < 0) |
|---|
| 260 |
return -1; |
|---|
| 261 |
\endcode |
|---|
| 262 |
|
|---|
| 263 |
*/ |
|---|