Blob Blame History Raw
From 002238dff53b284c9455554f146176ee8de2de4a Mon Sep 17 00:00:00 2001
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Fri, 31 May 2013 12:41:01 -0300
Subject: [PATCH 02/32] ras-record: make the code more generic

Now that we're ready to add more tables to the database, make
the code that creates and inserts data into the table more
generic.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 ras-record.c |  173 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 110 insertions(+), 63 deletions(-)

diff --git a/ras-record.c b/ras-record.c
index 8995c9e..3af0791 100644
--- a/ras-record.c
+++ b/ras-record.c
@@ -28,80 +28,128 @@
 #include "ras-mc-handler.h"
 #include "ras-logger.h"
 
+/* #define DEBUG_SQL 1 */
+
 #define SQLITE_RAS_DB RASSTATEDIR "/" RAS_DB_FNAME
 
-const char *mc_event_db = " mc_event ";
-const char *mc_event_db_create_fields = "("
-		"id INTEGER PRIMARY KEY"
-		", timestamp TEXT"
-		", err_count INTEGER"
-		", err_type TEXT"
-		", err_msg TEXT"		/* 5 */
-		", label TEXT"
-		", mc INTEGER"
-		", top_layer INTEGER"
-		", middle_layer INTEGER"
-		", lower_layer INTEGER"		/* 10 */
-		", address INTEGER"
-		", grain INTEGER"
-		", syndrome INTEGER"
-		", driver_detail TEXT"		/* 14 */
-	")";
-
-const char *mc_event_db_fields = "("
-		"id"
-		", timestamp"
-		", err_count"
-		", err_type"
-		", err_msg"			/* 5 */
-		", label"
-		", mc"
-		", top_layer"
-		", middle_layer"
-		", lower_layer"			/* 10 */
-		", address"
-		", grain"
-		", syndrome"
-		", driver_detail"		/* 14 */
-	")";
-
-#define NUM_MC_EVENT_DB_VALUES	14
-
-const char *createdb = "CREATE TABLE IF NOT EXISTS";
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*(x)))
+
+struct db_fields {
+	char *name;
+	char *type;
+};
+
+struct db_table_descriptor {
+	char			*name;
+	const struct db_fields	*fields;
+	size_t			num_fields;
+};
+
+static const struct db_fields mc_event_fields[] = {
+		{ .name="id",			.type="INTEGER PRIMARY KEY" },
+		{ .name="timestamp",		.type="TEXT" },
+		{ .name="err_count",		.type="INTEGER" },
+		{ .name="err_type",		.type="TEXT" },
+		{ .name="err_msg",		.type="TEXT" },
+		{ .name="label",		.type="TEXT" },
+		{ .name="mc",			.type="INTEGER" },
+		{ .name="top_layer",		.type="INTEGER" },
+		{ .name="middle_layer",		.type="INTEGER" },
+		{ .name="lower_layer",		.type="INTEGER" },
+		{ .name="address",		.type="INTEGER" },
+		{ .name="grain",		.type="INTEGER" },
+		{ .name="syndrome",		.type="INTEGER" },
+		{ .name="driver_detail",	.type="TEXT" },
+};
+
+static const struct db_table_descriptor mc_event_tab = {
+	.name = "mc_event",
+	.fields = mc_event_fields,
+	.num_fields = ARRAY_SIZE(mc_event_fields),
+};
+
 const char *insertdb = "INSERT INTO";
 const char *valuesdb = " VALUES ";
 
