bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition, const std::string& event) { std::string eventName; if (HAS_ATTR(transition, "event")) { eventName = ATTR(transition, "event"); } else if(HAS_ATTR(transition, "eventexpr")) { if (_dataModel) { eventName = _dataModel.evalAsString(ATTR(transition, "eventexpr")); } else { LOG(ERROR) << "Transition has eventexpr attribute with no datamodel defined"; return false; } } else { return false; } std::list<std::string> eventNames = tokenizeIdRefs(eventName); std::list<std::string>::iterator eventIter = eventNames.begin(); while(eventIter != eventNames.end()) { if(nameMatch(*eventIter, event) && hasConditionMatch(transition)) { return true; } eventIter++; } return false; }
void PromelaDataModel::init(const Element<std::string>& dataElem, const Node<std::string>& node, const std::string& content) { // from <datamodel> if (HAS_ATTR(dataElem, "id")) { Element<std::string> dataElemCopy = dataElem; std::string identifier = ATTR(dataElem, "id"); std::string type = (HAS_ATTR(dataElem, "type") ? ATTR(dataElem, "type") : "int"); std::string arrSize; size_t bracketPos = type.find("["); if (bracketPos != std::string::npos) { arrSize = type.substr(bracketPos, type.length() - bracketPos); type = type.substr(0, bracketPos); } dataElemCopy.setAttribute("id", type + " " + identifier + arrSize); assign(dataElemCopy, node, content); dataElemCopy.setAttribute("id", identifier); return; } assign(dataElem, node, content); }
void CClientInfo::Config(const string& fileName) { ifstream inFile(fileName.c_str(), ifstream::in); string inXml, inLine; while (getline(inFile, inLine)) inXml += inLine; XmlVec confData(inXml.begin(), inXml.end()); confData.push_back('\0'); XmlDoc xmlDoc; try { xmlDoc.parse<0>(&confData[0]); } catch (...) { LOG("ERROR: failed to load the server config file."); return; } XmlNodePtr pNode = NULL; if ((pNode = xmlDoc.first_node("server_list"))) { XmlNodePtr pItem = pNode->first_node("server"); while (pItem) { int pId = HAS_ATTR(pItem, "id") ? atoi(ATTR_VALUE(pItem, "id")) : -1; string ipStr = HAS_ATTR(pItem, "ip") ? ATTR_VALUE(pItem, "ip") : "127.0.0.1"; int port = HAS_ATTR(pItem, "port") ? atoi(ATTR_VALUE(pItem, "port")) : 12345; m_svrMap[pId] = pair<string, int>(ipStr, port); pItem = pItem->next_sibling("server"); } } if ((pNode = xmlDoc.first_node("parameters"))) { m_connNum = HAS_NODE(pNode, "conn_num") ? atoi(NODE_VALUE(pNode, "conn_num")) : 1; m_fixRate = HAS_NODE(pNode, "fix_rate") ? atoi(NODE_VALUE(pNode, "fix_rate")) : 0; m_initTimeout = HAS_NODE(pNode, "init_timeout") ? atoi(NODE_VALUE(pNode, "init_timeout")) : 20; m_videoLen = HAS_NODE(pNode, "video_len") ? atoi(NODE_VALUE(pNode, "video_len")) : 278; m_initBufferSize = HAS_NODE(pNode, "init_buffer_size") ? atoi(NODE_VALUE(pNode, "init_buffer_size")) : 10; } LOG("--------------------------------------------------"); svrMap_t::const_iterator cIt = m_svrMap.begin(); for (; cIt != m_svrMap.end(); ++cIt) { LOG("|server: id=%d, %s:%d.", (*cIt).first, (*cIt).second.first.c_str(), (*cIt).second.second); } LOG("|number of connections: %d.", m_connNum); LOG("|video length: %d.", m_videoLen); LOG("|fix rate: %d.", m_fixRate); LOG("|init buffer timeout: %d.", m_initTimeout); LOG("|init buffer size: %d.", m_initBufferSize); LOG("--------------------------------------------------"); xmlDoc.clear(); m_rateVec.push_back(350); m_rateVec.push_back(470); m_rateVec.push_back(630); m_rateVec.push_back(845); m_rateVec.push_back(1130); m_rateVec.push_back(1520); m_rateVec.push_back(2040); }
void PromelaDataModel::assign(const Element<std::string>& assignElem, const Node<std::string>& node, const std::string& content) { std::string expr; std::string key; std::string value; if (node) { ERROR_EXECUTION_THROW("Assigning DOM node to variable is not supported"); } if (HAS_ATTR(assignElem, "id")) { key = ATTR(assignElem, "id"); } else if (HAS_ATTR(assignElem, "location")) { key = ATTR(assignElem, "location"); } if (HAS_ATTR(assignElem, "expr")) { if (key.length() == 0) { ERROR_EXECUTION_THROW("Assign element has neither id nor location"); } value = ATTR(assignElem, "expr"); } else { value = content; } if (key.length() > 0) { PromelaParser parser(key); // declaration is an array? if (parser.ast->operands.size() > 0 && parser.ast->operands.back()->operands.size() > 0 && parser.ast->operands.back()->operands.back()->type == PML_VAR_ARRAY) { evaluateDecl(parser.ast); expr = content; } else if (value.length() > 0) { expr = key + " = " + value + ";"; } else { // declaration expr = key + ";"; } } else { expr = content; } PromelaParser parser(expr, 2, PromelaParser::PROMELA_DECL, PromelaParser::PROMELA_STMNT); if (parser.type == PromelaParser::PROMELA_DECL) evaluateDecl(parser.ast); if (parser.type == PromelaParser::PROMELA_STMNT) evaluateStmnt(parser.ast); // parser.dump(); // std::cout << Data::toJSON(_variables) << std::endl; }
void XPathDataModel::init(const Element<std::string>& dataElem, const Node<std::string>& node, const std::string& content) { std::string location; if (HAS_ATTR(dataElem, "id")) { location = ATTR(dataElem, "id"); } else if (HAS_ATTR(dataElem, "location")) { location = ATTR(dataElem, "location"); } NodeSet<std::string> nodeSet; if (node || (content.length() > 0)) { _datamodel.appendChild(_doc.importNode(dataElem, true)); nodeSet.push_back(dataElem); } else if (HAS_ATTR(dataElem, "expr")) { try { Element<std::string> container = _doc.createElement("data"); container.setAttribute("id", location); XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc); switch (expr.type()) { case NODE_SET: { for (size_t i = 0; i < expr.asNodeSet().size(); i++) { container.appendChild(expr.asNodeSet()[i].cloneNode(true)); nodeSet.push_back(expr.asNodeSet()[i].cloneNode(true)); } break; } case STRING: container.appendChild(_doc.createTextNode(expr.asString())); nodeSet.push_back(_doc.createTextNode(expr.asString())); break; case NUMBER: { container.appendChild(_doc.createTextNode(toStr(expr.asNumber()))); nodeSet.push_back(_doc.createTextNode(toStr(expr.asNumber()))); break; } case Arabica::XPath::BOOL: case ANY: ERROR_EXECUTION_THROW("expr evaluates to type ANY"); } _datamodel.appendChild(container); } catch (SyntaxException e) { ERROR_EXECUTION_THROW(e.what()); } } else { LOG(ERROR) << "data element has no content"; } _varResolver.setVariable(location, nodeSet); }
static void printNodeSet(const std::list<XERCESC_NS::DOMElement*> nodes) { std::string seperator; for (auto nIter = nodes.begin(); nIter != nodes.end(); nIter++) { std::cerr << seperator << (HAS_ATTR(*nIter, "id") ? ATTR(*nIter, "id") : DOMUtils::xPathForNode(*nIter)); seperator = ", "; } }
char * __mod_ssl_sni_common_handler (MyQttCtx * myqtt_ctx, MyQttConn * conn, const char * serverName, axlPointer user_data, const char * attr_name) { MyQttdCtx * ctx = user_data; axlNode * node; /* find certificate node by Name */ node = __mod_ssl_get_certificate_node_by_name (ctx, serverName); if (! node) { wrn ("No certificate was found for serverName=%s, requested by connecting ip=%s", serverName, myqtt_conn_get_host_ip (conn)); return NULL; /* no node certificate was found, finish * here */ } /* end if */ if (! HAS_ATTR (node, attr_name)) { wrn ("No certificate was found for serverName=%s, requested by connecting ip=%s, node %s attribute was not defined", serverName, myqtt_conn_get_host_ip (conn), attr_name); return NULL; /* no crt attr was found, finish here */ } /* end if */ /* ok, now report certificate location */ if (__mod_ssl_debug) msg ("Reporting certificate %s=%s for serverName=%s", attr_name, ATTR_VALUE (node, attr_name), serverName); /* report certificate */ return axl_strdup (ATTR_VALUE (node, attr_name)); }
std::list<Breakpoint> Debugger::getQualifiedInvokeBreakpoints(InterpreterImpl* impl, const XERCESC_NS::DOMElement* invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) { std::list<Breakpoint> breakpoints; Breakpoint bp = breakpointTemplate; // copy base as template bp.subject = Breakpoint::INVOKER; bp.element = invokeElem; bp.invokeId = invokeId; if (HAS_ATTR(invokeElem, "type")) { bp.invokeType = ATTR(invokeElem, "type"); } else if (HAS_ATTR(invokeElem, "typeexpr")) { bp.invokeType = impl->evalAsData(ATTR(invokeElem, "typeexpr")).atom; } breakpoints.push_back(bp); return breakpoints; }
std::list<Breakpoint> getQualifiedInvokeBreakpoints(Interpreter interpreter, const Arabica::DOM::Element<std::string>& invokeElem, const std::string invokeId, Breakpoint breakpointTemplate) { std::list<Breakpoint> breakpoints; Breakpoint bp = breakpointTemplate; // copy base as template bp.subject = Breakpoint::INVOKER; bp.element = invokeElem; bp.invokeId = invokeId; if (HAS_ATTR(invokeElem, "type")) { bp.invokeType = ATTR(invokeElem, "type"); } else if (HAS_ATTR(invokeElem, "typeexpr")) { bp.invokeType = interpreter.getDataModel().evalAsString(ATTR(invokeElem, "typeexpr")); } breakpoints.push_back(bp); return breakpoints; }
void XPathDataModel::assign(const NodeSet<std::string>& key, const std::string& value, const Element<std::string>& assignElem) { if (key.size() == 0) return; for (size_t i = 0; i < key.size(); i++) { Node<std::string> node = key[i]; switch (node.getNodeType()) { case Node_base::ATTRIBUTE_NODE: { Attr<std::string> attr(node); attr.setValue(value); break; } case Node_base::TEXT_NODE: { Text<std::string> text(node); text.setNodeValue(value); break; } case Node_base::ELEMENT_NODE: { Element<std::string> element(node); if (HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "addattribute")) { // addattribute: Add an attribute with the name specified by 'attr' // and value specified by 'expr' to the node specified by 'location'. if (!HAS_ATTR(assignElem, "attr")) ERROR_EXECUTION_THROW("Assign element is missing 'attr'"); element.setAttribute(ATTR(assignElem, "attr"), value); } else { /// test 547 while(element.hasChildNodes()) element.removeChild(element.getChildNodes().item(0)); Text<std::string> text = _doc.createTextNode(value); element.appendChild(text); } break; } default: ERROR_EXECUTION_THROW("Unsupported node type with assign"); break; } } }
Arabica::XPath::NodeSet<std::string> InterpreterDraft6::selectEventlessTransitions() { Arabica::XPath::NodeSet<std::string> enabledTransitions; NodeSet<std::string> states; for (unsigned int i = 0; i < _configuration.size(); i++) { if (isAtomic(_configuration[i])) states.push_back(_configuration[i]); } states.to_document_order(); #if 0 std::cout << "Atomic States: "; for (int i = 0; i < atomicStates.size(); i++) { std::cout << ATTR(atomicStates[i], "id") << ", "; } std::cout << std::endl; #endif unsigned int index = 0; while(states.size() > index) { bool foundTransition = false; NodeSet<std::string> transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", states[index]); for (unsigned int k = 0; k < transitions.size(); k++) { if (!HAS_ATTR(transitions[k], "event") && hasConditionMatch(transitions[k])) { enabledTransitions.push_back(transitions[k]); foundTransition = true; goto LOOP; } } if (!foundTransition) { Node<std::string> parent = states[index].getParentNode(); if (parent) { states.push_back(parent); } } LOOP: index++; } #if 0 std::cout << "Enabled eventless transitions: " << std::endl; for (int i = 0; i < enabledTransitions.size(); i++) { std::cout << enabledTransitions[i] << std::endl << "----" << std::endl; } std::cout << std::endl; #endif enabledTransitions = filterPreempted(enabledTransitions); return enabledTransitions; }
void FetchElement::enterElement(const Arabica::DOM::Element<std::string>& node) { if (!HAS_ATTR(node, "src") && !HAS_ATTR(node, "srcexpr")) { LOG(ERROR) << "Fetch element requires src or srcexpr"; return; } if (HAS_ATTR(node, "srcexpr") && !_interpreter->getDataModel()) { LOG(ERROR) << "Fetch element with srcexpr requires datamodel"; return; } _source = (HAS_ATTR(node, "src") ? ATTR(node, "src") : _interpreter->getDataModel().evalAsString(ATTR(node, "srcexpr"))); if (!HAS_ATTR(node, "callback") && !HAS_ATTR(node, "callbackexpr")) { LOG(ERROR) << "Fetch element requires callback or callbackexpr"; return; } if (HAS_ATTR(node, "callbackexpr") && !_interpreter->getDataModel()) { LOG(ERROR) << "Fetch element with callbackexpr requires datamodel"; return; } _callback = (HAS_ATTR(node, "callback") ? ATTR(node, "callback") : _interpreter->getDataModel().evalAsString(ATTR(node, "callbackexpr"))); _type = (HAS_ATTR(node, "type") ? ATTR(node, "type") : "text"); if (!iequals(_type, "text") && !iequals(_type, "url") && !iequals(_type, "json") && !iequals(_type, "xml")) { LOG(ERROR) << "Fetch element type attribute not one of text, url, json, xml."; return; } _targetUrl = URL(_source); if (!_targetUrl.isAbsolute()) { if (!_targetUrl.toAbsolute(_interpreter->getBaseURL(node))) { LOG(ERROR) << "Cannot transform " << _source << " into absolute URL"; return; } } _targetUrl.addMonitor(this); URLFetcher::fetchURL(_targetUrl); }
bool InterpreterDraft6::isWithinParallel(const Node<std::string>& transition) { if (isTargetless(transition)) return false; Node<std::string> source; if (HAS_ATTR(transition, "type") && iequals(ATTR(transition, "type"), "internal")) { source = getSourceState(transition); } else { source = getSourceState(transition).getParentNode(); } NodeSet<std::string> targets = getTargetStates(transition); targets.push_back(source); Node<std::string> lcpa = findLCPA(targets); return lcpa; }
void DebugSession::breakExecution(Data replyData) { std::lock_guard<std::recursive_mutex> lock(_mutex); std::list<XERCESC_NS::DOMElement*> configuration = _interpreter.getConfiguration(); for (auto state : configuration) { if (HAS_ATTR(state, "id")) { replyData.compound["activeStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); if (isAtomic(state)) { replyData.compound["basicStates"].array.push_back(Data(ATTR(state, "id"), Data::VERBATIM)); } } } replyData.compound["replyType"] = Data("breakpoint", Data::VERBATIM); _debugger->pushData(shared_from_this(), replyData); // wait for resume from the client _resumeCond.wait(_mutex); }
/** * @brief Init the valvulad log module. */ void valvulad_log_init (ValvuladCtx * ctx) { /* get current valvulad configuration */ axlDoc * doc = ctx->config; axlNode * node; /* check log reporting */ node = axl_doc_get (doc, "/valvula/global-settings/log-reporting"); if (node == NULL) { abort_error ("Unable to find log configuration <valvula/global-settings/log-reporting>"); return; } /* end if */ /* check enabled attribute */ if (! HAS_ATTR (node, "enabled")) { abort_error ("Missing attribute 'enabled' located at <valvula/global-settings/log-reporting>. Unable to determine if log is enabled"); return; } /* check if log reporting is enabled or not */ if (! HAS_ATTR_VALUE (node, "enabled", "yes")) { msg ("log reporting to file disabled"); return; } /* check for syslog usage */ ctx->use_syslog = HAS_ATTR_VALUE (node, "use-syslog", "yes"); msg ("Checking for usage of syslog %d", ctx->use_syslog); if (ctx->use_syslog) { /* open syslog */ openlog ("valvulad", LOG_PID, LOG_MAIL); msg ("Using syslog facility for logging"); return; } /* end if */ return; }
/** * @internal Function that creates a connection to the MySQL database * configured on the xml node. */ MYSQL * mod_sasl_mysql_get_connection (TurbulenceCtx * ctx, axlNode * auth_db_node_conf, axlError ** err) { MYSQL * conn; int port = 0; int reconnect = 1; axlDoc * doc; axlNode * node; if (ctx == NULL || auth_db_node_conf == NULL) { axl_error_report (err, -1, "Received null ctx, auth db node or sql query, failed to run SQL command"); return NULL; } /* end if */ /* check if the connection is already defined */ conn = axl_node_annotate_get (auth_db_node_conf, "mysql-conn", axl_false); if (conn) { /* reuse connection */ return conn; } /* end if */ /* get document containing MySQL settings */ doc = axl_node_annotate_get (auth_db_node_conf, "mysql-conf", axl_false); if (doc == NULL) { axl_error_report (err, -1, "Found no xml document defining MySQL settings to connect to the database"); return NULL; } /* end if */ /* get the node that contains the configuration */ node = axl_doc_get (doc, "/sasl-auth-db/connection-settings"); /* create a mysql connection */ conn = mysql_init (NULL); /* get port */ if (HAS_ATTR (node, "port") && strlen (ATTR_VALUE (node, "port")) > 0) { /* get port configured by the user */ port = atoi (ATTR_VALUE (node, "port")); } /* create a connection */ if (mysql_real_connect (conn, /* get host */ ATTR_VALUE (node, "host"), /* get user */ ATTR_VALUE (node, "user"), /* get password */ ATTR_VALUE (node, "password"), /* get database */ ATTR_VALUE (node, "database"), port, NULL, 0) == NULL) { axl_error_report (err, mysql_errno (conn), "Mysql connect error: %s, failed to run SQL command", mysql_error (conn)); return NULL; } /* end if */ /* flag here to reconnect in case of lost connection */ mysql_options (conn, MYSQL_OPT_RECONNECT, (const char *) &reconnect); /* record connection */ axl_node_annotate_data_full (auth_db_node_conf, "mysql-conn", NULL, conn, (axlDestroyFunc) mysql_close); return conn; }
void RespondElement::enterElement(const Arabica::DOM::Element<std::string>& node) { // try to get the request id if (!HAS_ATTR(node, "to")) { LOG(ERROR) << "Respond element requires to attribute"; return; } if (HAS_ATTR(node, "to") && !_interpreter->getDataModel()) { LOG(ERROR) << "Respond element with to requires datamodel"; return; } std::string requestId = _interpreter->getDataModel().evalAsString(ATTR(node, "to")); // try to get the request object InterpreterHTTPServlet* servlet = _interpreter->getHTTPServlet(); tthread::lock_guard<tthread::recursive_mutex> lock(servlet->getMutex()); if (servlet->getRequests().find(requestId) == servlet->getRequests().end()) { LOG(ERROR) << "No matching HTTP request for respond element"; return; } assert(servlet->getRequests().find(requestId) != servlet->getRequests().end()); HTTPServer::Request httpReq = servlet->getRequests()[requestId]; assert(httpReq.evhttpReq != NULL); HTTPServer::Reply httpReply(httpReq); servlet->getRequests().erase(requestId); // get the status or default to 200 std::string statusStr = (HAS_ATTR(node, "status") ? ATTR(node, "status") : "200"); if (!isNumeric(statusStr.c_str(), 10)) { LOG(ERROR) << "Respond element with non-numeric status " << statusStr; return; } httpReply.status = strTo<int>(statusStr);; // extract the content Arabica::XPath::NodeSet<std::string> contents = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "content", node); if (contents.size() > 0) { Arabica::DOM::Element<std::string> contentElem = Arabica::DOM::Element<std::string>(contents[0]); if (HAS_ATTR(contentElem, "expr")) { // -- content is evaluated string from datamodel ------ if (_interpreter->getDataModel()) { try { Data contentData = _interpreter->getDataModel().getStringAsData(ATTR(contentElem, "expr")); if (contentData.atom.length() > 0) { httpReply.content = contentData.atom; httpReply.headers["Content-Type"] = "text/plain"; } else if (contentData.binary) { httpReply.content = std::string(contentData.binary.getData(), contentData.binary.getSize()); httpReply.headers["Content-Type"] = contentData.binary.getMimeType(); } else if (contentData.node) { std::stringstream ss; ss << contentData.node; httpReply.content = ss.str();; httpReply.headers["Content-Type"] = "application/xml"; } else { httpReply.content = Data::toJSON(contentData); httpReply.headers["Content-Type"] = "application/json"; } } catch (Event e) { LOG(ERROR) << "Syntax error with expr in content child of Respond element:" << std::endl << e << std::endl; return; } } else { LOG(ERROR) << "content element has expr attribute but no datamodel is specified."; return; } } else if (HAS_ATTR(contentElem, "file") || HAS_ATTR(contentElem, "fileexpr")) { // -- content is from file ------ URL file; if (HAS_ATTR(contentElem, "fileexpr")) { if (_interpreter->getDataModel()) { try { file = "file://" + _interpreter->getDataModel().evalAsString(ATTR(contentElem, "fileexpr")); } catch (Event e) { LOG(ERROR) << "Syntax error with fileexpr in content child of Respond element:" << std::endl << e << std::endl; return; } } } else { file = "file://" + ATTR(contentElem, "fileexpr"); } if (file) { httpReply.content = file.getInContent(); size_t lastDot; if ((lastDot = file.path().find_last_of(".")) != std::string::npos) { std::string extension = file.path().substr(lastDot + 1); std::string mimeType = URL::getMimeType(extension); if (mimeType.length() > 0) { httpReply.headers["Content-Type"] = mimeType; } } } } else if (contents[0].hasChildNodes()) { // -- content embedded as child nodes ------ httpReply.content = contents[0].getFirstChild().getNodeValue(); } else { LOG(ERROR) << "content element does not specify any content."; return; } } // process headers Arabica::XPath::NodeSet<std::string> headers = InterpreterImpl::filterChildElements(_interpreter->getNameSpaceInfo().getXMLPrefixForNS(getNamespace()) + "header", node); for (int i = 0; i < headers.size(); i++) { Arabica::DOM::Element<std::string> headerElem = Arabica::DOM::Element<std::string>(headers[i]); std::string name; if (HAS_ATTR(headerElem, "name")) { name = ATTR(headerElem, "name"); } else if(HAS_ATTR(headerElem, "nameexpr")) { if (_interpreter->getDataModel()) { try { name = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "nameexpr")); } catch (Event e) { LOG(ERROR) << "Syntax error with nameexpr in header child of Respond element:" << std::endl << e << std::endl; return; } } else { LOG(ERROR) << "header element has nameexpr attribute but no datamodel is specified."; return; } } else { LOG(ERROR) << "header element has no name or nameexpr attribute."; return; } std::string value; if (HAS_ATTR(headerElem, "value")) { value = ATTR(headerElem, "value"); } else if(HAS_ATTR(headerElem, "valueexpr")) { if (_interpreter->getDataModel()) { try { value = _interpreter->getDataModel().evalAsString(ATTR(headerElem, "valueexpr")); } catch (Event e) { LOG(ERROR) << "Syntax error with valueexpr in header child of Respond element:" << std::endl << e << std::endl; return; } } else { LOG(ERROR) << "header element has valueexpr attribute but no datamodel is specified."; return; } } else { LOG(ERROR) << "header element has no value or valueexpr attribute."; return; } httpReply.headers[name] = value; } // send the reply HTTPServer::reply(httpReply); servlet->getRequests().erase(requestId); }
void XPathDataModel::assign(const Element<std::string>& key, const NodeSet<std::string>& value, const Element<std::string>& assignElem) { Element<std::string> element(key); if (value.size() == 0 || !value[0]) return; if (false) { } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "firstchild")) { // firstchild: Insert the value specified by 'expr' before all of the children at 'location'. for (size_t i = value.size(); i; i--) { Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true)); element.insertBefore(importedNode, element.getFirstChild()); } } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "lastchild")) { // lastchild: Insert the value specified by 'expr' after all of the children at 'location'. for (size_t i = 0; i < value.size(); i++) { Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true)); element.appendChild(importedNode); } } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "previoussibling")) { // previoussibling: Insert the value specified by 'expr' before the // node specified by 'location', keeping the same parent. Node<std::string> parent = element.getParentNode(); if (!parent) ERROR_EXECUTION_THROW("Node has no parent"); for (size_t i = 0; i < value.size(); i++) { Node<std::string> importedNode = (value[i].getOwnerDocument() == _doc ? value[i].cloneNode(true) : _doc.importNode(value[i], true)); parent.insertBefore(importedNode, element); } } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "nextsibling")) { // nextsibling: Insert the value specified by 'expr' after the node // specified by 'location', keeping the same parent. Node<std::string> parent = element.getParentNode(); if (!parent) ERROR_EXECUTION_THROW("Node has no parent"); for (size_t i = value.size(); i; i--) { Node<std::string> importedNode = (value[i-1].getOwnerDocument() == _doc ? value[i-1].cloneNode(true) : _doc.importNode(value[i-1], true)); Node<std::string> nextSibling = element.getNextSibling(); if (nextSibling) { parent.insertBefore(importedNode, element.getNextSibling()); } else { parent.appendChild(importedNode); } } } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "replace")) { // replace: Replace the node specified by 'location' by the value specified by 'expr'. Node<std::string> parent = element.getParentNode(); if (!parent) ERROR_EXECUTION_THROW("Node has no parent"); if (value.size() != 1) ERROR_EXECUTION_THROW("Value not singular"); Node<std::string> importedNode = (value[0].getOwnerDocument() == _doc ? value[0].cloneNode(true) : _doc.importNode(value[0], true)); parent.replaceChild(importedNode, element); } else if (assignElem && HAS_ATTR(assignElem, "type") && iequals(ATTR(assignElem, "type"), "delete")) { // delete: Delete the node specified by 'location'. ('expr' is ignored.). Node<std::string> parent = element.getParentNode(); if (!parent) ERROR_EXECUTION_THROW("Node has no parent"); parent.removeChild(element); } else { // replacechildren: Replace all the children at 'location' with the value specified by 'expr'. while(element.hasChildNodes()) element.removeChild(element.getChildNodes().item(0)); for (size_t i = 0; i < value.size(); i++) { Node<std::string> importedNode = element.getOwnerDocument().importNode(value[i], true); element.appendChild(importedNode); } } }
/** * @internal Terminates the myqttd excution, returing the exit signal * provided as first parameter. This function is used to notify a * context that a signal was received. * * @param ctx The myqttd context to terminate. * @param _signal The exit code to return. */ void myqttd_signal_exit (MyQttdCtx * ctx, int _signal) { /* get myqttd context */ axlDoc * doc; axlNode * node; MyQttAsyncQueue * queue; char * backtrace_file; /* lock the mutex and check */ myqtt_mutex_lock (&ctx->exit_mutex); if (ctx->is_exiting) { msg ("process already existing, signal received=%d, doing nothing...", _signal); /* other thread is already cleaning */ myqtt_mutex_unlock (&ctx->exit_mutex); return; } /* end if */ msg ("received termination signal (%d) on PID %d, preparing exit process", _signal, getpid ()); /* flag that myqttd is existing and do all cleanup * operations */ ctx->is_exiting = axl_true; myqtt_mutex_unlock (&ctx->exit_mutex); switch (_signal) { case SIGINT: msg ("caught SIGINT, terminating myqttd.."); break; case SIGTERM: msg ("caught SIGTERM, terminating myqttd.."); break; #if defined(AXL_OS_UNIX) case SIGKILL: msg ("caught SIGKILL, terminating myqttd.."); break; case SIGQUIT: msg ("caught SIGQUIT, terminating myqttd.."); break; #endif case SIGSEGV: case SIGABRT: error ("caught %s, anomalous termination (this is an internal myqttd or module error)", _signal == SIGSEGV ? "SIGSEGV" : "SIGABRT"); /* check current termination option */ doc = myqttd_config_get (ctx); node = axl_doc_get (doc, "/myqtt/global-settings/on-bad-signal"); error ("applying configured action %s", (node && HAS_ATTR (node, "action")) ? ATTR_VALUE (node, "action") : "not defined"); if (HAS_ATTR_VALUE (node, "action", "ignore")) { /* do notify if enabled */ CHECK_AND_REPORT_MAIL_TO ("Bad signal received at myqttd process, default action: ignore", "Received termination signal but it was ignored.", NULL); /* ignore the signal emision */ return; } else if (HAS_ATTR_VALUE (node, "action", "hold")) { /* lock the process */ error ("Bad signal found, locking process, now you can attach or terminate pid: %d", getpid ()); CHECK_AND_REPORT_MAIL_TO ("Bad signal received a myqttd process, default action: hold", "Received termination signal and the process was hold for examination", NULL); queue = myqtt_async_queue_new (); myqtt_async_queue_pop (queue); return; } else if (HAS_ATTR_VALUE (node, "action", "backtrace")) { /* create temporal file */ error ("Bad signal found, creating backtrace for current process: %d", getpid ()); backtrace_file = myqttd_support_get_backtrace (ctx, getpid ()); if (backtrace_file == NULL) error ("..backtrace error, unable to produce backtrace.."); else error ("..backtrace created at: %s", backtrace_file); /* check if we have to do a mail notification */ CHECK_AND_REPORT_MAIL_TO ("Bad signal received a myqttd process, default action: backtrace", NULL, backtrace_file); /* release backtrace */ axl_free (backtrace_file); } /* signal myqtt to not terminate threads (to avoid * deadlocks) */ exit (-1); break; default: msg ("terminating myqttd.."); break; } /* end if */ /* Unlock the listener here. Do not perform any deallocation * operation here because we are in the middle of a signal * handler execution. By unlocking the listener, the * myqttd_cleanup is called cleaning the room. */ msg ("Unlocking myqttd listener: %p", ctx); /* unlock the current listener */ myqtt_listener_unlock (MYQTTD_MYQTT_CTX (ctx)); return; } /* end if */
// a macrostep InterpreterState InterpreterDraft6::step(bool blocking) { try { monIter_t monIter; NodeSet<std::string> enabledTransitions; // setup document and interpreter if (!_isInitialized) init(); // if we failed return false if (!_isInitialized) return INIT_FAILED; // run initial transitions if (!_stable) { stabilize(); // we might only need a single step if (!_running) goto EXIT_INTERPRETER; return INITIALIZED; } if (!_running) return FINISHED; // read an external event and react if (blocking) { // wait until an event becomes available while(_externalQueue.isEmpty()) { _condVar.wait(_mutex); } } else { // return immediately if external queue is empty if (_externalQueue.isEmpty()) return NOTHING_TODO; } _currEvent = _externalQueue.pop(); #if VERBOSE std::cout << "Received externalEvent event " << _currEvent.name << std::endl; if (_running && _currEvent.name == "unblock.and.die") { std::cout << "Still running " << this << std::endl; } else { std::cout << "Aborting " << this << std::endl; } #endif _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external // when we were blocking on destructor invocation if (!_running) { goto EXIT_INTERPRETER; return INTERRUPTED; } // --- MONITOR: beforeProcessingEvent ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); } USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) } if (iequals(_currEvent.name, "cancel.invoke." + _sessionId)) return INTERRUPTED; try { _dataModel.setEvent(_currEvent); } catch (Event e) { LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent; } for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin(); invokeIter != _invokers.end(); invokeIter++) { if (iequals(invokeIter->first, _currEvent.invokeid)) { Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement()); for (int k = 0; k < finalizes.size(); k++) { Element<std::string> finalizeElem = Element<std::string>(finalizes[k]); executeContent(finalizeElem); } } if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) { try { // do not autoforward to invokers that send to #_parent from the SCXML IO Processor! // Yes do so, see test229! // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) invokeIter->second.send(_currEvent); } catch(...) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first; } } } // run internal processing until we reach a stable configuration again enabledTransitions = selectTransitions(_currEvent.name); if (!enabledTransitions.empty()) { // test 403b enabledTransitions.to_document_order(); microstep(enabledTransitions); } stabilize(); return PROCESSED; EXIT_INTERPRETER: if (!_running) { // --- MONITOR: beforeCompletion ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeCompletion(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(beforeCompletion) } exitInterpreter(); if (_sendQueue) { std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin(); while(sendIter != _sendIds.end()) { _sendQueue->cancelEvent(sendIter->first); sendIter++; } } // --- MONITOR: afterCompletion ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->afterCompletion(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(afterCompletion) } return FINISHED; } assert(hasLegalConfiguration()); _mutex.unlock(); // remove datamodel if(_dataModel) _dataModel = DataModel(); return PROCESSED; } catch (boost::bad_weak_ptr e) { LOG(ERROR) << "Unclean shutdown " << std::endl << std::endl; return INTERRUPTED; } // set datamodel to null from this thread if(_dataModel) _dataModel = DataModel(); }
void XPathDataModel::assign(const Element<std::string>& assignElem, const Node<std::string>& node, const std::string& content) { std::string location; if (HAS_ATTR(assignElem, "id")) { location = ATTR(assignElem, "id"); } else if (HAS_ATTR(assignElem, "location")) { location = ATTR(assignElem, "location"); } // test 326ff XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); #ifdef VERBOSE LOG(INFO) << "Key XPath : " << key.asString(); #endif #if 0 if (key.type() == NODE_SET) { try { for (size_t i = 0; i < key.asNodeSet().size(); i++) { Node<std::string> node = key.asNodeSet()[i]; if (node == _varResolver.resolveVariable("", "_ioprocessors").asNodeSet()[0]) ERROR_EXECUTION_THROW("Cannot assign _ioProcessors"); if (node == _varResolver.resolveVariable("", "_sessionid").asNodeSet()[0]) ERROR_EXECUTION_THROW("Cannot assign _sessionid"); if (node == _varResolver.resolveVariable("", "_name").asNodeSet()[0]) ERROR_EXECUTION_THROW("Cannot assign _name"); if (node == _varResolver.resolveVariable("", "_event").asNodeSet()[0]) ERROR_EXECUTION_THROW("Cannot assign _event"); } } catch (Event e) {} } #endif NodeSet<std::string> nodeSet; if (node) { Node<std::string> data = node; while (data) { // do not add empty text as a node if (data.getNodeType() == Node_base::TEXT_NODE) { std::string trimmed = data.getNodeValue(); boost::trim(trimmed); if (trimmed.length() == 0) { data = data.getNextSibling(); continue; } } nodeSet.push_back(data); data = data.getNextSibling(); } assign(key, nodeSet, assignElem); } else if (content.length() > 0) { Text<std::string> textNode = _doc.createTextNode(spaceNormalize(content)); nodeSet.push_back(textNode); assign(key, nodeSet, assignElem); } else if (HAS_ATTR(assignElem, "expr")) { XPathValue<std::string> value = _xpath.evaluate_expr(ATTR(assignElem, "expr"), _doc); #ifdef VERBOSE LOG(INFO) << "Value XPath : " << value.asString(); #endif assign(key, value, assignElem); } else { LOG(ERROR) << "assign element has no content"; } // std::cout << _datamodel << std::endl; }
// process transitions until we are in a stable configuration again void InterpreterDraft6::stabilize() { monIter_t monIter; NodeSet<std::string> enabledTransitions; _stable = false; if (_configuration.size() == 0) { // goto initial configuration NodeSet<std::string> initialTransitions = getDocumentInitialTransitions(); assert(initialTransitions.size() > 0); enterStates(initialTransitions); } do { // process microsteps for enabled transitions until there are no more left enabledTransitions = selectEventlessTransitions(); if (enabledTransitions.size() == 0) { if (_internalQueue.size() == 0) { _stable = true; } else { _currEvent = _internalQueue.front(); _internalQueue.pop_front(); #if VERBOSE std::cout << "Received internal event " << _currEvent.name << std::endl; #endif // --- MONITOR: beforeProcessingEvent ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); } USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) } if (_dataModel) _dataModel.setEvent(_currEvent); enabledTransitions = selectTransitions(_currEvent.name); } } if (!enabledTransitions.empty()) { // test 403b enabledTransitions.to_document_order(); microstep(enabledTransitions); } } while(!_internalQueue.empty() || !_stable); monIter = _monitors.begin(); // --- MONITOR: onStableConfiguration ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->onStableConfiguration(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration) } // when we reach a stable configuration, invoke for (unsigned int i = 0; i < _statesToInvoke.size(); i++) { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]); for (unsigned int j = 0; j < invokes.size(); j++) { if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) { invoke(invokes[j]); } } } _statesToInvoke = NodeSet<std::string>(); }
void StateTransitionMonitor::beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { std::lock_guard<std::recursive_mutex> lock(_mutex); std::cerr << "Entering: " << (HAS_ATTR(state, "id") ? ATTR(state, "id") : DOMUtils::xPathForNode(state)) << std::endl; }
void InterpreterDraft6::mainEventLoop() { monIter_t monIter; while(_running) { NodeSet<std::string> enabledTransitions; _stable = false; // Here we handle eventless transitions and transitions // triggered by internal events until machine is stable while(_running && !_stable) { #if VERBOSE std::cout << "Configuration: "; for (int i = 0; i < _configuration.size(); i++) { std::cout << ATTR(_configuration[i], "id") << ", "; } std::cout << std::endl; #endif enabledTransitions = selectEventlessTransitions(); if (enabledTransitions.size() == 0) { if (_internalQueue.size() == 0) { _stable = true; } else { _currEvent = _internalQueue.front(); _internalQueue.pop_front(); #if VERBOSE std::cout << "Received internal event " << _currEvent.name << std::endl; #endif // --- MONITOR: beforeProcessingEvent ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); } USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) } if (_dataModel) _dataModel.setEvent(_currEvent); enabledTransitions = selectTransitions(_currEvent.name); } } if (!enabledTransitions.empty()) { // test 403b enabledTransitions.to_document_order(); microstep(enabledTransitions); } } for (unsigned int i = 0; i < _statesToInvoke.size(); i++) { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _statesToInvoke[i]); for (unsigned int j = 0; j < invokes.size(); j++) { if (!HAS_ATTR(invokes[j], "persist") || !DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) { invoke(invokes[j]); } } } _statesToInvoke = NodeSet<std::string>(); if (!_internalQueue.empty()) continue; // assume that we have a legal configuration as soon as the internal queue is empty assert(hasLegalConfiguration()); monIter = _monitors.begin(); // --- MONITOR: onStableConfiguration ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->onStableConfiguration(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(onStableConfiguration) } _mutex.unlock(); // whenever we have a stable configuration, run the mainThread hooks with 200fps while(_externalQueue.isEmpty() && _thread == NULL) { runOnMainThread(200); } _mutex.lock(); while(_externalQueue.isEmpty()) { _condVar.wait(_mutex); } _currEvent = _externalQueue.pop(); #if VERBOSE std::cout << "Received externalEvent event " << _currEvent.name << std::endl; if (_running && _currEvent.name == "unblock.and.die") { std::cout << "Still running " << this << std::endl; } else { std::cout << "Aborting " << this << std::endl; } #endif _currEvent.eventType = Event::EXTERNAL; // make sure it is set to external if (!_running) goto EXIT_INTERPRETER; // --- MONITOR: beforeProcessingEvent ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeProcessingEvent(shared_from_this(), _currEvent); } USCXML_MONITOR_CATCH_BLOCK(beforeProcessingEvent) } if (_dataModel && iequals(_currEvent.name, "cancel.invoke." + _sessionId)) break; if (_dataModel) { try { _dataModel.setEvent(_currEvent); } catch (Event e) { LOG(ERROR) << "Syntax error while setting external event:" << std::endl << e << std::endl << _currEvent; } } for (std::map<std::string, Invoker>::iterator invokeIter = _invokers.begin(); invokeIter != _invokers.end(); invokeIter++) { if (iequals(invokeIter->first, _currEvent.invokeid)) { Arabica::XPath::NodeSet<std::string> finalizes = filterChildElements(_nsInfo.xmlNSPrefix + "finalize", invokeIter->second.getElement()); for (int k = 0; k < finalizes.size(); k++) { Element<std::string> finalizeElem = Element<std::string>(finalizes[k]); executeContent(finalizeElem); } } if (HAS_ATTR(invokeIter->second.getElement(), "autoforward") && DOMUtils::attributeIsTrue(ATTR(invokeIter->second.getElement(), "autoforward"))) { try { // do not autoforward to invokers that send to #_parent from the SCXML IO Processor! // Yes do so, see test229! // if (!boost::equals(_currEvent.getOriginType(), "http://www.w3.org/TR/scxml/#SCXMLEventProcessor")) invokeIter->second.send(_currEvent); } catch(...) { LOG(ERROR) << "Exception caught while sending event to invoker " << invokeIter->first; } } } enabledTransitions = selectTransitions(_currEvent.name); if (!enabledTransitions.empty()) { // test 403b enabledTransitions.to_document_order(); microstep(enabledTransitions); } } EXIT_INTERPRETER: // --- MONITOR: beforeCompletion ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeCompletion(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(beforeCompletion) } exitInterpreter(); if (_sendQueue) { std::map<std::string, std::pair<InterpreterImpl*, SendRequest> >::iterator sendIter = _sendIds.begin(); while(sendIter != _sendIds.end()) { _sendQueue->cancelEvent(sendIter->first); sendIter++; } } // --- MONITOR: afterCompletion ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->afterCompletion(shared_from_this()); } USCXML_MONITOR_CATCH_BLOCK(afterCompletion) } }
int tbc_mod_gen_compile () { axlDtd * dtd; axlDoc * doc; axlError * error; axlNode * node; axlNode * moddef; char * mod_name; char * tolower; char * toupper; char * description; /* parse DTD document */ dtd = axl_dtd_parse (TBC_MOD_GEN_DTD, -1, &error); if (dtd == NULL) { /* report error and dealloc resources */ error ("Failed to parse DTD, error found: %s", axl_error_get (error)); axl_error_free (error); return axl_false; } /* end if */ /* nice, now parse the xml file */ doc = axl_doc_parse_from_file (exarg_get_string ("compile"), &error); if (doc == NULL) { /* report error and dealloc resources */ error ("unable to parse file: %s, error found: %s", exarg_get_string ("compile"), axl_error_get (error)); axl_error_free (error); axl_dtd_free (dtd); } /* end if */ /* nice, now validate content */ if (! axl_dtd_validate (doc, dtd, &error)) { /* report error and dealloc */ error ("failed to validate module description provided: %s, error found: %s", exarg_get_string ("compile"), axl_error_get (error)); axl_error_free (error); axl_doc_free (doc); axl_dtd_free (dtd); return axl_false; } /* end if */ /* ok, now produce source code */ axl_dtd_free (dtd); /* open file */ moddef = axl_doc_get_root (doc); node = axl_doc_get (doc, "/mod-def/name"); mod_name = (char *) axl_node_get_content (node, NULL); mod_name = support_clean_name (mod_name); tolower = support_to_lower (mod_name); toupper = support_to_upper (mod_name); /* out dir */ support_open_file (ctx, "%s%s.c", get_out_dir (), mod_name); /* place copyright if found */ node = axl_doc_get (doc, "/mod-def/copyright"); if (node != NULL) { /* place the copyright */ } /* end if */ write ("/* %s implementation */\n", mod_name); write ("#include <turbulence.h>\n\n"); write ("/* use this declarations to avoid c++ compilers to mangle exported\n"); write (" * names. */\n"); write ("BEGIN_C_DECLS\n\n"); write ("/* global turbulence context reference */\n"); write ("TurbulenceCtx * ctx = NULL;\n\n"); /* place here additional content */ node = axl_doc_get (doc, "/mod-def/source-code/additional-content"); if (node != NULL) { write ("%s\n", axl_node_get_content (node, NULL)); } /* end if */ /* init handler */ write ("/* %s init handler */\n", mod_name); write ("static int %s_init (TurbulenceCtx * _ctx) {\n", tolower); push_indent (); write ("/* configure the module */\n"); write ("TBC_MOD_PREPARE (_ctx);\n\n"); pop_indent (); node = axl_doc_get (doc, "/mod-def/source-code/init"); if (axl_node_get_content (node, NULL)) { /* write the content defined */ write ("%s\n", axl_node_get_content (node, NULL)); } write ("} /* end %s_init */\n\n", tolower); /* close handler */ write ("/* %s close handler */\n", mod_name); write ("static void %s_close (TurbulenceCtx * _ctx) {\n", tolower); node = axl_doc_get (doc, "/mod-def/source-code/close"); if (axl_node_get_content (node, NULL)) { /* write the content defined */ write ("%s\n", axl_node_get_content (node, NULL)); } write ("} /* end %s_close */\n\n", tolower); /* reconf handler */ write ("/* %s reconf handler */\n", mod_name); write ("static void %s_reconf (TurbulenceCtx * _ctx) {\n", tolower); node = axl_doc_get (doc, "/mod-def/source-code/reconf"); if (axl_node_get_content (node, NULL)) { /* write the content defined */ write ("%s\n", axl_node_get_content (node, NULL)); } write ("} /* end %s_reconf */\n\n", tolower); /* unload handler */ write ("/* %s unload handler */\n", mod_name); write ("static void %s_unload (TurbulenceCtx * _ctx) {\n", tolower); node = axl_doc_get (doc, "/mod-def/source-code/unload"); if (axl_node_get_content (node, NULL)) { /* write the content defined */ write ("%s\n", axl_node_get_content (node, NULL)); } write ("} /* end %s_unload */\n\n", tolower); /* ppath_selected handler */ write ("/* %s ppath-selected handler */\n", mod_name); write ("static axl_bool %s_ppath_selected (TurbulenceCtx * _ctx, TurbulencePPathDef * ppath_selected, VortexConnection * conn) {\n", tolower); node = axl_doc_get (doc, "/mod-def/source-code/ppath-selected"); if (axl_node_get_content (node, NULL)) { /* write the content defined */ write ("%s\n", axl_node_get_content (node, NULL)); } write ("} /* end %s_ppath_selected */\n\n", tolower); /* write handler description */ write ("/* Entry point definition for all handlers included in this module */\n"); write ("TurbulenceModDef module_def = {\n"); push_indent (); write ("\"%s\",\n", mod_name); node = axl_doc_get (doc, "/mod-def/description"); description = (char *) axl_node_get_content (node, NULL); write ("\"%s\",\n", description ? description : ""); write ("%s_init,\n", tolower); write ("%s_close,\n", tolower); write ("%s_reconf,\n", tolower); write ("%s_unload,\n", tolower); write ("%s_ppath_selected\n", tolower); pop_indent (); write ("};\n\n"); write ("END_C_DECLS\n\n"); /* close content */ support_close_file (ctx); /* create the makefile required */ support_open_file (ctx, "%sMakefile.am", get_out_dir ()); write ("# Module definition\n"); write ("EXTRA_DIST = %s\n\n", exarg_get_string ("compile")); write ("INCLUDES = -Wall -g -ansi $(TURBULENCE_CFLAGS) -I../../src -DCOMPILATION_DATE=`date +%%s` \\\n"); push_indent (); write ("-DVERSION=\\\"$(VERSION)\\\" \\\n"); write ("$(AXL_CFLAGS) $(VORTEX_CFLAGS) $(EXARG_CFLAGS)\n\n"); pop_indent (); write ("# configure module binary\n"); write ("lib_LTLIBRARIES = %s.la\n", mod_name); write ("%s_la_SOURCES = %s.c %s\n", mod_name, mod_name, HAS_ATTR (moddef, "sources") ? ATTR_VALUE (moddef, "sources") : ""); write ("%s_la_LDFLAGS = -module -ldl\n\n", mod_name); write ("# reconfigure module installation directory\n"); write ("libdir = `turbulence-config --mod-dir`\n\n"); write ("# configure site module installation\n"); write ("modconfdir = `turbulence-config --mod-xml`\n"); write ("modconf_DATA = %s.xml %s.win32.xml\n\n", mod_name, mod_name); write ("%s.xml %s.win32.xml:\n", mod_name, mod_name); push_indent (); write ("echo \"<mod-turbulence location=\\\"`turbulence-config --mod-dir`/%s.so\\\"/>\" > %s.xml\n", mod_name, mod_name); write ("echo \"<mod-turbulence location=\\\"../modules/%s.dll\\\"/>\" > %s.win32.xml\n", mod_name, mod_name); pop_indent (); support_close_file (ctx); /* create autoconf if defined */ if (exarg_is_defined ("enable-autoconf")) { msg ("found autoconf support files request.."); /* create the autogen.sh */ support_open_file (ctx, "%sautogen.sh", get_out_dir ()); write ("# autogen.sh file created by tbc-mod-gen\n"); write ("PACKAGE=\"%s: %s\"\n\n", mod_name, description); write ("(automake --version) < /dev/null > /dev/null 2>&1 || {\n"); push_indent (); write ("echo;\n"); write ("echo \"You must have automake installed to compile $PACKAGE\";\n"); write ("echo;\n"); write ("exit;\n"); pop_indent (); write ("}\n\n"); write ("(autoconf --version) < /dev/null > /dev/null 2>&1 || {\n"); push_indent (); write ("echo;\n"); write ("echo \"You must have autoconf installed to compile $PACKAGE\";\n"); write ("echo;\n"); write ("exit;\n"); pop_indent (); write ("}\n\n"); write ("echo \"Generating configuration files for $PACKAGE, please wait....\"\n"); write ("echo;\n\n"); write ("touch NEWS README AUTHORS ChangeLog\n"); write ("libtoolize --force;\n"); write ("aclocal $ACLOCAL_FLAGS;\n"); write ("autoheader;\n"); write ("automake --add-missing;\n"); write ("autoconf;\n\n"); write ("./configure $@ --enable-maintainer-mode --enable-compile-warnings\n"); support_close_file (ctx); support_make_executable (ctx, "%sautogen.sh", get_out_dir ()); /* now create the configure.ac file */ support_open_file (ctx, "%sconfigure.ac", get_out_dir ()); write ("dnl configure.ac template file created by tbc-mod-gen\n"); write ("AC_INIT(%s.c)\n\n", mod_name); write ("dnl declare a global version value\n"); write ("%s_VERSION=\"0.0.1\"\n", toupper); write ("AC_SUBST(%s_VERSION)\n\n", toupper); write ("AC_CONFIG_AUX_DIR(.)\n"); write ("AM_INIT_AUTOMAKE(%s, $%s_VERSION)\n\n", mod_name, toupper); write ("AC_CONFIG_HEADER(config.h)\n"); write ("AM_MAINTAINER_MODE\n"); write ("AC_PROG_CC\n"); write ("AC_ISC_POSIX\n"); write ("AC_HEADER_STDC\n"); write ("AM_PROG_LIBTOOL\n\n"); write ("dnl external dependencies\n"); write ("PKG_CHECK_MODULES(AXL, axl >= %s)\n\n", AXL_VERSION); write ("dnl general libries subsitution\n"); write ("AC_SUBST(AXL_CFLAGS)\n"); write ("AC_SUBST(AXL_LIBS)\n\n"); write ("dnl external dependencies\n"); write ("PKG_CHECK_MODULES(VORTEX, vortex >= %s) \n\n", VORTEX_VERSION); write ("dnl general libries subsitution\n"); write ("AC_SUBST(VORTEX_CFLAGS)\n"); write ("AC_SUBST(VORTEX_LIBS)\n\n"); write ("dnl external dependencies\n"); write ("PKG_CHECK_MODULES(EXARG, exarg)\n\n"); write ("dnl general libries subsitution\n"); write ("AC_SUBST(EXARG_CFLAGS)\n"); write ("AC_SUBST(EXARG_LIBS)\n\n"); write ("dnl external dependencies\n"); write ("PKG_CHECK_MODULES(TURBULENCE, turbulence >= %s)\n\n", VERSION); write ("dnl general libries subsitution\n"); write ("AC_SUBST(TURBULENCE_CFLAGS)\n"); write ("AC_SUBST(TURBULENCE_LIBS)\n\n"); write ("AC_OUTPUT([\n"); write ("Makefile\n"); write ("])\n\n"); write ("echo \"------------------------------------------\"\n"); write ("echo \"-- mod_template Settings --\"\n"); write ("echo \"------------------------------------------\"\n"); write ("echo \"------------------------------------------\"\n"); write ("echo \"-- Let it BEEP! --\"\n"); write ("echo \"-- --\"\n"); write ("echo \"-- NOW TYPE: make; make install --\"\n"); write ("echo \"------------------------------------------\"\n"); support_close_file (ctx); } /* end if */ /* dealloc */ axl_free (tolower); axl_free (toupper); axl_doc_free (doc); /* create the script file */ support_open_file (ctx, "%sgen-code", get_out_dir ()); write ("#!/bin/sh\n\n"); /* write the mod gen */ write ("tbc-mod-gen --compile %s --out-dir %s\n", exarg_get_string ("compile"), exarg_get_string ("out-dir")); support_close_file (ctx); support_make_executable (ctx, "%sgen-code", get_out_dir ()); msg ("%s created!", mod_name); axl_free (mod_name); return axl_true; }
axl_bool mod_sasl_mysql_do_auth (TurbulenceCtx * ctx, VortexConnection * conn, axlNode * auth_db_node_conf, const char * auth_id, const char * authorization_id, const char * formated_password, const char * password, const char * serverName, const char * sasl_method, axlError ** err) { char * query; axlDoc * doc; axlNode * node; axl_bool _result = axl_false; /* check import parameters without doing anything */ if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, password)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, formated_password)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, serverName)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, authorization_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, sasl_method)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, auth_id)) return axl_false; if (! mod_sasl_mysql_check_unallowed_sequence (ctx, conn, vortex_connection_get_host (conn))) return axl_false; /* get the auth query */ doc = axl_node_annotate_get (auth_db_node_conf, "mysql-conf", axl_false); if (doc == NULL) { axl_error_report (err, -1, "Found no xml document defining MySQL settings to connect to the database"); return axl_false; } /* end if */ /* check for ip filter reference */ node = axl_doc_get (doc, "/sasl-auth-db/ip-filter"); if (node && HAS_ATTR (node, "query")) { /* ip filter defined, get query */ query = axl_strdup (ATTR_VALUE (node, "query")); /* replace query with recognized tokens */ axl_replace (query, "%u", auth_id); axl_replace (query, "%n", serverName); axl_replace (query, "%i", authorization_id); axl_replace (query, "%m", sasl_method); msg ("Checking IP filter for auth id [%s], query [%s]", auth_id, query); if (! mod_sasl_mysql_check_ip_filter_query (ctx, query, conn, auth_db_node_conf)) { error ("login failure: %s, ip filtered by defined expression associated to user: %s denied connection from %s", auth_id, auth_id, vortex_connection_get_host_ip (conn)); axl_free (query); return 0; } msg ("IP not filtered by defined expression associated to user: %s allowed connection from %s", auth_id, vortex_connection_get_host_ip (conn)); /* ip not filtered, now let the auth continue */ axl_free (query); } /* end if */ /***** ALT AUTHENTICATION *****/ /* get alt password if defined <get-password-alt> */ node = axl_doc_get (doc, "/sasl-auth-db/get-password-alt"); if (node) { /* get query */ query = (char *) ATTR_VALUE_TRANS (node, "query"); /* call to do auth operation */ _result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_false, /* skip login error reporting */ axl_true, err); /* clean for cleanup node <get-password-alt-cleanup> */ node = axl_doc_get (doc, "/sasl-auth-db/get-password-alt-cleanup"); if (node) { /* get query */ query = (char *) ATTR_VALUE_TRANS (node, "query"); /* call and skip getting value reported */ if (! __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_true, /* skip login error reporting */ axl_true, err)) error ("Cleanup query failed, please, review <get-password-alt-cleanup>.."); } /* end if */ } /* end if */ /**** MAIN AUTHENTICATION ****/ /* if authentication failed, try with main table */ if (! _result) { /* get the node that contains the configuration */ node = axl_doc_get (doc, "/sasl-auth-db/get-password"); query = (char *) ATTR_VALUE (node, "query"); /* call to do auth operation */ _result = __mod_sasl_mysql_prepare_query_and_auth (ctx, query, conn, auth_db_node_conf, auth_id, authorization_id, formated_password, password, serverName, sasl_method, axl_false, /* skip login error reporting */ axl_false, err); } /* end if */ /* now check for auth-log declaration to report it */ node = axl_doc_get (doc, "/sasl-auth-db/auth-log"); if (node) { /* log auth defined */ query = axl_strdup (ATTR_VALUE (node, "query")); /* replace query with recognized tokens */ axl_replace (query, "%t", _result ? "ok" : "failed"); axl_replace (query, "%u", auth_id); axl_replace (query, "%n", serverName); axl_replace (query, "%i", authorization_id); axl_replace (query, "%m", sasl_method); axl_replace (query, "%p", vortex_connection_get_host (conn)); msg ("Trying to auth-log %s:%s with query string %s", auth_id, _result ? "ok" : "failed", query); /* exec query */ if (! mod_sasl_mysql_do_query (ctx, auth_db_node_conf, query, axl_true, err)) { error ("Unable to auth-log, failed query configured, error was: %d:%s", axl_error_get_code (*err), axl_error_get (*err)); axl_error_free (*err); } axl_free (query); } /* end if */ if (!_result) error ("login failure: %s, failed from: %s", auth_id, vortex_connection_get_host_ip (conn)); return _result ? 1 : 0; }
axl_bool mod_sasl_mysql_load_auth_db (TurbulenceCtx * ctx, SaslAuthBackend * sasl_backend, axlNode * auth_db_node_conf, axlError ** err) { MYSQL * conn; const char * location; char * basedir = NULL; axlDoc * doc; axlError * local_err = NULL; /* check if location is defined */ if (! HAS_ATTR (auth_db_node_conf, "location")) { axl_error_report (err, -1, "Unable to open auth mysql database, 'location' attribute is not defined"); return axl_false; } /* end if */ /* find the node that holds the connection configuration */ location = ATTR_VALUE (auth_db_node_conf, "location"); /* check if the location is relative or not */ if (! turbulence_file_is_fullpath (location)) { /* get base dir of the sasl.conf that represents this backend */ basedir = turbulence_base_dir (common_sasl_get_file_path (sasl_backend)); /* now build a new path */ location = axl_strdup_printf ("%s%s%s", basedir, VORTEX_FILE_SEPARATOR, location); msg ("Found relative file to auth mysql db settings, resolved to: %s", location); } /* end if */ /* now load the file */ doc = axl_doc_parse_from_file (location, &local_err); /* check for error and report */ if (doc == NULL) { axl_error_report (err, -1, "Failed to open auth mysql db at %s error was %s", location, axl_error_get (local_err)); axl_error_free (local_err); } /* end if */ /* dealloc some variables */ if (basedir) { axl_free (basedir); axl_free ((char *) location); } /* end if */ /* return if error */ if (doc == NULL) { return axl_false; } /* end if */ /* do DTD validation */ if (! axl_dtd_validate (doc, mysql_sasl_dtd, &local_err)) { axl_error_report (err, -1, "Failed to open auth mysql db at %s, found DTD error %s", location, axl_error_get (local_err)); axl_error_free (local_err); axl_doc_free (doc); return axl_false; } /* end if */ /* link the document to this node so we can reuse it later */ axl_node_annotate_data_full (auth_db_node_conf, "mysql-conf", NULL, doc, (axlDestroyFunc) axl_doc_free); /* request to load msyql database */ conn = mod_sasl_mysql_get_connection (ctx, auth_db_node_conf, err); if (conn == NULL) return axl_false; msg ("load database ok"); /* connection ok, this means we have loaded the database */ return axl_true; }
void InterpreterDraft6::exitStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { NodeSet<std::string> statesToExit; monIter_t monIter; #if VERBOSE std::cout << _name << ": Enabled exit transitions: " << std::endl; for (int i = 0; i < enabledTransitions.size(); i++) { std::cout << enabledTransitions[i] << std::endl; } std::cout << std::endl; #endif for (int i = 0; i < enabledTransitions.size(); i++) { Element<std::string> t = ((Element<std::string>)enabledTransitions[i]); if (!isTargetless(t)) { Node<std::string> ancestor; Node<std::string> source = getSourceState(t); // std::cout << t << std::endl << TAGNAME(t) << std::endl; NodeSet<std::string> tStates = getTargetStates(t); bool isInternal = (HAS_ATTR(t, "type") && iequals(ATTR(t, "type"), "internal")); // external is default bool allDescendants = true; for (int j = 0; j < tStates.size(); j++) { if (!isDescendant(tStates[j], source)) { allDescendants = false; break; } } if (isInternal && allDescendants && isCompound(source)) { ancestor = source; } else { NodeSet<std::string> tmpStates; tmpStates.push_back(source); tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end()); #if VERBOSE std::cout << _name << ": tmpStates: "; for (int i = 0; i < tmpStates.size(); i++) { std::cout << ATTR(tmpStates[i], "id") << ", "; } std::cout << std::endl; #endif ancestor = findLCCA(tmpStates); } #if VERBOSE std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl;; #endif for (int j = 0; j < _configuration.size(); j++) { if (isDescendant(_configuration[j], ancestor)) statesToExit.push_back(_configuration[j]); } } } // remove statesToExit from _statesToInvoke std::list<Node<std::string> > tmp; for (int i = 0; i < _statesToInvoke.size(); i++) { if (!isMember(_statesToInvoke[i], statesToExit)) { tmp.push_back(_statesToInvoke[i]); } } _statesToInvoke = NodeSet<std::string>(); _statesToInvoke.insert(_statesToInvoke.end(), tmp.begin(), tmp.end()); statesToExit.forward(false); statesToExit.sort(); #if VERBOSE std::cout << _name << ": States to exit: "; for (int i = 0; i < statesToExit.size(); i++) { std::cout << LOCALNAME(statesToExit[i]) << ":" << ATTR(statesToExit[i], "id") << ", "; } std::cout << std::endl; #endif for (int i = 0; i < statesToExit.size(); i++) { NodeSet<std::string> histories = filterChildElements(_nsInfo.xmlNSPrefix + "history", statesToExit[i]); for (int j = 0; j < histories.size(); j++) { Element<std::string> historyElem = (Element<std::string>)histories[j]; std::string historyType = (historyElem.hasAttribute("type") ? historyElem.getAttribute("type") : "shallow"); NodeSet<std::string> historyNodes; for (int k = 0; k < _configuration.size(); k++) { if (iequals(historyType, "deep")) { if (isAtomic(_configuration[k]) && isDescendant(_configuration[k], statesToExit[i])) historyNodes.push_back(_configuration[k]); } else { if (_configuration[k].getParentNode() == statesToExit[i]) historyNodes.push_back(_configuration[k]); } } _historyValue[historyElem.getAttribute("id")] = historyNodes; #if VERBOSE std::cout << _name << ": History node " << ATTR(historyElem, "id") << " contains: "; for (int i = 0; i < historyNodes.size(); i++) { std::cout << ATTR(historyNodes[i], "id") << ", "; } std::cout << std::endl; #endif } } for (int i = 0; i < statesToExit.size(); i++) { // --- MONITOR: beforeExitingState ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); } USCXML_MONITOR_CATCH_BLOCK(beforeExitingState) } NodeSet<std::string> onExits = filterChildElements(_nsInfo.xmlNSPrefix + "onExit", statesToExit[i]); for (int j = 0; j < onExits.size(); j++) { Element<std::string> onExitElem = (Element<std::string>)onExits[j]; executeContent(onExitElem); } // --- MONITOR: afterExitingState ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->afterExitingState(shared_from_this(), Element<std::string>(statesToExit[i]), (i + 1 < statesToExit.size())); } USCXML_MONITOR_CATCH_BLOCK(afterExitingState) } NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToExit[i]); for (int j = 0; j < invokes.size(); j++) { Element<std::string> invokeElem = (Element<std::string>)invokes[j]; if (HAS_ATTR(invokeElem, "persist") && DOMUtils::attributeIsTrue(ATTR(invokeElem, "persist"))) { // extension for flattened SCXML documents, we will need an explicit uninvoke element } else { cancelInvoke(invokeElem); } } // remove statesToExit[i] from _configuration - test409 tmp.clear(); for (int j = 0; j < _configuration.size(); j++) { if (_configuration[j] != statesToExit[i]) { tmp.push_back(_configuration[j]); } } _configuration = NodeSet<std::string>(); _configuration.insert(_configuration.end(), tmp.begin(), tmp.end()); } }
void PostponeElement::enterElement(const Arabica::DOM::Element<std::string>& node) { if (!_interpreter->getDataModel()) { LOG(ERROR) << "Postpone element requires a datamodel"; return; } // under which condition will we postpone the current event? if (HAS_ATTR(node, "cond")) { std::string cond = ATTR(node, "cond"); try { if (!_interpreter->getDataModel().evalAsBool(cond)) return; } catch (Event e) { LOG(ERROR) << "Syntax error in cond attribute of postpone element:" << std::endl << e << std::endl; return; } } // chaining causes the event to fire if the condition was true since postponing bool chained = false; if (HAS_ATTR(node, "chaining")) { chained = iequals(ATTR(node, "chaining"), "true"); } // when will we refire the event? std::string until; try { if (HAS_ATTR(node, "untilexpr")) { until = _interpreter->getDataModel().evalAsString(ATTR(node, "untilexpr")); } else if (HAS_ATTR(node, "until")) { until = ATTR(node, "until"); } } catch (Event e) { LOG(ERROR) << "Syntax error in postpone element untilexpr:" << std::endl << e << std::endl; return; } if (until.length() == 0) { LOG(ERROR) << "Postpone element requires until or untilexpr attribute "; return; } // LOG(INFO) << until; #if 0 std::string timeoutStr = "0s"; try { if (HAS_ATTR(node, "timeoutexpr")) { timeoutStr = _interpreter->getDataModel().evalAsString(ATTR(node, "timeoutexpr")); } else if (HAS_ATTR(node, "timeout")) { timeoutStr = ATTR(node, "timeout"); } } catch (Event e) { LOG(ERROR) << "Syntax error in postpone element timeoutexpr:" << std::endl << e << std::endl; return; } uint64_t timeout = 0; NumAttr timeoutAttr(timeoutStr); if (iequals(timeoutAttr.unit, "s")) { timeout = strTo<int>(timeoutAttr.value) * 1000; } else if (iequals(timeoutAttr.unit, "ms")) { timeout = strTo<int>(timeoutAttr.value); } if (timeout > 0) { timeout += tthread::chrono::system_clock::now(); } #endif Event currEvent = _interpreter->getCurrentEvent(); Resubmitter::postpone(currEvent, until, 0, chained, _interpreter); }
void InterpreterDraft6::enterStates(const Arabica::XPath::NodeSet<std::string>& enabledTransitions) { NodeSet<std::string> statesToEnter; NodeSet<std::string> statesForDefaultEntry; monIter_t monIter; #if VERBOSE std::cout << _name << ": Enabled enter transitions: " << std::endl; for (int i = 0; i < enabledTransitions.size(); i++) { std::cout << "\t" << enabledTransitions[i] << std::endl; } std::cout << std::endl; #endif for (int i = 0; i < enabledTransitions.size(); i++) { Element<std::string> transition = ((Element<std::string>)enabledTransitions[i]); if (!isTargetless(transition)) { std::string transitionType = (iequals(transition.getAttribute("type"), "internal") ? "internal" : "external"); NodeSet<std::string> tStates = getTargetStates(transition); #if VERBOSE std::cout << _name << ": Target States: "; for (int i = 0; i < tStates.size(); i++) { std::cout << ATTR(tStates[i], "id") << ", "; } std::cout << std::endl; #endif Node<std::string> ancestor; Node<std::string> source = getSourceState(transition); #if VERBOSE std::cout << _name << ": Source States: " << ATTR(source, "id") << std::endl; #endif assert(source); bool allDescendants = true; for (int j = 0; j < tStates.size(); j++) { if (!isDescendant(tStates[j], source)) { allDescendants = false; break; } } if (iequals(transitionType, "internal") && isCompound(source) && allDescendants) { ancestor = source; } else { NodeSet<std::string> tmpStates; tmpStates.push_back(source); tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end()); ancestor = findLCCA(tmpStates); } #if VERBOSE std::cout << _name << ": Ancestor: " << ATTR(ancestor, "id") << std::endl; #endif for (int j = 0; j < tStates.size(); j++) { addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry); } #if VERBOSE std::cout << _name << ": States to enter: "; for (int i = 0; i < statesToEnter.size(); i++) { std::cout << LOCALNAME(statesToEnter[i]) << ":" << ATTR(statesToEnter[i], "id") << ", "; } std::cout << std::endl; #endif for (int j = 0; j < tStates.size(); j++) { NodeSet<std::string> ancestors = getProperAncestors(tStates[j], ancestor); #if VERBOSE std::cout << _name << ": Proper Ancestors of " << ATTR(tStates[j], "id") << " and " << ATTR(ancestor, "id") << ": "; for (int i = 0; i < ancestors.size(); i++) { std::cout << ATTR(ancestors[i], "id") << ", "; } std::cout << std::endl; #endif for (int k = 0; k < ancestors.size(); k++) { statesToEnter.push_back(ancestors[k]); if(isParallel(ancestors[k])) { NodeSet<std::string> childs = getChildStates(ancestors[k]); for (int l = 0; l < childs.size(); l++) { bool someIsDescendant = false; for (int m = 0; m < statesToEnter.size(); m++) { if (isDescendant(statesToEnter[m], childs[l])) { someIsDescendant = true; break; } } if (!someIsDescendant) { addStatesToEnter(childs[l], statesToEnter, statesForDefaultEntry); } } } } } } } statesToEnter.to_document_order(); #if VERBOSE std::cout << _name << ": States to enter: "; for (int i = 0; i < statesToEnter.size(); i++) { std::cout << ATTR(statesToEnter[i], "id") << ", "; } std::cout << std::endl; #endif for (int i = 0; i < statesToEnter.size(); i++) { Element<std::string> stateElem = (Element<std::string>)statesToEnter[i]; // extension for flattened interpreters for (unsigned int k = 0; k < statesToEnter.size(); k++) { NodeSet<std::string> invokes = filterChildElements(_nsInfo.xmlNSPrefix + "invoke", statesToEnter[k]); for (unsigned int j = 0; j < invokes.size(); j++) { if (HAS_ATTR(invokes[j], "persist") && DOMUtils::attributeIsTrue(ATTR(invokes[j], "persist"))) { invoke(invokes[j]); } } } // --- MONITOR: beforeEnteringState ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->beforeEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size())); } USCXML_MONITOR_CATCH_BLOCK(beforeEnteringState) } // extension for flattened SCXML documents, we will need an explicit uninvoke element NodeSet<std::string> uninvokes = filterChildElements(_nsInfo.xmlNSPrefix + "uninvoke", statesToEnter[i]); for (int j = 0; j < uninvokes.size(); j++) { Element<std::string> uninvokeElem = (Element<std::string>)uninvokes[j]; cancelInvoke(uninvokeElem); } _configuration.push_back(stateElem); _statesToInvoke.push_back(stateElem); // if (_binding == LATE && stateElem.getAttribute("isFirstEntry").size() > 0) { if (_binding == LATE && !isMember(stateElem, _alreadyEntered)) { NodeSet<std::string> dataModelElems = filterChildElements(_nsInfo.xmlNSPrefix + "datamodel", stateElem); if(dataModelElems.size() > 0 && _dataModel) { Arabica::XPath::NodeSet<std::string> dataElems = filterChildElements(_nsInfo.xmlNSPrefix + "data", dataModelElems[0]); for (int j = 0; j < dataElems.size(); j++) { if (dataElems[j].getNodeType() == Node_base::ELEMENT_NODE) initializeData(Element<std::string>(dataElems[j])); } } _alreadyEntered.push_back(stateElem); // stateElem.setAttribute("isFirstEntry", ""); } // execute onentry executable content NodeSet<std::string> onEntryElems = filterChildElements(_nsInfo.xmlNSPrefix + "onEntry", stateElem); executeContent(onEntryElems, false); // --- MONITOR: afterEnteringState ------------------------------ for(monIter_t monIter = _monitors.begin(); monIter != _monitors.end(); monIter++) { try { (*monIter)->afterEnteringState(shared_from_this(), stateElem, (i + 1 < statesToEnter.size())); } USCXML_MONITOR_CATCH_BLOCK(afterEnteringState) } if (isMember(stateElem, statesForDefaultEntry)) { // execute initial transition content for compound states Arabica::XPath::NodeSet<std::string> transitions = _xpath.evaluate("" + _nsInfo.xpathPrefix + "initial/" + _nsInfo.xpathPrefix + "transition", stateElem).asNodeSet(); for (int j = 0; j < transitions.size(); j++) { executeContent(transitions[j]); } } if (isFinal(stateElem)) { internalDoneSend(stateElem); Element<std::string> parent = (Element<std::string>)stateElem.getParentNode(); if (isParallel(parent.getParentNode())) { Element<std::string> grandParent = (Element<std::string>)parent.getParentNode(); Arabica::XPath::NodeSet<std::string> childs = getChildStates(grandParent); bool inFinalState = true; for (int j = 0; j < childs.size(); j++) { if (!isInFinalState(childs[j])) { inFinalState = false; break; } } if (inFinalState) { internalDoneSend(parent); } } } } for (int i = 0; i < _configuration.size(); i++) { Element<std::string> stateElem = (Element<std::string>)_configuration[i]; if (isFinal(stateElem) && parentIsScxmlState(stateElem)) { _running = false; _done = true; } } }