// InNetProducer.cc
// Contact person: P G Jones
// See InNetProducer.hh for more details.
//—————————————————————---------------------------------------------——//
#include
using namespace CLHEP;
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace RAT;
#include
#include
#include
#include
#include
using namespace std;
InNetProducer::InNetProducer()
{
fMainBlock = NULL;
Init();
}
InNetProducer::InNetProducer( ProcBlock* block )
{
SetMainBlock(block);
Init();
}
void InNetProducer::Init()
{
// Build commands
G4UIdirectory* innetDir = new G4UIdirectory( "/rat/innet/" );
innetDir->SetGuidance( "Read Events from ROOT file" );
fListenCmd = new G4UIcmdWithAnInteger("/rat/innet/listen", this);
fListenCmd->SetGuidance("port number to accept connections on");
fListenCmd->SetParameterName("port", false);
}
G4String
InNetProducer::GetCurrentValue( G4UIcommand* )
{
Log::Die( "InNetProducer::GetCurrentValue:invalid innet \"get\" command" );
return G4String( "You win! How did you manage to see this?." );
}
void InNetProducer::SetNewValue( G4UIcommand* command, G4String newValue )
{
if( command == fListenCmd )
{
const int port = G4UIcmdWithAnInteger::GetNewIntValue(newValue);
Listen( port );
}
Log::Die( "InNetProducer::SetNewValue: Invalid command" );
}
void
InNetProducer::Listen( const int port )
{
TServerSocket* server = new TServerSocket(port);
if( !server->IsValid() )
{
delete server;
Log::Die( "InNetProducer::Listen: Cannot open port." );
}
server->SetOption( kNoBlock, 1 );
TMonitor monitor;
list sockets;
bool error = false;
DS::Run* run = NULL;
long long defaultNumEvents = DB::Get()->GetLink( "IO" )->GetI( "default_num_events" );
long long nEntries; //number of entries to loop over
long long count = 0;
nEntries = defaultNumEvents;
while( !error && !SignalHandler::IsTermRequested() && count != nEntries)
{
++count;
TSocket* newSocket = server->Accept();
if( newSocket == NULL )
{
error = true;
continue;
}
else if( (void *)newSocket != (void *) -1 )
{
// -1 returned by Accept() if no new connection to accept
// BTW: Whoever thought that returning -1 in a pointer
// was an acceptable way to flag a special return condition
// should be flogged with the C++ standard.
sockets.push_back( newSocket );
monitor.Add( newSocket, TMonitor::kRead );
}
TSocket* socketWithData = monitor.Select( 50 /* wait up to 50 ms */ );
if( socketWithData != NULL && (void *) socketWithData != (void *) -1)
{
TMessage* msg;
Int_t readResult = socketWithData->Recv(msg);
if( readResult == 0 )
{
// Other side closed connection
warn << "innet: Host " << socketWithData->GetInetAddress().GetHostName() << " has disconnected\n";
monitor.Remove(socketWithData);
sockets.remove(socketWithData);
socketWithData->Close();
delete socketWithData;
}
else if( readResult == -1 )
error = true;
else if( readResult == -4 ) // Socket has no data to read. How'd this happen?
warn << "innet: Socket selected which has no data.\n";
else
{
DS::Entry* ds = dynamic_cast( msg->ReadObject( DS::Entry::Class() ) );
DS::Run* newRun = dynamic_cast( msg->ReadObject( DS::Run::Class() ) );
if( ds != NULL)
{
fMainBlock->DSEvent( *run, *ds );
delete ds;
}
else if( newRun != NULL )
{
if( run->GetRunID() == newRun->GetRunID() ) // Second receipt invokes EndOfRun
fMainBlock->EndOfRun( *run );
delete run;
run = newRun;
Producer::BeginOfRun( *run );
fMainBlock->BeginOfRun( *run );
}
else
error = true;
}
delete msg;
}
}
// Done, now free up sockets
std::list::iterator iSocket;
for (iSocket = sockets.begin(); iSocket != sockets.end(); ++iSocket)
delete *iSocket;
delete server;
}