Merge branch 'collectd-5.7' into collectd-5.8
[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
32  * Py_BEGIN_ALLOW_THREADS
33  * from the other direction. If a Python thread calls a C function
34  * Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
35  * we don't intend to call any Python functions.
36  *
37  * These two macros are used whenever a C thread intends to call some Python
38  * function, usually because some registered callback was triggered.
39  * Just like Py_BEGIN_ALLOW_THREADS it opens a block so these macros have to be
40  * used in pairs. They acquire the GIL, create a new Python thread state and
41  * swap
42  * the current thread state with the new one. This means this thread is now
43  * allowed
44  * to execute Python code. */
45
46 #define CPY_LOCK_THREADS                                                       \
47   {                                                                            \
48     PyGILState_STATE gil_state;                                                \
49     gil_state = PyGILState_Ensure();
50
51 #define CPY_RETURN_FROM_THREADS                                                \
52   PyGILState_Release(gil_state);                                               \
53   return
54
55 #define CPY_RELEASE_THREADS                                                    \
56   PyGILState_Release(gil_state);                                               \
57   }
58
59 /* This macro is a shortcut for calls like
60  * x = PyObject_Repr(x);
61  * This can't be done like this example because this would leak
62  * a reference the the original x and crash in case of x == NULL.
63  * This calling syntax is less than elegant but it works, saves
64  * a lot of lines and avoids potential refcount errors. */
65
66 #define CPY_SUBSTITUTE(func, a, ...)                                           \
67   do {                                                                         \
68     if ((a) != NULL) {                                                         \
69       PyObject *__tmp = (a);                                                   \
70       (a) = func(__VA_ARGS__);                                                 \
71       Py_DECREF(__tmp);                                                        \
72     }                                                                          \
73   } while (0)
74
75 /* Python3 compatibility layer. To keep the actual code as clean as possible
76  * do a lot of defines here. */
77
78 #if PY_MAJOR_VERSION >= 3
79 #define IS_PY3K
80 #endif
81
82 #ifdef IS_PY3K
83
84 #define PyInt_FromLong PyLong_FromLong
85 #define CPY_INIT_TYPE PyVarObject_HEAD_INIT(NULL, 0)
86 #define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyBytes_Check(o))
87 #define CPY_STRCAT_AND_DEL(a, b)                                               \
88   do {                                                                         \
89     CPY_STRCAT((a), (b));                                                      \
90     Py_XDECREF((b));                                                           \
91   } while (0)
92 static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
93   PyObject *ret;
94
95   if (!a || !*a)
96     return;
97
98   ret = PyUnicode_Concat(*a, b);
99   Py_DECREF(*a);
100   *a = ret;
101 }
102
103 #else
104
105 #define CPY_INIT_TYPE PyObject_HEAD_INIT(NULL) 0,
106 #define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyString_Check(o))
107 #define CPY_STRCAT_AND_DEL PyString_ConcatAndDel
108 #define CPY_STRCAT PyString_Concat
109
110 #endif
111
112 static inline const char *cpy_unicode_or_bytes_to_string(PyObject **o) {
113   if (PyUnicode_Check(*o)) {
114     PyObject *tmp;
115     tmp = PyUnicode_AsEncodedString(*o, NULL, NULL); /* New reference. */
116     if (tmp == NULL)
117       return NULL;
118     Py_DECREF(*o);
119     *o = tmp;
120   }
121 #ifdef IS_PY3K
122   return PyBytes_AsString(*o);
123 #else
124   return PyString_AsString(*o);
125 #endif
126 }
127
128 static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
129 #ifdef IS_PY3K
130   /* Python3 preferrs unicode */
131   PyObject *ret;
132   ret = PyUnicode_Decode(buf, strlen(buf), NULL, NULL);
133   if (ret != NULL)
134     return ret;
135   PyErr_Clear();
136   return PyBytes_FromString(buf);
137 #else
138   return PyString_FromString(buf);
139 #endif
140 }
141
142 void cpy_log_exception(const char *context);
143
144 /* Python object declarations. */
145
146 typedef struct {
147   // clang-format off
148   PyObject_HEAD         /* No semicolon! */
149   PyObject *parent;     /* Config */
150   PyObject *key;        /* String */
151   PyObject *values;     /* Sequence */
152   PyObject *children;   /* Sequence */
153   // clang-format on
154 } Config;
155 extern PyTypeObject ConfigType;
156
157 typedef struct {
158   // clang-format off
159   PyObject_HEAD /* No semicolon! */
160   double time;
161   // clang-format on
162   char host[DATA_MAX_NAME_LEN];
163   char plugin[DATA_MAX_NAME_LEN];
164   char plugin_instance[DATA_MAX_NAME_LEN];
165   char type[DATA_MAX_NAME_LEN];
166   char type_instance[DATA_MAX_NAME_LEN];
167 } PluginData;
168 extern PyTypeObject PluginDataType;
169 #define PluginData_New()                                                       \
170   PyObject_CallFunctionObjArgs((PyObject *)&PluginDataType, (void *)0)
171
172 typedef struct {
173   PluginData data;
174   PyObject *values; /* Sequence */
175   PyObject *meta;   /* dict */
176   double interval;
177 } Values;
178 extern PyTypeObject ValuesType;
179 #define Values_New()                                                           \
180   PyObject_CallFunctionObjArgs((PyObject *)&ValuesType, (void *)0)
181
182 typedef struct {
183   PluginData data;
184   PyObject *meta;   /* dict */
185   int severity;
186   char message[NOTIF_MAX_MSG_LEN];
187 } Notification;
188 extern PyTypeObject NotificationType;
189 #define Notification_New()                                                     \
190   PyObject_CallFunctionObjArgs((PyObject *)&NotificationType, (void *)0)
191
192 typedef PyLongObject Signed;
193 extern PyTypeObject SignedType;
194
195 typedef PyLongObject Unsigned;
196 extern PyTypeObject UnsignedType;