diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1c12f922f..83fb2745f 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -181,6 +181,9 @@ static struct lightningd *new_lightningd(const tal_t *ctx) * linked-list as part of the 100k-peers project! */ ld->peers = tal(ld, struct peer_node_id_map); peer_node_id_map_init(ld->peers); + /*~ And this was done at the same time, for db lookups at startup */ + ld->peers_by_dbid = tal(ld, struct peer_dbid_map); + peer_dbid_map_init(ld->peers_by_dbid); /*~ For multi-part payments, we need to keep some incoming payments * in limbo until we get all the parts, or we time them out. */ diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index a7eaad336..22e47010e 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -181,6 +181,8 @@ struct lightningd { /* All peers we're tracking (by node_id) */ struct peer_node_id_map *peers; + /* And those in database by dbid */ + struct peer_dbid_map *peers_by_dbid; /* Outstanding connect commands. */ struct list_head connects; diff --git a/lightningd/memdump.c b/lightningd/memdump.c index 1a14c349d..64cfa6bec 100644 --- a/lightningd/memdump.c +++ b/lightningd/memdump.c @@ -156,6 +156,7 @@ static void finish_report(const struct leak_detect *leaks) memleak_scan_htable(memtable, &ld->htlcs_out->raw); memleak_scan_htable(memtable, &ld->htlc_sets->raw); memleak_scan_htable(memtable, &ld->peers->raw); + memleak_scan_htable(memtable, &ld->peers_by_dbid->raw); /* Now delete ld and those which it has pointers to. */ memleak_scan_obj(memtable, ld); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 24123ec26..bb3128bca 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -72,6 +72,8 @@ static void destroy_peer(struct peer *peer) { peer_node_id_map_del(peer->ld->peers, peer); + if (peer->dbid) + peer_dbid_map_del(peer->ld->peers_by_dbid, peer); } static void peer_update_features(struct peer *peer, @@ -81,6 +83,14 @@ static void peer_update_features(struct peer *peer, peer->their_features = tal_dup_talarr(peer, u8, their_features); } +void peer_set_dbid(struct peer *peer, u64 dbid) +{ + assert(!peer->dbid); + assert(dbid); + peer->dbid = dbid; + peer_dbid_map_add(peer->ld->peers_by_dbid, peer); +} + struct peer *new_peer(struct lightningd *ld, u64 dbid, const struct node_id *id, const struct wireaddr_internal *addr, @@ -107,6 +117,8 @@ struct peer *new_peer(struct lightningd *ld, u64 dbid, #endif peer_node_id_map_add(ld->peers, peer); + if (dbid) + peer_dbid_map_add(ld->peers_by_dbid, peer); tal_add_destructor(peer, destroy_peer); return peer; } @@ -131,6 +143,7 @@ void maybe_delete_peer(struct peer *peer) /* This isn't sufficient to keep it in db! */ if (peer->dbid != 0) { wallet_peer_delete(peer->ld->wallet, peer->dbid); + peer_dbid_map_del(peer->ld->peers_by_dbid, peer); peer->dbid = 0; } return; @@ -177,17 +190,7 @@ static void peer_channels_cleanup(struct lightningd *ld, struct peer *find_peer_by_dbid(struct lightningd *ld, u64 dbid) { - struct peer *p; - struct peer_node_id_map_iter it; - - /* FIXME: Support lookup by dbid directly! */ - for (p = peer_node_id_map_first(ld->peers, &it); - p; - p = peer_node_id_map_next(ld->peers, &it)) { - if (p->dbid == dbid) - return p; - } - return NULL; + return peer_dbid_map_get(ld->peers_by_dbid, dbid); } struct peer *peer_by_id(struct lightningd *ld, const struct node_id *id) diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index c5f11bbee..a967866bf 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -102,6 +102,9 @@ u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx); /* We've loaded peers from database, set them going. */ void setup_peers(struct lightningd *ld); +/* When database first writes peer into db, it sets the dbid */ +void peer_set_dbid(struct peer *peer, u64 dbid); + /* At startup, re-send any transactions we want bitcoind to have */ void resend_closing_transactions(struct lightningd *ld); @@ -156,4 +159,24 @@ HTABLE_DEFINE_TYPE(struct peer, peer_node_id, node_id_hash, peer_node_id_eq, peer_node_id_map); +static inline size_t dbid_hash(u64 dbid) +{ + return siphash24(siphash_seed(), &dbid, sizeof(dbid)); +} + +static u64 peer_dbid(const struct peer *peer) +{ + assert(peer->dbid); + return peer->dbid; +} + +static bool peer_dbid_eq(const struct peer *peer, u64 dbid) +{ + return peer->dbid == dbid; +} +/* Defines struct peer_dbid_map */ +HTABLE_DEFINE_TYPE(struct peer, + peer_dbid, dbid_hash, peer_dbid_eq, + peer_dbid_map); + #endif /* LIGHTNING_LIGHTNINGD_PEER_CONTROL_H */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 2113ba84f..037bb20b9 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1934,6 +1934,8 @@ int main(int argc, const char *argv[]) /* Only elements in ld we should access */ ld->peers = tal(ld, struct peer_node_id_map); peer_node_id_map_init(ld->peers); + ld->peers_by_dbid = tal(ld, struct peer_dbid_map); + peer_dbid_map_init(ld->peers_by_dbid); ld->rr_counter = 0; node_id_from_hexstr("02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66, &ld->id); /* Accessed in peer destructor sanity check */ diff --git a/wallet/wallet.c b/wallet/wallet.c index 673736443..2822732f1 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2155,7 +2155,7 @@ static void wallet_peer_save(struct wallet *w, struct peer *peer) if (db_step(stmt)) { /* So we already knew this peer, just return its dbid */ - peer->dbid = db_col_u64(stmt, "id"); + peer_set_dbid(peer, db_col_u64(stmt, "id")); tal_free(stmt); /* Since we're at it update the wireaddr */ @@ -2174,7 +2174,7 @@ static void wallet_peer_save(struct wallet *w, struct peer *peer) db_bind_node_id(stmt, 0, &peer->id); db_bind_text(stmt, 1,addr); db_exec_prepared_v2(stmt); - peer->dbid = db_last_insert_id_v2(take(stmt)); + peer_set_dbid(peer, db_last_insert_id_v2(take(stmt))); } }