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