use of org.voltdb.utils.CatalogUtil.CatalogAndIds in project voltdb by VoltDB.
the class UpdateCore method executePlanFragment.
@Override
public DependencyPair executePlanFragment(Map<Integer, List<VoltTable>> dependencies, long fragmentId, ParameterSet params, SystemProcedureExecutionContext context) {
if (fragmentId == SysProcFragmentId.PF_updateCatalogPrecheckAndSync) {
String[] tablesThatMustBeEmpty = (String[]) params.getParam(0);
String[] reasonsForEmptyTables = (String[]) params.getParam(1);
checkForNonEmptyTables(tablesThatMustBeEmpty, reasonsForEmptyTables, context);
// Send out fragments to do the initial round-trip to synchronize
// all the cluster sites on the start of catalog update, we'll do
// the actual work on the *next* round-trip below
// Don't actually care about the returned table, just need to send something
// back to the MPI scoreboard
DependencyPair success = new DependencyPair.TableDependencyPair(DEP_updateCatalogSync, new VoltTable(new ColumnInfo[] { new ColumnInfo("UNUSED", VoltType.BIGINT) }));
if (!context.isLowestSiteId()) {
// id on this host.
if (log.isInfoEnabled()) {
log.info("Site " + CoreUtils.hsIdToString(m_site.getCorrespondingSiteId()) + " completed data precheck.");
}
return success;
}
// 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 {
m_javaClass.forName(classname, true, testjarloader);
}// care about here.
catch (UnsupportedClassVersionError e) {
String msg = "Cannot load classes compiled with a higher version of Java than currently" + " in use. Class " + classname + " was compiled with ";
Integer major = 0;
try {
major = Integer.parseInt(e.getMessage().split("version")[1].trim().split("\\.")[0]);
} catch (Exception ex) {
log.debug("Unable to parse compile version number from UnsupportedClassVersionError.", ex);
}
if (m_versionMap.containsKey(major)) {
msg = msg.concat(m_versionMap.get(major) + ", current runtime version is " + System.getProperty("java.version") + ".");
} else {
msg = msg.concat("an incompatable Java version.");
}
log.error(msg);
throw new VoltAbortException(msg);
} 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);
}
if (log.isInfoEnabled()) {
log.info("Site " + CoreUtils.hsIdToString(m_site.getCorrespondingSiteId()) + " completed data and catalog precheck.");
}
return success;
} else if (fragmentId == SysProcFragmentId.PF_updateCatalogPrecheckAndSyncAggregate) {
// Don't actually care about the returned table, just need to send something
// back to the MPI scoreboard
log.info("Site " + CoreUtils.hsIdToString(m_site.getCorrespondingSiteId()) + " acknowledged data and catalog prechecks.");
return new DependencyPair.TableDependencyPair(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;
boolean requireCatalogDiffCmdsApplyToEE = ((Byte) params.toArray()[3]) != 0;
boolean hasSchemaChange = ((Byte) params.toArray()[4]) != 0;
boolean requiresNewExportGeneration = ((Byte) params.toArray()[5]) != 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, DeprecatedProcedureAPIAccess.getVoltPrivateRealTransactionId(this), getUniqueId(), catalogStuff.deploymentBytes, catalogStuff.getDeploymentHash(), requireCatalogDiffCmdsApplyToEE, hasSchemaChange, requiresNewExportGeneration);
// The producer would have been turned off by the code above already.
if (VoltDB.instance().getReplicationRole() == ReplicationRole.NONE && !VoltDB.instance().getReplicationActive()) {
context.resetDrAppliedTracker();
}
// update the local catalog. Safe to do this thanks to the check to get into here.
long uniqueId = m_runner.getUniqueId();
long spHandle = m_runner.getTxnState().getNotice().getSpHandle();
context.updateCatalog(commands, p.getFirst(), p.getSecond(), requiresSnapshotIsolation, uniqueId, spHandle, requireCatalogDiffCmdsApplyToEE, requiresNewExportGeneration);
if (log.isDebugEnabled()) {
log.debug(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));
}
} else // if seen before by this code, then check to see if this is a restart
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);
}
VoltTable result = new VoltTable(VoltSystemProcedure.STATUS_SCHEMA);
result.addRow(VoltSystemProcedure.STATUS_OK);
return new DependencyPair.TableDependencyPair(DEP_updateCatalog, result);
} else if (fragmentId == SysProcFragmentId.PF_updateCatalogAggregate) {
VoltTable result = VoltTableUtil.unionTables(dependencies.get(DEP_updateCatalog));
return new DependencyPair.TableDependencyPair(DEP_updateCatalogAggregate, result);
} else {
VoltDB.crashLocalVoltDB("Received unrecognized plan fragment id " + fragmentId + " in UpdateApplicationCatalog", false, null);
}
throw new RuntimeException("Should not reach this code");
}
use of org.voltdb.utils.CatalogUtil.CatalogAndIds in project voltdb by VoltDB.
the class RealVoltDB method readDeploymentAndCreateStarterCatalogContext.
boolean readDeploymentAndCreateStarterCatalogContext(VoltDB.Configuration config) {
/*
* Debate with the cluster what the deployment file should be
*/
try {
ZooKeeper zk = m_messenger.getZK();
byte[] deploymentBytes = null;
try {
deploymentBytes = org.voltcore.utils.CoreUtils.urlToBytes(m_config.m_pathToDeployment);
} catch (Exception ex) {
//Let us get bytes from ZK
}
DeploymentType deployment = null;
try {
if (deploymentBytes != null) {
CatalogUtil.writeCatalogToZK(zk, // Fill in innocuous values for non-deployment stuff
0, 0L, 0L, // spin loop in Inits.LoadCatalog.run() needs
new byte[] {}, // this to be of zero length until we have a real catalog.
null, deploymentBytes);
hostLog.info("URL of deployment: " + m_config.m_pathToDeployment);
} else {
CatalogAndIds catalogStuff = CatalogUtil.getCatalogFromZK(zk);
deploymentBytes = catalogStuff.deploymentBytes;
}
} catch (KeeperException.NodeExistsException e) {
CatalogAndIds catalogStuff = CatalogUtil.getCatalogFromZK(zk);
byte[] deploymentBytesTemp = catalogStuff.deploymentBytes;
if (deploymentBytesTemp != null) {
//We will ignore the supplied or default deployment anyways.
if (deploymentBytes != null && !m_config.m_deploymentDefault) {
byte[] deploymentHashHere = CatalogUtil.makeDeploymentHash(deploymentBytes);
if (!(Arrays.equals(deploymentHashHere, catalogStuff.getDeploymentHash()))) {
hostLog.warn("The locally provided deployment configuration did not " + " match the configuration information found in the cluster.");
} else {
hostLog.info("Deployment configuration pulled from other cluster node.");
}
}
//Use remote deployment obtained.
deploymentBytes = deploymentBytesTemp;
} else {
hostLog.error("Deployment file could not be loaded locally or remotely, " + "local supplied path: " + m_config.m_pathToDeployment);
deploymentBytes = null;
}
} catch (KeeperException.NoNodeException e) {
// no deploymentBytes case is handled below. So just log this error.
if (hostLog.isDebugEnabled()) {
hostLog.debug("Error trying to get deployment bytes from cluster", e);
}
}
if (deploymentBytes == null) {
hostLog.error("Deployment information could not be obtained from cluster node or locally");
VoltDB.crashLocalVoltDB("No such deployment file: " + m_config.m_pathToDeployment, false, null);
}
if (deployment == null) {
deployment = CatalogUtil.getDeployment(new ByteArrayInputStream(deploymentBytes));
}
// wasn't a valid xml deployment file
if (deployment == null) {
hostLog.error("Not a valid XML deployment file at URL: " + m_config.m_pathToDeployment);
VoltDB.crashLocalVoltDB("Not a valid XML deployment file at URL: " + m_config.m_pathToDeployment, false, null);
}
/*
* Check for invalid deployment file settings (enterprise-only) in the community edition.
* Trick here is to print out all applicable problems and then stop, rather than stopping
* after the first one is found.
*/
if (!m_config.m_isEnterprise) {
boolean shutdownDeployment = false;
boolean shutdownAction = false;
// check license features for community version
if ((deployment.getCluster() != null) && (deployment.getCluster().getKfactor() > 0)) {
consoleLog.error("K-Safety is not supported " + "in the community edition of VoltDB.");
shutdownDeployment = true;
}
if ((deployment.getSnapshot() != null) && (deployment.getSnapshot().isEnabled())) {
consoleLog.error("Snapshots are not supported " + "in the community edition of VoltDB.");
shutdownDeployment = true;
}
if ((deployment.getCommandlog() != null) && (deployment.getCommandlog().isEnabled())) {
consoleLog.error("Command logging is not supported " + "in the community edition of VoltDB.");
shutdownDeployment = true;
}
if ((deployment.getExport() != null) && deployment.getExport().getConfiguration() != null && !deployment.getExport().getConfiguration().isEmpty()) {
consoleLog.error("Export is not supported " + "in the community edition of VoltDB.");
shutdownDeployment = true;
}
// check the start action for the community edition
if (m_config.m_startAction != StartAction.CREATE) {
consoleLog.error("Start action \"" + m_config.m_startAction.getClass().getSimpleName() + "\" is not supported in the community edition of VoltDB.");
shutdownAction = true;
}
// if the process needs to stop, try to be helpful
if (shutdownAction || shutdownDeployment) {
String msg = "This process will exit. Please run VoltDB with ";
if (shutdownDeployment) {
msg += "a deployment file compatible with the community edition";
}
if (shutdownDeployment && shutdownAction) {
msg += " and ";
}
if (shutdownAction && !shutdownDeployment) {
msg += "the CREATE start action";
}
msg += ".";
VoltDB.crashLocalVoltDB(msg, false, null);
}
}
// note the heart beats are specified in seconds in xml, but ms internally
HeartbeatType hbt = deployment.getHeartbeat();
if (hbt != null) {
m_config.m_deadHostTimeoutMS = hbt.getTimeout() * 1000;
m_messenger.setDeadHostTimeout(m_config.m_deadHostTimeoutMS);
} else {
hostLog.info("Dead host timeout set to " + m_config.m_deadHostTimeoutMS + " milliseconds");
}
PartitionDetectionType pt = deployment.getPartitionDetection();
if (pt != null) {
m_config.m_partitionDetectionEnabled = pt.isEnabled();
m_messenger.setPartitionDetectionEnabled(m_config.m_partitionDetectionEnabled);
}
// get any consistency settings into config
ConsistencyType consistencyType = deployment.getConsistency();
if (consistencyType != null) {
m_config.m_consistencyReadLevel = Consistency.ReadLevel.fromReadLevelType(consistencyType.getReadlevel());
}
final String elasticSetting = deployment.getCluster().getElastic().trim().toUpperCase();
if (elasticSetting.equals("ENABLED")) {
TheHashinator.setConfiguredHashinatorType(HashinatorType.ELASTIC);
} else if (!elasticSetting.equals("DISABLED")) {
VoltDB.crashLocalVoltDB("Error in deployment file, elastic attribute of " + "cluster element must be " + "'enabled' or 'disabled' but was '" + elasticSetting + "'", false, null);
} else {
TheHashinator.setConfiguredHashinatorType(HashinatorType.LEGACY);
}
// log system setting information
SystemSettingsType sysType = deployment.getSystemsettings();
if (sysType != null) {
if (sysType.getElastic() != null) {
hostLog.info("Elastic duration set to " + sysType.getElastic().getDuration() + " milliseconds");
hostLog.info("Elastic throughput set to " + sysType.getElastic().getThroughput() + " mb/s");
}
if (sysType.getTemptables() != null) {
hostLog.info("Max temptable size set to " + sysType.getTemptables().getMaxsize() + " mb");
}
if (sysType.getSnapshot() != null) {
hostLog.info("Snapshot priority set to " + sysType.getSnapshot().getPriority() + " [0 - 10]");
}
if (sysType.getQuery() != null) {
if (sysType.getQuery().getTimeout() > 0) {
hostLog.info("Query timeout set to " + sysType.getQuery().getTimeout() + " milliseconds");
m_config.m_queryTimeout = sysType.getQuery().getTimeout();
} else if (sysType.getQuery().getTimeout() == 0) {
hostLog.info("Query timeout set to unlimited");
m_config.m_queryTimeout = 0;
}
}
}
// log a warning on console log if security setting is turned off, like durability warning.
SecurityType securityType = deployment.getSecurity();
if (securityType == null || !securityType.isEnabled()) {
consoleLog.warn(SECURITY_OFF_WARNING);
}
// create a dummy catalog to load deployment info into
Catalog catalog = new Catalog();
// Need these in the dummy catalog
Cluster cluster = catalog.getClusters().add("cluster");
cluster.getDatabases().add("database");
String result = CatalogUtil.compileDeployment(catalog, deployment, true);
if (result != null) {
// Any other non-enterprise deployment errors will be caught and handled here
// (such as <= 0 host count)
VoltDB.crashLocalVoltDB(result);
}
m_catalogContext = new CatalogContext(//txnid
TxnEgo.makeZero(MpInitiator.MP_INIT_PID).getTxnId(), //timestamp
0, catalog, new DbSettings(m_clusterSettings, m_nodeSettings), new byte[] {}, null, deploymentBytes, 0, m_messenger);
return ((deployment.getCommandlog() != null) && (deployment.getCommandlog().isEnabled()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.voltdb.utils.CatalogUtil.CatalogAndIds in project voltdb by VoltDB.
the class UpdateCore method run.
/**
* Parameters to run are provided internally and do not map to the
* user's input.
* @param ctx
* @param catalogDiffCommands
* @param catalogURL
* @param expectedCatalogVersion
* @return Standard STATUS table.
*/
@SuppressWarnings("deprecation")
public VoltTable[] run(SystemProcedureExecutionContext ctx, String catalogDiffCommands, byte[] catalogHash, byte[] catalogBytes, int expectedCatalogVersion, String deploymentString, String[] tablesThatMustBeEmpty, String[] reasonsForEmptyTables, byte requiresSnapshotIsolation, byte worksWithElastic, byte[] deploymentHash, byte requireCatalogDiffCmdsApplyToEE, byte hasSchemaChange, byte requiresNewExportGeneration) throws Exception {
assert (tablesThatMustBeEmpty != null);
/*
* Validate that no elastic join is in progress, blocking this catalog update.
* If this update works with elastic then do the update anyways
*/
ZooKeeper zk = VoltDB.instance().getHostMessenger().getZK();
if (worksWithElastic == 0 && !zk.getChildren(VoltZK.catalogUpdateBlockers, false).isEmpty()) {
throw new VoltAbortException("Can't do a catalog update while an elastic join or rejoin is active");
}
// write uac blocker zk node
VoltZK.createCatalogUpdateBlocker(zk, VoltZK.uacActiveBlocker);
// check rejoin blocker node
if (zk.exists(VoltZK.rejoinActiveBlocker, false) != null) {
VoltZK.removeCatalogUpdateBlocker(zk, VoltZK.uacActiveBlocker, log);
throw new VoltAbortException("Can't do a catalog update while an elastic join or rejoin is active");
}
try {
// Pull the current catalog and deployment version and hash info. Validate that we're either:
// (a) starting a new, valid catalog or deployment update
// (b) restarting a valid catalog or deployment update
// otherwise, we can bomb out early. This should guarantee that we only
// ever write valid catalog and deployment state to ZK.
CatalogAndIds catalogStuff = CatalogUtil.getCatalogFromZK(zk);
// New update?
if (catalogStuff.version == expectedCatalogVersion) {
if (log.isInfoEnabled()) {
log.info("New catalog update from: " + catalogStuff.toString());
log.info("To: catalog hash: " + Encoder.hexEncode(catalogHash).substring(0, 10) + ", deployment hash: " + Encoder.hexEncode(deploymentHash).substring(0, 10));
}
} else // restart?
{
if (catalogStuff.version == (expectedCatalogVersion + 1) && Arrays.equals(catalogStuff.getCatalogHash(), catalogHash) && Arrays.equals(catalogStuff.getDeploymentHash(), deploymentHash)) {
if (log.isInfoEnabled()) {
log.info("Restarting catalog update: " + catalogStuff.toString());
}
} else {
String errmsg = "Invalid catalog update. Catalog or deployment change was planned " + "against one version of the cluster configuration but that version was " + "no longer live when attempting to apply the change. This is likely " + "the result of multiple concurrent attempts to change the cluster " + "configuration. Please make such changes synchronously from a single " + "connection to the cluster.";
log.warn(errmsg);
throw new VoltAbortException(errmsg);
}
}
byte[] deploymentBytes = deploymentString.getBytes("UTF-8");
// update the global version. only one site per node will accomplish this.
// others will see there is no work to do and gracefully continue.
// then update data at the local site.
CatalogUtil.updateCatalogToZK(zk, expectedCatalogVersion + 1, DeprecatedProcedureAPIAccess.getVoltPrivateRealTransactionId(this), getUniqueId(), catalogBytes, catalogHash, deploymentBytes);
try {
performCatalogVerifyWork(expectedCatalogVersion, tablesThatMustBeEmpty, reasonsForEmptyTables, requiresSnapshotIsolation);
} catch (VoltAbortException vae) {
// If there is a cluster failure before this point, we will re-run
// the transaction with the same input args and the new state,
// which we will recognize as a restart and do the right thing.
log.debug("Catalog update cannot be applied. Rolling back ZK state");
CatalogUtil.updateCatalogToZK(zk, catalogStuff.version, catalogStuff.txnId, catalogStuff.uniqueId, catalogStuff.catalogBytes, catalogStuff.getCatalogHash(), catalogStuff.deploymentBytes);
// hopefully this will throw a SpecifiedException if the fragment threw one
throw vae;
// If there is a cluster failure after this point, we will re-run
// the transaction with the same input args and the old state,
// which will look like a new UAC transaction. If there is no
// cluster failure, we leave the ZK state consistent with the
// catalog state which we entered here with.
}
performCatalogUpdateWork(catalogDiffCommands, expectedCatalogVersion, requiresSnapshotIsolation, requireCatalogDiffCmdsApplyToEE, hasSchemaChange, requiresNewExportGeneration);
} finally {
// remove the uac blocker when exits
VoltZK.removeCatalogUpdateBlocker(zk, VoltZK.uacActiveBlocker, log);
}
// This is when the UpdateApplicationCatalog really ends in the blocking path
log.info(String.format("Globally updating the current application catalog and deployment " + "(new hashes %s, %s).", Encoder.hexEncode(catalogHash).substring(0, 10), Encoder.hexEncode(deploymentHash).substring(0, 10)));
VoltTable result = new VoltTable(VoltSystemProcedure.STATUS_SCHEMA);
result.addRow(VoltSystemProcedure.STATUS_OK);
return (new VoltTable[] { result });
}
Aggregations