From dea4b5a016406ad17491d65466c12ebbb1a98e20 Mon Sep 17 00:00:00 2001 From: Yves G Date: Wed, 31 Jan 2018 15:13:03 +0100 Subject: [PATCH] switch from Step.run() recursion to Step.run()-in-a-loop to avoid too-deep call stacks --- TODO.md | 1 - pyruse/base.py | 6 ++---- pyruse/main.py | 8 +++++--- pyruse/workflow.py | 5 +---- tests/main.py | 9 +++++++-- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/TODO.md b/TODO.md index 7e5845b..0366933 100644 --- a/TODO.md +++ b/TODO.md @@ -2,5 +2,4 @@ * Improve documentation, especially on the contents of `pyruse.json`. * Maybe switch from storing the daily journal in a file, to storing it in a database. -* Maybe switch from Step.run() recursion to Step.run()-in-a-loop to avoid too-deep call stacks. * Eventually make the code more elegant, as I learn more about Python… diff --git a/pyruse/base.py b/pyruse/base.py index 54eaafb..7d4cf07 100644 --- a/pyruse/base.py +++ b/pyruse/base.py @@ -36,8 +36,7 @@ class Filter(Step): except Exception as e: nextStep = self.altStep log.error("Error while executing %s: %s." % (type(self), str(e))) - if nextStep: - nextStep.run(entry) + return nextStep class Action(Step): def __init__(self): @@ -54,5 +53,4 @@ class Action(Step): except Exception as e: nextStep = None log.error("Error while executing %s: %s." % (type(self), str(e))) - if nextStep: - nextStep.run(entry) + return nextStep diff --git a/pyruse/main.py b/pyruse/main.py index 818e192..3aa4d49 100644 --- a/pyruse/main.py +++ b/pyruse/main.py @@ -17,7 +17,7 @@ def _setPyrusePaths(): sys.path.insert(1, p) PYRUSE_PATHS.insert(0, os.curdir) -def _doForEachJournalEntry(fct): +def _doForEachJournalEntry(workflow): j = journal.Reader(journal.SYSTEM_ONLY) j.seek_tail() j.get_previous() @@ -25,7 +25,9 @@ def _doForEachJournalEntry(fct): event = j.wait(None) if event == journal.APPEND: for entry in j: - fct(entry) + step = workflow.firstStep + while step is not None: + step = step.run(entry) def boot(modName): if "action_" in modName: @@ -39,7 +41,7 @@ def main(): _setPyrusePaths() conf = config.Config(PYRUSE_PATHS).asMap().get("actions", {}) wf = workflow.Workflow(conf) - _doForEachJournalEntry(wf.run) + _doForEachJournalEntry(wf) if __name__ == '__main__': main() diff --git a/pyruse/workflow.py b/pyruse/workflow.py index 8b07b9b..53c232d 100644 --- a/pyruse/workflow.py +++ b/pyruse/workflow.py @@ -18,10 +18,7 @@ class Workflow: for setter in dangling: setter(entryPoint) dangling = newDangling - self.run = firstStep.run if firstStep else self._noRun - - def _noRun(self, whatever): - pass + self.firstStep = firstStep def _initChain(self, actions, label, seen): dangling = [] diff --git a/tests/main.py b/tests/main.py index ec6d43c..7dbf22a 100644 --- a/tests/main.py +++ b/tests/main.py @@ -53,9 +53,9 @@ def main(): ] _clean() for e in test: - wf.run(e) + run(wf, e) actions.action_dailyReport.Action._hour = 25 - wf.run(entry("bck", "login", "Failed password for root from ::1", 11)) + run(wf, entry("bck", "login", "Failed password for root from ::1", 11)) for f in ['acted_on.log', 'email.dump', 'nftBan.cmd', 'unfiltered.log']: assert os.path.exists(f), "file should exist: " + f try: @@ -83,5 +83,10 @@ def entry(host, service, message, microsecond = None): "MESSAGE": message } +def run(workflow, logEntry): + step = workflow.firstStep + while step is not None: + step = step.run(logEntry) + if __name__ == '__main__': main()