summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-02-07 20:19:23 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-02-07 20:19:23 +0000
commit6b7a8a38f609117572820711638508a23ad57850 (patch)
treecfd15ced8363fa5163cbf874ec01178254169fbf
parent9f67144615b018828226949701a6935336cbfc43 (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
-rw-r--r--sca-cpp/trunk/modules/java/eval.hpp18
-rw-r--r--sca-cpp/trunk/modules/java/io.hpp43
-rw-r--r--sca-cpp/trunk/modules/java/mod-java.cpp4
-rw-r--r--sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java14
-rw-r--r--sca-cpp/trunk/modules/python/eval.hpp53
-rw-r--r--sca-cpp/trunk/modules/python/io.hpp127
-rw-r--r--sca-cpp/trunk/modules/python/mod-python.cpp2
-rw-r--r--sca-cpp/trunk/modules/server/client-test.hpp4
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp2
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)));
}
/**