Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

osg::ClusterServer Class Reference
[Cluster]

Cluster rendering server. More...

#include <OSGClusterServer.h>

List of all members.

Public Member Functions

Constructors
ClusterServer (WindowPtr window, const std::string &serviceName, const std::string &connectionType="StreamSock", const std::string &address="", UInt32 servicePort=8437, const std::string &serviceGroup="")
Destructor
*virtual ~ClusterServer (void)
server actions
*void start (void)
void stop (void)
void render (RenderActionBase *action)
void doSync (bool applyToChangelist)
void doRender (RenderActionBase *action)
void doSwap (void)
window access
*WindowPtr getClusterWindow (void)
WindowPtr getServerWindow (void)
RemoteAspectgetRemoteAspect (void) const
set
*void setInterface (const std::string &interf)

Protected Member Functions

ClusterWindow changed function
*bool windowChanged (FieldContainerPtr &fcp, RemoteAspect *)

Protected Attributes

Member
*WindowPtr _window
PointConnection_connection
std::string _requestAddress
std::string _boundAddress
ClusterWindowPtr _clusterWindow
RemoteAspect_aspect
std::string _serviceName
std::string _connectionType
UInt32 _servicePort
std::string _serviceGroup
UInt32 _serverId
std::string _interface

Private Member Functions

 ClusterServer (const ClusterServer &source)
 prohibit default function (move to 'public' if needed)
void operator= (const ClusterServer &source)
 prohibit default function (move to 'public' if needed)
helper function
*void acceptClient ()


Detailed Description

A ClusterServer is responsible for syncronizing all client changes. Each cluster renderer can offer it's service by a symbolic name. So it is possible to have a server called "left" or "right". The server uses a local Qt or GLUT window for rendering.
 // create a server
 GLUTWindowPtr window=GLUTWindowcreate();
 server = new ClusterServer(window,"server1","Multicast");
 // wait for clients to connect
 server->init();
 ...
 // render
 server->render(ract);
 

Definition at line 59 of file OSGClusterServer.h.


Constructor & Destructor Documentation

ClusterServer::ClusterServer WindowPtr  window,
const std::string &  serviceName,
const std::string &  connectionType = "StreamSock",
const std::string &  address = "",
UInt32  servicePort = 8437,
const std::string &  serviceGroup = ""
 

Constructor

Parameters:
window rendering window. e.g. a Qt or GLUT window
serviceName wait for connections that request this name
connectionType network type. e.g. "Multicast"
address address to wait for connections
servicePort port to wait for connections

Definition at line 88 of file OSGClusterServer.cpp.

References _requestAddress, and _serviceName.

00093                                                               :
00094     _window(window),
00095     _connection(NULL),
00096     _requestAddress(address),
00097     _boundAddress(""),
00098     _clusterWindow(),
00099     _aspect(NULL),
00100     _serviceName(serviceName),
00101     _connectionType(connectionType),
00102     _servicePort(servicePort),
00103     _serviceGroup(serviceGroup),
00104     _serverId(0),
00105     _interface("")
00106 {
00107     char localhost[256];
00108 
00109     // default is hostname
00110     if(_serviceName.empty())
00111     {
00112         gethostname(localhost,255);
00113         _serviceName = localhost;
00114     }
00115     // if service contains ":" than treat as address
00116     if(_requestAddress.empty())
00117     {
00118         if(strstr(_serviceName.c_str(),":"))
00119             _requestAddress = _serviceName;
00120     }
00121 }

ClusterServer::~ClusterServer void   )  [virtual]
 

Destructor. Disconnect from all connected rendering servers

Definition at line 128 of file OSGClusterServer.cpp.

References _aspect, and _connection.

00129 {
00130     try
00131     {
00132         if(_connection)
00133             delete _connection;
00134         if(_aspect)
00135             delete _aspect;
00136     }
00137     catch(...)
00138     {
00139     }
00140 }

osg::ClusterServer::ClusterServer const ClusterServer source  )  [private]
 


Member Function Documentation

void ClusterServer::start void   ) 
 

start server

Start cluster server and wait for a client to connect. This method will return after a client connection or an error situation.

Definition at line 151 of file OSGClusterServer.cpp.

