source: branches/PublicaMundi_David-devel/zoo-project/zoo-kernel/service_internal_python.c @ 544

Last change on this file since 544 was 531, checked in by david, 10 years ago
  • remove metapath parameter for python and js support
  • use conf in memory for C,python and js services
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 19.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{
29  PyObject *error;
30};
31
32#if PY_MAJOR_VERSION >= 3
33#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
34#define PyInt_FromLong PyLong_FromLong
35#define PyInt_AsLong PyLong_AsLong
36#define PyString_FromString PyUnicode_FromString
37#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
38#define PyString_Check PyUnicode_Check
39#define PyString_AsString _PyUnicode_AsString
40#define PyString_Size PyUnicode_GetSize
41#else
42#define GETSTATE(m) (&_state)
43static struct module_state _state;
44#endif
45
46static PyObject *ZooError;
47
48PyMethodDef zooMethods[] = {
49  {"_", PythonTranslate, METH_VARARGS,
50   "Translate a string using the zoo-services textdomain."},
51  {"update_status", PythonUpdateStatus, METH_VARARGS,
52   "Update status percentage of a running process."},
53  {NULL, NULL, 0, NULL}         /* tempt not the blade, all fear the sentinel */
54};
55
56#if PY_MAJOR_VERSION >= 3
57
58static int
59myextension_traverse (PyObject * m, visitproc visit, void *arg)
60{
61  Py_VISIT (GETSTATE (m)->error);
62  return 0;
63}
64
65static int
66myextension_clear (PyObject * m)
67{
68  Py_CLEAR (GETSTATE (m)->error);
69  return 0;
70}
71
72static struct PyModuleDef moduledef = {
73  PyModuleDef_HEAD_INIT,
74  "zoo",
75  NULL,
76  sizeof (struct module_state),
77  zooMethods,
78  NULL,
79  myextension_traverse,
80  myextension_clear,
81  NULL
82};
83#endif
84
85PyMODINIT_FUNC
86init_zoo ()
87{
88  PyObject *tmp, *d;
89  PyObject *module =
90#if PY_MAJOR_VERSION >= 3
91    PyModule_Create (&moduledef);
92#else
93    Py_InitModule ("zoo", zooMethods);
94#endif
95  if (module == NULL)
96    {
97#if PY_MAJOR_VERSION >= 3
98      return NULL;
99#else
100      return;
101#endif
102    }
103
104  struct module_state *st = GETSTATE (module);
105
106  d = PyModule_GetDict (module);
107  tmp = PyInt_FromLong (3);
108  PyDict_SetItemString (d, "SERVICE_SUCCEEDED", tmp);
109  Py_DECREF (tmp);
110
111  tmp = PyInt_FromLong (4);
112  PyDict_SetItemString (d, "SERVICE_FAILED", tmp);
113  Py_DECREF (tmp);
114
115  tmp = PyString_FromString (ZOO_VERSION);
116  PyDict_SetItemString (d, "VERSION", tmp);
117  Py_DECREF (tmp);
118
119  ZooError = PyErr_NewException ((char *) "zoo.error", NULL, NULL);
120  Py_INCREF (ZooError);
121  PyModule_AddObject (module, "error", ZooError);
122#if PY_MAJOR_VERSION >= 3
123  return module;
124#endif
125}
126
127int
128zoo_python_support (maps ** main_conf, map * request, service * s,
129                    maps ** real_inputs, maps ** real_outputs)
130{
131  char *pythonpath;
132  char *python_path;
133  maps *m = *main_conf;
134  maps *inputs = *real_inputs;
135  maps *outputs = *real_outputs;
136  map *tmp0 = getMapFromMaps (*main_conf, "lenv", "cwd");
137  char *python_package =
138    (char *) malloc ((strlen (s->identifier) - strlen (s->name) + 1) *
139                     sizeof (char));
140  python_package[0] = '\0';
141  python_package =
142    strncat (python_package, s->identifier,
143             strlen (s->identifier) - strlen (s->name) - 1);
144  python_package[strlen (s->identifier) - strlen (s->name)] = '\0';
145  char *ntmp = tmp0->value;
146  map *tmp = NULL;
147  int hasToClean = 0;
148  tmp = getMapFromMaps (*main_conf, "env", "PYTHONPATH");
149#ifdef DEBUG
150  fprintf (stderr, "PYTHON SUPPORT \n");
151#endif
152  if (tmp != NULL)
153    {
154#ifdef DEBUG
155      fprintf (stderr, "PYTHON SUPPORT (%i)\n", strlen (tmp->value));
156#endif
157      python_path = (char *) malloc ((strlen (tmp->value)) * sizeof (char));
158      sprintf (python_path, "%s", tmp->value);
159      hasToClean = 1;
160    }
161  else
162    {
163      python_path = (char *) ".";
164    }
165  pythonpath =
166    (char *) malloc ((2 + strlen (python_path) + strlen (ntmp)) *
167                     sizeof (char));
168#ifdef WIN32
169  sprintf (pythonpath, "%s;%s", ntmp, python_path);
170#else
171  sprintf (pythonpath, "%s:%s", ntmp, python_path);
172#endif
173
174#ifdef DEBUG
175  fprintf (stderr, "PYTHONPATH=%s\n", pythonpath);
176#endif
177#ifndef WIN32
178  setenv ("PYTHONPATH", pythonpath, 1);
179#else
180  SetEnvironmentVariable ("PYTHONPATH", pythonpath);
181  char *toto = (char *) malloc ((strlen (pythonpath) + 12) * sizeof (char));
182  sprintf (toto, "PYTHONPATH=%s", pythonpath);
183  putenv (toto);
184  free (toto);
185#endif
186  if (hasToClean > 0)
187    free (python_path);
188  free (pythonpath);
189
190  PyThreadState *mainstate;
191#if PY_MAJOR_VERSION >= 3
192  PyImport_AppendInittab ("zoo", init_zoo);
193#else
194  PyEval_InitThreads ();
195#endif
196  Py_Initialize ();
197#if PY_MAJOR_VERSION >= 3
198  PyEval_InitThreads ();
199  PyImport_ImportModule ("zoo");
200#else
201  init_zoo ();
202#endif
203  mainstate = PyThreadState_Swap (NULL);
204  PyEval_ReleaseLock ();
205  PyGILState_STATE gstate;
206  gstate = PyGILState_Ensure ();
207  PyObject *pName, *pModule, *pFunc;
208  tmp = getMap (s->content, "serviceProvider");
209  if (tmp != NULL)
210    {
211      char *module_name =
212        (char *) malloc (strlen (python_package) + strlen (tmp->value) + 2);
213      sprintf (module_name, "%s.%s", python_package, tmp->value);
214      pName = PyString_FromString (module_name);
215      free (python_package);
216      free (module_name);
217      fprintf (stderr, "%s %d", tmp->value, __LINE__);
218    }
219  else
220    {
221      map *err = createMap ("text",
222                            "Unable to parse serviceProvider please check your zcfg file.");
223      addToMap (err, "code", "NoApplicableCode");
224      printExceptionReportResponse (m, err);
225      exit (-1);
226    }
227  pModule = PyImport_Import (pName);
228  int res = SERVICE_FAILED;
229  if (pModule != NULL)
230    {
231      pFunc = PyObject_GetAttrString (pModule, s->name);
232      if (pFunc && PyCallable_Check (pFunc))
233        {
234          PyObject *pValue;
235          PyDictObject *arg1 = PyDict_FromMaps (m);
236          PyDictObject *arg2 = PyDict_FromMaps (inputs);
237          PyDictObject *arg3 = PyDict_FromMaps (outputs);
238          PyObject *pArgs = PyTuple_New (3);
239          if (!pArgs)
240            return -1;
241          PyTuple_SetItem (pArgs, 0, (PyObject *) arg1);
242          PyTuple_SetItem (pArgs, 1, (PyObject *) arg2);
243          PyTuple_SetItem (pArgs, 2, (PyObject *) arg3);
244          pValue = PyObject_CallObject (pFunc, pArgs);
245          if (pValue != NULL)
246            {
247              res = PyInt_AsLong (pValue);
248              freeMaps (real_outputs);
249              free (*real_outputs);
250              freeMaps (main_conf);
251              free (*main_conf);
252              *main_conf = mapsFromPyDict (arg1);
253              *real_outputs = mapsFromPyDict (arg3);
254#ifdef DEBUG
255              fprintf (stderr, "Result of call: %i\n", PyInt_AsLong (pValue));
256              dumpMaps (inputs);
257              dumpMaps (*real_outputs);
258#endif
259            }
260          else
261            {
262              PyObject *ptype, *pvalue, *ptraceback;
263              PyErr_Fetch (&ptype, &pvalue, &ptraceback);
264              PyObject *trace = PyObject_Str (pvalue);
265              char pbt[10240];
266              if (PyString_Check (trace))
267                sprintf (pbt, "TRACE : %s", PyString_AsString (trace));
268              else
269                fprintf (stderr, "EMPTY TRACE ?");
270              trace = NULL;
271              trace = PyObject_Str (ptype);
272              if (PyString_Check (trace))
273                {
274                  char *tpbt = zStrdup (pbt);
275                  sprintf (pbt, "%s\n%s", tpbt, PyString_AsString (trace));
276                  free (tpbt);
277                }
278              else
279                fprintf (stderr, "EMPTY TRACE ?");
280
281              char *tpbt = zStrdup (pbt);
282              pName = PyString_FromString ("traceback");
283              pModule = PyImport_Import (pName);
284              pArgs = PyTuple_New (1);
285              PyTuple_SetItem (pArgs, 0, ptraceback);
286              pFunc = PyObject_GetAttrString (pModule, "format_tb");
287              pValue = PyObject_CallObject (pFunc, pArgs);
288              trace = NULL;
289              trace = PyObject_Str (pValue);
290              if (PyString_Check (trace))
291                sprintf (pbt,
292                         "%s\nUnable to run your python process properly. Please check the following messages : %s",
293                         tpbt, PyString_AsString (trace));
294              else
295                sprintf (pbt,
296                         "%s \n Unable to run your python process properly. Unable to provide any futher informations.",
297                         tpbt);
298              free (tpbt);
299              map *err = createMap ("text", pbt);
300              addToMap (err, "code", "NoApplicableCode");
301              printExceptionReportResponse (m, err);
302              res = -1;
303            }
304        }
305      else
306        {
307          char tmpS[1024];
308          sprintf (tmpS, "Cannot find the %s function in the %s file.\n",
309                   s->name, tmp->value);
310          map *tmps = createMap ("text", tmpS);
311          printExceptionReportResponse (m, tmps);
312          res = -1;
313        }
314    }
315  else
316    {
317      char tmpS[1024];
318      sprintf (tmpS, "Python module %s cannot be loaded.\n", tmp->value);
319      map *tmps = createMap ("text", tmpS);
320      printExceptionReportResponse (m, tmps);
321      if (PyErr_Occurred ())
322        PyErr_Print ();
323      PyErr_Clear ();
324      res = -1;
325    }
326#if PY_MAJOR_VERSION < 3
327  PyGILState_Release (gstate);
328  PyEval_AcquireLock ();
329#endif
330  PyThreadState_Swap (mainstate);
331  Py_Finalize ();
332  return res;
333}
334
335PyDictObject *
336PyDict_FromMaps (maps * t)
337{
338  PyObject *res = PyDict_New ();
339  maps *tmp = t;
340  while (tmp != NULL)
341    {
342      PyObject *value = (PyObject *) PyDict_FromMap (tmp->content);
343      PyObject *name = PyString_FromString (tmp->name);
344      if (PyDict_SetItem (res, name, value) < 0)
345        {
346          fprintf (stderr, "Unable to set map value ...");
347          return NULL;
348        }
349      Py_DECREF (name);
350      tmp = tmp->next;
351    }
352  return (PyDictObject *) res;
353}
354
355PyDictObject *
356PyDict_FromMap (map * t)
357{
358  PyObject *res = PyDict_New ();
359  map *tmp = t;
360  int hasSize = 0;
361  map *isArray = getMap (tmp, "isArray");
362  map *size = getMap (tmp, "size");
363  map *tmap = getMapType (tmp);
364  while (tmp != NULL)
365    {
366      PyObject *name = PyString_FromString (tmp->name);
367      if (strcasecmp (tmp->name, "value") == 0)
368        {
369          if (isArray != NULL)
370            {
371              map *len = getMap (tmp, "length");
372              int cnt = atoi (len->value);
373              PyObject *value = PyList_New (cnt);
374              PyObject *mvalue = PyList_New (cnt);
375              PyObject *svalue = PyList_New (cnt);
376
377              for (int i = 0; i < cnt; i++)
378                {
379
380                  map *vMap = getMapArray (tmp, "value", i);
381                  map *sMap = getMapArray (tmp, "size", i);
382
383                  if (vMap != NULL)
384                    {
385
386                      PyObject *lvalue;
387                      PyObject *lsvalue;
388                      if (sMap == NULL)
389                        {
390                          lvalue = PyString_FromString (vMap->value);
391                          lsvalue = Py_None;
392                        }
393                      else
394                        {
395                          lvalue =
396                            PyString_FromStringAndSize (vMap->value,
397                                                        atoi (sMap->value));
398                          lsvalue = PyString_FromString (sMap->value);
399                          hasSize = 1;
400                        }
401
402                      if (PyList_SetItem (value, i, lvalue) < 0)
403                        {
404                          fprintf (stderr, "Unable to set key value pair...");
405                          return NULL;
406                        }
407                      if (PyList_SetItem (svalue, i, lsvalue) < 0)
408                        {
409                          fprintf (stderr, "Unable to set key value pair...");
410                          return NULL;
411                        }
412                    }
413
414                  map *mMap = getMapArray (tmp, tmap->name, i);
415                  PyObject *lmvalue;
416                  if (mMap != NULL)
417                    {
418                      lmvalue = PyString_FromString (mMap->value);
419                    }
420                  else
421                    lmvalue = Py_None;
422
423                  if (PyList_SetItem (mvalue, i, lmvalue) < 0)
424                    {
425                      fprintf (stderr, "Unable to set key value pair...");
426                      return NULL;
427                    }
428
429                }
430
431              if (PyDict_SetItem (res, name, value) < 0)
432                {
433                  fprintf (stderr, "Unable to set key value pair...");
434                  return NULL;
435                }
436              if (PyDict_SetItem
437                  (res, PyString_FromString (tmap->name), mvalue) < 0)
438                {
439                  fprintf (stderr, "Unable to set key value pair...");
440                  return NULL;
441                }
442              if (hasSize > 0)
443                if (PyDict_SetItem (res, PyString_FromString ("size"), svalue)
444                    < 0)
445                  {
446                    fprintf (stderr, "Unable to set key value pair...");
447                    return NULL;
448                  }
449            }
450          else if (size != NULL)
451            {
452              PyObject *value =
453                PyString_FromStringAndSize (tmp->value, atoi (size->value));
454              if (PyDict_SetItem (res, name, value) < 0)
455                {
456                  Py_DECREF (value);
457                  fprintf (stderr, "Unable to set key value pair...");
458                  return NULL;
459                }
460              Py_DECREF (value);
461            }
462          else
463            {
464              PyObject *value = PyString_FromString (tmp->value);
465              if (PyDict_SetItem (res, name, value) < 0)
466                {
467                  Py_DECREF (value);
468                  fprintf (stderr, "Unable to set key value pair...");
469                  return NULL;
470                }
471              Py_DECREF (value);
472            }
473        }
474      else
475        {
476          if (PyDict_GetItem (res, name) == NULL)
477            {
478              PyObject *value = PyString_FromString (tmp->value);
479              if (PyDict_SetItem (res, name, value) < 0)
480                {
481                  Py_DECREF (value);
482                  fprintf (stderr, "Unable to set key value pair...");
483                  return NULL;
484                }
485              Py_DECREF (value);
486            }
487        }
488      Py_DECREF (name);
489      tmp = tmp->next;
490    }
491  return (PyDictObject *) res;
492}
493
494maps *
495mapsFromPyDict (PyDictObject * t)
496{
497  maps *res = NULL;
498  maps *cursor = res;
499  PyObject *list = PyDict_Keys ((PyObject *) t);
500  int nb = PyList_Size (list);
501  int i;
502  for (i = 0; i < nb; i++)
503    {
504#ifdef DEBUG
505      fprintf (stderr, ">> parsing maps %d\n", i);
506#endif
507      PyObject *key = PyList_GetItem (list, i);
508      PyObject *value = PyDict_GetItem ((PyObject *) t, key);
509#ifdef DEBUG
510      fprintf (stderr, ">> DEBUG VALUES : %s => %s\n",
511               PyString_AsString (key), PyString_AsString (value));
512#endif
513      cursor = (maps *) malloc (MAPS_SIZE);
514      cursor->name = PyString_AsString (key);
515      cursor->content = mapFromPyDict ((PyDictObject *) value);
516#ifdef DEBUG
517      dumpMap (cursor->content);
518#endif
519      cursor->next = NULL;
520      if (res == NULL)
521        res = dupMaps (&cursor);
522      else
523        addMapsToMaps (&res, cursor);
524      freeMap (&cursor->content);
525      free (cursor->content);
526      free (cursor);
527      Py_DECREF (key);
528#ifdef DEBUG
529      dumpMaps (res);
530      fprintf (stderr, ">> parsed maps %d\n", i);
531#endif
532    }
533  Py_DECREF (list);
534  return res;
535}
536
537map *
538mapFromPyDict (PyDictObject * t)
539{
540  map *res = NULL;
541  PyObject *list = PyDict_Keys ((PyObject *) t);
542  int nb = PyList_Size (list);
543  int i;
544  for (i = 0; i < nb; i++)
545    {
546      PyObject *key = PyList_GetItem (list, i);
547      PyObject *value = PyDict_GetItem ((PyObject *) t, key);
548#ifdef DEBUG
549      fprintf (stderr, ">> DEBUG VALUES : %s => %s\n",
550               PyString_AsString (key), PyString_AsString (value));
551#endif
552
553      if (strcmp (PyString_AsString (key), "value") == 0)
554        {
555          char *buffer = NULL;
556          Py_ssize_t size;
557#if PY_MAJOR_VERSION >= 3
558          buffer = _PyUnicode_AsStringAndSize (value, &size);
559#else
560          PyString_AsStringAndSize (value, &buffer, &size);
561#endif
562          if (res != NULL)
563            {
564              addToMap (res, PyString_AsString (key), "");
565            }
566          else
567            {
568              res = createMap (PyString_AsString (key), "");
569            }
570          map *tmpR = getMap (res, "value");
571          free (tmpR->value);
572          tmpR->value = (char *) malloc ((size + 1) * sizeof (char));
573          memmove (tmpR->value, buffer, size * sizeof (char));
574          tmpR->value[size] = 0;
575          char sin[1024];
576          sprintf (sin, "%ld", size);
577          addToMap (res, "size", sin);
578        }
579      else
580        {
581          char *lkey = PyString_AsString (key);
582          char *lvalue = PyString_AsString (value);
583          if (res != NULL)
584            {
585              if (PyString_Size (value) > 0)
586                addToMap (res, lkey, lvalue);
587            }
588          else
589            {
590              if (PyString_Size (value) > 0)
591                res = createMap (lkey, lvalue);
592            }
593        }
594    }
595  Py_DECREF (list);
596  return res;
597}
598
599PyObject *
600PythonTranslate (PyObject * self, PyObject * args)
601{
602  char *str;
603  if (!PyArg_ParseTuple (args, "s", &str))
604    {
605#ifdef DEBUG
606      fprintf (stderr, "Incorrect arguments to update status function");
607#endif
608      return NULL;
609    }
610  return PyString_FromString (_ss (str));
611}
612
613PyObject *
614PythonUpdateStatus (PyObject * self, PyObject * args)
615{
616  maps *conf;
617  PyObject *confdict;
618  int istatus;
619  char *status;
620  if (!PyArg_ParseTuple (args, "O!i", &PyDict_Type, &confdict, &istatus))
621    {
622#ifdef DEBUG
623      fprintf (stderr, "Incorrect arguments to update status function");
624#endif
625      return NULL;
626    }
627  if (istatus < 0 || istatus > 100)
628    {
629      PyErr_SetString (ZooError, "Status must be a percentage.");
630      return NULL;
631    }
632  else
633    {
634      char tmpStatus[4];
635      snprintf (tmpStatus, 4, "%i", istatus);
636      status = zStrdup (tmpStatus);
637    }
638  /* now update the map */
639  {
640    PyObject *lenv = PyMapping_GetItemString (confdict, (char *) "lenv");
641    if (lenv && PyMapping_Check (lenv))
642      {
643        PyObject *valobj = PyString_FromString (status);
644        PyMapping_SetItemString (lenv, (char *) "status", valobj);
645        Py_DECREF (valobj);
646      }
647    Py_DECREF (lenv);
648  }
649  conf = mapsFromPyDict ((PyDictObject *) confdict);
650  if (getMapFromMaps (conf, "lenv", "status") != NULL)
651    {
652      if (status != NULL)
653        {
654          setMapInMaps (conf, "lenv", "status", status);
655          free (status);
656        }
657      else
658        setMapInMaps (conf, "lenv", "status", "15");
659      _updateStatus (conf);
660    }
661  freeMaps (&conf);
662  free (conf);
663  Py_RETURN_NONE;
664}
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