From fa667968633baa8909ca63c01edef50d6ce2fad0 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Thu, 5 Jan 2012 20:35:55 +0000 Subject: [PATCH] When grabbing the schema migration lock, ensure that the current version is set to what we expect it to be. Otherwise if one node reads an old value for the schema version, it will be able to grab the migration lock as long as another node has already completed the migration. --- .../java/com/samskivert/depot/impl/DepotMarshaller.java | 7 +++++-- src/main/java/com/samskivert/depot/impl/DepotMetaData.java | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java b/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java index caf4d17..68c30ae 100644 --- a/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java +++ b/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java @@ -530,7 +530,7 @@ public class DepotMarshaller implements QueryMarshal // try to update migratingVersion to the new version to indicate to other processes // that we are handling the migration and that they should wait - if (_meta.updateMigratingVersion(getTableName(), _schemaVersion, 0)) { + if (_meta.updateMigratingVersion(getTableName(), currentVersion, _schemaVersion, 0)) { break; // we got the lock, let's go } @@ -549,6 +549,7 @@ public class DepotMarshaller implements QueryMarshal // fetch all relevant information regarding our table from the database TableMetaData metaData = TableMetaData.load(ctx, getTableName()); + int expectedDbVersion = currentVersion; try { if (!metaData.tableExists) { // if the table does not exist, create it @@ -564,11 +565,13 @@ public class DepotMarshaller implements QueryMarshal // and update our version in the schema version table _meta.updateVersion(getTableName(), _schemaVersion); + expectedDbVersion = _schemaVersion; } finally { // set our migrating version back to zero try { - if (!_meta.updateMigratingVersion(getTableName(), 0, _schemaVersion)) { + if (!_meta.updateMigratingVersion( + getTableName(), expectedDbVersion, 0, _schemaVersion)) { log.warning("Failed to restore migrating version to zero!", "record", _pClass); } } catch (Exception e) { diff --git a/src/main/java/com/samskivert/depot/impl/DepotMetaData.java b/src/main/java/com/samskivert/depot/impl/DepotMetaData.java index c8ac971..b6e3574 100644 --- a/src/main/java/com/samskivert/depot/impl/DepotMetaData.java +++ b/src/main/java/com/samskivert/depot/impl/DepotMetaData.java @@ -126,7 +126,8 @@ public class DepotMetaData * if some other process acquired the lock. */ public boolean updateMigratingVersion ( - final String pClass, final int newMigratingVersion, final int guardVersion) + final String pClass, final int currentVersion, + final int newMigratingVersion, final int guardVersion) { return _ctx.invoke(new SimpleModifier() { @Override @@ -135,6 +136,7 @@ public class DepotMetaData "update " + liaison.tableSQL(SCHEMA_VERSION_TABLE) + " set " + liaison.columnSQL(MV_COLUMN) + " = " + newMigratingVersion + " where " + liaison.columnSQL(P_COLUMN) + " = '" + pClass + "'" + + " and " + liaison.columnSQL(V_COLUMN) + " = " + currentVersion + " and " + liaison.columnSQL(MV_COLUMN) + " = " + guardVersion); } }) > 0;