예제 #1
0
        public void TestIt()
        {
            var stmtText =
                "insert into ThroughputPerFeed " +
                " select feed, count(*) as cnt " +
                "from " + typeof(FeedEvent).FullName + ".win:time_batch(1 sec) " +
                "group by feed";

            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;

            var runtime = EPRuntimeProvider.GetDefaultRuntime(configuration);
            var stmt    = runtime.DeployStatement(stmtText);

            stmt.Events += DisplayEvents;

            /*
             * while(true)
             * {
             *  FeedEvent event;
             *  event = new FeedEvent(FeedEnum.FEED_A, "IBM", 70);
             *  engine.GetEPRuntime().SendEvent(event);
             *  event = new FeedEvent(FeedEnum.FEED_B, "IBM", 70);
             *  engine.GetEPRuntime().SendEvent(event);
             * }
             */
        }
예제 #2
0
        public void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Runtime.Threading.IsInternalTimerEnabled = false;
            configuration.Common.AddEventType("MarketDataEvent", typeof(MarketDataEvent).FullName);
            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;

            _runtime = EPRuntimeProvider.GetRuntime("TestTicksPerSecondStatement", configuration);
            _runtime.Initialize();
            _runtime.EventService.AdvanceTime(0);

            TicksPerSecondStatement.Create(_runtime);
            var stmt = TicksFalloffStatement.Create(_runtime);

            _listener    = new SupportUpdateListener();
            stmt.Events += _listener.Update;

            // Use external clocking for the test
            _runtime.EventService.ClockExternal();
        }
예제 #3
0
        public void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;
            configuration.Common.AddEventType("StockTick", typeof(StockTick).FullName);
            _runtime = EPRuntimeProvider.GetRuntime("TestStockTickerRSI", configuration);
            _runtime.Initialize();

            _stockListener  = new RSIStockTickerListener(_runtime, PERIOD);
            _expressionText = "every tick=StockTick(stockSymbol='" + SYMBOL + "')";
            //_expressionText = "every tick1=StockTick(stockSymbol='GOOG') -> tick2=StockTick(stockSymbol='GOOG')";
            _factory         = _runtime.CompileDeploy(_expressionText).Statements[0];
            _factory.Events += _stockListener.Update;

            var rsiEvent = typeof(RSIEvent).FullName;
            var viewExpr = "select * from " + rsiEvent + ".win:length(1)";

            _rsiListener     = new RSIListener();
            _factory         = _runtime.CompileDeploy(viewExpr).Statements[0];
            _factory.Events += _rsiListener.Update;
            _rsiListener.Reset();
        }
예제 #4
0
        public void Run()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            // load config - this defines the XML event types to be processed
            var configFile = "esper.examples.cfg.xml";
            var url        = container.ResourceManager().ResolveResourceURL(configFile);
            var config     = new Configuration(container);

            config.Configure(url);

            // get engine instance
            var runtime = EPRuntimeProvider.GetRuntime(runtimeUri, config);

            // set up statement
            var rfidStmt = RFIDTagsPerSensorStmt.Create(runtime);

            rfidStmt.Events += LogRate;

            // Send events
            var eventCount = 0;

            while (eventCount < numEvents)
            {
                SendEvent(runtime);
                eventCount++;
            }
        }
