[SATYR PATCH 9/9] python: bindings for duphash
Martin Milata
mmilata at redhat.com
Wed Jun 26 20:14:13 UTC 2013
Closes #66.
Signed-off-by: Martin Milata <mmilata at redhat.com>
---
python/py_base_thread.c | 39 ++++++++++++++++++++++++++++++++++++++-
python/py_base_thread.h | 1 +
python/py_module.c | 5 +++++
tests/python/gdb.py | 5 +++++
tests/python/java.py | 9 +++++++++
tests/python/koops.py | 5 +++++
tests/python/python.py | 9 +++++++++
7 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/python/py_base_thread.c b/python/py_base_thread.c
index 8053878..5bbbade 100644
--- a/python/py_base_thread.c
+++ b/python/py_base_thread.c
@@ -34,11 +34,19 @@
" DISTANCE_JACCARD or DISTANCE_DAMERAU_LEVENSHTEIN\n"\
"Returns: positive float - distance between the two threads"
+#define get_duphash_doc "Usage: thread.get_duphash(frames=0, flags=DUPHASH_NORMAL, prefix='')\n"\
+ "Returns: string - thread's duplication hash\n"\
+ "frames: integer - number of frames to use (default 0 means use all)\n"\
+ "flags: integer - bitwise sum of flags (DUPHASH_NORMAL, DUPHASH_NOHASH,\n"\
+ " DUPHASH_NONORMALIZE)\n"\
+ "prefix: string - string to be prepended in front of the text before hashing"
+
static PyMethodDef
thread_methods[] =
{
/* methods */
- { "distance", (PyCFunction)sr_py_base_thread_distance, METH_VARARGS|METH_KEYWORDS, distance_doc },
+ { "distance", (PyCFunction)sr_py_base_thread_distance, METH_VARARGS|METH_KEYWORDS, distance_doc },
+ { "get_duphash", (PyCFunction)sr_py_base_thread_get_duphash, METH_VARARGS|METH_KEYWORDS, get_duphash_doc },
{ NULL },
};
@@ -242,3 +250,32 @@ sr_py_base_thread_distance(PyObject *self, PyObject *args, PyObject *kwds)
float dist = sr_distance(dist_type, t1->thread, t2->thread);
return PyFloat_FromDouble((double)dist);
}
+
+PyObject *
+sr_py_base_thread_get_duphash(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ const char *prefix = NULL;
+ int frames = 0, flags = 0;
+
+ static const char *kwlist[] = { "frames", "flags", "prefix", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iis", (char **)kwlist,
+ &frames, &flags, &prefix))
+ 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_thread_get_duphash((struct sr_thread *)this->thread,
+ frames, (char *)prefix, flags);
+ if (!hash)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "cannot obtain duphash");
+ return NULL;
+ }
+
+ PyObject *result = PyString_FromString(hash);
+ free(hash);
+ return result;
+}
diff --git a/python/py_base_thread.h b/python/py_base_thread.h
index 663555c..e9f1af7 100644
--- a/python/py_base_thread.h
+++ b/python/py_base_thread.h
@@ -51,6 +51,7 @@ int sr_py_base_thread_cmp(struct sr_py_base_thread *self, struct sr_py_base_thre
/* methods */
PyObject *sr_py_base_thread_distance(PyObject *self, PyObject *args, PyObject *kwds);
+PyObject *sr_py_base_thread_get_duphash(PyObject *self, PyObject *args, PyObject *kwds);
#ifdef __cplusplus
}
diff --git a/python/py_module.c b/python/py_module.c
index 36c4e0f..f049a03 100644
--- a/python/py_module.c
+++ b/python/py_module.c
@@ -17,6 +17,7 @@
#include "py_metrics.h"
#include "distance.h"
+#include "thread.h"
#include "stacktrace.h"
#include "gdb/sharedlib.h"
@@ -151,6 +152,10 @@ init_satyr()
PyModule_AddObject(module, "BaseThread",
(PyObject *)&sr_py_base_thread_type);
+ PyModule_AddIntConstant(module, "DUPHASH_NORMAL", SR_DUPHASH_NORMAL);
+ PyModule_AddIntConstant(module, "DUPHASH_NOHASH", SR_DUPHASH_NOHASH);
+ PyModule_AddIntConstant(module, "DUPHASH_NONORMALIZE", SR_DUPHASH_NONORMALIZE);
+
Py_INCREF(&sr_py_single_stacktrace_type);
PyModule_AddObject(module, "SingleThreadStacktrace",
(PyObject *)&sr_py_single_stacktrace_type);
diff --git a/tests/python/gdb.py b/tests/python/gdb.py
index 06565b4..2752771 100755
--- a/tests/python/gdb.py
+++ b/tests/python/gdb.py
@@ -78,6 +78,11 @@ class TestGdbThread(BindingsTestCase):
dup.number = 9000
self.assertNotEqual(self.thread, dup)
+ def test_duphash(self):
+ expected_plain = 'Thread\n write\n virNetSocketWriteWire\n virNetSocketWrite\n'
+ self.assertEqual(self.thread.get_duphash(flags=satyr.DUPHASH_NOHASH, frames=3), expected_plain)
+ self.assertEqual(self.thread.get_duphash(), '4ff2e92d89425e18e82b94c214c7ccfec8b31793')
+
class TestGdbSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.GdbStacktrace(contents).libs[0]
diff --git a/tests/python/java.py b/tests/python/java.py
index dfd5eb0..eaa3d48 100755
--- a/tests/python/java.py
+++ b/tests/python/java.py
@@ -74,6 +74,15 @@ class TestJavaThread(BindingsTestCase):
dup.name = ' 45678987\n\n\n\n'
self.assertNotEqual(self.thread, dup)
+ def test_duphash(self):
+ expected_plain = '''Thread
+org.hibernate.exception.ConstraintViolationException
+org.hibernate.exception.SQLStateConverter.convert
+org.hibernate.exception.JDBCExceptionHelper.convert
+'''
+ self.assertEqual(self.thread.get_duphash(flags=satyr.DUPHASH_NOHASH, frames=3), expected_plain)
+ self.assertEqual(self.thread.get_duphash(), '81450a80a9d9307624b08e80dc244beb63d91138')
+
class TestJavaSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.JavaStacktrace(contents).libs[0]
diff --git a/tests/python/koops.py b/tests/python/koops.py
index 10cba82..f1de360 100755
--- a/tests/python/koops.py
+++ b/tests/python/koops.py
@@ -70,6 +70,11 @@ class TestKerneloops(BindingsTestCase):
def test_bthash(self):
self.assertEqual(self.koops.get_bthash(), '73c7ce83d5ba90a1acbcc7915a62595914321f97')
+ def test_duphash(self):
+ expected_plain = 'Thread\n__alloc_pages_nodemask\nip_copy_metadata\nip_forward_options\n'
+ self.assertEqual(self.koops.get_duphash(flags=satyr.DUPHASH_NOHASH, frames=3), expected_plain)
+ self.assertEqual(self.koops.get_duphash(), '53f62f9d6f7de093f50653863d200f4789ace7ef')
+
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 0421935..1fcd49d 100755
--- a/tests/python/python.py
+++ b/tests/python/python.py
@@ -87,6 +87,15 @@ class TestPythonStacktrace(BindingsTestCase):
def test_bthash(self):
self.assertEqual(self.trace.get_bthash(), 'fa0a7ff4b65f18661a6ce102eb787ff0d77ff12f')
+ def test_duphash(self):
+ expected_plain = '''Thread
+/usr/share/PackageKit/helpers/yum/yumBackend.py:2534
+/usr/share/PackageKit/helpers/yum/yumBackend.py:2593
+/usr/share/PackageKit/helpers/yum/yumBackend.py:2551
+'''
+ self.assertEqual(self.trace.get_duphash(flags=satyr.DUPHASH_NOHASH, frames=3), expected_plain)
+ self.assertEqual(self.trace.get_duphash(), '2c8e509a33966a08df1dd8b2348e850d1bc5b776')
+
class TestPythonFrame(BindingsTestCase):
def setUp(self):
self.frame = satyr.PythonStacktrace(contents).frames[-1]
--
1.7.11.7
More information about the Crash-catcher
mailing list