/** The main function for the background thread * * Loops until the forground thread requests it to stop. Reads data from the *network, * parses it and stores the resulting events (and other metadata) in a temporary * workspace. */ void ISISLiveEventDataListener::run() { try { if (!m_isConnected) // sanity check { throw std::runtime_error(std::string("No connection to the DAE.")); } TCPStreamEventDataNeutron events; while (!m_stopThread) { // get the header with the type of the packet Receive(events.head, "Events header", "Corrupt stream - you should reconnect."); if (!(events.head.type == TCPStreamEventHeader::Neutron)) { // don't know what to do with it - stop throw std::runtime_error("Unknown packet type."); } CollectJunk(events.head); // get the header with the sream size Receive(events.head_n, "Neutrons header", "Corrupt stream - you should reconnect."); CollectJunk(events.head_n); // absolute pulse (frame) time Mantid::Kernel::DateAndTime pulseTime = m_startTime + static_cast<double>(events.head_n.frame_time_zero); // Save the pulse charge in the logs double protons = static_cast<double>(events.head_n.protons); m_eventBuffer[0] ->mutableRun() .getTimeSeriesProperty<double>(PROTON_CHARGE_PROPERTY) ->addValue(pulseTime, protons); events.data.resize(events.head_n.nevents); uint32_t nread = 0; // receive the events while (nread < events.head_n.nevents) { int ntoread = m_socket.available() / static_cast<int>(sizeof(TCPStreamEventNeutron)); if (ntoread > static_cast<int>(events.head_n.nevents - nread)) { ntoread = static_cast<int>(events.head_n.nevents - nread); } if (ntoread > 0) { m_socket.receiveBytes( &(events.data[nread]), ntoread * static_cast<int>(sizeof(TCPStreamEventNeutron))); nread += ntoread; } else { Poco::Thread::sleep(RECV_WAIT); } } if (!events.isValid()) { throw std::runtime_error("corrupt stream - you should reconnect"); } // store the events saveEvents(events.data, pulseTime, events.head_n.period); } } catch (std::runtime_error & e) { // exception handler for generic runtime exceptions g_log.error() << "Caught a runtime exception." << std::endl << "Exception message: " << e.what() << std::endl; m_isConnected = false; m_backgroundException = boost::make_shared<std::runtime_error>(e); } catch (std::invalid_argument & e) { // TimeSeriesProperty (and possibly some other things) can // can throw these errors g_log.error() << "Caught an invalid argument exception." << std::endl << "Exception message: " << e.what() << std::endl; m_isConnected = false; std::string newMsg( "Invalid argument exception thrown from the background thread: "); newMsg += e.what(); m_backgroundException = boost::make_shared<std::runtime_error>(newMsg); } catch (...) { // Default exception handler g_log.error() << "Uncaught exception in ISISLiveEventDataListener network " "read thread." << std::endl; m_isConnected = false; m_backgroundException = boost::shared_ptr<std::runtime_error>( new std::runtime_error("Unknown error in backgound thread")); } }
/// connect to an event mode control progam and read live events int liveData(const std::string& host) { static char* junk_buffer[10000]; Poco::Net::StreamSocket s; Poco::UInt16 port = 10000; Poco::Net::SocketAddress address(host, port); s.connect(address); TCPStreamEventDataSetup setup; while( s.available() < static_cast<int>(sizeof(setup)) ) { Poco::Thread::sleep(1000); } s.receiveBytes(&setup, sizeof(setup)); if ( !setup.isValid() ) { throw std::runtime_error("version wrong"); } std::cerr << "run number " << setup.head_setup.run_number << std::endl; TCPStreamEventDataNeutron events; while(true) { while(s.available() < static_cast<int>(sizeof(events.head))) { Poco::Thread::sleep(100); } s.receiveBytes(&events.head, sizeof(events.head)); if ( !events.head.isValid() ) { throw std::runtime_error("corrupt stream - you should reconnect"); } if ( !(events.head.type == TCPStreamEventHeader::Neutron) ) { throw std::runtime_error("corrupt stream - you should reconnect"); } s.receiveBytes(junk_buffer, events.head.length - static_cast<uint32_t>(sizeof(events.head))); while(s.available() < static_cast<int>(sizeof(events.head_n))) { Poco::Thread::sleep(100); } s.receiveBytes(&events.head_n, sizeof(events.head_n)); if ( !events.head_n.isValid() ) { throw std::runtime_error("corrupt stream - you should reconnect"); } s.receiveBytes(junk_buffer, events.head_n.length - static_cast<uint32_t>(sizeof(events.head_n))); events.data.resize(events.head_n.nevents); uint32_t nread = 0; while( nread < events.head_n.nevents ) { uint32_t ntoread = static_cast<uint32_t>(s.available() / static_cast<int>(sizeof(TCPStreamEventNeutron))); if ( ntoread > (events.head_n.nevents - nread) ) { ntoread = events.head_n.nevents - nread; } if (ntoread > 0) { s.receiveBytes(&(events.data[nread]), ntoread * static_cast<int>(sizeof(TCPStreamEventNeutron))); nread += ntoread; } else { Poco::Thread::sleep(100); } } if (!events.isValid()) { throw std::runtime_error("corrupt stream - you should reconnect"); } //TCPStreamEventHeader& head = events.head; TCPStreamEventHeaderNeutron& head_n = events.head_n; std::cerr << "Read " << nread << " events for frame number " << head_n.frame_number << " time " << head_n.frame_time_zero << std::endl; for(int i=0; i<10; ++i) { std::cerr << events.data[i].time_of_flight << " " << events.data[i].spectrum << std::endl; } } s.close(); return 0; }