From 72adac638e6802a61a1e1934c06e590519b56e6a Mon Sep 17 00:00:00 2001
From: Cyril Feraudet <cyril@feraudet.com>
Date: Wed, 9 Nov 2011 15:12:11 +0100
Subject: [PATCH] Adding write_mysql output plugin

---
 configure.in            |    4 +-
 contrib/write_mysql.sql |  136 ++++++++++++++++
 src/Makefile.am         |   12 ++
 src/collectd.conf.in    |    9 +
 src/collectd.conf.pod   |   38 +++++
 src/write_mysql.c       |  391 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 589 insertions(+), 1 deletions(-)
 create mode 100644 contrib/write_mysql.sql
 create mode 100644 src/write_mysql.c

diff --git a/configure.in b/configure.in
index 9b6397f..cdb7dc5 100644
--- a/configure.in
+++ b/configure.in
@@ -2200,7 +2200,7 @@ then
 fi
 if test "x$with_libmysql" = "xyes"
 then
-	with_mysql_libs=`$with_mysql_config --libs 2>/dev/null`
+	with_mysql_libs=`$with_mysql_config --libs_r 2>/dev/null`
 	mysql_config_status=$?
 
 	if test $mysql_config_status -ne 0
@@ -4678,6 +4678,7 @@ AC_PLUGIN([vmem],        [$plugin_vmem],       [Virtual memory statistics])
 AC_PLUGIN([vserver],     [$plugin_vserver],    [Linux VServer statistics])
 AC_PLUGIN([wireless],    [$plugin_wireless],   [Wireless statistics])
 AC_PLUGIN([write_http],  [$with_libcurl],      [HTTP output plugin])
+AC_PLUGIN([write_mysql], [$with_libmysql],     [MySQL output plugin])
 AC_PLUGIN([write_redis], [$with_libcredis],    [Redis output plugin])
 AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
 AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
@@ -4999,6 +5000,7 @@ Configuration:
     vserver . . . . . . . $enable_vserver
     wireless  . . . . . . $enable_wireless
     write_http  . . . . . $enable_write_http
+    write_mysql . . . . . $enable_write_mysql
     write_redis . . . . . $enable_write_redis
     xmms  . . . . . . . . $enable_xmms
     zfs_arc . . . . . . . $enable_zfs_arc
