diff --git a/lightningd/log.c b/lightningd/log.c index fd98393c3..9d86c2ad4 100644 --- a/lightningd/log.c +++ b/lightningd/log.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ struct log_book { * is more directly because the notification needs ld->plugins. */ struct lightningd *ld; + /* Cache of all node_ids, to avoid multiple copies. */ + struct node_id_map *cache; }; struct log { @@ -69,6 +72,32 @@ struct log { enum log_level *print_level; }; +/* Avoids duplicate node_id entries. */ +struct node_id_cache { + size_t count; + struct node_id node_id; +}; + +static const struct node_id *node_cache_id(const struct node_id_cache *nc) +{ + return &nc->node_id; +} + +static size_t node_id_hash(const struct node_id *id) +{ + return siphash24(siphash_seed(), id->k, sizeof(id->k)); +} + +static bool node_id_cache_eq(const struct node_id_cache *nc, + const struct node_id *node_id) +{ + return node_id_eq(&nc->node_id, node_id); +} + +HTABLE_DEFINE_TYPE(struct node_id_cache, + node_cache_id, node_id_hash, node_id_cache_eq, + node_id_map); + static const char *level_prefix(enum log_level level) { switch (level) { @@ -152,6 +181,8 @@ static size_t prune_log(struct log_book *log) list_del_from(&log->log, &i->list); log->mem_used -= mem_used(i); + if (i->nc && --i->nc->count == 0) + tal_free(i->nc); tal_free(i); skipped++; deleted++; @@ -174,6 +205,8 @@ struct log_book *new_log_book(struct lightningd *ld, size_t max_mem) list_head_init(&lr->print_filters); lr->init_time = time_now(); lr->ld = ld; + lr->cache = tal(lr, struct node_id_map); + node_id_map_init(lr->cache); list_head_init(&lr->log); return lr; @@ -247,6 +280,11 @@ static void add_entry(struct log *log, struct log_entry *l) } } +static void destroy_node_id_cache(struct node_id_cache *nc, struct log_book *lr) +{ + node_id_map_del(lr->cache, nc); +} + static struct log_entry *new_log_entry(struct log *log, enum log_level level, const struct node_id *node_id) { @@ -259,10 +297,19 @@ static struct log_entry *new_log_entry(struct log *log, enum log_level level, l->io = NULL; if (!node_id) node_id = log->default_node_id; - if (node_id) - l->node_id = tal_dup(l, struct node_id, node_id); - else - l->node_id = NULL; + if (node_id) { + l->nc = node_id_map_get(log->lr->cache, node_id); + if (!l->nc) { + l->nc = tal(log->lr->cache, struct node_id_cache); + l->nc->count = 0; + l->nc->node_id = *node_id; + node_id_map_add(log->lr->cache, l->nc); + tal_add_destructor2(l->nc, destroy_node_id_cache, + log->lr); + } + l->nc->count++; + } else + l->nc = NULL; return l; } @@ -271,7 +318,8 @@ static void maybe_print(struct log *log, const struct log_entry *l, size_t offset) { if (l->level >= log_print_level(log)) - log_to_file(log->prefix, l->level, l->node_id, offset != 0, + log_to_file(log->prefix, l->level, + l->nc ? &l->nc->node_id : NULL, offset != 0, &l->time, l->log + offset, l->io, tal_bytelen(l->io), log->lr->outf); } @@ -315,7 +363,8 @@ void log_io(struct log *log, enum log_level dir, /* Print first, in case we need to truncate. */ if (l->level >= log_print_level(log)) - log_to_file(log->prefix, l->level, l->node_id, false, + log_to_file(log->prefix, l->level, + l->nc ? &l->nc->node_id : NULL, false, &l->time, str, data, len, log->lr->outf); @@ -400,7 +449,8 @@ static void log_each_line_(const struct log_book *lr, list_for_each(&lr->log, i, list) { func(i->skipped, time_between(i->time, lr->init_time), - i->level, i->node_id, i->prefix, i->log, i->io, arg); + i->level, i->nc ? &i->nc->node_id : NULL, + i->prefix, i->log, i->io, arg); } } @@ -644,7 +694,8 @@ void logging_options_parsed(struct log_book *lr) /* Catch up, since before we were only printing BROKEN msgs */ list_for_each(&lr->log, l, list) { if (l->level >= filter_level(lr, l->prefix)) - log_to_file(l->prefix, l->level, l->node_id, false, + log_to_file(l->prefix, l->level, + l->nc ? &l->nc->node_id : NULL, false, &l->time, l->log, l->io, tal_bytelen(l->io), lr->outf); } diff --git a/lightningd/log.h b/lightningd/log.h index 1c0504cb0..f50044111 100644 --- a/lightningd/log.h +++ b/lightningd/log.h @@ -81,7 +81,7 @@ struct log_entry { struct timeabs time; enum log_level level; unsigned int skipped; - struct node_id *node_id; + struct node_id_cache *nc; const char *prefix; char *log; /* Iff LOG_IO */