You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.3 KiB
155 lines
4.3 KiB
7 years ago
|
diff -up nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c
|
||
|
--- nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig 2016-02-10 10:46:23.100398000 -0500
|
||
|
+++ nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c 2016-02-10 10:46:59.540317000 -0500
|
||
|
@@ -29,7 +29,9 @@
|
||
|
*
|
||
|
* clients: an "id" column containing a BLOB with the long-form clientid as
|
||
|
* sent by the client, a "time" column containing a timestamp (in
|
||
|
- * epoch seconds) of when the record was last updated.
|
||
|
+ * epoch seconds) of when the record was last updated, and a
|
||
|
+ * "has_session" column containing a boolean value indicating
|
||
|
+ * whether the client has sessions (v4.1+) or not (v4.0).
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
@@ -50,7 +52,7 @@
|
||
|
|
||
|
#include "xlog.h"
|
||
|
|
||
|
-#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
|
||
|
+#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 2
|
||
|
|
||
|
/* in milliseconds */
|
||
|
#define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
|
||
|
@@ -120,6 +122,81 @@ out:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+sqlite_maindb_update_v1_to_v2(void)
|
||
|
+{
|
||
|
+ int ret, ret2;
|
||
|
+ char *err;
|
||
|
+
|
||
|
+ /* begin transaction */
|
||
|
+ ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
|
||
|
+ &err);
|
||
|
+ if (ret != SQLITE_OK) {
|
||
|
+ xlog(L_ERROR, "Unable to begin transaction: %s", err);
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Check schema version again. This time, under an exclusive
|
||
|
+ * transaction to guard against racing DB setup attempts
|
||
|
+ */
|
||
|
+ ret = sqlite_query_schema_version();
|
||
|
+ switch (ret) {
|
||
|
+ case 1:
|
||
|
+ /* Still at v1 -- do conversion */
|
||
|
+ break;
|
||
|
+ case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
|
||
|
+ /* Someone else raced in and set it up */
|
||
|
+ ret = 0;
|
||
|
+ goto rollback;
|
||
|
+ default:
|
||
|
+ /* Something went wrong -- fail! */
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* create v2 clients table */
|
||
|
+ ret = sqlite3_exec(dbh, "ALTER TABLE clients ADD COLUMN "
|
||
|
+ "has_session INTEGER;",
|
||
|
+ NULL, NULL, &err);
|
||
|
+ if (ret != SQLITE_OK) {
|
||
|
+ xlog(L_ERROR, "Unable to update clients table: %s", err);
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = snprintf(buf, sizeof(buf), "UPDATE parameters SET value = %d "
|
||
|
+ "WHERE key = \"version\";",
|
||
|
+ CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
|
||
|
+ if (ret < 0) {
|
||
|
+ xlog(L_ERROR, "sprintf failed!");
|
||
|
+ goto rollback;
|
||
|
+ } else if ((size_t)ret >= sizeof(buf)) {
|
||
|
+ xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
|
||
|
+ if (ret != SQLITE_OK) {
|
||
|
+ xlog(L_ERROR, "Unable to update schema version: %s", err);
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
|
||
|
+ if (ret != SQLITE_OK) {
|
||
|
+ xlog(L_ERROR, "Unable to commit transaction: %s", err);
|
||
|
+ goto rollback;
|
||
|
+ }
|
||
|
+out:
|
||
|
+ sqlite3_free(err);
|
||
|
+ return ret;
|
||
|
+rollback:
|
||
|
+ ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
|
||
|
+ if (ret2 != SQLITE_OK)
|
||
|
+ xlog(L_ERROR, "Unable to rollback transaction: %s", err);
|
||
|
+ goto out;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Start an exclusive transaction and recheck the DB schema version. If it's
|
||
|
* still zero (indicating a new database) then set it up. If that all works,
|
||
|
@@ -127,9 +204,9 @@ out:
|
||
|
* transaction. On any error, rollback the transaction.
|
||
|
*/
|
||
|
int
|
||
|
-sqlite_maindb_init_v1(void)
|
||
|
+sqlite_maindb_init_v2(void)
|
||
|
{
|
||
|
- int ret;
|
||
|
+ int ret, ret2;
|
||
|
char *err = NULL;
|
||
|
|
||
|
/* Start a transaction */
|
||
|
@@ -169,7 +246,7 @@ sqlite_maindb_init_v1(void)
|
||
|
|
||
|
/* create the "clients" table */
|
||
|
ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
|
||
|
- "time INTEGER);",
|
||
|
+ "time INTEGER, has_session INTEGER);",
|
||
|
NULL, NULL, &err);
|
||
|
if (ret != SQLITE_OK) {
|
||
|
xlog(L_ERROR, "Unable to create clients table: %s", err);
|
||
|
@@ -207,7 +284,9 @@ out:
|
||
|
|
||
|
rollback:
|
||
|
/* Attempt to rollback the transaction */
|
||
|
- sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
|
||
|
+ ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
|
||
|
+ if (ret2 != SQLITE_OK)
|
||
|
+ xlog(L_ERROR, "Unable to rollback transaction: %s", err);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
@@ -255,9 +334,15 @@ sqlite_prepare_dbh(const char *topdir)
|
||
|
/* DB is already set up. Do nothing */
|
||
|
ret = 0;
|
||
|
break;
|
||
|
+ case 1:
|
||
|
+ /* Old DB -- update to new schema */
|
||
|
+ ret = sqlite_maindb_update_v1_to_v2();
|
||
|
+ if (ret)
|
||
|
+ goto out_close;
|
||
|
+ break;
|
||
|
case 0:
|
||
|
/* Query failed -- try to set up new DB */
|
||
|
- ret = sqlite_maindb_init_v1();
|
||
|
+ ret = sqlite_maindb_init_v2();
|
||
|
if (ret)
|
||
|
goto out_close;
|
||
|
break;
|