summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--runtime/Makefile.am1
-rw-r--r--runtime/rsyslog.c166
-rw-r--r--runtime/rsyslog.h6
-rw-r--r--syslogd.c61
-rw-r--r--syslogd.h1
6 files changed, 186 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 29c12e9c..d88a124c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+- split of a "runtime library" for rsyslog - this is not yet a clean
+ model, because some modularization is still outstanding. In theory,
+ this shall enable other utilities but rsyslogd to use the same
+ runtime
---------------------------------------------------------------------------
Version 3.17.1 (rgerhards), 2008-04-15
- removed dependency on MAXHOSTNAMELEN as much as it made sense.
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 8cb3a638..6cd54f91 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -5,6 +5,7 @@ pkglib_LTLIBRARIES =
#pkglib_LTLIBRARIES = librsyslog.la
librsyslog_la_SOURCES = \
+ rsyslog.c \
rsyslog.h \
atomic.h \
syslogd-types.h \
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
new file mode 100644
index 00000000..0d983bb1
--- /dev/null
+++ b/runtime/rsyslog.c
@@ -0,0 +1,166 @@
+/* rsyslog.c - the main entry point into rsyslog's runtime library (RTL)
+ *
+ * This module contains all function which work on a RTL global level. It's
+ * name is abbreviated to "rsrt" (rsyslog runtime).
+ *
+ * Please note that the runtime library is plugin-safe. That is, it must be
+ * initialized by calling a global initialization function. However, that
+ * function checks if the library is already initialized and, if so, does
+ * nothing except incrementing a refeence count. Similarly, the deinit
+ * function does nothing as long as there are still other users (which
+ * is tracked via the refcount). As such, it is safe to call init and
+ * exit multiple times, as long as this are always matching calls. This
+ * capability is needed for a plugin system, where one plugin never
+ * knows what the other did.
+ *
+ * The rsyslog runtime library is in general reentrant and thread-safe. There
+ * are some intentional exceptions (e.g. inside the msg object). These are
+ * documented. Any other threading and reentrency issue can be considered a bug.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "vm.h"
+#include "sysvar.h"
+#include "stringbuf.h"
+#include "wti.h"
+#include "wtp.h"
+#include "expr.h"
+#include "ctok.h"
+#include "vmop.h"
+#include "vmstk.h"
+#include "vmprg.h"
+#include "datetime.h"
+#include "queue.h"
+#include "conf.h"
+
+/* static data */
+static int iRefCount = 0; /* our refcount - it MUST exist only once inside a process (not thread)
+ thus it is perfectly OK to use a static. MUST be initialized to 0! */
+
+/* globally initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * If ppErrObj is provided, it receives a char pointer to the name of the object that
+ * caused the problem (if one occured). The caller must never free this pointer. If
+ * ppErrObj is NULL, no such information will be provided. pObjIF is the pointer to
+ * the "obj" object interface, which may be used to query any other rsyslog objects.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
+{
+ DEFiRet;
+
+ if(iRefCount == 0) {
+ /* init runtime only if not yet done */
+ if(ppErrObj != NULL) *ppErrObj = "obj";
+ CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
+ CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */
+
+ /* initialize core classes. We must be very careful with the order of events. Some
+ * classes use others and if we do not initialize them in the right order, we may end
+ * up with an invalid call. The most important thing that can happen is that an error
+ * is detected and needs to be logged, wich in turn requires a broader number of classes
+ * to be available. The solution is that we take care in the order of calls AND use a
+ * class immediately after it is initialized. And, of course, we load those classes
+ * first that we use ourselfs... -- rgerhards, 2008-03-07
+ */
+ if(ppErrObj != NULL) *ppErrObj = "datetime";
+ CHKiRet(datetimeClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "msg";
+ CHKiRet(msgClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "str,";
+ CHKiRet(strmClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wti";
+ CHKiRet(wtiClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "wtp";
+ CHKiRet(wtpClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "queue";
+ CHKiRet(queueClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmstk";
+ CHKiRet(vmstkClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "sysvar";
+ CHKiRet(sysvarClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vm";
+ CHKiRet(vmClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmop";
+ CHKiRet(vmopClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "vmprg";
+ CHKiRet(vmprgClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "ctok_token";
+ CHKiRet(ctok_tokenClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "ctok";
+ CHKiRet(ctokClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "expr";
+ CHKiRet(exprClassInit(NULL));
+ if(ppErrObj != NULL) *ppErrObj = "conf";
+ CHKiRet(confClassInit(NULL));
+
+ /* dummy "classes" */
+ if(ppErrObj != NULL) *ppErrObj = "str";
+ CHKiRet(strInit());
+ }
+
+ ++iRefCount;
+ dbgprintf("rsyslog runtime initialized, version %s, current users %d\n", VERSION, iRefCount);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* globally de-initialze the runtime system
+ * NOTE: this is NOT thread safe and must not be called concurrently. If that
+ * ever poses a problem, we may use proper mutex calls - not considered needed yet.
+ * This function must be provided with the caller's obj object pointer. This is
+ * automatically deinitialized by the runtime system.
+ * rgerhards, 2008-04-16
+ */
+rsRetVal
+rsrtExit(obj_if_t *pObjIF)
+{
+ DEFiRet;
+
+ if(iRefCount == 1) {
+ /* do actual de-init only if we are the last runtime user */
+ confClassExit();
+ objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
+ }
+
+ --iRefCount;
+ /* TODO we must deinit this pointer! pObjIF = NULL; / * no longer exists for this caller */
+
+ dbgprintf("rsyslog runtime de-initialized, current users %d\n", iRefCount);
+
+ RETiRet;
+}
+
+
+/* vim:set ai:
+ */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 2bc7f904..2dfc266b 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -46,6 +46,7 @@
/* define some base data types */
typedef struct thrdInfo thrdInfo_t;
+typedef struct filed selector_t; /* TODO: this so far resides in syslogd.c, think about modularization */
/* some universal 64 bit define... */
typedef long long int64;
@@ -266,6 +267,11 @@ typedef unsigned char uchar;
void dbgprintf(char *, ...) __attribute__((format(printf, 1, 2)));
#include "debug.h"
+#include "obj.h"
+
+/* some runtime prototypes */
+rsRetVal rsrtInit(char **ppErrObj, obj_if_t *pObjIF);
+rsRetVal rsrtExit(obj_if_t *pObjIF);
#endif /* multi-include protection */
/* vim:set ai:
diff --git a/syslogd.c b/syslogd.c
index ef12424b..68ffe5ce 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -152,15 +152,8 @@
#include "threads.h"
#include "queue.h"
#include "stream.h"
-#include "wti.h"
-#include "wtp.h"
-#include "expr.h"
-#include "ctok.h"
#include "conf.h"
-#include "vmop.h"
-#include "vmstk.h"
#include "vm.h"
-#include "vmprg.h"
#include "errmsg.h"
#include "datetime.h"
#include "sysvar.h"
@@ -2830,8 +2823,9 @@ static void mainThread()
}
-/* Method to initialize all global classes.
+/* Method to initialize all global classes and use the objects that we need.
* rgerhards, 2008-01-04
+ * rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime
*/
static rsRetVal
InitGlobalClasses(void)
@@ -2839,67 +2833,31 @@ InitGlobalClasses(void)
DEFiRet;
char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */
- pErrObj = "obj";
- CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
- CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
- /* the following classes were intialized by objClassInit() */
+ /* Intialize the runtime system */
+ pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */
+ CHKiRet(rsrtInit(&pErrObj, &obj));
+
+ /* Now tell the system which classes we need ourselfs */
pErrObj = "errmsg";
CHKiRet(objUse(errmsg, CORE_COMPONENT));
pErrObj = "module";
CHKiRet(objUse(module, CORE_COMPONENT));
pErrObj = "var";
CHKiRet(objUse(var, CORE_COMPONENT));
-
- /* initialize and use classes. We must be very careful with the order of events. Some
- * classes use others and if we do not initialize them in the right order, we may end
- * up with an invalid call. The most important thing that can happen is that an error
- * is detected and needs to be logged, wich in turn requires a broader number of classes
- * to be available. The solution is that we take care in the order of calls AND use a
- * class immediately after it is initialized. And, of course, we load those classes
- * first that we use ourselfs... -- rgerhards, 2008-03-07
- */
pErrObj = "datetime";
- CHKiRet(datetimeClassInit(NULL));
CHKiRet(objUse(datetime, CORE_COMPONENT));
- pErrObj = "msg";
- CHKiRet(msgClassInit(NULL));
- pErrObj = "str,";
- CHKiRet(strmClassInit(NULL));
- pErrObj = "wti";
- CHKiRet(wtiClassInit(NULL));
- pErrObj = "wtp";
- CHKiRet(wtpClassInit(NULL));
- pErrObj = "queue";
- CHKiRet(queueClassInit(NULL));
- pErrObj = "vmstk";
- CHKiRet(vmstkClassInit(NULL));
- pErrObj = "sysvar";
- CHKiRet(sysvarClassInit(NULL));
pErrObj = "vm";
- CHKiRet(vmClassInit(NULL));
CHKiRet(objUse(vm, CORE_COMPONENT));
- pErrObj = "vmop";
- CHKiRet(vmopClassInit(NULL));
- pErrObj = "vmprg";
- CHKiRet(vmprgClassInit(NULL));
- pErrObj = "ctok_token";
- CHKiRet(ctok_tokenClassInit(NULL));
- pErrObj = "ctok";
- CHKiRet(ctokClassInit(NULL));
pErrObj = "expr";
- CHKiRet(exprClassInit(NULL));
CHKiRet(objUse(expr, CORE_COMPONENT));
pErrObj = "conf";
- CHKiRet(confClassInit(NULL));
CHKiRet(objUse(conf, CORE_COMPONENT));
- /* dummy "classes" */
+ /* intialize some dummy classes that are not part of the runtime */
pErrObj = "action";
CHKiRet(actionClassInit());
pErrObj = "template";
CHKiRet(templateInit());
- pErrObj = "str";
- CHKiRet(strInit());
/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
pErrObj = "net";
@@ -2939,7 +2897,6 @@ GlobalClassExit(void)
objRelease(datetime, CORE_COMPONENT);
/* TODO: implement the rest of the deinit */
- confClassExit();
#if 0
CHKiRet(datetimeClassInit(NULL));
CHKiRet(msgClassInit(NULL));
@@ -2969,7 +2926,7 @@ GlobalClassExit(void)
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
#endif
- objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
+ rsrtExit(&obj); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
RETiRet;
}
diff --git a/syslogd.h b/syslogd.h
index 46de8d28..a26af519 100644
--- a/syslogd.h
+++ b/syslogd.h
@@ -113,7 +113,6 @@ struct filed {
linkedList_t llActList; /* list of configured actions */
};
-typedef struct filed selector_t; /* new type name */
#define MSG_PARSE_HOSTNAME 1