summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Meckelein <mmeckelein@hq.adiscon.com>2004-12-08 10:20:02 +0000
committerMichael Meckelein <mmeckelein@hq.adiscon.com>2004-12-08 10:20:02 +0000
commitdbdfb25343a525b852e0954b80c5654aeb6fd175 (patch)
treee2a6fbe8a33d09e96b6de632db11b9148b3d7c7b
parentae1f5ac3fe907f77cd31a96bad2c494687f9f273 (diff)
downloadrsyslog-dbdfb25343a525b852e0954b80c5654aeb6fd175.tar.gz
rsyslog-dbdfb25343a525b852e0954b80c5654aeb6fd175.tar.xz
rsyslog-dbdfb25343a525b852e0954b80c5654aeb6fd175.zip
DB error handling
-rw-r--r--Makefile6
-rw-r--r--syslogd.c186
2 files changed, 159 insertions, 33 deletions
diff --git a/Makefile b/Makefile
index abb36daf..4ccbf27f 100644
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,8 @@
CC= gcc
#CFLAGS= -g -DSYSV -Wall
LDFLAGS= -g
-CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
-#CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -DWITH_DB
+#CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
+CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -DWITH_DB
LDFLAGS= -s
# Look where your install program is.
@@ -13,7 +13,7 @@ BINDIR = /usr/sbin
MANDIR = /usr/man
# Uncommenting the following to use mysql.
-#LIBS = -lmysqlclient #/var/lib/mysql/mysql
+LIBS = -lmysqlclient #/var/lib/mysql/mysql
# There is one report that under an all ELF system there may be a need to
# explicilty link with libresolv.a. If linking syslogd fails you may wish
diff --git a/syslogd.c b/syslogd.c
index 067351f6..3a913048 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -605,6 +605,8 @@ static char sccsid[] = "@(#)rsyslogd.c 0.2 (Adiscon) 11/08/2004";
#define _DB_MAXDBLEN 128 /* maximum number of db */
#define _DB_MAXUNAMELEN 128 /* maximum number of user name */
#define _DB_MAXPWDLEN 128 /* maximum number of user's pass */
+#define _DB_DELAYTIMEONERROR 20 /* If an error occur we stop logging until
+ a delayed time is over */
#endif
#ifndef UTMP_FILE
@@ -787,6 +789,10 @@ struct msg {
char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 chracters) */
};
+#ifdef WITH_DB
+
+#endif
+
/*
* This structure represents the files that will have log
* copies printed.
@@ -810,6 +816,10 @@ struct filed {
char f_dbname[_DB_MAXDBLEN+1]; /* DB name */
char f_dbuid[_DB_MAXUNAMELEN+1]; /* DB user */
char f_dbpwd[_DB_MAXPWDLEN+1]; /* DB user's password */
+ time_t f_timeResumeOnError; /* 0 if no error is present,
+ otherwise is it set to the
+ time a retrail should be attampt */
+ int f_iLastDBErrNo; /* Last db error number. 0 = no error */
#endif
time_t f_time; /* time this was last written */
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
@@ -995,6 +1005,9 @@ void sighup_handler();
void initMySQL(register struct filed *f);
void writeMySQL(register struct filed *f);
void closeMySQL(register struct filed *f);
+void reInitMySQL(register struct filed *f);
+int checkDBErrorState(register struct filed *f);
+void DBErrorHandler(register struct filed *f);
#endif
int getSubString(char **pSrc, char *pDst, size_t DstSize, char cSep);
@@ -4790,14 +4803,26 @@ void sighup_handler()
*/
void initMySQL(register struct filed *f)
{
+ int iCounter = 0;
+ assert(f != NULL);
printf("in initMysql() \n");
mysql_init(&f->f_hmysql);
- /* Connect to database */
- if (!mysql_real_connect(&f->f_hmysql, f->f_dbsrv, f->f_dbuid, f->f_dbpwd, f->f_dbname, 0, NULL, 0)) {
- printf("cant connect to database \n");
- exit(0);
- }
+ do {
+ iCounter++;
+ /* Connect to database */
+ if (!mysql_real_connect(&f->f_hmysql, f->f_dbsrv, f->f_dbuid, f->f_dbpwd, f->f_dbname, 0, NULL, 0)) {
+ /* if also the second attempt failed
+ we call the error handler */
+ if(iCounter)
+ DBErrorHandler(f);
+ }
+ else
+ {
+ f->f_timeResumeOnError = 0; /* We have a working db connection */
+ dprintf("connect successfully to db\n");
+ }
+ } while (mysql_errno(&f->f_hmysql) && iCounter<2);
}
/*
@@ -4807,11 +4832,27 @@ void initMySQL(register struct filed *f)
*/
void closeMySQL(register struct filed *f)
{
+ assert(f != NULL);
printf("in closeMySQL\n");
mysql_close(&f->f_hmysql);
}
/*
+ * Reconnect a MySQL connection.
+ * Initially added 2004-12-02
+ */
+void reInitMySQL(register struct filed *f)
+{
+ assert(f != NULL);
+
+ dprintf("reInitMySQL\n");
+ /* close the current handle */
+ closeMySQL(f);
+ /* new connection */
+ initMySQL(f);
+}
+
+/*
* The following function writes the current log entry
* to an established MySQL session.
* Initially added 2004-10-28
@@ -4819,35 +4860,120 @@ void closeMySQL(register struct filed *f)
void writeMySQL(register struct filed *f)
{
char *psz;
- /* char sql_command[MAXLINE+1048];
- char szTimestamp[15];
- char szRcvAtTimestamp[15];
- formatTimestampToMySQL(&f->f_pMsg->tTIMESTAMP, szTimestamp, sizeof(szTimestamp)/sizeof(char));
- formatTimestampToMySQL(&f->f_pMsg->tRcvdAt, szRcvAtTimestamp, sizeof(szTimestamp)/sizeof(char));
- */
- printf("in writeMySQL()\n");
+ int iCounter=0;
+ assert(f != NULL);
+ dprintf("in writeMySQL()\n");
iovCreate(f);
psz = iovAsString(f);
-printf("psz: \"%s\"\n", psz);
- printf("in writeMySQL()2\n");
- /* snprintf(sql_command, sizeof(sql_command),
- "INSERT INTO SystemEvents (Message, ReceivedAt, DeviceReportedTime, "
- "Facility, Priority, FromHost, SysLogTag, InfoUnitID) "
- "VALUES "
- " ('%s', '%s', '%s', %d, %d, '%s', '%s', 1)",
- f->f_pMsg->pszMSG, szRcvAtTimestamp, szTimestamp,
- f->f_pMsg->iFacility, f->f_pMsg->iSeverity,
- f->f_pMsg->pszHOSTNAME, f->f_pMsg->pszTAG);
- */
- /* query */
- if(mysql_query(&f->f_hmysql, psz)) {
- dprintf("mysql insert failed. ErrNo: %d\n", mysql_errno(&f->f_hmysql));
- exit(0);
- }
- else {
- printf("insert sucessfully\n");
+
+ if (checkDBErrorState(f))
+ return;
+
+ /*
+ * Now we are trying to insert the data.
+ *
+ * If the first attampt failes we simply try a second one. If also
+ * the second attampt failed we discard this message and enable
+ * the "delay" error hanlding.
+ */
+ do {
+ iCounter++;
+ /* query */
+ if(mysql_query(&f->f_hmysql, psz)) {
+
+ /* if also the second attempt failed
+ we call the error handler */
+ if(iCounter)
+ DBErrorHandler(f);
+ }
+ else {
+ dprintf("db insert sucessfully\n");
+ }
+ } while (mysql_errno(&f->f_hmysql) && iCounter<2);
+}
+
+/**
+ * DBErrorHandler
+ *
+ * Call this function if an db error apears. It will initiate
+ * the "delay" handling which stopped the db logging for some
+ * time.
+ */
+void DBErrorHandler(register struct filed *f)
+{
+ /* TODO:
+ * NO DB connection -> Can not log to DB
+ * --------------------
+ * Case 1: db server unavailable
+ * We can check after a specified time interval if the server is up.
+ * Also a reason can be a down DNS service.
+ * Case 2: uid, pwd or dbname are incorrect
+ * If this is a fault in the syslog.conf we have no chance to recover. But
+ * if it is a problem of the DB we can make a retry after some time. Possible
+ * are that the admin has not already set up the database table. Or he has not
+ * created the database user yet.
+ * Case 3: unkown error
+ * If we get an unkowon error here, we should in any case try to recover after
+ * a specified time interval.
+ *
+ * Insert failed -> Can not log to DB
+ * --------------------
+ * If the insert fails it is never a good idea to give up. Only an
+ * invalid sql sturcture (wrong template) force us to disable db
+ * logging.
+ *
+ * Think about diffrent "delay" for diffrent errors!
+ */
+ dprintf("db error no: %d\n", mysql_errno(&f->f_hmysql));
+ dprintf("db error: %s\n", mysql_error(&f->f_hmysql));
+ /* Enable "delay" */
+ f->f_timeResumeOnError = time(&f->f_timeResumeOnError) + _DB_DELAYTIMEONERROR ;
+ f->f_iLastDBErrNo = mysql_errno(&f->f_hmysql);
+
+}
+
+/**
+ * checkDBErrorState
+ *
+ * Check if we can go on with database logging or if we should wait
+ * a little bit longer. It also check if the DB hanlde is still valid.
+ * If it is necessary, it takes action to reinitiate the db connection.
+ *
+ * \ret int Returns 0 if no error dedected.
+ */
+int checkDBErrorState(register struct filed *f)
+{
+ assert(f != NULL);
+ dprintf("in checkDBErrorState, timeResumeOnError: %d\n", f->f_timeResumeOnError);
+
+ /* If timeResumeOnError == 0 no error occured,
+ we can return with 0 (no error) */
+ if (f->f_timeResumeOnError == 0)
+ return 0;
+
+ (void) time(&now);
+ /* Now we know an error occured. We check timeResumeOnError
+ if we can process. If we have not reach the resume time
+ yet, we return an error status. */
+ if (f->f_timeResumeOnError > now)
+ {
+ dprintf("Wait time is not over yet.\n");
+ return 1;
}
+
+ /* Ok, we can try to resume the database logging. First
+ we have to reset the status to 0 (timeResumeOnError).
+ Then we check if we need to reinitiate the database
+ connection. We reinitiate if we know that the database
+ handle is invalid or if an unkown error appeared. */
+/* TODO: this is not really implemented yet */
+ f->f_timeResumeOnError = 0;
+ f->f_iLastDBErrNo = 0;
+ reInitMySQL(f);
+ return 0;
+
}
+
#endif /* #ifdef WITH_DB */
/**