use of org.voltdb.utils.InMemoryJarfile.JarLoader 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.InMemoryJarfile.JarLoader in project voltdb by VoltDB.
the class TestInMemoryJarfile method testJarfileRemoveClassRemovesInnerClasses.
public void testJarfileRemoveClassRemovesInnerClasses() throws Exception {
InMemoryJarfile dut = new InMemoryJarfile();
// Add a class file that we know has inner classes
// Someday this seems like it should be an operation directly on InMemoryJarfile
VoltCompiler comp = new VoltCompiler(false);
// This will pull in all the inner classes (currently 4 of them), but check anyway
comp.addClassToJar(dut, org.voltdb_testprocs.updateclasses.InnerClassesTestProc.class);
JarLoader loader = dut.getLoader();
assertEquals(5, loader.getClassNames().size());
System.out.println(loader.getClassNames());
assertTrue(loader.getClassNames().contains("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerNotPublic"));
assertTrue(dut.get("org/voltdb_testprocs/updateclasses/InnerClassesTestProc$InnerNotPublic.class") != null);
// Now, remove the outer class and verify that all the inner classes go away.
dut.removeClassFromJar("org.voltdb_testprocs.updateclasses.InnerClassesTestProc");
assertTrue(loader.getClassNames().isEmpty());
assertTrue(dut.get("org/voltdb_testprocs/updateclasses/InnerClassesTestProc$InnerNotPublic.class") == null);
}
use of org.voltdb.utils.InMemoryJarfile.JarLoader in project voltdb by VoltDB.
the class VoltCompilerUtils method getClassAsBytes.
public static byte[] getClassAsBytes(final Class<?> c) throws IOException {
ClassLoader cl = c.getClassLoader();
if (cl == null) {
cl = Thread.currentThread().getContextClassLoader();
}
String classAsPath = classNameToPackagePath(c.getName());
if (cl instanceof JarLoader) {
InMemoryJarfile memJar = ((JarLoader) cl).getInMemoryJarfile();
return memJar.get(classAsPath);
} else {
BufferedInputStream cis = null;
ByteArrayOutputStream baos = null;
try {
cis = new BufferedInputStream(cl.getResourceAsStream(classAsPath));
baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int rsize = 0;
while ((rsize = cis.read(buf)) != -1) {
baos.write(buf, 0, rsize);
}
} finally {
try {
if (cis != null)
cis.close();
} catch (Exception ignoreIt) {
}
try {
if (baos != null)
baos.close();
} catch (Exception ignoreIt) {
}
}
return baos.toByteArray();
}
}
use of org.voltdb.utils.InMemoryJarfile.JarLoader in project voltdb by VoltDB.
the class VoltCompiler method getInnerClasses.
public List<Class<?>> getInnerClasses(Class<?> c) throws VoltCompilerException {
ImmutableList.Builder<Class<?>> builder = ImmutableList.builder();
ClassLoader cl = c.getClassLoader();
if (cl == null) {
cl = Thread.currentThread().getContextClassLoader();
}
// if loading from an InMemoryJarFile, the process is a bit different...
if (cl instanceof JarLoader) {
String[] classes = ((JarLoader) cl).getInnerClassesForClass(c.getName());
for (String innerName : classes) {
Class<?> clz = null;
try {
clz = cl.loadClass(innerName);
} catch (ClassNotFoundException e) {
String msg = "Unable to load " + c + " inner class " + innerName + " from in-memory jar representation.";
throw new VoltCompilerException(msg);
}
assert (clz != null);
builder.add(clz);
}
} else {
String stem = c.getName().replace('.', '/');
String cpath = stem + ".class";
URL curl = cl.getResource(cpath);
if (curl == null) {
throw new VoltCompilerException(String.format("Failed to find class file %s in jar.", cpath));
}
// load from an on-disk jar
if ("jar".equals(curl.getProtocol())) {
Pattern nameRE = Pattern.compile("\\A(" + stem + "\\$[^/]+).class\\z");
String jarFN;
try {
jarFN = URLDecoder.decode(curl.getFile(), "UTF-8");
} catch (UnsupportedEncodingException e) {
String msg = "Unable to UTF-8 decode " + curl.getFile() + " for class " + c;
throw new VoltCompilerException(msg);
}
jarFN = jarFN.substring(5, jarFN.indexOf('!'));
JarFile jar = null;
try {
jar = new JarFile(jarFN);
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
String name = entries.nextElement().getName();
Matcher mtc = nameRE.matcher(name);
if (mtc.find()) {
String innerName = mtc.group(1).replace('/', '.');
Class<?> inner;
try {
inner = cl.loadClass(innerName);
} catch (ClassNotFoundException e) {
String msg = "Unable to load " + c + " inner class " + innerName;
throw new VoltCompilerException(msg);
}
builder.add(inner);
}
}
} catch (IOException e) {
String msg = "Cannot access class " + c + " source code location of " + jarFN;
throw new VoltCompilerException(msg);
} finally {
if (jar != null)
try {
jar.close();
} catch (Exception ignoreIt) {
}
;
}
} else // load directly from a classfile
if ("file".equals(curl.getProtocol())) {
Pattern nameRE = Pattern.compile("/(" + stem + "\\$[^/]+).class\\z");
File sourceDH = new File(curl.getFile()).getParentFile();
for (File f : sourceDH.listFiles()) {
Matcher mtc = nameRE.matcher(f.getAbsolutePath());
if (mtc.find()) {
String innerName = mtc.group(1).replace('/', '.');
Class<?> inner;
try {
inner = cl.loadClass(innerName);
} catch (ClassNotFoundException e) {
String msg = "Unable to load " + c + " inner class " + innerName;
throw new VoltCompilerException(msg);
}
builder.add(inner);
}
}
}
}
return builder.build();
}
Aggregations