Programmatic Startup

For some developers, it may be convenient to start agents or hosts programmatically. It is not really hard, though you should be aware of some difficulties when attempting to do so. Don't worry, there are not too many of them!

Advantages

First, what reasons could you possibly have to embed AgentScape in your own application? A good reason would be for running tests or to have control over the classpath yourself. If the standard classpath and directory setup does not suit your needs, or you would like to integrate AgentScape in you application directly without making service. If you run AgentScape from a classpath that you also use to develop your own agents, you do not need to build jar files for injecting the agents, but you can just start the agents directly (well, more or less..)

Starting a Host

Starting a single host can be done quite easily using the class org.iids.aos.startup.HostBootstrapper. This is actually the same class that is used when starting a host from the commandline (ie. when using lib/boot.jar). But in addition to using boot.jar, you can also instantiate this class yourself and do your own startup.

Now, you actually have two options: either use an existing configuration file (one created by the configuration editor) or build one by hand. We'll explore the simplest example first.

Using an existing configuration file

In this example, we have an existing configuration stored in loc.xml. This file defines a single location (loc) and number of hosts (host1, host2 and host3).

To start one of these hosts, just invoke the host bootstrapper like this:

HostBootstrapper hbs = new HostBootstrapper();
hbs.startHost("loc.xml", "host1");

Now, if host1 is set to be the location manager, this will be taken care of as well. If it has to start the lookup service, this is also automatically done. Your AgentScape host is now embedded in your running JVM. Easy, right?

Building the configuration file at runtime

Things get more interesting when you do not (or do not want to) have an existing startup script. Since the configuration file is based on an XML schema processed by XmlBeans, you can build the document yourself quite easily. All you need to do is to create a new AgentScapeDocument (org.agentscape.config.AgentscapeDocument) and fill it with contents using the classes generated by XmlBeans. Easy peasy!

AgentscapeDocument doc = AgentscapeDocument.Factory.newInstance();
Agentscape as = doc.addNewAgentscape();
Location loc = as.addNewLocation();
Host host = loc.addNewHost();
 
// setup the lookup service
LookupConfig lookup = as.addNewLookup();
lookup.setHost("localhost");
lookup.setPort("8888");
 
// configure the location
loc.setName ("MyLocName");
 
// configure the host
host.setName ("host1");
host.setLocationmanager(true); // host is location manager
host.setLookupserver(true);    // host also starts the lookup service
 
// if you want to add some services to the host, this can also be done
Services services = host.addNewConfig().addNewServices();
ServiceConfig sc = services.addNewService();
 
// fill in the service config, etc..

As you see, hand-building the configuration can be quite verbose. But once you have this hand-built configuration, you can just pass it to the host bootstrapper and startup will begin just as when using a normal configuration file.

HostBootstrapper hbs = new HostBootstrapper();
AgentScapeDocument doc = createConfig(); // your own method
 
// for now we convert the document to an inputstream
hbs.startHost(new ByteArrayInputStream(doc.toString().getBytes()), "host1");

Waiting for startup to finish

After the bootstrapper was requested to start the host, the host will be started in its own thread. This may take a while to complete. To make sure that the host was completely started, you could use the following snippet (it will be part of the HostBootstrapper once 2.0-m5 is released):

boolean isStartupComplete (HostBootstrapper hb) throws Exception
{
	// this one should return the host ID of the instance that was started
 
	SystemServiceInfo hostInfo = hb.getHostManager();
	SystemServiceConfig hostConfig = hostInfo.getConfig();
	AgentScapeID hostId = hostConfig.getServiceId();
	AgentScapeID locId = hostConfig.getLocationId();
 
	// connect to the local API
 
	AgentScapeApi api = AgentScapeClient.getAgentScapeClient(hostId);
	if (api == null)
	{
		System.err.println ("Could not obtain API");
	}
	try
	{
		List<AgentScapeID> locations = api.listLocations();
 
		if (locations == null || !locations.contains(locId))
		{
			throw new Exception("Cannot find location " + locId +
					" in list " + locations);
		}
	}
	catch (RemoteException e)
	{
		throw new Exception("Unable to list locations", e);
	}
 
	// the location is up
	// check if the host is alive as well
 
	LookupCache lc = hostInfo.getContext().getLookupCache();
	LocationManager lm = null;
 
	// note: we must loop for a number of times
 
	try
	{
		lm = lc.getLocationManager(locId);
 
		boolean found = false;
		long startTime = System.currentTimeMillis();
 
		while (!found)
		{
			int RETRIES = 10;  // times
			int DELAY = 500;  // in ms
 
			for (int i = 0; i < RETRIES && !found; i++)
			{
				Set<AgentScapeID> hosts = lm.list_hosts().keySet();
				if (hosts.contains(hostId))
				{
					found = true;
					break;
				}
				else
				{
					try
					{
						Thread.sleep(DELAY);
					}
					catch (InterruptedException e)
					{
						// ignore
					}
				}
			}
 
			if (!found)
			{
				long endTime = System.currentTimeMillis();
				double timeSec = (endTime - startTime) / 1000.0;
				System.err.println(String.format("Waited for more than %.1f sec for host to boot", timeSec));
				return false;
			}
		}
 
		long endTime = System.currentTimeMillis();
		double timeSec = (endTime - startTime) / 1000.0;
		System.err.println(String.format("Host startup in %.1f sec", timeSec));
		return true;
	}
	catch (LocationUnknownException e)
	{
		throw new StartupException("Unable to query location manager", e);
	}
	finally
	{
		lc.releaseSystemService(lm);
	}
}		
development/programmatic_startup.txt · Last modified: 2013/02/01 15:11 by reinier