예제 #5
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        public void Run()
        {
            var container = ContainerExtensions.CreateDefaultContainer();

            // Configure engine with event names to make the statements more readable.
            // This could also be done in a configuration file.
            var configuration = new Configuration(container);

            configuration.Common.AddEventType("TxnEventA", typeof(TxnEventA));
            configuration.Common.AddEventType("TxnEventB", typeof(TxnEventB));
            configuration.Common.AddEventType("TxnEventC", typeof(TxnEventC));

            // Get engine instance
            var runtime = EPRuntimeProvider.GetRuntime(_engineURI, configuration);

            // We will be supplying timer events externally.
            // We will assume that each bucket arrives within a defined period of time.
            runtime.EventService.ClockExternal();

            // Set up statement for listening to combined events
            var combinedEventStmt = CombinedEventStmt.Create(runtime);

            combinedEventStmt.Events += LogCombinedEvents;

            // Set up statements for realtime summary latency data - overall totals and totals per customer and per supplier
            RealtimeSummaryStmt realtimeSummaryStmt = new RealtimeSummaryStmt(runtime);

            realtimeSummaryStmt.TotalsStatement.Events   += LogSummaryTotals;
            realtimeSummaryStmt.CustomerStatement.Events +=
                (sender, e) => LogSummaryGroup("customerId", e);
            realtimeSummaryStmt.SupplierStatement.Events +=
                (sender, e) => LogSummaryGroup("supplierId", e);

            // Set up statement for finding missing events
            var findMissingEventStmt = FindMissingEventStmt.Create(runtime);

            findMissingEventStmt.Events += FindMissingEvent;

            // The feeder to feed the engine
            var feeder = new FeederOutputStream(runtime);

            // Generate transactions
            var source = new TransactionEventSource(_numTransactions);
            var output = new ShuffledBucketOutput(source, feeder, _bucketSize);

            // Feed events
            if (_continuousSimulation)
            {
                while (true)
                {
                    output.Output();
                    Thread.Sleep(5000); // Send a batch every 5 seconds
                }
            }
            else
            {
                output.Output();
            }
        }
예제 #6
0
            public void Init(int sleepListenerMillis)
            {
                var container     = ContainerExtensions.CreateDefaultContainer();
                var configuration = new Configuration(container);

                configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;
                configuration.Common.AddEventType("Market", typeof(MarketData));
                _runtime          = EPRuntimeProvider.GetRuntime("benchmark", configuration);
                _marketDataSender = _runtime.EventService.GetEventSender("Market");
                _sleepMillis      = sleepListenerMillis;
            }
예제 #7
0
        public void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;

            _runtime = EPRuntimeProvider.GetDefaultRuntime(configuration);
            _sender  = _runtime.EventService.GetEventSender(typeof(OperationMeasurement).FullName);

            new ErrorRateMonitor();
        }
예제 #8
0
        public virtual void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer();

            var configuration = new Configuration(container);

            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;
            configuration.Common.AddEventType("TxnEventA", typeof(TxnEventA));
            configuration.Common.AddEventType("TxnEventB", typeof(TxnEventB));
            configuration.Common.AddEventType("TxnEventC", typeof(TxnEventC));

            _runtime = EPRuntimeProvider.GetRuntime("TestStmtBase", configuration);
            _runtime.Initialize();

            _eventService = _runtime.EventService;
        }
        public void SetUp()
        {
            _listener = new StockTickerResultListener();

            var container = ContainerExtensions.CreateDefaultContainer(false)
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.AddEventType("PriceLimit", typeof(PriceLimit).FullName);
            configuration.Common.AddEventType("StockTick", typeof(StockTick).FullName);

            _runtime = EPRuntimeProvider.GetRuntime("TestStockTickerMultithreaded", configuration);
            _runtime.Initialize();
            new StockTickerMonitor(_runtime, _listener);
        }
