diff mbox series

[4/5] trace-cruncher: Add APIs for histogram control

Message ID 20211207142811.398929-5-y.karadz@gmail.com (mailing list archive)
State Accepted
Headers show
Series trace-cruncher: Kernel histograms | expand

Commit Message

Yordan Karadzhov Dec. 7, 2021, 2:28 p.m. UTC
This is an almost direct wrapping of the corresponding APIs defined in
libtracefs. The 'continue' API (tracefs_hist_continue()) gets renamed
to resume(), because 'continue' is a keyword in Python.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 src/ftracepy-utils.c | 202 ++++++++++++++++++++++++++++++++++---------
 src/ftracepy-utils.h |  18 ++++
 src/ftracepy.c       |  30 +++++++
 3 files changed, 207 insertions(+), 43 deletions(-)
diff mbox series

Patch

diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index d7e6d6a..a735d88 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -836,6 +836,165 @@  PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
 	Py_RETURN_NONE;
 }
 
+static bool get_optional_instance(PyObject *py_obj,
+				  struct tracefs_instance **instance)
+{
+	PyTfsInstance *py_inst;
+
+	if (!py_obj) {
+		*instance = NULL;
+		return true;
+	}
+
+	if (!PyTfsInstance_Check(py_obj)) {
+		PyErr_SetString(TRACECRUNCHER_ERROR,
+				"Passing argument \'instance\' with incompatible type.");
+		return false;
+	}
+
+	py_inst = (PyTfsInstance *)py_obj;
+	*instance = py_inst->ptrObj;
+
+	return true;
+}
+
+bool get_instance_from_arg(PyObject *args, PyObject *kwargs,
+			   struct tracefs_instance **instance)
+{
+	static char *kwlist[] = {"instance", NULL};
+	PyObject *py_inst = NULL;
+	*instance = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "|O",
+					 kwlist,
+					 &py_inst)) {
+		return false;
+	}
+
+	if (!get_optional_instance(py_inst, instance))
+		return NULL;
+
+	return true;
+}
+
+static bool hist_cmd(PyTraceHist *self, PyObject *args, PyObject *kwargs,
+		     enum tracefs_hist_command cmd,
+		     const char *err_msg)
+{
+	struct tracefs_instance *instance;
+
+	if (!get_instance_from_arg(args, kwargs, &instance))
+		return NULL;
+
+	if (tracefs_hist_command(instance, self->ptrObj, cmd) < 0) {
+		char *buff;
+
+		if (asprintf(&buff, "%s %s",
+			     err_msg, get_hist_name(self->ptrObj)) <= 0) {
+			MEM_ERROR;
+			return false;
+		}
+
+		TfsError_setstr(instance, buff);
+		free(buff);
+
+		return false;
+	}
+
+	return true;
+}
+
+PyObject *PyTraceHist_start(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs)
+{
+	if (!hist_cmd(self, args, kwargs,
+		      TRACEFS_HIST_CMD_START,
+		      "Failed to start filling the histogram"))
+		return false;
+
+	Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_stop(PyTraceHist *self, PyObject *args,
+					      PyObject *kwargs)
+{
+	if (!hist_cmd(self, args, kwargs,
+		      TRACEFS_HIST_CMD_PAUSE,
+		      "Failed to stop filling the histogram"))
+		return false;
+
+	Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_resume(PyTraceHist *self, PyObject *args,
+						PyObject *kwargs)
+{
+	if (!hist_cmd(self, args, kwargs,
+		      TRACEFS_HIST_CMD_CONT,
+		      "Failed to resume filling the histogram"))
+		return false;
+
+	Py_RETURN_NONE;
+}
+
+PyObject *PyTraceHist_clear(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs)
+{
+	if (!hist_cmd(self, args, kwargs,
+		      TRACEFS_HIST_CMD_CLEAR,
+		      "Failed to clear the histogram"))
+		return false;
+
+	Py_RETURN_NONE;
+}
+
+static char *hist_read(PyTraceHist *self, PyObject *args,
+					  PyObject *kwargs)
+{
+	struct tracefs_instance *instance;
+	const char *hist_file = "hist";
+	char *data;
+
+	if (!get_instance_from_arg(args, kwargs, &instance))
+		return NULL;
+
+	data = tracefs_event_file_read(instance,
+				       tracefs_hist_get_system(self->ptrObj),
+				       tracefs_hist_get_event(self->ptrObj),
+				       hist_file,
+				       NULL);
+	if (!data) {
+		TfsError_fmt(instance,
+			     "Failed read data from histogram \'%s\'.",
+			     get_hist_name(self->ptrObj));
+	}
+
+	return data;
+}
+
+PyObject *PyTraceHist_read(PyTraceHist *self, PyObject *args,
+					      PyObject *kwargs)
+{
+	char *data = hist_read(self, args, kwargs);
+	PyObject *ret = PyUnicode_FromString(data);
+
+	free(data);
+	return ret;
+}
+
+PyObject *PyTraceHist_close(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs)
+{
+	if (!hist_cmd(self, args, kwargs,
+		      TRACEFS_HIST_CMD_DESTROY,
+		      "Failed to close the histogram"))
+		return false;
+
+	Py_RETURN_NONE;
+}
+
 PyObject *PyFtrace_dir(PyObject *self)
 {
 	return PyUnicode_FromString(tracefs_tracing_dir());
@@ -967,49 +1126,6 @@  PyObject *PyFtrace_find_instance(PyObject *self, PyObject *args,
 	return py_inst;
 }
 
-static bool get_optional_instance(PyObject *py_obj,
-				  struct tracefs_instance **instance)
-{
-	PyTfsInstance *py_inst;
-
-	if (!py_obj) {
-		*instance = NULL;
-		return true;
-	}
-
-	if (!PyTfsInstance_Check(py_obj)) {
-		PyErr_SetString(TRACECRUNCHER_ERROR,
-				"Passing argument \'instance\' with incompatible type.");
-		return false;
-	}
-
-	py_inst = (PyTfsInstance *)py_obj;
-	*instance = py_inst->ptrObj;
-
-	return true;
-}
-
-bool get_instance_from_arg(PyObject *args, PyObject *kwargs,
-			   struct tracefs_instance **instance)
-{
-	static char *kwlist[] = {"instance", NULL};
-	PyObject *py_inst = NULL;
-	*instance = NULL;
-
-	if (!PyArg_ParseTupleAndKeywords(args,
-					 kwargs,
-					 "|O",
-					 kwlist,
-					 &py_inst)) {
-		return false;
-	}
-
-	if (!get_optional_instance(py_inst, instance))
-		return NULL;
-
-	return true;
-}
-
 PyObject *PyFtrace_available_tracers(PyObject *self, PyObject *args,
 						     PyObject *kwargs)
 {
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index 07d2cac..d09c8bf 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -101,6 +101,24 @@  PyObject *PyTraceHist_sort_keys(PyTraceHist *self, PyObject *args,
 PyObject *PyTraceHist_sort_key_direction(PyTraceHist *self, PyObject *args,
 							    PyObject *kwargs);
 
+PyObject *PyTraceHist_start(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs);
+
+PyObject *PyTraceHist_stop(PyTraceHist *self, PyObject *args,
+					      PyObject *kwargs);
+
+PyObject *PyTraceHist_resume(PyTraceHist *self, PyObject *args,
+						PyObject *kwargs);
+
+PyObject *PyTraceHist_clear(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs);
+
+PyObject *PyTraceHist_read(PyTraceHist *self, PyObject *args,
+					      PyObject *kwargs);
+
+PyObject *PyTraceHist_close(PyTraceHist *self, PyObject *args,
+					       PyObject *kwargs);
+
 PyObject *PyFtrace_dir(PyObject *self);
 
 PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs);
diff --git a/src/ftracepy.c b/src/ftracepy.c
index b91cda9..b270b71 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -184,6 +184,36 @@  static PyMethodDef PyTraceHist_methods[] = {
 	 METH_VARARGS | METH_KEYWORDS,
 	 "Set the direction of a sort key field."
 	},
+	{"start",
+	 (PyCFunction) PyTraceHist_start,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Start acquiring data."
+	},
+	{"stop",
+	 (PyCFunction) PyTraceHist_stop,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Pause acquiring data."
+	},
+	{"resume",
+	 (PyCFunction) PyTraceHist_resume,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Continue acquiring data."
+	},
+	{"clear",
+	 (PyCFunction) PyTraceHist_clear,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Reset the histogram."
+	},
+	{"read",
+	 (PyCFunction) PyTraceHist_read,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Read the content of the histogram."
+	},
+	{"close",
+	 (PyCFunction) PyTraceHist_close,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Destroy the histogram."
+	},
 	{NULL, NULL, 0, NULL}
 };