use of org.apache.cassandra.db.migration.Migration in project eiger by wlloyd.
the class DefinitionsUpdateVerbHandler method doVerb.
/** someone sent me their data definitions */
public void doVerb(final Message message, String id) {
try {
// these are the serialized row mutations that I must apply.
// check versions at every step along the way to make sure migrations are not applied out of order.
Collection<Column> cols = MigrationManager.makeColumns(message);
for (Column col : cols) {
final UUID version = UUIDGen.getUUID(col.name());
if (version.timestamp() > Schema.instance.getVersion().timestamp()) {
final Migration m = Migration.deserialize(col.value(), message.getVersion());
assert m.getVersion().equals(version);
StageManager.getStage(Stage.MIGRATION).submit(new WrappedRunnable() {
protected void runMayThrow() throws Exception {
// check to make sure the current version is before this one.
if (Schema.instance.getVersion().timestamp() == version.timestamp())
logger.debug("Not appling (equal) " + version.toString());
else if (Schema.instance.getVersion().timestamp() > version.timestamp())
logger.debug("Not applying (before)" + version.toString());
else {
logger.debug("Applying {} from {}", m.getClass().getSimpleName(), message.getFrom());
try {
m.apply();
// update gossip, but don't contact nodes directly
m.passiveAnnounce();
} catch (ConfigurationException ex) {
// Trying to apply the same migration twice. This happens as a result of gossip.
logger.debug("Migration not applied " + ex.getMessage());
}
}
}
});
}
}
} catch (IOException ex) {
throw new IOError(ex);
}
}
use of org.apache.cassandra.db.migration.Migration in project eiger by wlloyd.
the class DefsTest method testMigrations.
@Test
public void testMigrations() throws IOException, ConfigurationException {
// do a save. make sure it doesn't mess with the defs version.
UUID prior = Schema.instance.getVersion();
UUID ver0 = UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress());
DefsTable.dumpToStorage(ver0);
assert Schema.instance.getVersion().equals(prior);
// add a cf.
CFMetaData newCf1 = addTestCF("Keyspace1", "MigrationCf_1", "Migration CF");
Migration m1 = new AddColumnFamily(newCf1);
m1.apply();
UUID ver1 = m1.getVersion();
assert Schema.instance.getVersion().equals(ver1);
// drop it.
Migration m3 = new DropColumnFamily("Keyspace1", "MigrationCf_1");
m3.apply();
UUID ver3 = m3.getVersion();
assert Schema.instance.getVersion().equals(ver3);
// now lets load the older migrations to see if that code works.
Collection<IColumn> serializedMigrations = Migration.getLocalMigrations(ver1, ver3);
assert serializedMigrations.size() == 2;
// test deserialization of the migrations.
Migration[] reconstituded = new Migration[2];
int i = 0;
for (IColumn col : serializedMigrations) {
UUID version = UUIDGen.getUUID(col.name());
reconstituded[i] = Migration.deserialize(col.value(), MessagingService.version_);
assert version.equals(reconstituded[i].getVersion());
i++;
}
assert m1.getClass().equals(reconstituded[0].getClass());
assert m3.getClass().equals(reconstituded[1].getClass());
// verify that the row mutations are the same. rather than exposing the private fields, serialize and verify.
assert m1.serialize().equals(reconstituded[0].serialize());
assert m3.serialize().equals(reconstituded[1].serialize());
}
use of org.apache.cassandra.db.migration.Migration in project eiger by wlloyd.
the class MigrationManager method applyMigrations.
/**
* gets called during startup if we notice a mismatch between the current migration version and the one saved. This
* can only happen as a result of the commit log recovering schema updates, which overwrites lastVersionId.
*
* This method silently eats IOExceptions thrown by Migration.apply() as a result of applying a migration out of
* order.
*/
public static void applyMigrations(final UUID from, final UUID to) throws IOException {
List<Future<?>> updates = new ArrayList<Future<?>>();
Collection<IColumn> migrations = Migration.getLocalMigrations(from, to);
for (IColumn col : migrations) {
// assuming MessagingService.version_ is a bit of a risk, but you're playing with fire if you purposefully
// take down a node to upgrade it during the middle of a schema update.
final Migration migration = Migration.deserialize(col.value(), MessagingService.version_);
Future<?> update = StageManager.getStage(Stage.MIGRATION).submit(new Runnable() {
public void run() {
try {
migration.apply();
} catch (ConfigurationException ex) {
// this happens if we try to apply something that's already been applied. ignore and proceed.
logger.debug("Migration not applied " + ex.getMessage());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
});
updates.add(update);
}
// wait on all the updates before proceeding.
for (Future<?> f : updates) {
try {
f.get();
} catch (InterruptedException e) {
throw new IOException(e);
} catch (ExecutionException e) {
throw new IOException(e);
}
}
// we don't need to send rpcs, but we need to update gossip
passiveAnnounce(to);
}
Aggregations