Browse Source

gossipd/gossip_store: keep count of deleted entries, don't use bs->count.

We didn't count some records before, so we could compare the two counters.
This is much simpler, and avoids reliance on bs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
htlc_accepted_hook
Rusty Russell 6 years ago
parent
commit
5161b79bfc
  1. 47
      gossipd/gossip_store.c
  2. 2
      tests/test_gossip.py

47
gossipd/gossip_store.c

@ -33,8 +33,9 @@ struct gossip_store {
u64 len; u64 len;
/* Counters for entries in the gossip_store entries. This is used to /* Counters for entries in the gossip_store entries. This is used to
* decide whether we should rewrite the on-disk store or not */ * decide whether we should rewrite the on-disk store or not.
size_t count; * Note: count includes deleted. */
size_t count, deleted;
/* Handle to the routing_state to retrieve additional information, /* Handle to the routing_state to retrieve additional information,
* should it be needed */ * should it be needed */
@ -75,7 +76,7 @@ static bool append_msg(int fd, const u8 *msg, u32 timestamp, u64 *len)
struct gossip_store *gossip_store_new(struct routing_state *rstate) struct gossip_store *gossip_store_new(struct routing_state *rstate)
{ {
struct gossip_store *gs = tal(rstate, struct gossip_store); struct gossip_store *gs = tal(rstate, struct gossip_store);
gs->count = 0; gs->count = gs->deleted = 0;
gs->writable = true; gs->writable = true;
gs->fd = open(GOSSIP_STORE_FILENAME, O_RDWR|O_APPEND|O_CREAT, 0600); gs->fd = open(GOSSIP_STORE_FILENAME, O_RDWR|O_APPEND|O_CREAT, 0600);
gs->rstate = rstate; gs->rstate = rstate;
@ -161,13 +162,10 @@ static size_t transfer_store_msg(int from_fd, size_t from_off, int to_fd,
/* Local unannounced channels don't appear in broadcast map, but we need to /* Local unannounced channels don't appear in broadcast map, but we need to
* remember them anyway, so we manually append to the store. * remember them anyway, so we manually append to the store.
* */
* Note these do *not* add to gs->count, since that's compared with
* the broadcast map count.
*/
static bool add_local_unnannounced(int in_fd, int out_fd, static bool add_local_unnannounced(int in_fd, int out_fd,
struct node *self, struct node *self,
u64 *len) u64 *len, size_t *count)
{ {
struct chan_map_iter i; struct chan_map_iter i;
struct chan *c; struct chan *c;
@ -184,6 +182,7 @@ static bool add_local_unnannounced(int in_fd, int out_fd,
&peer->id, c->sat); &peer->id, c->sat);
if (!append_msg(out_fd, msg, 0, len)) if (!append_msg(out_fd, msg, 0, len))
return false; return false;
(*count)++;
for (size_t i = 0; i < 2; i++) { for (size_t i = 0; i < 2; i++) {
size_t len_with_header; size_t len_with_header;
@ -202,6 +201,7 @@ static bool add_local_unnannounced(int in_fd, int out_fd,
c->half[i].bcast.index = *len; c->half[i].bcast.index = *len;
*len += len_with_header; *len += len_with_header;
(*count)++;
} }
} }
@ -236,7 +236,7 @@ bool gossip_store_compact(struct gossip_store *gs,
assert(oldb); assert(oldb);
status_trace( status_trace(
"Compacting gossip_store with %zu entries, %zu of which are stale", "Compacting gossip_store with %zu entries, %zu of which are stale",
gs->count, gs->count - oldb->count); gs->count, gs->deleted);
newb = new_broadcast_state(gs->rstate, gs, oldb->peers); newb = new_broadcast_state(gs->rstate, gs, oldb->peers);
fd = open(GOSSIP_STORE_TEMP_FILENAME, O_RDWR|O_APPEND|O_CREAT, 0600); fd = open(GOSSIP_STORE_TEMP_FILENAME, O_RDWR|O_APPEND|O_CREAT, 0600);
@ -281,18 +281,24 @@ bool gossip_store_compact(struct gossip_store *gs,
goto unlink_disable; goto unlink_disable;
} }
len += msg_len; len += msg_len;
/* This amount field doesn't add to count. */ count++;
} }
} }
/* Local unannounced channels are not in the store! */ /* Local unannounced channels are not in the store! */
self = get_node(gs->rstate, &gs->rstate->local_id); self = get_node(gs->rstate, &gs->rstate->local_id);
if (self && !add_local_unnannounced(gs->fd, fd, self, &len)) { if (self && !add_local_unnannounced(gs->fd, fd, self, &len, &count)) {
status_broken("Failed writing unannounced to gossip store: %s", status_broken("Failed writing unannounced to gossip store: %s",
strerror(errno)); strerror(errno));
goto unlink_disable; goto unlink_disable;
} }
if (count != gs->count - gs->deleted) {
status_broken("Expected %zu msgs in new gossip store, got %zu",
gs->count - gs->deleted, count);
goto unlink_disable;
}
if (rename(GOSSIP_STORE_TEMP_FILENAME, GOSSIP_STORE_FILENAME) == -1) { if (rename(GOSSIP_STORE_TEMP_FILENAME, GOSSIP_STORE_FILENAME) == -1) {
status_broken( status_broken(
"Error swapping compacted gossip_store into place: %s", "Error swapping compacted gossip_store into place: %s",
@ -302,8 +308,9 @@ bool gossip_store_compact(struct gossip_store *gs,
status_trace( status_trace(
"Compaction completed: dropped %zu messages, new count %zu, len %"PRIu64, "Compaction completed: dropped %zu messages, new count %zu, len %"PRIu64,
gs->count - count, count, len); gs->deleted, count, len);
gs->count = count; gs->count = count;
gs->deleted = 0;
*offset = gs->len - len; *offset = gs->len - len;
gs->len = len; gs->len = len;
close(gs->fd); close(gs->fd);
@ -334,7 +341,7 @@ bool gossip_store_maybe_compact(struct gossip_store *gs,
return false; return false;
if (gs->count < 1000) if (gs->count < 1000)
return false; return false;
if (gs->count < (*bs)->count * 1.25) if (gs->deleted < gs->count / 4)
return false; return false;
return gossip_store_compact(gs, bs, offset); return gossip_store_compact(gs, bs, offset);
@ -361,6 +368,8 @@ u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg,
} }
gs->count++; gs->count++;
if (addendum)
gs->count++;
return off; return off;
} }
@ -412,6 +421,7 @@ void gossip_store_delete(struct gossip_store *gs,
"Failed writing len to delete @%u: %s", "Failed writing len to delete @%u: %s",
bcast->index, strerror(errno)); bcast->index, strerror(errno));
fcntl(gs->fd, F_SETFL, flags); fcntl(gs->fd, F_SETFL, flags);
gs->deleted++;
} }
const u8 *gossip_store_get(const tal_t *ctx, const u8 *gossip_store_get(const tal_t *ctx,
@ -505,8 +515,10 @@ void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)
} }
/* Skip deleted entries */ /* Skip deleted entries */
if (be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_DELETED_BIT) if (be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_DELETED_BIT) {
gs->deleted++;
goto next; goto next;
}
switch (fromwire_peektype(msg)) { switch (fromwire_peektype(msg)) {
case WIRE_GOSSIP_STORE_CHANNEL_AMOUNT: case WIRE_GOSSIP_STORE_CHANNEL_AMOUNT:
@ -570,8 +582,7 @@ void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs)
goto truncate; goto truncate;
} }
if (fromwire_peektype(msg) != WIRE_GOSSIP_STORE_CHANNEL_AMOUNT) gs->count++;
gs->count++;
next: next:
gs->len += sizeof(hdr) + msglen; gs->len += sizeof(hdr) + msglen;
clean_tmpctx(); clean_tmpctx();
@ -592,8 +603,8 @@ truncate_nomsg:
out: out:
status_trace("total store load time: %"PRIu64" msec", status_trace("total store load time: %"PRIu64" msec",
time_to_msec(time_between(time_now(), start))); time_to_msec(time_between(time_now(), start)));
status_trace("gossip_store: Read %zu/%zu/%zu/%zu cannounce/cupdate/nannounce/cdelete from store in %"PRIu64" bytes", status_trace("gossip_store: Read %zu/%zu/%zu/%zu cannounce/cupdate/nannounce/cdelete from store (%zu deleted) in %"PRIu64" bytes",
stats[0], stats[1], stats[2], stats[3], stats[0], stats[1], stats[2], stats[3], gs->deleted,
gs->len); gs->len);
gs->writable = true; gs->writable = true;
} }

2
tests/test_gossip.py

@ -885,7 +885,7 @@ def test_gossip_store_load(node_factory):
l1.start() l1.start()
# May preceed the Started msg waited for in 'start'. # May preceed the Started msg waited for in 'start'.
wait_for(lambda: l1.daemon.is_in_log('gossip_store: Read 1/1/1/0 cannounce/cupdate/nannounce/cdelete from store in 770 bytes')) wait_for(lambda: l1.daemon.is_in_log(r'gossip_store: Read 1/1/1/0 cannounce/cupdate/nannounce/cdelete from store \(0 deleted\) in 770 bytes'))
assert not l1.daemon.is_in_log('gossip_store.*truncating') assert not l1.daemon.is_in_log('gossip_store.*truncating')

Loading…
Cancel
Save