Package org.fcrepo.client.test

Source Code of org.fcrepo.client.test.PerformanceTests

/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.client.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.PrintStream;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.fcrepo.client.FedoraClient;

import org.fcrepo.common.Constants;
import org.fcrepo.common.http.PreemptiveAuth;

import org.fcrepo.server.access.FedoraAPIAMTOM;
import org.fcrepo.server.management.FedoraAPIMMTOM;
import org.fcrepo.server.utilities.TypeUtility;


/**
* Performs test to determine the time necessary to execute
* various repository activities.
*
* @author Bill Branan
*/
public class PerformanceTests
        implements Constants {

    private FedoraAPIMMTOM apim;
    private FedoraAPIAMTOM apia;

    private static int iterations = 10;
    private static int threads = 10;

    private static final String pid = "demo:performance";

    private static String DEMO_FOXML_TEXT;

    private static String datastream =
            "http://local.fedora.server/fedora-demo/simple-image-demo/coliseum-thumb.jpg";

    private String host;
    private String port;
    private String context;
    private String username;
    private String password;


    private String[] PIDS;
    private byte[][] FOXML;

    static {
        // Test FOXML object
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        sb.append("<foxml:digitalObject PID=\"" + pid +
                  "\" VERSION=\"1.1\" xmlns:foxml=\"info:fedora/fedora-system:def/foxml#\"");
        sb.append(
                "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"info:fedora/fedora-system:def/foxml# http://www.fedora.info/definitions/1/0/foxml1-1.xsd\">");
        sb.append("  <foxml:objectProperties>");
        sb.append("    <foxml:property NAME=\"info:fedora/fedora-system:def/model#state\" VALUE=\"Active\"/>");
        sb.append("    <foxml:property NAME=\"info:fedora/fedora-system:def/model#label\" VALUE=\"Test Object\"/>");
        sb.append("    <foxml:property NAME=\"info:fedora/fedora-system:def/model#ownerId\" VALUE=\"fedoraAdmin\"/>");
        sb.append(
                "    <foxml:property NAME=\"info:fedora/fedora-system:def/model#createdDate\" VALUE=\"2008-07-09T19:28:04.890Z\"/>");
        sb.append(
                "    <foxml:property NAME=\"info:fedora/fedora-system:def/view#lastModifiedDate\" VALUE=\"2008-07-09T19:32:31.750Z\"/>");
        sb.append("  </foxml:objectProperties>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"X\" ID=\"AUDIT\" STATE=\"A\" VERSIONABLE=\"false\">");
        sb.append("    <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:04.890Z\"");
        sb.append(
                "      FORMAT_URI=\"info:fedora/fedora-system:format/xml.fedora.audit\" ID=\"AUDIT.0\" LABEL=\"Fedora Object Audit Trail\" MIMETYPE=\"text/xml\">");
        sb.append("      <foxml:xmlContent>");
        sb.append("        <audit:auditTrail xmlns:audit=\"info:fedora/fedora-system:def/audit#\">");
        sb.append("          <audit:record ID=\"AUDREC1\">");
        sb.append("            <audit:process type=\"Fedora API-M\"/>");
        sb.append("            <audit:action>ingest</audit:action>");
        sb.append("            <audit:componentID/>");
        sb.append("            <audit:responsibility>fedoraAdmin</audit:responsibility>");
        sb.append("            <audit:date>2008-07-09T19:28:04.890Z</audit:date>");
        sb.append("            <audit:justification>Created New Object</audit:justification>");
        sb.append("          </audit:record>");
        sb.append("        </audit:auditTrail>");
        sb.append("      </foxml:xmlContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"X\" ID=\"DC\" STATE=\"A\" VERSIONABLE=\"true\">");
        sb.append(
                "    <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:04.890Z\" ID=\"DC1.0\" LABEL=\"Dublin Core Metadata\"");
        sb.append("      MIMETYPE=\"text/xml\" SIZE=\"226\">");
        sb.append("      <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
        sb.append("      <foxml:xmlContent>");
        sb.append(
                "        <oai_dc:dc xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:oai_dc=\"http://www.openarchives.org/OAI/2.0/oai_dc/\">");
        sb.append("          <dc:title>Test Object</dc:title>");
        sb.append("          <dc:identifier>" + pid + "</dc:identifier>");
        sb.append("        </oai_dc:dc>");
        sb.append("      </foxml:xmlContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"X\" ID=\"XDS1\" STATE=\"A\" VERSIONABLE=\"true\">");
        sb.append(
                "    <foxml:datastreamVersion CREATED=\"2008-07-09T19:28:58.125Z\" ID=\"XDS1.0\" LABEL=\"XML Datastream 1\" MIMETYPE=\"text/xml\" SIZE=\"41\">");
        sb.append("      <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
        sb.append("      <foxml:xmlContent>");
        sb.append("        <xml>Datastream Content</xml>");
        sb.append("      </foxml:xmlContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"X\" ID=\"XDS2\" STATE=\"A\" VERSIONABLE=\"true\">");
        sb.append(
                "    <foxml:datastreamVersion CREATED=\"2008-07-09T19:29:33.609Z\" ID=\"XDS2.0\" LABEL=\"XML Datastream 2\" MIMETYPE=\"text/xml\" SIZE=\"41\">");
        sb.append("      <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
        sb.append("      <foxml:xmlContent>");
        sb.append("        <xml>Datastream Content</xml>");
        sb.append("      </foxml:xmlContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"M\" ID=\"MDS1\" STATE=\"A\" VERSIONABLE=\"true\">");
        sb.append(
                "    <foxml:datastreamVersion CREATED=\"2008-07-09T19:31:57.593Z\" ID=\"MDS1.0\" LABEL=\"Managed Datastream 1\" MIMETYPE=\"text/xml\" SIZE=\"0\">");
        sb.append("      <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
        sb.append("      <foxml:binaryContent>");
        sb.append("              PHhtbD5EYXRhc3RyZWFtIENvbnRlbnQ8L3htbD4=");
        sb.append("            </foxml:binaryContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("  <foxml:datastream CONTROL_GROUP=\"M\" ID=\"MDS2\" STATE=\"A\" VERSIONABLE=\"true\">");
        sb.append(
                "    <foxml:datastreamVersion CREATED=\"2008-07-09T19:32:31.750Z\" ID=\"MDS2.0\" LABEL=\"Managed Datastream 2\" MIMETYPE=\"text/xml\" SIZE=\"0\">");
        sb.append("      <foxml:contentDigest DIGEST=\"none\" TYPE=\"DISABLED\"/>");
        sb.append("      <foxml:binaryContent>");
        sb.append("              PHhtbD5EYXRhc3RyZWFtIENvbnRlbnQ8L3htbD4=");
        sb.append("            </foxml:binaryContent>");
        sb.append("    </foxml:datastreamVersion>");
        sb.append("  </foxml:datastream>");
        sb.append("</foxml:digitalObject>");

        DEMO_FOXML_TEXT = sb.toString();
    }

    public void init(String host, String port, String context, String username, String password) throws Exception {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        this.context = context;

        String baseURL = "http://" + host + ":" + port + "/" + context;
        FedoraClient fedoraClient = new FedoraClient(baseURL, username, password);
        apim = fedoraClient.getAPIMMTOM();
        apia = fedoraClient.getAPIAMTOM();
        fedoraClient.shutdown();

        PIDS = apim.getNextPID(new BigInteger(Integer.valueOf(iterations).toString()), "demo").toArray(new String[]{});
        FOXML = new byte[iterations][];
        for (int i = 0; i < iterations; i++) {
            FOXML[i] = DEMO_FOXML_TEXT.replaceAll(pid, PIDS[i]).getBytes("UTF-8");
        }
    }

    private void runIngest(byte[] foxml) throws Exception {
        apim.ingest(TypeUtility.convertBytesToDataHandler(foxml), FOXML1_1.uri, "Ingest Test");
    }

    private void runAddDatastream(String pid, String dsId) throws Exception {
        apim.addDatastream(pid,
                           dsId,
                           null,
                           "New Datastream",
                           true,
                           "text/xml",
                           null,
                           datastream,
                           "M",
                           "A",
                           null,
                           null,
                           "Adding Test Datastream");
    }

    private void runModifyDatastreamByRef(String pid) throws Exception {
        apim.modifyDatastreamByReference(pid,
                                         "MDS1",
                                         null,
                                         "New Label",
                                         "text/xml",
                                         null,
                                         datastream,
                                         null,
                                         null,
                                         "Modify Datastream Test",
                                         false);
    }

    private void runModifyDatastreamByValue(String pid) throws Exception {
        String dsContent = "<xml>Updated Content</xml>";
        apim.modifyDatastreamByValue(pid,
                                     "XDS1",
                                     null,
                                     "New Label",
                                     "text/xml",
                                     null,
                                     TypeUtility.convertBytesToDataHandler(dsContent.getBytes()),
                                     null,
                                     null,
                                     "Modify Datastream Test",
                                     false);
    }

    private void runPurgeDatastream(String pid, String dsId) throws Exception {
        apim.purgeDatastream(pid, dsId, null, null, "Purge Datastream Test", false);
    }

    private void runPurgeObject(String pid) throws Exception {
        apim.purgeObject(pid, "Removing Test Object", false);
    }

    private void runGetDatastream(String pid) throws Exception {
        apia.getDatastreamDissemination(pid, "MDS1", null);
    }

    private void runGetDatastreamRest(String pid) throws Exception {
        HttpGet httpMethod = getHttpMethod(pid);
        HttpClient client = getHttpClient();
        HttpResponse response =
                client.execute(httpMethod);
        if (response.getEntity() != null) {
            EntityUtils.consumeQuietly(response.getEntity());
        }
        httpMethod.releaseConnection();
    }

    /**
     * @return average run time for a single operation
     */
    public long runIngestTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        for (int i = 0; i < iterations; i++) {
            startTime = System.currentTimeMillis();
            runIngest(FOXML[0]);
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
            runPurgeObject(PIDS[0]);
        }
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return average run time for a single operation
     */
    public long runAddDatastreamTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        for (int i = 0; i < iterations; i++) {
            startTime = System.currentTimeMillis();
            runAddDatastream(PIDS[0], "MDS3");
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
            runPurgeDatastream(PIDS[0], "MDS3");
        }
        runPurgeObject(PIDS[0]);
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return average run time for a single operation
     */
    public long runModifyDatastreamByRefTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        for (int i = 0; i < iterations; i++) {
            startTime = System.currentTimeMillis();
            runModifyDatastreamByRef(PIDS[0]);
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
        }
        runPurgeObject(PIDS[0]);
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return average run time for a single operation
     */
    public long runModifyDatastreamByValueTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        for (int i = 0; i < iterations; i++) {
            startTime = System.currentTimeMillis();
            runModifyDatastreamByValue(PIDS[0]);
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
        }
        runPurgeObject(PIDS[0]);
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return average run time for a single operation
     */
    public long runPurgeDatastreamTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        for (int i = 0; i < iterations; i++) {
            runAddDatastream(PIDS[0], "MDS3");
            startTime = System.currentTimeMillis();
            runPurgeDatastream(PIDS[0], "MDS3");
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
        }
        runPurgeObject(PIDS[0]);
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return average run time for a single operation
     */
    public long runPurgeObjectTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        for (int i = 0; i < iterations; i++) {
            runIngest(FOXML[0]);
            startTime = System.currentTimeMillis();
            runPurgeObject(PIDS[0]);
            stopTime = System.currentTimeMillis();
            totalTime += (stopTime - startTime);
        }
        long average = totalTime / iterations;
        return average;
    }

    /**
     * @return total time to run all iterations
     */
    public long runGetDatastreamTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runGetDatastream(PIDS[0]);
        }
        stopTime = System.currentTimeMillis();
        totalTime = (stopTime - startTime);
        runPurgeObject(PIDS[0]);

        return totalTime;
    }

    /**
     * @return total time to run all iterations
     */
    public long runGetDatastreamRestTest() throws Exception {
        long totalTime = 0;
        long startTime = 0;
        long stopTime = 0;
        runIngest(FOXML[0]);
        HttpGet httpMethod = getHttpMethod(PIDS[0]);
        HttpClient client = getHttpClient();
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            HttpResponse response =
                client.execute(httpMethod);
            EntityUtils.consumeQuietly(response.getEntity());
        }
        httpMethod.releaseConnection();
        stopTime = System.currentTimeMillis();
        totalTime = (stopTime - startTime);
        runPurgeObject(PIDS[0]);

        return totalTime;
    }

    private HttpGet getHttpMethod(String pid) {
        String url = "http://" + host + ":" + port + "/" + context + "/get/" + pid + "/" + "MDS1";
        HttpGet httpMethod = new HttpGet(url);
        httpMethod.setHeader(HttpHeaders.CONNECTION, "Keep-Alive");
        return httpMethod;
    }

    private HttpClient getHttpClient() {
        DefaultHttpClient client = new PreemptiveAuth();
        client.getCredentialsProvider().setCredentials(
                new AuthScope(host, Integer.valueOf(port), "realm"),
                new UsernamePasswordCredentials(username, password));
        return client;
    }

    /**
     * @return total time to run all iterations
     *         {ingest, addDatastream, modifyDatastreamByReference,
     *         modifyDatastreamByValue, purgeDatastream, purgeObject}
     */
    public long[] runThroughputTests() throws Exception {
        long ingestTime = 0;
        long addDsTime = 0;
        long modifyRefTime = 0;
        long modifyValTime = 0;
        long purgeDsTime = 0;
        long purgeObjectTime = 0;
        long startTime = 0;
        long stopTime = 0;

        // Ingest
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runIngest(FOXML[i]);
        }
        stopTime = System.currentTimeMillis();
        ingestTime = (stopTime - startTime);

        // Add Datastream
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runAddDatastream(PIDS[i], "MDS3");
        }
        stopTime = System.currentTimeMillis();
        addDsTime = (stopTime - startTime);

        // Modify Datastream By Reference
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runModifyDatastreamByRef(PIDS[i]);
        }
        stopTime = System.currentTimeMillis();
        modifyRefTime = (stopTime - startTime);

        // Modify Datastream By Value
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runModifyDatastreamByValue(PIDS[i]);
        }
        stopTime = System.currentTimeMillis();
        modifyValTime = (stopTime - startTime);

        // Purge Datastream
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runPurgeDatastream(PIDS[i], "MDS1");
        }
        stopTime = System.currentTimeMillis();
        purgeDsTime = (stopTime - startTime);

        // Purge Object
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            runPurgeObject(PIDS[i]);
        }
        stopTime = System.currentTimeMillis();
        purgeObjectTime = (stopTime - startTime);

        // Get Datastream and Get Datastream REST results
        // do not change from round-trip tests

        long[] totals = {ingestTime,
                         addDsTime,
                         modifyRefTime,
                         modifyValTime,
                         purgeDsTime,
                         purgeObjectTime};
        return totals;
    }

    /**
     * @return total time to run all iterations with threading
     *         {ingest, addDatastream, modifyDatastreamByReference,
     *         modifyDatastreamByValue, purgeDatastream, purgeObject,
     *         getDatastream, getDatastreamREST}
     */
    public long[] runThreadedThroughputTests() throws Exception {
        long ingestTime = 0;
        long addDsTime = 0;
        long modifyRefTime = 0;
        long modifyValTime = 0;
        long purgeDsTime = 0;
        long purgeObjectTime = 0;
        long getDatastreamTime = 0;
        long getDatastreamRestTime = 0;
        long startTime = 0;
        long stopTime = 0;

        ExecutorService threadPool = Executors.newFixedThreadPool(threads);

        // Ingest
        ArrayList<Callable<Boolean>> ingestRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            ingestRunnerList.add(new MethodRunner(MethodType.INGEST, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(ingestRunnerList);
        stopTime = System.currentTimeMillis();
        ingestTime = (stopTime - startTime);

        // Add Datastream
        ArrayList<Callable<Boolean>> addDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            addDatastreamRunnerList.add(new MethodRunner(MethodType.ADD_DATASTREAM, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(addDatastreamRunnerList);
        stopTime = System.currentTimeMillis();
        addDsTime = (stopTime - startTime);

        // Modify Datastream By Reference
        ArrayList<Callable<Boolean>> modDatastreamRefRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            modDatastreamRefRunnerList.add(new MethodRunner(MethodType.MODIFY_DATASTREAM_REF, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(modDatastreamRefRunnerList);
        stopTime = System.currentTimeMillis();
        modifyRefTime = (stopTime - startTime);

        // Modify Datastream By Value
        ArrayList<Callable<Boolean>> modDatastreamValRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            modDatastreamValRunnerList.add(new MethodRunner(MethodType.MODIFY_DATASTREAM_VAL, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(modDatastreamValRunnerList);
        stopTime = System.currentTimeMillis();
        modifyValTime = (stopTime - startTime);

        // Purge Datastream
        ArrayList<Callable<Boolean>> purgeDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            purgeDatastreamRunnerList.add(new MethodRunner(MethodType.PURGE_DATASTREAM, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(purgeDatastreamRunnerList);
        stopTime = System.currentTimeMillis();
        purgeDsTime = (stopTime - startTime);

        // Purge Object
        ArrayList<Callable<Boolean>> purgeObjectRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            purgeObjectRunnerList.add(new MethodRunner(MethodType.PURGE_OBJECT, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(purgeObjectRunnerList);
        stopTime = System.currentTimeMillis();
        purgeObjectTime = (stopTime - startTime);

        // Get Datastream
        ArrayList<Callable<Boolean>> getDatastreamRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            getDatastreamRunnerList.add(new MethodRunner(MethodType.GET_DATASTREAM, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(getDatastreamRunnerList);
        stopTime = System.currentTimeMillis();
        getDatastreamTime = (stopTime - startTime);

        // Get Datastream REST
        ArrayList<Callable<Boolean>> getDatastreamRestRunnerList = new ArrayList<Callable<Boolean>>();
        for (int i = 0; i < iterations; i++) {
            getDatastreamRestRunnerList.add(new MethodRunner(MethodType.GET_DATASTREAM_REST, i));
        }
        startTime = System.currentTimeMillis();
        threadPool.invokeAll(getDatastreamRestRunnerList);
        stopTime = System.currentTimeMillis();
        getDatastreamRestTime = (stopTime - startTime);

        long[] totals = {ingestTime,
                         addDsTime,
                         modifyRefTime,
                         modifyValTime,
                         purgeDsTime,
                         purgeObjectTime,
                         getDatastreamTime,
                         getDatastreamRestTime};
        return totals;
    }

    private enum MethodType {
        INGEST,
        ADD_DATASTREAM,
        MODIFY_DATASTREAM_REF,
        MODIFY_DATASTREAM_VAL,
        PURGE_DATASTREAM,
        PURGE_OBJECT,
        GET_DATASTREAM,
        GET_DATASTREAM_REST;
    }

    /*
     * Runnable class to use within threads. Executes a
     * Fedora method based on the MethodType defined.
     */

    private class MethodRunner implements Callable<Boolean> {

        MethodType methodType;
        int index;

        public MethodRunner(MethodType methodType, int index) {
            this.methodType = methodType;
            this.index = index;
        }

        @Override
        public Boolean call() throws Exception {
            if (methodType.equals(MethodType.INGEST)) {
                runIngest(FOXML[index]);
            } else if (methodType.equals(MethodType.ADD_DATASTREAM)) {
                runAddDatastream(PIDS[index], "MDS3");
            } else if (methodType.equals(MethodType.MODIFY_DATASTREAM_REF)) {
                runModifyDatastreamByRef(PIDS[index]);
            } else if (methodType.equals(MethodType.MODIFY_DATASTREAM_VAL)) {
                runModifyDatastreamByValue(PIDS[index]);
            } else if (methodType.equals(MethodType.PURGE_DATASTREAM)) {
                runPurgeDatastream(PIDS[index], "MDS1");
            } else if (methodType.equals(MethodType.PURGE_OBJECT)) {
                runPurgeObject(PIDS[index]);
            } else if (methodType.equals(MethodType.GET_DATASTREAM)) {
                runGetDatastream(PIDS[index]);
            } else if (methodType.equals(MethodType.GET_DATASTREAM_REST)) {
                runGetDatastreamRest(PIDS[index]);
            }
            return new Boolean(true);
        }
    }

    private static double round(double d) {
        int decimalPlace = 5;
        BigDecimal bd = new BigDecimal(Double.toString(d));
        bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
        return bd.doubleValue();
    }

    private static void usage() {
        System.out.println("Runs a set of performance tests over a running Fedora repository.");
        System.out.println("USAGE: ant performance-tests " +
                           "-Dhost=HOST " +
                           "-Dport=PORT " +
                           "-Dusername=USERNAME " +
                           "-Dpassword=PASSWORD " +
                           "-Diterations=NUM-ITERATIONS " +
                           "-Dthreads=NUM-THREADS " +
                           "-Dfile=OUTPUT-FILE " +
                           "-Dname=TEST-NAME" +
                           "[-Dcontext=CONTEXT]");
        System.out.println("Where:");
        System.out.println("  HOST = Host on which Fedora server is running.");
        System.out.println("  PORT = Port on which the Fedora server APIs can be accessed.");
        System.out.println("  USERNAME = A fedora user with administrative privileges.");
        System.out.println("  PASSWORD = The fedora user's password.");
        System.out.println("  NUM-ITERATIONS = The number of times to perform each operation.");
        System.out.println("  NUM-THREADS = The number of threads to use in the thread pool");
        System.out.println("                when running threaded tests.");
        System.out.println("  OUTPUT-FILE = The file to which the test results will be written.");
        System.out.println("                If the file does not exist, it will be created, if the");
        System.out.println("                file does exist the new results will be appended.");
        System.out.println("  TEST-NAME   = A name for this test run.");
        System.out.println(
                "  CONTEXT     = The application server context Fedora is deployed in. This parameter is optional");
        System.out.println("Example:");
        System.out.println("ant performance-tests " +
                           "-Dhost=localhost " +
                           "-Dport=8080 " +
                           "-Dusername=fedoraAdmin " +
                           "-Dpassword=fedoraAdmin " +
                           "-Diterations=100 " +
                           "-Dthreads=10 " +
                           "-Dfile=C:\\temp\\performance_testing_output.txt " +
                           "-Dname=\"Test 1\"" +
                           "-Dcontext=my-fedora");
        System.exit(1);
    }

    public static void main(String[] args) throws Exception {

        if (args.length < 8 || args.length > 9) {
            usage();
        }

        String host = args[0];
        String port = args[1];
        String username = args[2];
        String password = args[3];
        String itr = args[4];
        String thrds = args[5];
        String output = args[6];
        String name = args[7];
        String context = Constants.FEDORA_DEFAULT_APP_CONTEXT;

        if (args.length == 9 && !args[8].equals("")) {
            context = args[8];
        }

        if (host == null || host.startsWith("$") ||
            port == null || port.startsWith("$") ||
            username == null || username.startsWith("$") ||
            password == null || password.startsWith("$") ||
            itr == null || itr.startsWith("$") ||
            thrds == null || thrds.startsWith("$") ||
            output == null || output.startsWith("$") ||
            name == null || name.startsWith("$")) {
            usage();
        }
        name = name.replaceAll(",", ";");
        iterations = Integer.parseInt(itr);
        threads = Integer.parseInt(thrds);

        boolean newFile = true;
        File outputFile = new File(output);

        File tempFile = null;
        BufferedReader reader = null;
        String line = "";
        if (outputFile.exists()) {
            newFile = false;

            // Create a copy of the file to read from
            tempFile = File.createTempFile("performance-test", "tmp");
            BufferedReader input = new BufferedReader(new FileReader(outputFile));
            PrintStream tempOut = new PrintStream(tempFile);

            while ((line = input.readLine()) != null) {
                tempOut.println(line);
            }
            input.close();
            tempOut.close();

            reader = new BufferedReader(new FileReader(tempFile));
        }
        PrintStream out = new PrintStream(outputFile);

        if (newFile) {
            out.println("--------------------------------------------------------------" +
                        " Performance Test Results " +
                        "--------------------------------------------------------------");
        }

        PerformanceTests tests = new PerformanceTests();
        tests.init(host, port, context, username, password);
        System.out.println("Running Ingest Round-Trip Test...");
        long ingestResults = tests.runIngestTest();
        System.out.println("Running AddDatastream Round-Trip Test...");
        long addDsResults = tests.runAddDatastreamTest();
        System.out.println("Running ModifyDatastreamByReference Round-Trip Test...");
        long modifyRefResults = tests.runModifyDatastreamByRefTest();
        System.out.println("Running ModifyDatastreamByValue Round-Trip Test...");
        long modifyValResults = tests.runModifyDatastreamByValueTest();
        System.out.println("Running PurgeDatastream Round-Trip Test...");
        long purgeDsResults = tests.runPurgeDatastreamTest();
        System.out.println("Running PurgeObject Round-Trip Test...");
        long purgeObjectResults = tests.runPurgeObjectTest();
        System.out.println("Running GetDatastream Round-Trip Test...");
        long getDatastreamResults = tests.runGetDatastreamTest();
        System.out.println("Running GetDatastreamREST Round-Trip Test...");
        long getDatastreamRestResults = tests.runGetDatastreamRestTest();
        System.out.println("Running Throughput Tests...");
        long[] tpResults = tests.runThroughputTests();
        System.out.println("Running Threaded Throughput Tests...");
        long[] tptResults = tests.runThreadedThroughputTests();

        if (newFile) {
            out.println(
                    "1. Test performing each operation in isolation. Time (in ms) is the average required to perform each operation.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        out.println(name + ", " +
                    ingestResults + ", " +
                    addDsResults + ", " +
                    modifyRefResults + ", " +
                    modifyValResults + ", " +
                    purgeDsResults + ", " +
                    purgeObjectResults + ", " +
                    getDatastreamResults / iterations + ", " +
                    getDatastreamRestResults / iterations);

        out.println();
        if (newFile) {
            out.println("2. Operations-Per-Second based on results listed in item 1.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        double ingestPerSecond = 1000 / (double) ingestResults;
        double addDsPerSecond = 1000 / (double) addDsResults;
        double modifyRefPerSecond = 1000 / (double) modifyRefResults;
        double modifyValPerSecond = 1000 / (double) modifyValResults;
        double purgeDsPerSecond = 1000 / (double) purgeDsResults;
        double purgeObjPerSecond = 1000 / (double) purgeObjectResults;
        double getDatastreamPerSecond = 1000 / ((double) getDatastreamResults / iterations);
        double getDatastreamRestPerSecond = 1000 / ((double) getDatastreamRestResults / iterations);
        out.println(name + ", " +
                    round(ingestPerSecond) + ", " +
                    round(addDsPerSecond) + ", " +
                    round(modifyRefPerSecond) + ", " +
                    round(modifyValPerSecond) + ", " +
                    round(purgeDsPerSecond) + ", " +
                    round(purgeObjPerSecond) + ", " +
                    round(getDatastreamPerSecond) + ", " +
                    round(getDatastreamRestPerSecond));

        out.println();
        if (newFile) {
            out.println(
                    "3. Test performing operations back-to-back. Time (in ms) is that required to perform all iterations.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        out.println(name + ", " +
                    tpResults[0] + ", " +
                    tpResults[1] + ", " +
                    tpResults[2] + ", " +
                    tpResults[3] + ", " +
                    tpResults[4] + ", " +
                    tpResults[5] + ", " +
                    getDatastreamResults + ", " +
                    getDatastreamRestResults);

        out.println();
        if (newFile) {
            out.println("4. Operations-Per-Second based on results listed in item 3.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        double ingestItPerSecond = (double) (iterations * 1000) / tpResults[0];
        double addDsItPerSecond = (double) (iterations * 1000) / tpResults[1];
        double modifyRefItPerSecond = (double) (iterations * 1000) / tpResults[2];
        double modifyValItPerSecond = (double) (iterations * 1000) / tpResults[3];
        double purgeDsItPerSecond = (double) (iterations * 1000) / tpResults[4];
        double purgeObjItPerSecond = (double) (iterations * 1000) / tpResults[5];
        double getDsItPerSecond = (double) (iterations * 1000) / getDatastreamResults;
        double getDsRestItPerSecond = (double) (iterations * 1000) / getDatastreamRestResults;
        out.println(name + ", " +
                    round(ingestItPerSecond) + ", " +
                    round(addDsItPerSecond) + ", " +
                    round(modifyRefItPerSecond) + ", " +
                    round(modifyValItPerSecond) + ", " +
                    round(purgeDsItPerSecond) + ", " +
                    round(purgeObjItPerSecond) + ", " +
                    round(getDsItPerSecond) + ", " +
                    round(getDsRestItPerSecond));

        out.println();
        if (newFile) {
            out.println(
                    "5. Test performing operations using a thread pool. Time (in ms) is that required to perform all iterations.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        out.println(name + ", " +
                    tptResults[0] + ", " +
                    tptResults[1] + ", " +
                    tptResults[2] + ", " +
                    tptResults[3] + ", " +
                    tptResults[4] + ", " +
                    tptResults[5] + ", " +
                    tptResults[6] + ", " +
                    tptResults[7]);

        out.println();
        if (newFile) {
            out.println("6. Operations-Per-Second based on results listed in item 5.");
            out.println(
                    "test name, ingest, addDatastream, modifyDatastreamByReference, modifyDatastreamByValue, purgeDatastream, purgeObject, getDatastream, getDatastreamREST");
        } else {
            line = reader.readLine();
            while (line != null && line.length() > 2) {
                out.println(line);
                line = reader.readLine();
            }
        }
        double thrdIngestItPerSecond = (double) (iterations * 1000) / tptResults[0];
        double thrdAddDsItPerSecond = (double) (iterations * 1000) / tptResults[1];
        double thrdModifyRefItPerSecond = (double) (iterations * 1000) / tptResults[2];
        double thrdModifyValItPerSecond = (double) (iterations * 1000) / tptResults[3];
        double thrdPurgeDsItPerSecond = (double) (iterations * 1000) / tptResults[4];
        double thrdPurgeObjItPerSecond = (double) (iterations * 1000) / tptResults[5];
        double thrdGetDsItPerSecond = (double) (iterations * 1000) / tptResults[6];
        double thrdGetDsRestItPerSecond = (double) (iterations * 1000) / tptResults[7];
        out.println(name + ", " +
                    round(thrdIngestItPerSecond) + ", " +
                    round(thrdAddDsItPerSecond) + ", " +
                    round(thrdModifyRefItPerSecond) + ", " +
                    round(thrdModifyValItPerSecond) + ", " +
                    round(thrdPurgeDsItPerSecond) + ", " +
                    round(thrdPurgeObjItPerSecond) + ", " +
                    round(thrdGetDsItPerSecond) + ", " +
                    round(thrdGetDsRestItPerSecond));

        if (!newFile) {
            reader.close();
            tempFile.delete();
        }
        out.close();

        System.out.println("Performance Tests Complete.");
    }

}
TOP

Related Classes of org.fcrepo.client.test.PerformanceTests

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.