|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/8] tools/libs/store: add support to use watches with a depth parameter
Add a new xs_watch_depth() function to libxenstore allowing to limit
the scope of a Xenstore watch. It can be used only in case Xenstore is
supporting the XENSTORE_SERVER_FEATURE_WATCHDEPTH feature.
For convenience add a xs_watch_try_depth() wrapper, which will call
xs_watch_depth() if supported and xs_watch() otherwise.
Cache the supported features of Xenstore in order not having to get
them from Xenstore for each call of one of the new functions.
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
docs/man/xl.cfg.5.pod.in | 6 ++
tools/include/xenstore.h | 16 +++++
tools/libs/store/libxenstore.map | 2 +
tools/libs/store/xs.c | 116 ++++++++++++++++++++++++++-----
xen/include/public/io/xs_wire.h | 2 +
5 files changed, 123 insertions(+), 19 deletions(-)
diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 3aac0bc4fb..2f77016ecf 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -740,6 +740,12 @@ Xenstore is capable to reconnect to a guest.
Xenstore will present an error value in case it disconnects due to an error
condition.
+=item B<0x00000004>
+
+Xenstore supports to set watches with a limited depth (depth 0 matches
+only the watched node, depth 1 matches the node and its direct children,
+etc.).
+
=back
The features supported by the running Xenstore instance can be retrieved
diff --git a/tools/include/xenstore.h b/tools/include/xenstore.h
index 6b661e5895..8a6afd97f5 100644
--- a/tools/include/xenstore.h
+++ b/tools/include/xenstore.h
@@ -177,6 +177,22 @@ bool xs_set_permissions(struct xs_handle *h,
xs_transaction_t t,
*/
bool xs_watch(struct xs_handle *h, const char *path, const char *token);
+/* Same as xs_watch(), but with limiting the matching for modified
+ * children to a specified depth (depth 0 only matches the node itself,
+ * depth 1 will additionally match direct children of the node, etc.).
+ * Only supported if the XENSTORE_SERVER_FEATURE_WATCHDEPTH (4) is set
+ * in the returned features of xs_get_features_supported().
+ */
+bool xs_watch_depth(struct xs_handle *h, const char *path, const char *token,
+ unsigned int depth);
+
+/* If supported, same as xs_watch_depth(), use xs_watch() otherwise.
+ * As a result watches might trigger for nodes below the watched path, too.
+ * Not to be used for special watches!
+ */
+bool xs_watch_try_depth(struct xs_handle *h, const char *path,
+ const char *token, unsigned int depth);
+
/* Return the FD to poll on to see if a watch has fired. */
int xs_fileno(struct xs_handle *h);
diff --git a/tools/libs/store/libxenstore.map b/tools/libs/store/libxenstore.map
index a08ddd549f..7067068998 100644
--- a/tools/libs/store/libxenstore.map
+++ b/tools/libs/store/libxenstore.map
@@ -52,4 +52,6 @@ VERS_4.2 {
xs_set_global_quota;
xs_get_domain_quota;
xs_set_domain_quota;
+ xs_watch_depth;
+ xs_watch_try_depth;
} VERS_4.1;
diff --git a/tools/libs/store/xs.c b/tools/libs/store/xs.c
index dda37f7526..0bea464a33 100644
--- a/tools/libs/store/xs.c
+++ b/tools/libs/store/xs.c
@@ -984,37 +984,29 @@ bool xs_restrict(struct xs_handle *h, unsigned domid)
return false;
}
-/* Watch a node for changes (poll on fd to detect, or call read_watch()).
- * When the node (or any child) changes, fd will become readable.
- * Token is returned when watch is read, to allow matching.
- * Returns false on failure.
- */
-bool xs_watch(struct xs_handle *h, const char *path, const char *token)
+static bool xs_watch_helper(struct xs_handle *h)
{
- struct xsd_sockmsg msg = { .type = XS_WATCH };
- struct iovec iov[3];
-
#ifdef USE_PTHREAD
+ sigset_t set, old_set;
+ pthread_attr_t attr;
+ static size_t stack_size;
+#ifdef USE_DLSYM
+ size_t (*getsz)(pthread_attr_t *attr);
+#endif
+
#define DEFAULT_THREAD_STACKSIZE (16 * 1024)
/* NetBSD doesn't have PTHREAD_STACK_MIN. */
#ifndef PTHREAD_STACK_MIN
# define PTHREAD_STACK_MIN 0
#endif
-#define READ_THREAD_STACKSIZE \
- ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \
+#define READ_THREAD_STACKSIZE \
+ ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \
PTHREAD_STACK_MIN : DEFAULT_THREAD_STACKSIZE)
/* We dynamically create a reader thread on demand. */
mutex_lock(&h->request_mutex);
if (!h->read_thr_exists) {
- sigset_t set, old_set;
- pthread_attr_t attr;
- static size_t stack_size;
-#ifdef USE_DLSYM
- size_t (*getsz)(pthread_attr_t *attr);
-#endif
-
if (pthread_attr_init(&attr) != 0) {
mutex_unlock(&h->request_mutex);
return false;
@@ -1050,16 +1042,89 @@ bool xs_watch(struct xs_handle *h, const char *path,
const char *token)
mutex_unlock(&h->request_mutex);
#endif
+ return true;
+}
+
+/* Watch a node for changes (poll on fd to detect, or call read_watch()).
+ * When the node (or any child) changes, fd will become readable.
+ * Token is returned when watch is read, to allow matching.
+ * Returns false on failure.
+ */
+bool xs_watch(struct xs_handle *h, const char *path, const char *token)
+{
+ struct xsd_sockmsg msg = { .type = XS_WATCH };
+ struct iovec iov[3];
+
+ if (!xs_watch_helper(h))
+ return false;
+
+ iov[0].iov_base = &msg;
+ iov[0].iov_len = sizeof(msg);
+ iov[1].iov_base = (void *)path;
+ iov[1].iov_len = strlen(path) + 1;
+ iov[2].iov_base = (void *)token;
+ iov[2].iov_len = strlen(token) + 1;
+
+ return xs_bool(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL));
+}
+
+/* Same as xs_watch(), but with limiting the matching for modified
+ * children to a specified depth (depth 0 only matches the node itself,
+ * depth 1 will additionally match direct children of the node, etc.).
+ * Only supported if the XENSTORE_SERVER_FEATURE_WATCHDEPTH (4) is set
+ * in the returned features of xs_get_features_supported().
+ */
+bool xs_watch_depth(struct xs_handle *h, const char *path, const char *token,
+ unsigned int depth)
+{
+ struct xsd_sockmsg msg = { .type = XS_WATCH };
+ struct iovec iov[4];
+ char depthstr[MAX_STRLEN(depth)];
+ static bool depth_supported;
+
+ if (!xs_watch_helper(h))
+ return false;
+
+ if (!depth_supported) {
+ unsigned int features;
+
+ if (!xs_get_features_supported(h, &features))
+ return false;
+ if (!(features & XENSTORE_SERVER_FEATURE_WATCHDEPTH))
+ return false;
+ depth_supported = true;
+ }
+
+ snprintf(depthstr, sizeof(depthstr), "%u", depth);
+
iov[0].iov_base = &msg;
iov[0].iov_len = sizeof(msg);
iov[1].iov_base = (void *)path;
iov[1].iov_len = strlen(path) + 1;
iov[2].iov_base = (void *)token;
iov[2].iov_len = strlen(token) + 1;
+ iov[3].iov_base = depthstr;
+ iov[3].iov_len = strlen(depthstr) + 1;
return xs_bool(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL));
}
+/* If supported, same as xs_watch_depth(), use xs_watch() otherwise.
+ * As a result watches might trigger for nodes below the watched path, too.
+ * Not to be used for special watches!
+ */
+bool xs_watch_try_depth(struct xs_handle *h, const char *path,
+ const char *token, unsigned int depth)
+{
+ unsigned int features;
+
+ if (xs_get_features_supported(h, &features) &&
+ (features & XENSTORE_SERVER_FEATURE_WATCHDEPTH) &&
+ xs_watch_depth(h, path, token, depth))
+ return true;
+
+ return xs_watch(h, path, token);
+}
/* Clear the pipe token if there are no more pending watchs.
* We suppose the watch_mutex is already taken.
@@ -1420,13 +1485,26 @@ static bool xs_uint(char *reply, unsigned int *uintval)
bool xs_get_features_supported(struct xs_handle *h, unsigned int *features)
{
+ static unsigned int own_features = 0;
+ static bool features_valid = false;
struct xsd_sockmsg msg = { .type = XS_GET_FEATURE };
struct iovec iov[1];
+ if (features_valid) {
+ *features = own_features;
+ return true;
+ }
+
iov[0].iov_base = &msg;
iov[0].iov_len = sizeof(msg);
- return xs_uint(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL), features);
+ if (!xs_uint(xs_talkv(h, iov, ARRAY_SIZE(iov), NULL), &own_features))
+ return false;
+
+ features_valid = true;
+ *features = own_features;
+
+ return true;
}
bool xs_get_features_domain(struct xs_handle *h, unsigned int domid,
diff --git a/xen/include/public/io/xs_wire.h b/xen/include/public/io/xs_wire.h
index d2e2b8b9eb..2e763bc877 100644
--- a/xen/include/public/io/xs_wire.h
+++ b/xen/include/public/io/xs_wire.h
@@ -124,6 +124,8 @@ struct xenstore_domain_interface {
#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
/* The presence of the "error" field in the ring page */
#define XENSTORE_SERVER_FEATURE_ERROR 2
+/* The XS_WATCH command can be used with a <depth> parameter */
+#define XENSTORE_SERVER_FEATURE_WATCHDEPTH 4
/* Valid values for the connection field */
#define XENSTORE_CONNECTED 0 /* the steady-state */
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |