/**
 * @file db.c Database routines for ndo2db daemon
 */
/*
 * Copyright 2009-2014 Nagios Core Development Team and Community Contributors
 * Copyright 2005-2009 Ethan Galstad
 *
 * This file is part of NDOUtils.
 *
 * NDOUtils is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * NDOUtils 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NDOUtils. If not, see <http://www.gnu.org/licenses/>.
 */

/* include our project's header files */
#include "../include/config.h"
#include "../include/common.h"
#include "../include/io.h"
#include "../include/utils.h"
#include "../include/protoapi.h"
#include "../include/ndo2db.h"
#include "../include/dbhandlers.h"
#include "../include/db.h"

extern int errno;

extern ndo2db_dbconfig ndo2db_db_settings;
extern time_t ndo2db_db_last_checkin_time;

char *ndo2db_db_rawtablenames[NDO2DB_MAX_DBTABLES]={
	"instances",
	"conninfo",
	"objects",
	"objecttypes",
	"logentries",
	"systemcommands",
	"eventhandlers",
	"servicechecks",
	"hostchecks",
	"programstatus",
	"externalcommands",
	"servicestatus",
	"hoststatus",
	"processevents",
	"timedevents",
	"timedeventqueue",
	"flappinghistory",
	"commenthistory",
	"comments",
	"notifications",
	"contactnotifications",
	"contactnotificationmethods",
	"acknowledgements",
	"statehistory",
	"downtimehistory",
	"scheduleddowntime",
	"configfiles",
	"configfilevariables",
	"runtimevariables",
	"contactstatus",
	"customvariablestatus",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"",
	"commands",
	"timeperiods",
	"timeperiod_timeranges",
	"contactgroups",
	"contactgroup_members",
	"hostgroups",
	"hostgroup_members",
	"servicegroups",
	"servicegroup_members",
	"hostescalations",
	"hostescalation_contacts",
	"serviceescalations",
	"serviceescalation_contacts",
	"hostdependencies",
	"servicedependencies",
	"contacts",
	"contact_addresses",
	"contact_notificationcommands",
	"hosts",
	"host_parenthosts",
	"host_contacts",
	"services",
	"service_contacts",
	"customvariables",
	"host_contactgroups",
	"service_contactgroups",
	"hostescalation_contactgroups",
	"serviceescalation_contactgroups",
	"service_parentservices",
        };


char *ndo2db_db_tablenames[NDO2DB_MAX_DBTABLES];

/*
#define DEBUG_NDO2DB_QUERIES 1
*/

/****************************************************************************/
/* CONNECTION FUNCTIONS                                                     */
/****************************************************************************/

/* initialize database structures */
int ndo2db_db_init(ndo2db_idi *idi){
	register int x;

	if(idi==NULL)
		return NDO_ERROR;

	/* initialize db server type */
	idi->dbinfo.server_type=ndo2db_db_settings.server_type;

	/* initialize table names */
	for(x=0;x<NDO2DB_MAX_DBTABLES;x++){
		if((ndo2db_db_tablenames[x]=(char *)malloc(strlen(ndo2db_db_rawtablenames[x])+((ndo2db_db_settings.dbprefix==NULL)?0:strlen(ndo2db_db_settings.dbprefix))+1))==NULL)
			return NDO_ERROR;
		sprintf(ndo2db_db_tablenames[x],"%s%s",(ndo2db_db_settings.dbprefix==NULL)?"":ndo2db_db_settings.dbprefix,ndo2db_db_rawtablenames[x]);
	        }

	/* initialize other variables */
	idi->dbinfo.connected=NDO_FALSE;
	idi->dbinfo.error=NDO_FALSE;
	idi->dbinfo.instance_id=0L;
	idi->dbinfo.conninfo_id=0L;
	idi->dbinfo.latest_program_status_time=(time_t)0L;
	idi->dbinfo.latest_host_status_time=(time_t)0L;
	idi->dbinfo.latest_service_status_time=(time_t)0L;
	idi->dbinfo.latest_queued_event_time=(time_t)0L;
	idi->dbinfo.latest_realtime_data_time=(time_t)0L;
	idi->dbinfo.latest_comment_time=(time_t)0L;
	idi->dbinfo.clean_event_queue=NDO_FALSE;
	idi->dbinfo.last_notification_id=0L;
	idi->dbinfo.last_contact_notification_id=0L;
	idi->dbinfo.max_timedevents_age=ndo2db_db_settings.max_timedevents_age;
	idi->dbinfo.max_systemcommands_age=ndo2db_db_settings.max_systemcommands_age;
	idi->dbinfo.max_servicechecks_age=ndo2db_db_settings.max_servicechecks_age;
	idi->dbinfo.max_hostchecks_age=ndo2db_db_settings.max_hostchecks_age;
	idi->dbinfo.max_eventhandlers_age=ndo2db_db_settings.max_eventhandlers_age;
	idi->dbinfo.max_externalcommands_age=ndo2db_db_settings.max_externalcommands_age;
	idi->dbinfo.max_notifications_age=ndo2db_db_settings.max_notifications_age;
	idi->dbinfo.max_contactnotifications_age=ndo2db_db_settings.max_contactnotifications_age;
	idi->dbinfo.max_contactnotificationmethods_age=ndo2db_db_settings.max_contactnotificationmethods_age;
	idi->dbinfo.max_logentries_age=ndo2db_db_settings.max_logentries_age;
	idi->dbinfo.max_acknowledgements_age=ndo2db_db_settings.max_acknowledgements_age;	
	idi->dbinfo.last_table_trim_time=(time_t)0L;
	idi->dbinfo.last_logentry_time=(time_t)0L;
	idi->dbinfo.last_logentry_data=NULL;
	idi->dbinfo.object_hashlist=NULL;

	/* initialize db structures, etc. */
	if(!mysql_init(&idi->dbinfo.mysql_conn)){
		syslog(LOG_USER|LOG_INFO,"Error: mysql_init() failed\n");
		return NDO_ERROR;
	}

	return NDO_OK;
        }


/* clean up database structures */
int ndo2db_db_deinit(ndo2db_idi *idi){
	register int x;

	if(idi==NULL)
		return NDO_ERROR;

	/* free table names */
	for(x=0;x<NDO2DB_MAX_DBTABLES;x++){
		if(ndo2db_db_tablenames[x])
			free(ndo2db_db_tablenames[x]);
		ndo2db_db_tablenames[x]=NULL;
	        }

	/* free cached object ids */
	ndo2db_free_cached_object_ids(idi);

	return NDO_OK;
        }


/* connects to the database server */
int ndo2db_db_connect(ndo2db_idi *idi){
	int result=NDO_OK;

	if(idi==NULL)
		return NDO_ERROR;

	/* we're already connected... */
	if(idi->dbinfo.connected==NDO_TRUE)
		return NDO_OK;

	if (!mysql_real_connect(
			&idi->dbinfo.mysql_conn,
			ndo2db_db_settings.host,
			ndo2db_db_settings.username,
			ndo2db_db_settings.password,
			ndo2db_db_settings.dbname,
			ndo2db_db_settings.port,
			ndo2db_db_settings.socket,
			CLIENT_REMEMBER_OPTIONS
	)) {
		mysql_close(&idi->dbinfo.mysql_conn);
		syslog(LOG_USER|LOG_INFO,"Error: Could not connect to MySQL database: %s",mysql_error(&idi->dbinfo.mysql_conn));
		result=NDO_ERROR;
		idi->disconnect_client=NDO_TRUE;
	} else {
		idi->dbinfo.connected=NDO_TRUE;
		syslog(LOG_USER|LOG_DEBUG,"Successfully connected to MySQL database");
	}

	return result;
        }


/* disconnects from the database server */
int ndo2db_db_disconnect(ndo2db_idi *idi){

	if(idi==NULL)
		return NDO_ERROR;

	/* we're not connected... */
	if(idi->dbinfo.connected==NDO_FALSE)
		return NDO_OK;

	/* close the connection to the database server */
	mysql_close(&idi->dbinfo.mysql_conn);
	idi->dbinfo.connected=NDO_FALSE;
	syslog(LOG_USER|LOG_DEBUG,"Successfully disconnected from MySQL database");

	return NDO_OK;
        }


