Package org.voltdb.regressionsuites

Source Code of org.voltdb.regressionsuites.TestTPCCLogicalRecovery

/* This file is part of VoltDB.
* Copyright (C) 2008-2010 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package org.voltdb.regressionsuites;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;

import junit.framework.Test;

import org.voltdb.BackendTarget;
import org.voltdb.CatalogContext;
import org.voltdb.DefaultSnapshotDataTarget;
import org.voltdb.VoltTable;
import org.voltdb.benchmark.tpcc.TPCCClient;
import org.voltdb.benchmark.tpcc.TPCCLoader;
import org.voltdb.benchmark.tpcc.TPCCProjectBuilder;
import org.voltdb.catalog.CatalogMap;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Site;
import org.voltdb.client.Client;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.NoConnectionsException;
import org.voltdb.client.ProcCallException;
import org.voltdb.utils.SnapshotVerifier;

import edu.brown.hstore.HStoreConstants;
import edu.brown.hstore.Hstoreservice.Status;
import edu.brown.hstore.cmdlog.CommandLogReader;
import edu.brown.hstore.cmdlog.CommandLogWriter;
import edu.brown.hstore.cmdlog.LogEntry;

/**
* Test logical recovery
*/
public class TestTPCCLogicalRecovery extends RegressionSuite {

    private static final String TMPDIR = "./obj/snapshot";
    private static final String CMDLOGDIR = "./obj/cmdlog";

    private static final String TESTNONCE = "testnonce";
    private static final int ALLOWEXPORT = 0;

    private static int NUM_SITES = -1;
    private static int NUM_PARTITIONS = -1;

    // TPCC
    private static final String PREFIX = "tpcc";
    private static int NUM_TRANSACTIONS = 500;
    private static final String projectJAR = "logical_" + PREFIX + ".jar";

    public TestTPCCLogicalRecovery(String name) {
        super(name);
    }

    @Override
    public void setUp() {
        deleteTestFiles();
        deleteCommandLogDir();
        super.setUp();
        DefaultSnapshotDataTarget.m_simulateFullDiskWritingChunk = false;
        DefaultSnapshotDataTarget.m_simulateFullDiskWritingHeader = false;
        org.voltdb.sysprocs.SnapshotRegistry.clear();
    }

