|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 4/8] tools/xenstored: add depth information to watches
Add the depth for matching subdirectories of a watch to the watch
handling. A depth value of -1 is used for the current model of no
limit.
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
tools/xenstored/lu.c | 3 ++
tools/xenstored/watch.c | 110 ++++++++++++++++++++++++++++------------
tools/xenstored/watch.h | 1 +
3 files changed, 81 insertions(+), 33 deletions(-)
diff --git a/tools/xenstored/lu.c b/tools/xenstored/lu.c
index eaffdbc69e..7d9f086a59 100644
--- a/tools/xenstored/lu.c
+++ b/tools/xenstored/lu.c
@@ -183,6 +183,9 @@ void lu_read_state(void)
case XS_STATE_TYPE_WATCH:
read_state_watch(ctx, state.buf);
break;
+ case XS_STATE_TYPE_WATCH_EXT:
+ read_state_watch_ext(ctx, state.buf);
+ break;
case XS_STATE_TYPE_TA:
xprintf("live-update: ignore transaction record\n");
break;
diff --git a/tools/xenstored/watch.c b/tools/xenstored/watch.c
index 36e4d33f22..3f1049911b 100644
--- a/tools/xenstored/watch.c
+++ b/tools/xenstored/watch.c
@@ -39,26 +39,35 @@ struct watch
/* Offset into path for skipping prefix (used for relative paths). */
unsigned int prefix_len;
+ int depth; /* -1: no depth limit. */
char *token;
char *node;
};
/* Is child a subnode of parent, or equal? */
-static bool is_child(const char *child, const char *parent)
+static bool is_child(const char *child, const char *parent, int depth)
{
- unsigned int len = strlen(parent);
-
- /*
- * / should really be "" for this algorithm to work, but that's a
- * usability nightmare.
- */
- if (streq(parent, "/"))
- return true;
+ unsigned int len = strlen(parent); /* len == 1 if parent is "/". */
+ unsigned int sub_levels = (len == 1) ? 1 : 0;
if (strncmp(child, parent, len) != 0)
return false;
- return child[len] == '/' || child[len] == '\0';
+ if (child[len] != '/' && child[len] != '\0' && len > 1)
+ return false;
+
+ if (depth < 0 || child[len] == '\0')
+ return true;
+
+ while (sub_levels <= depth) {
+ if (child[len] == '\0')
+ return true;
+ if (child[len] == '/')
+ sub_levels++;
+ len++;
+ }
+
+ return false;
}
static const char *get_watch_path(const struct watch *watch, const char *name)
@@ -145,7 +154,7 @@ void fire_watches(struct connection *conn, const void *ctx,
const char *name,
get_watch_path(watch, name),
watch->token);
} else {
- if (is_child(name, watch->node))
+ if (is_child(name, watch->node, watch->depth))
send_event(req, i,
get_watch_path(watch, name),
watch->token);
@@ -170,7 +179,7 @@ static int check_watch_path(struct connection *conn, const
void *ctx,
}
static struct watch *add_watch(struct connection *conn, const char *path,
- const char *token, bool relative,
+ const char *token, int depth, bool relative,
bool no_quota_check)
{
struct watch *watch;
@@ -178,6 +187,7 @@ static struct watch *add_watch(struct connection *conn,
const char *path,
watch = talloc(conn, struct watch);
if (!watch)
goto nomem;
+ watch->depth = depth;
watch->node = talloc_strdup(watch, path);
watch->token = talloc_strdup(watch, token);
if (!watch->node || !watch->token)
@@ -204,6 +214,7 @@ int do_watch(const void *ctx, struct connection *conn,
struct buffered_data *in)
{
struct watch *watch;
const char *vec[2];
+ int depth = -1;
bool relative;
if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
@@ -223,7 +234,7 @@ int do_watch(const void *ctx, struct connection *conn,
struct buffered_data *in)
if (domain_check_quota_add(conn->domain, ACC_WATCH, 1))
return ENOSPC;
- watch = add_watch(conn, vec[0], vec[1], relative, false);
+ watch = add_watch(conn, vec[0], vec[1], depth, relative, false);
if (!watch)
return errno;
@@ -287,28 +298,47 @@ const char *dump_state_watches(FILE *fp, struct
connection *conn,
const char *ret = NULL;
struct watch *watch;
struct xs_state_watch sw;
+ struct xs_state_watch_ext swe;
struct xs_state_record_header head;
const char *path;
-
- head.type = XS_STATE_TYPE_WATCH;
+ size_t path_len, token_len;
list_for_each_entry(watch, &conn->watches, list) {
- head.length = sizeof(sw);
-
- sw.conn_id = conn_id;
path = get_watch_path(watch, watch->node);
- sw.path_length = strlen(path) + 1;
- sw.token_length = strlen(watch->token) + 1;
- head.length += sw.path_length + sw.token_length;
+ path_len = strlen(path) + 1;
+ token_len = strlen(watch->token) + 1;
+
+ if (watch->depth >= 0) {
+ head.type = XS_STATE_TYPE_WATCH_EXT;
+ head.length = sizeof(swe);
+ swe.conn_id = conn_id;
+ swe.path_length = path_len;
+ swe.token_length = token_len;
+ swe.depth = watch->depth;
+ } else {
+ head.type = XS_STATE_TYPE_WATCH;
+ head.length = sizeof(sw);
+ sw.conn_id = conn_id;
+ sw.path_length = path_len;
+ sw.token_length = token_len;
+ }
+
+ head.length += path_len + token_len;
head.length = ROUNDUP(head.length, 3);
if (fwrite(&head, sizeof(head), 1, fp) != 1)
return "Dump watch state error";
- if (fwrite(&sw, sizeof(sw), 1, fp) != 1)
- return "Dump watch state error";
- if (fwrite(path, sw.path_length, 1, fp) != 1)
+ if (watch->depth >= 0) {
+ if (fwrite(&swe, sizeof(sw), 1, fp) != 1)
+ return "Dump watch state ext error";
+ } else {
+ if (fwrite(&sw, sizeof(sw), 1, fp) != 1)
+ return "Dump watch state error";
+ }
+
+ if (fwrite(path, path_len, 1, fp) != 1)
return "Dump watch path error";
- if (fwrite(watch->token, sw.token_length, 1, fp) != 1)
+ if (fwrite(watch->token, token_len, 1, fp) != 1)
return "Dump watch token error";
ret = dump_state_align(fp);
@@ -319,27 +349,41 @@ const char *dump_state_watches(FILE *fp, struct
connection *conn,
return ret;
}
-void read_state_watch(const void *ctx, const void *state)
+static void process_state_watch(const void *ctx, unsigned int conn_id,
+ const char *path, const char *token,
+ int depth)
{
- const struct xs_state_watch *sw = state;
struct connection *conn;
- const char *path, *token;
bool relative;
- conn = get_connection_by_id(sw->conn_id);
+ conn = get_connection_by_id(conn_id);
if (!conn)
barf("connection not found for read watch");
- path = (char *)sw->data;
- token = path + sw->path_length;
-
/* Don't check success, we want the relative information only. */
check_watch_path(conn, ctx, &path, &relative);
if (!path)
barf("allocation error for read watch");
- if (!add_watch(conn, path, token, relative, true))
+ if (!add_watch(conn, path, token, depth, relative, true))
barf("error adding watch");
+
+}
+
+void read_state_watch(const void *ctx, const void *state)
+{
+ const struct xs_state_watch *sw = state;
+
+ process_state_watch(ctx, sw->conn_id, (char *)sw->data,
+ (char *)sw->data + sw->path_length, -1);
+}
+
+void read_state_watch_ext(const void *ctx, const void *state)
+{
+ const struct xs_state_watch_ext *swe = state;
+
+ process_state_watch(ctx, swe->conn_id, (char *)swe->data,
+ (char *)swe->data + swe->path_length, swe->depth);
}
/*
diff --git a/tools/xenstored/watch.h b/tools/xenstored/watch.h
index d9ac6a334a..afdfdc6b2f 100644
--- a/tools/xenstored/watch.h
+++ b/tools/xenstored/watch.h
@@ -37,5 +37,6 @@ const char *dump_state_watches(FILE *fp, struct connection
*conn,
unsigned int conn_id);
void read_state_watch(const void *ctx, const void *state);
+void read_state_watch_ext(const void *ctx, const void *state);
#endif /* _XENSTORED_WATCH_H */
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |