com.sonatype.nexus.perftest.ClientSwarm.java Source code

Java tutorial

Introduction

Here is the source code for com.sonatype.nexus.perftest.ClientSwarm.java

Source

/*
 * Copyright (c) 2007-2013 Sonatype, Inc. All rights reserved.
 *
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
 * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
 */
package com.sonatype.nexus.perftest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

/**
 * Models a group of similar clients. The clients performs the same operation. Request rate is configured for the swarm.
 */
public class ClientSwarm {

    private final List<Thread> threads;

    private final Metric metric;

    public static interface ClientRequestInfo {
        String getSwarmName();

        int getClientId();

        int getRequestId();

        <T> void setContextValue(String key, T value);

        <T> T getContextValue(String key);
    }

    @JsonTypeInfo(use = Id.MINIMAL_CLASS, include = As.PROPERTY, property = "class")
    public static interface Operation {
        public void perform(ClientRequestInfo requestInfo) throws Exception;
    }

    private static class ClientThread extends Thread implements ClientRequestInfo {
        private final String swarmName;

        private final int clientId;

        private final Operation operation;

        private final RequestRate rate;

        private final Metric metric;

        private int requestId;

        private final HashMap<String, Object> context = new HashMap<>();

        public ClientThread(String swarmName, int clientId, Operation operation, Metric metric, RequestRate rate) {
            super(String.format("%s-%d", swarmName, clientId));
            this.swarmName = swarmName;
            this.clientId = clientId;
            this.operation = operation;
            this.metric = metric;
            this.rate = rate;
        }

        @Override
        public final void run() {
            while (true) {
                requestId++;
                try {
                    rate.delay();
                } catch (InterruptedException e) {
                    break;
                }

                Metric.Context context = metric.time();
                boolean success = false;
                String failureMessage = null;
                try {
                    operation.perform(this);
                    success = true;
                } catch (InterruptedException e) {
                    // TODO more graceful shutdown
                    break;
                } catch (Exception e) {
                    failureMessage = e.getMessage();

                    e.printStackTrace();
                } finally {
                    if (success) {
                        context.success();
                    } else {
                        context.failure(failureMessage);
                    }
                }
            }
        }

        @Override
        public String getSwarmName() {
            return swarmName;
        }

        @Override
        public int getClientId() {
            return clientId;
        }

        @Override
        public int getRequestId() {
            return requestId;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <T> T getContextValue(String key) {
            return (T) context.get(key);
        }

        @Override
        public <T> void setContextValue(String key, T value) {
            context.put(key, value);
        }
    }

    @JsonCreator
    public ClientSwarm(@JsonProperty("name") String name, @JsonProperty("operation") Operation operation,
            @JsonProperty("rate") RequestRate rate, @JsonProperty("numberOfClients") int clientCount) {

        metric = new Metric(name);
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < clientCount; i++) {
            threads.add(new ClientThread(name, i, operation, metric, rate));
        }
        this.threads = Collections.unmodifiableList(threads);
    }

    public void start() {
        for (Thread thread : threads) {
            thread.start();
        }
    }

    public void stop() throws InterruptedException {
        for (Thread thread : threads) {
            for (int i = 0; i < 3 && thread.isAlive(); i++) {
                thread.interrupt();
                thread.join(1000L);
            }
            if (thread.isAlive()) {
                StringBuilder sb = new StringBuilder(
                        String.format("Thread %s ignored interrupt flag\n", thread.getName()));
                for (StackTraceElement f : thread.getStackTrace()) {
                    sb.append("\t").append(f.toString()).append("\n");
                }
                System.err.println(sb.toString());
            }
        }
    }

    public Metric getMetric() {
        return metric;
    }
}