|
|
ca33c4 |
From 517a37ae7beeb77e2b4870be11611f82c1200b3c Mon Sep 17 00:00:00 2001
|
|
|
ca33c4 |
From: Matthew Almond <malmond@fb.com>
|
|
|
ca33c4 |
Date: Thu, 11 Jun 2020 13:01:04 -0700
|
|
|
ca33c4 |
Subject: [PATCH 2/2] Measure plugin
|
|
|
ca33c4 |
|
|
|
ca33c4 |
---
|
|
|
ca33c4 |
macros.in | 1 +
|
|
|
ca33c4 |
plugins/Makefile.am | 4 +
|
|
|
ca33c4 |
plugins/measure.c | 231 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
ca33c4 |
3 files changed, 236 insertions(+)
|
|
|
ca33c4 |
create mode 100644 plugins/measure.c
|
|
|
ca33c4 |
|
|
|
ca33c4 |
diff --git a/macros.in b/macros.in
|
|
|
ca33c4 |
index 3cc8a3555..c8a087959 100644
|
|
|
ca33c4 |
--- a/macros.in
|
|
|
ca33c4 |
+++ b/macros.in
|
|
|
ca33c4 |
@@ -1173,6 +1173,7 @@ package or when debugging this package.\
|
|
|
ca33c4 |
# Transaction plugin macros
|
|
|
ca33c4 |
%__plugindir %{_libdir}/rpm-plugins
|
|
|
ca33c4 |
%__transaction_reflink %{__plugindir}/reflink.so
|
|
|
ca33c4 |
+%__transaction_measure %{__plugindir}/measure.so
|
|
|
ca33c4 |
%__transaction_systemd_inhibit %{__plugindir}/systemd_inhibit.so
|
|
|
ca33c4 |
%__transaction_selinux %{__plugindir}/selinux.so
|
|
|
ca33c4 |
%__transaction_syslog %{__plugindir}/syslog.so
|
|
|
ca33c4 |
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
|
|
|
ca33c4 |
index 06393ce8d..daed6423c 100644
|
|
|
ca33c4 |
--- a/plugins/Makefile.am
|
|
|
ca33c4 |
+++ b/plugins/Makefile.am
|
|
|
ca33c4 |
@@ -29,6 +29,10 @@ systemd_inhibit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/
|
|
|
ca33c4 |
plugins_LTLIBRARIES += systemd_inhibit.la
|
|
|
ca33c4 |
endif
|
|
|
ca33c4 |
|
|
|
ca33c4 |
+measure_la_SOURCES = measure.c
|
|
|
ca33c4 |
+measure_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
|
|
|
ca33c4 |
+plugins_LTLIBRARIES += measure.la
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
prioreset_la_SOURCES = prioreset.c
|
|
|
ca33c4 |
prioreset_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
|
|
|
ca33c4 |
plugins_LTLIBRARIES += prioreset.la
|
|
|
ca33c4 |
diff --git a/plugins/measure.c b/plugins/measure.c
|
|
|
ca33c4 |
new file mode 100644
|
|
|
ca33c4 |
index 000000000..2cdfc885e
|
|
|
ca33c4 |
--- /dev/null
|
|
|
ca33c4 |
+++ b/plugins/measure.c
|
|
|
ca33c4 |
@@ -0,0 +1,231 @@
|
|
|
ca33c4 |
+#include "system.h"
|
|
|
ca33c4 |
+#include "time.h"
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+#include <rpm/rpmlog.h>
|
|
|
ca33c4 |
+#include <rpm/rpmmacro.h>
|
|
|
ca33c4 |
+#include <rpm/rpmts.h>
|
|
|
ca33c4 |
+#include "lib/rpmlib.h"
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+#include "lib/rpmplugin.h"
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+struct measurestat {
|
|
|
ca33c4 |
+ /* We're counting psm not packages because packages often run psm_pre/post
|
|
|
ca33c4 |
+ more than once and we want to accumulate the time
|
|
|
ca33c4 |
+ */
|
|
|
ca33c4 |
+ unsigned int psm_count;
|
|
|
ca33c4 |
+ unsigned int scriptlet_count;
|
|
|
ca33c4 |
+ struct timespec plugin_start;
|
|
|
ca33c4 |
+ struct timespec psm_start;
|
|
|
ca33c4 |
+ struct timespec scriptlet_start;
|
|
|
ca33c4 |
+};
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC push(const char *format, const char *value, const char *formatted)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ char *key = NULL;
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+ if (formatted == NULL) {
|
|
|
ca33c4 |
+ /* yes we're okay with discarding const here */
|
|
|
ca33c4 |
+ key = (char *)format;
|
|
|
ca33c4 |
+ } else {
|
|
|
ca33c4 |
+ if (rasprintf(&key, format, formatted) == -1) {
|
|
|
ca33c4 |
+ rpmlog(
|
|
|
ca33c4 |
+ RPMLOG_ERR,
|
|
|
ca33c4 |
+ _("measure: Failed to allocate formatted key %s, %s\n"),
|
|
|
ca33c4 |
+ format,
|
|
|
ca33c4 |
+ formatted
|
|
|
ca33c4 |
+ );
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (rpmPushMacro(NULL, key, NULL, value, RMIL_GLOBAL)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to set %s\n"), key);
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ if (formatted != NULL) {
|
|
|
ca33c4 |
+ free(key);
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC diff_ms(char **ms, struct timespec *start, struct timespec *end)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ if (rasprintf(ms, "%ld", (
|
|
|
ca33c4 |
+ (end->tv_sec - start->tv_sec) * 1000 +
|
|
|
ca33c4 |
+ (end->tv_nsec - start->tv_nsec) / 1000000
|
|
|
ca33c4 |
+ )) == -1) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to allocate formatted ms\n"));
|
|
|
ca33c4 |
+ return RPMRC_FAIL;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ return RPMRC_OK;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_init(rpmPlugin plugin, rpmts ts)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+ struct measurestat *state = rcalloc(1, sizeof(*state));
|
|
|
ca33c4 |
+ if (clock_gettime(CLOCK_MONOTONIC, &state->plugin_start)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to get plugin_start time\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ state->psm_count = 0;
|
|
|
ca33c4 |
+ state->scriptlet_count = 0;
|
|
|
ca33c4 |
+ rpmPluginSetData(plugin, state);
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static void measure_cleanup(rpmPlugin plugin)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ free(state);
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_tsm_post(rpmPlugin plugin, rpmts ts, int res)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ char *psm_count = NULL, *scriptlet_count = NULL;
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+ if (rasprintf(&psm_count, "%d", state->psm_count) == -1) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to allocate formatted psm_count\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (rasprintf(&scriptlet_count, "%d", state->scriptlet_count) == -1) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to allocate formatted scriptlet_count\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("_measure_plugin_psm_count", psm_count, NULL) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("_measure_plugin_scriptlet_count", scriptlet_count, NULL) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ free(psm_count);
|
|
|
ca33c4 |
+ free(scriptlet_count);
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_psm_pre(rpmPlugin plugin, rpmte te)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+ if (clock_gettime(CLOCK_MONOTONIC, &state->psm_start)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to get psm_start time\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_psm_post(rpmPlugin plugin, rpmte te, int res)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ struct timespec end;
|
|
|
ca33c4 |
+ char *offset = NULL, *duration = NULL, *prefix = NULL;
|
|
|
ca33c4 |
+ Header h = rpmteHeader(te);
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+ if (clock_gettime(CLOCK_MONOTONIC, &end)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to get psm end time\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (rasprintf(&prefix, "_measure_plugin_package_%u", state->psm_count) == -1) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to allocate prefix\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (diff_ms(&offset, &state->plugin_start, &state->psm_start) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (diff_ms(&duration, &state->psm_start, &end) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_nevra", rpmteNEVRA(te), prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_compressor", headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR), prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_offset", offset, prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_ms", duration, prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ state->psm_count += 1;
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ headerFree(h);
|
|
|
ca33c4 |
+ free(prefix);
|
|
|
ca33c4 |
+ free(duration);
|
|
|
ca33c4 |
+ free(offset);
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_scriptlet_pre(rpmPlugin plugin,
|
|
|
ca33c4 |
+ const char *s_name, int type)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ if (clock_gettime(CLOCK_MONOTONIC, &state->scriptlet_start)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to get scriptlet_start time\n"));
|
|
|
ca33c4 |
+ return RPMRC_FAIL;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ return RPMRC_OK;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+static rpmRC measure_scriptlet_post(rpmPlugin plugin,
|
|
|
ca33c4 |
+ const char *s_name, int type, int res)
|
|
|
ca33c4 |
+{
|
|
|
ca33c4 |
+ struct measurestat *state = rpmPluginGetData(plugin);
|
|
|
ca33c4 |
+ struct timespec end;
|
|
|
ca33c4 |
+ char *offset = NULL, *duration = NULL, *prefix = NULL;
|
|
|
ca33c4 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+ if (clock_gettime(CLOCK_MONOTONIC, &end)) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to get end time\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+ if (rasprintf(&prefix, "_measure_plugin_scriptlet_%d", state->scriptlet_count) == -1) {
|
|
|
ca33c4 |
+ rpmlog(RPMLOG_ERR, _("measure: Failed to allocate formatted prefix\n"));
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (diff_ms(&offset, &state->plugin_start, &state->scriptlet_start) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (diff_ms(&duration, &state->scriptlet_start, &end) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_name", s_name, prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_offset", offset, prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ if (push("%s_ms", duration, prefix) != RPMRC_OK) {
|
|
|
ca33c4 |
+ goto exit;
|
|
|
ca33c4 |
+ }
|
|
|
ca33c4 |
+ state->scriptlet_count += 1;
|
|
|
ca33c4 |
+ rc = RPMRC_OK;
|
|
|
ca33c4 |
+exit:
|
|
|
ca33c4 |
+ free(prefix);
|
|
|
ca33c4 |
+ free(duration);
|
|
|
ca33c4 |
+ free(offset);
|
|
|
ca33c4 |
+ return rc;
|
|
|
ca33c4 |
+}
|
|
|
ca33c4 |
+
|
|
|
ca33c4 |
+struct rpmPluginHooks_s measure_hooks = {
|
|
|
ca33c4 |
+ .init = measure_init,
|
|
|
ca33c4 |
+ .cleanup = measure_cleanup,
|
|
|
ca33c4 |
+ .tsm_post = measure_tsm_post,
|
|
|
ca33c4 |
+ .psm_pre = measure_psm_pre,
|
|
|
ca33c4 |
+ .psm_post = measure_psm_post,
|
|
|
ca33c4 |
+ .scriptlet_pre = measure_scriptlet_pre,
|
|
|
ca33c4 |
+ .scriptlet_post = measure_scriptlet_post,
|
|
|
ca33c4 |
+};
|
|
|
ca33c4 |
--
|
|
|
ca33c4 |
2.24.1
|
|
|
ca33c4 |
|