summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-10-29 16:22:20 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2013-10-29 16:22:20 +0100
commit343df920c9b1b469daefde1688459234e4b29d73 (patch)
treed4cb2f72da036dbe07130b7d42a0e15e5dbf9363
parent64a4358384699478babd8bd90c724c171b1c549f (diff)
parentffc64138fdc6a40b0ee4dca290900ca4a3965f24 (diff)
downloadrsyslog-343df920c9b1b469daefde1688459234e4b29d73.tar.gz
rsyslog-343df920c9b1b469daefde1688459234e4b29d73.tar.bz2
rsyslog-343df920c9b1b469daefde1688459234e4b29d73.zip
Merge branch 'master' into master-ruleeng
-rw-r--r--ChangeLog17
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac21
-rw-r--r--doc/manual.html2
-rw-r--r--doc/mmsequence.html148
-rw-r--r--doc/rsyslog_conf_modules.html1
-rw-r--r--grammar/rainerscript.c13
-rw-r--r--plugins/mmsequence/Makefile.am8
-rw-r--r--plugins/mmsequence/mmsequence.c396
-rw-r--r--runtime/glbl.c1
-rw-r--r--runtime/msg.c16
-rw-r--r--runtime/ruleset.c6
12 files changed, 616 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index fc3f40ec..d46ee682 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,10 @@
-- bugfix: unset statement always worked on message var, even if local
- var was given
---------------------------------------------------------------------------
-Version 7.5.6 [devel] 2013-10-??
+Version 7.5.6 [devel] 2013-10-29
+- improved performance of RainerScript variable access
+ by refactoring the whole body of variable handling code. This also
+ solves some of the anomalies experienced in some versions of rsyslog.
+ All variable types are now handled in unified code, including
+ access via templates.
- RainerScript: make use of 64 bit for numbers where available
Thanks to Pavel Levshin for enhancement.
- slight performance optimization if GCC is used
@@ -14,6 +17,10 @@ Version 7.5.6 [devel] 2013-10-??
such, we consider the current approach as an experiment that did not
work out and opt to removing it, clearing the way for a better future
solution. Note: global vars were introduced in 7.5.3 on Sept, 11th 2013.
+- new module mmsequence, primarily used for action load balancing
+ Thanks to Pavel Levshin for contributing this module.
+- bugfix: unset statement always worked on message var, even if local
+ var was given
- imudp: support for binding to ruleset added
- bugfix: segfault if variable was assigned to non-container subtree
Thanks to Pavel Levshin for the fix
@@ -207,6 +214,10 @@ Version 7.4.6 [v7.4-stable] 2013-11-??
Thanks to Pavel Levshin for reporting the problem and its location.
- bugfix: memleak in re_extract() function
Thanks to Pavel Levshin for reporting this problem.
+- bugfix: potential abort in RainerScript optimizer
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=488
+ Thanks to Thomas Doll for reporting the problem and Pavel Levshin for
+ fixing it.
- bugfix: memory leak in omhiredis
Thanks to Pavel Levshin for the fix
- bugfix: segfault if variable was assigned to non-container subtree
diff --git a/Makefile.am b/Makefile.am
index c5e41c75..6eb7b5b8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -249,6 +249,10 @@ if ENABLE_MMCOUNT
SUBDIRS += plugins/mmcount
endif
+if ENABLE_MMSEQUENCE
+SUBDIRS += plugins/mmsequence
+endif
+
if ENABLE_MMFIELDS
SUBDIRS += plugins/mmfields
endif
diff --git a/configure.ac b/configure.ac
index dfe12dac..3abd559e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[7.5.5],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[7.5.6],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -993,8 +993,8 @@ AM_CONDITIONAL(ENABLE_MMUTF8FIX, test x$enable_mmutf8fix = xyes)
AC_ARG_ENABLE(mmcount,
[AS_HELP_STRING([--enable-mmcount],[Enable message counting @<:@default=no@:>@])],
[case "${enableval}" in
- yes) enable_xmpp="yes" ;;
- no) enable_xmpp="no" ;;
+ yes) enable_mmcount="yes" ;;
+ no) enable_mmcount="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mmcount) ;;
esac],
[enable_mmcount=no]
@@ -1002,6 +1002,19 @@ AC_ARG_ENABLE(mmcount,
AM_CONDITIONAL(ENABLE_MMCOUNT, test x$enable_mmcount = xyes)
+# mmsequence
+AC_ARG_ENABLE(mmsequence,
+ [AS_HELP_STRING([--enable-mmsequence],[Enable sequence generator @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mmsequence="yes" ;;
+ no) enable_mmsequence="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mmsequence) ;;
+ esac],
+ [enable_mmsequence=no]
+)
+AM_CONDITIONAL(ENABLE_MMSEQUENCE, test x$enable_mmsequence = xyes)
+
+
# mmfields
AC_ARG_ENABLE(mmfields,
[AS_HELP_STRING([--enable-mmfields],[Enable building mmfields support @<:@default=no@:>@])],
@@ -1564,6 +1577,7 @@ AC_CONFIG_FILES([Makefile \
plugins/mmanon/Makefile \
plugins/mmutf8fix/Makefile \
plugins/mmcount/Makefile \
+ plugins/mmsequence/Makefile \
plugins/mmfields/Makefile \
plugins/mmpstrucdata/Makefile \
plugins/mmrfc5424addhmac/Makefile \
@@ -1633,6 +1647,7 @@ echo " mmsnmptrapd module will be compiled: $enable_mmsnmptrapd"
echo " mmutf8fix enabled: $enable_mmutf8fix"
echo " mmrfc5424addhmac enabled: $enable_mmrfc5424addhmac"
echo " mmpstrucdata enabled: $enable_mmpstrucdata"
+echo " mmsequence enabled: $enable_mmsequence"
echo
echo "---{ strgen modules }---"
echo " sm_cust_bindcdr module will be compiled: $enable_sm_cust_bindcdr"
diff --git a/doc/manual.html b/doc/manual.html
index 3bc803ca..3e3625d9 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ professional services</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 7.5.5 (devel branch) of rsyslog.</b>
+<p><b>This documentation is for version 7.5.6 (devel branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/mmsequence.html b/doc/mmsequence.html
new file mode 100644
index 00000000..75ac57b4
--- /dev/null
+++ b/doc/mmsequence.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en">
+<title>mmsequence</title></head>
+
+<body>
+<a href="rsyslog_conf_modules.html">back</a>
+
+<h1>Number generator and counter module (mmsequence)</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; mmsequence</b></p>
+<p><b>Author: </b>Pavel Levshin &lt;pavel@levshin.spb.ru&gt;</p>
+<p><b>Status: </b>Non project-supported module - contact author
+or rsyslog mailing list for questions</p>
+<p><b>Available since</b>: 7.5.6</p>
+<p><b>Description</b>:</p>
+<p>This module generates numeric sequences of different kinds. It can be used
+to count messages up to a limit and to number them. It can generate random
+numbers in a given range.</p>
+
+<p>This module is implemented via the output module interface, so it is
+called just as an action. The number generated is stored in a variable.</p>
+<p>&nbsp;</p>
+<p><b>Action Parameters</b>:</p>
+<ul>
+<li><b>mode</b> "random" or "instance" or "key"
+ <p>Specifies mode of the action. In "random" mode, the module
+ generates uniformly distributed integer numbers in a range defined
+ by "from" and "to".</p>
+
+ <p>In "instance" mode, which is default, the action produces a counter
+ in range [from, to). This counter is specific to this action instance.</p>
+
+ <p>In "key" mode, the counter can be shared between multiple instances.
+ This counter is identified by a name, which is defined with "key"
+ parameter.</p>
+</li>
+<li><b>from</b> [non-negative integer], default "0"
+ <p>Starting value for counters and lower margin for random generator.</p>
+</li>
+<li><b>to</b> [positive integer], default "INT_MAX"
+ <p>Upper margin for all sequences. Note that this margin is not
+ inclusive. When next value for a counter is equal or greater than
+ this parameter, the counter resets to the starting value.</p>
+</li>
+<li><b>step</b> [non-negative integer], default "1"
+ <p>Increment for counters. If step is "0", it can be used to fetch
+ current value without modification. The latter not applies to
+ "random" mode. This is useful in "key" mode or to get constant
+ values in "instance" mode.</p>
+</li>
+<li><b>key</b> [word], default ""
+ <p>Name of the global counter which is used in this action.</p>
+</li>
+<li><b>var</b> [word], default "$!mmsequence"
+ <p>Name of the variable where the number will be stored.
+ Should start with "$".</p>
+</li>
+</ul>
+
+
+<p><b>Sample</b>:</p>
+<pre>
+# load balance
+Ruleset(
+ name="logd"
+ queue.workerthreads="5"
+ ){
+
+ Action(
+ type="mmsequence"
+ mode="instance"
+ from="0"
+ to="2"
+ var="$.seq"
+ )
+
+ if $.seq == "0" then {
+ Action(
+ type="mmnormalize"
+ userawmsg="on"
+ rulebase="/etc/rsyslog.d/rules.rb"
+ )
+ } else {
+ Action(
+ type="mmnormalize"
+ userawmsg="on"
+ rulebase="/etc/rsyslog.d/rules.rb"
+ )
+ }
+
+ # output logic here
+}
+ # generate random numbers
+ action(
+ type="mmsequence"
+ mode="random"
+ to="100"
+ var="$!rndz"
+ )
+ # count from 0 to 99
+ action(
+ type="mmsequence"
+ mode="instance"
+ to="100"
+ var="$!cnt1"
+ )
+ # the same as before but the counter is global
+ action(
+ type="mmsequence"
+ mode="key"
+ key="key1"
+ to="100"
+ var="$!cnt2"
+ )
+ # count specific messages but place the counter in every message
+ if $msg contains "txt" then
+ action(
+ type="mmsequence"
+ mode="key"
+ to="100"
+ var="$!cnt3"
+ )
+ else
+ action(
+ type="mmsequence"
+ mode="key"
+ to="100"
+ step="0"
+ var="$!cnt3"
+ key=""
+ )
+</pre>
+
+
+<p><b>Legacy Configuration Directives</b>:</p>
+
+ <p>Not supported.</p>
+
+
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>] [<a href="manual.html">manual
+index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a> project.<br>
+Copyright &copy; 2008-2013 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL
+version 3 or higher.</font></p>
+
+</body></html>
diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html
index dbec96f8..8dc3ed56 100644
--- a/doc/rsyslog_conf_modules.html
+++ b/doc/rsyslog_conf_modules.html
@@ -126,6 +126,7 @@ the output module interface.
<li><a href="mmutf8fix.html">mmutf8fix</a> - used to fix invalid UTF-8 character sequences
<li><a href="mmrfc5424addhmac.html">mmrfc5424addhmac</a> - custom module for adding HMACs to
rfc5424-formatted messages if not already present
+<li><a href="mmsequence.html">mmsequence</a> - sequence generator and counter plugin
</ul>
<a name="lm"></a><h2>String Generator Modules</h2>
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 30c36201..76b91940 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -2469,7 +2469,9 @@ cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
doIndent(indent); dbgprintf("PROPFILT\n");
doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
propIDToName(stmt->d.s_propfilt.prop.id));
- if(stmt->d.s_propfilt.prop.name != NULL) {
+ if(stmt->d.s_propfilt.prop.id == PROP_CEE ||
+ stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR ||
+ stmt->d.s_propfilt.prop.id == PROP_GLOBAL_VAR) {
doIndent(indent);
dbgprintf("\tCEE-Prop.: '%s'\n", stmt->d.s_propfilt.prop.name);
}
@@ -3068,12 +3070,15 @@ cnfexprOptimize(struct cnfexpr *expr)
expr->r = exprswap;
}
}
- if(expr->l->nodetype == 'V') {
- expr = cnfexprOptimize_CMP_var(expr);
- }
if(expr->r->nodetype == 'A') {
cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r);
}
+ /* This should be evaluated last because it may change expr
+ * to a function.
+ */
+ if(expr->l->nodetype == 'V') {
+ expr = cnfexprOptimize_CMP_var(expr);
+ }
break;
case CMP_LE:
case CMP_GE:
diff --git a/plugins/mmsequence/Makefile.am b/plugins/mmsequence/Makefile.am
new file mode 100644
index 00000000..543d6d84
--- /dev/null
+++ b/plugins/mmsequence/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = mmsequence.la
+
+mmsequence_la_SOURCES = mmsequence.c
+mmsequence_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+mmsequence_la_LDFLAGS = -module -avoid-version
+mmsequence_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/mmsequence/mmsequence.c b/plugins/mmsequence/mmsequence.c
new file mode 100644
index 00000000..20a85370
--- /dev/null
+++ b/plugins/mmsequence/mmsequence.c
@@ -0,0 +1,396 @@
+/* mmsequence.c
+ * Generate a number based on some sequence.
+ *
+ * Copyright 2013 pavel@levshin.spb.ru.
+ *
+ * Based on: mmcount.c
+ * Copyright 2013 Red Hat Inc.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <time.h>
+#include <limits.h>
+#include <json/json.h>
+#include <pthread.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "hashtable.h"
+
+#define JSON_VAR_NAME "$!mmsequence"
+
+enum mmSequenceModes {
+ mmSequenceRandom,
+ mmSequencePerInstance,
+ mmSequencePerKey
+};
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("mmsequence")
+
+
+DEFobjCurrIf(errmsg);
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+typedef struct _instanceData {
+ enum mmSequenceModes mode;
+ int valueFrom;
+ int valueTo;
+ int step;
+ unsigned int seed;
+ int value;
+ char *pszKey;
+ char *pszVar;
+} instanceData;
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+};
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current exec process */
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "mode", eCmdHdlrGetWord, 0 },
+ { "from", eCmdHdlrNonNegInt, 0 },
+ { "to", eCmdHdlrPositiveInt, 0 },
+ { "step", eCmdHdlrNonNegInt, 0 },
+ { "key", eCmdHdlrGetWord, 0 },
+ { "var", eCmdHdlrGetWord, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+/* table for key-counter pairs */
+static struct hashtable *ght;
+static pthread_mutex_t ght_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ENDbeginCnfLoad
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ENDendCnfLoad
+
+BEGINcheckCnf
+CODESTARTcheckCnf
+ENDcheckCnf
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+ENDactivateCnf
+
+BEGINfreeCnf
+CODESTARTfreeCnf
+ENDfreeCnf
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->mode = mmSequencePerInstance;
+ pData->valueFrom = 0;
+ pData->valueTo = INT_MAX;
+ pData->step = 1;
+ pData->pszKey = "";
+ pData->pszVar = JSON_VAR_NAME;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ char *cstr;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (mmsequence)\n");
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG));
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "mode")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"random",
+ sizeof("random")-1)) {
+ pData->mode = mmSequenceRandom;
+ } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"instance",
+ sizeof("instance")-1)) {
+ pData->mode = mmSequencePerInstance;
+ } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"key",
+ sizeof("key")-1)) {
+ pData->mode = mmSequencePerKey;
+ } else {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ errmsg.LogError(0, RS_RET_INVLD_MODE,
+ "mmsequence: invalid mode '%s' - ignored",
+ cstr);
+ free(cstr);
+ }
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "from")) {
+ pData->valueFrom = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "to")) {
+ pData->valueTo = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "step")) {
+ pData->step = pvals[i].val.d.n;
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "key")) {
+ pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL);
+ continue;
+ }
+ if(!strcmp(actpblk.descr[i].name, "var")) {
+ cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ if (strlen(cstr) < 3) {
+ errmsg.LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmsequence: valid variable name should be at least "
+ "3 symbols long, got %s", cstr);
+ free(cstr);
+ } else if (cstr[0] != '$') {
+ errmsg.LogError(0, RS_RET_VALUE_NOT_SUPPORTED,
+ "mmsequence: valid variable name should start with $,"
+ "got %s", cstr);
+ free(cstr);
+ } else {
+ pData->pszVar = cstr;
+ }
+ continue;
+ }
+ dbgprintf("mmsequence: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ switch(pData->mode) {
+ case mmSequenceRandom:
+ pData->seed = (unsigned int)(intptr_t)pData ^ (unsigned int)time(NULL);
+ break;
+ case mmSequencePerInstance:
+ pData->value = pData->valueTo;
+ break;
+ case mmSequencePerKey:
+ if (pthread_mutex_lock(&ght_mutex)) {
+ DBGPRINTF("mmsequence: mutex lock has failed!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if (ght == NULL) {
+ if(NULL == (ght = create_hashtable(100, hash_from_string, key_equals_string, NULL))) {
+ pthread_mutex_unlock(&ght_mutex);
+ DBGPRINTF("mmsequence: error creating hash table!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ pthread_mutex_unlock(&ght_mutex);
+ break;
+ default:
+ errmsg.LogError(0, RS_RET_INVLD_MODE,
+ "mmsequence: this mode is not currently implemented");
+ }
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+static int *
+getCounter(struct hashtable *ht, char *str, int initial) {
+ int *pCounter;
+ char *pStr;
+
+ pCounter = hashtable_search(ht, str);
+ if(pCounter) {
+ return pCounter;
+ }
+
+ /* counter is not found for the str, so add new entry and
+ return the counter */
+ if(NULL == (pStr = strdup(str))) {
+ DBGPRINTF("mmsequence: memory allocation for key failed\n");
+ return NULL;
+ }
+
+ if(NULL == (pCounter = (int*)malloc(sizeof(*pCounter)))) {
+ DBGPRINTF("mmsequence: memory allocation for value failed\n");
+ free(pStr);
+ return NULL;
+ }
+ *pCounter = initial;
+
+ if(!hashtable_insert(ht, pStr, pCounter)) {
+ DBGPRINTF("mmsequence: inserting element into hashtable failed\n");
+ free(pStr);
+ free(pCounter);
+ return NULL;
+ }
+ return pCounter;
+}
+
+
+BEGINdoAction
+ msg_t *pMsg;
+ struct json_object *json;
+ int val = 0;
+ int *pCounter;
+CODESTARTdoAction
+ pMsg = (msg_t*) ppString[0];
+
+ switch(pData->mode) {
+ case mmSequenceRandom:
+ val = pData->valueFrom + (rand_r(&pData->seed) %
+ (pData->valueTo - pData->valueFrom));
+ break;
+ case mmSequencePerInstance:
+ if (pData->value >= pData->valueTo - pData->step) {
+ pData->value = pData->valueFrom;
+ } else {
+ pData->value += pData->step;
+ }
+ val = pData->value;
+ break;
+ case mmSequencePerKey:
+ if (!pthread_mutex_lock(&ght_mutex)) {
+ pCounter = getCounter(ght, pData->pszKey, pData->valueTo);
+ if(pCounter) {
+ if (*pCounter >= pData->valueTo - pData->step
+ || *pCounter < pData->valueFrom ) {
+ *pCounter = pData->valueFrom;
+ } else {
+ *pCounter += pData->step;
+ }
+ val = *pCounter;
+ } else {
+ errmsg.LogError(0, RS_RET_NOT_FOUND,
+ "mmsequence: unable to fetch the counter from hash");
+ }
+ pthread_mutex_unlock(&ght_mutex);
+ } else {
+ errmsg.LogError(0, RS_RET_ERR,
+ "mmsequence: mutex lock has failed!");
+ }
+
+ break;
+ default:
+ errmsg.LogError(0, RS_RET_NOT_IMPLEMENTED,
+ "mmsequence: this mode is not currently implemented");
+ }
+
+ /* finalize_it: */
+ json = json_object_new_int(val);
+ if (json == NULL) {
+ errmsg.LogError(0, RS_RET_OBJ_CREATION_FAILED,
+ "mmsequence: unable to create JSON");
+ } else if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)pData->pszVar + 1, json)) {
+ errmsg.LogError(0, RS_RET_OBJ_CREATION_FAILED,
+ "mmsequence: unable to pass out the value");
+ json_object_put(json);
+ }
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(strncmp((char*) p, ":mmsequence:", sizeof(":mmsequence:") - 1)) {
+ errmsg.LogError(0, RS_RET_LEGA_ACT_NOT_SUPPORTED,
+ "mmsequence supports only v6+ config format, use: "
+ "action(type=\"mmsequence\" ...)");
+ }
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(errmsg, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+ENDqueryEtryPt
+
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ DBGPRINTF("mmsequence: module compiled with rsyslog version %s.\n", VERSION);
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ENDmodInit
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 17ae0451..e1d4e92d 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -447,7 +447,6 @@ finalize_it:
static prop_t*
GetLocalHostNameProp(void)
{
- prop.AddRef(propLocalHostName);
return(propLocalHostName);
}
diff --git a/runtime/msg.c b/runtime/msg.c
index 21ab18e5..5df4e031 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -359,7 +359,7 @@ MsgSetRcvFromIPWithoutAddRef(msg_t *pThis, prop_t *new)
/* set RcvFrom name in msg object WITHOUT calling AddRef.
* rgerhards, 2013-01-22
*/
-void MsgSetRcvFrom(msg_t *pThis, prop_t *new)
+void MsgSetRcvFromWithoutAddRef(msg_t *pThis, prop_t *new)
{
assert(pThis != NULL);
@@ -401,7 +401,7 @@ resolveDNS(msg_t *pMsg) {
localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip);
if(localRet == RS_RET_OK) {
/* we pass down the props, so no need for AddRef */
- MsgSetRcvFrom(pMsg, localName);
+ MsgSetRcvFromWithoutAddRef(pMsg, localName);
MsgSetRcvFromIPWithoutAddRef(pMsg, ip);
}
}
@@ -2244,6 +2244,18 @@ finalize_it:
RETiRet;
}
+/* rgerhards 2008-09-10: set RcvFrom name in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-30
+ */
+void MsgSetRcvFrom(msg_t *pThis, prop_t *new)
+{
+ prop.AddRef(new);
+ MsgSetRcvFromWithoutAddRef(pThis, new);
+}
+
+
/* This is used to set the property via a string. This function should not be
* called if there is a reliable way for a caller to make sure that the
* same name can be used across multiple messages. However, if it can not
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 3e5223f9..db253d28 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -446,9 +446,9 @@ evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
} else if(stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR) {
DBGPRINTF("Filter: check for local var '%s' (value '%s') ",
stmt->d.s_propfilt.prop.name, pszPropVal);
- //} else if(stmt->d.s_propfilt.propID == PROP_GLOBAL_VAR) {
- //DBGPRINTF("Filter: check for global var '%s' (value '%s') ",
- //stmt->d.s_propfilt.propName, pszPropVal);
+ } else if(stmt->d.s_propfilt.prop.id == PROP_GLOBAL_VAR) {
+ DBGPRINTF("Filter: check for global var '%s' (value '%s') ",
+ stmt->d.s_propfilt.prop.name, pszPropVal);
} else {
DBGPRINTF("Filter: check for property '%s' (value '%s') ",
propIDToName(stmt->d.s_propfilt.prop.id), pszPropVal);