예제 #10
0
        public void Run()
        {
            var container = ContainerExtensions.CreateDefaultContainer(false)
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.AddEventType("PriceLimit", typeof(PriceLimit));
            configuration.Common.AddEventType("StockTick", typeof(StockTick));

            Log.Info("Setting up EPL");

            var runtime = EPRuntimeProvider.GetRuntime(_engineURI, configuration);

            runtime.Initialize();

            var eventService = runtime.EventService;

            new StockTickerMonitor(runtime, new StockTickerResultListener());

            Log.Info("Generating test events: 1 million ticks, ratio 2 hits, 100 stocks");
            var generator = new StockTickerEventGenerator();
            var stream    = generator.MakeEventStream(1000000, 500000, 100, 25, 30, 48, 52, false);

            Log.Info("Generating " + stream.Count + " events");

            Log.Info("Sending " + stream.Count + " limit and tick events");
            foreach (var @event in stream)
            {
                eventService.SendEventBean(@event, @event.GetType().Name);

                if (_continuousSimulation)
                {
                    try {
                        Thread.Sleep(200);
                    }
                    catch (ThreadInterruptedException e) {
                        Log.Debug("Interrupted", e);
                        break;
                    }
                }
            }

            Log.Info("Done.");
        }
        public void Run()
        {
            Log.Info("Setting up engine instance.");

            var container = ContainerExtensions.CreateDefaultContainer();

            var config = new Configuration(container);

            config.Common.EventMeta.DefaultEventRepresentation = EventUnderlyingType.MAP; // use Map-type events for testing
            config.Compiler.AddPlugInVirtualDataWindow("sample", "samplevdw", typeof(SampleVirtualDataWindowFactory).FullName);
            config.Common.AddEventType(typeof(SampleTriggerEvent));
            config.Common.AddEventType(typeof(SampleJoinEvent));
            config.Common.AddEventType(typeof(SampleMergeEvent));

            var runtime = EPRuntimeProvider.GetRuntime("LargeExternalDataExample", config);

            // First: Create an event type for rows of the external data - here the example use a Map-based event and any of the other types (POJO, XML) can be used as well.
            // Populate event property names and types.
            // Note: the type must match the data returned by virtual data window indexes.
            CompileDeploy(runtime, "create schema SampleEvent as (key1 string, key2 string, value1 int, value2 double)");

            Log.Info("Creating named window with virtual.");

            // Create Named Window holding SampleEvent instances
            CompileDeploy(runtime, "create window MySampleWindow.sample:samplevdw() as SampleEvent");

            // Example subquery
            Log.Info("Running subquery example.");
            RunSubquerySample(runtime);

            // Example joins
            Log.Info("Running join example.");
            RunJoinSample(runtime);

            // Sample FAF
            Log.Info("Running fire-and-forget query example.");
            RunSampleFireAndForgetQuery(runtime);

            // Sample On-Merge
            Log.Info("Running on-merge example.");
            RunSampleOnMerge(runtime);

            // Cleanup
            Log.Info("Destroying engine instance, sample completed successfully.");
            runtime.Destroy();
        }
예제 #12
0
        public void SetUp()
        {
            _container = ContainerExtensions.CreateDefaultContainer()
                         .InitializeDefaultServices()
                         .InitializeDatabaseDrivers();

            var url    = _container.ResourceManager().ResolveResourceURL("esper.examples.cfg.xml");
            var config = new Configuration(_container);

            config.Configure(url);

            _runtime = EPRuntimeProvider.GetRuntime("AutoIdSim", config);
            _runtime.Initialize();

            _listener = new SupportUpdateListener();
            var rfidStmt = RFIDTagsPerSensorStmt.Create(_runtime);

            rfidStmt.Events += _listener.Update;
        }
예제 #13
0
        public void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.AddEventType("FraudWarning", typeof(FraudWarning));
            configuration.Common.AddEventType("Withdrawal", typeof(Withdrawal));
            configuration.Common.EventMeta.ClassPropertyResolutionStyle = PropertyResolutionStyle.CASE_INSENSITIVE;

            _runtime = EPRuntimeProvider.GetRuntime("FraudMonitorTest", configuration);
            _runtime.EventService.ClockExternal();

            _fraudWarningSender = _runtime.EventService.GetEventSender("FraudWarning");
            _withdrawalSender   = _runtime.EventService.GetEventSender("Withdrawal");

            _listener = new SupportUpdateListener();
            new FraudMonitor(_runtime, _listener.Update);
        }
예제 #14
0
        public void SetUp()
        {
            _listener = new StockTickerResultListener();

            var container = ContainerExtensions.CreateDefaultContainer(false)
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.AddEventType("PriceLimit", typeof(PriceLimit));
            configuration.Common.AddEventType("StockTick", typeof(StockTick));

            _runtime = EPRuntimeProvider.GetRuntime("TestStockTickerSimple", configuration);

            // To reduce logging noise and get max performance
            _runtime.EventService.ClockExternal();

            _priceLimitSender = _runtime.EventService.GetEventSender("PriceLimit");
            _stockTickSender  = _runtime.EventService.GetEventSender("StockTick");
        }
