Add a per-handle identifier. The main effect of this is to change
trace output from:
libguestfs: trace: foo
to:
libguestfs: trace: ID: foo
which makes it simpler to follow traces from multi-threaded programs.
---
generator/actions.ml | 43 +++++++++++++++++++++++++++++++++++++++++++
src/events.c | 10 ++++++++--
src/guestfs-internal.h | 1 +
src/handle.c | 32 ++++++++++++++++++++++++++++++++
src/launch.c | 5 +++++
5 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/generator/actions.ml b/generator/actions.ml
index c1755b9..ae4bb0c 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -3369,6 +3369,49 @@ To download to the current directory, use C<.> as in:
Wildcards cannot be used." };
+ { defaults with
+ name = "set_identifier"; added = (1, 31, 14);
+ style = RErr, [String "identifier"], [];
+ fish_alias = ["identifier"];
+ blocking = false;
+ shortdesc = "set the handle identifier";
+ longdesc = "\
+This is an informative string which the caller may optionally
+set in the handle. It is printed in various places, allowing
+the current handle to be identified in debugging output.
+
+One important place is when tracing is enabled. If the
+identifier string is not an empty string, then trace messages
+change from this:
+
+ libguestfs: trace: get_tmpdir
+ libguestfs: trace: get_tmpdir = \"/tmp\"
+
+to this:
+
+ libguestfs: trace: ID: get_tmpdir
+ libguestfs: trace: ID: get_tmpdir = \"/tmp\"
+
+where C<ID> is the identifier string set by this call.
+
+The identifier must only contain alphanumeric ASCII characters,
+underscore and minus sign. The default is the empty string.
+
+See also C<guestfs_set_program>, C<guestfs_set_trace>,
+C<guestfs_get_identifier>" };
+
+ { defaults with
+ name = "get_identifier"; added = (1, 31, 14);
+ style = RConstString "identifier", [], [];
+ blocking = false;
+ tests = [
+ InitNone, Always, TestRun (
+ [["get_identifier"]]), []
+ ];
+ shortdesc = "get the handle identifier";
+ longdesc = "\
+Get the handle identifier. See C<guestfs_set_identifier>." };
+
]
(* daemon_functions are any functions which cause some action
diff --git a/src/events.c b/src/events.c
index d5efefe..5fed0c0 100644
--- a/src/events.c
+++ b/src/events.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <assert.h>
#include "c-ctype.h"
@@ -136,7 +137,7 @@ guestfs_int_call_callbacks_message (guestfs_h *g, uint64_t event,
/* APPLIANCE => <buf>
* LIBRARY => libguestfs: <buf>\n
* WARNING => libguestfs: warning: <buf>\n
- * TRACE => libguestfs: trace: <buf>\n (RHBZ#673479)
+ * TRACE => libguestfs: trace: [<ID>:] <buf>\n (RHBZ#673479)
*/
if (event != GUESTFS_EVENT_APPLIANCE)
@@ -145,8 +146,13 @@ guestfs_int_call_callbacks_message (guestfs_h *g, uint64_t event,
if (event == GUESTFS_EVENT_WARNING)
fputs ("warning: ", stderr);
- if (event == GUESTFS_EVENT_TRACE)
+ if (event == GUESTFS_EVENT_TRACE) {
fputs ("trace: ", stderr);
+ if (STRNEQ (g->identifier, "")) {
+ fputs (g->identifier, stderr);
+ fputs (": ", stderr);
+ }
+ }
/* Special or non-printing characters in the buffer must be
* escaped (RHBZ#731744). The buffer can contain any 8 bit
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 72f9968..34b5f1d 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -371,6 +371,7 @@ struct guestfs_h
struct hv_param *hv_params; /* Extra hv parameters. */
char *program; /* Program name. */
+ char *identifier; /* Handle identifier. */
/* Array of drives added by add-drive* APIs.
*
diff --git a/src/handle.c b/src/handle.c
index e2d0aa3..ff109ea 100644
--- a/src/handle.c
+++ b/src/handle.c
@@ -32,6 +32,7 @@
#include "glthread/lock.h"
#include "ignore-value.h"
+#include "c-ctype.h"
#include "guestfs.h"
#include "guestfs-internal.h"
@@ -128,6 +129,9 @@ guestfs_create_flags (unsigned flags, ...)
#endif
if (!g->program) goto error;
+ g->identifier = strdup ("");
+ if (!g->identifier) goto error;
+
if (guestfs_int_set_backend (g, DEFAULT_BACKEND) == -1) {
warning (g, _("libguestfs was built with an invalid default backend, using
'direct' instead"));
if (guestfs_int_set_backend (g, "direct") == -1) {
@@ -667,6 +671,34 @@ guestfs_impl_get_program (guestfs_h *g)
}
int
+guestfs_impl_set_identifier (guestfs_h *g, const char *identifier)
+{
+ size_t i, len;
+
+ /* Check the identifier contains only permitted characters. */
+ len = strlen (identifier);
+ for (i = 0; i < len; ++i) {
+ char c = identifier[i];
+
+ if (!c_isalnum (c) && c != '_' && c != '-') {
+ error (g, _("identifier must contain only alphanumeric characters, underscore
or minus sign"));
+ return -1;
+ }
+ }
+
+ free (g->identifier);
+ g->identifier = safe_strdup (g, identifier);
+
+ return 0;
+}
+
+const char *
+guestfs_impl_get_identifier (guestfs_h *g)
+{
+ return g->identifier;
+}
+
+int
guestfs_impl_set_backend (guestfs_h *g, const char *method)
{
if (guestfs_int_set_backend (g, method) == -1) {
diff --git a/src/launch.c b/src/launch.c
index 99c5582..ddd7091 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -75,6 +75,8 @@ guestfs_impl_launch (guestfs_h *g)
CLEANUP_FREE char *backend = guestfs_get_backend (g);
debug (g, "launch: program=%s", g->program);
+ if (STRNEQ (g->identifier, ""))
+ debug (g, "launch: identifier=%s", g->identifier);
debug (g, "launch:
version=%"PRIi64".%"PRIi64".%"PRIi64"%s",
v->major, v->minor, v->release, v->extra);
@@ -359,6 +361,7 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char
*appliance_dev,
"%s" /* verbose */
"%s" /* network */
" TERM=%s" /* TERM environment variable */
+ "%s%s" /* handle identifier */
"%s%s", /* append */
#ifdef __arm__
g->memsize,
@@ -369,6 +372,8 @@ guestfs_int_appliance_command_line (guestfs_h *g, const char
*appliance_dev,
g->verbose ? " guestfs_verbose=1" : "",
g->enable_network ? " guestfs_network=1" : "",
term ? term : "linux",
+ STRNEQ (g->identifier, "") ? " guestfs_identifier=" :
"",
+ g->identifier,
g->append ? " " : "", g->append ? g->append :
"");
return ret;
--
2.5.0