source: branches/prototype-v0/zoo-project/zoo-kernel/service_internal_python.c @ 933

Last change on this file since 933 was 933, checked in by knut, 3 years ago

Resolve certain string-related type conflicts, e.g., char* vs. const char* or char[N], that may cause errors in some build environments. Resolve a problem with the include order of fcgi_stdio.h (note: should verify that this harmonizes with resolution of same problem in trunk).

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 23.8 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
27/**
28 * The state for the zoo Python module
29 */
30struct module_state {
31   PyObject *error;
32};
33
34#if PY_MAJOR_VERSION >= 3
35#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
36#define PyInt_FromLong PyLong_FromLong
37#define PyInt_AsLong PyLong_AsLong
38#define PyString_FromString PyUnicode_FromString
39#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
40#define PyString_Check PyUnicode_Check
41#define PyString_AsString _PyUnicode_AsString
42#define PyString_Size PyUnicode_GetSize
43#else
44#define GETSTATE(m) (&_state)
45static struct module_state _state;
46#endif
47
48/**
49 * The exception for the zoo Python module
50 */
51static PyObject* ZooError;
52
53/**
54 * Function definitions for the zoo Python Module
55 *
56 * Define the following functions available from a service loaded and running
57 * from the ZOO-Kernel Python environment:
58 *  - "_" corresponding to the PythonTranslate function
59 *  - "update_status" corresponding to the PythonUpdateStatus function
60 * @see PythonTranslate, PythonUpdateStatus
61 */
62PyMethodDef zooMethods[] = {
63  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
64  {"update_status", PythonUpdateStatus, METH_VARARGS, "Update status percentage of a running process."},
65  {NULL, NULL, 0, NULL} /* tempt not the blade, all fear the sentinel */
66};
67
68#if PY_MAJOR_VERSION >= 3
69
70static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
71  Py_VISIT(GETSTATE(m)->error);
72  return 0;
73}
74
75static int myextension_clear(PyObject *m) {
76  Py_CLEAR(GETSTATE(m)->error);
77  return 0;
78}
79
80static struct PyModuleDef moduledef = {
81  PyModuleDef_HEAD_INIT,
82  "zoo",
83  NULL,
84  sizeof(struct module_state),
85  zooMethods,
86  NULL,
87  myextension_traverse,
88  myextension_clear,
89  NULL
90};
91#endif
92
93/**
94 * Function to create and initialize the zoo Python module
95 *
96 * @return the Python module (for Python versions < 3, nothing for version >=3)
97 */
98PyMODINIT_FUNC init_zoo(){
99  PyObject *tmp,*d;
100  PyObject *module = 
101#if PY_MAJOR_VERSION >= 3
102    PyModule_Create(&moduledef);
103#else
104    Py_InitModule("zoo", zooMethods);
105#endif
106  if (module == NULL){
107#if PY_MAJOR_VERSION >= 3
108    return NULL;
109#else
110    return;
111#endif
112  }
113
114  struct module_state *st = GETSTATE(module);
115
116  d = PyModule_GetDict(module);
117  tmp = PyInt_FromLong(3);
118  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
119  Py_DECREF(tmp);
120
121  tmp = PyInt_FromLong(4);
122  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
123  Py_DECREF(tmp);
124
125  tmp = PyString_FromString(ZOO_VERSION);
126  PyDict_SetItemString(d, "VERSION", tmp);
127  Py_DECREF(tmp);
128
129  ZooError = PyErr_NewException((char*)"zoo.error", NULL, NULL);
130  Py_INCREF(ZooError);
131  PyModule_AddObject(module, "error", ZooError);
132#if PY_MAJOR_VERSION >= 3
133  return module;
134#endif
135}
136
137/**
138 * Load a Python module then run the function corresponding to the service
139 * by passing the conf, inputs and outputs parameters by reference.
140 *
141 * @param main_conf the conf maps containing the main.cfg settings
142 * @param request the map containing the HTTP request
143 * @param s the service structure
144 * @param real_inputs the maps containing the inputs
145 * @param real_outputs the maps containing the outputs
146 */
147int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
148
149  char *pythonpath;
150  char *python_path;
151
152#ifdef WIN32
153  const char* os_pathsep = ";";
154#else
155  const char* os_pathsep = ":";
156#endif
157  static char EMPTY[] = "";
158
159  maps* m=*main_conf;
160  maps* inputs=*real_inputs;
161  maps* outputs=*real_outputs;
162  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
163  char *ntmp=tmp0->value; 
164  map* tmp=NULL;
165  int hasToClean=0;
166  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH"); 
167
168  map* kvp = NULL;
169  char* libPath = NULL;
170  if (hasvalue(*main_conf, "main", "libPath", &kvp)) {
171          libPath = kvp->value;
172  }
173  else {
174          //libPath = "";
175    libPath = EMPTY;
176  }
177
178#ifdef DEBUG
179  fprintf(stderr,"PYTHON SUPPORT \n");
180#endif
181  if(tmp!=NULL){
182#ifdef DEBUG
183    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
184#endif
185    python_path=(char*)malloc((strlen(tmp->value)+1)*sizeof(char));
186    sprintf(python_path,"%s",tmp->value);
187    hasToClean=1;
188  }
189  else{
190    map* cwdMap=getMapFromMaps(*main_conf,"main","servicePath");
191    if(cwdMap!=NULL)
192      python_path=cwdMap->value;
193    else
194      python_path=(char*)".";   
195  }
196  tmp=NULL;
197  tmp=getMap(request,"metapath");
198  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
199    //pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
200          pythonpath = (char*)malloc((5 + strlen(python_path) + strlen(ntmp) + strlen(tmp->value) + strlen(libPath)) * sizeof(char));
201#ifdef WIN32
202  //sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
203        sprintf(pythonpath, "%s/%s/;%s;%s", ntmp, tmp->value, python_path, libPath);
204#else
205  //sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
206  sprintf(pythonpath, "%s/%s/:%s:%s", ntmp, tmp->value, python_path, libPath); 
207#endif
208  }
209  else{
210    //pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
211          pythonpath = (char*)malloc((3 + strlen(python_path) + strlen(ntmp) + strlen(libPath)) * sizeof(char));
212#ifdef WIN32
213    //sprintf(pythonpath,"%s;%s",ntmp,python_path);
214        sprintf(pythonpath, "%s;%s;%s", ntmp, python_path, libPath);
215#else
216    //sprintf(pythonpath,"%s:%s",ntmp,python_path);
217        sprintf(pythonpath, "%s:%s:%s", ntmp, python_path, libPath);
218#endif 
219  }
220#ifdef DEBUG
221    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
222#endif
223        map* home = NULL;
224// knut: also set PYTHONHOME environment variable so that Python can load standard modules
225#ifndef WIN32   
226  setenv("PYTHONPATH",pythonpath,1); 
227  //= getMapFromMaps(*main_conf, "env", "PYTHONHOME");
228  if (hasvalue(*main_conf, "env", "PYTHONHOME", &home)) {
229          setenv("PYTHONHOME", home->value, 1); // overwrite
230  }
231#else   
232  SetEnvironmentVariable("PYTHONPATH",pythonpath);
233  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
234  sprintf(toto,"PYTHONPATH=%s",pythonpath);
235  _putenv(toto);
236  free(toto);
237  if (hasvalue(*main_conf, "env", "PYTHONHOME", &home)) { 
238          SetEnvironmentVariable("PYTHONHOME", home->value);
239  }
240  char buffer[128];       
241#endif 
242  if(hasToClean>0)
243    free(python_path);
244  free(pythonpath);
245
246  PyThreadState *mainstate;
247#if PY_MAJOR_VERSION >= 3 
248  PyImport_AppendInittab("zoo", init_zoo); 
249#else
250  PyEval_InitThreads();
251#endif 
252  Py_Initialize(); 
253#if PY_MAJOR_VERSION >= 3 
254  PyEval_InitThreads();
255  PyImport_ImportModule("zoo"); 
256#else
257  init_zoo();
258#endif 
259  mainstate = PyThreadState_Swap(NULL);
260  PyEval_ReleaseLock();
261  PyGILState_STATE gstate;
262  gstate = PyGILState_Ensure();
263  PyObject *pName, *pModule, *pFunc;
264  tmp=getMap(s->content,"serviceProvider");
265  map* mp=getMap(request,"metapath");
266  if(tmp!=NULL){
267    if(mp!=NULL && strlen(mp->value)>0){
268      char *mps=zStrdup(mp->value);
269      int i,len=strlen(mps);
270      int j=0;
271      for(i=0;i<len;i++){
272        if(mps[i]=='/'){
273          mps[i]='.';
274        }
275      }
276      char *mn=(char*)malloc((strlen(mps)+strlen(tmp->value)+2)*sizeof(char));
277      sprintf(mn,"%s.%s",mps,tmp->value);
278      pName = PyString_FromString(mn);   
279      free(mn);
280      free(mps);
281    }
282    else{
283      pName = PyString_FromString(tmp->value);
284    }
285  }
286  else{
287    errorException (m, "Unable to parse serviceProvider please check your zcfg file.", "NoApplicableCode", NULL);
288    exit(-1);
289  } 
290  pModule = PyImport_Import(pName);   
291  int res=SERVICE_FAILED;
292  if (pModule != NULL) {
293    pFunc=PyObject_GetAttrString(pModule,s->name);
294    if (pFunc && PyCallable_Check(pFunc)){
295      PyObject *pValue;
296      PyDictObject* arg1=PyDict_FromMaps(m);
297      PyDictObject* arg2=PyDict_FromMaps(inputs);
298      PyDictObject* arg3=PyDict_FromMaps(outputs);
299      PyObject *pArgs=PyTuple_New(3);
300      if (!pArgs)
301        return -1;
302      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
303      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
304      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
305      pValue = PyObject_CallObject(pFunc, pArgs);         
306      if (pValue != NULL) {
307        res=PyInt_AsLong(pValue);
308        freeMaps(real_outputs);
309        free(*real_outputs);
310        freeMaps(main_conf);
311        free(*main_conf);
312        *main_conf=mapsFromPyDict(arg1);
313        *real_outputs=mapsFromPyDict(arg3);     
314#ifdef DEBUG
315        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
316        dumpMaps(inputs);
317        dumpMaps(*real_outputs);
318#endif
319      }else{
320        PythonZooReport(m,tmp->value,0);
321        res=-1;
322      }
323    }
324    else{
325      char tmpS[1024];
326      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
327      errorException(m,tmpS,"NoApplicableCode",NULL);
328      res=-1;
329    }
330  } else{
331    PythonZooReport(m,tmp->value,1);
332    res=-1;
333  } 
334#if PY_MAJOR_VERSION < 3
335  PyGILState_Release(gstate);
336  PyEval_AcquireLock();
337#endif
338  PyThreadState_Swap(mainstate);
339  Py_Finalize(); 
340  return res;
341}
342
343/**
344 * Report Python error which may occur on loading the Python module or at
345 * runtime.
346 *
347 * @param m the conf maps containing the main.cfg settings
348 * @param module the service name
349 * @param load 1 if the Python module was not loaded yet
350 */
351void PythonZooReport(maps* m,const char* module,int load){
352  PyObject *pName, *pModule, *pFunc;
353  PyObject *ptype, *pvalue, *ptraceback,*pValue,*pArgs;
354  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
355  char *pStrErrorMessage = PyString_AsString(pvalue);
356  char *tmp0=_("Python module %s cannot be loaded. Message: %s\n");
357 
358  PyObject *trace=PyObject_Str(pvalue);
359  char *pbt=NULL;
360  if(PyString_Check(trace)){
361    pbt=(char*)malloc((8+strlen(PyString_AsString(trace)))*sizeof(char));
362    sprintf(pbt,"TRACE: %s",PyString_AsString(trace));
363  }
364  else
365    fprintf(stderr,"EMPTY TRACE ?");
366
367  trace=NULL;
368 
369  trace=PyObject_Str(ptype);
370  if(PyString_Check(trace)){
371    char *tpbt=zStrdup(pbt);
372    if(pbt!=NULL)
373      free(pbt);
374    pbt=(char*)malloc((1+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
375    sprintf(pbt,"%s\n%s",tpbt,PyString_AsString(trace));
376    free(tpbt);
377  }
378  else
379    fprintf(stderr,"EMPTY TRACE ?");
380 
381  if(ptraceback!=NULL){
382    char *tpbt=zStrdup(pbt);
383    pName = PyString_FromString("traceback");
384    pModule = PyImport_Import(pName);
385    pArgs = PyTuple_New(1);
386    PyTuple_SetItem(pArgs, 0, ptraceback);
387    pFunc = PyObject_GetAttrString(pModule,"format_tb");
388    pValue = PyObject_CallObject(pFunc, pArgs);
389    trace=NULL;
390    trace=PyObject_Str(pValue);
391    if(PyString_Check(trace)){
392      if(pbt!=NULL)
393        free(pbt);
394      char* format=_("%s\nUnable to run your python process properly. Please check the following messages : %s");
395      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
396      sprintf(pbt,format,tpbt,PyString_AsString(trace));
397    }
398    else{
399      if(pbt!=NULL)
400        free(pbt);
401      char* format=_("%s \n Unable to run your python process properly. Unable to provide any further information.");
402      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
403      sprintf(pbt,format,tpbt);
404    }
405    free(tpbt);
406  }
407  if(load>0){
408    char *tmpS=(char*)malloc((strlen(tmp0)+strlen(module)+strlen(pbt)+1)*sizeof(char));
409    sprintf(tmpS,tmp0,module,pbt);
410    errorException(m,tmpS,"NoApplicableCode",NULL);
411    free(tmpS);
412  }else
413    errorException(m,pbt,"NoApplicableCode",NULL);
414  free(pbt);
415}
416
417/**
418 * Convert a maps to a Python dictionary
419 *
420 * @param t the maps to convert
421 * @return a new PyDictObject containing the converted maps
422 * @see PyDict_FromMap
423 * @warning make sure to free resources returned by this function
424 */
425PyDictObject* PyDict_FromMaps(maps* t){
426  PyObject* res=PyDict_New( );
427  maps* tmp=t;
428  while(tmp!=NULL){
429    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
430    if(tmp->child!=NULL){
431      PyObject* cname=PyString_FromString("child");
432      PyObject* childs=(PyObject*)PyDict_FromMaps(tmp->child);
433      if(PyDict_SetItem(value,cname,childs)<0){
434        fprintf(stderr,"Unable to set map value ...");
435        return NULL;
436      } 
437      Py_DECREF(cname);
438    }
439    PyObject* name=PyString_FromString(tmp->name);
440    if(PyDict_SetItem(res,name,value)<0){
441      fprintf(stderr,"Unable to set map value ...");
442      return NULL;
443    }
444    Py_DECREF(name);
445    tmp=tmp->next;
446  } 
447  return (PyDictObject*) res;
448}
449
450/**
451 * Convert a map to a Python dictionary
452 *
453 * @param t the map to convert
454 * @return a new PyDictObject containing the converted maps
455 * @warning make sure to free resources returned by this function
456 */
457PyDictObject* PyDict_FromMap(map* t){
458  PyObject* res=PyDict_New( );
459  map* tmp=t;
460  int hasSize=0;
461  map* isArray=getMap(tmp,"isArray");
462  map* size=getMap(tmp,"size");
463  map* useFile=getMap(tmp,"use_file");
464  map* cacheFile=getMap(tmp,"cache_file");
465  map* tmap=getMapType(tmp);
466  while(tmp!=NULL){
467    PyObject* name=PyString_FromString(tmp->name);
468    if(strcasecmp(tmp->name,"value")==0) {
469      if(isArray!=NULL){
470        map* len=getMap(tmp,"length");
471        int cnt=atoi(len->value);
472        PyObject* value=PyList_New(cnt);
473        PyObject* mvalue=PyList_New(cnt);
474        PyObject* svalue=PyList_New(cnt);
475        PyObject* cvalue=PyList_New(cnt);
476
477        for(int i=0;i<cnt;i++){
478         
479          map* vMap=getMapArray(t,"value",i);
480          map* uMap=getMapArray(t,"use_file",i);
481          map* sMap=getMapArray(t,"size",i);
482          map* cMap=getMapArray(t,"cache_file",i);
483
484          if(vMap!=NULL){
485           
486            PyObject* lvalue;
487            PyObject* lsvalue;
488            PyObject* lcvalue;
489            if(sMap==NULL || uMap!=NULL){
490              lvalue=PyString_FromString(vMap->value);
491            }
492            else{   
493              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
494            }
495            if(sMap!=NULL){
496              lsvalue=PyString_FromString(sMap->value);
497              hasSize=1;
498            }
499            else
500              lsvalue=Py_None;
501            if(uMap!=NULL){
502              lcvalue=PyString_FromString(cMap->value);;
503            }else
504              lcvalue=Py_None;
505
506            if(PyList_SetItem(value,i,lvalue)<0){
507              fprintf(stderr,"Unable to set key value pair...");
508              return NULL;
509            } 
510            if(PyList_SetItem(svalue,i,lsvalue)<0){
511              fprintf(stderr,"Unable to set key value pair...");
512              return NULL;
513            } 
514            if(PyList_SetItem(cvalue,i,lcvalue)<0){
515              fprintf(stderr,"Unable to set key value pair...");
516              return NULL;
517            }
518          }
519         
520          PyObject* lmvalue;
521          map* mMap=getMapArray(tmp,tmap->name,i);
522          if(mMap!=NULL){
523            lmvalue=PyString_FromString(mMap->value);
524          }else
525            lmvalue=Py_None;
526         
527          if(PyList_SetItem(mvalue,i,lmvalue)<0){
528              fprintf(stderr,"Unable to set key value pair...");
529              return NULL;
530          } 
531         
532        }
533
534        if(PyDict_SetItem(res,name,value)<0){
535          fprintf(stderr,"Unable to set key value pair...");
536          return NULL;
537        }
538        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
539          fprintf(stderr,"Unable to set key value pair...");
540          return NULL;
541        }
542        if(PyDict_SetItem(res,PyString_FromString("cache_file"),cvalue)<0){
543          fprintf(stderr,"Unable to set key value pair...");
544          return NULL;
545        }
546        if(hasSize>0)
547          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
548            fprintf(stderr,"Unable to set key value pair...");
549            return NULL;
550          }
551      }
552      else if(size!=NULL && useFile==NULL){
553        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
554        if(PyDict_SetItem(res,name,value)<0){
555          Py_DECREF(value);
556          fprintf(stderr,"Unable to set key value pair...");
557          return NULL;
558        }
559        Py_DECREF(value);
560      }
561      else{
562        PyObject* value=PyString_FromString(tmp->value);
563        if(PyDict_SetItem(res,name,value)<0){
564          Py_DECREF(value);
565          fprintf(stderr,"Unable to set key value pair...");
566          return NULL;
567        }
568        Py_DECREF(value);
569      }
570    }
571    else{
572      if(PyDict_GetItem(res,name)==NULL){
573        PyObject* value=PyString_FromString(tmp->value);
574        if(PyDict_SetItem(res,name,value)<0){
575          Py_DECREF(value);
576          fprintf(stderr,"Unable to set key value pair...");
577          return NULL;
578        }
579        Py_DECREF(value);
580      }
581    }
582    Py_DECREF(name);
583    tmp=tmp->next;
584  }
585  return (PyDictObject*) res;
586}
587
588/**
589 * Convert a Python dictionary to a maps
590 *
591 * @param t the PyDictObject to convert
592 * @return a new maps containing the converted PyDictObject
593 * @warning make sure to free resources returned by this function
594 */
595maps* mapsFromPyDict(PyDictObject* t){
596  maps* res=NULL;
597  maps* cursor=NULL;
598  PyObject* list=PyDict_Keys((PyObject*)t);
599  int nb=PyList_Size(list);
600  int i;
601  PyObject* key;
602  PyObject* value;
603  for(i=0;i<nb;i++){
604#ifdef DEBUG
605    fprintf(stderr,">> parsing maps %d\n",i);
606#endif
607    key=PyList_GetItem(list,i);
608    value=PyDict_GetItem((PyObject*)t,key);
609#ifdef DEBUG
610    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
611            PyString_AsString(key),PyString_AsString(value));
612#endif
613    cursor=createMaps(PyString_AsString(key));
614    cursor->content=mapFromPyDict((PyDictObject*)value);
615    PyObject* cname=PyString_FromString("child");
616    PyObject* childs=PyDict_GetItem((PyObject*)value,cname);
617    if(childs!=NULL)
618      cursor->child=mapsFromPyDict((PyDictObject*)childs);
619    Py_DECREF(cname);
620#ifdef DEBUG
621    dumpMap(cursor->content);
622#endif
623    cursor->next=NULL;
624    if(res==NULL)
625      res=dupMaps(&cursor);
626    else
627      addMapsToMaps(&res,cursor);
628    freeMap(&cursor->content);
629    free(cursor->content);
630    free(cursor);
631#ifdef DEBUG
632    dumpMaps(res);
633    fprintf(stderr,">> parsed maps %d\n",i);
634#endif
635  }
636  Py_DECREF(list);
637  return res;
638}
639
640/**
641 * Convert a Python dictionary to a maps
642 *
643 * @param t the PyDictObject to convert
644 * @return a new maps containing the converted PyDictObject
645 * @warning make sure to free resources returned by this function
646 */
647maps* _mapsFromPyDict(PyDictObject* t){
648       
649        PyObject* list = PyDict_Keys((PyObject*)t); // new ref 
650        int nb = PyList_Size(list);     
651       
652        if (nb < 1) {
653                Py_DECREF(list);
654                return NULL;
655        }
656
657        maps* ptr = (maps*) malloc(MAPS_SIZE);
658        maps* res = ptr;       
659       
660        PyObject* key;
661        PyObject* value;
662       
663        for(int i = 0; i < nb; i++) {
664               
665                key = PyList_GetItem(list,i); // borrowed ref
666                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref
667               
668                ptr->name = zStrdup(PyString_AsString(key));
669                ptr->content = mapFromPyDict((PyDictObject*) value);
670               
671                ptr->next = i < nb - 1 ? (maps*) malloc(MAPS_SIZE) : NULL;
672                ptr = ptr->next;
673        }
674        Py_DECREF(list);
675
676        return res;
677} // mapsFromPyDict
678
679/**
680 * Convert a Python dictionary to a map
681 *
682 * @param t the PyDictObject to convert
683 * @return a new map containing the converted PyDictObject
684 * @warning make sure to free resources returned by this function
685 */
686map* mapFromPyDict(PyDictObject* t){
687  map* res=NULL;
688  PyObject* list=PyDict_Keys((PyObject*)t);
689  int nb=PyList_Size(list);
690  int i;
691  PyObject* key;
692  PyObject* value;
693  for(i=0;i<nb;i++){
694    key=PyList_GetItem(list,i);
695    value=PyDict_GetItem((PyObject*)t,key);
696#ifdef DEBUG
697    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
698            PyString_AsString(key),PyString_AsString(value));
699#endif
700    if(strncmp(PyString_AsString(key),"child",5)!=0){
701      if(strncmp(PyString_AsString(key),"value",5)==0){
702        char *buffer=NULL;
703        Py_ssize_t size;
704#if PY_MAJOR_VERSION >= 3
705        if(PyBytes_Check(value)){
706          size=PyBytes_Size(value);
707          buffer=PyBytes_AsString(value);
708        }
709        else
710          if(PyUnicode_Check(value) && PyUnicode_READY(value) == 0){
711            buffer=PyUnicode_AsUTF8AndSize(value,&size);
712          }
713          else{
714#ifdef DEBUG
715            fprintf(stderr,"Unsupported return value.");
716#endif
717            return NULL;
718          }
719#else
720        PyString_AsStringAndSize(value,&buffer,&size);
721#endif     
722        res = addToMapWithSize(res,PyString_AsString(key),buffer,size);
723      }else{
724        char* lkey=PyString_AsString(key);
725        char* lvalue=PyString_AsString(value);
726        if(res!=NULL){
727          if(PyString_Size(value)>0)
728            addToMap(res,lkey,lvalue);
729        }
730        else{
731          if(PyString_Size(value)>0)
732            res=createMap(lkey,lvalue);
733        }
734      }
735    }
736  }
737  Py_DECREF(list);
738  return res;
739}
740
741/**
742 * Convert a Python dictionary to a map
743 *
744 * @param t the PyDictObject to convert
745 * @return a new map containing the converted PyDictObject
746 * @warning make sure to free resources returned by this function
747 */
748map* _mapFromPyDict(PyDictObject* t) {
749       
750        PyObject* list = PyDict_Keys((PyObject*) t); // new ref
751        int nb = PyList_Size(list);
752       
753        if (nb < 1) {
754                Py_DECREF(list);
755                return NULL;
756        }       
757       
758        map* ptr = (map*) malloc(MAP_SIZE);
759        map* res = ptr;
760       
761        PyObject* key;
762        PyObject* value;
763        char *buffer = NULL;
764        Py_ssize_t size;
765        for(int i = 0; i < nb; i++) {
766               
767                key = PyList_GetItem(list, i); // borrowed ref
768                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref             
769                               
770                ptr->name = zStrdup(PyString_AsString(key));           
771                map* msize = NULL;
772               
773        #if PY_MAJOR_VERSION >= 3
774                if (PyBytes_Check(value)) {
775                // value is byte array
776                        size = PyBytes_Size(value);                             
777                        buffer = PyBytes_AsString(value); // pointer to internal buffer
778                        char sz[32];
779                        sprintf(sz, "%d", (int) size); 
780                        msize = createMap("size", sz);                 
781                }
782                else if (PyUnicode_Check(value) && PyUnicode_READY(value) == 0) {
783                // value is string object               
784                        buffer = PyUnicode_AsUTF8AndSize(value, &size);
785                        size++;
786                }
787                else {
788                        printf("Type not recognized\n");
789                        // error handling
790                        // ...
791                }
792        #else   
793                PyString_AsStringAndSize(value, &buffer, &size);
794                size++;
795                // to do: handle byte arrays
796        #endif
797               
798                ptr->value = (char*) malloc(size); // check for NULL pointer
799                memmove(ptr->value, buffer, size);
800                       
801                if (msize != NULL) {
802                        ptr->next = msize;
803                        ptr = ptr->next;
804                }                                               
805               
806                ptr->next = i < nb - 1 ? (map*) malloc(MAP_SIZE) : NULL;
807                ptr = ptr->next;
808        }       
809        Py_DECREF(list);
810                       
811        return res;
812} // mapFromPyDict
813
814/**
815 * Use the ZOO-Services messages translation function from the Python
816 * environment
817 *
818 * @param self the Python object on which we can run the method
819 * @param args the Python arguments given from the Python environment
820 * @return a new Python string containing the translated value
821 * @see _ss
822 */
823PyObject*
824PythonTranslate(PyObject* self, PyObject* args)
825{
826  char *str;
827  if (!PyArg_ParseTuple(args, "s", &str)){
828#ifdef DEBUG
829    fprintf(stderr,"Incorrect arguments to update status function");
830#endif
831    return NULL;
832  }
833  return PyString_FromString(_ss(str));
834}
835
836/**
837 * Update the ongoing status of a running service from the Python environment
838 *
839 * @param self the Python object on which we can run the method
840 * @param args the Python arguments given from the Python environment
841 * @return None to the Python environment
842 * @see _updateStatus
843 */
844PyObject*
845PythonUpdateStatus(PyObject* self, PyObject* args)
846{
847  maps* conf;
848  PyObject* confdict;
849  int istatus;
850  char* status=NULL;
851  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
852#ifdef DEBUG
853    fprintf(stderr,"Incorrect arguments to update status function");
854#endif
855    Py_RETURN_NONE;
856  }
857  if (istatus < 0 || istatus > 100){
858     PyErr_SetString(ZooError, "Status must be a percentage.");
859     Py_RETURN_NONE;
860  }else{
861     char tmpStatus[4];
862     snprintf(tmpStatus, 4, "%i", istatus);
863     status = zStrdup(tmpStatus);
864  }
865  // create a local copy and update the lenv map
866  conf = mapsFromPyDict((PyDictObject*)confdict);
867  if(status!=NULL){
868    setMapInMaps(conf,"lenv","status",status);
869    free(status);
870  }
871  else
872    setMapInMaps(conf,"lenv","status","15");
873  _updateStatus(conf);
874  freeMaps(&conf);
875  free(conf);
876  Py_RETURN_NONE;
877}
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

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