package demodispatch;

import java.util.Random;
import jet.server.api.cluster.LoadBalancer;
import jet.server.api.cluster.Member;
import jet.server.api.cluster.ReportMember;

 /**
 * Class DemoLoadBalancer is a demo which randomly selects a member by DemoLoadBalancer
 * 
 * Usage: 
 *     1. Add DemoLoadBalancer.class into classPath in JRServer.bat.
 *     2. In server.properties set: loadbalance.custom_class=DemoLoadBalancer.
 *        Or on command line set the system properties: -Dloadbalance.custom_class=DemoLoadBalancer
 *     3. Launch JRServer.bat, customized loadBalancer DemoLoadBalancer will 
 *        be applied.
 * 
 * @version 1.00, 04/24/03
 */

public class DemoLoadBalancer implements LoadBalancer {

	private Random select = new Random();

	/**
 	 * This is default constructor, a customized load balancer should has a constructor with an empty argument.
 	 */
	public DemoLoadBalancer() {
	}

    /**
     * Implements LoadBalancer defining method,in order to select a member from all useful members.
     * @param  localMember   Default useful local member without other useful member
     * @param  allMembers    All members that are joined into cluster server
     * @return Member  a useful member from all useful members
     */
	public Member selectMember(Member localMember, Member[] allMembers) {
		if (allMembers.length == 1) {
			return localMember;
		}

		Member[] m = getMembers(allMembers);

		if (m.length == 0) {
			return localMember;
		}		
		return randomSelect(m);
	}

	/**
	 * Random select a member from all useful members	
	 * @param	members		All useful members
	 * @return	Member  A member that is selected randomly from all useful members
	 */
	private Member randomSelect(Member[] members) {
       return members[select.nextInt(members.length)];
	}

	/**
	 * Get all useful members	 
	 * @param	members		All members that joined into cluster server
	 * @return	All useful members
	 */
	private Member[] getMembers(Member[] members) {
		int i = 0;
		int n = 0;
		Member[] tempMember = new Member[members.length];
		for (i = 0; i < members.length; i++) {
			if (canSelectMember(members[i])) {
				tempMember[n++] = members[i];
			}
		}

		if (n > 1) {
			Member[] m = new Member[n];
			for (i = 0; i < n; i++)
				m[i] = tempMember[i];
				return m;
		}
		return new Member[0];
	}

    /**
     * Estimate if member can be used, the method will be invoked in method getMembers
     * @param	member   The member will be determined if it can be used.
     * @return	The boolean value for the member if can be used.
     */
	private boolean canSelectMember(Member member) {
		int reports = ((ReportMember)member).getConcurrentReports();
		int maxReports = ((ReportMember)member).getMaxConcurrentReports();
		if (maxReports == 0) {
			return true;
		}
		if (reports < maxReports) {
			return true;
		}
		return false;
	}
}