References _aspect, _connection, acceptClient(), osg::BinaryDataHandler::flush(), osg::ClusterWindowBase::getClassType(), osg::BinaryDataHandler::getValue(), osg::osgTypedMethodFunctor2ObjPtrCPtrRef(), osg::BinaryDataHandler::putValue(), osg::RemoteAspect::registerChanged(), osg::Connection::selectChannel(), osg::BinaryDataHandler::setNetworkOrder(), and windowChanged().

00152 {
00153     OSG::FieldContainerType *fct;
00154 
00155     // reset conneciton
00156     if(_connection)
00157         delete _connection;
00158     _connection = NULL;
00159 
00160     // create aspect
00161     _aspect = new RemoteAspect();
00162 
00163     // register interrest for all changed cluster windows
00164     for(UInt32 i = 0; i < OSG::TypeFactory::the()->getNumTypes(); ++i)
00165     {
00166         fct=OSG::FieldContainerFactory::the()->findType(i);
00167         if(fct && fct->isDerivedFrom(ClusterWindow::getClassType()))
00168         {
00169             _aspect->registerChanged(
00170                 *fct,
00171                 osgTypedMethodFunctor2ObjPtrCPtrRef
00172                 <
00173                 bool,
00174                 ClusterServer,
00175                 FieldContainerPtr,
00176                 RemoteAspect     *
00177                 >(this,&ClusterServer::windowChanged));
00178         }
00179     }
00180     // accept incomming connections
00181     try {
00182         UInt8                    forceNetworkOrder;
00183 #if BYTE_ORDER == LITTLE_ENDIAN
00184         UInt8                    littleEndian = true;
00185 #else
00186         UInt8                    littleEndian = false;
00187 #endif
00188 
00189         // accept
00190         acceptClient();
00191         // determine network order
00192         _connection->putValue(littleEndian);
00193         _connection->flush();
00194         _connection->selectChannel();
00195         _connection->getValue(forceNetworkOrder);
00196         _connection->setNetworkOrder((forceNetworkOrder != 0));
00197     } 
00198     catch(...)
00199     {
00200         throw;
00201     }
00202 }

void ClusterServer::stop void   ) 
 

Stop cluster server, remove current remote aspect and all its field containers.

Definition at line 207 of file OSGClusterServer.cpp.

References _aspect, _clusterWindow, _connection, and osg::NullFC.

00208 {
00209     // get aspect ownership
00210     if(_clusterWindow != NullFC)
00211     {
00212         _aspect=_clusterWindow->getNetwork()->getAspect();
00213         _clusterWindow->getNetwork()->setAspect(NULL);
00214     }
00215     // destroy connection
00216     try
00217     {
00218         if(_connection)
00219             delete _connection;
00220         _connection = NULL;
00221     }
00222     catch(...)
00223     {
00224     }
00225     // destroy aspect
00226     if(_aspect)
00227         delete _aspect;
00228     // reset 
00229     _connection=NULL;
00230     _aspect=NULL;
00231     _clusterWindow=NullFC;
00232 }

void ClusterServer::render RenderActionBase action  ) 
 

sync with client and render scenegraph

Definition at line 236 of file OSGClusterServer.cpp.

References doRender(), doSwap(), and doSync().

00237 {
00238     doSync(false);
00239     doRender(action);
00240     doSwap();
00241 }

void ClusterServer::doSync bool  applyToChangelist  ) 
 

Synchronize all field containers with the client and call serverInit, serverRender and serverSwap for the cluster window. The cluster server uses the first synced ClusterWindow that contains the name of this server. serverInit is called after the first ClusterWindow sync.

todo: Sync RenderAciton contents

Definition at line 252 of file OSGClusterServer.cpp.

References _aspect, _clusterWindow, _connection, _serverId, _serviceName, _window, osg::NullFC, osg::RemoteAspect::receiveSync(), osg::SHLChunk::setClusterId(), and SINFO.

Referenced by render().

