summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2014-04-25 01:51:36 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2014-04-25 01:51:36 +0200
commit5adfca9b651e0e383d463da9e8158e75cad8e7c7 (patch)
tree906d85ae42ceede085d7c84bf9cdd9e678c03ae7 /src
parent482ddc46a62b9a6b8bd615fd35b2bac6d3b7d841 (diff)
downloadfastd-5adfca9b651e0e383d463da9e8158e75cad8e7c7.tar
fastd-5adfca9b651e0e383d463da9e8158e75cad8e7c7.zip
Remove ref-counting on remotes
Now that peers have a peer id we can use that to specify a peer in a resolve return. As the remote list of a peer doesn't change without the peer id changing, instead of taking a remote ref we can just use the peer id and remote index.
Diffstat (limited to 'src')
-rw-r--r--src/async.c27
-rw-r--r--src/async.h4
-rw-r--r--src/fastd.c31
-rw-r--r--src/peer.c62
-rw-r--r--src/peer.h27
-rw-r--r--src/resolve.c14
6 files changed, 71 insertions, 94 deletions
diff --git a/src/async.c b/src/async.c
index f5133f6..cb9ee14 100644
--- a/src/async.c
+++ b/src/async.c
@@ -44,28 +44,15 @@ void fastd_async_init(void) {
static void handle_resolve_return(const void *buf) {
const fastd_async_resolve_return_t *resolve_return = buf;
- size_t i;
- for (i = 0; i < VECTOR_LEN(ctx.peers); i++) {
- fastd_peer_t *peer = VECTOR_INDEX(ctx.peers, i);
+ fastd_peer_t *peer = fastd_peer_find_by_id(resolve_return->peer_id);
+ if (!peer)
+ return;
- if (!peer->config)
- continue;
+ if (!peer->config)
+ exit_bug("resolve return for temporary peer");
- fastd_remote_t *remote;
- for (remote = peer->remotes; remote; remote = remote->next) {
- if (remote == resolve_return->remote)
- break;
- }
-
- if (!remote)
- continue;
-
- fastd_peer_handle_resolve(peer, remote, resolve_return->n_addr, resolve_return->addr);
-
- break;
- }
-
- fastd_remote_unref(resolve_return->remote);
+ fastd_remote_t *remote = &VECTOR_INDEX(peer->remotes, resolve_return->remote);
+ fastd_peer_handle_resolve(peer, remote, resolve_return->n_addr, resolve_return->addr);
}
void fastd_async_handle(void) {
diff --git a/src/async.h b/src/async.h
index 7e1921c..f2a8f20 100644
--- a/src/async.h
+++ b/src/async.h
@@ -31,7 +31,9 @@
struct fastd_async_resolve_return {
- fastd_remote_t *remote;
+ uint64_t peer_id;
+ size_t remote;
+
size_t n_addr;
fastd_peer_address_t addr[];
};
diff --git a/src/fastd.c b/src/fastd.c
index 3ee445a..80079b5 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -405,14 +405,14 @@ static inline void no_valid_address_debug(const fastd_peer_t *peer) {
pr_debug("not sending a handshake to %P (no valid address resolved)", peer);
}
-static void send_handshake(fastd_peer_t *peer) {
+static void send_handshake(fastd_peer_t *peer, fastd_remote_t *next_remote) {
if (!fastd_peer_is_established(peer)) {
- if (!peer->next_remote->n_addresses) {
+ if (!next_remote->n_addresses) {
no_valid_address_debug(peer);
return;
}
- fastd_peer_claim_address(peer, NULL, NULL, &peer->next_remote->addresses[peer->next_remote->current_address], false);
+ fastd_peer_claim_address(peer, NULL, NULL, &next_remote->addresses[next_remote->current_address], false);
fastd_peer_reset_socket(peer);
}
@@ -447,33 +447,36 @@ static void handle_handshake_queue(void) {
fastd_peer_schedule_handshake_default(peer);
if (!fastd_peer_may_connect(peer)) {
- if (peer->next_remote != NULL) {
+ if (peer->next_remote != -1) {
pr_debug("temporarily disabling handshakes with %P", peer);
- peer->next_remote = NULL;
+ peer->next_remote = -1;
}
return;
}
- if (peer->next_remote || fastd_peer_is_established(peer)) {
- send_handshake(peer);
+ fastd_remote_t *next_remote = fastd_peer_get_next_remote(peer);
+
+ if (next_remote || fastd_peer_is_established(peer)) {
+ send_handshake(peer, next_remote);
if (fastd_peer_is_established(peer))
return;
- if (++peer->next_remote->current_address < peer->next_remote->n_addresses)
+ if (++next_remote->current_address < next_remote->n_addresses)
return;
- peer->next_remote = peer->next_remote->next;
+ peer->next_remote++;
}
- if (!peer->next_remote)
- peer->next_remote = peer->remotes;
+ if (peer->next_remote < 0 || (size_t)peer->next_remote >= VECTOR_LEN(peer->remotes))
+ peer->next_remote = 0;
- peer->next_remote->current_address = 0;
+ next_remote = fastd_peer_get_next_remote(peer);
+ next_remote->current_address = 0;
- if (fastd_remote_is_dynamic(peer->next_remote))
- fastd_resolve_peer(peer, peer->next_remote);
+ if (fastd_remote_is_dynamic(next_remote))
+ fastd_resolve_peer(peer, next_remote);
}
static bool maintain_peer(fastd_peer_t *peer) {
diff --git a/src/peer.c b/src/peer.c
index 2d4b8bf..846d274 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -226,8 +226,6 @@ static void init_handshake(fastd_peer_t *peer) {
}
void fastd_peer_handle_resolve(fastd_peer_t *peer, fastd_remote_t *remote, size_t n_addresses, const fastd_peer_address_t *addresses) {
- remote->resolving = false;
-
free(remote->addresses);
remote->addresses = malloc(n_addresses*sizeof(fastd_peer_address_t));
memcpy(remote->addresses, addresses, n_addresses*sizeof(fastd_peer_address_t));
@@ -245,13 +243,16 @@ static void setup_peer(fastd_peer_t *peer) {
peer->state = STATE_INIT;
- fastd_remote_t *remote;
- for (remote = peer->remotes; remote; remote = remote->next) {
- remote->last_resolve_timeout = ctx.now;
- remote->resolving = false;
+ if (VECTOR_LEN(peer->remotes) == 0) {
+ peer->next_remote = -1;
}
+ else {
+ size_t i;
+ for (i = 0; i < VECTOR_LEN(peer->remotes); i++)
+ VECTOR_INDEX(peer->remotes, i).last_resolve_timeout = ctx.now;
- peer->next_remote = peer->remotes;
+ peer->next_remote = 0;
+ }
peer->last_handshake_timeout = ctx.now;
peer->last_handshake_address.sa.sa_family = AF_UNSPEC;
@@ -264,12 +265,13 @@ static void setup_peer(fastd_peer_t *peer) {
if (!peer->protocol_state)
conf.protocol->init_peer_state(peer);
- if (peer->next_remote) {
- peer->next_remote->current_address = 0;
+ fastd_remote_t *next_remote = fastd_peer_get_next_remote(peer);
+ if (next_remote) {
+ next_remote->current_address = 0;
- if (fastd_remote_is_dynamic(peer->next_remote)) {
+ if (fastd_remote_is_dynamic(next_remote)) {
peer->state = STATE_RESOLVING;
- fastd_resolve_peer(peer, peer->next_remote);
+ fastd_resolve_peer(peer, next_remote);
}
else {
init_handshake(peer);
@@ -296,12 +298,10 @@ static void delete_peer(fastd_peer_t *peer) {
if (!peer->config)
free(peer->protocol_config);
- while (peer->remotes) {
- fastd_remote_t *remote = peer->remotes;
- peer->remotes = remote->next;
+ for (i = 0; i < VECTOR_LEN(peer->remotes); i++)
+ free(VECTOR_INDEX(peer->remotes, i).addresses);
- fastd_remote_unref(remote);
- }
+ VECTOR_FREE(peer->remotes);
free(peer);
}
@@ -435,11 +435,12 @@ bool fastd_peer_matches_address(const fastd_peer_t *peer, const fastd_peer_addre
if (fastd_peer_is_floating(peer))
return true;
- fastd_remote_t *remote;
- for (remote = peer->remotes; remote; remote = remote->next) {
- size_t i;
- for (i = 0; i < remote->n_addresses; i++) {
- if (fastd_peer_address_equal(&remote->addresses[i], addr))
+ size_t i, j;
+ for (i = 0; i < VECTOR_LEN(peer->remotes); i++) {
+ fastd_remote_t *remote = &VECTOR_INDEX(peer->remotes, i);
+
+ for (j = 0; j < remote->n_addresses; j++) {
+ if (fastd_peer_address_equal(&remote->addresses[j], addr))
return true;
}
}
@@ -578,22 +579,19 @@ fastd_peer_t* fastd_peer_add(fastd_peer_config_t *peer_conf) {
peer->group = find_peer_group(ctx.peer_group, peer_conf->group);
peer->protocol_config = peer_conf->protocol_config;
- fastd_remote_t **remote = &peer->remotes;
- fastd_remote_config_t *remote_config = peer_conf->remotes;
+ VECTOR_ALLOC(peer->remotes, 0);
- while (remote_config) {
- *remote = calloc(1, sizeof(fastd_remote_t));
- (*remote)->ref = 1;
- (*remote)->config = remote_config;
+ fastd_remote_config_t *remote_config;
+ for (remote_config = peer_conf->remotes; remote_config; remote_config = remote_config->next) {
+ fastd_remote_t remote = {.config = remote_config};
if (!remote_config->hostname) {
- (*remote)->n_addresses = 1;
- (*remote)->addresses = malloc(sizeof(fastd_peer_address_t));
- (*remote)->addresses[0] = remote_config->address;
+ remote.n_addresses = 1;
+ remote.addresses = malloc(sizeof(fastd_peer_address_t));
+ remote.addresses[0] = remote_config->address;
}
- remote = &(*remote)->next;
- remote_config = remote_config->next;
+ VECTOR_ADD(peer->remotes, remote);
}
pr_verbose("adding peer %P (group `%s')", peer, peer->group->conf->name);
diff --git a/src/peer.h b/src/peer.h
index 41cee20..804dbeb 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -43,8 +43,8 @@ struct fastd_peer {
struct timespec timeout;
struct timespec keepalive_timeout;
- fastd_remote_t *remotes;
- fastd_remote_t *next_remote;
+ VECTOR(fastd_remote_t) remotes;
+ ssize_t next_remote;
struct timespec next_handshake;
fastd_dlist_head_t handshake_entry;
@@ -84,10 +84,6 @@ struct fastd_peer_eth_addr {
};
struct fastd_remote {
- fastd_remote_t *next;
-
- size_t ref;
-
fastd_remote_config_t *config;
size_t n_addresses;
@@ -95,7 +91,6 @@ struct fastd_remote {
fastd_peer_address_t *addresses;
struct timespec last_resolve_timeout;
- bool resolving;
};
struct fastd_remote_config {
@@ -173,6 +168,13 @@ static inline bool fastd_peer_is_temporary(const fastd_peer_t *peer) {
return (!peer->config);
}
+static inline fastd_remote_t * fastd_peer_get_next_remote(fastd_peer_t *peer) {
+ if (peer->next_remote < 0)
+ return NULL;
+
+ return &VECTOR_INDEX(peer->remotes, peer->next_remote);
+}
+
static inline bool fastd_peer_is_established(const fastd_peer_t *peer) {
switch(peer->state) {
case STATE_ESTABLISHED:
@@ -183,17 +185,6 @@ static inline bool fastd_peer_is_established(const fastd_peer_t *peer) {
}
}
-static inline void fastd_remote_ref(fastd_remote_t *remote) {
- remote->ref++;
-}
-
-static inline void fastd_remote_unref(fastd_remote_t *remote) {
- if(!--remote->ref) {
- free(remote->addresses);
- free(remote);
- }
-}
-
static inline bool fastd_remote_is_dynamic(const fastd_remote_t *remote) {
return remote->config->hostname;
}
diff --git a/src/resolve.c b/src/resolve.c
index e791687..7c512ee 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -33,7 +33,8 @@
typedef struct resolv_arg {
- fastd_remote_t *remote;
+ uint64_t peer_id;
+ size_t remote;
char *hostname;
fastd_peer_address_t constraints;
} resolv_arg_t;
@@ -71,6 +72,7 @@ static void* resolve_peer(void *varg) {
uint8_t retbuf[sizeof(fastd_async_resolve_return_t) + n_addr*sizeof(fastd_peer_address_t)] __attribute__((aligned(8)));
fastd_async_resolve_return_t *ret = (fastd_async_resolve_return_t*)retbuf;
+ ret->peer_id = arg->peer_id;
ret->remote = arg->remote;
if (n_addr) {
@@ -107,11 +109,6 @@ void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote) {
if (!peer->config)
exit_bug("trying to resolve temporary peer");
- if (remote->resolving) {
- pr_debug("not resolving %P as there is already a resolve running", peer);
- return;
- }
-
if (!fastd_timed_out(&remote->last_resolve_timeout)) {
/* last resolve was just a few seconds ago */
return;
@@ -119,13 +116,12 @@ void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote) {
pr_verbose("resolving host `%s' for peer %P...", remote->config->hostname, peer);
- fastd_remote_ref(remote);
remote->last_resolve_timeout = fastd_in_seconds(conf.min_resolve_interval);
- remote->resolving = true;
resolv_arg_t *arg = malloc(sizeof(resolv_arg_t));
- arg->remote = remote;
+ arg->peer_id = peer->id;
+ arg->remote = remote - VECTOR_DATA(peer->remotes);
arg->hostname = strdup(remote->config->hostname);
arg->constraints = remote->config->address;