source: trunk/zoo-project/zoo-kernel/service_internal_python.c @ 471

Last change on this file since 471 was 471, checked in by djay, 10 years ago

Remove leaks from DescribeProcess? and JavaScript? support. Fix wrong ulinet update on previous commit. Use the new updateStatus/setOutputValue functions as described in #88 from longProcess. Add default value for QREncode service in ZCFG. Fix name of profile service in the ZCFG file.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 15.2 KB
RevLine 
[1]1/**
2 * Author : Gérald FENOY
3 *
[453]4 * Copyright (c) 2009-2014 GeoLabs SARL
[1]5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "service_internal_python.h"
26
[392]27struct module_state {
28    PyObject *error;
29};
30
31#if PY_MAJOR_VERSION >= 3
32#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
[453]33#define PyInt_FromLong PyLong_FromLong
34#define PyInt_AsLong PyLong_AsLong
35#define PyString_FromString PyUnicode_FromString
36#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
37#define PyString_Check PyUnicode_Check
38#define PyString_AsString _PyUnicode_AsString
39#define PyString_Size PyUnicode_GetSize
[392]40#else
41#define GETSTATE(m) (&_state)
42static struct module_state _state;
43#endif
44
[368]45static PyObject* ZooError;
46
47PyMethodDef zooMethods[] = {
[376]48  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
[368]49  {"update_status", PythonUpdateStatus, METH_VARARGS, "Update status percentage of a running process."},
50  {NULL, NULL, 0, NULL} /* tempt not the blade, all fear the sentinel */
51};
52
[392]53#if PY_MAJOR_VERSION >= 3
54
55static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
56  Py_VISIT(GETSTATE(m)->error);
57  return 0;
58}
59
60static int myextension_clear(PyObject *m) {
61  Py_CLEAR(GETSTATE(m)->error);
62  return 0;
63}
64
65static struct PyModuleDef moduledef = {
66  PyModuleDef_HEAD_INIT,
67  "zoo",
68  NULL,
69  sizeof(struct module_state),
70  zooMethods,
71  NULL,
72  myextension_traverse,
73  myextension_clear,
74  NULL
75};
76#endif
77
[368]78PyMODINIT_FUNC init_zoo(){
79  PyObject *tmp,*d;
[392]80  PyObject *module = 
81#if PY_MAJOR_VERSION >= 3
82    PyModule_Create(&moduledef);
83#else
84    Py_InitModule("zoo", zooMethods);
85#endif
86  if (module == NULL){
87#if PY_MAJOR_VERSION >= 3
88    return NULL;
89#else
[368]90    return;
[392]91#endif
92  }
93
94  struct module_state *st = GETSTATE(module);
95
[368]96  d = PyModule_GetDict(module);
97  tmp = PyInt_FromLong(3);
98  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
99  Py_DECREF(tmp);
100
101  tmp = PyInt_FromLong(4);
102  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
103  Py_DECREF(tmp);
104
[465]105  tmp = PyString_FromString(ZOO_VERSION);
106  PyDict_SetItemString(d, "VERSION", tmp);
107  Py_DECREF(tmp);
108
[368]109  ZooError = PyErr_NewException("zoo.error", NULL, NULL);
110  Py_INCREF(ZooError);
111  PyModule_AddObject(module, "error", ZooError);
[392]112#if PY_MAJOR_VERSION >= 3
113  return module;
114#endif
[368]115}
116
[1]117int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
[451]118  char *pythonpath;
119  char *python_path;
[1]120  maps* m=*main_conf;
121  maps* inputs=*real_inputs;
122  maps* outputs=*real_outputs;
[392]123  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
124  char *ntmp=tmp0->value;
[1]125  map* tmp=NULL;
[451]126  int hasToClean=0;
[1]127  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
[63]128#ifdef DEBUG
[9]129  fprintf(stderr,"PYTHON SUPPORT \n");
[63]130#endif
[1]131  if(tmp!=NULL){
[63]132#ifdef DEBUG
[9]133    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
[63]134#endif
[9]135    python_path=(char*)malloc((strlen(tmp->value))*sizeof(char));
136    sprintf(python_path,"%s",tmp->value);
[451]137    hasToClean=1;
[1]138  }
139  else{
[451]140    python_path=".";
[1]141  }
142  tmp=NULL;
143  tmp=getMap(request,"metapath");
[392]144  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
145    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
[1]146#ifdef WIN32
[451]147  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
[1]148#else
[451]149  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
[1]150#endif
[392]151  }
152  else{
153    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
[1]154#ifdef WIN32
155    sprintf(pythonpath,"%s;%s",ntmp,python_path);
156#else
[392]157    sprintf(pythonpath,"%s:%s",ntmp,python_path);
[1]158#endif
[392]159  }
[67]160#ifdef DEBUG
[9]161    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
[67]162#endif
[1]163#ifndef WIN32
164  setenv("PYTHONPATH",pythonpath,1);
165#else
166  SetEnvironmentVariable("PYTHONPATH",pythonpath);
[364]167  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
168  sprintf(toto,"PYTHONPATH=%s",pythonpath);
169  putenv(toto);
[451]170  free(toto);
[1]171#endif
[451]172  if(hasToClean>0)
173    free(python_path);
[1]174  free(pythonpath);
[9]175
[295]176  PyThreadState *mainstate;
[392]177#if PY_MAJOR_VERSION >= 3
178  PyImport_AppendInittab("zoo", init_zoo);
179#else
[295]180  PyEval_InitThreads();
[392]181#endif
[1]182  Py_Initialize();
[392]183#if PY_MAJOR_VERSION >= 3
184  PyEval_InitThreads();
185  PyImport_ImportModule("zoo");
186#else
[368]187  init_zoo();
[392]188#endif
[295]189  mainstate = PyThreadState_Swap(NULL);
190  PyEval_ReleaseLock();
191  PyGILState_STATE gstate;
192  gstate = PyGILState_Ensure();
[1]193  PyObject *pName, *pModule, *pFunc;
194  tmp=getMap(s->content,"serviceProvider");
[9]195  if(tmp!=NULL)
[453]196    pName = PyString_FromString(tmp->value);
[9]197  else{
198    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
199    addToMap(err,"code","NoApplicableCode");
200    printExceptionReportResponse(m,err);
201    exit(-1);
202  }
[1]203  pModule = PyImport_Import(pName);
204  int res=SERVICE_FAILED;
205  if (pModule != NULL) {
206    pFunc=PyObject_GetAttrString(pModule,s->name);
207    if (pFunc && PyCallable_Check(pFunc)){
[114]208      PyObject *pValue;
[1]209      PyDictObject* arg1=PyDict_FromMaps(m);
210      PyDictObject* arg2=PyDict_FromMaps(inputs);
211      PyDictObject* arg3=PyDict_FromMaps(outputs);
212      PyObject *pArgs=PyTuple_New(3);
[114]213      if (!pArgs)
214        return -1;
[1]215      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
216      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
217      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
218      pValue = PyObject_CallObject(pFunc, pArgs);
219      if (pValue != NULL) {
220        res=PyInt_AsLong(pValue);
[9]221        freeMaps(real_outputs);
222        free(*real_outputs);
[59]223        freeMaps(main_conf);
224        free(*main_conf);
[57]225        *main_conf=mapsFromPyDict(arg1);
[9]226        *real_outputs=mapsFromPyDict(arg3);
[1]227#ifdef DEBUG
228        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
229        dumpMaps(inputs);
[364]230        dumpMaps(*real_outputs);
[1]231#endif
[9]232      }else{     
[1]233        PyObject *ptype,*pvalue, *ptraceback;
234        PyErr_Fetch(&ptype, &pvalue, &ptraceback);
235        PyObject *trace=PyObject_Str(pvalue);
236        char pbt[10240];
237        if(PyString_Check(trace))
238          sprintf(pbt,"TRACE : %s",PyString_AsString(trace));
239        else
240          fprintf(stderr,"EMPTY TRACE ?");
241        trace=NULL;
242        trace=PyObject_Str(ptype);
[59]243        if(PyString_Check(trace)){
[453]244          char *tpbt=zStrdup(pbt);
[337]245          sprintf(pbt,"%s\n%s\0",tpbt,PyString_AsString(trace));
[59]246          free(tpbt);
247        }
[1]248        else
249          fprintf(stderr,"EMPTY TRACE ?");
[332]250       
[453]251        char *tpbt=zStrdup(pbt);
[1]252        pName = PyString_FromString("traceback");
253        pModule = PyImport_Import(pName);
254        pArgs = PyTuple_New(1);
255        PyTuple_SetItem(pArgs, 0, ptraceback);
256        pFunc = PyObject_GetAttrString(pModule,"format_tb");
257        pValue = PyObject_CallObject(pFunc, pArgs);
258        trace=NULL;
259        trace=PyObject_Str(pValue);
260        if(PyString_Check(trace))
[332]261          sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",tpbt,PyString_AsString(trace));
[1]262        else
[332]263          sprintf(pbt,"%s \n Unable to run your python process properly. Unable to provide any futher informations. %s",tpbt);
264        free(tpbt);
[1]265        map* err=createMap("text",pbt);
266        addToMap(err,"code","NoApplicableCode");
267        printExceptionReportResponse(m,err);
[295]268        res=-1;
[1]269      }
270    }
271    else{
272      char tmpS[1024];
[295]273      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
[1]274      map* tmps=createMap("text",tmpS);
275      printExceptionReportResponse(m,tmps);
[295]276      res=-1;
[1]277    }
278  } else{
279    char tmpS[1024];
[9]280    sprintf(tmpS, "Python module %s cannot be loaded.\n", tmp->value);
[1]281    map* tmps=createMap("text",tmpS);
282    printExceptionReportResponse(m,tmps);
283    if (PyErr_Occurred())
284      PyErr_Print();
[295]285    PyErr_Clear();
286    res=-1;
287    //exit(-1);
[1]288  } 
[392]289#if PY_MAJOR_VERSION < 3
[295]290  PyGILState_Release(gstate);
[469]291  PyEval_ReleaseLock();
[392]292#endif
[295]293  PyThreadState_Swap(mainstate);
[1]294  Py_Finalize();
295  return res;
296}
297
298PyDictObject* PyDict_FromMaps(maps* t){
299  PyObject* res=PyDict_New( );
300  maps* tmp=t;
301  while(tmp!=NULL){
[295]302    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
[453]303    PyObject* name=PyString_FromString(tmp->name);
[295]304    if(PyDict_SetItem(res,name,value)<0){
305      fprintf(stderr,"Unable to set map value ...");
306      return NULL;
[1]307    }
[295]308    Py_DECREF(name);
[1]309    tmp=tmp->next;
310  } 
311  return (PyDictObject*) res;
312}
313
314PyDictObject* PyDict_FromMap(map* t){
315  PyObject* res=PyDict_New( );
316  map* tmp=t;
[360]317  int hasSize=0;
318  map* isArray=getMap(tmp,"isArray");
[58]319  map* size=getMap(tmp,"size");
[360]320  map* tmap=getMapType(tmp);
[1]321  while(tmp!=NULL){
[453]322    PyObject* name=PyString_FromString(tmp->name);
[360]323    if(strcasecmp(tmp->name,"value")==0) {
324      if(isArray!=NULL){
325        map* len=getMap(tmp,"length");
326        int cnt=atoi(len->value);
327        PyObject* value=PyList_New(cnt);
328        PyObject* mvalue=PyList_New(cnt);
329        PyObject* svalue=PyList_New(cnt);
330
331        for(int i=0;i<cnt;i++){
332         
333          map* vMap=getMapArray(tmp,"value",i);     
334          map* sMap=getMapArray(tmp,"size",i);
335
336          if(vMap!=NULL){
337           
338            PyObject* lvalue;
339            PyObject* lsvalue;
340            if(sMap==NULL){
341              lvalue=PyString_FromString(vMap->value);
342              lsvalue=Py_None;
343            }
[453]344            else{   
[360]345              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
346              lsvalue=PyString_FromString(sMap->value);
347              hasSize=1;
348            }
349
350            if(PyList_SetItem(value,i,lvalue)<0){
351              fprintf(stderr,"Unable to set key value pair...");
352              return NULL;
353            } 
354            if(PyList_SetItem(svalue,i,lsvalue)<0){
355              fprintf(stderr,"Unable to set key value pair...");
356              return NULL;
357            } 
358          }
359         
360          map* mMap=getMapArray(tmp,tmap->name,i);
361          PyObject* lmvalue;
362          if(mMap!=NULL){
363            lmvalue=PyString_FromString(mMap->value);
364          }else
365            lmvalue=Py_None;
366         
367          if(PyList_SetItem(mvalue,i,lmvalue)<0){
368              fprintf(stderr,"Unable to set key value pair...");
369              return NULL;
370          } 
371         
372        }
373
374        if(PyDict_SetItem(res,name,value)<0){
375          fprintf(stderr,"Unable to set key value pair...");
376          return NULL;
377        }
378        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
379          fprintf(stderr,"Unable to set key value pair...");
380          return NULL;
381        }
382        if(hasSize>0)
383          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
384            fprintf(stderr,"Unable to set key value pair...");
385            return NULL;
386          }
387      }
388      else if(size!=NULL){
[453]389        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
[59]390        if(PyDict_SetItem(res,name,value)<0){
[471]391          Py_DECREF(value);
[295]392          fprintf(stderr,"Unable to set key value pair...");
393          return NULL;
[43]394        }
[471]395        Py_DECREF(value);
[58]396      }
[59]397      else{
[453]398        PyObject* value=PyString_FromString(tmp->value);
[59]399        if(PyDict_SetItem(res,name,value)<0){
[471]400          Py_DECREF(value);
[295]401          fprintf(stderr,"Unable to set key value pair...");
402          return NULL;
[43]403        }
[471]404        Py_DECREF(value);
[59]405      }
406    }
407    else{
[360]408      if(PyDict_GetItem(res,name)==NULL){
[453]409        PyObject* value=PyString_FromString(tmp->value);
[360]410        if(PyDict_SetItem(res,name,value)<0){
[471]411          Py_DECREF(value);
[360]412          fprintf(stderr,"Unable to set key value pair...");
413          return NULL;
414        }
[471]415        Py_DECREF(value);
[43]416      }
[59]417    }
418    Py_DECREF(name);
[1]419    tmp=tmp->next;
420  }
421  return (PyDictObject*) res;
422}
423
424maps* mapsFromPyDict(PyDictObject* t){
425  maps* res=NULL;
426  maps* cursor=res;
427  PyObject* list=PyDict_Keys((PyObject*)t);
428  int nb=PyList_Size(list);
429  int i;
430  for(i=0;i<nb;i++){
431#ifdef DEBUG
432    fprintf(stderr,">> parsing maps %d\n",i);
433#endif
434    PyObject* key=PyList_GetItem(list,i);
435    PyObject* value=PyDict_GetItem((PyObject*)t,key);
436#ifdef DEBUG
437    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
438            PyString_AsString(key),PyString_AsString(value));
439#endif
[9]440    cursor=(maps*)malloc(MAPS_SIZE);
[1]441    cursor->name=PyString_AsString(key);
[295]442    cursor->content=mapFromPyDict((PyDictObject*)value);
[1]443#ifdef DEBUG
[295]444    dumpMap(cursor->content);
[1]445#endif
446    cursor->next=NULL;
447    if(res==NULL)
[59]448      res=dupMaps(&cursor);
[1]449    else
450      addMapsToMaps(&res,cursor);
[59]451    freeMap(&cursor->content);
452    free(cursor->content);
453    free(cursor);
[471]454    Py_DECREF(key);
[1]455#ifdef DEBUG
456    dumpMaps(res);
457    fprintf(stderr,">> parsed maps %d\n",i);
458#endif
459  }
460  return res;
461}
462
463map* mapFromPyDict(PyDictObject* t){
464  map* res=NULL;
465  PyObject* list=PyDict_Keys((PyObject*)t);
466  int nb=PyList_Size(list);
467  int i;
468  for(i=0;i<nb;i++){
469    PyObject* key=PyList_GetItem(list,i);
470    PyObject* value=PyDict_GetItem((PyObject*)t,key);
471#ifdef DEBUG
472    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
473            PyString_AsString(key),PyString_AsString(value));
474#endif
[453]475   
[100]476    if(strcmp(PyString_AsString(key),"value")==0){
477      char *buffer=NULL;
[67]478      Py_ssize_t size;
[392]479#if PY_MAJOR_VERSION >= 3
480      buffer=_PyUnicode_AsStringAndSize(value,&size);
481#else
[67]482      PyString_AsStringAndSize(value,&buffer,&size);
[392]483#endif
[67]484      if(res!=NULL){
485        addToMap(res,PyString_AsString(key),"");
486      }else{
487        res=createMap(PyString_AsString(key),"");
488      }
489      map* tmpR=getMap(res,"value");
490      free(tmpR->value);
[100]491      tmpR->value=(char*)malloc((size+1)*sizeof(char));
492      memmove(tmpR->value,buffer,size*sizeof(char));
493      tmpR->value[size]=0;
494      char sin[1024];
495      sprintf(sin,"%d",size);
496      addToMap(res,"size",sin);
[67]497    }else{
[471]498      char* lkey=PyString_AsString(key);
499      char* lvalue=PyString_AsString(value);
[392]500      if(res!=NULL){
[411]501        if(PyString_Size(value)>0)
[471]502          addToMap(res,lkey,lvalue);
[392]503      }
504      else{
[411]505        if(PyString_Size(value)>0)
[471]506          res=createMap(lkey,lvalue);
[392]507      }
[67]508    }
[471]509    Py_DECREF(value);
510    Py_DECREF(key);
[1]511  }
512  return res;
513}
[368]514
515PyObject*
[376]516PythonTranslate(PyObject* self, PyObject* args)
517{
518  char *str;
519  if (!PyArg_ParseTuple(args, "s", &str)){
520#ifdef DEBUG
521    fprintf(stderr,"Incorrect arguments to update status function");
522#endif
523    return NULL;
524  }
525  return PyString_FromString(_ss(str));
526}
527
528PyObject*
[368]529PythonUpdateStatus(PyObject* self, PyObject* args)
530{
531  maps* conf;
532  PyObject* confdict;
533  int istatus;
534  char* status;
535  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
536#ifdef DEBUG
537    fprintf(stderr,"Incorrect arguments to update status function");
538#endif
539    return NULL;
540  }
541  if (istatus < 0 || istatus > 100){
542     PyErr_SetString(ZooError, "Status must be a percentage.");
543     return NULL;
544  }else{
545     char tmpStatus[4];
546     snprintf(tmpStatus, 4, "%i", istatus);
[453]547     status = zStrdup(tmpStatus);
[368]548  }
549  /* now update the map */
550  {
551    PyObject* lenv = PyMapping_GetItemString(confdict, "lenv");
552    if (lenv && PyMapping_Check(lenv)){
[453]553      PyObject* valobj = PyString_FromString(status);
[368]554      PyMapping_SetItemString(lenv, "status", valobj);
555      Py_DECREF(valobj);
556    }
557    Py_DECREF(lenv);
558  }
559  conf = mapsFromPyDict((PyDictObject*)confdict);
560  if (getMapFromMaps(conf,"lenv","status") != NULL){
561    if(status!=NULL){
562      setMapInMaps(conf,"lenv","status",status);
563      free(status);
564    }
565    else
566      setMapInMaps(conf,"lenv","status","15");
[471]567    _updateStatus(conf);
[368]568  }
569  freeMaps(&conf);
570  free(conf);
571  Py_RETURN_NONE;
572}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png