/* post-connect routines */
int ndo2db_db_hello(ndo2db_idi *idi){
	char *buf=NULL;
	char *ts=NULL;
	int result=NDO_OK;
	int have_instance=NDO_FALSE;
	time_t current_time;

	/* make sure we have an instance name */
	if(idi->instance_name==NULL)
		idi->instance_name=strdup("default");

	/* get existing instance */
	if(asprintf(&buf,"SELECT instance_id FROM %s WHERE instance_name='%s'",ndo2db_db_tablenames[NDO2DB_DBTABLE_INSTANCES],idi->instance_name)==-1)
		buf=NULL;
	if((result=ndo2db_db_query(idi,buf))==NDO_OK){
		idi->dbinfo.mysql_result=mysql_store_result(&idi->dbinfo.mysql_conn);
		if((idi->dbinfo.mysql_row=mysql_fetch_row(idi->dbinfo.mysql_result))!=NULL){
			ndo2db_convert_string_to_unsignedlong(idi->dbinfo.mysql_row[0],&idi->dbinfo.instance_id);
			have_instance=NDO_TRUE;
		}
		mysql_free_result(idi->dbinfo.mysql_result);
		idi->dbinfo.mysql_result=NULL;
	}
	free(buf);

	/* insert new instance if necessary */
	if(have_instance==NDO_FALSE){
		if(asprintf(&buf,"INSERT INTO %s SET instance_name='%s'",ndo2db_db_tablenames[NDO2DB_DBTABLE_INSTANCES],idi->instance_name)==-1)
			buf=NULL;
		if((result=ndo2db_db_query(idi,buf))==NDO_OK){
			idi->dbinfo.instance_id=mysql_insert_id(&idi->dbinfo.mysql_conn);
		}
		free(buf);
	        }
	
	ts=ndo2db_db_timet_to_sql(idi,idi->data_start_time);

	/* record initial connection information */
	if(asprintf(&buf,"INSERT INTO %s SET instance_id='%lu', connect_time=NOW(), last_checkin_time=NOW(), bytes_processed='0', lines_processed='0', entries_processed='0', agent_name='%s', agent_version='%s', disposition='%s', connect_source='%s', connect_type='%s', data_start_time=%s"
		    ,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONNINFO]
		    ,idi->dbinfo.instance_id
		    ,idi->agent_name
		    ,idi->agent_version
		    ,idi->disposition
		    ,idi->connect_source
		    ,idi->connect_type
		    ,ts
		   )==-1)
		buf=NULL;
	if((result=ndo2db_db_query(idi,buf))==NDO_OK){
		idi->dbinfo.conninfo_id=mysql_insert_id(&idi->dbinfo.mysql_conn);
	}
	free(buf);
	free(ts);

	/* get cached object ids... */
	ndo2db_get_cached_object_ids(idi);

	/* get latest times from various tables... */
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_PROGRAMSTATUS],"status_update_time",(unsigned long *)&idi->dbinfo.latest_program_status_time);
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_HOSTSTATUS],"status_update_time",(unsigned long *)&idi->dbinfo.latest_host_status_time);
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_SERVICESTATUS],"status_update_time",(unsigned long *)&idi->dbinfo.latest_service_status_time);
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONTACTSTATUS],"status_update_time",(unsigned long *)&idi->dbinfo.latest_contact_status_time);
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_TIMEDEVENTQUEUE],"queued_time",(unsigned long *)&idi->dbinfo.latest_queued_event_time);
	ndo2db_db_get_latest_data_time(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_COMMENTS],"entry_time",(unsigned long *)&idi->dbinfo.latest_comment_time);

	/* calculate time of latest realtime data */
	idi->dbinfo.latest_realtime_data_time=(time_t)0L;
	if(idi->dbinfo.latest_program_status_time>idi->dbinfo.latest_realtime_data_time)
		idi->dbinfo.latest_realtime_data_time=idi->dbinfo.latest_program_status_time;
	if(idi->dbinfo.latest_host_status_time>idi->dbinfo.latest_realtime_data_time)
		idi->dbinfo.latest_realtime_data_time=idi->dbinfo.latest_host_status_time;
	if(idi->dbinfo.latest_service_status_time>idi->dbinfo.latest_realtime_data_time)
		idi->dbinfo.latest_realtime_data_time=idi->dbinfo.latest_service_status_time;
	if(idi->dbinfo.latest_contact_status_time>idi->dbinfo.latest_realtime_data_time)
		idi->dbinfo.latest_realtime_data_time=idi->dbinfo.latest_contact_status_time;
	if(idi->dbinfo.latest_queued_event_time>idi->dbinfo.latest_realtime_data_time)
		idi->dbinfo.latest_realtime_data_time=idi->dbinfo.latest_queued_event_time;

	/* get current time */
	/* make sure latest time stamp isn't in the future - this will cause problems if a backwards system time change occurs */
	time(&current_time);
	if(idi->dbinfo.latest_realtime_data_time>current_time)
		idi->dbinfo.latest_realtime_data_time=current_time;

	/* set flags to clean event queue, etc. */
	idi->dbinfo.clean_event_queue=NDO_TRUE;

	/* set misc data */
	idi->dbinfo.last_notification_id=0L;
	idi->dbinfo.last_contact_notification_id=0L;

	return result;
        }


