com.espertech.esper.filter.TestIndexTreeBuilderMultithreaded.java Source code

Java tutorial

Introduction

Here is the source code for com.espertech.esper.filter.TestIndexTreeBuilderMultithreaded.java

Source

/*
 * *************************************************************************************
 *  Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
 *  http://esper.codehaus.org                                                          *
 *  http://www.espertech.com                                                           *
 *  ---------------------------------------------------------------------------------- *
 *  The software in this package is published under the terms of the GPL license       *
 *  a copy of which has been included with this distribution in the license.txt file.  *
 * *************************************************************************************
 */

package com.espertech.esper.filter;

import java.util.Vector;
import java.util.List;
import java.util.LinkedList;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;

import junit.framework.TestCase;
import com.espertech.esper.support.bean.SupportBean;
import com.espertech.esper.support.filter.SupportFilterSpecBuilder;
import com.espertech.esper.support.filter.SupportFilterHandle;
import com.espertech.esper.support.filter.IndexTreeBuilderRunnable;
import com.espertech.esper.support.event.SupportEventTypeFactory;
import com.espertech.esper.support.event.SupportEventBeanFactory;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestIndexTreeBuilderMultithreaded extends TestCase {
    private Vector<FilterSpecCompiled> testFilterSpecs;
    private Vector<EventBean> matchedEvents;
    private Vector<EventBean> unmatchedEvents;

    private EventType eventType;

    private FilterHandleSetNode topNode;
    private IndexTreeBuilder builder;
    private List<FilterHandle> filterCallbacks;
    private List<IndexTreePath> pathsAddedTo;

    public void setUp() {
        builder = new IndexTreeBuilder();
        eventType = SupportEventTypeFactory.createBeanType(SupportBean.class);
        topNode = new FilterHandleSetNode();
        filterCallbacks = new LinkedList<FilterHandle>();
        pathsAddedTo = new LinkedList<IndexTreePath>();

        testFilterSpecs = new Vector<FilterSpecCompiled>();
        matchedEvents = new Vector<EventBean>();
        unmatchedEvents = new Vector<EventBean>();

        // Any int and double value specified here must match only the current filter spec not any other filter spec
        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.GREATER_OR_EQUAL, 100000 }));
        matchedEvents.add(makeEvent(9999999, -1));
        unmatchedEvents.add(makeEvent(0, -1));

        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.GREATER_OR_EQUAL, 10,
                "doublePrimitive", FilterOperator.EQUAL, 0.5 }));
        matchedEvents.add(makeEvent(10, 0.5));
        unmatchedEvents.add(makeEvent(0, 0.5));

        testFilterSpecs.add(makeSpec(new Object[] { "doublePrimitive", FilterOperator.EQUAL, 0.8 }));
        matchedEvents.add(makeEvent(-1, 0.8));
        unmatchedEvents.add(makeEvent(-1, 0.1));

        testFilterSpecs.add(makeSpec(new Object[] { "doublePrimitive", FilterOperator.EQUAL, 99.99, "intPrimitive",
                FilterOperator.LESS, 1 }));
        matchedEvents.add(makeEvent(0, 99.99));
        unmatchedEvents.add(makeEvent(2, 0.5));

        testFilterSpecs.add(makeSpec(new Object[] { "doublePrimitive", FilterOperator.GREATER, .99, "intPrimitive",
                FilterOperator.EQUAL, 5001 }));
        matchedEvents.add(makeEvent(5001, 1.1));
        unmatchedEvents.add(makeEvent(5002, 0.98));

        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.LESS, -99000 }));
        matchedEvents.add(makeEvent(-99001, -1));
        unmatchedEvents.add(makeEvent(-98999, -1));

        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.GREATER_OR_EQUAL, 11,
                "doublePrimitive", FilterOperator.GREATER, 888.0 }));
        matchedEvents.add(makeEvent(11, 888.001));
        unmatchedEvents.add(makeEvent(10, 888));

        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.EQUAL, 973, "doublePrimitive",
                FilterOperator.EQUAL, 709.0 }));
        matchedEvents.add(makeEvent(973, 709));
        unmatchedEvents.add(makeEvent(0, 0.5));

        testFilterSpecs.add(makeSpec(new Object[] { "intPrimitive", FilterOperator.EQUAL, 973, "doublePrimitive",
                FilterOperator.EQUAL, 655.0 }));
        matchedEvents.add(makeEvent(973, 655));
        unmatchedEvents.add(makeEvent(33838, 655.5));
    }

    public void testVerifyFilterSpecSet() {
        // Add all the above filter definitions
        for (FilterSpecCompiled filterSpec : testFilterSpecs) {
            FilterValueSet filterValues = filterSpec.getValueSet(null, null, null);
            FilterHandle callback = new SupportFilterHandle();
            filterCallbacks.add(callback);
            pathsAddedTo.add(builder.add(filterValues, callback, topNode));
        }

        // None of the not-matching events should cause any match
        for (EventBean theEvent : unmatchedEvents) {
            List<FilterHandle> matches = new LinkedList<FilterHandle>();
            topNode.matchEvent(theEvent, matches);
            assertTrue(matches.size() == 0);
        }

        // All of the matching events should cause exactly one match
        for (EventBean theEvent : matchedEvents) {
            List<FilterHandle> matches = new LinkedList<FilterHandle>();
            topNode.matchEvent(theEvent, matches);
            assertTrue(matches.size() == 1);
        }

        // Remove all expressions previously added
        int count = 0;
        for (IndexTreePath treePath : pathsAddedTo) {
            FilterHandle callback = filterCallbacks.get(count++);
            builder.remove(eventType, callback,
                    new EventTypeIndexBuilderIndexLookupableIterator(treePath.toArray()), topNode);
        }

        // After the remove no matches are expected
        for (EventBean theEvent : matchedEvents) {
            List<FilterHandle> matches = new LinkedList<FilterHandle>();
            topNode.matchEvent(theEvent, matches);
            assertTrue(matches.size() == 0);
        }
    }

    public void testMultithreaded() throws Exception {
        FilterHandleSetNode topNode = new FilterHandleSetNode();

        performMultithreadedTest(topNode, 2, 1000, 1);
        performMultithreadedTest(topNode, 3, 1000, 1);
        performMultithreadedTest(topNode, 4, 1000, 1);

        performMultithreadedTest(new FilterHandleSetNode(), 2, 1000, 1);
        performMultithreadedTest(new FilterHandleSetNode(), 3, 1000, 1);
        performMultithreadedTest(new FilterHandleSetNode(), 4, 1000, 1);
    }

    private void performMultithreadedTest(FilterHandleSetNode topNode, int numberOfThreads, int numberOfRunnables,
            int numberOfSecondsSleep) throws Exception {
        log.info(".performMultithreadedTest Loading thread pool work queue,numberOfRunnables=" + numberOfRunnables);

        ThreadPoolExecutor pool = new ThreadPoolExecutor(0, numberOfThreads, 99999, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>());

        for (int i = 0; i < numberOfRunnables; i++) {
            IndexTreeBuilderRunnable runnable = new IndexTreeBuilderRunnable(eventType, topNode, testFilterSpecs,
                    matchedEvents, unmatchedEvents);

            pool.execute(runnable);
        }

        log.info(".performMultithreadedTest Starting thread pool, threads=" + numberOfThreads);
        pool.setCorePoolSize(numberOfThreads);

        // Sleep X seconds
        sleep(numberOfSecondsSleep);

        log.info(".performMultithreadedTest Completed, numberOfRunnables=" + numberOfRunnables
                + "  numberOfThreads=" + numberOfThreads + "  completed=" + pool.getCompletedTaskCount());

        pool.shutdown();
        pool.awaitTermination(1, TimeUnit.SECONDS);

        assertTrue(pool.getCompletedTaskCount() == numberOfRunnables);
    }

    private void sleep(int sec) {
        try {
            Thread.sleep(sec * 1000);
        } catch (InterruptedException e) {
            log.warn(e);
        }
    }

    private FilterSpecCompiled makeSpec(Object[] args) {
        return SupportFilterSpecBuilder.build(eventType, args);
    }

    private EventBean makeEvent(int aInt, double aDouble) {
        SupportBean bean = new SupportBean();
        bean.setIntPrimitive(aInt);
        bean.setDoublePrimitive(aDouble);
        return SupportEventBeanFactory.createObject(bean);
    }

    private static final Log log = LogFactory.getLog(TestIndexTreeBuilderMultithreaded.class);
}