예제 #15
0
        static void Main()
        {
            _random = new Random();

            var container = ContainerExtensions.CreateDefaultContainer();

            // Creates a statement that looks for market data events.
            var configuration = new Configuration(container);

            configuration.Common.AddEventType <MarketDataTrade>();
            configuration.Common.AddEventType <EndOfTest>();
            // set to true to decouple event processing from msmq latency
            configuration.Runtime.Threading.IsThreadPoolOutbound = false;

            _runtime = EPRuntimeProvider.GetDefaultRuntime(configuration);
            CompileDeploy("select * from MarketDataTrade").
            Events += (sender, eventArgs) => _publisher.SendEvent(eventArgs);
            CompileDeploy("select * from EndOfTest")
            .Events += (sender, eventArgs) => _publisher.SendEvent(eventArgs);

            // create a publisher
            _publisher = new MsmqPublisher(MqPath);
            // create a consumer
            _consumer      = new MsmqConsumer(MqPath, ConsumeEvent);
            _consumerEvent = new ManualResetEvent(false);

            // mark the starting time
            var milliTime = PerformanceObserver.TimeMillis(
                delegate
            {
                // send some events
                SendEvents();

                // wait for events
                _consumerEvent.WaitOne();
            });

            Console.WriteLine("Recv: {0} events in {1} ms", _eventsConsumed, milliTime);
            Console.ReadLine();
        }
예제 #16
0
        public void SetUp()
        {
            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            var configuration = new Configuration(container);

            configuration.Common.EventMeta.ClassPropertyResolutionStyle =
                PropertyResolutionStyle.CASE_INSENSITIVE;

            _listener = new MatchAlertListener();
            EPRuntimeProvider
            .GetDefaultRuntime()
            .DeploymentService
            .UndeployAll();

            _runtime = EPRuntimeProvider.GetDefaultRuntime(configuration);
            _runtime.Initialize();

            new MatchMakingMonitor(_runtime, _listener);
        }