00253 {
00254     // do we have a cluster window?
00255     if(_clusterWindow==NullFC)
00256     {
00257         do
00258         {
00259             // recive 
00260             _aspect->receiveSync(*_connection,applyToChangelist);
00261         }
00262         while(_clusterWindow==NullFC);
00263         // get server id
00264         for(_serverId=0;
00265             _clusterWindow->getServers()[_serverId] != _serviceName &&
00266                 _serverId<_clusterWindow->getServers().size();
00267             _serverId++);
00268         // server connected and cluster window found
00269         SINFO << "Start server " << _serviceName 
00270               << " with id "     << _serverId 
00271               << std::endl;
00272         // now the window is responsible for connection and aspect
00273         _clusterWindow->getNetwork()->setMainConnection(_connection);
00274         _clusterWindow->getNetwork()->setAspect        (_aspect);
00275         _connection=NULL;
00276         _aspect=NULL;
00277         SHLChunk::setClusterId(Int32(_serverId));
00278         _clusterWindow->serverInit(_window,_serverId);
00279     }
00280 
00281     RemoteAspect *aspect=_clusterWindow->getNetwork()->getAspect();
00282     Connection   *connection=_clusterWindow->getNetwork()->getMainConnection();
00283 
00284     // sync with render clinet
00285     aspect->receiveSync(*connection,applyToChangelist);
00286 
00287     // sync with render client
00288     if(_clusterWindow->getInterleave())
00289     {
00290         // if the reminder of the division of interleave and 
00291         // framecount is equal to the servers id, the right
00292         // sync point for the current render frame is reached
00293         while( (_clusterWindow->getFrameCount()%
00294                 _clusterWindow->getInterleave())
00295                !=
00296                (_serverId%_clusterWindow->getInterleave()) ) 
00297         {
00298             aspect->receiveSync(*connection,applyToChangelist);
00299         }
00300     }
00301 }

void ClusterServer::doRender RenderActionBase action  ) 
 

render server window

Definition at line 305 of file OSGClusterServer.cpp.

References _clusterWindow, _serverId, and _window.

Referenced by render().

00306 {
00307     _clusterWindow->serverRender( _window,_serverId,action );
00308 }

void ClusterServer::doSwap void   ) 
 

swap server window

Definition at line 312 of file OSGClusterServer.cpp.

References _clusterWindow, _serverId, and _window.

Referenced by render().

00313 {
00314     _clusterWindow->serverSwap  ( _window,_serverId );
00315 }

WindowPtr ClusterServer::getClusterWindow void   ) 
 

return the cluster window received from the client

Definition at line 319 of file OSGClusterServer.cpp.

References _clusterWindow.

00320 {
00321     return _clusterWindow;
00322 }

WindowPtr ClusterServer::getServerWindow void   ) 
 

return the window used for rendering

Definition at line 326 of file OSGClusterServer.cpp.

References _window.

00327 {
00328     return _window;
00329 }

RemoteAspect * osg::ClusterServer::getRemoteAspect void   )  const [inline]
 

return the cluster window received from the client

Definition at line 46 of file OSGClusterServer.inl.

References _aspect.

00047 {
00048     return _aspect;
00049 }

void osg::ClusterServer::setInterface const std::string &  interf  )  [inline]
 

Definition at line 52 of file OSGClusterServer.inl.

References _interface.

00053 {
00054     _interface = interf;
00055 }

bool ClusterServer::windowChanged FieldContainerPtr fcp,
RemoteAspect
[protected]
 

clusterWindow changed callback. This is a callback functor. It is called for each change of a ClusterWindow.

Definition at line 334 of file OSGClusterServer.cpp.

References _clusterWindow, _serviceName, osg::AttachmentContainerPtr::dcast(), osg::NullFC, and SWARNING.

Referenced by start().

00336 {
00337     if(_clusterWindow != NullFC)
00338         return true;
00339 
00340     ClusterWindowPtr window=ClusterWindowPtr::dcast(fcp);
00341 
00342     if(window->getServers().size())
00343     {
00344         if(window->getServers().find(_serviceName) == 
00345            window->getServers().end())
00346         {
00347             SWARNING << "wrong window" << std::endl;
00348         }
00349         else
00350         {
00351             _clusterWindow=window;
00352         }
00353     }
00354     return true;
00355 }

void ClusterServer::acceptClient  )  [private]
 

Wait for incomming clients. A client can send a request for a special connection type or it can try to connect it it knows the servers address.

Definition at line 361 of file OSGClusterServer.cpp.

