//============================================================================= // METHOD: SPELLipcIncomingRequest:run //============================================================================= void SPELLipcIncomingRequest::run() { std::string senderId = m_message->getSender(); std::string receiverId = m_message->getReceiver(); // If the request has been canceled beforehand if (m_cancel) return; SPELLipcMessage* response = m_listener->processRequest(m_message); if (response && !m_cancel) { response->setSender(receiverId); response->setReceiver(senderId); // Do not set sequence number if it is already set. // This happens when forwarding requests. if (response->getSequence() == -1) { response->setSequence( m_message->getSequence() ); } try { if (m_interface->isConnected()) { SPELLipcOutput& writer = m_interface->getWriter(m_message->getKey()); writer.send(response); m_interface->endRequest( getThreadId() ); } } catch(...) {}; delete response; } finish(); delete m_message; }
//============================================================================= // METHOD: SPELLipcMessageMailbox::retrieve //============================================================================= SPELLipcMessage SPELLipcMessageMailbox::retrieve( std::string id, unsigned long timeoutMsec ) { DEBUG(NAME + "Retrieve response with id " + id) SPELLipcMessageQueue* queue = getQueue(id); SPELLipcMessage msg = VOID_MESSAGE; try { if (timeoutMsec == 0) { msg = queue->pull(); } else { msg = queue->pull(timeoutMsec); } remove(id); } catch( SPELLqueueTimeout& timeout ) { //remove(id); // Re-throw the exception throw SPELLipcError(NAME + "Response timed out (limit " + ISTR(timeoutMsec) + " msec.)", (SPELLerrorCode) IPC_ERROR_TIMEOUT_ECODE); } DEBUG(NAME + "Retrieve message with id " + id + " done: " + msg.getSequenceStr()); return msg; }
//============================================================================= // METHOD: SPELLlistenerContext::onNewContext //============================================================================= void SPELLlistenerContext::onNewContext( const SPELLipcMessage& msg ) { ContextInfo* ctxInfo; std::string ctxName = msg.get(MessageField::FIELD_CTX_NAME); ctxInfo = &m_openContexts[ctxName]; ctxInfo->m_key = msg.getKey(); ctxInfo->m_port = STRI(msg.get(MessageField::FIELD_CTX_PORT)); ctxInfo->m_status = MessageValue::DATA_CTX_RUNNING; DEBUG("New context:"); DEBUG("- Name=" + ctxInfo->m_name); DEBUG("- Key=" + ISTR(ctxInfo->m_key)); DEBUG("- Port=" + ISTR(ctxInfo->m_port)); DEBUG("- Status=" + ctxInfo->m_status); m_waitForContextStart.set(); // Notify to other clients SPELLipcMessage notify( msg ); notify.setId( ListenerMessages::MSG_CONTEXT_OP ); notify.setType( MSG_TYPE_ONEWAY ); notify.set( MessageField::FIELD_CTX_STATUS, MessageValue::DATA_CTX_RUNNING ); notify.setSender("LST"); notify.setReceiver("GUI"); m_gui->displace(¬ify); // Send notification to peer if any, and if alignment is enabled if (m_peer) m_peer->displace(msg); }
//============================================================================= // METHOD: SPELLclient:: //============================================================================= SPELLipcMessage SPELLclient::sendRequestToClient( const SPELLipcMessage& msg ) { TICK_IN; SPELLipcMessage result = VOID_MESSAGE; DEBUG( NAME + "Send request to client: " + msg.dataStr() ); result = m_clientIPC.sendRequest( getClientKey(), msg, m_ipcTimeoutGuiRequestMsec ); DEBUG( NAME + "Response for request to client: " + result.dataStr() ); TICK_OUT; return result; }
//============================================================================= // METHOD: SPELLipcMessageMailbox::cancelAll() //============================================================================= void SPELLipcMessageMailbox::cancelAll() { SPELLipcMessageQueueMap::iterator mit; for( mit = m_queueMap.begin(); mit != m_queueMap.end(); mit++) { SPELLipcMessage* dummyResponse = new SPELLipcMessage("dummy"); dummyResponse->setType( MSG_TYPE_RESPONSE ); SPELLipcMessageQueue* queue = (*mit).second; queue->push(dummyResponse); } }
//============================================================================= // METHOD: SPELLlistenerContext::startContext //============================================================================= SPELLipcMessage SPELLlistenerContext::startContext( const SPELLipcMessage& msg ) { std::string cmd; std::string name; name = msg.get(MessageField::FIELD_CTX_NAME); cmd = SPELLutils::getSPELL_HOME() + PATH_SEPARATOR + "bin" + PATH_SEPARATOR + "SPELL-Context -n " + name + " -s " + ISTR(m_port) + " -c " + m_configFile; DEBUG("Opening context using command: " + cmd); std::string identifier = "CTX_" + name; // Will have no effect if the listener is there already SPELLprocessManager::instance().addListener("CTX_" + name, this); // Clear process information, in case it is there already SPELLprocessManager::instance().clearProcess(identifier); // Register and start the process SPELLprocessManager::instance().startProcess("CTX_" + name, cmd); // Notify to other clients SPELLipcMessage notify( msg ); notify.setId( ListenerMessages::MSG_CONTEXT_OP ); notify.setType( MSG_TYPE_ONEWAY ); notify.set( MessageField::FIELD_CTX_STATUS, MessageValue::DATA_CTX_STARTING ); notify.setSender("LST"); notify.setReceiver("GUI"); m_gui->displace(¬ify); DEBUG("Wait context " + name + " login"); m_waitForContextStart.clear(); bool timeout = m_waitForContextStart.wait(15*1000); DEBUG("Wait context " + name + " login done: timeout " + BSTR(timeout)); if (timeout) { SPELLipcMessage resp = SPELLipcHelper::createErrorResponse(ContextMessages::RSP_OPEN_CTX, msg); resp.set( MessageField::FIELD_FATAL, PythonConstants::True); resp.set( MessageField::FIELD_ERROR, "Cannot open context " + name); resp.set( MessageField::FIELD_REASON, "Context did not log in in time"); return resp; } else { LOG_INFO("Context running"); return SPELLipcHelper::createResponse(ContextMessages::RSP_OPEN_CTX, msg); } }
//============================================================================= // METHOD: SPELLclientIPC:: //============================================================================= SPELLipcMessage SPELLclientIPC::processRequest( const SPELLipcMessage& msg ) { int clientKey = msg.getKey(); DEBUG("[CLTRCV] Received request from client: " + msg.getId()); SPELLipcMessage resp = VOID_MESSAGE; SPELLclientInterestList* list = getClientInterestList(clientKey); // If the message is a login message, redirect it to the client manager if (msg.getId() == ContextMessages::REQ_GUI_LOGIN) { SPELLclientManager::instance().clientLogin(clientKey, msg.get( MessageField::FIELD_HOST )); resp = SPELLipcHelper::createResponse(ContextMessages::RSP_GUI_LOGIN, msg); } // If the message is a logout message, redirect it to the client manager else if (msg.getId() == ContextMessages::REQ_GUI_LOGOUT ) { // No need to close IPC here. When the GUI receives the response, // it will close the channel by sending EOC. There, IPC layer will // automatically close the corresponding channel. SPELLclientManager::instance().clientLogout(clientKey); resp = SPELLipcHelper::createResponse(ContextMessages::RSP_GUI_LOGOUT, msg); } else if (list != NULL) { //DEBUG("[CLTRCV] Distribute client request: " + msg.getId()); resp = list->distributeRequest(msg); //DEBUG("[CLTRCV] Got response for client request: " + msg.getId()); // Executor request additional processing (request attended by executor that need to be processed in context also) // But only if the response is not an error if (resp.getType() != MSG_TYPE_ERROR) { if (msg.getId() == ExecutorMessages::REQ_SET_CONFIG) { SPELLipcMessage cfgChange( msg ); cfgChange.setId( ContextMessages::MSG_EXEC_CONFIG ); cfgChange.setType( MSG_TYPE_ONEWAY ); SPELLclientManager::instance().notifyMonitoringClients(&cfgChange); } } if (resp.isVoid()) { LOG_ERROR("Unable to get response for client request " + msg.getId()); } } else { LOG_ERROR("No listeners for client " + ISTR(clientKey) + " to distribute request: " + msg.getId()); } return resp; }
//============================================================================= // METHOD: SPELLipcMessageMailbox::cancel() //============================================================================= void SPELLipcMessageMailbox::cancel( std::string id ) { SPELLipcMessageQueueMap::iterator mit; for( mit = m_queueMap.begin(); mit != m_queueMap.end(); mit++) { if (mit->first == id) { SPELLipcMessage* dummyResponse = new SPELLipcMessage("dummy"); dummyResponse->setType( MSG_TYPE_RESPONSE ); SPELLipcMessageQueue* queue = mit->second; queue->push(dummyResponse); break; } } }
//============================================================================= // METHOD: SPELLexecutorIPC:: //============================================================================= SPELLipcMessage SPELLexecutorIPC::sendRequest( const std::string& executorId, const SPELLipcMessage& msg, unsigned long timeoutMsec ) { if (m_connected) { SPELLipcMessage toSend(msg); return m_ipc.sendRequest(toSend,timeoutMsec); } else { SPELLipcMessage resp = SPELLipcHelper::createErrorResponse("IpcErrorResponse", msg); resp.set( MessageField::FIELD_ERROR, "Cannot send request" ); resp.set( MessageField::FIELD_REASON, "IPC not connected"); resp.set( MessageField::FIELD_FATAL, PythonConstants::True ); return resp; } }
SPELLipcMessage* processRequest( SPELLipcMessage* msg ) { SPELLipcMessage* resp = SPELLipcHelper::createResponse("dummy", msg); try { std::cout << "request received from " << msg->getKey() << ": " << msg->get("NUM") << std::endl; resp->setId("resp"); resp->setType(MSG_TYPE_RESPONSE); resp->set("NUM", msg->get("NUM")); usleep(200000); } catch(SPELLcoreException& ex) { std::cerr << "PROCESS ERROR: " << ex.what() << std::endl; } return resp; };
//============================================================================= // METHOD: SPELLlistenerContext::processRequest //============================================================================= SPELLipcMessage SPELLlistenerContext::processRequest( const SPELLipcMessage& msg ) { DEBUG("Got request: " + msg.getId()); // No request from context yet return VOID_MESSAGE; }
//============================================================================= // METHOD: SPELLipcMessageMailbox::place //============================================================================= bool SPELLipcMessageMailbox::place( std::string id, const SPELLipcMessage& msg ) { DEBUG(NAME + "Place message on queue with id " + id + " (" + msg.getSequenceStr() + ")"); SPELLipcMessageQueue* queue = getQueue(id); if(queue) { DEBUG(NAME + "Place message IN"); queue->push(msg); DEBUG(NAME + "Place message OUT"); return true; } else { LOG_ERROR("###### No queue to place response " + msg.dataStr()); return false; } }
//============================================================================= // METHOD: SPELLlistenerContext::processMessage //============================================================================= void SPELLlistenerContext::processMessage( const SPELLipcMessage& msg ) { DEBUG("Got message: " + msg.getId()); if (msg.getId() == ListenerMessages::MSG_CONTEXT_OPEN) { this->onNewContext(msg); } else if (msg.getId() == ListenerMessages::MSG_CONTEXT_CLOSED) { this->onClosedContext(msg); } else { LOG_ERROR("Unprocessed message: " + msg.getId()) } }
//============================================================================= // METHOD: SPELLipcMessageMailbox::cancel() //============================================================================= void SPELLipcMessageMailbox::cancel( std::string id ) { DEBUG(NAME + "Requested to cancel request " + id); SPELLipcMessageQueueMap::iterator mit; for( mit = m_queueMap.begin(); mit != m_queueMap.end(); mit++) { DEBUG(NAME + "Checking " + id + " <> " + mit->first); if (mit->first == id) { DEBUG( NAME + "Canceling request " + id); SPELLipcMessage* cancelResponse = new SPELLipcMessage( MessageId::MSG_ID_CANCEL ); cancelResponse->setType( MSG_TYPE_RESPONSE ); SPELLipcMessageQueue* queue = mit->second; queue->push(cancelResponse); break; } } }
//============================================================================= // METHOD: SPELLlistenerContext::attachContext //============================================================================= SPELLipcMessage SPELLlistenerContext::attachContext( const SPELLipcMessage& msg ) { std::string name; SPELLipcMessage res = SPELLipcHelper::createResponse(ContextMessages::RSP_ATTACH_CTX, msg); name = msg.get(MessageField::FIELD_CTX_NAME); this->fillContextInfo(name, res); return res; }
//============================================================================= // METHOD: SPELLclientIPC:: //============================================================================= void SPELLclientIPC::processMessage( const SPELLipcMessage& msg ) { // Get the peer key int clientKey = msg.getKey(); SPELLclientInterestList* list = getClientInterestList(clientKey); if (list != NULL) { list->distributeMessage(msg); } }
//============================================================================= // METHOD: SPELLexecutorIPC:: //============================================================================= void SPELLexecutorIPC::processMessage( const SPELLipcMessage& msg ) { TICK_IN; DEBUG("[EXCIPC] Received message from executor: " + msg.dataStr()); // Certain messages are for monitoring clients only if ((msg.getId() != MessageId::MSG_ID_PROMPT_START)&&(msg.getId() != MessageId::MSG_ID_PROMPT_END)) { DEBUG("[EXCIPC] Forward message to controller"); m_controller.processMessageFromExecutor(msg); } if (msg.getId() != ExecutorMessages::MSG_NOTIF_EXEC_CLOSE) { DEBUG("[EXCIPC] Forward message to monitoring clients"); notifyMessage(msg); } DEBUG("[EXCIPC] Message processed"); TICK_OUT; }
//============================================================================= // METHOD: SPELLclient:: //============================================================================= void SPELLclient::processMessageFromClient( const SPELLipcMessage& msg ) { std::string procId = msg.get( MessageField::FIELD_PROC_ID ); SPELLexecutor* exec = SPELLexecutorManager::instance().getExecutor(procId); if (exec) { if (msg.getId() == ExecutorMessages::ACKNOWLEDGE) { if (exec->getControllingClient() != this) { return; } } exec->sendMessageToExecutor(msg); } else { LOG_ERROR("Cannot send message, no suitable executor found"); } }
//============================================================================= // METHOD: SPELLclientManager:: //============================================================================= void SPELLclientManager::completeMonitoringInfo( const std::string& procId, SPELLipcMessage& msg ) { std::list<std::string> monitoring = getMonitoringClients(procId); std::list<std::string>::iterator it; std::string monitoringList = ""; for( it = monitoring.begin(); it != monitoring.end(); it++) { if (monitoringList != "") monitoringList += ","; monitoringList += (*it); } msg.set( MessageField::FIELD_GUI_LIST, monitoringList ); }
//============================================================================= // METHOD: SPELLexecutorIPC::processConnectionError //============================================================================= bool SPELLexecutorIPC::shouldForwardToMonitoring( const SPELLipcMessage& msg ) { std::string requestId = msg.getId(); if (msg.getType() == MSG_TYPE_PROMPT) { return false; } if ( requestId == ContextMessages::REQ_OPEN_EXEC ) { return false; } else if ( requestId == ContextMessages::REQ_INSTANCE_ID ) { return false; } else if ( requestId == ContextMessages::REQ_EXEC_INFO ) { return false; } else if ( requestId == ContextMessages::REQ_DEL_SHARED_DATA ) { return false; } else if ( requestId == ContextMessages::REQ_SET_SHARED_DATA ) { return false; } else if ( requestId == ContextMessages::REQ_GET_SHARED_DATA ) { return false; } else if ( requestId == ContextMessages::REQ_GET_SHARED_DATA_KEYS ) { return false; } return true; }
//============================================================================= // METHOD: SPELLserverCif::openSubprocedure //============================================================================= std::string SPELLserverCif::openSubprocedure( const std::string& procId, const std::string& args, bool automatic, bool blocking, bool visible ) { std::string openModeStr = "{"; DEBUG("[CIF] Open subprocedure options: " + BSTR(automatic) + "," + BSTR(blocking) + "," + BSTR(visible)); openModeStr += (automatic ? (LanguageModifiers::Automatic + ":" + PythonConstants::True) : (LanguageModifiers::Automatic + ":" + PythonConstants::False)) + ","; openModeStr += (blocking ? (LanguageModifiers::Blocking + ":" + PythonConstants::True) : (LanguageModifiers::Blocking+ ":" + PythonConstants::False)) + ","; openModeStr += (visible ? (LanguageModifiers::Visible + ":" + PythonConstants::True) : (LanguageModifiers::Visible + ":" + PythonConstants::False)) + "}"; std::string parent = SPELLexecutor::instance().getProcId(); // Request first an available instance number SPELLipcMessage instanceMsg(ContextMessages::REQ_INSTANCE_ID); instanceMsg.setType(MSG_TYPE_REQUEST); instanceMsg.set(MessageField::FIELD_PROC_ID, procId); SPELLipcMessage* response = sendCTXRequest( &instanceMsg, SPELL_CIF_CTXREQUEST_TIMEOUT_SEC ); std::string subprocId = ""; subprocId = response->get(MessageField::FIELD_INSTANCE_ID); delete response; DEBUG("[CIF] Request context to open subprocedure " + subprocId + " in mode " + openModeStr); SPELLipcMessage openMsg(ContextMessages::REQ_OPEN_EXEC); openMsg.setType(MSG_TYPE_REQUEST); openMsg.set(MessageField::FIELD_PROC_ID, parent); openMsg.set(MessageField::FIELD_SPROC_ID, subprocId); openMsg.set(MessageField::FIELD_OPEN_MODE, openModeStr); openMsg.set(MessageField::FIELD_ARGS, args); response = sendCTXRequest( &openMsg, SPELL_CIF_OPENPROC_TIMEOUT_SEC ); delete response; /** \todo failure handle */ return subprocId; }
//============================================================================= // METHOD: SPELLclientManager:: //============================================================================= void SPELLclientManager::notifyMonitoringClients( const SPELLipcMessage& msg ) { DEBUG("Notify monitoring clients TRY-IN"); SPELLmonitor m(m_clientLock); DEBUG("Notify monitoring clients IN"); ClientMap::const_iterator it; int controllingKey = msg.getKey(); for( it = m_clientMap.begin(); it != m_clientMap.end(); it++ ) { SPELLclient* client = it->second; if (it->first == controllingKey) continue; DEBUG(" - client " + ISTR(it->first)); client->sendMessageToClient(msg); } DEBUG("Notify monitoring clients done"); }
//============================================================================= // METHOD: SPELLlistenerContext::displace //============================================================================= SPELLipcMessage SPELLlistenerContext::displace( const SPELLipcMessage& msg ) { SPELLipcMessage res = VOID_MESSAGE; std::string name; DEBUG("Got IPC object: " + msg.getId()); if (msg.getId() == ContextMessages::REQ_OPEN_CTX) res = this->startContext(msg); else if (msg.getId() == ContextMessages::REQ_CLOSE_CTX) res = this->stopContext(msg); else if (msg.getId() == ContextMessages::REQ_CTX_INFO) res = this->contextInfo(msg); else if (msg.getId() == ContextMessages::REQ_ATTACH_CTX) res = this->attachContext(msg); else if (msg.getId() == ContextMessages::REQ_DESTROY_CTX) res = this->destroyContext(msg); else LOG_ERROR("Unprocessed message: " + msg.getId()) DEBUG("Response IPC object: " + res.dataStr()); return res; }
//============================================================================= // METHOD: SPELLexecutorIPC:: //============================================================================= SPELLipcMessage SPELLexecutorIPC::processRequest( const SPELLipcMessage& msg ) { TICK_IN; DEBUG("[EXCIPC] Received request from executor: " + msg.dataStr()); SPELLipcMessage resp = VOID_MESSAGE; DEBUG("[EXCIPC] Forward request to controller"); resp = m_controller.processRequestFromExecutor(msg); // Certain requests are to be sent to controlling clients only if ( shouldForwardToMonitoring(msg) ) { DEBUG("[EXCIPC] Forward to monitoring clients"); // Notify request notifyRequest(msg); } DEBUG("[EXCIPC] Request processed"); TICK_OUT; return resp; }
//============================================================================= // METHOD: SPELLlistenerContext::destroyContext //============================================================================= SPELLipcMessage SPELLlistenerContext::destroyContext( const SPELLipcMessage& msg ) { std::string name; name = msg.get(MessageField::FIELD_CTX_NAME); ContextInfo& ctxInfo = m_openContexts[name]; ctxInfo.m_status = MessageValue::DATA_CTX_AVAILABLE; m_ipc->disconnectClient( ctxInfo.m_key ); try { SPELLprocessManager::instance().killProcess("CTX_" + name); SPELLprocessManager::instance().waitProcess("CTX_" + name); SPELLprocessManager::instance().clearProcess("CTX_" + name); } catch(SPELLcoreException& ex) {}; LOG_INFO("Destroyed context"); return SPELLipcHelper::createResponse(ContextMessages::RSP_DESTROY_CTX, msg); }
//============================================================================= // METHOD: SPELLlistenerContext::fillContextInfo //============================================================================= void SPELLlistenerContext::fillContextInfo(const std::string ctxName, SPELLipcMessage& msg ) { std::string driverName; SPELLcontextConfig* ctxConfig; SPELLdriverConfig* drvConfig; ContextInfo* ctxInfo; ctxInfo = &m_openContexts[ctxName]; ctxConfig = ctxInfo->m_ctxConfig; drvConfig = ctxInfo->m_drvConfig; msg.set(MessageField::FIELD_CTX_NAME, ctxName); msg.set( MessageField::FIELD_CTX_PORT, ISTR(ctxInfo->m_port) ); if (ctxConfig != NULL) { msg.set(MessageField::FIELD_CTX_DRV, ctxConfig->getDriverName()); msg.set(MessageField::FIELD_CTX_SC, ctxConfig->getSC()); msg.set(MessageField::FIELD_CTX_FAM, ctxConfig->getFamily()); msg.set(MessageField::FIELD_CTX_GCS, ctxConfig->getGCS()); msg.set(MessageField::FIELD_CTX_DESC, ctxConfig->getDescription()); msg.set(MessageField::FIELD_CTX_STATUS, ctxInfo->m_status); } else { msg.set(MessageField::FIELD_CTX_DRV, "Unknown"); msg.set(MessageField::FIELD_CTX_SC, "Unknown"); msg.set(MessageField::FIELD_CTX_FAM, "Unknown"); msg.set(MessageField::FIELD_CTX_GCS, "Unknown"); msg.set(MessageField::FIELD_CTX_DESC, "Unknown"); msg.set(MessageField::FIELD_CTX_STATUS, "ERROR"); } if (drvConfig != NULL) { msg.set(MessageField::FIELD_CTX_MAXPROC, ISTR(drvConfig->getMaxProcs())); } else { msg.set(MessageField::FIELD_CTX_MAXPROC, "0" ); } }
//============================================================================= // METHOD: SPELLclient:: //============================================================================= SPELLipcMessage SPELLclient::processRequestFromClient( const SPELLipcMessage& msg ) { //DEBUG(" Client request start"); // Create the login message std::string requestId = msg.getId(); SPELLipcMessage resp = VOID_MESSAGE; try { if ( requestId == ContextMessages::REQ_INSTANCE_ID ) { resp = SPELLcontext::instance().getInstanceId( msg ); } else if ( requestId == ContextMessages::REQ_OPEN_EXEC ) { resp = SPELLcontext::instance().openExecutor( msg, this ); } else if ( requestId == ContextMessages::REQ_CLOSE_EXEC ) { resp = SPELLcontext::instance().closeExecutor( msg ); } else if ( requestId == ContextMessages::REQ_KILL_EXEC ) { resp = SPELLcontext::instance().killExecutor( msg ); } else if ( requestId == ContextMessages::REQ_ATTACH_EXEC ) { resp = SPELLcontext::instance().attachExecutor( msg, this ); } else if ( requestId == ContextMessages::REQ_DETACH_EXEC ) { resp = SPELLcontext::instance().detachExecutor( msg, this ); } else if (msg.getId() == ContextMessages::REQ_RECOVER_EXEC) { resp = SPELLcontext::instance().recoverExecutor( msg, this ); } else if (msg.getId() == ContextMessages::REQ_PROC_LIST) { resp = SPELLcontext::instance().getProcedureList( msg ); } else if (msg.getId() == ContextMessages::REQ_EXEC_LIST) { resp = SPELLcontext::instance().getExecutorList( msg ); } else if (msg.getId() == ContextMessages::REQ_PROC_PROP) { resp = SPELLcontext::instance().getProcedureProperties( msg ); } else if (msg.getId() == ContextMessages::REQ_PROC_CODE) { resp = SPELLcontext::instance().getProcedureCode( msg ); } else if (msg.getId() == ContextMessages::REQ_EXEC_INFO) { resp = SPELLcontext::instance().getExecutorInfo( msg ); } else if (msg.getId() == ContextMessages::REQ_CLIENT_INFO) { resp = SPELLcontext::instance().getClientInfo( msg ); } else if (msg.getId() == ContextMessages::REQ_SERVER_FILE_PATH) { resp = SPELLcontext::instance().getServerFilePath( msg ); } else if (msg.getId() == ContextMessages::REQ_RECOVERY_LIST) { resp = SPELLcontext::instance().getProcedureRecoveryList( msg ); } else if (msg.getId() == ContextMessages::REQ_ASRUN_LIST) { resp = SPELLcontext::instance().getProcedureAsRunList( msg ); } else if (msg.getId() == ContextMessages::REQ_DELETE_RECOVERY ) { resp = SPELLcontext::instance().deleteRecoveryFiles(msg); } else if (msg.getId() == ContextMessages::REQ_REMOVE_CONTROL ) { resp = SPELLcontext::instance().removeControl(msg); } else if (msg.getId() == ContextMessages::REQ_SET_BACKGROUND ) { resp = SPELLcontext::instance().setExecutorInBackground(msg); } else if (msg.getId() == ContextMessages::REQ_LIST_FILES ) { resp = SPELLcontext::instance().listFiles(msg); } else if (msg.getId() == ContextMessages::REQ_LIST_DATADIRS ) { resp = SPELLcontext::instance().listDataDirectories(msg); } else if (msg.getId() == ContextMessages::REQ_INPUT_FILE ) { resp = SPELLcontext::instance().getInputFile(msg); } else if (msg.getId() == ContextMessages::REQ_CURRENT_TIME ) { resp = SPELLcontext::instance().getCurrentTime(msg); } else if ( requestId == ContextMessages::REQ_DEL_SHARED_DATA ) { resp = SPELLcontext::instance().clearSharedData(msg); } else if ( requestId == ContextMessages::REQ_SET_SHARED_DATA ) { resp = SPELLcontext::instance().setSharedData(msg); } else if ( requestId == ContextMessages::REQ_GET_SHARED_DATA ) { resp = SPELLcontext::instance().getSharedData(msg); } else if ( requestId == ContextMessages::REQ_GET_SHARED_DATA_KEYS ) { resp = SPELLcontext::instance().getSharedDataKeys(msg); } else if ( requestId == ContextMessages::REQ_GET_SHARED_DATA_SCOPES ) { resp = SPELLcontext::instance().getSharedDataScopes(msg); } else if ( requestId == ContextMessages::REQ_DEL_SHARED_DATA_SCOPE ) { resp = SPELLcontext::instance().removeSharedDataScope(msg); } else if ( requestId == ContextMessages::REQ_ADD_SHARED_DATA_SCOPE ) { resp = SPELLcontext::instance().addSharedDataScope(msg); } else if ( requestId == ContextMessages::REQ_GET_CTX_EXEC_DFLT ) { resp = SPELLcontext::instance().getExecutorDefaults(msg); } else if ( requestId == ContextMessages::REQ_SET_CTX_EXEC_DFLT ) { resp = SPELLcontext::instance().setExecutorDefaults(msg); } else { // Forward the request to the executor std::string procId = msg.get( MessageField::FIELD_PROC_ID ); try { DEBUG( NAME + "Forward request to executor " + procId +": " + msg.getId()); SPELLexecutor* exec = SPELLexecutorManager::instance().getExecutor(procId); resp = exec->sendRequestToExecutor(msg); if (resp.isVoid()) { LOG_ERROR("Unable to obtain response for client request " + msg.getId() + " from executor "); } } catch( SPELLcoreException& ex ) { LOG_ERROR( NAME + "Unable to send request to executor '" + procId + "', unable to find"); std::string id = msg.getId(); SPELLutils::replace(id, "REQ", "RSP"); resp = SPELLipcHelper::createErrorResponse(id,msg); resp.set(MessageField::FIELD_ERROR, "Unable to send request to executor " + procId); resp.set(MessageField::FIELD_REASON, "Cannot find the executor"); resp.set(MessageField::FIELD_FATAL, PythonConstants::True ); } } } catch(SPELLexecutorManager::OperationError& err) { LOG_ERROR( NAME + "Error in client request processing " + ISTR(err.errorCode)); std::string id = msg.getId(); SPELLutils::replace(id, "REQ", "RSP"); resp = SPELLipcHelper::createErrorResponse(id,msg); resp.set(MessageField::FIELD_ERROR, "Error in client processing"); resp.set(MessageField::FIELD_REASON, err.message); resp.set(MessageField::FIELD_FATAL, PythonConstants::True); } catch(...) { LOG_ERROR( NAME + "Unknown error in client request processing"); std::string id = msg.getId(); SPELLutils::replace(id, "REQ", "RSP"); resp = SPELLipcHelper::createErrorResponse(id,msg); resp.set(MessageField::FIELD_ERROR, "Error in client processing"); resp.set(MessageField::FIELD_REASON, "Unknown reason"); resp.set(MessageField::FIELD_FATAL, PythonConstants::True); } //DEBUG(" Client request end"); return resp; }
//============================================================================= // METHOD: SPELLserverCif::prompt //============================================================================= std::string SPELLserverCif::prompt( const std::string& message, PromptOptions options, unsigned int ptype, unsigned int scope ) { DEBUG("[CIF] Prompt message"); std::string timeStr = getTimestampUsec(); SPELLipcMessage promptMessage(MessageId::MSG_ID_PROMPT); completeMessage( &promptMessage ); promptMessage.setType(MSG_TYPE_PROMPT); promptMessage.set(MessageField::FIELD_PROC_ID, getProcId() ); promptMessage.set(MessageField::FIELD_TEXT, message); promptMessage.set(MessageField::FIELD_DATA_TYPE, ISTR(ptype)); promptMessage.set(MessageField::FIELD_TIME, timeStr); promptMessage.set(MessageField::FIELD_SCOPE, ISTR(scope)); // Used for the prompt display message PromptOptions optionsToShow; DEBUG("[CIF] Prompt typecode " + ISTR(ptype)); if (ptype == LanguageConstants::PROMPT_NUM || ptype == LanguageConstants::PROMPT_ALPHA || ptype == LanguageConstants::PROMPT_DATE ) { DEBUG("[CIF] Prompt is simple"); promptMessage.set(MessageField::FIELD_EXPECTED, ""); } else if ( ptype & LanguageConstants::PROMPT_LIST ) { DEBUG("[CIF] Prompt is list"); PromptOptions::iterator it; int keyCount = 1; std::string optionStr = ""; std::string expectedStr = ""; // Iterate over the option list and build the option and expected values strings for( it = options.begin(); it != options.end(); it++) { std::string key; std::string value; std::string opt = (*it); DEBUG("[CIF] Option: " + opt); if (optionStr.size()>0) optionStr += IPCinternals::OPT_SEPARATOR; if (expectedStr.size()>0) expectedStr += IPCinternals::OPT_SEPARATOR; if ( opt.find(IPCinternals::KEY_SEPARATOR) == std::string::npos ) { // Put an internal key in this case key = ISTR(keyCount); value = opt; // Trim the value trim(value); } else { int idx = opt.find(IPCinternals::KEY_SEPARATOR); key = opt.substr(0, idx); // Trim the key trim(key); value = opt.substr(idx+1, opt.size()-idx); // Trim the value trim(value); } DEBUG("[CIF] Option key: '" + key + "'"); DEBUG("[CIF] Option value: '" + value + "'"); optionStr += key + IPCinternals::KEY_SEPARATOR + value; optionsToShow.push_back(key + ": " + value); if (ptype & LanguageConstants::PROMPT_ALPHA) { expectedStr += value; DEBUG("[CIF] Expected: " + value); } else { expectedStr += key; DEBUG("[CIF] Expected: " + key); } keyCount++; } promptMessage.set(MessageField::FIELD_EXPECTED, expectedStr); promptMessage.set(MessageField::FIELD_OPTIONS, optionStr); } else if (ptype == LanguageConstants::PROMPT_OK) { promptMessage.set(MessageField::FIELD_EXPECTED, "O"); promptMessage.set(MessageField::FIELD_OPTIONS, "O" + IPCinternals::KEY_SEPARATOR + " Ok"); optionsToShow.push_back("O: Ok"); } else if (ptype == LanguageConstants::PROMPT_CANCEL) { promptMessage.set(MessageField::FIELD_EXPECTED, "C"); promptMessage.set(MessageField::FIELD_OPTIONS, "C" + IPCinternals::KEY_SEPARATOR + " Cancel"); optionsToShow.push_back("C: Cancel"); } else if (ptype == LanguageConstants::PROMPT_YES) { promptMessage.set(MessageField::FIELD_EXPECTED, "Y"); promptMessage.set(MessageField::FIELD_OPTIONS, "Y" + IPCinternals::KEY_SEPARATOR + " Yes"); optionsToShow.push_back("Y: Yes"); } else if (ptype == LanguageConstants::PROMPT_NO) { promptMessage.set(MessageField::FIELD_EXPECTED, "N"); promptMessage.set(MessageField::FIELD_OPTIONS, "N" + IPCinternals::KEY_SEPARATOR + " No"); optionsToShow.push_back("N: No"); } else if (ptype == LanguageConstants::PROMPT_YES_NO) { promptMessage.set(MessageField::FIELD_EXPECTED, "Y|N"); promptMessage.set(MessageField::FIELD_OPTIONS, "Y" + IPCinternals::KEY_SEPARATOR + " Yes|N" + IPCinternals::KEY_SEPARATOR + " No"); optionsToShow.push_back("Y: Yes"); optionsToShow.push_back("N: No"); } else if (ptype == LanguageConstants::PROMPT_OK_CANCEL) { promptMessage.set(MessageField::FIELD_EXPECTED, "O|C"); promptMessage.set(MessageField::FIELD_OPTIONS, "O" + IPCinternals::KEY_SEPARATOR + " Ok|C" + IPCinternals::KEY_SEPARATOR + " Cancel"); optionsToShow.push_back("O: Ok"); optionsToShow.push_back("C: Cancel"); } DEBUG("[CIF] Option string: " + promptMessage.get(MessageField::FIELD_OPTIONS)); DEBUG("[CIF] Expected string: " + promptMessage.get(MessageField::FIELD_EXPECTED)); // Write the prompt display std::string msgToShow = message; if (optionsToShow.size()>0) { msgToShow += "\nAvailable options:\n"; for(PromptOptions::iterator pit = optionsToShow.begin(); pit != optionsToShow.end(); pit++) { msgToShow += " - " + (*pit) + "\n"; } } // Send the display message via the buffer to ensure synchronization m_buffer->prompt(msgToShow, LanguageConstants::SCOPE_PROMPT); // Ensure buffer is flushed m_buffer->flush(); // Write the prompt in the asrun m_asRun->writePrompt( getStack(), message, scope ); DEBUG("[CIF] Messsage prepared"); // Send request to client SPELLipcMessage* response = sendGUIRequest(&promptMessage, SPELL_CIF_PROMPT_TIMEOUT_SEC); DEBUG("[CIF] Prompt response received"); std::string toProcess = ""; if (response->getId() == MessageId::MSG_ID_CANCEL) { LOG_WARN("Prompt cancelled"); DEBUG("[CIF] Prompt cancelled"); toProcess = PROMPT_CANCELLED; // Abort execution in this case SPELLexecutor::instance().abort("Prompt cancelled",true); } else if (response->getId() == MessageId::MSG_ID_TIMEOUT) { LOG_ERROR("Prompt timed out"); DEBUG("[CIF] Prompt timed out"); toProcess = PROMPT_TIMEOUT; // Abort execution in this case SPELLexecutor::instance().abort("Prompt timed out", true); } else if (response->getType() == MSG_TYPE_ERROR) { std::string errorMsg = response->get( MessageField::FIELD_ERROR ); DEBUG("[CIF] Prompt error: " + errorMsg ); LOG_ERROR("Prompt error: " + errorMsg); toProcess = PROMPT_ERROR; // \todo Should fix this and use an error code if (errorMsg == "No controlling client") { warning("No controlling client to issue prompt!", LanguageConstants::SCOPE_SYS ); SPELLexecutor::instance().pause(); } else { error( "Prompt error: " + errorMsg, LanguageConstants::SCOPE_SYS ); // Abort execution in this case SPELLexecutor::instance().abort("Prompt error",true); } } else { toProcess = response->get(MessageField::FIELD_RVALUE); DEBUG("[CIF] Prompt response: " + toProcess); } // \todo When there is no controlling client we should keep the child procedure in prompt waiting state // Send the display message via the buffer to ensure synchronization m_buffer->write("Answer: '" + toProcess + "'", LanguageConstants::SCOPE_PROMPT); m_buffer->flush(); m_asRun->writeAnswer( getStack(), toProcess, scope ); return toProcess; }
//============================================================================= // METHOD: SPELLserverCif::processRequest //============================================================================= SPELLipcMessage* SPELLserverCif::processRequest( SPELLipcMessage* msg ) { std::string requestId = msg->getId(); std::string procId = msg->get(MessageField::FIELD_PROC_ID); SPELLipcMessage* response = new SPELLipcMessage( msg->getId() ); response->setType(MSG_TYPE_RESPONSE); response->setReceiver( msg->getSender() ); response->setSender( msg->getReceiver() ); if (requestId == ExecutorMessages::REQ_GET_CONFIG) { m_processor.processGetConfig(msg,response); } else if (requestId == ExecutorMessages::REQ_SET_CONFIG) { m_processor.processSetConfig(msg,response); } else if (requestId == ExecutorMessages::REQ_SET_BREAKPOINT) { m_processor.processSetBreakpoint(msg, response); } else if (requestId == ExecutorMessages::REQ_CLEAR_BREAKPOINT) { m_processor.processClearBreakpoints(msg, response); } else if (requestId == ExecutorMessages::REQ_VARIABLE_NAMES) { m_processor.processGetVariables(msg, response); } else if (requestId == ExecutorMessages::REQ_VARIABLE_WATCH) { m_processor.processVariableWatch(msg, response); } else if (requestId == ExecutorMessages::REQ_VARIABLE_NOWATCH) { m_processor.processVariableNoWatch(msg, response); } else if (requestId == ExecutorMessages::REQ_WATCH_NOTHING) { m_processor.processWatchNothing(msg, response); } else if (requestId == ExecutorMessages::REQ_CHANGE_VARIABLE) { m_processor.processChangeVariable(msg, response); } else if (msg->getType() == MSG_TYPE_NOTIFY) { if (procId != SPELLexecutor::instance().getProcId()) { m_processor.processNotificationForChild(msg,response); } else { LOG_ERROR("[CIF] Unexpected message for executor " + procId); } } else { LOG_ERROR("[CIF] Unprocessed request: " + requestId) } return response; }
//============================================================================= // METHOD: SPELLlistenerContext::stopContext //============================================================================= SPELLipcMessage SPELLlistenerContext::stopContext( const SPELLipcMessage& msg ) { SPELLipcMessage closemsg( ContextMessages::MSG_CLOSE_CTX ); ContextInfo* ctxInfo; std::string name; name = msg.get(MessageField::FIELD_CTX_NAME); this->fillContextInfo(name, closemsg); ctxInfo = &m_openContexts[name]; closemsg.setType( MSG_TYPE_ONEWAY ); closemsg.setSender("LST"); closemsg.setReceiver("CTX_" + name); m_waitForContextClose.clear(); DEBUG("Send close message to context"); m_ipc->sendMessage( ctxInfo->m_key, closemsg ); DEBUG("Wait for context to close"); bool timeout = m_waitForContextClose.wait( 5000 ); DEBUG("Disconnect context IPC"); m_ipc->disconnectClient( ctxInfo->m_key ); DEBUG("Disconnected context IPC"); if (timeout) { LOG_WARN("Cannot close, killing instead"); SPELLprocessManager::instance().killProcess("CTX_" + name); } else { try { DEBUG("Waiting context process to finish"); SPELLprocessManager::instance().waitProcess("CTX_" + name); SPELLprocessManager::instance().clearProcess("CTX_" + name); LOG_INFO("Closed context"); SPELLipcMessage notify(ListenerMessages::MSG_CONTEXT_OP); notify.setType( MSG_TYPE_ONEWAY ); ctxInfo = &m_openContexts[msg.get(MessageField::FIELD_CTX_NAME)]; ctxInfo->m_status = MessageValue::DATA_CTX_AVAILABLE; std::string identifier = "CTX_" + ctxInfo->m_name; DEBUG("Closed context:"); DEBUG("- Name=" + ctxInfo->m_name); DEBUG("- Key=" + ISTR(ctxInfo->m_key)); DEBUG("- Port=" + ISTR(ctxInfo->m_port)); DEBUG("- Status=" + ctxInfo->m_status); SPELLprocessManager::instance().removeListener(identifier, this); SPELLprocessManager::instance().clearProcess(identifier); this->fillContextInfo(ctxInfo->m_name, notify); // Notify other clients notify.setId( ListenerMessages::MSG_CONTEXT_OP ); notify.set( MessageField::FIELD_CTX_STATUS, MessageValue::DATA_CTX_AVAILABLE ); notify.setSender("LST"); notify.setReceiver("GUI"); m_gui->displace(¬ify); } catch(SPELLcoreException& ex) {}; } return SPELLipcHelper::createResponse(ContextMessages::RSP_CLOSE_CTX, msg); }