lightningd: avoid keeping multiple copies of nodeid.

Simple refcount FTW.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2019-11-18 10:57:17 +10:30
parent 4fc498f901
commit 0c6d8996fc
2 changed files with 60 additions and 9 deletions

View File

@ -3,6 +3,7 @@
#include <backtrace.h>
#include <ccan/array_size/array_size.h>
#include <ccan/err/err.h>
#include <ccan/htable/htable_type.h>
#include <ccan/io/io.h>
#include <ccan/opt/opt.h>
#include <ccan/read_write_all/read_write_all.h>
@ -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);
}

View File

@ -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 */