diff --git a/contrib/write_mysql.sql b/contrib/write_mysql.sql
new file mode 100644
index 0000000..0d1f84c
--- /dev/null
+++ b/contrib/write_mysql.sql
@@ -0,0 +1,136 @@
+-- MySQL dump 10.11
+--
+-- Host: localhost    Database: collectd
+-- ------------------------------------------------------
+-- Server version	5.0.77
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Current Database: `collectd`
+--
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `collectd` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `collectd`;
+
+--
+-- Table structure for table `data`
+--
+
+DROP TABLE IF EXISTS `data`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `data` (
+  `id` bigint(20) NOT NULL auto_increment,
+  `timestamp` double NOT NULL,
+  `host_id` int(11) NOT NULL,
+  `plugin_id` int(11) NOT NULL,
+  `plugin_instance` varchar(255) default NULL,
+  `type_id` int(11) NOT NULL,
+  `typeinstance` varchar(255) default NULL,
+  `dataset_id` int(11) NOT NULL,
+  `value` double NOT NULL,
+  PRIMARY KEY  (`id`),
+  KEY `timestamp` (`timestamp`),
+  KEY `host_id` (`host_id`),
+  KEY `plugin_id` (`plugin_id`),
+  KEY `type_id` (`type_id`),
+  KEY `typeinstance_id` (`typeinstance`),
+  KEY `dataset_id` (`dataset_id`),
+  CONSTRAINT `data_ibfk_1` FOREIGN KEY (`host_id`) REFERENCES `host` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `data_ibfk_2` FOREIGN KEY (`plugin_id`) REFERENCES `plugin` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `data_ibfk_3` FOREIGN KEY (`type_id`) REFERENCES `type` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `data_ibfk_4` FOREIGN KEY (`dataset_id`) REFERENCES `dataset` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Table structure for table `dataset`
+--
+
+DROP TABLE IF EXISTS `dataset`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `dataset` (
+  `id` int(11) NOT NULL auto_increment,
+  `type_id` int(11) NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `type` enum('COUNTER','GAUGE','DERIVE','ABSOLUTE') NOT NULL,
+  `min` double NOT NULL,
+  `max` double NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `id` (`id`,`type_id`),
+  KEY `name` (`name`),
+  KEY `type_id` (`type_id`),
+  CONSTRAINT `dataset_ibfk_1` FOREIGN KEY (`type_id`) REFERENCES `type` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Table structure for table `host`
+--
+
+DROP TABLE IF EXISTS `host`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `host` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(255) NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Table structure for table `plugin`
+--
+
+DROP TABLE IF EXISTS `plugin`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `plugin` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(255) NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `id` (`id`,`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Table structure for table `type`
+--
+
+DROP TABLE IF EXISTS `type`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `type` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(255) NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `id` (`id`,`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
+SET character_set_client = @saved_cs_client;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2011-11-07 12:57:15
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 795de57..123206b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -256,6 +256,18 @@ collectd_LDADD += "-dlopen" csv.la
 collectd_DEPENDENCIES += csv.la
 endif
 
+if BUILD_PLUGIN_WRITE_MYSQL
+pkglib_LTLIBRARIES += write_mysql.la
+write_mysql_la_SOURCES = write_mysql.c
+write_mysql_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" write_mysql.la
+if BUILD_WITH_LIBMYSQL
+write_mysql_la_CFLAGS = $(BUILD_WITH_LIBMYSQL_CFLAGS)
+write_mysql_la_LIBADD = $(BUILD_WITH_LIBMYSQL_LIBS) -lmysqlclient_r
+endif
+collectd_DEPENDENCIES += write_mysql.la
+endif
+
 if BUILD_PLUGIN_CURL
 pkglib_LTLIBRARIES += curl.la
 curl_la_SOURCES = curl.c
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 94cf2a9..bd7330a 100644
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@@ -141,6 +141,7 @@
 #@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
 #@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
 #@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
+#@BUILD_PLUGIN_WRITE_MYSQL_TRUE@LoadPlugin write_mysql
 #@BUILD_PLUGIN_WRITE_REDIS_TRUE@LoadPlugin write_redis
 #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
 #@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
@@ -960,6 +961,14 @@
 #	</URL>
 #</Plugin>
 
+#<Plugin write_mysql>
+#	Host "localhost"
+#	User "root"
+#	Passwd ""
+#	Database "collectd"
+#	Port "3306"
+#</Plugin>
+
 #<Plugin write_redis>
 #	<Node "example">
 #		Host "localhost"
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index b0f8dfe..3ca8630 100644
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -4820,6 +4820,44 @@ number.
 
 =back
 
+=head2 Plugin C<write_mysql>
+
+This output plugin submits values to a MySQL server. 
+You need first to create database and tables on your MySQL server as described
+in C<contrib/write_mysql.sql> .
+
+Synopsis of the configuration is:
+
+ <Plugin write_mysql>
+     Host "localhost"
+     User "root"
+     Passwd ""
+     Database "collectd"
+     Port "3306"
+ </Plugin>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+MySQL server hostname to connect to. Default is localhost.
+
+=item B<User> I<Username>
+
+User name needed for MySQL authentication. Default is root.
+
+=item B<Password> I<Password>
+
+Password needed for MySQL authentication. Default is empty.
+
+=item B<Database> I<Database>
+
+Database where located tables to insert to. Default is collectd.
+
+=item B<Port> I<Port>
+
+MySQL server port to connect to. Default is 3306.
+
 =head1 FILTER CONFIGURATION
 
 Starting with collectd 4.6 there is a powerful filtering infrastructure
diff --git a/src/write_mysql.c b/src/write_mysql.c
new file mode 100644
index 0000000..b9429f4
--- /dev/null
+++ b/src/write_mysql.c
@@ -0,0 +1,391 @@
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#ifdef HAVE_MYSQL_H
+#include <mysql.h>
+#elif defined(HAVE_MYSQL_MYSQL_H)
+#include <mysql/mysql.h>
+#endif
+#include <pthread.h>
+
+typedef struct host_s host_t;
+struct host_s {
+	char	name[DATA_MAX_NAME_LEN];
+	int	id;
+	host_t	*next_host;
+};
+
+typedef struct plugin_s plugin_t;
+struct plugin_s {
+	char	name[DATA_MAX_NAME_LEN];
+	int	id;
+	plugin_t	*next_plugin;
+};
+
+typedef struct type_s type_t;
+struct type_s {
+	char	name[DATA_MAX_NAME_LEN];
+	int	id;
+	type_t	*next_type;
+};
+
+typedef struct dataset_s dataset_t;
+struct dataset_s {
+	char	name[DATA_MAX_NAME_LEN];
+	int	id;
+	int	type_id;
+	dataset_t	*next_dataset;
+};
+
+
+static const char *config_keys[] =
+{
+	"Host",
+	"User",
+	"Passwd",
+	"Database",
+	"Port"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+char *host = "localhost";
+char *user = "root";
+char *passwd = "";
+char *database = "collectd";
+int port = 0;
+
+host_t *host_list = NULL;
+plugin_t *plugin_list = NULL;
+type_t *type_list = NULL;
+dataset_t *dataset_list = NULL;
+MYSQL *conn;
+pthread_mutex_t mutex;
+
+static int write_mysql_config (const char *key, const char *value) {
+	if (strcasecmp ("Host", key) == 0) {
+		host = strdup (value);
+	} else if (strcasecmp ("User", key) == 0) {
+		user = strdup (value);
+	} else if (strcasecmp ("Passwd", key) == 0) {
+		passwd = strdup (value);
+	} else if (strcasecmp ("Database", key) == 0) {
+		database = strdup (value);
+	} else if (strcasecmp ("Port", key) == 0) {
+		port = value;
+	}
+}
+
+static int write_mysql_init (void) {
+	conn = mysql_init(NULL);
+	if (mysql_real_connect(conn, host, user, passwd, database, port, NULL, 0) == NULL) {
+		ERROR("write_mysql plugin: Failed to connect to database %s "
+			" at server %s with user %s : %s", database, host, user, mysql_error (conn));
+		plugin_unregister_write ("write_mysql");
+		return (-1);
+	}
+	if (!mysql_thread_safe()) {
+		ERROR("write_mysql plugin: mysqlclient Thread Safe OFF");
+		return (-1);
+	} else {
+		DEBUG("write_mysql plugin: mysqlclient Thread Safe ON");
+	}
+	return (0);
+}
+
+
+static int add_host_id (char *hostname) {
+	int id, len;
+	id = '\0';
+	MYSQL_RES *result;
+	MYSQL_ROW row;
+	int num_fields;
+	char query[1024];
+	host_t *newhost;
+	len = ssnprintf (query, sizeof (query), "SELECT id FROM host WHERE name = '%s'", hostname);
+	DEBUG("write_mysql plugin: %s", query);
+	pthread_mutex_lock(&mutex);
+	mysql_real_query(conn, query, len);
+	result = mysql_store_result(conn);
+	if (row = mysql_fetch_row(result)) {
+		id = atoi(row[0]);
+		mysql_free_result(result);
+		pthread_mutex_unlock(&mutex);
+	} else {
+		mysql_free_result(result);
+		len = ssnprintf (query, sizeof (query), "INSERT INTO host (name) VALUES ('%s')", hostname);
+		DEBUG("write_mysql plugin: %s", query);
+		mysql_real_query(conn, query, len);
+		id = (int)mysql_insert_id(conn);
+	}
+	newhost = malloc(sizeof(host_t));
+	sstrncpy (newhost->name, hostname, sizeof(newhost->name));
+	newhost->id = id;
+	newhost->next_host = NULL;
+	if (host_list == NULL) {
+		host_list = newhost;
+	} else {
+		host_t *host = host_list;
+		while (host->next_host != NULL) {
+			host = host->next_host;
+		}
+		host->next_host = newhost;
+	}
+	pthread_mutex_unlock(&mutex);
+	return id;
+}
+		
+static int add_plugin_id (char *pluginname) {
+	int id, len;
+	id = '\0';
+	MYSQL_RES *result;
+	MYSQL_ROW row;
+	int num_fields;
+	char query[1024];
+	plugin_t *newplugin;
+	len = ssnprintf (query, sizeof (query), "SELECT id FROM plugin WHERE name = '%s'", pluginname);
+	DEBUG("write_mysql plugin: %s", query);
+	pthread_mutex_lock(&mutex);
+	mysql_real_query(conn, query, len);
+	result = mysql_store_result(conn);
+	if (row = mysql_fetch_row(result)) {
+		id = atoi(row[0]);
+		mysql_free_result(result);
+		pthread_mutex_unlock(&mutex);
+	} else {
+		mysql_free_result(result);
+		len = ssnprintf (query, sizeof (query), "INSERT INTO plugin (name) VALUES ('%s')", pluginname);
+		DEBUG("write_mysql plugin: %s", query);
+		mysql_real_query(conn, query, len);
+		id = (int)mysql_insert_id(conn);
+	}
+	newplugin = malloc(sizeof(plugin_t));
+	sstrncpy (newplugin->name, pluginname, sizeof(newplugin->name));
+	newplugin->id = id;
+	newplugin->next_plugin = NULL;
+	if (plugin_list == NULL) {
+		plugin_list = newplugin;
+	} else {
+		plugin_t *plugin = plugin_list;
+		while (plugin->next_plugin != NULL) {
+			plugin = plugin->next_plugin;
+		}
+		plugin->next_plugin = newplugin;
+	}
+	pthread_mutex_unlock(&mutex);
+	return id;
+}
+		
+static int add_type_id (char *typename) {
+	int id, len;
+	id = '\0';
+	MYSQL_RES *result;
+	MYSQL_ROW row;
+	int num_fields;
+	char query[1024];
+	type_t *newtype;
+	len = ssnprintf (query, sizeof (query), "SELECT id FROM type WHERE name = '%s'", typename);
+	DEBUG("write_mysql plugin: %s", query);
+	pthread_mutex_lock(&mutex);
+	mysql_real_query(conn, query, len);
+	result = mysql_store_result(conn);
+	if (row = mysql_fetch_row(result)) {
+		id = atoi(row[0]);
+		mysql_free_result(result);
+		pthread_mutex_unlock(&mutex);
+	} else {
+		mysql_free_result(result);
+		len = ssnprintf (query, sizeof (query), "INSERT INTO type (name) VALUES ('%s')", typename);
+		DEBUG("write_mysql plugin: %s", query);
+		mysql_real_query(conn, query, len);
+		id = (int)mysql_insert_id(conn);
+	}
+	newtype = malloc(sizeof(type_t));
+	sstrncpy (newtype->name, typename, sizeof(newtype->name));
+	newtype->id = id;
+	newtype->next_type = NULL;
+	if (type_list == NULL) {
+		type_list = newtype;
+	} else {
+		type_t *type = type_list;
+		while (type->next_type != NULL) {
+			type = type->next_type;
+		}
+		type->next_type = newtype;
+	}
+	pthread_mutex_unlock(&mutex);
+	return id;
+}
+		
+static int add_dataset_id (data_source_t *ds, int type_id) {
+	int id, len;
+	id = '\0';
+	MYSQL_RES *result;
+	MYSQL_ROW row;
+	int num_fields;
+	char query[1024];
+	char *type;
+	dataset_t *newdataset;
+	len = ssnprintf (query, sizeof (query), "SELECT id FROM dataset WHERE name = '%s' AND type_id = '%d'", ds->name, type_id);
+	DEBUG("write_mysql plugin: %s", query);
+	pthread_mutex_lock(&mutex);
+	mysql_real_query(conn, query, len);
+	result = mysql_store_result(conn);
+	if (row = mysql_fetch_row(result)) {
+		id = atoi(row[0]);
+		mysql_free_result(result);
+		pthread_mutex_unlock(&mutex);
+	} else {
+		mysql_free_result(result);
+		switch(ds->type) {
+			case DS_TYPE_COUNTER:
+				type = "COUNTER";
+			break;
+			case DS_TYPE_DERIVE:
+				type = "DERIVE";
+			break;
+			case DS_TYPE_ABSOLUTE:
+				type = "ABSOLUTE";
+			break;
+			default:
+				type = "GAUGE";
+			break;
+		}
+		len = ssnprintf (query, sizeof (query), "INSERT INTO dataset (name,type_id,type,min,max) VALUES ('%s','%d','%s','%f','%f')", ds->name, type_id, type, ds->min, ds->max);
+		DEBUG("write_mysql plugin: %s", query);
+		mysql_real_query(conn, query, len);
+		id = (int)mysql_insert_id(conn);
+	}
+	newdataset = malloc(sizeof(dataset_t));
+	sstrncpy (newdataset->name, ds->name, sizeof(newdataset->name));
+	newdataset->id = id;
+	newdataset->type_id = type_id;
+	newdataset->next_dataset = NULL;
+	if (dataset_list == NULL) {
+		dataset_list = newdataset;
+	} else {
+		dataset_t *dataset = dataset_list;
+		while (dataset->next_dataset != NULL) {
+			dataset = dataset->next_dataset;
+		}
+		dataset->next_dataset = newdataset;
+	}
+	pthread_mutex_unlock(&mutex);
+	return id;
+}
+		
+static int get_host_id (char *hostname) {
+	int id;
+	id = '\0';
+	host_t *host = host_list;
+	while (host) {
+		if (strcmp (hostname, host->name) == 0) {
+			id = host->id;
+			break;
+		}
+		host = host->next_host;
+	}
+	if (!id) {
+		id = add_host_id(hostname);
+	}
+	return (id);
+}
+
+static int get_plugin_id (char *pluginname) {
+	int id;
+	id = '\0';
+	plugin_t *plugin = plugin_list;
+	while (plugin) {
+		if (strcmp (pluginname, plugin->name) == 0) {
+			id = plugin->id;
+			break;
+		}
+		plugin = plugin->next_plugin;
+	}
+	if (!id) {
+		id = add_plugin_id(pluginname);
+	}
+	return (id);
+}
+
+static int get_type_id (char *typename) {
+	int id;
+	id = '\0';
+	type_t *type = type_list;
+	while (type) {
+		if (strcmp (typename, type->name) == 0) {
+			id = type->id;
+			break;
+		}
+		type = type->next_type;
+	}
+	if (!id) {
+		id = add_type_id(typename);
+	}
+	return (id);
+}
+
+static int get_dataset_id (data_source_t *ds, int type_id) {
+	int id;
+	id = '\0';
+	dataset_t *dataset = dataset_list;
+	while (dataset) {
+		if (strcmp (ds->name, dataset->name) == 0 && dataset->type_id == type_id) {
+			id = dataset->id;
+			break;
+		}
+		dataset = dataset->next_dataset;
+	}
+	if (!id) {
+		id = add_dataset_id(ds, type_id);
+	}
+	return (id);
+}
+
+static int write_mysql_write(const data_set_t *ds, const value_list_t *vl,
+		user_data_t __attribute__((unused)) *user_data) {
+	int i;
+	int host_id, plugin_id, type_id;
+	host_id = get_host_id((char*)vl->host);
+	plugin_id = get_plugin_id((char*)vl->plugin);
+	type_id = get_type_id((char*)vl->type);
+	gauge_t *rates = NULL;
+	for (i = 0; i < ds->ds_num; i++ ) {
+		char tmpquery[1024];
+		char query[1024], chartest;
+		int len;
+		data_source_t *dso = ds->ds + i;
+		int dataset_id = get_dataset_id(dso, type_id);
+		len = ssnprintf (tmpquery, sizeof (tmpquery), "INSERT INTO data "
+		"(timestamp,host_id,plugin_id,plugin_instance,type_id,typeinstance,dataset_id,value)"
+		"VALUES (%.3f,%d,%d,'%s',%d,'%s',%d,%%lf)", CDTIME_T_TO_DOUBLE (vl->time), host_id, 
+		plugin_id, vl->plugin_instance, type_id, vl->type_instance, dataset_id );
+		if (dso->type == DS_TYPE_GAUGE) {
+			len = ssnprintf (query, sizeof (query), tmpquery, vl->values[i].gauge);
+		} else {
+			if (rates == NULL) {
+				rates = uc_get_rate (ds, vl);
+			}
+			if (isnan(rates[i])) { continue; }
+			len = ssnprintf (query, sizeof (query), tmpquery, rates[i]);
+		}
+		//INFO("toto: %d", toto);
+		pthread_mutex_lock(&mutex);
+		DEBUG("write_mysql plugin: %s", query);
+		mysql_real_query(conn, query, len);
+		pthread_mutex_unlock(&mutex);
+	}
+	return (0);
+}
+
+static int write_mysql_shutdown(void) {
+	mysql_close(conn);
+}
+
+void module_register (void) {
+	plugin_register_init ("write_mysql", write_mysql_init);
+	plugin_register_config ("write_mysql", write_mysql_config,
+			config_keys, config_keys_num);
+	plugin_register_write ("write_mysql", write_mysql_write, /* user_data = */ NULL);
+	plugin_register_shutdown ("write_mysql", write_mysql_shutdown);
+}
+
-- 
1.7.6.1
