From 5adfca9b651e0e383d463da9e8158e75cad8e7c7 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 25 Apr 2014 01:51:36 +0200 Subject: 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. --- src/async.c | 27 +++++++------------------- src/async.h | 4 +++- src/fastd.c | 31 ++++++++++++++++-------------- src/peer.c | 62 +++++++++++++++++++++++++++++------------------------------ src/peer.h | 27 +++++++++----------------- src/resolve.c | 14 +++++--------- 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; -- cgit v1.2.3