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

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

Stop blowing the stack in ulinet. Add API function addToMapWithSize for assigning binary data to map. Add support for binary inputs/outputs for the PHP language.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 15.4 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2014 GeoLabs SARL
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
27struct module_state {
28    PyObject *error;
29};
30
31#if PY_MAJOR_VERSION >= 3
32#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
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
40#else
41#define GETSTATE(m) (&_state)
42static struct module_state _state;
43#endif
44
45static PyObject* ZooError;
46
47PyMethodDef zooMethods[] = {
48  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
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
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
78PyMODINIT_FUNC init_zoo(){
79  PyObject *tmp,*d;
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
90    return;
91#endif
92  }
93
94  struct module_state *st = GETSTATE(module);
95
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
105  tmp = PyString_FromString(ZOO_VERSION);
106  PyDict_SetItemString(d, "VERSION", tmp);
107  Py_DECREF(tmp);
108
109  ZooError = PyErr_NewException((char*)"zoo.error", NULL, NULL);
110  Py_INCREF(ZooError);
111  PyModule_AddObject(module, "error", ZooError);
112#if PY_MAJOR_VERSION >= 3
113  return module;
114#endif
115}
116
117int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
118  char *pythonpath;
119  char *python_path;
120  maps* m=*main_conf;
121  maps* inputs=*real_inputs;
122  maps* outputs=*real_outputs;
123  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
124  char *ntmp=tmp0->value;
125  map* tmp=NULL;
126  int hasToClean=0;
127  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
128#ifdef DEBUG
129  fprintf(stderr,"PYTHON SUPPORT \n");
130#endif
131  if(tmp!=NULL){
132#ifdef DEBUG
133    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
134#endif
135    python_path=(char*)malloc((strlen(tmp->value))*sizeof(char));
136    sprintf(python_path,"%s",tmp->value);
137    hasToClean=1;
138  }
139  else{
140    python_path=(char*)".";
141  }
142  tmp=NULL;
143  tmp=getMap(request,"metapath");
144  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
145    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
146#ifdef WIN32
147  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
148#else
149  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
150#endif
151  }
152  else{
153    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
154#ifdef WIN32
155    sprintf(pythonpath,"%s;%s",ntmp,python_path);
156#else
157    sprintf(pythonpath,"%s:%s",ntmp,python_path);
158#endif
159  }
160#ifdef DEBUG
161    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
162#endif
163#ifndef WIN32
164  setenv("PYTHONPATH",pythonpath,1);
165#else
166  SetEnvironmentVariable("PYTHONPATH",pythonpath);
167  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
168  sprintf(toto,"PYTHONPATH=%s",pythonpath);
169  putenv(toto);
170  free(toto);
171#endif
172  if(hasToClean>0)
173    free(python_path);
174  free(pythonpath);
175
176  PyThreadState *mainstate;
177#if PY_MAJOR_VERSION >= 3
178  PyImport_AppendInittab("zoo", init_zoo);
179#else
180  PyEval_InitThreads();
181#endif
182  Py_Initialize();
183#if PY_MAJOR_VERSION >= 3
184  PyEval_InitThreads();
185  PyImport_ImportModule("zoo");
186#else
187  init_zoo();
188#endif
189  mainstate = PyThreadState_Swap(NULL);
190  PyEval_ReleaseLock();
191  PyGILState_STATE gstate;
192  gstate = PyGILState_Ensure();
193  PyObject *pName, *pModule, *pFunc;
194  tmp=getMap(s->content,"serviceProvider");
195  map* mp=getMap(request,"metapath");
196  if(tmp!=NULL){
197    if(mp!=NULL && strlen(mp->value)>0){
198      char *mps=zStrdup(mp->value);
199      int i,len=strlen(mps);
200      int j=0;
201      for(i=0;i<len;i++){
202        if(mps[i]=='/'){
203          mps[i]='.';
204        }
205      }
206      char *mn=(char*)malloc((strlen(mps)+strlen(tmp->value)+2)*sizeof(char));
207      sprintf(mn,"%s.%s",mps,tmp->value);
208      pName = PyString_FromString(mn);
209      free(mn);
210      free(mps);
211    }
212    else{
213      pName = PyString_FromString(tmp->value);
214      fprintf(stderr,"%s %d",tmp->value,__LINE__);
215    }
216  }
217  else{
218    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
219    addToMap(err,"code","NoApplicableCode");
220    printExceptionReportResponse(m,err);
221    exit(-1);
222  }
223  pModule = PyImport_Import(pName);
224  int res=SERVICE_FAILED;
225  if (pModule != NULL) {
226    pFunc=PyObject_GetAttrString(pModule,s->name);
227    if (pFunc && PyCallable_Check(pFunc)){
228      PyObject *pValue;
229      PyDictObject* arg1=PyDict_FromMaps(m);
230      PyDictObject* arg2=PyDict_FromMaps(inputs);
231      PyDictObject* arg3=PyDict_FromMaps(outputs);
232      PyObject *pArgs=PyTuple_New(3);
233      if (!pArgs)
234        return -1;
235      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
236      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
237      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
238      pValue = PyObject_CallObject(pFunc, pArgs);
239      if (pValue != NULL) {
240        res=PyInt_AsLong(pValue);
241        freeMaps(real_outputs);
242        free(*real_outputs);
243        freeMaps(main_conf);
244        free(*main_conf);
245        *main_conf=mapsFromPyDict(arg1);
246        *real_outputs=mapsFromPyDict(arg3);
247#ifdef DEBUG
248        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
249        dumpMaps(inputs);
250        dumpMaps(*real_outputs);
251#endif
252      }else{     
253        PyObject *ptype,*pvalue, *ptraceback;
254        PyErr_Fetch(&ptype, &pvalue, &ptraceback);
255        PyObject *trace=PyObject_Str(pvalue);
256        char pbt[10240];
257        if(PyString_Check(trace))
258          sprintf(pbt,"TRACE : %s",PyString_AsString(trace));
259        else
260          fprintf(stderr,"EMPTY TRACE ?");
261        trace=NULL;
262        trace=PyObject_Str(ptype);
263        if(PyString_Check(trace)){
264          char *tpbt=zStrdup(pbt);
265          sprintf(pbt,"%s\n%s",tpbt,PyString_AsString(trace));
266          free(tpbt);
267        }
268        else
269          fprintf(stderr,"EMPTY TRACE ?");
270       
271        char *tpbt=zStrdup(pbt);
272        pName = PyString_FromString("traceback");
273        pModule = PyImport_Import(pName);
274        pArgs = PyTuple_New(1);
275        PyTuple_SetItem(pArgs, 0, ptraceback);
276        pFunc = PyObject_GetAttrString(pModule,"format_tb");
277        pValue = PyObject_CallObject(pFunc, pArgs);
278        trace=NULL;
279        trace=PyObject_Str(pValue);
280        if(PyString_Check(trace))
281          sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",tpbt,PyString_AsString(trace));
282        else
283          sprintf(pbt,"%s \n Unable to run your python process properly. Unable to provide any futher informations.",tpbt);
284        free(tpbt);
285        map* err=createMap("text",pbt);
286        addToMap(err,"code","NoApplicableCode");
287        printExceptionReportResponse(m,err);
288        res=-1;
289      }
290    }
291    else{
292      char tmpS[1024];
293      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
294      map* tmps=createMap("text",tmpS);
295      printExceptionReportResponse(m,tmps);
296      res=-1;
297    }
298  } else{
299    char tmpS[1024];
300    sprintf(tmpS, "Python module %s cannot be loaded.\n", tmp->value);
301    map* tmps=createMap("text",tmpS);
302    printExceptionReportResponse(m,tmps);
303    if (PyErr_Occurred())
304      PyErr_Print();
305    PyErr_Clear();
306    res=-1;
307  } 
308#if PY_MAJOR_VERSION < 3
309  PyGILState_Release(gstate);
310  PyEval_AcquireLock();
311#endif
312  PyThreadState_Swap(mainstate);
313  Py_Finalize();
314  return res;
315}
316
317PyDictObject* PyDict_FromMaps(maps* t){
318  PyObject* res=PyDict_New( );
319  maps* tmp=t;
320  while(tmp!=NULL){
321    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
322    PyObject* name=PyString_FromString(tmp->name);
323    if(PyDict_SetItem(res,name,value)<0){
324      fprintf(stderr,"Unable to set map value ...");
325      return NULL;
326    }
327    Py_DECREF(name);
328    tmp=tmp->next;
329  } 
330  return (PyDictObject*) res;
331}
332
333PyDictObject* PyDict_FromMap(map* t){
334  PyObject* res=PyDict_New( );
335  map* tmp=t;
336  int hasSize=0;
337  map* isArray=getMap(tmp,"isArray");
338  map* size=getMap(tmp,"size");
339  map* tmap=getMapType(tmp);
340  while(tmp!=NULL){
341    PyObject* name=PyString_FromString(tmp->name);
342    if(strcasecmp(tmp->name,"value")==0) {
343      if(isArray!=NULL){
344        map* len=getMap(tmp,"length");
345        int cnt=atoi(len->value);
346        PyObject* value=PyList_New(cnt);
347        PyObject* mvalue=PyList_New(cnt);
348        PyObject* svalue=PyList_New(cnt);
349
350        for(int i=0;i<cnt;i++){
351         
352          map* vMap=getMapArray(tmp,"value",i);     
353          map* sMap=getMapArray(tmp,"size",i);
354
355          if(vMap!=NULL){
356           
357            PyObject* lvalue;
358            PyObject* lsvalue;
359            if(sMap==NULL){
360              lvalue=PyString_FromString(vMap->value);
361              lsvalue=Py_None;
362            }
363            else{   
364              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
365              lsvalue=PyString_FromString(sMap->value);
366              hasSize=1;
367            }
368
369            if(PyList_SetItem(value,i,lvalue)<0){
370              fprintf(stderr,"Unable to set key value pair...");
371              return NULL;
372            } 
373            if(PyList_SetItem(svalue,i,lsvalue)<0){
374              fprintf(stderr,"Unable to set key value pair...");
375              return NULL;
376            } 
377          }
378         
379          map* mMap=getMapArray(tmp,tmap->name,i);
380          PyObject* lmvalue;
381          if(mMap!=NULL){
382            lmvalue=PyString_FromString(mMap->value);
383          }else
384            lmvalue=Py_None;
385         
386          if(PyList_SetItem(mvalue,i,lmvalue)<0){
387              fprintf(stderr,"Unable to set key value pair...");
388              return NULL;
389          } 
390         
391        }
392
393        if(PyDict_SetItem(res,name,value)<0){
394          fprintf(stderr,"Unable to set key value pair...");
395          return NULL;
396        }
397        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
398          fprintf(stderr,"Unable to set key value pair...");
399          return NULL;
400        }
401        if(hasSize>0)
402          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
403            fprintf(stderr,"Unable to set key value pair...");
404            return NULL;
405          }
406      }
407      else if(size!=NULL){
408        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
409        if(PyDict_SetItem(res,name,value)<0){
410          Py_DECREF(value);
411          fprintf(stderr,"Unable to set key value pair...");
412          return NULL;
413        }
414        Py_DECREF(value);
415      }
416      else{
417        PyObject* value=PyString_FromString(tmp->value);
418        if(PyDict_SetItem(res,name,value)<0){
419          Py_DECREF(value);
420          fprintf(stderr,"Unable to set key value pair...");
421          return NULL;
422        }
423        Py_DECREF(value);
424      }
425    }
426    else{
427      if(PyDict_GetItem(res,name)==NULL){
428        PyObject* value=PyString_FromString(tmp->value);
429        if(PyDict_SetItem(res,name,value)<0){
430          Py_DECREF(value);
431          fprintf(stderr,"Unable to set key value pair...");
432          return NULL;
433        }
434        Py_DECREF(value);
435      }
436    }
437    Py_DECREF(name);
438    tmp=tmp->next;
439  }
440  return (PyDictObject*) res;
441}
442
443maps* mapsFromPyDict(PyDictObject* t){
444  maps* res=NULL;
445  maps* cursor=res;
446  PyObject* list=PyDict_Keys((PyObject*)t);
447  int nb=PyList_Size(list);
448  int i;
449  for(i=0;i<nb;i++){
450#ifdef DEBUG
451    fprintf(stderr,">> parsing maps %d\n",i);
452#endif
453    PyObject* key=PyList_GetItem(list,i);
454    PyObject* value=PyDict_GetItem((PyObject*)t,key);
455#ifdef DEBUG
456    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
457            PyString_AsString(key),PyString_AsString(value));
458#endif
459    cursor=(maps*)malloc(MAPS_SIZE);
460    cursor->name=PyString_AsString(key);
461    cursor->content=mapFromPyDict((PyDictObject*)value);
462#ifdef DEBUG
463    dumpMap(cursor->content);
464#endif
465    cursor->next=NULL;
466    if(res==NULL)
467      res=dupMaps(&cursor);
468    else
469      addMapsToMaps(&res,cursor);
470    freeMap(&cursor->content);
471    free(cursor->content);
472    free(cursor);
473    Py_DECREF(key);
474#ifdef DEBUG
475    dumpMaps(res);
476    fprintf(stderr,">> parsed maps %d\n",i);
477#endif
478  }
479  Py_DECREF(list);
480  return res;
481}
482
483map* mapFromPyDict(PyDictObject* t){
484  map* res=NULL;
485  PyObject* list=PyDict_Keys((PyObject*)t);
486  int nb=PyList_Size(list);
487  int i;
488  for(i=0;i<nb;i++){
489    PyObject* key=PyList_GetItem(list,i);
490    PyObject* value=PyDict_GetItem((PyObject*)t,key);
491#ifdef DEBUG
492    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
493            PyString_AsString(key),PyString_AsString(value));
494#endif
495   
496    if(strcmp(PyString_AsString(key),"value")==0){
497      char *buffer=NULL;
498      Py_ssize_t size;
499#if PY_MAJOR_VERSION >= 3
500      buffer=_PyUnicode_AsStringAndSize(value,&size);
501#else
502      PyString_AsStringAndSize(value,&buffer,&size);
503#endif
504      addToMapWithSize(res,"value",buffer,size);
505    }else{
506      char* lkey=PyString_AsString(key);
507      char* lvalue=PyString_AsString(value);
508      if(res!=NULL){
509        if(PyString_Size(value)>0)
510          addToMap(res,lkey,lvalue);
511      }
512      else{
513        if(PyString_Size(value)>0)
514          res=createMap(lkey,lvalue);
515      }
516    }
517  }
518  Py_DECREF(list);
519  return res;
520}
521
522PyObject*
523PythonTranslate(PyObject* self, PyObject* args)
524{
525  char *str;
526  if (!PyArg_ParseTuple(args, "s", &str)){
527#ifdef DEBUG
528    fprintf(stderr,"Incorrect arguments to update status function");
529#endif
530    return NULL;
531  }
532  return PyString_FromString(_ss(str));
533}
534
535PyObject*
536PythonUpdateStatus(PyObject* self, PyObject* args)
537{
538  maps* conf;
539  PyObject* confdict;
540  int istatus;
541  char* status;
542  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
543#ifdef DEBUG
544    fprintf(stderr,"Incorrect arguments to update status function");
545#endif
546    return NULL;
547  }
548  if (istatus < 0 || istatus > 100){
549     PyErr_SetString(ZooError, "Status must be a percentage.");
550     return NULL;
551  }else{
552     char tmpStatus[4];
553     snprintf(tmpStatus, 4, "%i", istatus);
554     status = zStrdup(tmpStatus);
555  }
556  /* now update the map */
557  {
558    PyObject* lenv = PyMapping_GetItemString(confdict, (char *)"lenv");
559    if (lenv && PyMapping_Check(lenv)){
560      PyObject* valobj = PyString_FromString(status);
561      PyMapping_SetItemString(lenv, (char *)"status", valobj);
562      Py_DECREF(valobj);
563    }
564    Py_DECREF(lenv);
565  }
566  conf = mapsFromPyDict((PyDictObject*)confdict);
567  if (getMapFromMaps(conf,"lenv","status") != NULL){
568    if(status!=NULL){
569      setMapInMaps(conf,"lenv","status",status);
570      free(status);
571    }
572    else
573      setMapInMaps(conf,"lenv","status","15");
574    _updateStatus(conf);
575  }
576  freeMaps(&conf);
577  free(conf);
578  Py_RETURN_NONE;
579}
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