Search in sources :

Example 26 with InMemoryJarfile

use of org.voltdb.utils.InMemoryJarfile in project voltdb by VoltDB.

the class TestUpdateClasses method testDeleteClasses.

// Delete tests:
// single file match
// * match
// ** match
// comma-separated matches
// combine new jarfile with deleted stuff
// deleting inner classes
@Test
public void testDeleteClasses() throws Exception {
    System.out.println("\n\n-----\n testCollidingProc \n-----\n\n");
    String pathToCatalog = Configuration.getPathToCatalogForTest("updateclasses.jar");
    String pathToDeployment = Configuration.getPathToCatalogForTest("updateclasses.xml");
    VoltProjectBuilder builder = new VoltProjectBuilder();
    builder.addLiteralSchema("-- Don't care");
    builder.setUseDDLSchema(true);
    boolean success = builder.compile(pathToCatalog, 2, 1, 0);
    assertTrue("Schema compilation failed", success);
    MiscUtils.copyFile(builder.getPathToDeployment(), pathToDeployment);
    // This is maybe cheating a little bit?
    InMemoryJarfile jarfile = new InMemoryJarfile();
    for (Class<?> clazz : PROC_CLASSES) {
        VoltCompiler comp = new VoltCompiler(false);
        comp.addClassToJar(jarfile, clazz);
    }
    for (Class<?> clazz : EXTRA_CLASSES) {
        VoltCompiler comp = new VoltCompiler(false);
        comp.addClassToJar(jarfile, clazz);
    }
    for (Class<?> clazz : COLLIDING_CLASSES) {
        VoltCompiler comp = new VoltCompiler(false);
        comp.addClassToJar(jarfile, clazz);
    }
    try {
        VoltDB.Configuration config = new VoltDB.Configuration();
        config.m_pathToCatalog = pathToCatalog;
        config.m_pathToDeployment = pathToDeployment;
        startSystem(config);
        ClientResponse resp;
        // Make sure we're clean
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        assertEquals(0, resp.getResults()[0].getRowCount());
        // Add the jarfile we built
        resp = m_client.callProcedure("@UpdateClasses", jarfile.getFullJarBytes(), null);
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        assertEquals(PROC_CLASSES.length + EXTRA_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        // remove one class
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        resp = m_client.callProcedure("@UpdateClasses", null, PROC_CLASSES[0].getCanonicalName());
        assertFalse(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        // remove everything under fullddlfeatures
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        resp = m_client.callProcedure("@UpdateClasses", null, "org.voltdb_testprocs.fullddlfeatures.*");
        assertFalse(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertFalse(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        // Remove everything left
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(EXTRA_CLASSES[0].getCanonicalName()));
        resp = m_client.callProcedure("@UpdateClasses", null, "org.voltdb**");
        assertFalse(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertFalse(findClassInSystemCatalog(EXTRA_CLASSES[0].getCanonicalName()));
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        assertEquals(0, resp.getResults()[0].getRowCount());
        // put everything back
        // Add the jarfile we built
        resp = m_client.callProcedure("@UpdateClasses", jarfile.getFullJarBytes(), null);
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        assertEquals(PROC_CLASSES.length + EXTRA_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        // delete the common simple names from both packages simultaneously
        resp = m_client.callProcedure("@UpdateClasses", null, "**testImportProc   , **testCreateProcFromClassProc");
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        // should be the only thing left
        assertEquals(1, resp.getResults()[0].getRowCount());
        assertTrue(findClassInSystemCatalog(EXTRA_CLASSES[0].getCanonicalName()));
        // make a jar without the extra
        InMemoryJarfile jarfile2 = new InMemoryJarfile();
        for (Class<?> clazz : PROC_CLASSES) {
            VoltCompiler comp = new VoltCompiler(false);
            comp.addClassToJar(jarfile2, clazz);
        }
        for (Class<?> clazz : COLLIDING_CLASSES) {
            VoltCompiler comp = new VoltCompiler(false);
            comp.addClassToJar(jarfile2, clazz);
        }
        // finally, delete what's left and put the new jar in simultaneously
        resp = m_client.callProcedure("@UpdateClasses", jarfile2.getFullJarBytes(), "**updateclasses.*");
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        // extra class should be gone, others installed
        assertEquals(PROC_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        assertFalse(findClassInSystemCatalog(EXTRA_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        // now add a class with inner classes
        InMemoryJarfile inner = new InMemoryJarfile();
        VoltCompiler comp = new VoltCompiler(false);
        comp.addClassToJar(inner, org.voltdb_testprocs.updateclasses.InnerClassesTestProc.class);
        resp = m_client.callProcedure("@UpdateClasses", inner.getFullJarBytes(), null);
        // old stuff should have survived
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        // Did we get the new class and inner classes too?
        assertTrue(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc"));
        assertTrue(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerNotPublic"));
        assertTrue(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithConstructorArgs"));
        assertTrue(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithEasyConstructor"));
        assertTrue(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithNoConstructor"));
        // now just delete the parent class
        resp = m_client.callProcedure("@UpdateClasses", null, "org.voltdb_testprocs.updateclasses.InnerClassesTestProc");
        // old stuff should have survived
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        // Non-inner stuff should have survived
        assertEquals(PROC_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        // Inner classes and parent gone
        assertFalse(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc"));
        assertFalse(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerNotPublic"));
        assertFalse(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithConstructorArgs"));
        assertFalse(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithEasyConstructor"));
        assertFalse(findClassInSystemCatalog("org.voltdb_testprocs.updateclasses.InnerClassesTestProc$InnerWithNoConstructor"));
        // Empty string has no effect
        resp = m_client.callProcedure("@UpdateClasses", null, "");
        // old stuff should have survived
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        // Non-inner stuff should have survived
        assertEquals(PROC_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
        // pattern that matches nothing has no effect
        resp = m_client.callProcedure("@UpdateClasses", null, "com.voltdb.*");
        // old stuff should have survived
        resp = m_client.callProcedure("@SystemCatalog", "CLASSES");
        // Non-inner stuff should have survived
        assertEquals(PROC_CLASSES.length + COLLIDING_CLASSES.length, resp.getResults()[0].getRowCount());
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(PROC_CLASSES[1].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[0].getCanonicalName()));
        assertTrue(findClassInSystemCatalog(COLLIDING_CLASSES[1].getCanonicalName()));
    } finally {
        teardownSystem();
    }
}
Also used : VoltDB(org.voltdb.VoltDB) ClientResponse(org.voltdb.client.ClientResponse) VoltCompiler(org.voltdb.compiler.VoltCompiler) Configuration(org.voltdb.VoltDB.Configuration) VoltProjectBuilder(org.voltdb.compiler.VoltProjectBuilder) InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) Configuration(org.voltdb.VoltDB.Configuration) Test(org.junit.Test)

Example 27 with InMemoryJarfile

use of org.voltdb.utils.InMemoryJarfile in project voltdb by VoltDB.

the class VoltCompiler method compileInMemoryJarfile.

/**
     * Compile the provided jarfile.  Basically, treat the jarfile as a staging area
     * for the artifacts to be included in the compile, and then compile it in place.
     *
     * *NOTE*: Does *NOT* work with project.xml jarfiles.
     *
     * @return the compiled catalog is contained in the provided jarfile.
     *
     */
public void compileInMemoryJarfile(InMemoryJarfile jarfile) throws IOException {
    // Gather DDL files for recompilation
    List<VoltCompilerReader> ddlReaderList = new ArrayList<>();
    Entry<String, byte[]> entry = jarfile.firstEntry();
    while (entry != null) {
        String path = entry.getKey();
        // ddl files instead of using a brute force *.sql glob.
        if (path.toLowerCase().endsWith(".sql")) {
            ddlReaderList.add(new VoltCompilerJarFileReader(jarfile, path));
            compilerLog.trace("Added SQL file from jarfile to compilation: " + path);
        }
        entry = jarfile.higherEntry(entry.getKey());
    }
    // Use the in-memory jarfile-provided class loader so that procedure
    // classes can be found and copied to the new file that gets written.
    ClassLoader originalClassLoader = m_classLoader;
    try {
        m_classLoader = jarfile.getLoader();
        // Do the compilation work.
        InMemoryJarfile jarOut = compileInternal(null, null, ddlReaderList, jarfile);
        // explanation
        if (jarOut != null) {
            compilerLog.debug("Successfully recompiled InMemoryJarfile");
        } else {
            String errString = "Adhoc DDL failed";
            if (m_errors.size() > 0) {
                errString = m_errors.get(m_errors.size() - 1).getLogString();
            }
            int fronttrim = errString.indexOf("DDL Error");
            if (fronttrim < 0) {
                fronttrim = 0;
            }
            int endtrim = errString.indexOf(" in statement starting");
            if (endtrim < 0) {
                endtrim = errString.length();
            }
            String trimmed = errString.substring(fronttrim, endtrim);
            throw new IOException(trimmed);
        }
    } finally {
        // Restore the original class loader
        m_classLoader = originalClassLoader;
    }
}
Also used : InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) ArrayList(java.util.ArrayList) IOException(java.io.IOException)

Example 28 with InMemoryJarfile

use of org.voltdb.utils.InMemoryJarfile in project voltdb by VoltDB.

the class RealVoltDB method outputProcedures.

private int outputProcedures(Configuration config) {
    File outputFile = new File(config.m_getOutput);
    if (outputFile.exists() && !config.m_forceGetCreate) {
        consoleLog.fatal("Failed to save classes, file already exists: " + config.m_getOutput);
        return -1;
    }
    try {
        InMemoryJarfile catalogJar = CatalogUtil.loadInMemoryJarFile(MiscUtils.fileToBytes(new File(config.m_pathToCatalog)));
        InMemoryJarfile filteredJar = CatalogUtil.getCatalogJarWithoutDefaultArtifacts(catalogJar);
        filteredJar.writeToFile(outputFile);
        consoleLog.info("Classes saved in " + outputFile.getPath());
    } catch (IOException e) {
        consoleLog.fatal("Failed to read classes " + config.m_pathToCatalog + " : " + e.getMessage());
        return -1;
    }
    return 0;
}
Also used : InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) IOException(java.io.IOException) VoltFile(org.voltdb.utils.VoltFile) File(java.io.File)

Example 29 with InMemoryJarfile

use of org.voltdb.utils.InMemoryJarfile in project voltdb by VoltDB.

the class RestoreAgent method checkSnapshotIsComplete.

private SnapshotInfo checkSnapshotIsComplete(Long key, Snapshot s) {
    int partitionCount = -1;
    for (TableFiles tf : s.m_tableFiles.values()) {
        // Check if the snapshot is complete
        if (tf.m_completed.stream().anyMatch(b -> !b)) {
            m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because it was not completed.");
            return null;
        }
        // Replicated table doesn't check partition count
        if (tf.m_isReplicated) {
            continue;
        }
        // Everyone has to agree on the total partition count
        for (int count : tf.m_totalPartitionCounts) {
            if (partitionCount == -1) {
                partitionCount = count;
            } else if (count != partitionCount) {
                m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because it had the wrong partition count ").append(count).append(", expecting ").append(partitionCount);
                return null;
            }
        }
    }
    if (s.m_digests.isEmpty()) {
        m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because it had no valid digest file.");
        return null;
    }
    File digest = s.m_digests.get(0);
    Long catalog_crc = null;
    Map<Integer, Long> pidToTxnMap = new TreeMap<Integer, Long>();
    Set<String> digestTableNames = new HashSet<String>();
    // Create a valid but meaningless InstanceId to support pre-instanceId checking versions
    InstanceId instanceId = new InstanceId(0, 0);
    int newParitionCount = -1;
    try {
        JSONObject digest_detail = SnapshotUtil.CRCCheck(digest, LOG);
        if (digest_detail == null)
            throw new IOException();
        catalog_crc = digest_detail.getLong("catalogCRC");
        if (digest_detail.has("partitionTransactionIds")) {
            JSONObject pidToTxnId = digest_detail.getJSONObject("partitionTransactionIds");
            Iterator<String> it = pidToTxnId.keys();
            while (it.hasNext()) {
                String pidkey = it.next();
                Long txnidval = pidToTxnId.getLong(pidkey);
                pidToTxnMap.put(Integer.valueOf(pidkey), txnidval);
            }
        }
        if (digest_detail.has("instanceId")) {
            instanceId = new InstanceId(digest_detail.getJSONObject("instanceId"));
        }
        if (digest_detail.has("newPartitionCount")) {
            newParitionCount = digest_detail.getInt("newPartitionCount");
        }
        if (digest_detail.has("tables")) {
            JSONArray tableObj = digest_detail.getJSONArray("tables");
            for (int i = 0; i < tableObj.length(); i++) {
                digestTableNames.add(tableObj.getString(i));
            }
        }
    } catch (IOException ioe) {
        m_snapshotErrLogStr.append("\nUnable to read digest file: ").append(digest.getAbsolutePath()).append(" due to: ").append(ioe.getMessage());
        return null;
    } catch (JSONException je) {
        m_snapshotErrLogStr.append("\nUnable to extract catalog CRC from digest: ").append(digest.getAbsolutePath()).append(" due to: ").append(je.getMessage());
        return null;
    }
    if (s.m_catalogFile == null) {
        m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because it had no catalog.");
        return null;
    }
    try {
        byte[] bytes = MiscUtils.fileToBytes(s.m_catalogFile);
        InMemoryJarfile jarfile = CatalogUtil.loadInMemoryJarFile(bytes);
        if (jarfile.getCRC() != catalog_crc) {
            m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because catalog CRC did not match digest.");
            return null;
        }
        // Make sure this is not a partial snapshot.
        // Compare digestTableNames with all normal table names in catalog file.
        // A normal table is one that's NOT a materialized view, nor an export table.
        Set<String> catalogNormalTableNames = CatalogUtil.getNormalTableNamesFromInMemoryJar(jarfile);
        if (!catalogNormalTableNames.equals(digestTableNames)) {
            m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because this is a partial snapshot.");
            return null;
        }
    } catch (IOException ioe) {
        m_snapshotErrLogStr.append("\nRejected snapshot ").append(s.getNonce()).append(" because catalog file could not be validated");
        return null;
    }
    SnapshotInfo info = new SnapshotInfo(key, digest.getParent(), SnapshotUtil.parseNonceFromDigestFilename(digest.getName()), partitionCount, newParitionCount, catalog_crc, m_hostId, instanceId, digestTableNames, s.m_stype);
    // populate table to partition map.
    for (Entry<String, TableFiles> te : s.m_tableFiles.entrySet()) {
        TableFiles tableFile = te.getValue();
        HashSet<Integer> ids = new HashSet<Integer>();
        for (Set<Integer> idSet : tableFile.m_validPartitionIds) {
            ids.addAll(idSet);
        }
        if (!tableFile.m_isReplicated) {
            info.partitions.put(te.getKey(), ids);
        }
        // keep track of tables for which we've seen files while we're here
        info.fileTables.add(te.getKey());
    }
    info.setPidToTxnIdMap(pidToTxnMap);
    return info;
}
Also used : InstanceId(org.voltcore.utils.InstanceId) JSONArray(org.json_voltpatches.JSONArray) TableFiles(org.voltdb.sysprocs.saverestore.SnapshotUtil.TableFiles) JSONException(org.json_voltpatches.JSONException) IOException(java.io.IOException) TreeMap(java.util.TreeMap) JSONObject(org.json_voltpatches.JSONObject) InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) File(java.io.File) HashSet(java.util.HashSet)

Example 30 with InMemoryJarfile

use of org.voltdb.utils.InMemoryJarfile in project voltdb by VoltDB.

the class RealVoltDB method outputSchema.

private int outputSchema(Configuration config) {
    if ((new File(config.m_getOutput)).exists() && !config.m_forceGetCreate) {
        consoleLog.fatal("Failed to save schema file, file already exists: " + config.m_getOutput);
        return -1;
    }
    try {
        InMemoryJarfile catalogJar = CatalogUtil.loadInMemoryJarFile(MiscUtils.fileToBytes(new File(config.m_pathToCatalog)));
        String ddl = CatalogUtil.getAutoGenDDLFromJar(catalogJar);
        try (FileOutputStream fos = new FileOutputStream(config.m_getOutput.trim())) {
            fos.write(ddl.getBytes());
        } catch (IOException e) {
            consoleLog.fatal("Failed to write schema to " + config.m_getOutput + " : " + e.getMessage());
            return -1;
        }
        consoleLog.info("Schema saved in " + config.m_getOutput.trim());
    } catch (IOException e) {
        consoleLog.fatal("Failed to load the catalog jar from " + config.m_pathToCatalog + " : " + e.getMessage());
        return -1;
    }
    return 0;
}
Also used : InMemoryJarfile(org.voltdb.utils.InMemoryJarfile) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) VoltFile(org.voltdb.utils.VoltFile) File(java.io.File)

Aggregations

InMemoryJarfile (org.voltdb.utils.InMemoryJarfile)52 VoltCompiler (org.voltdb.compiler.VoltCompiler)26 File (java.io.File)20 ProcCallException (org.voltdb.client.ProcCallException)19 ClientResponse (org.voltdb.client.ClientResponse)18 Test (org.junit.Test)15 Configuration (org.voltdb.VoltDB.Configuration)15 IOException (java.io.IOException)14 VoltProjectBuilder (org.voltdb.compiler.VoltProjectBuilder)12 VoltDB (org.voltdb.VoltDB)9 Catalog (org.voltdb.catalog.Catalog)6 VoltTable (org.voltdb.VoltTable)5 VoltFile (org.voltdb.utils.VoltFile)5 ArrayList (java.util.ArrayList)4 JSONObject (org.json_voltpatches.JSONObject)3 CatalogContext (org.voltdb.CatalogContext)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 JAXBException (javax.xml.bind.JAXBException)2