/* pre-disconnect routines */
int ndo2db_db_goodbye(ndo2db_idi *idi){
	int result=NDO_OK;
	char *buf=NULL;
	char *ts=NULL;

	ts=ndo2db_db_timet_to_sql(idi,idi->data_end_time);

	/* record last connection information */
	if(asprintf(&buf,"UPDATE %s SET disconnect_time=NOW(), last_checkin_time=NOW(), data_end_time=%s, bytes_processed='%lu', lines_processed='%lu', entries_processed='%lu' WHERE conninfo_id='%lu'"
		    ,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONNINFO]
		    ,ts
		    ,idi->bytes_processed
		    ,idi->lines_processed
		    ,idi->entries_processed
		    ,idi->dbinfo.conninfo_id
		   )==-1)
		buf=NULL;
	result=ndo2db_db_query(idi,buf);
	free(buf);

	free(ts);

	return result;
        }


/* checking routines */
int ndo2db_db_checkin(ndo2db_idi *idi){
	int result=NDO_OK;
	char *buf=NULL;

	/* record last connection information */
	if(asprintf(&buf,"UPDATE %s SET last_checkin_time=NOW(), bytes_processed='%lu', lines_processed='%lu', entries_processed='%lu' WHERE conninfo_id='%lu'"
		    ,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONNINFO]
		    ,idi->bytes_processed
		    ,idi->lines_processed
		    ,idi->entries_processed
		    ,idi->dbinfo.conninfo_id
		   )==-1)
		buf=NULL;
	result=ndo2db_db_query(idi,buf);
	free(buf);

	time(&ndo2db_db_last_checkin_time);

	return result;
        }



/****************************************************************************/
/* MISC FUNCTIONS                                                           */
/****************************************************************************/

/* escape a string for a SQL statement */
char *ndo2db_db_escape_string(ndo2db_idi *idi, char *buf){
	register int x,y,z;
	char *newbuf=NULL;

	if(idi==NULL || buf==NULL)
		return NULL;

	z=strlen(buf);

	/* allocate space for the new string */
	if((newbuf=(char *)malloc((z*2)+1))==NULL)
		return NULL;

	/* escape characters */
	for(x=0,y=0;x<z;x++){

		if(buf[x]=='\'' || buf[x]=='\"' || buf[x]=='*' || buf[x]=='\\' || buf[x]=='$' || buf[x]=='?' || buf[x]=='.' || buf[x]=='^' || buf[x]=='+' || buf[x]=='[' || buf[x]==']' || buf[x]=='(' || buf[x]==')')
			newbuf[y++]='\\';

		newbuf[y++]=buf[x];
	        }

	/* terminate escape string */
	newbuf [y]='\0';

	return newbuf;
        }


