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.
154 lines
4.3 KiB
154 lines
4.3 KiB
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;
|
|
|