예제 #17
0
        public void RunExample(
            bool isRunFromUnitTest,
            string runtimeUri)
        {
            var numEventsToLoad            = 100000;
            var numFireAndForgetExecutions = 100;
            var numOnEventQueryExecutions  = 100000;

            if (isRunFromUnitTest)
            {
                numEventsToLoad            = 1000;
                numFireAndForgetExecutions = 5;
                numOnEventQueryExecutions  = 5;
            }

            // define event type - this example uses Map event representation
            //
            var configuration = new Configuration();

            var definition = new Dictionary <string, object>();

            definition.Put("sensor", typeof(string));
            definition.Put("temperature", typeof(double));
            configuration.Common.AddEventType("SensorEvent", definition);

            var definitionQuery = new Dictionary <string, object>();

            definitionQuery.Put("querytemp", typeof(double));
            configuration.Common.AddEventType("SensorQueryEvent", definitionQuery);

            // This example initializes the engine instance as it is running within an overall test suite.
            // This step would not be required unless re-using the same engine instance with different configurations.
            var runtime = EPRuntimeProvider.GetRuntime(runtimeUri, configuration);

            runtime.Initialize();

            // define a named window to hold the last 1000000 (1M) events
            //
            var epl = "create window SensorWindow.win:keepall() as select * from SensorEvent";

            Log.Info("Creating named window : " + epl);
            CompileDeploy(epl, runtime);

            epl = "insert into SensorWindow select * from SensorEvent";
            Log.Info("Creating insert statement for named window : " + epl);
            CompileDeploy(epl, runtime);

            // load 1M events
            //
            var random  = new Random();
            var sensors = "s1,s2,s3,s4,s5,s6".Split(',');

            Log.Info("Generating " + numEventsToLoad + " sensor events for the named window");
            IList <IDictionary <string, object> > events = new List <IDictionary <string, object> >();

            for (var i = 0; i < numEventsToLoad; i++)
            {
                var temperature = Math.Round(random.NextDouble() * 10, 5, MidpointRounding.AwayFromZero) + 80;
                var sensor      = sensors[random.Next(sensors.Length)];

                IDictionary <string, object> data = new LinkedHashMap <string, object>();
                data.Put("temperature", temperature);
                data.Put("sensor", sensor);

                events.Add(data);
            }

            Log.Info("Completed generating sensor events");

            Log.Info("Sending " + events.Count + " sensor events into runtime");

            foreach (var @event in events)
            {
                runtime.EventService.SendEventMap(@event, "SensorEvent");
            }

            Log.Info("Completed sending sensor events");

            // prepare on-demand query
            //
            var sampleTemperature = (double)events[0].Get("temperature");

            epl = "select * from SensorWindow where temperature = " + sampleTemperature;
            Log.Info("Compiling fire-and-forget query : " + epl);
            var args = new CompilerArguments();

            args.Path.Add(runtime.RuntimePath);

            var onDemandQueryCompiled = EPCompilerProvider.Compiler.CompileQuery(epl, args);
            var onDemandQuery         = runtime.FireAndForgetService.PrepareQuery(onDemandQueryCompiled);

            Log.Info("Executing fire-and-forget query " + numFireAndForgetExecutions + " times");
            long startTime = Environment.TickCount;

            for (var i = 0; i < numFireAndForgetExecutions; i++)
            {
                var result = onDemandQuery.Execute();
                if (result.Array.Length != 1)
                {
                    throw new ApplicationException(
                              "Failed assertion of result, expected a single row returned from query");
                }
            }

            long endTime  = Environment.TickCount;
            var  deltaSec = (endTime - startTime) / 1000.0;

            Log.Info(
                "Executing fire-and-forget query " +
                numFireAndForgetExecutions +
                " times took " +
                deltaSec +
                " seconds");

            // prepare on-select
            //
            epl = "on SensorQueryEvent select sensor from SensorWindow where temperature = querytemp";
            Log.Info("Creating on-select statement for named window : " + epl);
            var onSelectStmt = CompileDeploy(epl, runtime);

            onSelectStmt.Subscriber = this;

            Log.Info("Executing on-select query " + numOnEventQueryExecutions + " times");
            startTime = Environment.TickCount;
            for (var i = 0; i < numOnEventQueryExecutions; i++)
            {
                var queryParams = new Dictionary <string, object> {
                    ["querytemp"] = sampleTemperature
                };

                runtime.EventService.SendEventMap(queryParams, "SensorQueryEvent");
            }

            endTime  = Environment.TickCount;
            deltaSec = (endTime - startTime) / 1000.0;
            Log.Info("Executing on-select query " + numOnEventQueryExecutions + " times took " + deltaSec + " seconds");
        }
