Index: plugins/executors/python/SConscript =================================================================== --- plugins/executors/python/SConscript (revision 2740) +++ plugins/executors/python/SConscript (working copy) @@ -12,7 +12,7 @@ '.' ] -env = Environment(CPPPATH=listinc) +env = Environment(CPPPATH=listinc,LINKFLAGS="-Xlinker -export-dynamic") conf = Configure(env, config_h="config.h") Index: plugins/executors/python/config.h =================================================================== --- plugins/executors/python/config.h (revision 0) +++ plugins/executors/python/config.h (revision 0) @@ -0,0 +1,21 @@ +#ifndef BINARIES_PLUGINS_EXECUTORS_PYTHON_CONFIG_H_SEEN +#define BINARIES_PLUGINS_EXECUTORS_PYTHON_CONFIG_H_SEEN + + +/* Define to 1 if you have the header file. */ +#define HAVE_PYTHON_H 1 + +/* Define to 1 if you have the `python2.5' library. */ +#define HAVE_LIBPYTHON2_5 1 +#define PYTHON 1 + +/* Define to 1 if you have the `util' library. */ +#define HAVE_LIBUTIL 1 + +/* Define to 1 if you have the `pthread' library. */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `dl' library. */ +#define HAVE_LIBDL 1 + +#endif /* BINARIES_PLUGINS_EXECUTORS_PYTHON_CONFIG_H_SEEN */ Index: plugins/executors/python/python.cpp =================================================================== --- plugins/executors/python/python.cpp (revision 2740) +++ plugins/executors/python/python.cpp (working copy) @@ -16,12 +16,150 @@ */ #include "python.h" +#include +#include PyInterpreterState* pythonMainInterpreterState = NULL; HashMap pythonThreadData; +HashMap pythonEndingEvent; + +HashMap msgObserved; + +HashMap convertFunctions; + static Server *serverInstance; +static PyObject *callbackManager = NULL; + + + +class PythonManagerObserver : public Multicast +{ +public: + virtual int updateMulticast(MulticastRegistry* reg, string& msg, void* arg) + { + ThreadID tid = Thread::threadID(); + if (pythonEndingEvent.get(tid)!=0) + return -1; + Event endingEvent(false); + pythonEndingEvent.put(tid,&endingEvent); + + convertFunction func = convertFunctions.get(msg); + if (func==0) + return -2; + + PyObject *data = func(arg); + + long l = (long) tid; + PyObject* res = PyObject_CallMethod(callbackManager,(char*)"notifyMessage",(char*)"lsO:data",l, msg.c_str(),data); + + endingEvent.wait(); + pythonEndingEvent.remove(tid); + } +}; + +static PythonManagerObserver observer; + + +static PyObject *initializeCallbackManager(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + PyObject *temp; + + if (PyArg_ParseTuple(args, "O:initializeCallbackManager", &temp)) + { + Py_XINCREF(temp); + Py_XDECREF(callbackManager); + callbackManager = temp; + Py_INCREF(Py_None); + result = Py_None; + } + return result; + +} + +static PyObject *notifyCallbackEnd(PyObject *self, PyObject *args) +{ + + long l; + if (!PyArg_ParseTuple(args, (char*)"l", &l)) + return NULL; + ThreadID tid = (ThreadID)l; + Event *event = pythonEndingEvent.remove(tid); + if (event == 0) + return NULL; + event->signal(); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *registerPythonObserver(PyObject *self, PyObject *args) +{ + char *s; + if (!PyArg_ParseTuple(args, (char*)"s", &s)) + return NULL; + string msg(s); + int *referenceCounter = msgObserved.get(msg); + if (referenceCounter==0) + { + *referenceCounter = 1; + msgObserved.put(msg,referenceCounter); + + HttpStaticData* staticData =(HttpStaticData*) serverInstance->getGlobalData("http-static"); + + if(!staticData) + { + serverInstance->logLockAccess(); + serverInstance->logPreparePrintError(); + serverInstance->logWriteln("PythonHttpHandler: Invalid HTTP static data"); + serverInstance->logEndPrintError(); + serverInstance->logUnlockAccess(); + return NULL; + } + + staticData->addMulticast(msg, &observer); + + Py_INCREF(Py_None); + return Py_None; + } + + (*referenceCounter)++; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *removePythonObserver(PyObject *self, PyObject *args) +{ + char *s; + if (!PyArg_ParseTuple(args, (char*)"s", &s)) + return NULL; + string msg(s); + int *referenceCounter = msgObserved.get(msg); + if (referenceCounter==0) + { + return NULL; + } + + (*referenceCounter)--; + + if (*referenceCounter<=0) + { + msgObserved.remove(msg); + } + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef PythonCallbackManagerMethods[] = { + {(char*)"initializeCallbackManager", initializeCallbackManager, METH_VARARGS, (char*)"Initializes callbacks."}, + {(char*)"notifyCallbackEnd", notifyCallbackEnd, METH_VARARGS, (char*)"Notifies callaback's end."}, + {(char*)"registerPythonObserver", registerPythonObserver, METH_VARARGS, (char*)"Registers new python observer."}, + {(char*)"removePythonObserver", removePythonObserver, METH_VARARGS, (char*)"Removes a python observer."}, + {NULL, NULL, 0, NULL} +}; + char* name (char* name, u_long len) { char* str = (char*)"python"; @@ -73,16 +211,21 @@ setenv ("PYTHONPATH", path.c_str(), 1); } - Py_SetProgramName ((char *)("python")); - Py_Initialize (); + Py_SetProgramName ((char *)("python")); + Py_InitializeEx (0); PyEval_InitThreads (); mainThreadState = PyThreadState_Get (); pythonMainInterpreterState = mainThreadState->interp; - + PyEval_ReleaseLock (); + initModule((char*)"callbackManagerCSide",PythonCallbackManagerMethods); + + execute((char*)"import sys"); + execute((char*)"sys.path[0] = sys.path[0] + '/plugins/executors/python'"); + execute((char*)"from py import callbackManager"); return 0; } @@ -124,12 +267,33 @@ return 0; } -int execute (char* code, u_long length) + +convertFunction addTypeConverter(char* msg, convertFunction func) { - return executeImpl (code, length, NULL, 1); + string key(msg); + + convertFunction ret = convertFunctions.get(key); + + convertFunctions.put(key,func); + + return ret; } -int executeImpl (char* code, u_long length, PyThreadState *threadState, int newThreadState) +convertFunction removeTypeConverter(char* msg) +{ + string key(msg); + + convertFunction ret = convertFunctions.remove(key); + + return ret; +} + +int execute (char* code) +{ + return executeImpl (code, NULL, 1); +} + +int executeImpl (char* code, PyThreadState *threadState, int newThreadState) { PyInterpreterState *interpreter = NULL; PythonData* data = NULL; Index: plugins/executors/python/python.h =================================================================== --- plugins/executors/python/python.h (revision 2740) +++ plugins/executors/python/python.h (working copy) @@ -34,9 +34,9 @@ void clear(); }; -extern HashMap pythonThreadData; - +typedef PyObject* (*convertFunction)(void*); +extern HashMap pythonThreadData; #ifdef WIN32 #define EXPORTABLE(x) x _declspec(dllexport) @@ -50,12 +50,14 @@ EXPORTABLE(int) load(void* server,void* parser); EXPORTABLE(int) unLoad(void* p); +EXPORTABLE(convertFunction) addTypeConverter(char* msg, convertFunction); +EXPORTABLE(convertFunction) removeTypeConverter(char* msg); -EXPORTABLE(int) execute(char* code, u_long length); +EXPORTABLE(int) execute(char* code); EXPORTABLE(int) executeFromFile(char* filename); -EXPORTABLE(int) executeImpl (char* code, u_long length, PyThreadState *threadState, int newThreadState); +EXPORTABLE(int) executeImpl (char* code, PyThreadState *threadState, int newThreadState); EXPORTABLE(int) executeFromFileImpl(char* filename, PyThreadState *threadState, int newThreadState); EXPORTABLE(PyObject*) callObject(PyObject *obj, PyObject *args); Index: plugins/executors/python/py/__init__.py =================================================================== Index: plugins/executors/python/py/callbackManager.py =================================================================== --- plugins/executors/python/py/callbackManager.py (revision 0) +++ plugins/executors/python/py/callbackManager.py (revision 0) @@ -0,0 +1,71 @@ + +from threading import Thread as Work + +from Queue import * + +from callbackManagerCSide import * + +class MyServerData: + def __init__(self): + pass + +class MyServerThread(Work): + def __init__(self, queue): + self.queue = queue; + Work.__init__ ( self ) + + def run(self): + while True: + data = self.queue.get(True) + + myServerData = data["data"] + + for callback in data["callbacks"]: + callback.execute(myServerData) + + notifyCallbackEnd(data["tid"]) + + +class MyServerCallback: + + def __init__(self,callbackManager,msg): + callbackManager.addCallback(msg,self) + + def execute(self, data): + pass + +class MyServerCallbackManager: + + def __init__(self, nThreads): + self.callback = {} + self.threads = [] + self.queue = Queue(); + self.referenceCounter = {} + + for i in range(nThreads): + thread = MyServerThread(self.queue) + thread.start() + self.threads.append(thread) + + initializeCallbackManager(self) + + def addCallback(self, msg, callback): + self.callback[msg].append(callback) + + registerPythonObserver(msg) + + + def removeCallaback(self, msg, callback): + self.callback[msg].remove(callback) + removePythonObserver(msg) + + + def notifyMessage(self, tid, msg, myServerData): + data = {} + data["tid"] = tid + data["data"] = myServerData + data["callbacks"] = callback[msg] + queue.put(data) + + +callbackManager = MyServerCallbackManager(20) \ No newline at end of file