Merge branch 'collectd-5.5'
[collectd.git] / src / cpython.h
1 /**
2  * collectd - src/cpython.h
3  * Copyright (C) 2009  Sven Trenkel
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sven Trenkel <collectd at semidefinite.de>
25  **/
26
27 /* Some python versions don't include this by default. */
28
29 #include <longintrepr.h>
30
31 /* These two macros are basically Py_BEGIN_ALLOW_THREADS and Py_BEGIN_ALLOW_THREADS
32  * from the other direction. If a Python thread calls a C function
33  * Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
34  * we don't intend to call any Python functions.
35  *
36  * These two macros are used whenever a C thread intends to call some Python
37  * function, usually because some registered callback was triggered.
38  * Just like Py_BEGIN_ALLOW_THREADS it opens a block so these macros have to be
39  * used in pairs. They acquire the GIL, create a new Python thread state and swap
40  * the current thread state with the new one. This means this thread is now allowed
41  * to execute Python code. */
42
43 #define CPY_LOCK_THREADS {\
44         PyGILState_STATE gil_state;\
45         gil_state = PyGILState_Ensure();
46
47 #define CPY_RETURN_FROM_THREADS \
48         PyGILState_Release(gil_state);\
49         return
50
51 #define CPY_RELEASE_THREADS \
52         PyGILState_Release(gil_state);\
53 }
54
55 /* This macro is a shortcut for calls like
56  * x = PyObject_Repr(x);
57  * This can't be done like this example because this would leak
58  * a reference the the original x and crash in case of x == NULL.
59  * This calling syntax is less than elegant but it works, saves
60  * a lot of lines and avoids potential refcount errors. */
61
62 #define CPY_SUBSTITUTE(func, a, ...) do {\
63         if ((a) != NULL) {\
64                 PyObject *__tmp = (a);\
65                 (a) = func(__VA_ARGS__);\
66                 Py_DECREF(__tmp);\
67         }\
68 } while(0)
69
70 /* Python3 compatibility layer. To keep the actual code as clean as possible
71  * do a lot of defines here. */
72
73 #if PY_MAJOR_VERSION >= 3
74 #define IS_PY3K
75 #endif
76
77 #ifdef IS_PY3K
78
79 #define PyInt_FromLong PyLong_FromLong
80 #define CPY_INIT_TYPE         PyVarObject_HEAD_INIT(NULL, 0)
81 #define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyBytes_Check(o))
82 #define CPY_STRCAT_AND_DEL(a, b) do {\
83         CPY_STRCAT((a), (b));\
84         Py_XDECREF((b));\
85 } while (0)
86 static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
87         PyObject *ret;
88
89         if (!a || !*a)
90                 return;
91
92         ret = PyUnicode_Concat(*a, b);
93         Py_DECREF(*a);
94         *a = ret;
95 }
96
97 #else
98
99 #define CPY_INIT_TYPE         PyObject_HEAD_INIT(NULL) 0,
100 #define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyString_Check(o))
101 #define CPY_STRCAT_AND_DEL PyString_ConcatAndDel
102 #define CPY_STRCAT PyString_Concat
103
104 #endif
105
106 static inline const char *cpy_unicode_or_bytes_to_string(PyObject **o) {
107         if (PyUnicode_Check(*o)) {
108                 PyObject *tmp;
109                 tmp = PyUnicode_AsEncodedString(*o, NULL, NULL); /* New reference. */
110                 if (tmp == NULL)
111                         return NULL;
112                 Py_DECREF(*o);
113                 *o = tmp;
114         }
115 #ifdef IS_PY3K
116         return PyBytes_AsString(*o);
117 #else
118         return PyString_AsString(*o);
119 #endif
120 }
121
122 static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
123 #ifdef IS_PY3K
124 /* Python3 preferrs unicode */
125         PyObject *ret;
126         ret = PyUnicode_Decode(buf, strlen(buf), NULL, NULL);
127         if (ret != NULL)
128                 return ret;
129         PyErr_Clear();
130         return PyBytes_FromString(buf);
131 #else
132         return PyString_FromString(buf);
133 #endif
134 }
135
136 void cpy_log_exception(const char *context);
137
138 /* Python object declarations. */
139
140 typedef struct {
141         PyObject_HEAD        /* No semicolon! */
142         PyObject *parent;    /* Config */
143         PyObject *key;       /* String */
144         PyObject *values;    /* Sequence */
145         PyObject *children;  /* Sequence */
146 } Config;
147 extern PyTypeObject ConfigType;
148
149 typedef struct {
150         PyObject_HEAD        /* No semicolon! */
151         double time;
152         char host[DATA_MAX_NAME_LEN];
153         char plugin[DATA_MAX_NAME_LEN];
154         char plugin_instance[DATA_MAX_NAME_LEN];
155         char type[DATA_MAX_NAME_LEN];
156         char type_instance[DATA_MAX_NAME_LEN];
157 } PluginData;
158 extern PyTypeObject PluginDataType;
159 #define PluginData_New() PyObject_CallFunctionObjArgs((PyObject *) &PluginDataType, (void *) 0)
160
161 typedef struct {
162         PluginData data;
163         PyObject *values;    /* Sequence */
164         PyObject *meta;      /* dict */
165         double interval;
166 } Values;
167 extern PyTypeObject ValuesType;
168 #define Values_New() PyObject_CallFunctionObjArgs((PyObject *) &ValuesType, (void *) 0)
169
170 typedef struct {
171         PluginData data;
172         int severity;
173         char message[NOTIF_MAX_MSG_LEN];
174 } Notification;
175 extern PyTypeObject NotificationType;
176 #define Notification_New() PyObject_CallFunctionObjArgs((PyObject *) &NotificationType, (void *) 0)
177
178 typedef PyLongObject Signed;
179 extern PyTypeObject SignedType;
180
181 typedef PyLongObject Unsigned;
182 extern PyTypeObject UnsignedType;
183