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

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

Added some recent changes from trunk (r889), including some new utility functions and exception handling and new (conditional) definition of type bool. Added some new logic concerning Python and Mono environment and search paths. Fixed problem with Mono updateStatus function. Changed response_print.h to #include locale.h unconditionally and xlocale.h conditionally; xlocale.h is non-standard and can probably be dropped.

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