context: /* $Id$
   *
   * OpenMAMA: The open middleware agnostic messaging API
   * Copyright (C) 2011 NYSE Technologies, Inc.
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301 USA
   */
  
  using System;
  using System.Collections;
  using System.Threading;
  using System.IO;
  
  namespace Wombat.Mamda.Examples
  {
  	/// <summary>
  	/// </summary>
  	public class MamdaBookChurn
  	{
  
  		public static void Main(string[] args)
  		{
  			try
  			{
  				options = new CommandLineProcessor(args);
  
  				//Getting the log File name 
  				myLogFileName = options.getLogFileName();
  	            
  				if (myLogFileName != null)
  				{
  					myOutFile = new FileStream(myLogFileName, FileMode.OpenOrCreate); 
  					myOut = new StreamWriter(myOutFile);
  					myOut.WriteLine("Date/Time"+ "," + "ChurnStats" +","
  						+ "UpdateStats" + "," + "PeakMsgCount" + ","
  						+ "RecapStats" + "," + "BookGapStats" + ","
  						+"freeMemory" +"," +"Memory Used");
  				}
  				else
  				{
  					myOut = Console.Out;
  				}
  	            
  				// Initialize MAMA
  				bridge = new MamaBridge(options.getMiddleware());
  				Mama.open();
  				if (options.hasLogLevel())
  				{
  					myLogLevel = options.getLogLevel();
  					Mama.enableLogging(myLogLevel);
  				}
  
  				transport = new MamaTransport();
  				transport.create(options.getTransport(), bridge);
  
  				defaultQueue = Mama.getDefaultEventQueue(bridge);
  
  				//Get the Data dictionary.....
  				MamaSource dictionarySource = new MamaSource();
                  dictionarySource.symbolNamespace = options.getDictSource();
  				dictionarySource.transport = transport;
  				dictionary = buildDataDictionary(transport, defaultQueue, dictionarySource);
  	    
  				MamdaOrderBookFields.setDictionary(dictionary, null);
  	            
  				foreach (string symbol in options.getSymbolList())
  				{
  					subscribeToBooks(symbol);
  				}
  	            
  				myChurnRate = options.getChurnRate(); 
  	            
  				Thread.Sleep(10000);
  	            
  				//Getting the TimerInterval from the cmd prompt
  				myChurnInterval = options.getTimerInterval();
  	            
  				//Churn Timer
  				if (myChurnRate > 0)
  				{
  					myChurnTimer = safeCreateTimer(new ChurnCallback(), myChurnInterval);
  				}
  	            
  				//Stats Timer
  				myStatsTimer = safeCreateTimer(new StatsCallback(), 1.0);
  	            
  				Console.WriteLine("Hit Enter or Ctrl-C to exit.");
  				Mama.start(bridge);
  				GC.KeepAlive(dictionary);
  				Console.ReadLine();
  
  				if (myOutFile != null)
  				{
  					myOut.Close();
  				}
  			}
  			catch (Exception e)
  			{
  				Console.Error.WriteLine(e.ToString());
  				Environment.Exit(1);
  			}
  		}
  
  		private static void subscribeToBooks(string symbol)
  		{
  			MamdaSubscription aSubscription      = new MamdaSubscription();
  			MamdaOrderBookListener aBookListener = new MamdaOrderBookListener();
  			ListenerCallback callback            = new ListenerCallback();
  
  			aBookListener.addHandler(callback);
  			aSubscription.addMsgListener(aBookListener);
  			aSubscription.addStaleListener(callback);
  			aSubscription.setType(mamaSubscriptionType.MAMA_SUBSC_TYPE_BOOK);
          
  			aSubscription.create(
  				transport,
  				defaultQueue,
  				options.getSource(),
  				symbol,
  				null);
          
  			//Add the Mamda Subscription to the ArrayList
  			subscriptionList.Add(aSubscription);
  		}
  
  		private class ListenerCallback : MamdaOrderBookHandler, 
  										 MamdaStaleListener
  		{
  			public void onBookRecap (
  				MamdaSubscription        sub,
  				MamdaOrderBookListener   listener,
  				MamaMsg                  msg,
  				MamdaOrderBookDelta      bookDelta,
  				MamdaOrderBookRecap      bookRecap)
  			{
  				++myRecapStats;
  			}
  	        
  			public void onBookDelta (
  				MamdaSubscription        sub,
  				MamdaOrderBookListener   listener,
  				MamaMsg                  msg,
  				MamdaOrderBookDelta      bookDelta,
  				MamdaOrderBookRecap      bookRecap)
  			{
  				++myUpdateStats;
  			}
  	            
  			public void onBookClear (
  				MamdaSubscription        sub,
  				MamdaOrderBookListener   listener,
  				MamaMsg                  msg,
  				MamdaOrderBookDelta      bookDelta,
  				MamdaOrderBookRecap      fullBook)
  			{
  				Console.WriteLine("BookClear");
  			}
  	            
  			public void onBookGap(
  				MamdaSubscription        sub,
  				MamdaOrderBookListener   listener,
  				MamaMsg                  msg,
  				MamdaOrderBookGap        gapEvent,
  				MamdaOrderBookRecap      fullBook)
  			{
  				++myBookGapStats;
  			}
  	            
  			public void onStale(
  				MamdaSubscription   subscription,
  				mamaQuality         quality)
  			{
  				Console.WriteLine("Stale ({0} - {1})", subscription.getSymbol(), quality);
  			}
  		}
  
  		//ChurnCallback
  		private class ChurnCallback : MamaTimerCallback
  		{
  			public void onTimer(MamaTimer mamaTimer, object closure)
  			{
  				lock (myGuard)
  				{
  					onTimerImpl();
  				}
  			}
  			
  			public void onDestroy(MamaTimer mamaTimer, object closure)
  			{
  			}
  
  			private void onTimerImpl()
  			{
  				myNumToChurn = myChurnRate;
  				while (myNumToChurn-- > 0)
  				{
  					myRandomNo = generator.Next(65536) % options.getSymbolListSize();
  					//Accessing the mamda subscription object from the arrayList
  					try
  					{
  						sub = (MamdaSubscription)subscriptionList[myRandomNo];
  						subscriptionList.RemoveAt(myRandomNo);
  						tempSymbol = sub.getSymbol();
  						if (tempSymbol != null) 
  						{
  							//Deactivating the Mamda Subscription
  							sub.deactivate();
  							//Creating the MamdaSubscription 
  							subscribeToBooks(tempSymbol);
  							++myChurnStats;
  						}
  					}
  					catch (Exception e)
  					{
  						Console.WriteLine("Error: {0}", e.ToString());
  					}
  				}
  			}
  
  			private MamdaSubscription sub   = null;
  			private String      tempSymbol  = null;
  			private int         myNumToChurn= 0;
  			private int         myRandomNo  = 0; 
  
gt: 			Random              generator   = new Random();