void CompoundUpdateInputVisitor::_updateQueues( const Compound* compound ) { const TileQueues& inputQueues = compound->getInputTileQueues(); for( TileQueuesCIter i = inputQueues.begin(); i != inputQueues.end(); ++i ) { //----- Find corresponding output queue TileQueue* queue = *i; const std::string& name = queue->getName(); Compound::TileQueueMap::const_iterator j = _outputQueues.find( name ); if( j == _outputQueues.end( )) { LBVERB << "Can't find matching output queue, ignoring input queue " << name << std::endl; queue->unsetData(); continue; } LBASSERT( queue->isAttached( )); TileQueue* outputQueue = j->second; queue->setOutputQueue( outputQueue, compound ); } }
void CompoundUpdateOutputVisitor::_updateQueues(Compound* compound) { const TileQueues& queues = compound->getOutputTileQueues(); for (TileQueuesCIter i = queues.begin(); i != queues.end(); ++i) { //----- Check uniqueness of output queue name TileQueue* queue = *i; const std::string& name = queue->getName(); if (_outputTileQueues.find(name) != _outputTileQueues.end()) { LBWARN << "Multiple output queues of the same name are unsupported" << ", ignoring output queue " << name << std::endl; queue->unsetData(); continue; } queue->cycleData(_frameNumber, compound); //----- Generate tile task commands _generateWorkItems(queue, compound); _outputTileQueues[name] = queue; } }
void run() override { #ifdef __linux if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("lokit_connection"), 0, 0, 0) != 0) std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl; #endif try { // Open websocket connection between the child process and the // parent. The parent forwards us requests that it can't handle. HTTPClientSession cs("127.0.0.1", MASTER_PORT_NUMBER); cs.setTimeout(0); HTTPRequest request(HTTPRequest::HTTP_GET, CHILD_URI); HTTPResponse response; std::shared_ptr<WebSocket> ws(new WebSocket(cs, request, response)); _session.reset(new ChildProcessSession(ws, _loKit, _loKitDocument, std::to_string(_childId))); //std::shared_ptr<ChildProcessSession> session(new ChildProcessSession(ws, _loKit, _loKitDocument)); ws->setReceiveTimeout(0); // child Jail TID PID std::string hello("child " + std::to_string(_childId) + " " + _threadId + " " + std::to_string(Process::id())); _session->sendTextFrame(hello); TileQueue queue; Thread queueHandlerThread; QueueHandler handler(queue); handler.setSession(_session); queueHandlerThread.start(handler); int flags; int n; do { char buffer[1024]; n = ws->receiveFrame(buffer, sizeof(buffer), flags); if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE) { std::string firstLine = getFirstLine(buffer, n); StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); // The only kind of messages a child process receives are the single-line ones (?) assert(firstLine.size() == static_cast<std::string::size_type>(n)); queue.put(firstLine); } } while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE); queue.clear(); queue.put("eof"); queueHandlerThread.join(); } catch (Exception& exc) { std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl; } catch (std::exception& exc) { std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl; } }
void CompoundUpdateOutputVisitor::_updateOutput( Compound* compound ) { const Channel* channel = compound->getChannel(); const TileQueues& outputQueues = compound->getOutputTileQueues(); for( TileQueuesCIter i = outputQueues.begin(); i != outputQueues.end(); ++i ) { //----- Check uniqueness of output queue name TileQueue* queue = *i; const std::string& name = queue->getName(); if( _outputTileQueues.find( name ) != _outputTileQueues.end()) { LBWARN << "Multiple output queues of the same name are unsupported" << ", ignoring output queue " << name << std::endl; queue->unsetData(); continue; } queue->cycleData( _frameNumber, compound ); //----- Generate tile task packets _generateTiles( queue, compound ); _outputTileQueues[name] = queue; } if( !compound->testInheritTask( fabric::TASK_READBACK ) || !channel ) return; const Frames& outputFrames = compound->getOutputFrames(); if( outputFrames.empty( )) { compound->unsetInheritTask( fabric::TASK_READBACK ); return; } for( Frames::const_iterator i = outputFrames.begin(); i != outputFrames.end(); ++i ) { //----- Check uniqueness of output frame name Frame* frame = *i; const std::string& name = frame->getName(); if( _outputFrames.find( name ) != _outputFrames.end()) { LBWARN << "Multiple output frames of the same name are unsupported" << ", ignoring output frame " << name << std::endl; frame->unsetData(); continue; } //----- compute readback area const Viewport& frameVP = frame->getViewport(); const PixelViewport& inheritPVP = compound->getInheritPixelViewport(); PixelViewport framePVP( inheritPVP ); framePVP.apply( frameVP ); if( !framePVP.hasArea( )) // output frame has no pixels { LBINFO << "Skipping output frame " << name << ", no pixels" << std::endl; frame->unsetData(); continue; } //----- Create new frame datas // one frame data used for each eye pass // data is set only on master frame data (will copy to all others) frame->cycleData( _frameNumber, compound ); FrameData* frameData = frame->getMasterData(); LBASSERT( frameData ); LBLOG( LOG_ASSEMBLY ) << lunchbox::disableFlush << "Output frame \"" << name << "\" id " << frame->getID() << " v" << frame->getVersion()+1 << " data id " << frameData->getID() << " v" << frameData->getVersion() + 1 << " on channel \"" << channel->getName() << "\" tile pos " << framePVP.x << ", " << framePVP.y; //----- Set frame data parameters: // 1) offset is position wrt destination view const bool usesTiles = !compound->getInputTileQueues().empty(); frameData->setOffset( usesTiles ? Vector2i( 0 , 0 ) : Vector2i( framePVP.x, framePVP.y ) ); // 2) pvp is area within channel framePVP.x = static_cast< int32_t >( frameVP.x * inheritPVP.w ); framePVP.y = static_cast< int32_t >( frameVP.y * inheritPVP.h ); frameData->setPixelViewport( framePVP ); // 3) image buffers and storage type uint32_t buffers = frame->getBuffers(); frameData->setType( frame->getType() ); frameData->setBuffers( buffers == eq::Frame::BUFFER_UNDEFINED ? compound->getInheritBuffers() : buffers ); // 4) (source) render context frameData->setRange( compound->getInheritRange( )); frameData->setPixel( compound->getInheritPixel( )); frameData->setSubPixel( compound->getInheritSubPixel( )); frameData->setPeriod( compound->getInheritPeriod( )); frameData->setPhase( compound->getInheritPhase( )); //----- Set frame parameters: // 1) offset is position wrt window, i.e., the channel position if( compound->getInheritChannel() == channel ) frame->setOffset( Vector2i( inheritPVP.x, inheritPVP.y )); else { const PixelViewport& nativePVP = channel->getPixelViewport(); frame->setOffset( Vector2i( nativePVP.x, nativePVP.y )); } // 2) zoom _updateZoom( compound, frame ); //----- Commit frame->commitData(); _outputFrames[name] = frame; LBLOG( LOG_ASSEMBLY ) << " buffers " << frameData->getBuffers() << " read area " << framePVP << " readback " << frame->getZoom() << " assemble " << frameData->getZoom()<< lunchbox::enableFlush << std::endl ; } }
void run() override { static const std::string thread_name = "kit_ws_" + _sessionId; #ifdef __linux if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(thread_name.c_str()), 0, 0, 0) != 0) Log::error("Cannot set thread name to " + thread_name + "."); #endif Log::debug("Thread [" + thread_name + "] started."); try { // Open websocket connection between the child process and the // parent. The parent forwards us requests that it can't handle. HTTPClientSession cs("127.0.0.1", MASTER_PORT_NUMBER); cs.setTimeout(0); HTTPRequest request(HTTPRequest::HTTP_GET, CHILD_URI + _sessionId); HTTPResponse response; _ws = std::make_shared<WebSocket>(cs, request, response); _session.reset(new ChildProcessSession(_sessionId, _ws, _loKit, _loKitDocument, _jailId, _onLoad, _onUnload)); _ws->setReceiveTimeout(0); // child Jail TID PID std::string hello("child " + _jailId + " " + _sessionId + " " + std::to_string(Process::id())); _session->sendTextFrame(hello); TileQueue queue; QueueHandler handler(queue, _session, "kit_queue_" + _session->getId()); Thread queueHandlerThread; queueHandlerThread.start(handler); int flags; int n; do { char buffer[1024]; n = _ws->receiveFrame(buffer, sizeof(buffer), flags); if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE) { std::string firstLine = getFirstLine(buffer, n); if (firstLine == "eof") break; StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); // The only kind of messages a child process receives are the single-line ones (?) assert(firstLine.size() == static_cast<std::string::size_type>(n)); queue.put(firstLine); } } while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE && !_stop); queue.clear(); queue.put("eof"); queueHandlerThread.join(); // We should probably send the Client some sensible message and reason. _session->sendTextFrame("eof"); _session.reset(); } catch (const Exception& exc) { Log::error() << "Error: " << exc.displayText() << (exc.nested() ? " (" + exc.nested()->displayText() + ")" : "") << Log::end; } catch (const std::exception& exc) { Log::error(std::string("Exception: ") + exc.what()); } catch (...) { Log::error("Unexpected Exception."); } Log::debug("Thread [" + thread_name + "] finished."); }