standardjmeterengine.java

来自「测试工具」· Java 代码 · 共 550 行 · 第 1/2 页

JAVA
550
字号
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *  
 */

package org.apache.jmeter.engine;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.jmeter.testbeans.TestBean;
import org.apache.jmeter.testbeans.TestBeanHelper;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestListener;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterThread;
import org.apache.jmeter.threads.JMeterThreadMonitor;
import org.apache.jmeter.threads.ListenerNotifier;
import org.apache.jmeter.threads.TestCompiler;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.apache.jorphan.collections.SearchByClass;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

/**
 */
public class StandardJMeterEngine implements JMeterEngine, JMeterThreadMonitor, Runnable, Serializable {
	private static final Logger log = LoggingManager.getLoggerForClass();

	private static final long serialVersionUID = 231L; // Remember to change this when the class changes ...
	
	private transient Thread runningThread;

	private static long WAIT_TO_DIE = 5 * 1000; // 5 seconds

	private transient Map allThreads;

	private volatile boolean startingGroups; // flag to show that groups are still being created
	
	private boolean running = false;

	private boolean serialized = false;

	private volatile boolean schcdule_run = false;

	private HashTree test;

	private transient SearchByClass testListeners;

	private String host = null;

	private transient ListenerNotifier notifier;

	// Should we exit at end of the test? (only applies to server, because host is non-null)
	private static final boolean exitAfterTest =
		JMeterUtils.getPropDefault("server.exitaftertest", false);  // $NON-NLS-1$

    private static final boolean startListenersLater = 
        JMeterUtils.getPropDefault("jmeterengine.startlistenerslater", true); // $NON-NLS-1$

    static {
        if (startListenersLater){
            log.info("Listeners will be started after enabling running version");
            log.info("To revert to the earlier behaviour, define jmeterengine.startlistenerslater=false");
        }
    }
	// Allow engine and threads to be stopped from outside a thread
	// e.g. from beanshell server
	// Assumes that there is only one instance of the engine
	// at any one time so it is not guaranteed to work ...
	private static transient Map allThreadNames;

	private static StandardJMeterEngine engine;

	private static Map allThreadsSave;

	public static void stopEngineNow() {
		if (engine != null) // May be null if called from Unit test
			engine.stopTest(true);
	}

	public static void stopEngine() {
		if (engine != null) // May be null if called from Unit test
			engine.stopTest(false);
	}

	/*
	 * Allow functions etc to register for testStopped notification
	 */
	private static final List testList = new ArrayList();

	public static synchronized void register(TestListener tl) {
		testList.add(tl);
	}

	public static boolean stopThread(String threadName) {
		return stopThread(threadName, false);
	}

	public static boolean stopThreadNow(String threadName) {
		return stopThread(threadName, true);
	}

	private static boolean stopThread(String threadName, boolean now) {
		if (allThreadNames == null)
			return false;// e.g. not yet started
		JMeterThread thrd;
		try {
			thrd = (JMeterThread) allThreadNames.get(threadName);
		} catch (Exception e) {
			log.warn("stopThread: " + e);
			return false;
		}
		if (thrd != null) {
			thrd.stop();
			if (now) {
				Thread t = (Thread) allThreadsSave.get(thrd);
				if (t != null) {
					t.interrupt();
				}
			}
			return true;
		}
		return false;
	}

	// End of code to allow engine to be controlled remotely

	public StandardJMeterEngine() {
		allThreads = new HashMap();
		engine = this;
		allThreadNames = new HashMap();
		allThreadsSave = allThreads;
	}

	public StandardJMeterEngine(String host) {
		this();
		this.host = host;
	}

	public void configure(HashTree testTree) {
		test = testTree;
	}

	public void setHost(String host) {
		this.host = host;
	}

	protected HashTree getTestTree() {
		return test;
	}

	protected void compileTree() {
		PreCompiler compiler = new PreCompiler();
		getTestTree().traverse(compiler);
	}

	// TODO: in Java1.5, perhaps we can use Thread.setUncaughtExceptionHandler() instead
	private static class MyThreadGroup extends java.lang.ThreadGroup{
	    public MyThreadGroup(String s) {
	        super(s);
	      }
	      
	      public void uncaughtException(Thread t, Throwable e) {
	    	if (!(e instanceof ThreadDeath)) {
	    		log.error("Uncaught exception: ", e);
	    		System.err.println("Uncaught Exception " + e + ". See log file for details.");
	    	}
	      }

	}
	public void runTest() throws JMeterEngineException {
		try {
			runningThread = new Thread(new MyThreadGroup("JMeterThreadGroup"),this);
			runningThread.start();
		} catch (Exception err) {
			stopTest();
			StringWriter string = new StringWriter();
			PrintWriter writer = new PrintWriter(string);
			err.printStackTrace(writer);
			throw new JMeterEngineException(string.toString());
		}
	}

	private void removeThreadGroups(List elements) {
		Iterator iter = elements.iterator();
		while (iter.hasNext()) {
			Object item = iter.next();
			if (item instanceof ThreadGroup) {
				iter.remove();
			} else if (!(item instanceof TestElement)) {
				iter.remove();
			}
		}
	}

	protected void notifyTestListenersOfStart() {
		Iterator iter = testListeners.getSearchResults().iterator();
		while (iter.hasNext()) {
			TestListener tl = (TestListener) iter.next();
			if (tl instanceof TestBean)
				TestBeanHelper.prepare((TestElement) tl);
			if (host == null) {
				tl.testStarted();
			} else {
				tl.testStarted(host);
			}
		}
	}

	protected void notifyTestListenersOfEnd() {
        log.info("Notifying test listeners of end of test");
		Iterator iter = testListeners.getSearchResults().iterator();
		while (iter.hasNext()) {
			TestListener tl = (TestListener) iter.next();
			if (tl instanceof TestBean)
				TestBeanHelper.prepare((TestElement) tl);
			if (host == null) {
				tl.testEnded();
			} else {
				tl.testEnded(host);
			}
		}
		log.info("Test has ended");
		if (host != null) {
			long now=System.currentTimeMillis();
			System.out.println("Finished the test on host " + host + " @ "+new Date(now)+" ("+now+")");
			if (exitAfterTest){
				exit();
			}
		}
	}

	private ListedHashTree cloneTree(ListedHashTree tree) {
		TreeCloner cloner = new TreeCloner(true);
		tree.traverse(cloner);
		return cloner.getClonedTree();
	}

	public void reset() {
		if (running) {
			stopTest();
		}
	}

	public synchronized void threadFinished(JMeterThread thread) {
		try {
            allThreads.remove(thread);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?