/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.test.remoting.transport.multiplex.config;

import java.util.HashMap;
import java.util.Map;

import junit.framework.TestCase;

import org.jboss.logging.Logger;
import org.jboss.remoting.Client;
import org.jboss.remoting.InvokerLocator;
import org.jboss.remoting.callback.Callback;
import org.jboss.remoting.callback.HandleCallbackException;
import org.jboss.remoting.callback.InvokerCallbackHandler;
import org.jboss.remoting.transport.Connector;
import org.jboss.remoting.transport.PortUtil;
import org.jboss.remoting.transport.multiplex.Multiplex;

/**
 * @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
 *
 */
public class MemoryTestClient extends TestCase
{
	// Constants -----------------------------------------------------
	
	private static final Logger log = Logger.getLogger(MemoryTestClient.class);
	private MemoryWatcher memoryWatcher = new MemoryWatcher();
	public  static final int ITERATIONS = 1000;
	
	static class MemoryWatcher
	{
		private long lastIncreaseTime;
		private long currentMaxMemory;
		private Runtime runtime;
		private int callCounter;
		
		MemoryWatcher()
		{
			runtime = Runtime.getRuntime();
			lastIncreaseTime = System.currentTimeMillis();
			currentMaxMemory = runtime.totalMemory() - runtime.freeMemory();
		}
		
		void checkMemory(String note)
		{
			if (++callCounter % 100 == 0)
			{
//				System.gc();
				long currentMemory = runtime.totalMemory() - runtime.freeMemory(); 
//				if (currentMemory > currentMaxMemory)
//				{
					long currentTime = System.currentTimeMillis();
					System.out.println("     " + currentMemory + ": "
							+ (currentTime - lastIncreaseTime) + " (" + note + ")");
					lastIncreaseTime = currentTime;
					currentMaxMemory = currentMemory;
//				}
			}
		}
	}
	
	public static void main(String[] args)
	{
		try
		{
			MemoryTestClient client = new MemoryTestClient("test");
			client.setUp();
			client.testMultiplex();
			client.tearDown();
         Thread.sleep(3000000);
			System.out.println("done.");
		}
		catch (Throwable e)
		{
			e.printStackTrace();
		}
		
	}
	
	
	// Attributes ----------------------------------------------------
	
	// Constructors --------------------------------------------------
	
	public MemoryTestClient(String name)
	{
		super(name);
	}
	
	// TestCase overrides -------------------------------------------
	
	public void setUp() throws Exception
	{
		
		super.setUp();
		
	}
	
	public void tearDown() throws Exception
	{
		
		super.tearDown();
	}
	
	public void testMultiplex() throws Throwable
	{  
		try
		{
			for (int i = 0; i < ITERATIONS; i++)
			{         
				//Create a client for invoking on the server:         
				int localPort = PortUtil.findFreePort("localhost");
				log.info("Free port is:" + localPort);    
//				String locatorURI = "multiplex://localhost:9099/?blah=" + localPort;
				String locatorURI = new StringBuffer("multiplex://localhost:9099/?blah=").append(localPort).toString();
				InvokerLocator locatorClient = new InvokerLocator(locatorURI);
				Map configuration = new HashMap();
				configuration.put(Multiplex.CLIENT_MULTIPLEX_ID, "mytestid" + i);
				configuration.put(Multiplex.MULTIPLEX_BIND_HOST, "localhost");
				configuration.put(Multiplex.MULTIPLEX_BIND_PORT, String.valueOf(localPort));
				Client client = new Client(locatorClient, configuration);
				log.info("Created client");
				client.connect();
				log.info("Invoking");
				String response = (String)client.invoke("Cheese");
				log.info("Invocation completed");
				assertNotNull(response);
				assertEquals("Sausages", response);
				
				Connector callbackServerConnector = new Connector();      
				InvokerLocator callbackServerLocator = new InvokerLocator("multiplex://localhost:" + localPort + "/?serverMultiplexId=mytestid" + i);
				callbackServerConnector.setInvokerLocator(callbackServerLocator.getLocatorURI());      
				callbackServerConnector.create();      
				callbackServerConnector.start();
				log.info("Created callback server");
				log.info("Invoking");
				response = (String)client.invoke("Cheese");
				log.info("Invocation completed");
				assertNotNull(response);
				assertEquals("Sausages", response);
				SimpleCallbackHandler callbackHandler = new SimpleCallbackHandler();
				client.addListener(callbackHandler, callbackServerLocator);
//				client.removeListener(callbackHandler);
				
				client.disconnect();
				callbackServerConnector.stop();
				callbackServerConnector.destroy();
				
				memoryWatcher.checkMemory("" + (i+1));
				if (i % 1000 == 0)
					System.out.println("Created client: " + i + " (" + localPort + ")");
				Thread.sleep(50);
				
				
				
			}
		}
		catch (Throwable t)
		{
			log.error(t);
			t.printStackTrace();
		}
		
		//Thread.sleep(1000 * 60 * 30 * 10);
		
		//Now run netstat -a and see how many TCP connections are open!
		
	}
	
	class SimpleCallbackHandler implements InvokerCallbackHandler
	{
		
		Callback callback;
		
		public void handleCallback(Callback callback) throws HandleCallbackException
		{
			this.callback = callback;         
		}
		
	}
}



