MicroSpaceSystem.java

package org.microspace.space;

import org.microspace.specific.MicroSpaceAccessorGenerator;
import org.microspace.transport.specific.JvmCluster;
import org.microspace.transport.specific.JvmTransport;
import org.microspace.transport.specific.JvmTransportGenerator;

/**
 * A MicroSpaceSystem is a set of Spaces communicating inside a single JVM.
 * <p>
 * The system can be used to test setup with the following
 * spaces:
 * <ol>
 * <li>PRIMARY - one instance</li>
 * <li>BACKUP - one instance</li>
 * <li>REMOTE - 0 or more instances</li>
 * </ol>
 * <p>
 * On a user signal the PRIMARY and the BACKUP role can be switched.
 * <p>
 * 
 * REMOTE SPACE IS TILL UNDER DEVELOPMENT.
 * 
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 * @version 2017-07-05
 */
public class MicroSpaceSystem {
	
	final static String CLUSTER = "CLUSTER";

	final SimpleFailoverMicroSpace primarySpace;
	final SimpleFailoverMicroSpace backupSpace;
	final SimpleFailoverMicroSpace[] remoteSpaces;
	
	final JvmTransportGenerator generator;
	JvmCluster cluster;
	
	JvmTransport transport;
	
	/**
	 * Create a System of Spaces.
	 * @param remoteCount is the number of remote spaces.
	 */
	public MicroSpaceSystem (int remoteCount) {
		SpaceConfig config = new SpaceConfig();
		config.setAccessorGenerator(new MicroSpaceAccessorGenerator());
		config.setClusterName(CLUSTER);
		config.setClusterBackup(true);
		config.setClusterRecoveryTimeout(100L);
		generator = new JvmTransportGenerator();
		config.setClusterTransportGenerator(generator);
		config.setFileBackup(false);
		primarySpace = new SimpleFailoverMicroSpace(config);
		backupSpace = new SimpleFailoverMicroSpace(config);
		remoteSpaces = new SimpleFailoverMicroSpace[remoteCount];
		
		config.setRemoteSpace(true);
		for (int i=0; i<remoteCount; i++) {
			remoteSpaces[i] = new SimpleFailoverMicroSpace(config);
		}
	}
	/**
	 * Obtain the space that was primary when system started.
	 * 
	 * This may have changed if there was a failover.
	 * 
	 * @return The space with PRIMARY role.
	 */
	public SimpleFailoverMicroSpace getPrimarySpace () {
		return primarySpace;
	}
	/**
	 * Obtain the space that was backup when system started.
	 * 
	 * This may have changed if there was a failover.
	 * 
	 * @return The space with BACKUP role.
	 */
	public SimpleFailoverMicroSpace getBackupSpace () {
		return backupSpace;
	}
	public int getRemoteSpaceCount () {
		return remoteSpaces.length;
	}
	/**
	 * Obtain the remote space. 
	 * @param index is the remote space .
	 * @return One of the remote spaces.
	 */
	public SimpleFailoverMicroSpace getRemoteSpace (int index) {
		return remoteSpaces[index];
	}
	public void start () {
		primarySpace.start();
		backupSpace.start();
		cluster = generator.getCluster(CLUSTER);
		for (SimpleFailoverMicroSpace remote : remoteSpaces) {
			remote.start();
		}
	}
	public void shutdown () {
		primarySpace.start();
		backupSpace.start();
		for (SimpleFailoverMicroSpace remote : remoteSpaces) {
			remote.shutdown();
		}
		if (transport != null) {
			primarySpace.shutdown();
			backupSpace.shutdown();
		} else {
			backupSpace.shutdown();
			primarySpace.shutdown();
		}
	}
	
	/**
	 * Switch PRIMARY and BACKUP role. 
	 */
	public void failover () {
		if (transport != null) {
			cluster.add(transport);
			transport = null;
		} else {
			transport = cluster.getOldestTransport();
			cluster.remove(transport);
		}
	}
}