Rename "query info" to "query" everywhere, and "action" to "object"
[babeltrace.git] / bindings / python / bt2 / native_btcomponentclass.i
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 %{
26 #include <babeltrace/component/component-class.h>
27 #include <babeltrace/component/component-class-source.h>
28 #include <babeltrace/component/component-class-sink.h>
29 #include <babeltrace/component/component-class-filter.h>
30 #include <babeltrace/component/notification/iterator.h>
31 #include <babeltrace/component/notification/notification.h>
32 #include <assert.h>
33 #include <glib.h>
34 %}
35
36 /* Types */
37 struct bt_component_class;
38
39 /* Status */
40 enum bt_component_class_type {
41 BT_COMPONENT_CLASS_TYPE_UNKNOWN = -1,
42 BT_COMPONENT_CLASS_TYPE_SOURCE = 0,
43 BT_COMPONENT_CLASS_TYPE_SINK = 1,
44 BT_COMPONENT_CLASS_TYPE_FILTER = 2,
45 };
46
47 /* General functions */
48 const char *bt_component_class_get_name(
49 struct bt_component_class *component_class);
50 const char *bt_component_class_get_description(
51 struct bt_component_class *component_class);
52 const char *bt_component_class_get_help(
53 struct bt_component_class *component_class);
54 struct bt_value *bt_component_class_query(
55 struct bt_component_class *component_class,
56 const char *action, struct bt_value *params);
57 enum bt_component_class_type bt_component_class_get_type(
58 struct bt_component_class *component_class);
59
60 %{
61 /*
62 * This hash table associates a BT component class object address to a
63 * user-defined Python class (PyObject *). The keys and values are NOT
64 * owned by this hash table. The Python class objects are owned by the
65 * Python module, which should not be unloaded until it is not possible
66 * to create a user Python component anyway.
67 *
68 * This hash table is written to when a user-defined Python component
69 * class is created by one of the bt_py3_component_class_*_create()
70 * functions.
71 *
72 * This function is read from when a user calls bt_component_create()
73 * with a component class pointer created by one of the functions above.
74 * In this case, the original Python class needs to be found to
75 * instantiate it and associate the created Python component object with
76 * a BT component object instance.
77 */
78
79 static GHashTable *bt_cc_ptr_to_py_cls;
80
81 static void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
82 PyObject *py_cls)
83 {
84 g_hash_table_insert(bt_cc_ptr_to_py_cls, (gpointer) bt_cc,
85 (gpointer) py_cls);
86 }
87
88 static PyObject *lookup_cc_ptr_to_py_cls(struct bt_component_class *bt_cc)
89 {
90 return (PyObject *) g_hash_table_lookup(bt_cc_ptr_to_py_cls,
91 (gconstpointer) bt_cc);
92 }
93
94
95 /*
96 * Useful Python objects.
97 */
98
99 static PyObject *py_mod_bt2 = NULL;
100 static PyObject *py_mod_bt2_exc_error_type = NULL;
101 static PyObject *py_mod_bt2_exc_unsupported_feature_type = NULL;
102 static PyObject *py_mod_bt2_exc_try_again_type = NULL;
103 static PyObject *py_mod_bt2_exc_stop_type = NULL;
104 static PyObject *py_mod_bt2_values = NULL;
105 static PyObject *py_mod_bt2_values_create_from_ptr_func = NULL;
106
107 static void bt_py3_cc_init_from_bt2(void)
108 {
109 /*
110 * This is called once the bt2 package is loaded.
111 *
112 * Those modules and functions are needed while the package is
113 * used. Loading them here is safe because we know the bt2
114 * package is imported, and we know that the user cannot use the
115 * code here without importing bt2 first.
116 */
117 py_mod_bt2 = PyImport_ImportModule("bt2");
118 assert(py_mod_bt2);
119 py_mod_bt2_values = PyImport_ImportModule("bt2.values");
120 assert(py_mod_bt2_values);
121 py_mod_bt2_values_create_from_ptr_func =
122 PyObject_GetAttrString(py_mod_bt2_values,
123 "_create_from_ptr");
124 assert(py_mod_bt2_values_create_from_ptr_func);
125 py_mod_bt2_exc_error_type =
126 PyObject_GetAttrString(py_mod_bt2, "Error");
127 assert(py_mod_bt2_exc_error_type);
128 py_mod_bt2_exc_unsupported_feature_type =
129 PyObject_GetAttrString(py_mod_bt2, "UnsupportedFeature");
130 py_mod_bt2_exc_try_again_type =
131 PyObject_GetAttrString(py_mod_bt2, "TryAgain");
132 py_mod_bt2_exc_stop_type =
133 PyObject_GetAttrString(py_mod_bt2, "Stop");
134 assert(py_mod_bt2_exc_stop_type);
135 }
136
137 static void bt_py3_cc_exit_handler(void)
138 {
139 /*
140 * This is an exit handler (set by the bt2 package).
141 *
142 * We only give back the references that we took in
143 * bt_py3_cc_init_from_bt2() here. The global variables continue
144 * to exist for the code of this file, but they are now borrowed
145 * references. If this code is executed, it means that somehow
146 * to modules are still loaded, so it should be safe to use them
147 * even without a strong reference.
148 *
149 * We cannot do this in the library's destructor because it
150 * gets executed once Python is already finalized.
151 */
152 Py_XDECREF(py_mod_bt2_values_create_from_ptr_func);
153 Py_XDECREF(py_mod_bt2_values);
154 Py_XDECREF(py_mod_bt2);
155 Py_XDECREF(py_mod_bt2_exc_error_type);
156 Py_XDECREF(py_mod_bt2_exc_unsupported_feature_type);
157 Py_XDECREF(py_mod_bt2_exc_try_again_type);
158 Py_XDECREF(py_mod_bt2_exc_stop_type);
159 }
160
161
162 /* Library constructor and destructor */
163
164 __attribute__((constructor))
165 static void bt_py3_native_comp_class_ctor(void) {
166 /* Initialize component class association hash table */
167 bt_cc_ptr_to_py_cls = g_hash_table_new(g_direct_hash, g_direct_equal);
168 assert(bt_cc_ptr_to_py_cls);
169 }
170
171 __attribute__((destructor))
172 static void bt_py3_native_comp_class_dtor(void) {
173 /* Destroy component class association hash table */
174 if (bt_cc_ptr_to_py_cls) {
175 g_hash_table_destroy(bt_cc_ptr_to_py_cls);
176 }
177 }
178
179
180 /* Converts a BT value object to a bt2.values object */
181
182 static PyObject *bt_py3_bt_value_from_ptr(struct bt_value *value)
183 {
184 PyObject *py_create_from_ptr_func = NULL;
185 PyObject *py_value = NULL;
186 PyObject *py_ptr = NULL;
187
188 py_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(value),
189 SWIGTYPE_p_bt_value, 0);
190 py_value = PyObject_CallFunctionObjArgs(
191 py_mod_bt2_values_create_from_ptr_func, py_ptr, NULL);
192 if (!py_value) {
193 goto end;
194 }
195
196 /*
197 * _create_from_ptr() only wraps an existing reference. `value`
198 * is a borrowed reference here, so increment its reference
199 * count for this new owner.
200 */
201 bt_get(value);
202
203 end:
204 Py_XDECREF(py_ptr);
205 PyErr_Clear();
206 return py_value;
207 }
208
209
210 /* self.__init__(*args, **kwargs) */
211
212 static int bt_py3_call_self_init(PyObject *py_self, PyObject *py_args,
213 PyObject *py_kwargs)
214 {
215 int ret = 0;
216 size_t i;
217 PyObject *py_init_method_result = NULL;
218 PyObject *py_init_method = NULL;
219 PyObject *py_init_method_args = NULL;
220 PyObject *py_class = NULL;
221
222 py_class = PyObject_GetAttrString(py_self, "__class__");
223 if (!py_class) {
224 goto error;
225 }
226
227 py_init_method = PyObject_GetAttrString(py_class, "__init__");
228 if (!py_init_method) {
229 goto error;
230 }
231
232 /* Prepend py_self to the arguments (copy them to new tuple) */
233 py_init_method_args = PyTuple_New(PyTuple_Size(py_args) + 1);
234 if (!py_init_method_args) {
235 goto error;
236 }
237
238 Py_INCREF(py_self);
239 ret = PyTuple_SetItem(py_init_method_args, 0, py_self);
240 if (ret < 0) {
241 Py_DECREF(py_self);
242 goto error;
243 }
244
245 for (i = 0; i < PyTuple_Size(py_args); i++) {
246 PyObject *obj = PyTuple_GetItem(py_args, i);
247 if (!obj) {
248 goto error;
249 }
250
251 Py_INCREF(obj);
252 ret = PyTuple_SetItem(py_init_method_args, i + 1, obj);
253 if (ret < 0) {
254 Py_DECREF(obj);
255 goto error;
256 }
257 }
258
259 py_init_method_result = PyObject_Call(py_init_method,
260 py_init_method_args, py_kwargs);
261 if (!py_init_method_result) {
262 goto error;
263 }
264
265 goto end;
266
267 error:
268 ret = -1;
269
270 end:
271 Py_XDECREF(py_init_method_args);
272 Py_XDECREF(py_init_method_result);
273 Py_XDECREF(py_init_method);
274 Py_XDECREF(py_class);
275 return ret;
276 }
277
278
279 /* Component class proxy methods (delegate to the attached Python object) */
280
281 static enum bt_component_status bt_py3_cc_init(
282 struct bt_component *component, struct bt_value *params,
283 void *init_method_data)
284 {
285 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
286 int ret;
287
288 /*
289 * This function is either called from
290 * _UserComponentType.__call__() (when init_method_data contains
291 * the PyObject * currently creating this component) or from
292 * other code (init_method_data is NULL).
293 */
294 if (init_method_data) {
295 /*
296 * Called from _UserComponentType.__call__().
297 *
298 * The `params` argument is completely ignored here,
299 * because if the user creating the component object
300 * from the component class object wants parameters,
301 * they'll be in the keyword arguments anyway.
302 */
303 PyObject *py_comp = init_method_data;
304 PyObject *py_comp_ptr = NULL;
305 PyObject *py_init_args = NULL;
306 PyObject *py_init_kwargs = NULL;
307
308 /*
309 * No need to take a Python reference on py_comp here:
310 * we store it as a _borrowed_ reference. When all the
311 * Python references are dropped, the object's __del__()
312 * method is called. This method calls this side
313 * (bt_py3_component_on_del()) to swap the ownership:
314 * this BT component becomes the only owner of the
315 * Python object.
316 */
317 bt_component_set_private_data(component, py_comp);
318
319 /*
320 * Set this BT component pointer as py_comp._ptr, and
321 * take a reference on it (on success, at the end).
322 *
323 * This reference is put in the Python component
324 * object's __del__() method.
325 */
326 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component),
327 SWIGTYPE_p_bt_component, 0);
328 if (!py_comp_ptr) {
329 PyErr_Clear();
330 goto with_init_method_data_error;
331 }
332
333 ret = PyObject_SetAttrString(py_comp, "_ptr", py_comp_ptr);
334 if (ret < 0) {
335 PyErr_Clear();
336 goto with_init_method_data_error;
337 }
338
339 /*
340 * _UserComponentType.__call__() puts the arguments and
341 * keyword arguments to use for the py_comp.__init__()
342 * call in py_comp._init_args and py_comp._init_kwargs.
343 *
344 * We need to get them and remove them from py_comp before
345 * calling py_comp.__init__().
346 */
347 py_init_args = PyObject_GetAttrString(py_comp, "_init_args");
348 if (!py_init_args) {
349 PyErr_Clear();
350 goto with_init_method_data_error;
351 }
352
353 py_init_kwargs = PyObject_GetAttrString(py_comp, "_init_kwargs");
354 if (!py_init_kwargs) {
355 PyErr_Clear();
356 goto with_init_method_data_error;
357 }
358
359 ret = PyObject_DelAttrString(py_comp, "_init_args");
360 if (ret < 0) {
361 PyErr_Clear();
362 goto with_init_method_data_error;
363 }
364
365 ret = PyObject_DelAttrString(py_comp, "_init_kwargs");
366 if (ret < 0) {
367 PyErr_Clear();
368 goto with_init_method_data_error;
369 }
370
371 /* Ready to call py_comp.__init__() */
372 ret = bt_py3_call_self_init(py_comp, py_init_args,
373 py_init_kwargs);
374 if (ret) {
375 /*
376 * We do not clear any raised exception here
377 * so that the Python caller (the one who is
378 * instantiating the class) gets the exception
379 * from the __init__() method.
380 */
381 goto with_init_method_data_error;
382 }
383
384 /*
385 * py_comp.__init__() went well: get the native BT
386 * component object reference for the Python object.
387 */
388 bt_get(component);
389 goto with_init_method_data_end;
390
391 with_init_method_data_error:
392 status = BT_COMPONENT_STATUS_ERROR;
393
394 /*
395 * Reset py_comp._ptr to None to signal the error to
396 * _UserComponentType.__call__(). For exceptions raised
397 * from py_comp.__init__(), this is not important,
398 * because __call__() will also raise before even
399 * checking py_comp._ptr.
400 */
401 if (PyObject_HasAttrString(py_comp, "_ptr")) {
402 PyObject *py_err_type, *py_err_value, *py_err_traceback;
403 PyErr_Fetch(&py_err_type, &py_err_value,
404 &py_err_traceback);
405 Py_INCREF(Py_None);
406 PyObject_SetAttrString(py_comp, "_ptr", Py_None);
407 PyErr_Restore(py_err_type, py_err_value,
408 py_err_traceback);
409 }
410
411 /*
412 * Important: remove py_comp from our the BT component's
413 * private data. Since we're failing,
414 * bt_py3_cc_destroy() is about to be called: it must
415 * not consider py_comp. py_comp's __del__() method
416 * will be called (because the instance exists), but
417 * since py_comp._ptr is None, it won't do anything.
418 */
419 bt_component_set_private_data(component, NULL);
420
421 with_init_method_data_end:
422 Py_XDECREF(py_comp_ptr);
423 Py_XDECREF(py_init_args);
424 Py_XDECREF(py_init_kwargs);
425 } else {
426 /*
427 * Not called from _UserComponentType.__call__().
428 *
429 * In this case we need to instantiate the user-defined
430 * Python class. To do this we call the user-defined
431 * class manually with this already-created BT component
432 * object pointer as the __comp_ptr keyword argument.
433 *
434 * We keep a reference, the only existing one, to the
435 * created Python object. bt_py3_component_on_del() will
436 * never be called by the object's __del__() method
437 * because _UserComponentType.__call__() marks the
438 * object as owned by the native BT component object.
439 */
440 PyObject *py_cls = NULL;
441 PyObject *py_comp = NULL;
442 PyObject *py_params = NULL;
443 PyObject *py_comp_ptr = NULL;
444 PyObject *py_cls_ctor_args = NULL;
445 PyObject *py_cls_ctor_kwargs = NULL;
446
447 /*
448 * Get the user-defined Python class which created this
449 * component's class in the first place (borrowed
450 * reference).
451 */
452 py_cls = lookup_cc_ptr_to_py_cls(bt_component_get_class(component));
453 if (!py_cls) {
454 goto without_init_method_data_error;
455 }
456
457 /* BT value object -> Python bt2.values object */
458 py_params = bt_py3_bt_value_from_ptr(params);
459 if (!py_params) {
460 goto without_init_method_data_error;
461 }
462
463 /* Component pointer -> SWIG pointer Python object */
464 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component),
465 SWIGTYPE_p_bt_component, 0);
466 if (!py_comp_ptr) {
467 goto without_init_method_data_error;
468 }
469
470 /*
471 * Do the equivalent of this:
472 *
473 * py_comp = py_cls(__comp_ptr=py_comp_ptr, params=py_params)
474 *
475 * _UserComponentType.__call__() calls the Python
476 * component object's __init__() function itself in this
477 * case.
478 */
479 py_cls_ctor_args = PyTuple_New(0);
480 if (!py_cls_ctor_args) {
481 goto without_init_method_data_error;
482 }
483
484 py_cls_ctor_kwargs = PyDict_New();
485 if (!py_cls_ctor_kwargs) {
486 goto without_init_method_data_error;
487 }
488
489 ret = PyDict_SetItemString(py_cls_ctor_kwargs, "__comp_ptr",
490 py_comp_ptr);
491 if (ret < 0) {
492 goto without_init_method_data_error;
493 }
494
495 ret = PyDict_SetItemString(py_cls_ctor_kwargs, "params",
496 py_params);
497 if (ret < 0) {
498 goto without_init_method_data_error;
499 }
500
501 py_comp = PyObject_Call(py_cls, py_cls_ctor_args,
502 py_cls_ctor_kwargs);
503 if (!py_comp) {
504 goto without_init_method_data_error;
505 }
506
507 /*
508 * Our user Python component object is now fully created
509 * and initialized by the user. Since we just created
510 * it, this BT component is its only (persistent) owner.
511 */
512 bt_component_set_private_data(component, py_comp);
513 py_comp = NULL;
514 goto without_init_method_data_end;
515
516 without_init_method_data_error:
517 status = BT_COMPONENT_STATUS_ERROR;
518
519 /*
520 * Clear any exception: we're returning a bad status
521 * anyway. If this call originated from Python (creation
522 * from a plugin's component class, for example), then
523 * the user gets an appropriate creation error.
524 */
525 PyErr_Clear();
526
527 without_init_method_data_end:
528 Py_XDECREF(py_comp);
529 Py_XDECREF(py_params);
530 Py_XDECREF(py_comp_ptr);
531 Py_XDECREF(py_cls_ctor_args);
532 Py_XDECREF(py_cls_ctor_kwargs);
533 }
534
535 return status;
536 }
537
538 static void bt_py3_cc_destroy(struct bt_component *component)
539 {
540 PyObject *py_comp = bt_component_get_private_data(component);
541 PyObject *py_destroy_method_result = NULL;
542
543 if (py_comp) {
544 /*
545 * If we're here, this BT component is the only owner of
546 * its private user Python object. It is safe to
547 * decrement its reference count, and thus destroy it.
548 *
549 * We call its _destroy() method before doing so to notify
550 * the Python user.
551 */
552 py_destroy_method_result = PyObject_CallMethod(py_comp,
553 "_destroy", NULL);
554
555 /*
556 * Ignore any exception raised by the _destroy() method
557 * because it won't change anything at this point: the
558 * component is being destroyed anyway.
559 */
560 PyErr_Clear();
561 Py_XDECREF(py_destroy_method_result);
562 Py_DECREF(py_comp);
563 }
564 }
565
566 static struct bt_value *bt_py3_cc_query(
567 struct bt_component_class *component_class,
568 const char *object, struct bt_value *params)
569 {
570 PyObject *py_cls = NULL;
571 PyObject *py_params = NULL;
572 PyObject *py_query_func = NULL;
573 PyObject *py_object = NULL;
574 PyObject *py_results_addr = NULL;
575 struct bt_value *results = NULL;
576
577 py_cls = lookup_cc_ptr_to_py_cls(component_class);
578 if (!py_cls) {
579 goto error;
580 }
581
582 py_params = bt_py3_bt_value_from_ptr(params);
583 if (!py_params) {
584 goto error;
585 }
586
587 py_object = SWIG_FromCharPtr(object);
588 if (!py_object) {
589 goto error;
590 }
591
592 py_results_addr = PyObject_CallMethod(py_cls,
593 "_query_from_bt", "(OO)", py_object, py_params);
594 if (!py_results_addr) {
595 goto error;
596 }
597
598 /*
599 * The returned object, on success, is an integer object
600 * (PyLong) containing the address of a BT value object
601 * (which is now ours).
602 */
603 results = (struct bt_value *) PyLong_AsUnsignedLongLong(
604 py_results_addr);
605
606 /* Clear potential overflow error; should never happen */
607 if (PyErr_Occurred()) {
608 results = NULL;
609 goto error;
610 }
611
612 if (!results) {
613 goto error;
614 }
615
616 goto end;
617
618 error:
619 BT_PUT(results);
620 PyErr_Clear();
621
622 end:
623 Py_XDECREF(py_params);
624 Py_XDECREF(py_query_func);
625 Py_XDECREF(py_object);
626 Py_XDECREF(py_results_addr);
627 return results;
628 }
629
630 static enum bt_notification_iterator_status bt_py3_exc_to_notif_iter_status(void)
631 {
632 enum bt_notification_iterator_status status =
633 BT_NOTIFICATION_ITERATOR_STATUS_OK;
634 PyObject *exc = PyErr_Occurred();
635
636 if (!exc) {
637 goto end;
638 }
639
640 if (PyErr_GivenExceptionMatches(exc,
641 py_mod_bt2_exc_unsupported_feature_type)) {
642 status = BT_NOTIFICATION_ITERATOR_STATUS_UNSUPPORTED;
643 } else if (PyErr_GivenExceptionMatches(exc,
644 py_mod_bt2_exc_stop_type)) {
645 status = BT_NOTIFICATION_ITERATOR_STATUS_END;
646 } else {
647 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
648 }
649
650 end:
651 PyErr_Clear();
652 return status;
653 }
654
655 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_init(
656 struct bt_component *component,
657 struct bt_notification_iterator *iter, void *init_method_data)
658 {
659 enum bt_notification_iterator_status status =
660 BT_NOTIFICATION_ITERATOR_STATUS_OK;
661 PyObject *py_comp_cls = NULL;
662 PyObject *py_iter_cls = NULL;
663 PyObject *py_iter_ptr = NULL;
664 PyObject *py_init_method_result = NULL;
665 PyObject *py_iter = NULL;
666 PyObject *py_comp = bt_component_get_private_data(component);
667
668 /* Find user's Python notification iterator class */
669 py_comp_cls = PyObject_GetAttrString(py_comp, "__class__");
670 if (!py_comp_cls) {
671 goto error;
672 }
673
674 py_iter_cls = PyObject_GetAttrString(py_comp_cls, "_iter_cls");
675 if (!py_iter_cls) {
676 goto error;
677 }
678
679 /*
680 * Create object with borrowed BT notification iterator
681 * reference:
682 *
683 * py_iter = py_iter_cls.__new__(py_iter_cls, py_iter_ptr)
684 */
685 py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(iter),
686 SWIGTYPE_p_bt_notification_iterator, 0);
687 if (!py_iter_ptr) {
688 goto error;
689 }
690
691 py_iter = PyObject_CallMethod(py_iter_cls, "__new__",
692 "(OO)", py_iter_cls, py_iter_ptr);
693 if (!py_iter) {
694 goto error;
695 }
696
697 /*
698 * Initialize object:
699 *
700 * py_iter.__init__()
701 *
702 * At this point, py_iter._ptr is set, so this initialization
703 * function has access to the py_iter.component property (which
704 * gives it the user Python component object from which the
705 * iterator was created).
706 */
707 py_init_method_result = PyObject_CallMethod(py_iter, "__init__", NULL);
708 if (!py_init_method_result) {
709 goto error;
710 }
711
712 /*
713 * Since the Python code can never instantiate a user-defined
714 * notification iterator class, the BT notification iterator
715 * object does NOT belong to a user Python notification iterator
716 * object (borrowed reference). However this Python object is
717 * owned by this BT notification iterator object.
718 *
719 * In the Python world, the lifetime of the BT notification
720 * iterator is managed by a _GenericNotificationIterator
721 * instance:
722 *
723 * _GenericNotificationIterator instance:
724 * owns a native bt_notification_iterator object (iter)
725 * owns a UserNotificationIterator instance (py_iter)
726 * self._ptr is a borrowed reference to the
727 * native bt_notification_iterator object (iter)
728 */
729 bt_notification_iterator_set_private_data(iter, py_iter);
730 py_iter = NULL;
731 goto end;
732
733 error:
734 status = bt_py3_exc_to_notif_iter_status();
735 if (status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
736 /*
737 * Looks like there wasn't any exception from the Python
738 * side, but we're still in an error state here.
739 */
740 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
741 }
742
743 /*
744 * Clear any exception: we're returning a bad status anyway. If
745 * this call originated from Python, then the user gets an
746 * appropriate creation error.
747 */
748 PyErr_Clear();
749
750 end:
751 Py_XDECREF(py_comp_cls);
752 Py_XDECREF(py_iter_cls);
753 Py_XDECREF(py_iter_ptr);
754 Py_XDECREF(py_init_method_result);
755 Py_XDECREF(py_iter);
756 return status;
757 }
758
759 static void bt_py3_cc_notification_iterator_destroy(
760 struct bt_notification_iterator *iter)
761 {
762 PyObject *py_notif_iter =
763 bt_notification_iterator_get_private_data(iter);
764 PyObject *py_destroy_method_result = NULL;
765
766 assert(py_notif_iter);
767 py_destroy_method_result = PyObject_CallMethod(py_notif_iter,
768 "_destroy", NULL);
769
770 /*
771 * Ignore any exception raised by the _destroy() method because
772 * it won't change anything at this point. The notification
773 * iterator is being destroyed anyway.
774 */
775 PyErr_Clear();
776 Py_XDECREF(py_destroy_method_result);
777 Py_DECREF(py_notif_iter);
778 }
779
780 static struct bt_notification *bt_py3_cc_notification_iterator_get(
781 struct bt_notification_iterator *iter)
782 {
783 PyObject *py_notif_iter =
784 bt_notification_iterator_get_private_data(iter);
785 PyObject *py_get_method_result = NULL;
786 struct bt_notification *notif = NULL;
787
788 assert(py_notif_iter);
789 py_get_method_result = PyObject_CallMethod(py_notif_iter,
790 "_get_from_bt", NULL);
791 if (!py_get_method_result) {
792 goto error;
793 }
794
795 /*
796 * The returned object, on success, is an integer object
797 * (PyLong) containing the address of a BT notification
798 * object (which is now ours).
799 */
800 notif = (struct bt_notification *) PyLong_AsUnsignedLongLong(
801 py_get_method_result);
802
803 /* Clear potential overflow error; should never happen */
804 if (PyErr_Occurred()) {
805 notif = NULL;
806 goto error;
807 }
808
809 if (!notif) {
810 goto error;
811 }
812
813 goto end;
814
815 error:
816 BT_PUT(notif);
817
818 /*
819 * Clear any exception: we're returning NULL anyway. If this
820 * call originated from Python, then the user gets an
821 * appropriate error.
822 */
823 PyErr_Clear();
824
825 end:
826 Py_XDECREF(py_get_method_result);
827 return notif;
828 }
829
830 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_next(
831 struct bt_notification_iterator *iter)
832 {
833 enum bt_notification_iterator_status status;
834 PyObject *py_notif_iter =
835 bt_notification_iterator_get_private_data(iter);
836 PyObject *py_next_method_result = NULL;
837
838 assert(py_notif_iter);
839 py_next_method_result = PyObject_CallMethod(py_notif_iter,
840 "_next", NULL);
841 status = bt_py3_exc_to_notif_iter_status();
842 if (!py_next_method_result
843 && status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
844 /* Pretty sure this should never happen, but just in case */
845 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
846 }
847
848 Py_XDECREF(py_next_method_result);
849 return status;
850 }
851
852 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_seek_time(
853 struct bt_notification_iterator *iter, int64_t time)
854 {
855 enum bt_notification_iterator_status status;
856 PyObject *py_notif_iter =
857 bt_notification_iterator_get_private_data(iter);
858 PyObject *py_seek_to_time_method_result = NULL;
859
860 assert(py_notif_iter);
861 py_seek_to_time_method_result = PyObject_CallMethod(py_notif_iter,
862 "_seek_to_time", "(L)", time);
863 status = bt_py3_exc_to_notif_iter_status();
864 if (!py_seek_to_time_method_result
865 && status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
866 /* Pretty sure this should never happen, but just in case */
867 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
868 }
869
870 Py_XDECREF(py_seek_to_time_method_result);
871 return status;
872 }
873
874 static enum bt_component_status bt_py3_exc_to_component_status(void)
875 {
876 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
877 PyObject *exc = PyErr_Occurred();
878
879 if (!exc) {
880 goto end;
881 }
882
883 if (PyErr_GivenExceptionMatches(exc,
884 py_mod_bt2_exc_unsupported_feature_type)) {
885 status = BT_COMPONENT_STATUS_UNSUPPORTED;
886 } else if (PyErr_GivenExceptionMatches(exc,
887 py_mod_bt2_exc_try_again_type)) {
888 status = BT_COMPONENT_STATUS_AGAIN;
889 } else if (PyErr_GivenExceptionMatches(exc,
890 py_mod_bt2_exc_stop_type)) {
891 status = BT_COMPONENT_STATUS_END;
892 } else {
893 status = BT_COMPONENT_STATUS_ERROR;
894 }
895
896 end:
897 PyErr_Clear();
898 return status;
899 }
900
901 static enum bt_component_status bt_py3_cc_sink_consume(
902 struct bt_component *component)
903 {
904 PyObject *py_comp = bt_component_get_private_data(component);
905 PyObject *py_consume_method_result = NULL;
906 enum bt_component_status status;
907
908 py_consume_method_result = PyObject_CallMethod(py_comp,
909 "_consume", NULL);
910 status = bt_py3_exc_to_component_status();
911 if (!py_consume_method_result && status == BT_COMPONENT_STATUS_OK) {
912 /* Pretty sure this should never happen, but just in case */
913 status = BT_COMPONENT_STATUS_ERROR;
914 }
915
916 Py_XDECREF(py_consume_method_result);
917 return status;
918 }
919
920 static enum bt_component_status bt_py3_cc_sink_filter_add_iterator(
921 struct bt_component *component,
922 struct bt_notification_iterator *iter)
923 {
924 PyObject *py_comp = bt_component_get_private_data(component);
925 PyObject *py_add_iterator_method_result = NULL;
926 PyObject *py_notif_iter_ptr = NULL;
927 enum bt_component_status status;
928
929 py_notif_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(iter),
930 SWIGTYPE_p_bt_notification_iterator, 0);
931 if (!py_notif_iter_ptr) {
932 PyErr_Clear();
933 status = BT_COMPONENT_STATUS_ERROR;
934 goto end;
935 }
936
937 bt_get(iter);
938 py_add_iterator_method_result = PyObject_CallMethod(py_comp,
939 "_add_iterator_from_bt", "(O)", py_notif_iter_ptr);
940 status = bt_py3_exc_to_component_status();
941 if (!py_add_iterator_method_result
942 && status == BT_COMPONENT_STATUS_OK) {
943 /* Pretty sure this should never happen, but just in case */
944 status = BT_COMPONENT_STATUS_ERROR;
945 }
946
947 end:
948 Py_XDECREF(py_notif_iter_ptr);
949 Py_XDECREF(py_add_iterator_method_result);
950 return status;
951 }
952
953
954 /* Component class creation functions (called from Python module) */
955
956 static int bt_py3_cc_set_optional_attrs_methods(struct bt_component_class *cc,
957 const char *description, const char *help)
958 {
959 int ret = 0;
960
961 if (description) {
962 ret = bt_component_class_set_description(cc, description);
963 if (ret) {
964 goto end;
965 }
966 }
967
968 if (help) {
969 ret = bt_component_class_set_help(cc, help);
970 if (ret) {
971 goto end;
972 }
973 }
974
975 ret = bt_component_class_set_init_method(cc, bt_py3_cc_init);
976 if (ret) {
977 goto end;
978 }
979
980 ret = bt_component_class_set_destroy_method(cc, bt_py3_cc_destroy);
981 if (ret) {
982 goto end;
983 }
984
985 ret = bt_component_class_set_query_method(cc, bt_py3_cc_query);
986 if (ret) {
987 goto end;
988 }
989
990 end:
991 return ret;
992 }
993
994 static int bt_py3_cc_set_optional_iter_methods(struct bt_component_class *cc,
995 bool has_seek_time,
996 int (*set_notif_iter_init_method)(struct bt_component_class *, bt_component_class_notification_iterator_init_method),
997 int (*set_notif_iter_destroy_method)(struct bt_component_class *, bt_component_class_notification_iterator_destroy_method),
998 int (*set_notif_iter_seek_time_method)(struct bt_component_class *, bt_component_class_notification_iterator_seek_time_method))
999 {
1000 int ret;
1001
1002 ret = set_notif_iter_init_method(
1003 cc, bt_py3_cc_notification_iterator_init);
1004 if (ret) {
1005 goto end;
1006 }
1007
1008 ret = set_notif_iter_destroy_method(
1009 cc, bt_py3_cc_notification_iterator_destroy);
1010 if (ret) {
1011 goto end;
1012 }
1013
1014 if (has_seek_time) {
1015 ret = set_notif_iter_seek_time_method(
1016 cc, bt_py3_cc_notification_iterator_seek_time);
1017 if (ret) {
1018 goto end;
1019 }
1020 }
1021
1022 end:
1023 return ret;
1024 }
1025
1026 static struct bt_component_class *bt_py3_component_class_source_create(
1027 PyObject *py_cls, const char *name, const char *description,
1028 const char *help, bool has_seek_time)
1029 {
1030 struct bt_component_class *cc;
1031 int ret;
1032
1033 assert(py_cls);
1034 cc = bt_component_class_source_create(name,
1035 bt_py3_cc_notification_iterator_get,
1036 bt_py3_cc_notification_iterator_next);
1037 if (!cc) {
1038 goto end;
1039 }
1040
1041 ret = bt_py3_cc_set_optional_attrs_methods(cc, description, help);
1042 if (ret) {
1043 BT_PUT(cc);
1044 goto end;
1045 }
1046
1047 ret = bt_py3_cc_set_optional_iter_methods(cc, has_seek_time,
1048 bt_component_class_source_set_notification_iterator_init_method,
1049 bt_component_class_source_set_notification_iterator_destroy_method,
1050 bt_component_class_source_set_notification_iterator_seek_time_method);
1051 if (ret) {
1052 BT_PUT(cc);
1053 goto end;
1054 }
1055
1056 register_cc_ptr_to_py_cls(cc, py_cls);
1057 bt_component_class_freeze(cc);
1058
1059 end:
1060 return cc;
1061 }
1062
1063 static struct bt_component_class *bt_py3_component_class_filter_create(
1064 PyObject *py_cls, const char *name, const char *description,
1065 const char *help, bool has_seek_time)
1066 {
1067 struct bt_component_class *cc;
1068 int ret;
1069
1070 assert(py_cls);
1071 cc = bt_component_class_filter_create(name,
1072 bt_py3_cc_notification_iterator_get,
1073 bt_py3_cc_notification_iterator_next);
1074 if (!cc) {
1075 goto end;
1076 }
1077
1078 ret = bt_py3_cc_set_optional_attrs_methods(cc, description, help);
1079 if (ret) {
1080 BT_PUT(cc);
1081 goto end;
1082 }
1083
1084 ret = bt_py3_cc_set_optional_iter_methods(cc, has_seek_time,
1085 bt_component_class_filter_set_notification_iterator_init_method,
1086 bt_component_class_filter_set_notification_iterator_destroy_method,
1087 bt_component_class_filter_set_notification_iterator_seek_time_method);
1088 if (ret) {
1089 BT_PUT(cc);
1090 goto end;
1091 }
1092
1093 ret = bt_component_class_filter_set_add_iterator_method(cc,
1094 bt_py3_cc_sink_filter_add_iterator);
1095 if (ret) {
1096 BT_PUT(cc);
1097 goto end;
1098 }
1099
1100 register_cc_ptr_to_py_cls(cc, py_cls);
1101 bt_component_class_freeze(cc);
1102
1103 end:
1104 return cc;
1105 }
1106
1107 static struct bt_component_class *bt_py3_component_class_sink_create(
1108 PyObject *py_cls, const char *name, const char *description,
1109 const char *help)
1110 {
1111 struct bt_component_class *cc;
1112 int ret;
1113
1114 assert(py_cls);
1115 cc = bt_component_class_sink_create(name, bt_py3_cc_sink_consume);
1116 if (!cc) {
1117 goto end;
1118 }
1119
1120 ret = bt_py3_cc_set_optional_attrs_methods(cc, description, help);
1121 if (ret) {
1122 BT_PUT(cc);
1123 goto end;
1124 }
1125
1126 ret = bt_component_class_sink_set_add_iterator_method(cc,
1127 bt_py3_cc_sink_filter_add_iterator);
1128 if (ret) {
1129 BT_PUT(cc);
1130 goto end;
1131 }
1132
1133 register_cc_ptr_to_py_cls(cc, py_cls);
1134 bt_component_class_freeze(cc);
1135
1136 end:
1137 return cc;
1138 }
1139
1140
1141 /* Component creation function (called from Python module) */
1142
1143 static void bt_py3_component_create(
1144 struct bt_component_class *comp_class, PyObject *py_self,
1145 const char *name)
1146 {
1147 struct bt_component *component =
1148 bt_component_create_with_init_method_data(comp_class,
1149 name, NULL, py_self);
1150
1151 /*
1152 * Our component initialization function, bt_py3_cc_init(), sets
1153 * a new reference to the created component in the user's Python
1154 * object (py_self._ptr). This is where the reference is kept.
1155 * We don't need the returned component in this case (if any,
1156 * because it might be NULL if the creation failed, most
1157 * probably because py_self.__init__() raised something).
1158 */
1159 bt_put(component);
1160 }
1161
1162
1163 /* Component delete notification */
1164
1165 static void bt_py3_component_on_del(PyObject *py_comp)
1166 {
1167 /*
1168 * The Python component's __del__() function calls this to
1169 * indicate that there's no more reference on it from the
1170 * Python world.
1171 *
1172 * Since the BT component can continue to live once the Python
1173 * component object is deleted, we increment the Python
1174 * component's reference count so that it now only belong to the
1175 * BT component. We will decrement this reference count once
1176 * the BT component is destroyed in bt_py3_cc_destroy().
1177 */
1178 assert(py_comp);
1179 Py_INCREF(py_comp);
1180 }
1181 %}
1182
1183 %exception bt_py3_component_create {
1184 $action
1185 if (PyErr_Occurred()) {
1186 /* Exception is already set by bt_py3_component_create() */
1187 SWIG_fail;
1188 }
1189 }
1190
1191 struct bt_component_class *bt_py3_component_class_source_create(
1192 PyObject *py_cls, const char *name, const char *description,
1193 const char *help, bool has_seek_time);
1194 struct bt_component_class *bt_py3_component_class_filter_create(
1195 PyObject *py_cls, const char *name, const char *description,
1196 const char *help, bool has_seek_time);
1197 struct bt_component_class *bt_py3_component_class_sink_create(
1198 PyObject *py_cls, const char *name, const char *description,
1199 const char *help);
1200 void bt_py3_component_create(
1201 struct bt_component_class *comp_class, PyObject *py_self,
1202 const char *name);
1203 void bt_py3_component_on_del(PyObject *py_comp);
1204 void bt_py3_cc_init_from_bt2(void);
1205 void bt_py3_cc_exit_handler(void);
This page took 0.053893 seconds and 5 git commands to generate.