// Don't actually care about the returned table, just need to send something
// back to the MPI scoreboard
// We know the ZK bytes are okay because the run() method wrote them before sending
// out fragments
CatalogAndIds catalogStuff = null;
try {
catalogStuff = CatalogUtil.getCatalogFromZK(VoltDB.instance().getHostMessenger().getZK());
InMemoryJarfile testjar = new InMemoryJarfile(catalogStuff.catalogBytes);
JarLoader testjarloader = testjar.getLoader();
for (String classname : testjarloader.getClassNames()) {
try {
Class.forName(classname, true, testjarloader);
}
// LinkageError catches most of the various class loading errors we'd
// care about here.
catch (LinkageError | ClassNotFoundException e) {
String cause = e.getMessage();
if (cause == null && e.getCause() != null) {
cause = e.getCause().getMessage();
}
String msg = "Error loading class: " + classname + " from catalog: " +
e.getClass().getCanonicalName() + ", " + cause;
log.warn(msg);
throw new VoltAbortException(e);
}
}
} catch (Exception e) {
Throwables.propagate(e);
}
return new DependencyPair(DEP_updateCatalogSync,
new VoltTable(new ColumnInfo[] { new ColumnInfo("UNUSED", VoltType.BIGINT) } ));
}
else if (fragmentId == SysProcFragmentId.PF_updateCatalogPrecheckAndSyncAggregate) {
// Don't actually care about the returned table, just need to send something
// back to the MPI scoreboard
return new DependencyPair(DEP_updateCatalogSyncAggregate,
new VoltTable(new ColumnInfo[] { new ColumnInfo("UNUSED", VoltType.BIGINT) } ));
}
else if (fragmentId == SysProcFragmentId.PF_updateCatalog) {
String catalogDiffCommands = (String)params.toArray()[0];
String commands = Encoder.decodeBase64AndDecompress(catalogDiffCommands);
int expectedCatalogVersion = (Integer)params.toArray()[1];
boolean requiresSnapshotIsolation = ((Byte) params.toArray()[2]) != 0;
CatalogAndIds catalogStuff = null;
try {
catalogStuff = CatalogUtil.getCatalogFromZK(VoltDB.instance().getHostMessenger().getZK());
} catch (Exception e) {
Throwables.propagate(e);
}
String replayInfo = m_runner.getTxnState().isForReplay() ? " (FOR REPLAY)" : "";
// if this is a new catalog, do the work to update
if (context.getCatalogVersion() == expectedCatalogVersion) {
// update the global catalog if we get there first
@SuppressWarnings("deprecation")
Pair<CatalogContext, CatalogSpecificPlanner> p =
VoltDB.instance().catalogUpdate(
commands,
catalogStuff.catalogBytes,
catalogStuff.getCatalogHash(),
expectedCatalogVersion,
getVoltPrivateRealTransactionIdDontUseMe(),
getUniqueId(),
catalogStuff.getDeploymentHash());
// update the local catalog. Safe to do this thanks to the check to get into here.
context.updateCatalog(commands, p.getFirst(), p.getSecond(), requiresSnapshotIsolation);
log.info(String.format("Site %s completed catalog update with catalog hash %s, deployment hash %s%s.",
CoreUtils.hsIdToString(m_site.getCorrespondingSiteId()),
Encoder.hexEncode(catalogStuff.getCatalogHash()).substring(0, 10),
Encoder.hexEncode(catalogStuff.getDeploymentHash()).substring(0, 10),
replayInfo));
}
// if seen before by this code, then check to see if this is a restart
else if ((context.getCatalogVersion() == (expectedCatalogVersion + 1) &&
(Arrays.equals(context.getCatalogHash(), catalogStuff.getCatalogHash()) &&
Arrays.equals(context.getDeploymentHash(), catalogStuff.getDeploymentHash()))))
{
log.info(String.format("Site %s will NOT apply an assumed restarted and identical catalog update with catalog hash %s and deployment hash %s.",
CoreUtils.hsIdToString(m_site.getCorrespondingSiteId()),
Encoder.hexEncode(catalogStuff.getCatalogHash()),
Encoder.hexEncode(catalogStuff.getDeploymentHash())));
}
else {
VoltDB.crashLocalVoltDB("Invalid catalog update. Expected version: " + expectedCatalogVersion +
", current version: " + context.getCatalogVersion(), false, null);
}