-static int ras_mc_prepare_stmt(struct sqlite3_priv *priv)
+static int ras_mc_prepare_stmt(struct sqlite3_priv *priv,
+			       sqlite3_stmt **stmt,
+			       const struct db_table_descriptor *db_tab)
+
 {
 	int i, rc;
-	char sql[1024];
+	char sql[1024], *p = sql, *end = sql + sizeof(sql);
+	const struct db_fields *field;
+
+	p += snprintf(p, end - p, "INSERT INTO %s (",
+		      db_tab->name);
+
+	for (i = 0; i < db_tab->num_fields; i++) {
+		field = &db_tab->fields[i];
+		p += snprintf(p, end - p, "%s", field->name);
+
+		if (i < db_tab->num_fields - 1)
+			p += snprintf(p, end - p, ", ");
+	}
 
-	strcpy(sql, insertdb);
-	strcat(sql, mc_event_db);
-	strcat(sql, mc_event_db_fields);
-	strcat(sql, valuesdb);
+	p += snprintf(p, end - p, ") VALUES ( NULL, ");
 
-	strcat(sql, "(NULL, ");	/* Auto-increment field */
-	for (i = 1; i < NUM_MC_EVENT_DB_VALUES; i++) {
-		if (i < NUM_MC_EVENT_DB_VALUES - 1)
+	for (i = 1; i < db_tab->num_fields; i++) {
+		if (i <  db_tab->num_fields - 1)
 			strcat(sql, "?, ");
 		else
 			strcat(sql, "?)");
 	}
 
-	rc = sqlite3_prepare_v2(priv->db, sql, -1, &priv->stmt, NULL);
+#ifdef DEBUG_SQL
+	log(TERM, LOG_INFO, "SQL: %s\n", sql);
+#endif
+
+	rc = sqlite3_prepare_v2(priv->db, sql, -1, stmt, NULL);
 	if (rc != SQLITE_OK)
-		log(TERM, LOG_ERR, "Failed to prepare insert db on %s: error = %s\n",
-		       SQLITE_RAS_DB, sqlite3_errmsg(priv->db));
+		log(TERM, LOG_ERR,
+		    "Failed to prepare insert db at table %s (db %s): error = %s\n",
+		    db_tab->name, SQLITE_RAS_DB, sqlite3_errmsg(priv->db));
 
 	return rc;
 }
 
+static int ras_mc_create_table(struct sqlite3_priv *priv,
+			       const struct db_table_descriptor *db_tab)
+{
+	const struct db_fields *field;
+	char sql[1024], *p = sql, *end = sql + sizeof(sql);
+	int i,rc;
+
+	p += snprintf(p, end - p, "CREATE TABLE IF NOT EXISTS %s (",
+		      db_tab->name);
+
+	for (i = 0; i < db_tab->num_fields; i++) {
+		field = &db_tab->fields[i];
+		p += snprintf(p, end - p, "%s %s", field->name, field->type);
+
+		if (i < db_tab->num_fields - 1)
+			p += snprintf(p, end - p, ", ");
+	}
+	p += snprintf(p, end - p, ")");
+
+#ifdef DEBUG_SQL
+	log(TERM, LOG_INFO, "SQL: %s\n", sql);
+#endif
+
+	rc = sqlite3_exec(priv->db, sql, NULL, NULL, NULL);
+	if (rc != SQLITE_OK) {
+		log(TERM, LOG_ERR,
+		    "Failed to create table %s on %s: error = %d\n",
+		    db_tab->name, SQLITE_RAS_DB, rc);
+	}
+	return rc;
+}
+
 int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras)
 {
 	int rc;
 	sqlite3 *db;
-	char sql[1024];
 	struct sqlite3_priv *priv;
 
 	printf("Calling %s()\n", __FUNCTION__);
@@ -137,27 +185,26 @@ int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras)
 		free(priv);
 		return -1;
 	}
+	priv->db = db;
 
-	strcpy(sql, createdb);
-	strcat(sql, mc_event_db);
-	strcat(sql, mc_event_db_create_fields);
-	rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
+	rc = ras_mc_create_table(priv, &mc_event_tab);
 	if (rc != SQLITE_OK) {
-		log(TERM, LOG_ERR,
-		    "cpu %u: Failed to create db on %s: error = %d\n",
-		    cpu, SQLITE_RAS_DB, rc);
+		sqlite3_close(db);
 		free(priv);
 		return -1;
 	}
 
-	priv->db = db;
-	ras->db_priv = priv;
-
-	rc = ras_mc_prepare_stmt(priv);
-	if (rc == SQLITE_OK)
+	rc = ras_mc_prepare_stmt(priv, &priv->stmt, &mc_event_tab);
+	if (rc == SQLITE_OK) {
 		log(TERM, LOG_INFO,
 		    "cpu %u: Recording events at %s\n",
 		    cpu, SQLITE_RAS_DB);
+		ras->db_priv = priv;
+	} else {
+		sqlite3_close(db);
+		free(priv);
+		return -1;
+	}
 
 	return 0;
 }
-- 
1.7.1