diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-02-07 20:19:23 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-02-07 20:19:23 +0000 |
commit | 6b7a8a38f609117572820711638508a23ad57850 (patch) | |
tree | cfd15ced8363fa5163cbf874ec01178254169fbf /sca-cpp | |
parent | 9f67144615b018828226949701a6935336cbfc43 (diff) |
Support HTTPD graceful restarts for non-stop operation. Simplified Python and Java error capture and recovery.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@907470 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp')
-rw-r--r-- | sca-cpp/trunk/modules/java/eval.hpp | 18 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/io.hpp | 43 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/mod-java.cpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java | 14 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/eval.hpp | 53 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/io.hpp | 127 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/mod-python.cpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/client-test.hpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-eval.hpp | 2 |
9 files changed, 68 insertions, 199 deletions
diff --git a/sca-cpp/trunk/modules/java/eval.hpp b/sca-cpp/trunk/modules/java/eval.hpp index e10ec29a0b..9140fe75b4 100644 --- a/sca-cpp/trunk/modules/java/eval.hpp +++ b/sca-cpp/trunk/modules/java/eval.hpp @@ -29,13 +29,12 @@ #include "list.hpp" #include "value.hpp" -#include "io.hpp" namespace tuscany { namespace java { /** - * Initialize a JVM. + * Represent a Java VM runtime. */ jobject JNICALL nativeInvoke(JNIEnv *env, jobject self, jobject proxy, jobject method, jobjectArray args); @@ -87,9 +86,6 @@ public: jvm->GetEnv((void**)&env, JNI_VERSION_1_6); } - // Capture JVM standard IO - setupIO(); - // Lookup System classes and methods classClass = env->FindClass("java/lang/Class"); methodClass = env->FindClass("java/lang/reflect/Method"); @@ -114,6 +110,7 @@ public: loaderForName = env->GetStaticMethodID(loaderClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); invokerClass = env->FindClass("org/apache/tuscany/InvocationHandler"); invokerValueOf = env->GetStaticMethodID(invokerClass, "valueOf", "(Ljava/lang/Class;J)Ljava/lang/Object;"); + invokerStackTrace = env->GetStaticMethodID(invokerClass, "stackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); invokerLambda = env->GetFieldID(invokerClass, "lambda", "J"); iterableUtilClass = env->FindClass("org/apache/tuscany/IterableUtil"); iterableValueOf = env->GetStaticMethodID(iterableUtilClass, "list", "([Ljava/lang/Object;)Ljava/lang/Iterable;"); @@ -127,7 +124,6 @@ public: nm.signature = const_cast<char*>("(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"); nm.fnPtr = (void*)nativeInvoke; env->RegisterNatives(invokerClass, &nm, 1); - } JavaVM* jvm; @@ -154,13 +150,13 @@ public: jmethodID loaderForName; jclass invokerClass; jmethodID invokerValueOf; + jmethodID invokerStackTrace; jfieldID invokerLambda; jclass iterableUtilClass; jmethodID iterableValueOf; jmethodID iterableCar; jmethodID iterableCdr; jmethodID iterableIsNil; - }; /** @@ -169,9 +165,13 @@ public: string lastException(const JavaRuntime& jr) { if (!jr.env->ExceptionCheck()) return "No Exception"; - jr.env->ExceptionDescribe(); + const jthrowable ex = jr.env->ExceptionOccurred(); + const jstring trace = (jstring)jr.env->CallStaticObjectMethod(jr.invokerClass, jr.invokerStackTrace, ex); + const char* c = jr.env->GetStringUTFChars(trace, NULL); + const string msg(c); + jr.env->ReleaseStringUTFChars(trace, c); jr.env->ExceptionClear(); - return "UnknownException"; + return msg; } /** diff --git a/sca-cpp/trunk/modules/java/io.hpp b/sca-cpp/trunk/modules/java/io.hpp deleted file mode 100644 index 58ca58f0b2..0000000000 --- a/sca-cpp/trunk/modules/java/io.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* $Rev$ $Date$ */ - -#ifndef tuscany_java_io_hpp -#define tuscany_java_io_hpp - -/** - * Java IO functions. - */ -#include "stream.hpp" -#include "../scheme/io.hpp" - -namespace tuscany { -namespace java { - -/** - * Setup the display and log hooks. - */ -bool setupIO() { - return true; -} - -} -} -#endif /* tuscany_python_pyio_hpp */ diff --git a/sca-cpp/trunk/modules/java/mod-java.cpp b/sca-cpp/trunk/modules/java/mod-java.cpp index b8ac642c0e..4b8e7dca56 100644 --- a/sca-cpp/trunk/modules/java/mod-java.cpp +++ b/sca-cpp/trunk/modules/java/mod-java.cpp @@ -55,7 +55,9 @@ const failable<bool> stop(unused ServerConf& sc) { /** * Restart the module. */ -const failable<bool> restart(unused ServerConf& sc) { +const failable<bool> restart(ServerConf& sc) { + // Start a Java runtime + sc.moduleConf = new (gc_new<java::JavaRuntime>()) java::JavaRuntime(); return true; } diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java index 5707a07bc7..c5ec6005a1 100644 --- a/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java +++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java @@ -19,6 +19,8 @@ package org.apache.tuscany; +import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -40,7 +42,19 @@ class InvocationHandler implements java.lang.reflect.InvocationHandler { return Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new InvocationHandler(lambda)); } + /** + * Proxy invocation of a C++ function. + */ @Override public native Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable; + /** + * Return the stack trace of an exception. + */ + static String stackTrace(final Throwable e) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString(); + } } diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index 09c2cba92d..5231b0ef60 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -29,33 +29,52 @@ #include "list.hpp" #include "value.hpp" -#include "io.hpp" namespace tuscany { namespace python { /** - * Initialize the Python runtime. + * Represent a Python runtime. */ class PythonRuntime { public: - PythonRuntime() : owner(true) { + PythonRuntime() { + if (Py_IsInitialized()) + return; Py_InitializeEx(0); - setupIO(); - } - - PythonRuntime(unused const PythonRuntime& r) : owner(false) { } +}; - ~PythonRuntime() { - if (!owner) - return; - //Py_Finalize(); +/** + * Return the last python error. + */ +const string lastError() { + if(PyErr_Occurred()) { + PyObject* type; + PyObject* val; + PyObject* trace; + PyErr_Fetch(&type, &val, &trace); + if (type != NULL && val != NULL) { + PyObject* stype = PyObject_Str(type); + PyObject* sval = PyObject_Str(val); + string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval); + Py_DECREF(stype); + Py_DECREF(sval); + Py_DECREF(type); + Py_DECREF(val); + Py_XDECREF(trace); + PyErr_Print(); + return msg; + } + PyErr_Print(); + Py_XDECREF(type); + Py_XDECREF(val); + Py_XDECREF(trace); + PyErr_Print(); + return "Unknown Python error"; } - -private: - const bool owner; -}; + return ""; +} /** * Declare conversion functions. @@ -222,8 +241,10 @@ const failable<value> evalScript(const value& expr, PyObject* script) { // The start, stop, and restart functions are optional const value fn = car<value>(expr); - if (fn == "start" || fn == "stop" || fn == "restart") + if (fn == "start" || fn == "stop" || fn == "restart") { + PyErr_Clear(); return value(false); + } return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastError()); } diff --git a/sca-cpp/trunk/modules/python/io.hpp b/sca-cpp/trunk/modules/python/io.hpp deleted file mode 100644 index 10119a4f77..0000000000 --- a/sca-cpp/trunk/modules/python/io.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* $Rev$ $Date$ */ - -#ifndef tuscany_python_io_hpp -#define tuscany_python_io_hpp - -/** - * Hooks used to capture python stdout and stderr. - */ -#include <python2.6/Python.h> - -#include "stream.hpp" -#include "../scheme/io.hpp" - -namespace tuscany { -namespace python { - -/** - * Hook method used to redirect python output to a stream. - */ -PyObject* display(unused PyObject* self, PyObject* args) { - char* s = NULL; - if (!PyArg_ParseTuple(args, "s", &s)) - return NULL; - - scheme::displayStream() << s; - - Py_INCREF(Py_None); - return Py_None; -} - -PyMethodDef displayHookMethods[] = { - {"display", display, METH_VARARGS, "Redirects stdout"}, - {NULL, NULL, 0, NULL}}; - -/** - * Hook method used to redirect python errors to a stream. - */ -PyObject* log(unused PyObject* self, PyObject* args) { - char* s = NULL; - if (!PyArg_ParseTuple(args, "s", &s)) - return NULL; - - scheme::logStream() << s; - - Py_INCREF(Py_None); - return Py_None; -} - -PyMethodDef logHookMethods[] = { - {"log", log, METH_VARARGS, "Redirects stdout"}, - {NULL, NULL, 0, NULL}}; - -/** - * Setup the display and log hooks. - */ -bool setupIO() { - Py_InitModule("displayhook", displayHookMethods); - PyRun_SimpleString( - "import sys\n" - "import displayhook\n" - "\n" - "class DisplayHook:\n" - " def write(self, text):\n" - " displayhook.display(text)\n" - "\n" - "sys.stdout = DisplayHook()\n"); - - Py_InitModule("loghook", logHookMethods); - PyRun_SimpleString( - "import sys\n" - "import loghook\n" - "\n" - "class LogHook:\n" - " def write(self, text):\n" - " loghook.log(text)\n" - "\n" - "sys.stderr = LogHook()\n"); - return true; -} - -/** - * Return the last python error. - */ -const string lastError() { - ostream* pos = scheme::logOutStream; - ostringstream eos; - scheme::logOutStream = &eos; - if (PyErr_Occurred()) - PyErr_Print(); - scheme::logOutStream = pos; - return str(eos); -} - -/** - * Read and write values (using the scheme representation as it's the canonical - * representation used throughout the runtime.) - */ -const value readValue(istream& in) { - return scheme::readValue(in); -} - -const bool writeValue(const value& val, ostream& out) { - return scheme::writeValue(val, out); -} - -} -} -#endif /* tuscany_python_io_hpp */ diff --git a/sca-cpp/trunk/modules/python/mod-python.cpp b/sca-cpp/trunk/modules/python/mod-python.cpp index a45b83997f..df94f2e8a1 100644 --- a/sca-cpp/trunk/modules/python/mod-python.cpp +++ b/sca-cpp/trunk/modules/python/mod-python.cpp @@ -56,6 +56,8 @@ const failable<bool> stop(unused ServerConf& sc) { * Restart the module. */ const failable<bool> restart(unused ServerConf& sc) { + // Start a Python runtime + sc.moduleConf = new (gc_new<python::PythonRuntime>()) python::PythonRuntime(); return true; } diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp index 0f8b64a031..651a9016b2 100644 --- a/sca-cpp/trunk/modules/server/client-test.hpp +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -312,7 +312,7 @@ const bool testPut() { + (list<value>() + "price" + string("$2.99")); const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); http::CURLSession ch; - value rc = content(http::put(a, testURI, ch)); + value rc = content(http::put(a, testURI + "/111", ch)); assert(rc == value(true)); return true; } @@ -320,7 +320,7 @@ const bool testPut() { const bool testDel() { gc_scoped_pool pool; http::CURLSession ch; - value rc = content(http::del(testURI, ch)); + value rc = content(http::del(testURI + "/111", ch)); assert(rc == value(true)); return true; } diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 0e68e63016..6ab1d68ad6 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -395,7 +395,7 @@ const failable<bool> confComponents(const string& lifecycle, ServerConf& sc, ser debug(sc.implementations, "modeval::confComponents::implementations"); // Start or restart the component implementations - return applyLifecycleExpr(impls, mklist<value>(lifecycle)); + return applyLifecycleExpr(impls, mklist<value>(c_str(lifecycle))); } /** |