From da845b660b20abea0b234a68dc8333d5c40992e7 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 10 Apr 2019 17:01:29 +0930 Subject: [PATCH] gossipd: gossip_store_get() to load a single store entry. This will allow us to load on demand, and not keep all messages in memory. Signed-off-by: Rusty Russell --- gossipd/gossip_store.c | 57 ++++++++++++++++++++++++++++++++++++++++++ gossipd/gossip_store.h | 9 +++++++ 2 files changed, 66 insertions(+) diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 7896934cc..4312c07df 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -329,6 +329,63 @@ void gossip_store_add_channel_delete(struct gossip_store *gs, tal_free(msg); } +const u8 *gossip_store_get(const tal_t *ctx, + struct gossip_store *gs, + u64 offset) +{ + beint32_t belen, becsum; + u32 msglen, checksum; + u8 *msg, *gossip_msg; + struct amount_sat satoshis; + + if (offset == 0 || offset > gs->len) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: can't access offset %"PRIu64 + ", store len %"PRIu64, + offset, gs->len); + if (lseek(gs->fd, offset, SEEK_SET) < 0) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: can't seek offset %"PRIu64 + ", store len %"PRIu64": %s", + offset, gs->len, strerror(errno)); + + if (read(gs->fd, &belen, sizeof(belen)) != sizeof(belen) + || read(gs->fd, &becsum, sizeof(becsum)) != sizeof(becsum)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: can't read hdr offset %"PRIu64 + ", store len %"PRIu64": %s", + offset, gs->len, strerror(errno)); + } + + msglen = be32_to_cpu(belen); + checksum = be32_to_cpu(becsum); + msg = tal_arr(ctx, u8, msglen); + if (read(gs->fd, msg, msglen) != msglen) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: can't read len %u offset %"PRIu64 + ", store len %"PRIu64, + msglen, offset, gs->len); + + if (checksum != crc32c(0, msg, msglen)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: bad checksum offset %"PRIu64 + ", store len %"PRIu64, + offset, gs->len); + + /* Now try decoding it */ + if (!fromwire_gossip_store_node_announcement(ctx, msg, &gossip_msg) + && !fromwire_gossip_store_channel_announcement(ctx, msg, + &gossip_msg, + &satoshis) + && !fromwire_gossip_store_channel_update(ctx, msg, &gossip_msg)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "gossip_store: bad message %s offset %"PRIu64 + " from store len %"PRIu64, + tal_hex(tmpctx, msg), offset, gs->len); + } + return gossip_msg; +} + void gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) { beint32_t belen, becsum; diff --git a/gossipd/gossip_store.h b/gossipd/gossip_store.h index 49788debb..b37be3855 100644 --- a/gossipd/gossip_store.h +++ b/gossipd/gossip_store.h @@ -38,6 +38,15 @@ u64 gossip_store_add(struct gossip_store *gs, const u8 *gossip_msg); void gossip_store_add_channel_delete(struct gossip_store *gs, const struct short_channel_id *scid); +/** + * Direct store accessor: loads gossip msg back from store. + * + * Caller must ensure offset != 0. Never returns NULL. + */ +const u8 *gossip_store_get(const tal_t *ctx, + struct gossip_store *gs, + u64 offset); + /** * If we need to compact the gossip store, do so. * @gs: the gossip store.