diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-20 08:00:41 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-03-20 08:00:41 (GMT) |
commit | c6c1f3e2e333705bf7d54fffd4b18939a56f4ed8 (patch) | |
tree | 92af8be33c602a68d1912790cad657c2a012e2c0 /src | |
parent | ccbf595c52fd705ec70abc774a29b153a7281334 (diff) | |
download | uscxml-c6c1f3e2e333705bf7d54fffd4b18939a56f4ed8.zip uscxml-c6c1f3e2e333705bf7d54fffd4b18939a56f4ed8.tar.gz uscxml-c6c1f3e2e333705bf7d54fffd4b18939a56f4ed8.tar.bz2 |
Started Syteminvoker
Diffstat (limited to 'src')
-rw-r--r-- | src/uscxml/Factory.cpp | 7 | ||||
-rw-r--r-- | src/uscxml/Interpreter.cpp | 19 | ||||
-rw-r--r-- | src/uscxml/Interpreter.h | 14 | ||||
-rw-r--r-- | src/uscxml/plugins/Plugins.cpp | 1 | ||||
-rw-r--r-- | src/uscxml/plugins/Plugins.h | 1 | ||||
-rw-r--r-- | src/uscxml/plugins/element/postpone/PostponeElement.cpp | 25 | ||||
-rw-r--r-- | src/uscxml/plugins/element/postpone/PostponeElement.h | 7 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp | 2 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/http/HTTPServletInvoker.h | 1 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/system/SystemInvoker.cpp | 44 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/system/SystemInvoker.h | 40 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp | 8 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h | 2 | ||||
-rw-r--r-- | src/uscxml/server/HTTPServer.cpp | 31 | ||||
-rw-r--r-- | src/uscxml/server/HTTPServer.h | 1 |
15 files changed, 170 insertions, 33 deletions
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp index 4011446..623b551 100644 --- a/src/uscxml/Factory.cpp +++ b/src/uscxml/Factory.cpp @@ -15,6 +15,7 @@ # include "uscxml/plugins/invoker/http/HTTPServletInvoker.h" # include "uscxml/plugins/invoker/heartbeat/HeartbeatInvoker.h" # include "uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h" +# include "uscxml/plugins/invoker/system/SystemInvoker.h" # ifdef UMUNDO_FOUND # include "uscxml/plugins/invoker/umundo/UmundoInvoker.h" @@ -64,6 +65,7 @@ Factory::Factory() { pluma.acceptProviderType<InvokerImplProvider>(); pluma.acceptProviderType<IOProcessorImplProvider>(); pluma.acceptProviderType<DataModelImplProvider>(); + pluma.acceptProviderType<ElementImplProvider>(); pluma.loadFromFolder(pluginPath); std::vector<InvokerImplProvider*> invokerProviders; @@ -159,10 +161,13 @@ Factory::Factory() { registerInvoker(invoker); } { + SystemInvoker* invoker = new SystemInvoker(); + registerInvoker(invoker); + } + { EventIOProcessor* ioProcessor = new EventIOProcessor(); registerIOProcessor(ioProcessor); } - { FetchElement* element = new FetchElement(); registerExecutableContent(element); diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 95f4658..4ae4689 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -39,7 +39,9 @@ Interpreter::Interpreter() : Arabica::SAX2DOM::Parser<std::string>() { _parentQueue = NULL; _running = false; _done = false; + _isInitialized = false; _httpServlet = NULL; + _capabilities = CAN_BASIC_HTTP | CAN_GENERIC_HTTP; #ifdef _WIN32 WSADATA wsaData; @@ -170,7 +172,7 @@ Interpreter* Interpreter::fromInputSource(Arabica::SAX::InputSource<std::string> } else { interpreter->_document = interpreter->Arabica::SAX2DOM::Parser<std::string>::getDocument(); } - interpreter->init(); +// interpreter->init(); return interpreter; } @@ -191,14 +193,17 @@ void Interpreter::init() { normalize(_document); + if (_capabilities & CAN_GENERIC_HTTP) + _httpServlet = new HTTPServletInvoker(this); + _sendQueue = new DelayedEventQueue(); - _httpServlet = new HTTPServletInvoker(this); _sendQueue->start(); } else { LOG(ERROR) << "Cannot find SCXML element" << std::endl; } } + _isInitialized = true; } Interpreter::~Interpreter() { @@ -259,10 +264,13 @@ bool Interpreter::runOnMainThread(int fps, bool blocking) { // see: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation void Interpreter::interpret() { + if (!_isInitialized) + init(); + if (!_scxml) return; // dump(); - + _sessionId = getUUID(); std::string datamodelName; @@ -2520,6 +2528,11 @@ void Interpreter::setupIOProcessors() { tthread::lock_guard<tthread::mutex> lock(_mutex); std::map<std::string, IOProcessorImpl*>::iterator ioProcIter = Factory::getInstance()->_ioProcessors.begin(); while(ioProcIter != Factory::getInstance()->_ioProcessors.end()) { + if (boost::iequals(ioProcIter->first, "basichttp") && !(_capabilities & CAN_BASIC_HTTP)) { + ioProcIter++; + continue; + } + _ioProcessors[ioProcIter->first] = Factory::createIOProcessor(ioProcIter->first, this); _ioProcessors[ioProcIter->first].setType(ioProcIter->first); _ioProcessors[ioProcIter->first].setInterpreter(this); diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index 1a44f80..90c2b3b 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -76,6 +76,12 @@ public: LATE = 1 }; + enum Capabilities { + CAN_NOTHING = 0, + CAN_BASIC_HTTP = 1, + CAN_GENERIC_HTTP = 2, + }; + virtual ~Interpreter(); static Interpreter* fromDOM(const Arabica::DOM::Node<std::string>& node); @@ -162,6 +168,10 @@ public: return _document; } + void setCapabilities(unsigned int capabilities) { + _capabilities = capabilities; + } + void setName(const std::string& name); const std::string& getName() { return _name; @@ -222,6 +232,7 @@ protected: bool _running; bool _done; + bool _isInitialized; Binding _binding; Arabica::XPath::NodeSet<std::string> _configuration; Arabica::XPath::NodeSet<std::string> _statesToInvoke; @@ -306,7 +317,8 @@ protected: long _lastRunOnMainThread; std::string _name; std::string _sessionId; - + unsigned int _capabilities; + Data _cmdLineOptions; IOProcessor getIOProcessor(const std::string& type); diff --git a/src/uscxml/plugins/Plugins.cpp b/src/uscxml/plugins/Plugins.cpp index ba27728..65740e1 100644 --- a/src/uscxml/plugins/Plugins.cpp +++ b/src/uscxml/plugins/Plugins.cpp @@ -6,6 +6,7 @@ namespace uscxml { PLUMA_PROVIDER_SOURCE(DataModelImpl, 1, 1); PLUMA_PROVIDER_SOURCE(IOProcessorImpl, 1, 1); PLUMA_PROVIDER_SOURCE(InvokerImpl, 1, 1); +PLUMA_PROVIDER_SOURCE(ElementImpl, 1, 1); #endif }
\ No newline at end of file diff --git a/src/uscxml/plugins/Plugins.h b/src/uscxml/plugins/Plugins.h index 1e6ac0b..338dcaf 100644 --- a/src/uscxml/plugins/Plugins.h +++ b/src/uscxml/plugins/Plugins.h @@ -9,6 +9,7 @@ namespace uscxml { #ifdef BUILD_AS_PLUGINS PLUMA_PROVIDER_HEADER(IOProcessorImpl); PLUMA_PROVIDER_HEADER(InvokerImpl); +PLUMA_PROVIDER_HEADER(ElementImpl); PLUMA_PROVIDER_HEADER(DataModelImpl); #endif diff --git a/src/uscxml/plugins/element/postpone/PostponeElement.cpp b/src/uscxml/plugins/element/postpone/PostponeElement.cpp index 96cda6f..53782e1 100644 --- a/src/uscxml/plugins/element/postpone/PostponeElement.cpp +++ b/src/uscxml/plugins/element/postpone/PostponeElement.cpp @@ -40,6 +40,12 @@ void PostponeElement::enterElement(const Arabica::DOM::Node<std::string>& node) } } + // chaining causes the event to fire if the condition was true since postponing + bool chained = false; + if (HAS_ATTR(node, "chaining")) { + chained = boost::iequals(ATTR(node, "chaining"), "true"); + } + // when will we refire the event? std::string until; try { @@ -85,36 +91,29 @@ void PostponeElement::enterElement(const Arabica::DOM::Node<std::string>& node) } #endif Event currEvent = _interpreter->getCurrentEvent(); - Resubmitter::postpone(currEvent, until, 0, _interpreter); + Resubmitter::postpone(currEvent, until, 0, chained, _interpreter); } void PostponeElement::exitElement(const Arabica::DOM::Node<std::string>& node) { } -void PostponeElement::Resubmitter::postpone(const Event& event, std::string until, uint64_t timeout, Interpreter* interpreter) { +void PostponeElement::Resubmitter::postpone(const Event& event, std::string until, uint64_t timeout, bool chained, Interpreter* interpreter) { Resubmitter* resubmitter = getInstance(interpreter); - resubmitter->_postponedEvents.push_back(Postponed(event, until, timeout)); + resubmitter->_postponedEvents.push_back(Postponed(event, until, timeout, chained)); } void PostponeElement::Resubmitter::onStableConfiguration(Interpreter* interpreter) { std::list<Postponed>::iterator eventIter = _postponedEvents.begin(); + bool dispatched = false; while(eventIter != _postponedEvents.end()) { try { // LOG(INFO) << "Reevaluating: >> " << eventIter->first << " <<"; - if (eventIter->timeout > 0 && tthread::chrono::system_clock::now() < eventIter->timeout) { - // TODO: We should use an event queue -// LOG(INFO) << " -> Timeout"; - eventIter->event.name += ".timeout"; - interpreter->receive(eventIter->event, true); - _postponedEvents.erase(eventIter); - break; - } - if (interpreter->getDataModel().evalAsBool(eventIter->until)) { + if ((!dispatched || eventIter->chaining) && interpreter->getDataModel().evalAsBool(eventIter->until)) { // LOG(INFO) << " -> is TRUE"; eventIter->event.name += ".postponed"; interpreter->receive(eventIter->event, true); _postponedEvents.erase(eventIter); - break; + dispatched = true; } // LOG(INFO) << " -> is FALSE"; } catch (Event e) { diff --git a/src/uscxml/plugins/element/postpone/PostponeElement.h b/src/uscxml/plugins/element/postpone/PostponeElement.h index eb7a738..268493f 100644 --- a/src/uscxml/plugins/element/postpone/PostponeElement.h +++ b/src/uscxml/plugins/element/postpone/PostponeElement.h @@ -13,11 +13,12 @@ namespace uscxml { class PostponeElement : public ExecutableContentImpl { public: struct Postponed { - Postponed(const Event& event, const std::string& until, long timeout) : - event(event), until(until), timeout(timeout) {} + Postponed(const Event& event, const std::string& until, long timeout, bool chaining = false) : + event(event), until(until), timeout(timeout), chaining(chaining) {} Event event; std::string until; uint64_t timeout; + bool chaining; }; PostponeElement() {} @@ -48,7 +49,7 @@ protected: } static Resubmitter* getInstance(Interpreter* interpreter); - static void postpone(const Event& event, std::string until, uint64_t timeout, Interpreter* interpreter); + static void postpone(const Event& event, std::string until, uint64_t timeout, bool chained, Interpreter* interpreter); // InterpreterMonitor void onStableConfiguration(Interpreter* interpreter); diff --git a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp index a3556c2..ad7bb15 100644 --- a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp +++ b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.cpp @@ -30,7 +30,7 @@ HTTPServletInvoker::HTTPServletInvoker(Interpreter* interpreter) { while(!HTTPServer::registerServlet(path.str(), this)) { path.clear(); path.str(); - path << _interpreter->getName() << toStr(i++); + path << _interpreter->getName() << i++; } } diff --git a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h index 5d2d4b9..024616d 100644 --- a/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h +++ b/src/uscxml/plugins/invoker/http/HTTPServletInvoker.h @@ -35,6 +35,7 @@ public: virtual void setURL(const std::string& url) { _url = url; } + bool canAdaptPath() { return false; } tthread::recursive_mutex& getMutex() { return _mutex; diff --git a/src/uscxml/plugins/invoker/system/SystemInvoker.cpp b/src/uscxml/plugins/invoker/system/SystemInvoker.cpp new file mode 100644 index 0000000..492d6d3 --- /dev/null +++ b/src/uscxml/plugins/invoker/system/SystemInvoker.cpp @@ -0,0 +1,44 @@ +#include "SystemInvoker.h" +#include <glog/logging.h> + +#ifdef BUILD_AS_PLUGINS +#include <Pluma/Connector.hpp> +#endif + +namespace uscxml { + +#ifdef BUILD_AS_PLUGINS +PLUMA_CONNECTOR +bool connect(pluma::Host& host) { + host.add(new SystemInvokerProvider()); + return true; +} +#endif + +SystemInvoker::SystemInvoker() { +} + +SystemInvoker::~SystemInvoker() { +}; + +boost::shared_ptr<IOProcessorImpl> SystemInvoker::create(Interpreter* interpreter) { + boost::shared_ptr<SystemInvoker> invoker = boost::shared_ptr<SystemInvoker>(new SystemInvoker()); + invoker->_interpreter = interpreter; + return invoker; +} + +Data SystemInvoker::getDataModelVariables() { + Data data; + return data; +} + +void SystemInvoker::send(const SendRequest& req) { +} + +void SystemInvoker::cancel(const std::string sendId) { +} + +void SystemInvoker::invoke(const InvokeRequest& req) { +} + +}
\ No newline at end of file diff --git a/src/uscxml/plugins/invoker/system/SystemInvoker.h b/src/uscxml/plugins/invoker/system/SystemInvoker.h new file mode 100644 index 0000000..1440e79 --- /dev/null +++ b/src/uscxml/plugins/invoker/system/SystemInvoker.h @@ -0,0 +1,40 @@ +#ifndef SYSTEMINVOKER_H_W09J90F0 +#define SYSTEMINVOKER_H_W09J90F0 + +#include <uscxml/Interpreter.h> + +#ifdef BUILD_AS_PLUGINS +#include "uscxml/plugins/Plugins.h" +#endif + +namespace uscxml { + +class SystemInvoker : public InvokerImpl { +public: + SystemInvoker(); + virtual ~SystemInvoker(); + virtual boost::shared_ptr<IOProcessorImpl> create(Interpreter* interpreter); + + virtual std::set<std::string> getNames() { + std::set<std::string> names; + names.insert("system"); + names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#system"); + return names; + } + + virtual Data getDataModelVariables(); + virtual void send(const SendRequest& req); + virtual void cancel(const std::string sendId); + virtual void invoke(const InvokeRequest& req); + +protected: +}; + +#ifdef BUILD_AS_PLUGINS +PLUMA_INHERIT_PROVIDER(SystemInvoker, Invoker); +#endif + +} + + +#endif /* end of include guard: SYSTEMINVOKER_H_W09J90F0 */ diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp index 6c7a8fc..ad47896 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.cpp @@ -51,9 +51,11 @@ boost::shared_ptr<IOProcessorImpl> EventIOProcessor::create(Interpreter* interpr // register at http server std::string path = interpreter->getName(); - path += "/basichttp"; - if (!HTTPServer::registerServlet(path, io.get())) { - LOG(ERROR) << "Cannot register basichttp ioprocessor at " << path << ": " << " already taken"; + int i = 2; + while (!HTTPServer::registerServlet(path + "/basichttp", io.get())) { + std::stringstream ss; + ss << interpreter->getName() << i++; + path = ss.str(); } return io; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h index 70c6bea..9bb717b 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h +++ b/src/uscxml/plugins/ioprocessor/basichttp/libevent/EventIOProcessor.h @@ -43,6 +43,8 @@ public: _url = url; } + bool canAdaptPath() { return false; } + // URLMonitor void downloadStarted(const URL& url); void downloadCompleted(const URL& url); diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index 8be45e6..dd06ab7 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -56,7 +56,8 @@ HTTPServer::HTTPServer(unsigned short port) { } determineAddress(); - evhttp_set_timeout(_http, 5); +// evhttp_set_timeout(_http, 5); + // generic callback evhttp_set_gencb(_http, HTTPServer::httpRecvReqCallback, NULL); } @@ -217,7 +218,7 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD request.data.compound["content"] = Data::fromJSON(request.data.compound["content"].atom); } } - + if (callbackData == NULL) { HTTPServer::getInstance()->processByMatchingServlet(request); } else { @@ -236,7 +237,7 @@ void HTTPServer::processByMatchingServlet(const Request& request) { // is the servlet path a prefix of the actual path? std::string servletPath = "/" + servletIter->first; if (boost::iequals(actualPath.substr(0, servletPath.length()), servletPath) && // actual path is a prefix - boost::iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/' + boost::iequals(actualPath.substr(servletPath.length(), 1), "/")) { // and next character is a '/' if (bestPath.length() < servletPath.length()) { // this servlet is a better match bestPath = servletPath; @@ -299,20 +300,34 @@ bool HTTPServer::registerServlet(const std::string& path, HTTPServlet* servlet) HTTPServer* INSTANCE = getInstance(); tthread::lock_guard<tthread::recursive_mutex> lock(INSTANCE->_mutex); - if(INSTANCE->_servlets.find(path) != INSTANCE->_servlets.end()) { - return false; + // remove trailing and leading slash + std::string actualPath = path; + if (boost::ends_with(actualPath, "/")) + actualPath = actualPath.substr(0, actualPath.size() - 1); + if (boost::starts_with(actualPath, "/")) + actualPath = actualPath.substr(1); + std::string suffixedPath = actualPath; + + // if this servlet allows to adapt the path, do so + int i = 2; + while(INSTANCE->_servlets.find(suffixedPath) != INSTANCE->_servlets.end()) { + if (!servlet->canAdaptPath()) + return false; + std::stringstream ss; + ss << actualPath << i++; + suffixedPath = ss.str(); } std::stringstream servletURL; - servletURL << "http://" << INSTANCE->_address << ":" << INSTANCE->_port << "/" << path; + servletURL << "http://" << INSTANCE->_address << ":" << INSTANCE->_port << "/" << suffixedPath; servlet->setURL(servletURL.str()); - INSTANCE->_servlets[path] = servlet; + INSTANCE->_servlets[suffixedPath] = servlet; LOG(INFO) << "HTTP Servlet listening at: " << servletURL.str() << std::endl; // register callback - evhttp_set_cb(INSTANCE->_http, ("/" + path).c_str(), HTTPServer::httpRecvReqCallback, servlet); + evhttp_set_cb(INSTANCE->_http, ("/" + suffixedPath).c_str(), HTTPServer::httpRecvReqCallback, servlet); return true; } diff --git a/src/uscxml/server/HTTPServer.h b/src/uscxml/server/HTTPServer.h index 319b62f..990d0a7 100644 --- a/src/uscxml/server/HTTPServer.h +++ b/src/uscxml/server/HTTPServer.h @@ -83,6 +83,7 @@ private: class HTTPServlet { public: virtual void httpRecvRequest(const HTTPServer::Request& request) = 0; + virtual bool canAdaptPath() { return true; } virtual void setURL(const std::string& url) = 0; /// Called by the server with the actual URL }; |