References _boundAddress, _connection, _connectionType, _interface, _requestAddress, _serviceGroup, _serviceName, _servicePort, osg::PointConnection::acceptGroup(), osg::SocketAddress::ANY, osg::Socket::bind(), osg::Connection::bind(), osg::BinaryMessage::clear(), osg::DgramSocket::close(), osg::ConnectionType::getName(), osg::BinaryMessage::getString(), osg::PointConnection::getType(), osg::SocketAddress::isMulticast(), osg::DgramSocket::join(), osg::DgramSocket::open(), osg::BinaryMessage::putString(), osg::DgramSocket::recvFrom(), osg::DgramSocket::sendTo(), osg::Connection::setInterface(), osg::Socket::setReusePort(), SINFO, SWARNING, osg::ConnectionFactory::the(), and osg::Socket::waitReadable().

Referenced by start().

00362 {
00363     BinaryMessage  msg;
00364     DgramSocket    serviceSock;
00365     SocketAddress  addr;
00366     std::string    service;
00367     std::string    connectionType;
00368     UInt32         readable;
00369     bool           connected=false;
00370     std::string    address;
00371     bool           bound = false;
00372 
00373     SINFO << "Waiting for request of "
00374           << _serviceName
00375           << std::endl;
00376 
00377     try
00378     {
00379         if(!_requestAddress.empty())
00380         {            
00381             // create connection
00382             _connection = ConnectionFactory::the().
00383                 createPoint(_connectionType);
00384             if(_connection)
00385             {
00386                 // set interface
00387                 _connection->setInterface(_interface);
00388                 // bind connection
00389                 try 
00390                 {
00391                     // bind to requested address
00392                     _boundAddress = _connection->bind(_requestAddress);
00393                     bound = true;
00394                 }
00395                 catch(...)
00396                 {
00397                     SINFO << "Unable to bind, use name as symbolic service name" 
00398                           << std::endl;
00399                 }
00400             }
00401         }
00402         serviceSock.open();
00403         serviceSock.setReusePort(true);
00404         // join to multicast group
00405         if(!_serviceGroup.empty())
00406         {
00407             SocketAddress groupAddress = SocketAddress(
00408                 _serviceGroup.c_str(),
00409                 _servicePort);
00410             if(groupAddress.isMulticast())
00411             {
00412                 SINFO << "wait for request on multicast:" << 
00413                     _serviceGroup << std::endl;
00414                 serviceSock.bind(SocketAddress(SocketAddress::ANY,
00415                                                _servicePort));
00416                 serviceSock.join(SocketAddress(groupAddress));
00417             }
00418             else
00419             {
00420                 SINFO << "wait for request by broadcast:" << 
00421                     _serviceGroup << std::endl;
00422                 serviceSock.bind(SocketAddress(groupAddress));
00423             }
00424         }
00425         else
00426         {
00427             SINFO << "wait for request by broadcast" << std::endl;
00428             serviceSock.bind(SocketAddress(SocketAddress::ANY,
00429                                            _servicePort));
00430         }
00431 
00432         while(!connected)
00433         {
00434             try
00435             {
00436                 if(_connection) 
00437                     readable = serviceSock.waitReadable(.01);
00438                 else
00439                     readable = true;
00440                 if(readable)
00441                 {
00442                     serviceSock.recvFrom(msg,addr);
00443 
00444                     service        = msg.getString();
00445                     connectionType = msg.getString();
00446 
00447                     SINFO << "Request for " 
00448                           << service << " " 
00449                           << connectionType 
00450                           << std::endl;
00451                     
00452                     if(service == _serviceName)
00453                     {
00454                         // remove old connection if typename missmaches
00455                         if(_connection && 
00456                            _connection->getType()->getName() != connectionType)
00457                         {
00458                             delete _connection;
00459                             _connection = NULL;
00460                         }
00461                         // try to create connection
00462                         if(!_connection)
00463                         {
00464                             // create connection
00465                             _connection = ConnectionFactory::the().
00466                                 createPoint(connectionType);
00467                             if(_connection)
00468                             {
00469                                 // set interface
00470                                 _connection->setInterface(_interface);
00471                                 // bind connection
00472                                 _boundAddress = _connection->bind(_requestAddress);
00473                                 bound = true;
00474                             } 
00475                             else
00476                             {
00477                                 SINFO << "Unknown connection type '" 
00478                                       << connectionType << "'" << std::endl;
00479                             }
00480                         }
00481                         if(_connection)
00482                         {
00483                             msg.clear    (             );
00484                             msg.putString(_serviceName );
00485                             msg.putString(_boundAddress);
00486                             serviceSock.sendTo(msg, addr);
00487                             SINFO << "Response " 
00488                                   << connectionType << ":"
00489                                   << _boundAddress 
00490                                   << std::endl;
00491                         }
00492                     }
00493                 }
00494             }
00495             catch(SocketConnReset &e)
00496             {
00497                 // ignore if there is a connection. This can happen, if
00498                 // a client has send a request. The server has send an
00499                 // answer meanwile the client has send a second request
00500                 // the client gets the answer to the first request and
00501                 // the server tries to send a second answer. The second
00502                 // answer can not be delivered because the client has
00503                 // closed its service port. This is a win-socket problem.
00504 
00505                 SWARNING << e.what() << std::endl;
00506 
00507                 // if there is no connection, then its a real problem
00508                 if(!_connection)
00509                     throw;
00510             }
00511             catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
00512             {
00513                 SWARNING << e.what() << std::endl;
00514             }
00515             try 
00516             {
00517                 // try to accept
00518                 if(bound && _connection && _connection->acceptGroup(0.2) >= 0)
00519                 {
00520                     connected = true;
00521                     SINFO << "Connection accepted " << _boundAddress << std::endl;
00522                 }
00523             }
00524             catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
00525             {
00526                 SWARNING << e.what() << std::endl;
00527             }
00528         }
00529         serviceSock.close();
00530     }
00531     catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
00532     {
00533         throw;
00534     }
00535 }

