summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2012-09-21 10:41:05 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2012-09-21 10:41:05 +0200
commit87f415f16fec001a4f87e18817bace73f19d6416 (patch)
tree400d0e8ccd876cb40c1b6d59bc08b48a0034ae14
parentbda0ef62f01ab86f5f4d84fb3d0eb25c14aaea55 (diff)
downloadrsyslog-87f415f16fec001a4f87e18817bace73f19d6416.tar.gz
rsyslog-87f415f16fec001a4f87e18817bace73f19d6416.tar.xz
rsyslog-87f415f16fec001a4f87e18817bace73f19d6416.zip
Implement script optimization IF -> PRIFILT
-rw-r--r--grammar/rainerscript.c82
-rw-r--r--grammar/rainerscript.h2
-rw-r--r--runtime/ruleset.c32
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/rscript_optimizer1.sh13
-rw-r--r--tests/testsuites/rscript_optimizer1.conf12
6 files changed, 115 insertions, 29 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 5db62abc..9440dd2f 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1382,14 +1382,11 @@ cnffuncDestruct(struct cnffunc *func)
case CNFFUNC_RE_MATCH:
if(func->funcdata != NULL)
regexp.regfree(func->funcdata);
- free(func->funcdata);
- free(func->fname);
- break;
- case CNFFUNC_PRIFILT:
- free(func->funcdata);
break;
default:break;
}
+ free(func->funcdata);
+ free(func->fname);
}
/* Destruct an expression and all sub-expressions contained in it.
@@ -1464,6 +1461,22 @@ doIndent(int indent)
for(i = 0 ; i < indent ; ++i)
dbgprintf(" ");
}
+
+static void
+pmaskPrint(uchar *pmask, int indent)
+{
+ int i;
+ doIndent(indent);
+ dbgprintf("pmask: ");
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ if (pmask[i] == TABLE_NOPRI)
+ dbgprintf(" X ");
+ else
+ dbgprintf("%2X ", pmask[i]);
+ dbgprintf("\n");
+}
+
+
void
cnfexprPrint(struct cnfexpr *expr, int indent)
{
@@ -1570,14 +1583,7 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
if(func->fID == CNFFUNC_PRIFILT) {
struct funcData_prifilt *pD;
pD = (struct funcData_prifilt*) func->funcdata;
- doIndent(indent+1);
- dbgprintf("pmask: ");
- for (i = 0; i <= LOG_NFACILITIES; i++)
- if (pD->pmask[i] == TABLE_NOPRI)
- dbgprintf(" X ");
- else
- dbgprintf("%2X ", pD->pmask[i]);
- dbgprintf("\n");
+ pmaskPrint(pD->pmask, indent+1);
}
for(i = 0 ; i < func->nParams ; ++i) {
cnfexprPrint(func->expr[i], indent+1);
@@ -1641,7 +1647,12 @@ cnfstmtPrint(struct cnfstmt *root, int indent)
break;
case S_PRIFILT:
doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ pmaskPrint(stmt->d.s_prifilt.pmask, indent);
cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
+ if(stmt->d.s_prifilt.t_else != NULL) {
+ doIndent(indent); dbgprintf("ELSE\n");
+ cnfstmtPrint(stmt->d.s_prifilt.t_else, indent+1);
+ }
doIndent(indent); dbgprintf("END PRIFILT\n");
break;
case S_PROPFILT:
@@ -1751,6 +1762,7 @@ cnfstmtDestruct(struct cnfstmt *root)
break;
case S_PRIFILT:
cnfstmtDestruct(stmt->d.s_prifilt.t_then);
+ cnfstmtDestruct(stmt->d.s_prifilt.t_else);
break;
case S_PROPFILT:
if(stmt->d.s_propfilt.propName != NULL)
@@ -1801,6 +1813,7 @@ cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then)
if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) {
cnfstmt->printable = (uchar*)prifilt;
cnfstmt->d.s_prifilt.t_then = t_then;
+ cnfstmt->d.s_prifilt.t_else = NULL;
DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask);
}
return cnfstmt;
@@ -2014,7 +2027,6 @@ removeNOPs(struct cnfstmt *root)
if(root == NULL) goto done;
stmt = root;
while(stmt != NULL) {
-dbgprintf("RRRR: removeNOPs: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
if(stmt->nodetype == S_NOP) {
if(prevstmt != NULL)
/* end chain, is rebuild if more non-NOPs follow */
@@ -2034,6 +2046,41 @@ dbgprintf("RRRR: removeNOPs: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
done: return newRoot;
}
+
+static inline void
+cnfstmtOptimizeIf(struct cnfstmt *stmt)
+{
+ struct cnfstmt *t_then, *t_else;
+ struct cnfexpr *expr;
+ struct cnffunc *func;
+ struct funcData_prifilt *prifilt;
+
+ expr = stmt->d.s_if.expr;
+ cnfexprOptimize(expr);
+ stmt->d.s_if.t_then = removeNOPs(stmt->d.s_if.t_then);
+ stmt->d.s_if.t_else = removeNOPs(stmt->d.s_if.t_else);
+ cnfstmtOptimize(stmt->d.s_if.t_then);
+ cnfstmtOptimize(stmt->d.s_if.t_else);
+
+ if(stmt->d.s_if.expr->nodetype == 'F') {
+ func = (struct cnffunc*)expr;
+ if(func->fID == CNFFUNC_PRIFILT) {
+ DBGPRINTF("optimize IF to PRIFILT\n");
+ t_then = stmt->d.s_if.t_then;
+ t_else = stmt->d.s_if.t_else;
+ stmt->nodetype = S_PRIFILT;
+ prifilt = (struct funcData_prifilt*) func->funcdata;
+ memcpy(stmt->d.s_prifilt.pmask, prifilt->pmask,
+ sizeof(prifilt->pmask));
+ stmt->d.s_prifilt.t_then = t_then;
+ stmt->d.s_prifilt.t_else = t_else;
+ stmt->printable = (uchar*)
+ es_str2cstr(((struct cnfstringval*)func->expr[0])->estr, NULL);
+ cnfexprDestruct(expr);
+ }
+ }
+}
+
/* (recursively) optimize a statement */
void
cnfstmtOptimize(struct cnfstmt *root)
@@ -2044,11 +2091,7 @@ cnfstmtOptimize(struct cnfstmt *root)
dbgprintf("RRRR: stmtOptimize: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
switch(stmt->nodetype) {
case S_IF:
- cnfexprOptimize(stmt->d.s_if.expr);
- stmt->d.s_if.t_then = removeNOPs(stmt->d.s_if.t_then);
- stmt->d.s_if.t_else = removeNOPs(stmt->d.s_if.t_else);
- cnfstmtOptimize(stmt->d.s_if.t_then);
- cnfstmtOptimize(stmt->d.s_if.t_else);
+ cnfstmtOptimizeIf(stmt);
break;
case S_PRIFILT:
stmt->d.s_prifilt.t_then = removeNOPs(stmt->d.s_prifilt.t_then);
@@ -2232,6 +2275,7 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
func->nodetype = 'F';
func->fname = fname;
func->nParams = nParams;
+ func->funcdata = NULL;
func->fID = funcName2ID(fname, nParams);
/* shuffle params over to array (access speed!) */
param = paramlst;
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index bd29ff85..902ff4c5 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -158,6 +158,7 @@ struct cnfstmt {
struct {
uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
} s_prifilt;
struct {
fiop_t operation;
@@ -167,6 +168,7 @@ struct cnfstmt {
uintTiny propID;/* ID of the requested property */
es_str_t *propName;/* name of property for CEE-based filters */
struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
} s_propfilt;
struct action_s *act;
} d;
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index ea8849e2..f37370b4 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -96,8 +96,12 @@ scriptIterateAllActions(struct cnfstmt *root, rsRetVal (*pFunc)(void*, void*), v
pFunc, pParam);
break;
case S_PRIFILT:
- scriptIterateAllActions(stmt->d.s_prifilt.t_then,
- pFunc, pParam);
+ if(stmt->d.s_prifilt.t_then != NULL)
+ scriptIterateAllActions(stmt->d.s_prifilt.t_then,
+ pFunc, pParam);
+ if(stmt->d.s_prifilt.t_else != NULL)
+ scriptIterateAllActions(stmt->d.s_prifilt.t_else,
+ pFunc, pParam);
break;
case S_PROPFILT:
scriptIterateAllActions(stmt->d.s_propfilt.t_then,
@@ -313,11 +317,11 @@ execIf(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
static void
execPRIFILT(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
{
- sbool *thenAct;
+ sbool *newAct;
msg_t *pMsg;
int bRet;
int i;
- thenAct = newActive(pBatch);
+ newAct = newActive(pBatch);
for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
if(pBatch->pElem[i].state == BATCH_STATE_DISC)
continue; /* will be ignored in any case */
@@ -331,12 +335,22 @@ execPRIFILT(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
bRet = 1;
} else
bRet = 0;
- thenAct[i] = bRet;
- DBGPRINTF("batch: item %d PRIFILT %d\n", i, thenAct[i]);
+ newAct[i] = bRet;
+ DBGPRINTF("batch: item %d PRIFILT %d\n", i, newAct[i]);
}
- scriptExec(stmt->d.s_prifilt.t_then, pBatch, thenAct);
- freeActive(thenAct);
+ if(stmt->d.s_prifilt.t_then != NULL) {
+ scriptExec(stmt->d.s_prifilt.t_then, pBatch, newAct);
+ }
+ if(stmt->d.s_prifilt.t_else != NULL) {
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate)
+ ; ++i)
+ if(pBatch->pElem[i].state != BATCH_STATE_DISC)
+{
+ newAct[i] = !newAct[i];
+ scriptExec(stmt->d.s_prifilt.t_else, pBatch, newAct);
+ }
+ freeActive(newAct);
}
@@ -556,8 +570,6 @@ addScript(ruleset_t *pThis, struct cnfstmt *script)
pThis->last->next = script;
pThis->last = script;
}
-dbgprintf("RRRR: ruleset added script, script total now is:\n");
- cnfstmtPrint(pThis->root, 0);
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4765e917..715c024d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -69,6 +69,7 @@ TESTS += \
rscript_stop.sh \
rscript_stop2.sh \
rscript_prifilt.sh \
+ rscript_optimizer1.sh \
cee_simple.sh \
cee_diskqueue.sh \
linkedlistqueue.sh
@@ -281,6 +282,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/rscript_stop2.conf \
rscript_prifilt.sh \
testsuites/rscript_prifilt.conf \
+ rscript_optimizer1.sh \
+ testsuites/rscript_optimizer1.conf \
cee_simple.sh \
testsuites/cee_simple.conf \
cee_diskqueue.sh \
diff --git a/tests/rscript_optimizer1.sh b/tests/rscript_optimizer1.sh
new file mode 100755
index 00000000..1d2dcf87
--- /dev/null
+++ b/tests/rscript_optimizer1.sh
@@ -0,0 +1,13 @@
+# added 2012-09-20 by rgerhards
+# This file is part of the rsyslog project, released under ASL 2.0
+echo ===============================================================================
+echo \[rscript_optimizer1.sh\]: testing rainerscript optimizer
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup rscript_optimizer1.conf
+source $srcdir/diag.sh injectmsg 0 5000
+echo doing shutdown
+source $srcdir/diag.sh shutdown-when-empty
+echo wait on shutdown
+source $srcdir/diag.sh wait-shutdown
+source $srcdir/diag.sh seq-check 0 4999
+source $srcdir/diag.sh exit
diff --git a/tests/testsuites/rscript_optimizer1.conf b/tests/testsuites/rscript_optimizer1.conf
new file mode 100644
index 00000000..7720af7a
--- /dev/null
+++ b/tests/testsuites/rscript_optimizer1.conf
@@ -0,0 +1,12 @@
+$IncludeConfig diag-common.conf
+
+template(name="outfmt" type="list") {
+ property(name="msg" field.delimiter="58" field.number="2")
+ constant(value="\n")
+}
+
+/* tcpflood uses local4.=debug */
+if prifilt("syslog.*") then
+ stop # it actually doesn't matter what we do here
+else
+ action(type="omfile" file="./rsyslog.out.log" template="outfmt")