summaryrefslogtreecommitdiffstats
path: root/ffd/update.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/update.c')
-rw-r--r--ffd/update.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/ffd/update.c b/ffd/update.c
new file mode 100644
index 0000000..e5faab5
--- /dev/null
+++ b/ffd/update.c
@@ -0,0 +1,116 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "ffd.h"
+#include "neigh.h"
+#include "queue.h"
+
+#include <stdio.h>
+
+
+static ffd_queue_t *pending_updates = NULL;
+
+
+typedef struct _update_arg {
+ ffd_node_id_t node;
+ uint16_t type;
+ uint16_t key;
+
+ ffd_neigh_t *neigh;
+ unsigned ref;
+} update_arg;
+
+
+static inline update_arg* update_new(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh) {
+ update_arg *arg = malloc(sizeof(update_arg));
+
+ arg->node = *node;
+ arg->type = type;
+ arg->key = key;
+
+ if (neigh)
+ ffd_neigh_ref(neigh);
+ arg->neigh = neigh;
+
+ arg->ref = 0;
+
+ return arg;
+}
+
+static inline update_arg* update_ref(update_arg *arg) {
+ arg->ref++;
+ return arg;
+}
+
+static inline void update_unref(update_arg *arg) {
+ if (!--arg->ref) {
+ if (arg->neigh)
+ ffd_neigh_unref(arg->neigh);
+
+ free(arg);
+ }
+}
+
+void ffd_update_enqueue(const ffd_node_id_t *node, uint16_t type, uint16_t key, ffd_neigh_t *neigh, bool urgent) {
+ if (neigh)
+ ffd_neigh_ref(neigh);
+
+ update_arg *arg = update_new(node, type, key, neigh);
+
+ if (urgent) {
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 2*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 3*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 4*FFD_URGENT_DELAY, update_ref(arg));
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, 5*FFD_URGENT_DELAY, update_ref(arg));
+ }
+ else {
+ ffd_queue_put_delayed(&pending_updates, NULL, &now, FFD_DELAY, update_ref(arg));
+ }
+}
+
+int ffd_update_timeout(void) {
+ return ffd_queue_timeout(&pending_updates);
+}
+
+void ffd_update_run(void) {
+ while (!ffd_update_timeout()) {
+ update_arg *arg = pending_updates->arg;
+
+ ffd_neigh_t *neigh = arg->neigh;
+ ffd_announce_t *announce = ffd_announce_find(&arg->node, arg->type, arg->key);
+
+ fprintf(stderr, "debug: sending scheduled update.\n");
+
+ if (announce)
+ ffd_send_update(NULL, neigh, announce, false);
+ else
+ ffd_send_retract(neigh, arg->node, arg->type, arg->key);
+
+ update_unref(arg);
+ ffd_queue_drop(&pending_updates);
+ }
+}