When we added .thread_model to plugins, we forgot to expose
has_thread_model in the --dump-plugin output. What's more, it is
useful to determine if the plugin itself is aware of tighter
restrictions imposed by dynamic choices, by outputting both
'max_thread_model' (what the plugin was compiled as) and
'thread_model' (the resulting model based on runtime knowledge).
Note that this means that a plugin's .thread_model can be called prior
to .config, so the sh plugin must be prepared for a missing script.
In fact, exposing additional information during --dump-plugin will
make it easier for a future patch to make sh default to PARALLEL, and
still have introspection on which model will actually be used.
Fixes: 9911a9d3
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
docs/nbdkit-plugin.pod | 11 +++++---
plugins/sh/nbdkit-sh-plugin.pod | 3 +-
plugins/sh/sh.c | 3 ++
server/plugins.c | 49 ++++++++++++++++++++-------------
tests/test-dump-plugin.sh | 31 ++++++++++++++++++++-
5 files changed, 72 insertions(+), 25 deletions(-)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 8ce702da..fe9ada87 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -128,16 +128,19 @@ is called once just after the plugin is loaded into memory.
C<.config> is called zero or more times during command line parsing.
C<.config_complete> is called once after all configuration information
-has been passed to the plugin.
+has been passed to the plugin (but not during C<nbdkit --dump-plugin>).
Both are called after loading the plugin but before any connections
are accepted.
=item C<.thread_model>
-C<.thread_model> is called once after all configuration information
-has been passed to the plugin, and before any connections are
-accepted.
+In normal operation, C<.thread_model> is called once after
+C<.config_complete> has validated all configuration information, and
+before any connections are accepted. However, during C<nbdkit
+--dump-plugin>, it is called after any C<.config> calls but without
+C<.config_complete> (so a plugin which determines the results from a
+script must be prepared for a missing script).
=item C<.open>
diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index dfa086b5..41b9e7c7 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -191,7 +191,8 @@ C<"serialize_requests">, or
C<"parallel">.
This method is I<not> required; if omitted, then the plugin will be
executed under the default sh thread model (currently
C<"serialize_all_requests">, which implies this callback only makes a
-difference with an output of C<"serialize_connections">). If an error
+difference with an output of C<"serialize_connections">; look for
+'max_thread_model' in C<nbdkit --dump-plugin sh>). If an error
occurs, the script should output an error message and exit with status
C<1>; unrecognized output is ignored.
diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c
index e3d3c2f1..5869d9a4 100644
--- a/plugins/sh/sh.c
+++ b/plugins/sh/sh.c
@@ -273,6 +273,9 @@ sh_thread_model (void)
size_t slen;
int r;
+ if (!script)
+ return THREAD_MODEL;
+
switch (call_read (&s, &slen, args)) {
case OK:
if (slen > 0 && s[slen-1] == '\n')
diff --git a/server/plugins.c b/server/plugins.c
index 9da0361b..3bb20c93 100644
--- a/server/plugins.c
+++ b/server/plugins.c
@@ -140,6 +140,33 @@ plugin_version (struct backend *b)
return p->plugin.version;
}
+/* Map thread model to a string */
+static void
+plugin_dump_thread_model (const char *prefix, int model)
+{
+ flockfile (stdout);
+ printf ("%s=", prefix);
+ switch (model) {
+ case NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS:
+ printf ("serialize_connections");
+ break;
+ case NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS:
+ printf ("serialize_all_requests");
+ break;
+ case NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS:
+ printf ("serialize_requests");
+ break;
+ case NBDKIT_THREAD_MODEL_PARALLEL:
+ printf ("parallel");
+ break;
+ default:
+ printf ("%d # unknown thread model!", model);
+ break;
+ }
+ printf ("\n");
+ funlockfile (stdout);
+}
+
/* This implements the --dump-plugin option. */
static void
plugin_dump_fields (struct backend *b)
@@ -157,25 +184,8 @@ plugin_dump_fields (struct backend *b)
printf ("api_version=%d\n", p->plugin._api_version);
printf ("struct_size=%" PRIu64 "\n", p->plugin._struct_size);
- printf ("thread_model=");
- switch (p->plugin._thread_model) {
- case NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS:
- printf ("serialize_connections");
- break;
- case NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS:
- printf ("serialize_all_requests");
- break;
- case NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS:
- printf ("serialize_requests");
- break;
- case NBDKIT_THREAD_MODEL_PARALLEL:
- printf ("parallel");
- break;
- default:
- printf ("%d # unknown thread model!", p->plugin._thread_model);
- break;
- }
- printf ("\n");
+ plugin_dump_thread_model ("max_thread_model", p->plugin._thread_model);
+ plugin_dump_thread_model ("thread_model", backend->thread_model
(backend));
printf ("errno_is_preserved=%d\n", !!p->plugin.errno_is_preserved);
if (p->plugin.magic_config_key)
printf ("magic_config_key=%s\n", p->plugin.magic_config_key);
@@ -213,6 +223,7 @@ plugin_dump_fields (struct backend *b)
HAS (extents);
HAS (can_cache);
HAS (cache);
+ HAS (thread_model);
#undef HAS
/* Custom fields. */
diff --git a/tests/test-dump-plugin.sh b/tests/test-dump-plugin.sh
index 1d58a3a3..982d5062 100755
--- a/tests/test-dump-plugin.sh
+++ b/tests/test-dump-plugin.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# nbdkit
-# Copyright (C) 2014 Red Hat Inc.
+# Copyright (C) 2014-2019 Red Hat Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -68,3 +68,32 @@ do_test ()
esac
}
foreach_plugin do_test
+
+# Test that --dump-plugin can be used to introspect a resulting dynamic
+# thread model.
+out=$({
+ # sh does not yet support parallel
+ nbdkit --dump-plugin sh
+ # Here, the script further reduces things
+ nbdkit --dump-plugin sh - <<\EOF
+case $1 in
+ get_size) echo 1M ;;
+ thread_model) echo serialize_connections ;;
+ *) exit 2 ;;
+esac
+EOF
+ # Here, the filter further reduces things
+ nbdkit --dump-plugin --filter=noparallel sh serialize=connections
+} | grep thread_model)
+exp="max_thread_model=serialize_all_requests
+thread_model=serialize_all_requests
+has_thread_model=1
+max_thread_model=serialize_all_requests
+thread_model=serialize_connections
+has_thread_model=1
+max_thread_model=serialize_all_requests
+thread_model=serialize_connections
+has_thread_model=1"
+if [ "$out" != "$exp" ]; then
+ echo "thread_model mismatch"; exit 1
+fi
--
2.20.1