/*
- * Copyright (C) 2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2013 Andre Noll <maan@tuebingen.mpg.de>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
bool disabled;
};
-/* per open/close data */
+/* One active buddy */
struct sync_buddy {
int fd;
struct sync_buddy_info *sbi;
struct list_head node;
};
+/* Allocated in ->open() */
struct sync_filter_context {
int listen_fd;
struct list_head buddies;
bool ping_sent;
};
+/* Allocated and freed in ->parse_config() and ->free_config(). */
struct sync_filter_config {
struct sync_filter_args_info *conf;
struct sync_buddy_info *buddy_info;
static void sync_close_buddy(struct sync_buddy *buddy)
{
- if (buddy->fd < 0)
- return;
- PARA_DEBUG_LOG("closing %s\n", buddy->sbi->url);
+ PARA_DEBUG_LOG("closing %s, fd %d\n", buddy->sbi->url, buddy->fd);
close(buddy->fd);
- buddy->fd = -1;
+ list_del(&buddy->node);
+ free(buddy);
}
static void sync_close_buddies(struct sync_filter_context *ctx)
{
- struct sync_buddy *buddy;
+ struct sync_buddy *buddy, *tmp;
- FOR_EACH_BUDDY(buddy, &ctx->buddies)
+ FOR_EACH_BUDDY_SAFE(buddy, tmp, &ctx->buddies)
sync_close_buddy(buddy);
}
}
}
+/*
+ * At parse config time, we build an array of struct sync_buddy_info with one
+ * entry for each buddy given in the arguments. This array is not affected by
+ * sync_close(), so information stored there can be used for multiple instances
+ * (para_audiod). We store the resolved url and the ->disabled bit in this
+ * array.
+ */
static int sync_parse_config(int argc, char **argv, void **result)
{
int i, ret, n;
}
/*
- * True if we sent a packet to all budies and received a packet from each
+ * True if we sent a packet to all buddies and received a packet from each
* enabled buddy.
*/
static bool sync_complete(struct sync_filter_context *ctx)
FOR_EACH_BUDDY(buddy, &ctx->buddies) {
if (buddy->sbi->disabled)
continue;
+ if (buddy->ping_received == true)
+ continue;
PARA_NOTICE_LOG("disabling %s\n", buddy->sbi->url);
buddy->sbi->disabled = true;
}
tv_add(now, &to, &ctx->timeout);
}
-static void sync_pre_select(struct sched *s, struct task *t)
+static void sync_pre_select(struct sched *s, void *context)
{
int ret;
- struct filter_node *fn = container_of(t, struct filter_node, task);
+ struct filter_node *fn = context;
struct sync_filter_context *ctx = fn->private_data;
struct sync_filter_config *sfc = fn->conf;
return NULL;
}
-static int sync_post_select(__a_unused struct sched *s, struct task *t)
+static int sync_post_select(__a_unused struct sched *s, void *context)
{
int ret;
- struct filter_node *fn = container_of(t, struct filter_node, task);
+ struct filter_node *fn = context;
struct sync_filter_context *ctx = fn->private_data;
struct sync_filter_config *sfc = fn->conf;
struct sync_buddy *buddy, *tmp;
buddy->sbi->url, buddy->sbi->disabled?
"disabled" : "enabled");
ret = xwrite(buddy->fd, &c, 1);
- sync_close_buddy(buddy);
if (ret < 0) {
PARA_WARNING_LOG("failed to write to %s: %s\n",
buddy->sbi->url, para_strerror(-ret));
- list_del(&buddy->node);
+ sync_close_buddy(buddy);
}
}
ctx->ping_sent = true;
buddy->sbi->url);
buddy->sbi->disabled = false;
}
- list_del(&buddy->node);
+ buddy->ping_received = true;
}
}
if (!sync_complete(ctx))
return 1;
/*
* Although all enabled buddies are in sync we do not splice out
- * ourselves immediately. We rather wait until the timout expires,
+ * ourselves immediately. We rather wait until the timeout expires,
* or the buddy list has become empty. This opens a time window
* for disabled buddies to become enabled by sending us a packet.
*/