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