diff --git a/include/villas/hook_list.hpp b/include/villas/hook_list.hpp index 178d04773..9c00fbc8f 100644 --- a/include/villas/hook_list.hpp +++ b/include/villas/hook_list.hpp @@ -65,7 +65,7 @@ int hook_list_prepare_signals(struct vlist *hs, struct vlist *signals); int hook_list_add(struct vlist *hs, int mask, struct vpath *p, struct vnode *n); -int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt); +int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt, bool clone_if_modified = false); void hook_list_periodic(struct vlist *hs); diff --git a/include/villas/node.h b/include/villas/node.h index 396ee6fd4..f4b35dc1b 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -200,7 +200,7 @@ int node_reverse(struct vnode *n); int node_read(struct vnode *n, struct sample * smps[], unsigned cnt); -int node_write(struct vnode *n, struct sample * smps[], unsigned cnt); +int node_write(struct vnode *n, struct sample * smps[], unsigned cnt, bool clone_if_modified = false); int node_poll_fds(struct vnode *n, int fds[]); diff --git a/lib/hook_list.cpp b/lib/hook_list.cpp index 93dfe4604..c42eeac46 100644 --- a/lib/hook_list.cpp +++ b/lib/hook_list.cpp @@ -135,18 +135,27 @@ void hook_list_prepare(struct vlist *hs, vlist *sigs, int m, struct vpath *p, st } } -int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt) +int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt, bool clone_if_modified) { - unsigned current, processed = 0; + unsigned processed = 0; if (vlist_length(hs) == 0) return cnt; - for (current = 0; current < cnt; current++) { - struct sample *smp = smps[current]; + for (unsigned i = 0; i < cnt; i++) { + struct sample *smp, *old_smp; - for (size_t i = 0; i < vlist_length(hs); i++) { - Hook *h = (Hook *) vlist_at(hs, i); + if (clone_if_modified) { + old_smp = smps[i]; + smps[i] = sample_clone(old_smp); + + sample_decref(old_smp); + } + + smp = smps[i]; + + for (size_t j = 0; j < vlist_length(hs); j++) { + Hook *h = (Hook *) vlist_at(hs, j); auto ret = h->process(smp); smp->signals = h->getSignals(); @@ -165,7 +174,7 @@ int hook_list_process(struct vlist *hs, struct sample * smps[], unsigned cnt) } } -stop: SWAP(smps[processed], smps[current]); +stop: SWAP(smps[processed], smps[i]); processed++; skip: {} } diff --git a/lib/node.cpp b/lib/node.cpp index a8fc2a0b9..8d55d54ea 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -494,7 +494,7 @@ int node_read(struct vnode *n, struct sample * smps[], unsigned cnt) #endif /* WITH_HOOKS */ } -int node_write(struct vnode *n, struct sample * smps[], unsigned cnt) +int node_write(struct vnode *n, struct sample * smps[], unsigned cnt, bool clone_if_modified) { int tosend, sent, nsent = 0; unsigned vect; @@ -508,7 +508,7 @@ int node_write(struct vnode *n, struct sample * smps[], unsigned cnt) #ifdef WITH_HOOKS /* Run write hooks */ - cnt = hook_list_process(&n->out.hooks, smps, cnt); + cnt = hook_list_process(&n->out.hooks, smps, cnt, clone_if_modified && !n->out.read_only_hooks); if (cnt <= 0) return cnt; #endif /* WITH_HOOKS */ diff --git a/lib/node_direction.cpp b/lib/node_direction.cpp index 9f34090cb..0f33999b9 100644 --- a/lib/node_direction.cpp +++ b/lib/node_direction.cpp @@ -42,6 +42,8 @@ int node_direction_prepare(struct vnode_direction *nd, struct vnode *n) int m = nd->builtin ? t | (int) Hook::Flags::BUILTIN : 0; hook_list_prepare(&nd->hooks, &nd->signals, m, nullptr, n); + + nd->read_only_hooks = hook_list_is_read_only(&nd->hooks); #endif /* WITH_HOOKS */ nd->state = State::PREPARED; @@ -58,6 +60,7 @@ int node_direction_init(struct vnode_direction *nd, enum NodeDir dir, struct vno nd->vectorize = 1; nd->builtin = 1; nd->path = nullptr; + nd->read_only_hooks = false; #ifdef WITH_HOOKS ret = hook_list_init(&nd->hooks);