Signed-off-by: Martin Milata mmilata@redhat.com --- python/py_base_stacktrace.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ python/py_base_stacktrace.h | 2 ++ python/py_module.c | 4 ++++ tests/python/gdb.py | 3 +++ tests/python/java.py | 2 ++ tests/python/koops.py | 3 +++ tests/python/python.py | 3 +++ 7 files changed, 73 insertions(+)
diff --git a/python/py_base_stacktrace.c b/python/py_base_stacktrace.c index c729335..5739e3c 100644 --- a/python/py_base_stacktrace.c +++ b/python/py_base_stacktrace.c @@ -31,12 +31,17 @@ "Returns short text representation of the stacktrace. If max_frames is\n" \ "specified, the result includes only that much topmost frames.\n"
+#define get_bthash_doc "Usage: stacktrace.get_bthash([flags])\n" \ + "Returns: string - hash of the stacktrace\n" \ + "flags: integer - bitwise sum of flags (BTHASH_NORMAL, BTHASH_NOHASH)" + #define threads_doc "A list containing the objects representing threads in the stacktrace."
static PyMethodDef single_methods[] = { { "to_short_text", sr_py_single_stacktrace_to_short_text, METH_VARARGS, to_short_text_doc }, + { "get_bthash", sr_py_single_stacktrace_get_bthash, METH_VARARGS, get_bthash_doc }, { NULL }, };
@@ -100,6 +105,7 @@ static PyMethodDef multi_methods[] = { { "to_short_text", sr_py_multi_stacktrace_to_short_text, METH_VARARGS, to_short_text_doc }, + { "get_bthash", sr_py_multi_stacktrace_get_bthash, METH_VARARGS, get_bthash_doc }, { NULL }, };
@@ -291,3 +297,53 @@ sr_py_multi_stacktrace_to_short_text(PyObject *self, PyObject *args) free(text); return result; } + +/* TODO: these two functions (and the two above) are almost the same - there + * should be a way to not repeat the code */ +PyObject * +sr_py_single_stacktrace_get_bthash(PyObject *self, PyObject *args) +{ + int flags = 0; + if (!PyArg_ParseTuple(args, "|i", &flags)) + return NULL; + + struct sr_py_base_thread *this = + (struct sr_py_base_thread *)self; + if (frames_prepare_linked_list(this) < 0) + return NULL; + + char *hash = sr_stacktrace_get_bthash((struct sr_stacktrace *)this->thread, flags); + if (!hash) + { + PyErr_SetString(PyExc_RuntimeError, "cannot obtain bthash"); + return NULL; + } + + PyObject *result = PyString_FromString(hash); + free(hash); + return result; +} + +PyObject * +sr_py_multi_stacktrace_get_bthash(PyObject *self, PyObject *args) +{ + int flags = 0; + if (!PyArg_ParseTuple(args, "|i", &flags)) + return NULL; + + struct sr_py_multi_stacktrace *this = + (struct sr_py_multi_stacktrace *)self; + if (threads_prepare_linked_list(this) < 0) + return NULL; + + char *hash = sr_stacktrace_get_bthash((struct sr_stacktrace *)this->stacktrace, flags); + if (!hash) + { + PyErr_SetString(PyExc_RuntimeError, "cannot obtain bthash"); + return NULL; + } + + PyObject *result = PyString_FromString(hash); + free(hash); + return result; +} diff --git a/python/py_base_stacktrace.h b/python/py_base_stacktrace.h index a0d5e65..6b12fa4 100644 --- a/python/py_base_stacktrace.h +++ b/python/py_base_stacktrace.h @@ -56,6 +56,8 @@ PyObject *threads_to_python_list(struct sr_stacktrace *stacktrace, /* methods */ PyObject *sr_py_single_stacktrace_to_short_text(PyObject *self, PyObject *args); PyObject *sr_py_multi_stacktrace_to_short_text(PyObject *self, PyObject *args); +PyObject *sr_py_single_stacktrace_get_bthash(PyObject *self, PyObject *args); +PyObject *sr_py_multi_stacktrace_get_bthash(PyObject *self, PyObject *args);
#ifdef __cplusplus } diff --git a/python/py_module.c b/python/py_module.c index 8fb77cc..36c4e0f 100644 --- a/python/py_module.c +++ b/python/py_module.c @@ -17,6 +17,7 @@ #include "py_metrics.h"
#include "distance.h" +#include "stacktrace.h" #include "gdb/sharedlib.h"
static PyMethodDef @@ -158,6 +159,9 @@ init_satyr() PyModule_AddObject(module, "MultiThreadStacktrace", (PyObject *)&sr_py_multi_stacktrace_type);
+ PyModule_AddIntConstant(module, "BTHASH_NORMAL", SR_BTHASH_NORMAL); + PyModule_AddIntConstant(module, "BTHASH_NOHASH", SR_BTHASH_NOHASH); + Py_INCREF(&sr_py_gdb_frame_type); PyModule_AddObject(module, "GdbFrame", (PyObject *)&sr_py_gdb_frame_type); diff --git a/tests/python/gdb.py b/tests/python/gdb.py index 6e57c17..06565b4 100755 --- a/tests/python/gdb.py +++ b/tests/python/gdb.py @@ -61,6 +61,9 @@ class TestGdbStacktrace(BindingsTestCase): def test_to_short_text(self): self.assertEqual(self.trace.to_short_text(5), expected_short_text)
+ def test_bthash(self): + self.assertEqual(self.trace.get_bthash(), 'd0fcdc87161ccb093f7efeff12218321d8fd5298') + class TestGdbThread(BindingsTestCase): def setUp(self): self.thread = satyr.GdbStacktrace(contents).threads[0] diff --git a/tests/python/java.py b/tests/python/java.py index 1c7fc5f..dfd5eb0 100755 --- a/tests/python/java.py +++ b/tests/python/java.py @@ -57,6 +57,8 @@ class TestJavaStacktrace(BindingsTestCase): def test_to_short_text(self): self.assertEqual(self.trace.to_short_text(8), expected_short_text)
+ def test_bthash(self): + self.assertEqual(self.trace.get_bthash(), '184370433901aa9f14bfc85c29576e24ebca2c2e')
class TestJavaThread(BindingsTestCase): def setUp(self): diff --git a/tests/python/koops.py b/tests/python/koops.py index 81e67b9..10cba82 100755 --- a/tests/python/koops.py +++ b/tests/python/koops.py @@ -67,6 +67,9 @@ class TestKerneloops(BindingsTestCase): def test_to_short_text(self): self.assertEqual(self.koops.to_short_text(7), expected_short_text)
+ def test_bthash(self): + self.assertEqual(self.koops.get_bthash(), '73c7ce83d5ba90a1acbcc7915a62595914321f97') + class TestKoopsFrame(BindingsTestCase): def setUp(self): self.frame = satyr.Kerneloops(contents).frames[0] diff --git a/tests/python/python.py b/tests/python/python.py index 1ae36eb..0421935 100755 --- a/tests/python/python.py +++ b/tests/python/python.py @@ -84,6 +84,9 @@ class TestPythonStacktrace(BindingsTestCase): def test_to_short_text(self): self.assertEqual(self.trace.to_short_text(6), expected_short_text)
+ def test_bthash(self): + self.assertEqual(self.trace.get_bthash(), 'fa0a7ff4b65f18661a6ce102eb787ff0d77ff12f') + class TestPythonFrame(BindingsTestCase): def setUp(self): self.frame = satyr.PythonStacktrace(contents).frames[-1]