/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * 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.example.rfidassetzone; import com.espertech.esper.client.EPServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Random; import java.util.Set; import java.util.concurrent.Callable; public class AssetEventGenCallable implements Callable<Boolean> { public static final int NUM_ZONES = 20; private static final Logger log = LoggerFactory.getLogger(AssetEventGenCallable.class); private final EPServiceProvider engine; private final String[][] assetIds; private final int[][] zoneIds; private final Integer[] assetGroupsForThread; private final int ratioZoneMove; private final int ratioZoneSplit; private int numEventsSend; private int numZoneMoves; private int numZoneSplits; private int numSameZone; private Set<Integer> splitZoneGroups = new HashSet<Integer>(); private Random random = new Random(); private boolean shutdown; private boolean isGenerateZoneSplit; public AssetEventGenCallable(EPServiceProvider engine, String[][] assetIds, int[][] zoneIds, Integer[] assetGroupsForThread, int ratioZoneMove, int ratioZoneSplit) { this.engine = engine; this.assetIds = assetIds; this.zoneIds = zoneIds; this.assetGroupsForThread = assetGroupsForThread; this.ratioZoneMove = ratioZoneMove; this.ratioZoneSplit = ratioZoneSplit; isGenerateZoneSplit = true; } public void setShutdown(boolean shutdown) { this.shutdown = shutdown; } public void setGenerateZoneSplit(boolean generateZoneSplit) { isGenerateZoneSplit = generateZoneSplit; } public boolean isGenerateZoneSplit() { return isGenerateZoneSplit; } public int getNumEventsSend() { return numEventsSend; } public Boolean call() throws Exception { try { log.info(".call Thread " + Thread.currentThread().getId() + " starting"); while (!shutdown) { boolean isZoneMove = (random.nextInt() % ratioZoneMove) == 1; boolean isZoneSplit = (random.nextInt() % ratioZoneSplit) == 1; if (isZoneMove) { doZoneMove(); } else if (isZoneSplit && isGenerateZoneSplit) { doZoneSplit(); } else { doSameZone(); } } log.info(".call Thread " + Thread.currentThread().getId() + " done"); } catch (Exception ex) { log.error("Error in thread " + Thread.currentThread().getId(), ex); return false; } return true; } private void doZoneMove() { // Chose among one of the groups for this thread int index = Math.abs(random.nextInt()) % assetGroupsForThread.length; int groupNum = assetGroupsForThread[index]; // If this is a currently-split group, don't reunion if (splitZoneGroups.contains(groupNum)) { return; } // Determine zone to move to int newZone; do { newZone = Math.abs(random.nextInt()) % NUM_ZONES; } while (zoneIds[groupNum][0] == newZone); // Move all assets for this group to a new, random zone for (int i = 0; i < assetIds[i].length; i++) { zoneIds[groupNum][i] = newZone; LocationReport report = new LocationReport(assetIds[groupNum][i], newZone); engine.getEPRuntime().sendEvent(report); numEventsSend++; } numZoneMoves++; } private void doSameZone() { // Chose among one of the groups for this thread int index = Math.abs(random.nextInt()) % assetGroupsForThread.length; int groupNum = assetGroupsForThread[index]; // If this is a currently-split group, don't reunion if (splitZoneGroups.contains(groupNum)) { return; } // Re-send all assets for this group as the same zone for (int i = 0; i < assetIds[i].length; i++) { LocationReport report = new LocationReport(assetIds[groupNum][i], zoneIds[groupNum][i]); engine.getEPRuntime().sendEvent(report); numEventsSend++; } numSameZone++; } private void doZoneSplit() { int groupNum; do { int index = Math.abs(random.nextInt()) % assetGroupsForThread.length; groupNum = assetGroupsForThread[index]; } while (splitZoneGroups.contains(groupNum)); splitZoneGroups.add(groupNum); // Determine zone to move to int oldZone = zoneIds[groupNum][0]; int newZone; do { newZone = Math.abs(random.nextInt()) % NUM_ZONES; } while (zoneIds[groupNum][0] == newZone); log.info(".doZoneSplit Split group " + groupNum + " to different zones, from zone " + oldZone + " to zone " + newZone); // Move all assets for this group except the last asset to the new zone for (int i = 0; i < assetIds[i].length - 1; i++) { zoneIds[groupNum][i] = newZone; LocationReport report = new LocationReport(assetIds[groupNum][i], newZone); engine.getEPRuntime().sendEvent(report); numEventsSend++; } numZoneSplits++; } public int getNumZoneMoves() { return numZoneMoves; } public int getNumZoneSplits() { return numZoneSplits; } public int getNumSameZone() { return numSameZone; } public Set<Integer> getSplitZoneGroups() { return splitZoneGroups; } }