// 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; }