Search in sources :

Example 1 with JarLoader

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");
}
Also used : ColumnInfo(org.voltdb.VoltTable.ColumnInfo) CatalogSpecificPlanner(org.voltdb.CatalogSpecificPlanner) InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) CatalogAndIds(org.voltdb.utils.CatalogUtil.CatalogAndIds) VoltTable(org.voltdb.VoltTable) SpecifiedException(org.voltdb.exceptions.SpecifiedException) JarLoader(org.voltdb.utils.InMemoryJarfile.JarLoader) CatalogContext(org.voltdb.CatalogContext) DependencyPair(org.voltdb.DependencyPair)

Example 2 with JarLoader

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);
}
Also used : VoltCompiler(org.voltdb.compiler.VoltCompiler) JarLoader(org.voltdb.utils.InMemoryJarfile.JarLoader)

Example 3 with JarLoader

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();
    }
}
Also used : JarLoader(org.voltdb.utils.InMemoryJarfile.JarLoader) BufferedInputStream(java.io.BufferedInputStream) InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException)

Example 4 with JarLoader

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();
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) ImmutableList(com.google_voltpatches.common.collect.ImmutableList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) JarFile(java.util.jar.JarFile) JarEntry(java.util.jar.JarEntry) URL(java.net.URL) JAXBException(javax.xml.bind.JAXBException) SAXException(org.xml.sax.SAXException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) SAXParseException(org.xml.sax.SAXParseException) JarLoader(org.voltdb.utils.InMemoryJarfile.JarLoader) JarFile(java.util.jar.JarFile) File(java.io.File)

Aggregations

JarLoader (org.voltdb.utils.InMemoryJarfile.JarLoader)4 IOException (java.io.IOException)2 InMemoryJarfile (org.voltdb.utils.InMemoryJarfile)2 ImmutableList (com.google_voltpatches.common.collect.ImmutableList)1 BufferedInputStream (java.io.BufferedInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 File (java.io.File)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 MalformedURLException (java.net.MalformedURLException)1 URL (java.net.URL)1 JarEntry (java.util.jar.JarEntry)1 JarFile (java.util.jar.JarFile)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 JAXBException (javax.xml.bind.JAXBException)1 CatalogContext (org.voltdb.CatalogContext)1 CatalogSpecificPlanner (org.voltdb.CatalogSpecificPlanner)1 DependencyPair (org.voltdb.DependencyPair)1 VoltTable (org.voltdb.VoltTable)1 ColumnInfo (org.voltdb.VoltTable.ColumnInfo)1