/* SQL query conversion of time_t format to date/time format */
char *ndo2db_db_timet_to_sql(ndo2db_idi *idi, time_t t){
	char *buf=NULL;
	(void)idi; /* Unused, don't warn. */

	asprintf(&buf,"FROM_UNIXTIME(%lu)",(unsigned long)t);

	return buf;
        }


/* SQL query conversion of date/time format to time_t format */
char *ndo2db_db_sql_to_timet(ndo2db_idi *idi, char *field){
	char *buf=NULL;
	(void)idi; /* Unused, don't warn. */
	
	asprintf(&buf,"UNIX_TIMESTAMP(%s)",(field==NULL)?"":field);

	return buf;
        }


/* executes a SQL statement */
int ndo2db_db_query(ndo2db_idi *idi, char *buf){
	int result=NDO_OK;
	int query_result=0;

	if(idi==NULL || buf==NULL)
		return NDO_ERROR;

	/* if we're not connected, try and reconnect... */
	if(idi->dbinfo.connected==NDO_FALSE){
		if(ndo2db_db_connect(idi)==NDO_ERROR)
			return NDO_ERROR;
		ndo2db_db_hello(idi);
	        }

#ifdef DEBUG_NDO2DB_QUERIES
	printf("%s\n\n",buf);
#endif

	ndo2db_log_debug_info(NDO2DB_DEBUGL_SQL,0,"%s\n",buf);

	if (mysql_query(&idi->dbinfo.mysql_conn,buf)) {
		syslog(LOG_USER|LOG_INFO,"Error: mysql_query() failed for '%s'\n",buf);
		syslog(LOG_USER|LOG_INFO,"mysql_error: '%s'\n", mysql_error(&idi->dbinfo.mysql_conn));
		result=NDO_ERROR;
	}

	/* handle errors */
	if(result==NDO_ERROR)
		ndo2db_handle_db_error(idi,query_result);

	return result;
        }


/* frees memory associated with a query */
int ndo2db_db_free_query(ndo2db_idi *idi){

	if(idi==NULL)
		return NDO_ERROR;

	return NDO_OK;
        }


/* handles SQL query errors */
int ndo2db_handle_db_error(ndo2db_idi *idi, int query_result){
	int result=0;

	if(idi==NULL)
		return NDO_ERROR;

	/* we're not currently connected... */
	if(idi->dbinfo.connected==NDO_FALSE)
		return NDO_OK;

	result=mysql_errno(&idi->dbinfo.mysql_conn);
	if(result==CR_SERVER_LOST || result==CR_SERVER_GONE_ERROR){
		syslog(LOG_USER|LOG_INFO,"Error: Connection to MySQL database has been lost!\n");
		ndo2db_db_disconnect(idi);
		idi->disconnect_client=NDO_TRUE;
	}

	return NDO_OK;
        }


/* clears data from a given table (current instance only) */
int ndo2db_db_clear_table(ndo2db_idi *idi, char *table_name){
	char *buf=NULL;
	int result=NDO_OK;

	if(idi==NULL || table_name==NULL)
		return NDO_ERROR;

	if(asprintf(&buf,"DELETE FROM %s WHERE instance_id='%lu'"
		    ,table_name
		    ,idi->dbinfo.instance_id
		   )==-1)
		buf=NULL;

	result=ndo2db_db_query(idi,buf);
	free(buf);

	return result;
        }
		

