diff --git a/include/villas/hooks.h b/include/villas/hooks.h index 8dbd4c09c..110e01ba6 100644 --- a/include/villas/hooks.h +++ b/include/villas/hooks.h @@ -74,6 +74,15 @@ struct hook_info { */ typedef int (*hook_cb_t)(struct hook *h, int when, struct hook_info *i); +/** Destructor callback for hook_storage() + * + * @param data A pointer to the data which should be destroyed. + */ +typedef void (*dtor_cb_t)(void *); + +/** Constructor callback for hook_storage() */ +typedef int (*ctor_cb_t)(void *); + enum hook_state { HOOK_DESTROYED, HOOK_INITIALIZED @@ -157,7 +166,7 @@ int hook_run(struct path *p, struct sample *smps[], size_t cnt, int when); * @param len The size of hook prvate memory allocation. * @return A pointer to the allocated memory region or NULL after it was released. */ -void * hook_storage(struct hook *h, int when, size_t len); +void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_cb_t dtor); int hook_print(struct hook *h, int when, struct hook_info *j); int hook_ts(struct hook *h, int when, struct hook_info *j); diff --git a/lib/hooks.c b/lib/hooks.c index 5ffcc9044..daad04c42 100644 --- a/lib/hooks.c +++ b/lib/hooks.c @@ -75,14 +75,21 @@ int hook_run(struct path *p, struct sample *smps[], size_t cnt, int when) return cnt; } -void * hook_storage(struct hook *h, int when, size_t len) +void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_cb_t dtor) { switch (when) { case HOOK_INIT: h->_vd = alloc(len); + + if (ctor) + ctor(h->_vd); + break; case HOOK_DESTROY: + if (dtor) + dtor(h->_vd); + free(h->_vd); h->_vd = NULL; break; diff --git a/lib/hooks/hooks-other.c b/lib/hooks/hooks-other.c index 86733cb19..0a63ea5fa 100644 --- a/lib/hooks/hooks-other.c +++ b/lib/hooks/hooks-other.c @@ -46,10 +46,10 @@ int hook_convert(struct hook *h, int when, struct hook_info *k) TO_FIXED, TO_FLOAT } mode; - } *private = hook_storage(h, when, sizeof(*private)); + } *private = hook_storage(h, when, sizeof(*private), NULL, NULL); switch (when) { - case HOOK_DESTROY: + case HOOK_PARSE: if (!h->parameter) error("Missing parameter for hook: '%s'", h->name); @@ -83,7 +83,7 @@ int hook_decimate(struct hook *h, int when, struct hook_info *j) struct { unsigned ratio; unsigned counter; - } *private = hook_storage(h, when, sizeof(*private)); + } *private = hook_storage(h, when, sizeof(*private), NULL, NULL); switch (when) { case HOOK_PARSE: @@ -123,7 +123,7 @@ int hook_skip_first(struct hook *h, int when, struct hook_info *j) struct { struct timespec skip; /**< Time to wait until first message is not skipped */ struct timespec until; /**< Absolute point in time from where we accept samples. */ - } *private = hook_storage(h, when, sizeof(*private)); + } *private = hook_storage(h, when, sizeof(*private), NULL, NULL); char *endptr; double wait; diff --git a/lib/hooks/hooks-stats.c b/lib/hooks/hooks-stats.c index 4b787b78f..e0139efff 100644 --- a/lib/hooks/hooks-stats.c +++ b/lib/hooks/hooks-stats.c @@ -17,13 +17,9 @@ extern struct list *hook_nodes; REGISTER_HOOK("stats", "Collect statistics for the current path", 2, 1, hook_stats, HOOK_STATS) int hook_stats(struct hook *h, int when, struct hook_info *j) { - struct stats *s = hook_storage(h, when, sizeof(struct stats)); + struct stats *s = hook_storage(h, when, sizeof(struct stats), (ctor_cb_t) stats_init, (dtor_cb_t) stats_destroy); switch (when) { - case HOOK_INIT: - stats_init(s); - break; - case HOOK_READ: assert(j->smps); @@ -31,11 +27,7 @@ int hook_stats(struct hook *h, int when, struct hook_info *j) break; case HOOK_PATH_STOP: - stats_print(s); - break; - - case HOOK_DESTROY: - stats_destroy(s); + stats_print(s, 1); break; case HOOK_PATH_RESTART: