lib: rename INVALID_OBJECT status to UNKNOWN_OBJECT
[babeltrace.git] / src / bindings / python / bt2 / bt2 / native_bt_component_class.i
CommitLineData
6945df9a
SM
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
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
d24d5663 25%include <babeltrace2/graph/component-class.h>
d6bb425c
SM
26%include <babeltrace2/graph/component-class-const.h>
27%include <babeltrace2/graph/component-class-source-const.h>
28%include <babeltrace2/graph/component-class-source.h>
29%include <babeltrace2/graph/component-class-filter-const.h>
30%include <babeltrace2/graph/component-class-filter.h>
31%include <babeltrace2/graph/component-class-sink-const.h>
32%include <babeltrace2/graph/component-class-sink.h>
33%include <babeltrace2/graph/self-component-class-source.h>
34%include <babeltrace2/graph/self-component-class-filter.h>
35%include <babeltrace2/graph/self-component-class-sink.h>
6945df9a
SM
36
37%{
38/*
39 * This hash table associates a BT component class object address to a
40 * user-defined Python class (PyObject *). The keys and values are NOT
41 * owned by this hash table. The Python class objects are owned by the
42 * Python module, which should not be unloaded until it is not possible
43 * to create a user Python component anyway.
44 *
45 * This hash table is written to when a user-defined Python component
d24d5663 46 * class is created by one of the bt_bt2_component_class_*_create()
6945df9a
SM
47 * functions.
48 *
49 * This function is read from when a user calls bt_component_create()
50 * with a component class pointer created by one of the functions above.
51 * In this case, the original Python class needs to be found to
52 * instantiate it and associate the created Python component object with
53 * a BT component object instance.
54 */
55
56static GHashTable *bt_cc_ptr_to_py_cls;
57
7744859c
SM
58static
59void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
6945df9a
SM
60 PyObject *py_cls)
61{
62 if (!bt_cc_ptr_to_py_cls) {
63 /*
64 * Lazy-initializing this GHashTable because GLib
65 * might not be initialized yet and it needs to be
66 * before we call g_hash_table_new()
67 */
68 BT_LOGD_STR("Creating native component class to Python component class hash table.");
69 bt_cc_ptr_to_py_cls = g_hash_table_new(g_direct_hash, g_direct_equal);
70 BT_ASSERT(bt_cc_ptr_to_py_cls);
71 }
72
73 g_hash_table_insert(bt_cc_ptr_to_py_cls, (gpointer) bt_cc,
74 (gpointer) py_cls);
75}
76
7744859c
SM
77static
78PyObject *lookup_cc_ptr_to_py_cls(const bt_component_class *bt_cc)
6945df9a
SM
79{
80 if (!bt_cc_ptr_to_py_cls) {
81 BT_LOGW("Cannot look up Python component class because hash table is NULL: "
82 "comp-cls-addr=%p", bt_cc);
83 return NULL;
84 }
85
86 return (PyObject *) g_hash_table_lookup(bt_cc_ptr_to_py_cls,
87 (gconstpointer) bt_cc);
88}
89
90
91/*
92 * Useful Python objects.
93 */
94
95static PyObject *py_mod_bt2 = NULL;
96static PyObject *py_mod_bt2_exc_error_type = NULL;
4acc866e 97static PyObject *py_mod_bt2_exc_memory_error = NULL;
6945df9a
SM
98static PyObject *py_mod_bt2_exc_try_again_type = NULL;
99static PyObject *py_mod_bt2_exc_stop_type = NULL;
76b6c2f7 100static PyObject *py_mod_bt2_exc_unknown_object_type = NULL;
6945df9a 101
7744859c 102static
d24d5663 103void bt_bt2_cc_init_from_bt2(void)
6945df9a
SM
104{
105 /*
106 * This is called once the bt2 package is loaded.
107 *
108 * Those modules and functions are needed while the package is
109 * used. Loading them here is safe because we know the bt2
110 * package is imported, and we know that the user cannot use the
111 * code here without importing bt2 first.
112 */
113 py_mod_bt2 = PyImport_ImportModule("bt2");
114 BT_ASSERT(py_mod_bt2);
115 py_mod_bt2_exc_error_type =
694c792b 116 PyObject_GetAttrString(py_mod_bt2, "_Error");
6945df9a 117 BT_ASSERT(py_mod_bt2_exc_error_type);
4acc866e 118 py_mod_bt2_exc_memory_error =
694c792b 119 PyObject_GetAttrString(py_mod_bt2, "_MemoryError");
4acc866e 120 BT_ASSERT(py_mod_bt2_exc_memory_error);
6945df9a
SM
121 py_mod_bt2_exc_try_again_type =
122 PyObject_GetAttrString(py_mod_bt2, "TryAgain");
123 BT_ASSERT(py_mod_bt2_exc_try_again_type);
124 py_mod_bt2_exc_stop_type =
125 PyObject_GetAttrString(py_mod_bt2, "Stop");
126 BT_ASSERT(py_mod_bt2_exc_stop_type);
76b6c2f7
SM
127 py_mod_bt2_exc_unknown_object_type =
128 PyObject_GetAttrString(py_mod_bt2, "UnknownObject");
129 BT_ASSERT(py_mod_bt2_exc_unknown_object_type);
6945df9a
SM
130}
131
7744859c 132static
d24d5663 133void bt_bt2_cc_exit_handler(void)
6945df9a
SM
134{
135 /*
136 * This is an exit handler (set by the bt2 package).
137 *
138 * We only give back the references that we took in
d24d5663 139 * bt_bt2_cc_init_from_bt2() here. The global variables continue
6945df9a
SM
140 * to exist for the code of this file, but they are now borrowed
141 * references. If this code is executed, it means that somehow
142 * the modules are still loaded, so it should be safe to use
143 * them even without a strong reference.
144 *
145 * We cannot do this in the library's destructor because it
146 * gets executed once Python is already finalized.
147 */
148 Py_XDECREF(py_mod_bt2);
149 Py_XDECREF(py_mod_bt2_exc_error_type);
150 Py_XDECREF(py_mod_bt2_exc_try_again_type);
151 Py_XDECREF(py_mod_bt2_exc_stop_type);
76b6c2f7 152 Py_XDECREF(py_mod_bt2_exc_unknown_object_type);
6945df9a
SM
153}
154
155
156/* Library destructor */
157
158__attribute__((destructor))
7744859c 159static
d24d5663 160void native_comp_class_dtor(void) {
6945df9a
SM
161 /* Destroy component class association hash table */
162 if (bt_cc_ptr_to_py_cls) {
163 BT_LOGD_STR("Destroying native component class to Python component class hash table.");
164 g_hash_table_destroy(bt_cc_ptr_to_py_cls);
165 }
166}
167
ce4923b0
SM
168static
169void restore_current_thread_error_and_append_exception_chain_recursive(
170 PyObject *py_exc_value,
171 bt_self_component_class *self_component_class,
172 bt_self_component *self_component,
173 bt_self_message_iterator *self_message_iterator,
174 const char *module_name)
175{
176 PyObject *py_exc_cause_value;
177 PyObject *py_exc_type = NULL;
178 PyObject *py_exc_tb = NULL;
179 GString *gstr = NULL;
180
181 /* If this exception has a cause, handle that one first. */
182 py_exc_cause_value = PyException_GetCause(py_exc_value);
183 if (py_exc_cause_value) {
184 restore_current_thread_error_and_append_exception_chain_recursive(
185 py_exc_cause_value, self_component_class,
186 self_component, self_message_iterator, module_name);
187 }
188
189 /*
694c792b 190 * If the raised exception is a bt2._Error, restore the wrapped error.
ce4923b0
SM
191 */
192 if (PyErr_GivenExceptionMatches(py_exc_value, py_mod_bt2_exc_error_type)) {
193 PyObject *py_error_swig_ptr;
194 const bt_error *error;
195 int ret;
196
197 /*
694c792b 198 * We never raise a bt2._Error with a cause: it should be the
ce4923b0
SM
199 * end of the chain.
200 */
201 BT_ASSERT(!py_exc_cause_value);
202
203 /*
204 * We steal the error object from the exception, to move
205 * it back as the current thread's error.
206 */
207 py_error_swig_ptr = PyObject_GetAttrString(py_exc_value, "_ptr");
208 BT_ASSERT(py_error_swig_ptr);
209
210 ret = PyObject_SetAttrString(py_exc_value, "_ptr", Py_None);
211 BT_ASSERT(ret == 0);
212
213 ret = SWIG_ConvertPtr(py_error_swig_ptr, (void **) &error,
214 SWIGTYPE_p_bt_error, 0);
215 BT_ASSERT(ret == 0);
216
217 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(error);
218
219 Py_DECREF(py_error_swig_ptr);
220 }
221
222 py_exc_type = PyObject_Type(py_exc_value);
223 py_exc_tb = PyException_GetTraceback(py_exc_value);
224
225 gstr = bt_py_common_format_exception(py_exc_type, py_exc_value,
226 py_exc_tb, BT_LOG_OUTPUT_LEVEL, false);
227 if (!gstr) {
228 /* bt_py_common_format_exception has already warned. */
229 goto end;
230 }
231
232 if (self_component_class) {
233 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT_CLASS(
234 self_component_class, "%s", gstr->str);
235 } else if (self_component) {
236 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
237 self_component, "%s", gstr->str);
238 } else if (self_message_iterator) {
239 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
240 self_message_iterator, "%s", gstr->str);
241 } else {
242 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(
243 module_name, "%s", gstr->str);
244 }
245
246end:
247 if (gstr) {
248 g_string_free(gstr, TRUE);
249 }
250
251 Py_XDECREF(py_exc_cause_value);
252 Py_XDECREF(py_exc_type);
253 Py_XDECREF(py_exc_tb);
254}
255
256/*
257 * If you have the following code:
258 *
259 * try:
260 * try:
261 * something_that_raises_bt2_error()
694c792b 262 * except bt2._Error as e1:
ce4923b0
SM
263 * raise ValueError from e1
264 * except ValueError as e2:
265 * raise TypeError from e2
266 *
267 * We will have the following exception chain:
268 *
694c792b 269 * TypeError -> ValueError -> bt2._Error
ce4923b0
SM
270 *
271 * Where the TypeError is the current exception (obtained from PyErr_Fetch).
272 *
694c792b 273 * The bt2._Error contains a `struct bt_error *` that used to be the current
ce4923b0
SM
274 * thread's error, at the moment the exception was raised.
275 *
694c792b 276 * This function gets to the bt2._Error and restores the wrapped
ce4923b0
SM
277 * `struct bt_error *` as the current thread's error.
278 *
279 * Then, for each exception in the chain, starting with the oldest one, it adds
280 * an error cause to the current thread's error.
281 */
282static
283void restore_bt_error_and_append_current_exception_chain(
284 bt_self_component_class *self_component_class,
285 bt_self_component *self_component,
286 bt_self_message_iterator *self_message_iterator,
287 const char *module_name)
288{
289 BT_ASSERT(PyErr_Occurred());
290
291 /* Used to access and restore the current exception. */
292 PyObject *py_exc_type;
293 PyObject *py_exc_value;
294 PyObject *py_exc_tb;
295
296 /* Fetch and normalize the Python exception. */
297 PyErr_Fetch(&py_exc_type, &py_exc_value, &py_exc_tb);
298 PyErr_NormalizeException(&py_exc_type, &py_exc_value, &py_exc_tb);
299 BT_ASSERT(py_exc_type);
300 BT_ASSERT(py_exc_value);
301 BT_ASSERT(py_exc_tb);
302
303 /*
304 * Set the exception's traceback so it's possible to get it using
305 * PyException_GetTraceback in
306 * restore_current_thread_error_and_append_exception_chain_recursive.
307 */
308 PyException_SetTraceback(py_exc_value, py_exc_tb);
309
310 restore_current_thread_error_and_append_exception_chain_recursive(py_exc_value,
311 self_component_class, self_component, self_message_iterator,
312 module_name);
313
314 PyErr_Restore(py_exc_type, py_exc_value, py_exc_tb);
315}
316
d24d5663 317static inline
ce95fb26
SM
318void log_exception_and_maybe_append_error(int log_level,
319 bool append_error,
320 bt_self_component_class *self_component_class,
321 bt_self_component *self_component,
ce4923b0
SM
322 bt_self_message_iterator *self_message_iterator,
323 const char *module_name)
6945df9a 324{
7085eeaa 325 GString *gstr;
6945df9a 326
5084732e 327 BT_ASSERT(PyErr_Occurred());
cacd0713 328 gstr = bt_py_common_format_current_exception(BT_LOG_OUTPUT_LEVEL);
7085eeaa 329 if (!gstr) {
cacd0713 330 /* bt_py_common_format_current_exception() logs errors */
6945df9a
SM
331 goto end;
332 }
333
d24d5663 334 BT_LOG_WRITE(log_level, BT_LOG_TAG, "%s", gstr->str);
6945df9a 335
ce95fb26 336 if (append_error) {
ce4923b0
SM
337 restore_bt_error_and_append_current_exception_chain(
338 self_component_class, self_component,
339 self_message_iterator, module_name);
340
ce95fb26
SM
341 }
342
6945df9a 343end:
7085eeaa
PP
344 if (gstr) {
345 g_string_free(gstr, TRUE);
6945df9a 346 }
6945df9a
SM
347}
348
d24d5663 349static inline
ce4923b0 350void loge_exception(const char *module_name)
6945df9a 351{
ce4923b0
SM
352 log_exception_and_maybe_append_error(BT_LOG_ERROR, true, NULL, NULL,
353 NULL, module_name);
ce95fb26
SM
354}
355
356static
357void loge_exception_message_iterator(
358 bt_self_message_iterator *self_message_iterator)
359{
ce4923b0
SM
360 log_exception_and_maybe_append_error(BT_LOG_ERROR, true, NULL, NULL,
361 self_message_iterator, NULL);
6945df9a
SM
362}
363
d24d5663
PP
364static inline
365void logw_exception(void)
6945df9a 366{
ce4923b0
SM
367 log_exception_and_maybe_append_error(BT_LOG_WARNING, false, NULL, NULL,
368 NULL, NULL);
6945df9a
SM
369}
370
d24d5663 371static inline
ce95fb26
SM
372int py_exc_to_status(bt_self_component_class *self_component_class,
373 bt_self_component *self_component,
ce4923b0
SM
374 bt_self_message_iterator *self_message_iterator,
375 const char *module_name)
6945df9a 376{
d24d5663 377 int status = __BT_FUNC_STATUS_OK;
6945df9a
SM
378 PyObject *exc = PyErr_Occurred();
379
380 if (!exc) {
381 goto end;
382 }
383
384 if (PyErr_GivenExceptionMatches(exc,
d24d5663
PP
385 py_mod_bt2_exc_try_again_type)) {
386 status = __BT_FUNC_STATUS_AGAIN;
6945df9a 387 } else if (PyErr_GivenExceptionMatches(exc,
d24d5663
PP
388 py_mod_bt2_exc_stop_type)) {
389 status = __BT_FUNC_STATUS_END;
6945df9a 390 } else if (PyErr_GivenExceptionMatches(exc,
76b6c2f7
SM
391 py_mod_bt2_exc_unknown_object_type)) {
392 status = __BT_FUNC_STATUS_UNKNOWN_OBJECT;
6945df9a 393 } else {
d24d5663 394 /* Unknown exception: convert to general error */
ce95fb26
SM
395 log_exception_and_maybe_append_error(BT_LOG_WARNING, true,
396 self_component_class, self_component,
ce4923b0 397 self_message_iterator, module_name);
4acc866e
SM
398
399 if (PyErr_GivenExceptionMatches(exc,
400 py_mod_bt2_exc_memory_error)) {
401 status = __BT_FUNC_STATUS_MEMORY_ERROR;
402 } else {
403 status = __BT_FUNC_STATUS_ERROR;
404 }
6945df9a
SM
405 }
406
407end:
408 PyErr_Clear();
409 return status;
410}
411
ce95fb26
SM
412static
413int py_exc_to_status_component_class(bt_self_component_class *self_component_class)
414{
ce4923b0 415 return py_exc_to_status(self_component_class, NULL, NULL, NULL);
ce95fb26
SM
416}
417
418static
419int py_exc_to_status_component(bt_self_component *self_component)
420{
ce4923b0 421 return py_exc_to_status(NULL, self_component, NULL, NULL);
ce95fb26
SM
422}
423
424static
425int py_exc_to_status_message_iterator(
426 bt_self_message_iterator *self_message_iterator)
427{
ce4923b0 428 return py_exc_to_status(NULL, NULL, self_message_iterator, NULL);
ce95fb26
SM
429}
430
d24d5663
PP
431/* Component class proxy methods (delegate to the attached Python object) */
432
7744859c 433static
d24d5663 434bt_component_class_init_method_status component_class_init(
6945df9a
SM
435 bt_self_component *self_component,
436 void *self_component_v,
437 swig_type_info *self_comp_cls_type_swig_type,
438 const bt_value *params,
439 void *init_method_data)
440{
441 const bt_component *component = bt_self_component_as_component(self_component);
442 const bt_component_class *component_class = bt_component_borrow_class_const(component);
d24d5663 443 bt_component_class_init_method_status status = __BT_FUNC_STATUS_OK;
6945df9a
SM
444 PyObject *py_cls = NULL;
445 PyObject *py_comp = NULL;
446 PyObject *py_params_ptr = NULL;
447 PyObject *py_comp_ptr = NULL;
448
449 (void) init_method_data;
450
451 BT_ASSERT(self_component);
452 BT_ASSERT(self_component_v);
453 BT_ASSERT(self_comp_cls_type_swig_type);
454
455 /*
456 * Get the user-defined Python class which created this
457 * component's class in the first place (borrowed
458 * reference).
459 */
460 py_cls = lookup_cc_ptr_to_py_cls(component_class);
461 if (!py_cls) {
462 BT_LOGE("Cannot find Python class associated to native component class: "
463 "comp-cls-addr=%p", component_class);
464 goto error;
465 }
466
467 /* Parameters pointer -> SWIG pointer Python object */
468 py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
469 SWIGTYPE_p_bt_value, 0);
470 if (!py_params_ptr) {
471 BT_LOGE_STR("Failed to create a SWIG pointer object.");
472 goto error;
473 }
474
475 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_component_v),
476 self_comp_cls_type_swig_type, 0);
477 if (!py_comp_ptr) {
478 BT_LOGE_STR("Failed to create a SWIG pointer object.");
479 goto error;
480 }
481
482 /*
483 * Do the equivalent of this:
484 *
85906b6b 485 * py_comp = py_cls._bt_init_from_native(py_comp_ptr, py_params_ptr)
6945df9a 486 *
85906b6b 487 * _UserComponentType._bt_init_from_native() calls the Python
6945df9a
SM
488 * component object's __init__() function.
489 */
490 py_comp = PyObject_CallMethod(py_cls,
85906b6b 491 "_bt_init_from_native", "(OO)", py_comp_ptr, py_params_ptr);
6945df9a 492 if (!py_comp) {
85906b6b 493 BT_LOGW("Failed to call Python class's _bt_init_from_native() method: "
6945df9a 494 "py-cls-addr=%p", py_cls);
ce95fb26
SM
495 status = py_exc_to_status_component(self_component);
496 goto end;
6945df9a
SM
497 }
498
499 /*
500 * Our user Python component object is now fully created and
501 * initialized by the user. Since we just created it, this
502 * native component is its only (persistent) owner.
503 */
504 bt_self_component_set_data(self_component, py_comp);
505 py_comp = NULL;
506 goto end;
507
508error:
d24d5663 509 status = __BT_FUNC_STATUS_ERROR;
6945df9a
SM
510
511 /*
512 * Clear any exception: we're returning a bad status anyway. If
513 * this call originated from Python (creation from a plugin's
514 * component class, for example), then the user gets an
515 * appropriate creation error.
516 */
517 PyErr_Clear();
518
519end:
520 Py_XDECREF(py_comp);
521 Py_XDECREF(py_params_ptr);
522 Py_XDECREF(py_comp_ptr);
523 return status;
524}
525
526/*
527 * Method of bt_component_class_source to initialize a bt_self_component_source
528 * of that class.
529 */
530
7744859c 531static
d24d5663 532bt_component_class_init_method_status component_class_source_init(
7744859c 533 bt_self_component_source *self_component_source,
6945df9a
SM
534 const bt_value *params, void *init_method_data)
535{
536 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
d24d5663 537 return component_class_init(
6945df9a
SM
538 self_component,
539 self_component_source,
540 SWIGTYPE_p_bt_self_component_source,
541 params, init_method_data);
542}
543
7744859c 544static
d24d5663 545bt_component_class_init_method_status component_class_filter_init(
7744859c 546 bt_self_component_filter *self_component_filter,
6945df9a
SM
547 const bt_value *params, void *init_method_data)
548{
549 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
d24d5663 550 return component_class_init(
6945df9a
SM
551 self_component,
552 self_component_filter,
553 SWIGTYPE_p_bt_self_component_filter,
554 params, init_method_data);
555}
556
7744859c 557static
d24d5663 558bt_component_class_init_method_status component_class_sink_init(
7744859c 559 bt_self_component_sink *self_component_sink,
6945df9a
SM
560 const bt_value *params, void *init_method_data)
561{
562 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
d24d5663 563 return component_class_init(
6945df9a
SM
564 self_component,
565 self_component_sink,
566 SWIGTYPE_p_bt_self_component_sink,
567 params, init_method_data);
568}
569
7744859c 570static
d24d5663 571void component_class_finalize(bt_self_component *self_component)
6945df9a
SM
572{
573 PyObject *py_comp = bt_self_component_get_data(self_component);
574 BT_ASSERT(py_comp);
575
6a91742b 576 /* Call user's _user_finalize() method */
6945df9a 577 PyObject *py_method_result = PyObject_CallMethod(py_comp,
6a91742b 578 "_user_finalize", NULL);
6945df9a
SM
579
580 if (PyErr_Occurred()) {
6a91742b 581 BT_LOGW("User component's _user_finalize() method raised an exception: ignoring:");
d24d5663 582 logw_exception();
6945df9a
SM
583 }
584
585 /*
6a91742b
PP
586 * Ignore any exception raised by the _user_finalize() method
587 * because it won't change anything at this point: the component
588 * is being destroyed anyway.
6945df9a
SM
589 */
590 PyErr_Clear();
591 Py_XDECREF(py_method_result);
592 Py_DECREF(py_comp);
593}
594
7744859c 595static
d24d5663 596void component_class_source_finalize(bt_self_component_source *self_component_source)
6945df9a
SM
597{
598 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
d24d5663 599 component_class_finalize(self_component);
6945df9a
SM
600}
601
7744859c 602static
d24d5663 603void component_class_filter_finalize(bt_self_component_filter *self_component_filter)
6945df9a
SM
604{
605 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
d24d5663 606 component_class_finalize(self_component);
6945df9a
SM
607}
608
7744859c 609static
d24d5663 610void component_class_sink_finalize(bt_self_component_sink *self_component_sink)
6945df9a
SM
611{
612 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
d24d5663 613 component_class_finalize(self_component);
6945df9a
SM
614}
615
f00b8d40 616static
d24d5663 617bt_bool component_class_can_seek_beginning(
f00b8d40
SM
618 bt_self_message_iterator *self_message_iterator)
619{
620 PyObject *py_iter;
621 PyObject *py_result = NULL;
622 bt_bool can_seek_beginning = false;
623
624 py_iter = bt_self_message_iterator_get_data(self_message_iterator);
625 BT_ASSERT(py_iter);
626
85906b6b 627 py_result = PyObject_GetAttrString(py_iter, "_bt_can_seek_beginning_from_native");
f00b8d40
SM
628
629 BT_ASSERT(!py_result || PyBool_Check(py_result));
630
631 if (py_result) {
632 can_seek_beginning = PyObject_IsTrue(py_result);
633 } else {
634 /*
635 * Once can_seek_beginning can report errors, convert the
636 * exception to a status. For now, log and return false;
637 */
ce95fb26 638 loge_exception_message_iterator(self_message_iterator);
f00b8d40
SM
639 PyErr_Clear();
640 }
641
642 Py_XDECREF(py_result);
643
644 return can_seek_beginning;
645}
646
647static
d24d5663
PP
648bt_component_class_message_iterator_seek_beginning_method_status
649component_class_seek_beginning(bt_self_message_iterator *self_message_iterator)
f00b8d40
SM
650{
651 PyObject *py_iter;
652 PyObject *py_result;
d24d5663 653 bt_component_class_message_iterator_seek_beginning_method_status status;
f00b8d40
SM
654
655 py_iter = bt_self_message_iterator_get_data(self_message_iterator);
656 BT_ASSERT(py_iter);
85906b6b 657 py_result = PyObject_CallMethod(py_iter, "_bt_seek_beginning_from_native",
d24d5663 658 NULL);
f00b8d40 659 BT_ASSERT(!py_result || py_result == Py_None);
ce4923b0 660 status = py_exc_to_status_message_iterator(self_message_iterator);
f00b8d40 661 Py_XDECREF(py_result);
f00b8d40
SM
662 return status;
663}
664
7744859c 665static
d24d5663 666bt_component_class_port_connected_method_status component_class_port_connected(
6945df9a
SM
667 bt_self_component *self_component,
668 void *self_component_port,
669 swig_type_info *self_component_port_swig_type,
670 bt_port_type self_component_port_type,
671 const void *other_port,
672 swig_type_info *other_port_swig_type)
673{
d24d5663 674 bt_component_class_port_connected_method_status status;
6945df9a
SM
675 PyObject *py_comp = NULL;
676 PyObject *py_self_port_ptr = NULL;
677 PyObject *py_other_port_ptr = NULL;
678 PyObject *py_method_result = NULL;
679
680 py_comp = bt_self_component_get_data(self_component);
681 BT_ASSERT(py_comp);
6945df9a
SM
682 py_self_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_component_port),
683 self_component_port_swig_type, 0);
684 if (!py_self_port_ptr) {
685 BT_LOGF_STR("Failed to create a SWIG pointer object.");
d24d5663 686 status = __BT_FUNC_STATUS_MEMORY_ERROR;
6945df9a
SM
687 goto end;
688 }
689
690 py_other_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(other_port),
691 other_port_swig_type, 0);
692 if (!py_other_port_ptr) {
693 BT_LOGF_STR("Failed to create a SWIG pointer object.");
d24d5663 694 status = __BT_FUNC_STATUS_MEMORY_ERROR;
6945df9a
SM
695 goto end; }
696
697 py_method_result = PyObject_CallMethod(py_comp,
85906b6b 698 "_bt_port_connected_from_native", "(OiO)", py_self_port_ptr,
6945df9a 699 self_component_port_type, py_other_port_ptr);
6945df9a 700 BT_ASSERT(!py_method_result || py_method_result == Py_None);
ce95fb26 701 status = py_exc_to_status_component(self_component);
6945df9a
SM
702
703end:
704 Py_XDECREF(py_self_port_ptr);
705 Py_XDECREF(py_other_port_ptr);
706 Py_XDECREF(py_method_result);
6945df9a
SM
707 return status;
708}
709
7744859c 710static
d24d5663
PP
711bt_component_class_port_connected_method_status
712component_class_source_output_port_connected(
6945df9a
SM
713 bt_self_component_source *self_component_source,
714 bt_self_component_port_output *self_component_port_output,
715 const bt_port_input *other_port_input)
716{
717 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
718
d24d5663 719 return component_class_port_connected(
6945df9a
SM
720 self_component,
721 self_component_port_output,
722 SWIGTYPE_p_bt_self_component_port_output,
723 BT_PORT_TYPE_OUTPUT,
724 other_port_input,
725 SWIGTYPE_p_bt_port_input);
726}
727
7744859c 728static
d24d5663
PP
729bt_component_class_port_connected_method_status
730component_class_filter_input_port_connected(
6945df9a
SM
731 bt_self_component_filter *self_component_filter,
732 bt_self_component_port_input *self_component_port_input,
733 const bt_port_output *other_port_output)
734{
735 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
736
d24d5663 737 return component_class_port_connected(
6945df9a
SM
738 self_component,
739 self_component_port_input,
740 SWIGTYPE_p_bt_self_component_port_input,
741 BT_PORT_TYPE_INPUT,
742 other_port_output,
743 SWIGTYPE_p_bt_port_output);
744}
745
7744859c 746static
d24d5663
PP
747bt_component_class_port_connected_method_status
748component_class_filter_output_port_connected(
6945df9a
SM
749 bt_self_component_filter *self_component_filter,
750 bt_self_component_port_output *self_component_port_output,
751 const bt_port_input *other_port_input)
752{
753 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
754
d24d5663 755 return component_class_port_connected(
6945df9a
SM
756 self_component,
757 self_component_port_output,
758 SWIGTYPE_p_bt_self_component_port_output,
759 BT_PORT_TYPE_OUTPUT,
760 other_port_input,
761 SWIGTYPE_p_bt_port_input);
762}
763
7744859c 764static
d24d5663
PP
765bt_component_class_port_connected_method_status
766component_class_sink_input_port_connected(
6945df9a
SM
767 bt_self_component_sink *self_component_sink,
768 bt_self_component_port_input *self_component_port_input,
769 const bt_port_output *other_port_output)
770{
771 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
772
d24d5663 773 return component_class_port_connected(
6945df9a
SM
774 self_component,
775 self_component_port_input,
776 SWIGTYPE_p_bt_self_component_port_input,
777 BT_PORT_TYPE_INPUT,
778 other_port_output,
779 SWIGTYPE_p_bt_port_output);
780}
781
7744859c 782static
d24d5663
PP
783bt_component_class_sink_graph_is_configured_method_status
784component_class_sink_graph_is_configured(
7744859c 785 bt_self_component_sink *self_component_sink)
6945df9a
SM
786{
787 PyObject *py_comp = NULL;
788 PyObject *py_method_result = NULL;
d24d5663 789 bt_component_class_sink_graph_is_configured_method_status status = __BT_FUNC_STATUS_OK;
6945df9a
SM
790 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
791
792 py_comp = bt_self_component_get_data(self_component);
793 py_method_result = PyObject_CallMethod(py_comp,
85906b6b 794 "_bt_graph_is_configured_from_native", NULL);
6945df9a 795 BT_ASSERT(!py_method_result || py_method_result == Py_None);
ce95fb26 796 status = py_exc_to_status_component(self_component);
6945df9a 797 Py_XDECREF(py_method_result);
6945df9a
SM
798 return status;
799}
800
7744859c 801static
d24d5663 802bt_component_class_query_method_status component_class_query(
6945df9a 803 const bt_component_class *component_class,
ce95fb26 804 bt_self_component_class *self_component_class,
6945df9a
SM
805 const bt_query_executor *query_executor,
806 const char *object, const bt_value *params,
f4e38e70 807 bt_logging_level log_level,
6945df9a
SM
808 const bt_value **result)
809{
810 PyObject *py_cls = NULL;
811 PyObject *py_params_ptr = NULL;
812 PyObject *py_query_exec_ptr = NULL;
813 PyObject *py_query_func = NULL;
814 PyObject *py_object = NULL;
815 PyObject *py_results_addr = NULL;
d24d5663 816 bt_component_class_query_method_status status = __BT_FUNC_STATUS_OK;
6945df9a
SM
817
818 py_cls = lookup_cc_ptr_to_py_cls(component_class);
819 if (!py_cls) {
820 BT_LOGE("Cannot find Python class associated to native component class: "
821 "comp-cls-addr=%p", component_class);
822 goto error;
823 }
824
825 py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
826 SWIGTYPE_p_bt_value, 0);
827 if (!py_params_ptr) {
828 BT_LOGE_STR("Failed to create a SWIG pointer object.");
829 goto error;
830 }
831
832 py_query_exec_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(query_executor),
833 SWIGTYPE_p_bt_query_executor, 0);
834 if (!py_query_exec_ptr) {
835 BT_LOGE_STR("Failed to create a SWIG pointer object.");
836 goto error;
837 }
838
839 py_object = SWIG_FromCharPtr(object);
840 if (!py_object) {
841 BT_LOGE_STR("Failed to create a Python string.");
842 goto error;
843 }
844
845 py_results_addr = PyObject_CallMethod(py_cls,
85906b6b 846 "_bt_query_from_native", "(OOOi)", py_query_exec_ptr,
f4e38e70 847 py_object, py_params_ptr, (int) log_level);
6945df9a 848 if (!py_results_addr) {
85906b6b 849 BT_LOGW("Failed to call Python class's _bt_query_from_native() method: "
6945df9a 850 "py-cls-addr=%p", py_cls);
ce95fb26 851 status = py_exc_to_status_component_class(self_component_class);
6945df9a
SM
852 goto end;
853 }
854
855 /*
856 * The returned object, on success, is an integer object
857 * (PyLong) containing the address of a BT value object (new
858 * reference).
859 */
babe0791 860 *result = PyLong_AsVoidPtr(py_results_addr);
6945df9a
SM
861 BT_ASSERT(!PyErr_Occurred());
862 BT_ASSERT(*result);
863 goto end;
864
865error:
866 PyErr_Clear();
d24d5663 867 status = __BT_FUNC_STATUS_ERROR;
6945df9a
SM
868
869end:
870 Py_XDECREF(py_params_ptr);
871 Py_XDECREF(py_query_exec_ptr);
872 Py_XDECREF(py_query_func);
873 Py_XDECREF(py_object);
874 Py_XDECREF(py_results_addr);
875 return status;
876}
877
7744859c 878static
d24d5663 879bt_component_class_query_method_status component_class_source_query(
6945df9a
SM
880 bt_self_component_class_source *self_component_class_source,
881 const bt_query_executor *query_executor,
882 const char *object, const bt_value *params,
f4e38e70 883 bt_logging_level log_level,
6945df9a
SM
884 const bt_value **result)
885{
886 const bt_component_class_source *component_class_source = bt_self_component_class_source_as_component_class_source(self_component_class_source);
887 const bt_component_class *component_class = bt_component_class_source_as_component_class_const(component_class_source);
ce95fb26 888 bt_self_component_class *self_component_class = bt_self_component_class_source_as_self_component_class(self_component_class_source);
d24d5663 889
ce95fb26 890 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
6945df9a
SM
891}
892
7744859c 893static
d24d5663 894bt_component_class_query_method_status component_class_filter_query(
6945df9a
SM
895 bt_self_component_class_filter *self_component_class_filter,
896 const bt_query_executor *query_executor,
897 const char *object, const bt_value *params,
f4e38e70 898 bt_logging_level log_level,
6945df9a
SM
899 const bt_value **result)
900{
901 const bt_component_class_filter *component_class_filter = bt_self_component_class_filter_as_component_class_filter(self_component_class_filter);
902 const bt_component_class *component_class = bt_component_class_filter_as_component_class_const(component_class_filter);
ce95fb26 903 bt_self_component_class *self_component_class = bt_self_component_class_filter_as_self_component_class(self_component_class_filter);
d24d5663 904
ce95fb26 905 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
6945df9a
SM
906}
907
7744859c 908static
d24d5663 909bt_component_class_query_method_status component_class_sink_query(
6945df9a
SM
910 bt_self_component_class_sink *self_component_class_sink,
911 const bt_query_executor *query_executor,
912 const char *object, const bt_value *params,
f4e38e70 913 bt_logging_level log_level,
6945df9a
SM
914 const bt_value **result)
915{
916 const bt_component_class_sink *component_class_sink = bt_self_component_class_sink_as_component_class_sink(self_component_class_sink);
917 const bt_component_class *component_class = bt_component_class_sink_as_component_class_const(component_class_sink);
ce95fb26 918 bt_self_component_class *self_component_class = bt_self_component_class_sink_as_self_component_class(self_component_class_sink);
d24d5663 919
ce95fb26 920 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
6945df9a
SM
921}
922
7744859c 923static
d24d5663
PP
924bt_component_class_message_iterator_init_method_status
925component_class_message_iterator_init(
6945df9a
SM
926 bt_self_message_iterator *self_message_iterator,
927 bt_self_component *self_component,
928 bt_self_component_port_output *self_component_port_output)
929{
d24d5663 930 bt_component_class_message_iterator_init_method_status status = __BT_FUNC_STATUS_OK;
6945df9a
SM
931 PyObject *py_comp_cls = NULL;
932 PyObject *py_iter_cls = NULL;
933 PyObject *py_iter_ptr = NULL;
c5f330cd 934 PyObject *py_component_port_output_ptr = NULL;
6945df9a
SM
935 PyObject *py_init_method_result = NULL;
936 PyObject *py_iter = NULL;
937 PyObject *py_comp;
938
939 py_comp = bt_self_component_get_data(self_component);
940
5602ef81 941 /* Find user's Python message iterator class */
6945df9a
SM
942 py_comp_cls = PyObject_GetAttrString(py_comp, "__class__");
943 if (!py_comp_cls) {
944 BT_LOGE_STR("Cannot get Python object's `__class__` attribute.");
ce95fb26 945 goto python_error;
6945df9a
SM
946 }
947
948 py_iter_cls = PyObject_GetAttrString(py_comp_cls, "_iter_cls");
949 if (!py_iter_cls) {
950 BT_LOGE_STR("Cannot get Python class's `_iter_cls` attribute.");
ce95fb26 951 goto python_error;
6945df9a
SM
952 }
953
954 py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_message_iterator),
955 SWIGTYPE_p_bt_self_message_iterator, 0);
956 if (!py_iter_ptr) {
ce95fb26
SM
957 const char *err = "Failed to create a SWIG pointer object.";
958
959 BT_LOGE_STR(err);
960 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
961 self_message_iterator, err);
6945df9a
SM
962 goto error;
963 }
964
965 /*
5602ef81 966 * Create object with borrowed native message iterator
6945df9a
SM
967 * reference:
968 *
969 * py_iter = py_iter_cls.__new__(py_iter_cls, py_iter_ptr)
970 */
971 py_iter = PyObject_CallMethod(py_iter_cls, "__new__",
972 "(OO)", py_iter_cls, py_iter_ptr);
973 if (!py_iter) {
974 BT_LOGE("Failed to call Python class's __new__() method: "
975 "py-cls-addr=%p", py_iter_cls);
ce95fb26 976 goto python_error;
6945df9a
SM
977 }
978
979 /*
980 * Initialize object:
981 *
c5f330cd
SM
982 * py_iter.__init__(self_output_port)
983 *
51f97fcc 984 * through the _init_for_native helper static method.
6945df9a
SM
985 *
986 * At this point, py_iter._ptr is set, so this initialization
987 * function has access to self._component (which gives it the
988 * user Python component object from which the iterator was
989 * created).
990 */
51f97fcc
SM
991 py_component_port_output_ptr = SWIG_NewPointerObj(
992 SWIG_as_voidptr(self_component_port_output),
c5f330cd
SM
993 SWIGTYPE_p_bt_self_component_port_output, 0);
994 if (!py_component_port_output_ptr) {
ce95fb26
SM
995 const char *err = "Failed to create a SWIG pointer object.";
996
997 BT_LOGE_STR(err);
998 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
999 self_message_iterator, err);
c5f330cd
SM
1000 goto error;
1001 }
1002
d24d5663 1003 py_init_method_result = PyObject_CallMethod(py_iter,
85906b6b 1004 "_bt_init_from_native", "O", py_component_port_output_ptr);
6945df9a 1005 if (!py_init_method_result) {
ce95fb26
SM
1006 BT_LOGE_STR("User's __init__() method failed:");
1007 goto python_error;
6945df9a
SM
1008 }
1009
1010 /*
1011 * Since the Python code can never instantiate a user-defined
5602ef81
SM
1012 * message iterator class, the native message iterator
1013 * object does NOT belong to a user Python message iterator
6945df9a 1014 * object (borrowed reference). However this Python object is
5602ef81 1015 * owned by this native message iterator object.
6945df9a 1016 *
5602ef81
SM
1017 * In the Python world, the lifetime of the native message
1018 * iterator is managed by a _GenericMessageIterator
6945df9a
SM
1019 * instance:
1020 *
5602ef81
SM
1021 * _GenericMessageIterator instance:
1022 * owns a native bt_message_iterator object (iter)
6945df9a
SM
1023 * owns a _UserMessageIterator instance (py_iter)
1024 * self._ptr is a borrowed reference to the
5602ef81 1025 * native bt_private_connection_private_message_iterator
6945df9a
SM
1026 * object (iter)
1027 */
1028 bt_self_message_iterator_set_data(self_message_iterator, py_iter);
1029 py_iter = NULL;
1030 goto end;
1031
ce95fb26
SM
1032python_error:
1033 /* Handling of errors that cause a Python exception to be set. */
1034 status = py_exc_to_status_message_iterator(self_message_iterator);
1035 BT_ASSERT(status != __BT_FUNC_STATUS_OK);
1036 goto end;
6945df9a 1037
ce95fb26
SM
1038error:
1039 /* Handling of errors that don't cause a Python exception to be set. */
1040 status = __BT_FUNC_STATUS_ERROR;
6945df9a
SM
1041
1042end:
ce95fb26
SM
1043 BT_ASSERT(!PyErr_Occurred());
1044
6945df9a
SM
1045 Py_XDECREF(py_comp_cls);
1046 Py_XDECREF(py_iter_cls);
1047 Py_XDECREF(py_iter_ptr);
c5f330cd 1048 Py_XDECREF(py_component_port_output_ptr);
6945df9a
SM
1049 Py_XDECREF(py_init_method_result);
1050 Py_XDECREF(py_iter);
1051 return status;
1052}
1053
7744859c 1054static
d24d5663
PP
1055bt_component_class_message_iterator_init_method_status
1056component_class_source_message_iterator_init(
6945df9a
SM
1057 bt_self_message_iterator *self_message_iterator,
1058 bt_self_component_source *self_component_source,
1059 bt_self_component_port_output *self_component_port_output)
1060{
1061 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
d24d5663
PP
1062
1063 return component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
6945df9a
SM
1064}
1065
7744859c 1066static
d24d5663
PP
1067bt_component_class_message_iterator_init_method_status
1068component_class_filter_message_iterator_init(
6945df9a
SM
1069 bt_self_message_iterator *self_message_iterator,
1070 bt_self_component_filter *self_component_filter,
1071 bt_self_component_port_output *self_component_port_output)
1072{
1073 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
d24d5663
PP
1074
1075 return component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
6945df9a
SM
1076}
1077
7744859c 1078static
d24d5663 1079void component_class_message_iterator_finalize(
6945df9a
SM
1080 bt_self_message_iterator *message_iterator)
1081{
1082 PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
1083 PyObject *py_method_result = NULL;
1084
1085 BT_ASSERT(py_message_iter);
1086
6a91742b 1087 /* Call user's _user_finalize() method */
6945df9a 1088 py_method_result = PyObject_CallMethod(py_message_iter,
6a91742b 1089 "_user_finalize", NULL);
6945df9a
SM
1090
1091 if (PyErr_Occurred()) {
6a91742b 1092 BT_LOGW("User's _user_finalize() method raised an exception: ignoring:");
d24d5663 1093 logw_exception();
6945df9a
SM
1094 }
1095
1096 /*
6a91742b
PP
1097 * Ignore any exception raised by the _user_finalize() method
1098 * because it won't change anything at this point: the component
1099 * is being destroyed anyway.
6945df9a
SM
1100 */
1101 PyErr_Clear();
1102 Py_XDECREF(py_method_result);
1103 Py_DECREF(py_message_iter);
1104}
1105
1106/* Valid for both sources and filters. */
1107
7744859c 1108static
d24d5663
PP
1109bt_component_class_message_iterator_next_method_status
1110component_class_message_iterator_next(
7744859c
SM
1111 bt_self_message_iterator *message_iterator,
1112 bt_message_array_const msgs, uint64_t capacity,
1113 uint64_t *count)
6945df9a 1114{
d24d5663 1115 bt_component_class_message_iterator_next_method_status status = __BT_FUNC_STATUS_OK;
6945df9a
SM
1116 PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
1117 PyObject *py_method_result = NULL;
1118
1119 BT_ASSERT(py_message_iter);
1120 py_method_result = PyObject_CallMethod(py_message_iter,
85906b6b 1121 "_bt_next_from_native", NULL);
6945df9a 1122 if (!py_method_result) {
ce95fb26 1123 status = py_exc_to_status_message_iterator(message_iterator);
d24d5663 1124 BT_ASSERT(status != __BT_FUNC_STATUS_OK);
6945df9a
SM
1125 goto end;
1126 }
1127
1128 /*
1129 * The returned object, on success, is an integer object
5602ef81 1130 * (PyLong) containing the address of a native message
6945df9a
SM
1131 * object (which is now ours).
1132 */
babe0791 1133 msgs[0] = PyLong_AsVoidPtr(py_method_result);
6945df9a
SM
1134 *count = 1;
1135
1136 /* Clear potential overflow error; should never happen */
1137 BT_ASSERT(!PyErr_Occurred());
1138 goto end;
1139
1140end:
1141 Py_XDECREF(py_method_result);
1142 return status;
1143}
1144
7744859c 1145static
d24d5663
PP
1146bt_component_class_sink_consume_method_status
1147component_class_sink_consume(bt_self_component_sink *self_component_sink)
6945df9a
SM
1148{
1149 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
1150 PyObject *py_comp = bt_self_component_get_data(self_component);
1151 PyObject *py_method_result = NULL;
d24d5663 1152 bt_component_class_sink_consume_method_status status;
6945df9a
SM
1153
1154 BT_ASSERT(py_comp);
1155 py_method_result = PyObject_CallMethod(py_comp,
6a91742b 1156 "_user_consume", NULL);
ce95fb26 1157 status = py_exc_to_status_component(self_component);
d24d5663 1158 if (!py_method_result && status == __BT_FUNC_STATUS_OK) {
6945df9a 1159 /* Pretty sure this should never happen, but just in case */
6a91742b 1160 BT_LOGE("User's _user_consume() method failed without raising an exception: "
6945df9a 1161 "status=%d", status);
d24d5663 1162 status = __BT_FUNC_STATUS_ERROR;
6945df9a
SM
1163 }
1164
1165 Py_XDECREF(py_method_result);
1166 return status;
1167}
1168
1169static
d24d5663 1170int component_class_set_help_and_desc(
6945df9a
SM
1171 bt_component_class *component_class,
1172 const char *description, const char *help)
1173{
1174 int ret;
1175
1176 if (description) {
1177 ret = bt_component_class_set_description(component_class, description);
1178 if (ret) {
1179 BT_LOGE("Cannot set component class's description: "
1180 "comp-cls-addr=%p", component_class);
1181 goto end;
1182 }
1183 }
1184
1185 if (help) {
1186 ret = bt_component_class_set_help(component_class, help);
1187 if (ret) {
1188 BT_LOGE("Cannot set component class's help text: "
1189 "comp-cls-addr=%p", component_class);
1190 goto end;
1191 }
1192 }
1193
1194 ret = 0;
1195
1196end:
1197 return ret;
1198}
1199
1200static
d24d5663 1201bt_component_class_source *bt_bt2_component_class_source_create(
6945df9a
SM
1202 PyObject *py_cls, const char *name, const char *description,
1203 const char *help)
1204{
1205 bt_component_class_source *component_class_source;
1206 bt_component_class *component_class;
1207 int ret;
1208
1209 BT_ASSERT(py_cls);
6945df9a 1210 component_class_source = bt_component_class_source_create(name,
d24d5663 1211 component_class_message_iterator_next);
6945df9a
SM
1212 if (!component_class_source) {
1213 BT_LOGE_STR("Cannot create source component class.");
1214 goto end;
1215 }
1216
1217 component_class = bt_component_class_source_as_component_class(component_class_source);
1218
d24d5663 1219 if (component_class_set_help_and_desc(component_class, description, help)) {
6945df9a
SM
1220 goto end;
1221 }
1222
d24d5663 1223 ret = bt_component_class_source_set_init_method(component_class_source, component_class_source_init);
6945df9a 1224 BT_ASSERT(ret == 0);
d24d5663 1225 ret = bt_component_class_source_set_finalize_method(component_class_source, component_class_source_finalize);
f00b8d40
SM
1226 BT_ASSERT(ret == 0);
1227 ret = bt_component_class_source_set_message_iterator_can_seek_beginning_method(component_class_source,
d24d5663 1228 component_class_can_seek_beginning);
f00b8d40
SM
1229 BT_ASSERT(ret == 0);
1230 ret = bt_component_class_source_set_message_iterator_seek_beginning_method(component_class_source,
d24d5663 1231 component_class_seek_beginning);
6945df9a 1232 BT_ASSERT(ret == 0);
6945df9a 1233 ret = bt_component_class_source_set_output_port_connected_method(component_class_source,
d24d5663 1234 component_class_source_output_port_connected);
6945df9a 1235 BT_ASSERT(ret == 0);
d24d5663 1236 ret = bt_component_class_source_set_query_method(component_class_source, component_class_source_query);
6945df9a
SM
1237 BT_ASSERT(ret == 0);
1238 ret = bt_component_class_source_set_message_iterator_init_method(
d24d5663 1239 component_class_source, component_class_source_message_iterator_init);
6945df9a
SM
1240 BT_ASSERT(ret == 0);
1241 ret = bt_component_class_source_set_message_iterator_finalize_method(
d24d5663 1242 component_class_source, component_class_message_iterator_finalize);
6945df9a 1243 BT_ASSERT(ret == 0);
6945df9a
SM
1244 register_cc_ptr_to_py_cls(component_class, py_cls);
1245
1246end:
1247 return component_class_source;
1248}
1249
1250static
d24d5663 1251bt_component_class_filter *bt_bt2_component_class_filter_create(
6945df9a
SM
1252 PyObject *py_cls, const char *name, const char *description,
1253 const char *help)
1254{
1255 bt_component_class *component_class;
1256 bt_component_class_filter *component_class_filter;
1257 int ret;
1258
1259 BT_ASSERT(py_cls);
6945df9a 1260 component_class_filter = bt_component_class_filter_create(name,
d24d5663 1261 component_class_message_iterator_next);
6945df9a
SM
1262 if (!component_class_filter) {
1263 BT_LOGE_STR("Cannot create filter component class.");
1264 goto end;
1265 }
1266
1267 component_class = bt_component_class_filter_as_component_class(component_class_filter);
1268
d24d5663 1269 if (component_class_set_help_and_desc(component_class, description, help)) {
6945df9a
SM
1270 goto end;
1271 }
1272
d24d5663 1273 ret = bt_component_class_filter_set_init_method(component_class_filter, component_class_filter_init);
6945df9a 1274 BT_ASSERT(ret == 0);
d24d5663 1275 ret = bt_component_class_filter_set_finalize_method (component_class_filter, component_class_filter_finalize);
6945df9a 1276 BT_ASSERT(ret == 0);
f00b8d40 1277 ret = bt_component_class_filter_set_message_iterator_can_seek_beginning_method(component_class_filter,
d24d5663 1278 component_class_can_seek_beginning);
f00b8d40
SM
1279 BT_ASSERT(ret == 0);
1280 ret = bt_component_class_filter_set_message_iterator_seek_beginning_method(component_class_filter,
d24d5663 1281 component_class_seek_beginning);
f00b8d40 1282 BT_ASSERT(ret == 0);
6945df9a 1283 ret = bt_component_class_filter_set_input_port_connected_method(component_class_filter,
d24d5663 1284 component_class_filter_input_port_connected);
6945df9a
SM
1285 BT_ASSERT(ret == 0);
1286 ret = bt_component_class_filter_set_output_port_connected_method(component_class_filter,
d24d5663 1287 component_class_filter_output_port_connected);
6945df9a 1288 BT_ASSERT(ret == 0);
d24d5663 1289 ret = bt_component_class_filter_set_query_method(component_class_filter, component_class_filter_query);
6945df9a
SM
1290 BT_ASSERT(ret == 0);
1291 ret = bt_component_class_filter_set_message_iterator_init_method(
d24d5663 1292 component_class_filter, component_class_filter_message_iterator_init);
6945df9a
SM
1293 BT_ASSERT(ret == 0);
1294 ret = bt_component_class_filter_set_message_iterator_finalize_method(
d24d5663 1295 component_class_filter, component_class_message_iterator_finalize);
6945df9a 1296 BT_ASSERT(ret == 0);
6945df9a
SM
1297 register_cc_ptr_to_py_cls(component_class, py_cls);
1298
1299end:
1300 return component_class_filter;
1301}
1302
1303static
d24d5663 1304bt_component_class_sink *bt_bt2_component_class_sink_create(
6945df9a
SM
1305 PyObject *py_cls, const char *name, const char *description,
1306 const char *help)
1307{
1308 bt_component_class_sink *component_class_sink;
1309 bt_component_class *component_class;
1310 int ret;
1311
1312 BT_ASSERT(py_cls);
d24d5663 1313 component_class_sink = bt_component_class_sink_create(name, component_class_sink_consume);
6945df9a
SM
1314
1315 if (!component_class_sink) {
1316 BT_LOGE_STR("Cannot create sink component class.");
1317 goto end;
1318 }
1319
1320 component_class = bt_component_class_sink_as_component_class(component_class_sink);
1321
d24d5663 1322 if (component_class_set_help_and_desc(component_class, description, help)) {
6945df9a
SM
1323 goto end;
1324 }
1325
d24d5663 1326 ret = bt_component_class_sink_set_init_method(component_class_sink, component_class_sink_init);
6945df9a 1327 BT_ASSERT(ret == 0);
d24d5663 1328 ret = bt_component_class_sink_set_finalize_method(component_class_sink, component_class_sink_finalize);
6945df9a 1329 BT_ASSERT(ret == 0);
6945df9a 1330 ret = bt_component_class_sink_set_input_port_connected_method(component_class_sink,
d24d5663 1331 component_class_sink_input_port_connected);
6945df9a
SM
1332 BT_ASSERT(ret == 0);
1333 ret = bt_component_class_sink_set_graph_is_configured_method(component_class_sink,
d24d5663 1334 component_class_sink_graph_is_configured);
6945df9a 1335 BT_ASSERT(ret == 0);
d24d5663 1336 ret = bt_component_class_sink_set_query_method(component_class_sink, component_class_sink_query);
6945df9a 1337 BT_ASSERT(ret == 0);
6945df9a
SM
1338 register_cc_ptr_to_py_cls(component_class, py_cls);
1339
1340end:
1341 return component_class_sink;
1342}
1343%}
1344
d24d5663 1345struct bt_component_class_source *bt_bt2_component_class_source_create(
6945df9a
SM
1346 PyObject *py_cls, const char *name, const char *description,
1347 const char *help);
d24d5663 1348struct bt_component_class_filter *bt_bt2_component_class_filter_create(
6945df9a
SM
1349 PyObject *py_cls, const char *name, const char *description,
1350 const char *help);
d24d5663 1351struct bt_component_class_sink *bt_bt2_component_class_sink_create(
6945df9a
SM
1352 PyObject *py_cls, const char *name, const char *description,
1353 const char *help);
d24d5663
PP
1354void bt_bt2_cc_init_from_bt2(void);
1355void bt_bt2_cc_exit_handler(void);
This page took 0.096159 seconds and 4 git commands to generate.