예제 #18
0
        public void Run()
        {
            Log.Info("Setting up EPL");

            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            // This code runs as part of the automated regression test suite; Therefore disable internal timer theading to safe resources
            var config = new Configuration(container);

            config.Runtime.Threading.IsInternalTimerEnabled = false;

            var listener = new MatchAlertListener();
            var runtime  = EPRuntimeProvider.GetRuntime(_engineURI, config);

            runtime.Initialize();

            new MatchMakingMonitor(runtime, listener);

            var sender = runtime.EventService.GetEventSender(typeof(MobileUserBean).Name);

            Log.Info("Sending user information");
            var user1 = new MobileUserBean(1, 10, 10,
                                           Gender.MALE, HairColor.BLONDE, AgeRange.AGE_4,
                                           Gender.FEMALE, HairColor.BLACK, AgeRange.AGE_1);

            sender.SendEvent(user1);

            var user2 = new MobileUserBean(2, 10, 10,
                                           Gender.FEMALE, HairColor.BLACK, AgeRange.AGE_1,
                                           Gender.MALE, HairColor.BLONDE, AgeRange.AGE_4);

            sender.SendEvent(user2);

            Log.Info("Sending some near locations");
            user1.WithLocation(8.99999, 10);
            sender.SendEvent(user1);

            user1.WithLocation(9, 10);
            sender.SendEvent(user1);

            user1.WithLocation(11, 10);
            sender.SendEvent(user1);

            user1.WithLocation(11.0000001, 10);
            sender.SendEvent(user1);

            user2.WithLocation(10.0000001, 9);
            sender.SendEvent(user2);

            user1 = new MobileUserBean(1, 10, 10,
                                       Gender.MALE, HairColor.RED, AgeRange.AGE_6,
                                       Gender.FEMALE, HairColor.BLACK, AgeRange.AGE_5);
            sender.SendEvent(user1);

            // Test all combinations
            foreach (var gender in EnumHelper.GetValues <Gender>())
            {
                foreach (var color in EnumHelper.GetValues <HairColor>())
                {
                    foreach (var age in EnumHelper.GetValues <AgeRange>())
                    {
                        // Try user preferences
                        var userA = new MobileUserBean(2, 10, 10,
                                                       Gender.FEMALE, HairColor.BLACK, AgeRange.AGE_5,
                                                       gender, color, age);
                        sender.SendEvent(userA);
                    }
                }
            }

            var random = new Random();
            int maxEvents;

            if (_continuousSimulation)
            {
                maxEvents = int.MaxValue;
            }
            else
            {
                maxEvents = 100000;
                Log.Info("Sending 100k of random locations");
            }

            for (var i = 1; i < maxEvents; i++)
            {
                var x = 10 + random.Next(i) / 100000;
                var y = 10 + random.Next(i) / 100000;

                user2.WithLocation(x, y);
                sender.SendEvent(user2);

                if (_continuousSimulation)
                {
                    try {
                        Thread.Sleep(200);
                    } catch (ThreadInterruptedException e) {
                        Log.Debug("Interrupted", e);
                    }
                }
            }

            Log.Info("Done.");
        }
예제 #19
0
        public void Run()
        {
            if (_isWaitKeypress)
            {
                Console.WriteLine("...press enter to start simulation...");
                Console.ReadKey();
            }

            var container = ContainerExtensions.CreateDefaultContainer()
                            .InitializeDefaultServices()
                            .InitializeDatabaseDrivers();

            // Configure engine with event names to make the statements more readable.
            // This could also be done in a configuration file.
            var configuration = new Configuration(container);

            configuration.Common.AddEventType("MarketDataEvent", typeof(MarketDataEvent).FullName);

            // Get engine instance
            var runtime = EPRuntimeProvider.GetRuntime(_engineURI, configuration);

            // Set up statements
            var tickPerSecStmt = TicksPerSecondStatement.Create(runtime);

            tickPerSecStmt.Events += LogRate;

            var falloffStmt = TicksFalloffStatement.Create(runtime);

            falloffStmt.Events += MonitorRate;

            // Send events
            var threadPool = new DedicatedExecutorService(string.Empty, _numberOfThreads);
            var runnables  = new MarketDataSendRunnable[_numberOfThreads];

            for (var i = 0; i < _numberOfThreads; i++)
            {
                runnables[i] = new MarketDataSendRunnable(runtime);
                threadPool.Submit(runnables[i].Run);
            }

            var seconds = 0;
            var random  = new Random();

            while (seconds < _numSeconds)
            {
                seconds++;
                Thread.Sleep(1000);

                FeedEnum?feedToDropOff;
                if (random.NextDouble() * 100 < _dropProbability)
                {
                    feedToDropOff = FeedEnum.FEED_A;
                    if (random.Next(0, 2) == 1)
                    {
                        feedToDropOff = FeedEnum.FEED_B;
                    }
                    Log.Info("Setting drop-off for feed {0}", feedToDropOff);
                }
                else
                {
                    feedToDropOff = null;
                }

                foreach (var t in runnables)
                {
                    t.SetRateDropOffFeed(feedToDropOff);
                }
            }

            Log.Info("Shutting down threadpool");
            for (var i = 0; i < runnables.Length; i++)
            {
                runnables[i].SetShutdown();
            }
            threadPool.Shutdown();
            threadPool.AwaitTermination(new TimeSpan(0, 0, 0, 10));
        }