    @Override
    public void tearDown() {
        try {
            deleteTestFiles();
            deleteCommandLogDir();
            super.tearDown();
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }   

    private void deleteTestFiles() {
        FilenameFilter cleaner = new FilenameFilter() {
            public boolean accept(File dir, String file) {
                return file.startsWith(TESTNONCE) || file.endsWith(".vpt") || file.endsWith(".digest") || file.endsWith(".tsv") || file.endsWith(".csv");
            }
        };

        File tmp_dir = new File(TMPDIR);
        File[] tmp_files = tmp_dir.listFiles(cleaner);
        for (File tmp_file : tmp_files) {
            tmp_file.delete();
        }

    }

    private static synchronized void deleteCommandLogDir() {
        try {
            File cmdlogDir = new File(CMDLOGDIR);

            if (cmdlogDir.exists()) {
                File[] log_files = cmdlogDir.listFiles();
                for (File log_file : log_files) {
                    log_file.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static synchronized void setUpSnapshotDir() {
        try {
            File snapshotDir = new File(TMPDIR);

            if (!snapshotDir.exists()) {
                boolean result = snapshotDir.mkdir();
                if (result) {
                    System.out.println("Created snapshot directory.");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private VoltTable[] saveTables(Client client) {
        VoltTable[] results = null;
        try {
            results = client.callProcedure("@SnapshotSave", TMPDIR, TESTNONCE, (byte) 1).getResults();
        } catch (Exception ex) {
            ex.printStackTrace();
            fail("SnapshotSave exception: " + ex.getMessage());
        }
        return results;
    }

    private void validateSnapshot(boolean expectSuccess) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        PrintStream original = System.out;
        try {
            System.setOut(ps);
            String args[] = new String[] { TESTNONCE, "--dir", TMPDIR };
            SnapshotVerifier.main(args);
            ps.flush();
            String reportString = baos.toString("UTF-8");

            // System.err.println("Validate Snapshot :"+reportString);

            if (expectSuccess) {
                assertTrue(reportString.startsWith("Snapshot valid\n"));
                System.err.println("Validate Snapshot :" + "Snapshot valid");
            } else {
                assertTrue(reportString.startsWith("Snapshot corrupted\n"));
                System.err.println("Validate Snapshot :" + "Snapshot corrupted");
            }
        } catch (UnsupportedEncodingException e) {
        } finally {
            System.setOut(original);
        }
    }

    public void initializeTPCCDatabase(final CatalogContext catalogContext, final Client client, boolean scaleItems) throws Exception {
        String args[] = {
            "NOCONNECTIONS=true",
            "BENCHMARK.WAREHOUSE_PER_PARTITION=true",
            "BENCHMARK.NUM_LOADTHREADS=4",
            "BENCHMARK.SCALE_ITEMS="+scaleItems,
        };
        TPCCLoader loader = new TPCCLoader(args) {
            {
                this.setCatalogContext(catalogContext);
                this.setClientHandle(client);
            }
            @Override
            public CatalogContext getCatalogContext() {
                return (catalogContext);
            }
        };
        loader.load();
    }
   
   
    public void testTPCC() throws IOException, InterruptedException, ProcCallException {

        System.out.println("Starting testTPCC - Logical Recovery");               

        deleteTestFiles();
        setUpSnapshotDir();

        VoltTable results[] = null;
        Client client = this.getClient();
        CatalogContext cc = this.getCatalogContext();      
       
        // Load database
        try {
            initializeTPCCDatabase(cc, client, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Take Snapshot
        results = null;
        results = saveTables(client);

        validateSnapshot(true);
        final String MOCK_ARGS[] = { "HOST=localhost", "NUMCLIENTS=1",
                // XXX HACK to find catalog jar
                "CATALOG=" + "./obj/release/testobjects/" + projectJAR, "" };

        MOCK_ARGS[MOCK_ARGS.length - 1] = HStoreConstants.BENCHMARK_PARAM_PREFIX;

        TPCCClient tpccClient = new TPCCClient(MOCK_ARGS);

        // Run transactions
        long k_itr = 0;
        long numTransactions = NUM_TRANSACTIONS;
        long period = numTransactions / 10;

        for (k_itr = 0; k_itr < numTransactions; k_itr++) {
            boolean response = tpccClient.runOnce();
            assertEquals(response, true);

            if (k_itr % period == 0)
                System.out.println(String.format("Transactions Processed: %6d / %d", k_itr, numTransactions));
        }
       
        // Statistics        
        results = client.callProcedure("@Statistics", "table", 0).getResults();
        System.out.println(results[0]);

        VoltTable[] results_tmp = null;
        results_tmp = client.callProcedure("@Statistics", "table", 0).getResults();

        System.out.println("@Statistics before restart :");
        System.out.println(results_tmp[0]);
               
        // Kill and restart all the execution sites.
        m_config.shutDown();
        m_config.startUp();
        client = getClient();

        Calendar calendar;
        long t1,t2;

        calendar = Calendar.getInstance();                   
        t1 = calendar.getTimeInMillis();
       
        // LOGICAL : SNAPSHOT + CMD LOG
        try {
            results = client.callProcedure("@SnapshotRestore", TMPDIR, TESTNONCE, ALLOWEXPORT).getResults();

            System.out.println(results[0]);
            while (results[0].advanceRow()) {
                if (results[0].getString("RESULT").equals("FAILURE")) {
                    fail(results[0].getString("ERR_MSG"));
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            fail("SnapshotRestore exception: " + ex.getMessage());
        }       
       
        validateSnapshot(true);
       
        System.out.println("@Statistics after LOGICAL snapshot restore:");
        results = client.callProcedure("@Statistics", "table", 0).getResults();
        System.out.println(results[0]);
               
        //File logDir = new File("/mnt/pmfs" + File.separator + "cmdlog");                              
        File logDir = new File("./obj" + File.separator + "cmdlog");                              
       
        // Parse WAL logs for all sites
        CatalogMap<Site> sites = cc.sites;

        for(Site site : sites){
            String siteName = site.getName().toLowerCase();
            siteName = "h0" + siteName;           
            System.err.println("Site Prefix : "+siteName);
           
            parseAndApplyCommandLog(logDir, siteName);           
        }

        calendar = Calendar.getInstance();                   
        t2 = calendar.getTimeInMillis();

        System.err.println("Recovery Latency :" + (t2-t1)+ " ms");
       
        // checkYCSBTable(client, NUM_TUPLES);
    }
   
    // COMMAND LOG       
    File scanForLatestLogFile(File logDir, String prefix){
        System.err.println("Scanning logDir :" + logDir.getAbsolutePath());          

        final String logPrefix = prefix;
        FilenameFilter cleaner = new FilenameFilter() {
            public boolean accept(File dir, String file) {
                return  file.startsWith(logPrefix) && file.endsWith(CommandLogWriter.LOG_OUTPUT_EXT);
            }
        };

        File[] logFiles = logDir.listFiles(cleaner);
        File latestFile = null, prevFile = null;       
        long maxTimeStamp = Long.MIN_VALUE;
       
        for (File logFile : logFiles) {
            String name = logFile.getName();
            String delims = "_|\\.";
            String[] tokens = name.split(delims);

            //System.err.println("Tokens :"+Arrays.toString(tokens));

            if(tokens.length <= 1)
                continue;
           
            long fileTimestamp = Long.parseLong(tokens[1]) ;
            if(fileTimestamp > maxTimeStamp){
                maxTimeStamp = fileTimestamp;
                prevFile = latestFile;
                latestFile = logFile;        
            }
        }      

        if(prevFile != null){
            System.err.println("Using logfile :" + prevFile.getAbsolutePath());          
        }

        if(latestFile != null){
            System.err.println("Found latest logfile :" + latestFile.getAbsolutePath());          
        }
       
        return prevFile;
    }
   
    void parseAndApplyCommandLog(File logDir, String hostPrefix) throws NoConnectionsException, IOException, ProcCallException {

        if(logDir == null){
            System.err.println("logDir null ");          
            return;
        }

        File latestFile = scanForLatestLogFile(logDir, hostPrefix);
       
        if(latestFile == null){
            System.err.println("Command log not found :" + logDir.getAbsolutePath());          
            return;
        }
       
        System.out.println("parseCommandLog :" + latestFile.getAbsolutePath());

        // Now read in the file back in and check to see that we have two
        // entries that have our expected information
        CommandLogReader reader = null;

        try {
            reader = new CommandLogReader(latestFile.getAbsolutePath());
        } catch (Exception e) {
            System.err.println("Command log not found :" + latestFile.getAbsolutePath());
            return;
        }

        int ctr = 0;
        Iterator<LogEntry> log_itr = reader.iterator();
        ClientResponse cresponse = null;
        Client client = this.getClient();
        CatalogContext cc = this.getCatalogContext();
        VoltTable results[] = null;

        while (log_itr.hasNext()) {
            LogEntry entry = log_itr.next();

            assert(entry != null);
            //System.err.println("REDO :: TXN ID :" + entry.getTransactionId().longValue());
            //System.err.println("REDO :: PROC ID :" + entry.getProcedureId());

            Object[] entryParams = entry.getProcedureParams().toArray();
       
            String procName = cc.getProcedureById(entry.getProcedureId()).fullName();
            Procedure catalog_proc = cc.procedures.getIgnoreCase(procName);

            if(catalog_proc.getReadonly() == false){
                // System.out.println("Invoking procedure ::" + procName);

                cresponse = client.callProcedure(procName, entryParams);
                assertEquals(cresponse.getStatus(), Status.OK);
               
                // results = cresponse.getResults();
                // assertEquals(results.length, 1);
            }

            ctr++;
        }

        System.out.println("################################# WAL LOG entries :" + ctr);
    }

    /**
     * Build a list of the tests to be run. Use the regression suite helpers to
     * allow multiple back ends. JUnit magic that uses the regression suite
     * helper classes.
     */
    static public Test suite() {
        MultiConfigSuiteBuilder builder = new MultiConfigSuiteBuilder(TestTPCCLogicalRecovery.class);

        // COMMAND LOG
        builder.setGlobalConfParameter("site.commandlog_enable", true);
        builder.setGlobalConfParameter("site.commandlog_timeout", 1000);    
        builder.setGlobalConfParameter("site.commandlog_dir", "./obj/cmdlog");    

        builder.setGlobalConfParameter("site.anticache_enable", false);    

        TPCCProjectBuilder project = new TPCCProjectBuilder();

        project.addAllDefaults();

        VoltServerConfig m_config = null;
        boolean success = false;

        setUpSnapshotDir();
       
        // CONFIG #1: 2 Local Site with 4 Partitions running on JNI backend       
        /*
        NUM_SITES = 2;
        NUM_PARTITIONS = 2;
        m_config = new LocalCluster(projectJAR, NUM_SITES, NUM_PARTITIONS, 1, BackendTarget.NATIVE_EE_JNI);
        success = m_config.compile(project);
        assert (success);
        builder.addServerConfig(m_config);
        */
                  
       
        // CONFIG #2: 1 Local Site with 1 Partitions running on JNI backend   
        NUM_SITES = 1;
        NUM_PARTITIONS = 1;
        m_config = new LocalSingleProcessServer(projectJAR, NUM_PARTITIONS, BackendTarget.NATIVE_EE_JNI);
        success = m_config.compile(project);
        assert (success);
        builder.addServerConfig(m_config);    
       
        return builder;
    }
}
TOP

Related Classes of org.voltdb.regressionsuites.TestTPCCLogicalRecovery

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.