void osg::ClusterServer::operator= const ClusterServer source  )  [private]
 


Member Data Documentation

* WindowPtr osg::ClusterServer::_window [protected]
 

Definition at line 127 of file OSGClusterServer.h.

Referenced by doRender(), doSwap(), doSync(), and getServerWindow().

PointConnection* osg::ClusterServer::_connection [protected]
 

Definition at line 128 of file OSGClusterServer.h.

Referenced by acceptClient(), doSync(), start(), stop(), and ~ClusterServer().

std::string osg::ClusterServer::_requestAddress [protected]
 

Definition at line 129 of file OSGClusterServer.h.

Referenced by acceptClient(), and ClusterServer().

std::string osg::ClusterServer::_boundAddress [protected]
 

Definition at line 130 of file OSGClusterServer.h.

Referenced by acceptClient().

ClusterWindowPtr osg::ClusterServer::_clusterWindow [protected]
 

Definition at line 131 of file OSGClusterServer.h.

Referenced by doRender(), doSwap(), doSync(), getClusterWindow(), stop(), and windowChanged().

RemoteAspect* osg::ClusterServer::_aspect [protected]
 

Definition at line 132 of file OSGClusterServer.h.

Referenced by doSync(), getRemoteAspect(), start(), stop(), and ~ClusterServer().

std::string osg::ClusterServer::_serviceName [protected]
 

Definition at line 133 of file OSGClusterServer.h.

Referenced by acceptClient(), ClusterServer(), doSync(), and windowChanged().

std::string osg::ClusterServer::_connectionType [protected]
 

Definition at line 134 of file OSGClusterServer.h.

Referenced by acceptClient().

UInt32 osg::ClusterServer::_servicePort [protected]
 

Definition at line 135 of file OSGClusterServer.h.

Referenced by acceptClient().

std::string osg::ClusterServer::_serviceGroup [protected]
 

Definition at line 136 of file OSGClusterServer.h.

Referenced by acceptClient().

UInt32 osg::ClusterServer::_serverId [protected]
 

Definition at line 137 of file OSGClusterServer.h.

Referenced by doRender(), doSwap(), and doSync().

std::string osg::ClusterServer::_interface [protected]
 

Definition at line 138 of file OSGClusterServer.h.

Referenced by acceptClient(), and setInterface().


The documentation for this class was generated from the following files:
Generated on Thu Aug 25 04:13:03 2005 for OpenSG by  doxygen 1.4.3