/* gets latest data time value from a given table */
int ndo2db_db_get_latest_data_time(ndo2db_idi *idi, char *table_name, char *field_name, unsigned long *t){
	char *buf=NULL;
	char *ts[1];
	int result=NDO_OK;

	if(idi==NULL || table_name==NULL || field_name==NULL || t==NULL)
		return NDO_ERROR;

	*t=(time_t)0L;
	ts[0]=ndo2db_db_sql_to_timet(idi,field_name);

	if(asprintf(&buf,"SELECT %s AS latest_time FROM %s WHERE instance_id='%lu' ORDER BY %s DESC LIMIT 0,1"
		    ,ts[0]
		    ,table_name
		    ,idi->dbinfo.instance_id
		    ,field_name
		   )==-1)
		buf=NULL;

	if((result=ndo2db_db_query(idi,buf))==NDO_OK){
		idi->dbinfo.mysql_result=mysql_store_result(&idi->dbinfo.mysql_conn);
		if((idi->dbinfo.mysql_row=mysql_fetch_row(idi->dbinfo.mysql_result))!=NULL){
			ndo2db_convert_string_to_unsignedlong(idi->dbinfo.mysql_row[0],t);
		}
		mysql_free_result(idi->dbinfo.mysql_result);
		idi->dbinfo.mysql_result=NULL;
	}
	free(buf);
	free(ts[0]);

	return result;
        }
		

/* trim/delete old data from a given table */
int ndo2db_db_trim_data_table(ndo2db_idi *idi, char *table_name, char *field_name, unsigned long t){
	char *buf=NULL;
	char *ts[1];
	int result=NDO_OK;

	if(idi==NULL || table_name==NULL || field_name==NULL)
		return NDO_ERROR;

	ts[0]=ndo2db_db_timet_to_sql(idi,(time_t)t);

	if(asprintf(&buf,"DELETE FROM %s WHERE instance_id='%lu' AND %s<%s"
		    ,table_name
		    ,idi->dbinfo.instance_id
		    ,field_name
		    ,ts[0]
		   )==-1)
		buf=NULL;

	result=ndo2db_db_query(idi,buf);
	free(buf);
	free(ts[0]);

	return result;
        }
		

/* performs some periodic table maintenance... */
int ndo2db_db_perform_maintenance(ndo2db_idi *idi){
	time_t current_time;

	/* get the current time */
	time(&current_time);

	/* trim tables */
	if ((current_time-(time_t)60)>idi->dbinfo.last_table_trim_time) {
		if (idi->dbinfo.max_timedevents_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming timedevents.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_TIMEDEVENTS],"scheduled_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_timedevents_age));
		}
		if (idi->dbinfo.max_systemcommands_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming systemcommands.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_SYSTEMCOMMANDS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_systemcommands_age));
		}
		if (idi->dbinfo.max_servicechecks_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming servicechecks.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_SERVICECHECKS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_servicechecks_age));
		}
		if (idi->dbinfo.max_hostchecks_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming hostchecks.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_HOSTCHECKS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_hostchecks_age));
		}
		if (idi->dbinfo.max_eventhandlers_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming eventhandlers.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_EVENTHANDLERS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_eventhandlers_age));
		}
		if (idi->dbinfo.max_externalcommands_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming externalcommands.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_EXTERNALCOMMANDS],"entry_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_externalcommands_age));
		}
		if (idi->dbinfo.max_notifications_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming notifications.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_NOTIFICATIONS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_notifications_age));
		}
		if (idi->dbinfo.max_contactnotifications_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming contactnotifications.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONTACTNOTIFICATIONS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_contactnotifications_age));
		}
		if (idi->dbinfo.max_contactnotificationmethods_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming contactnotificationmethods.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_CONTACTNOTIFICATIONMETHODS],"start_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_contactnotificationmethods_age));
		}
		if (idi->dbinfo.max_logentries_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming logentries.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_LOGENTRIES],"entry_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_logentries_age));
		}
		if (idi->dbinfo.max_acknowledgements_age>0L) {
			syslog(LOG_USER|LOG_INFO,"Trimming acknowledgements.");
			ndo2db_db_trim_data_table(idi,ndo2db_db_tablenames[NDO2DB_DBTABLE_ACKNOWLEDGEMENTS],"entry_time",(time_t)((unsigned long)current_time-idi->dbinfo.max_acknowledgements_age));
		}
		idi->dbinfo.last_table_trim_time=current_time;
	}

	return NDO_OK;
}
