All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openl.util.ce.impl.Scheduler Maven / Gradle / Ivy

There is a newer version: 5.19.9
Show newest version
package org.openl.util.ce.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openl.util.TopoSort;
import org.openl.util.ce.IActivity;
import org.openl.util.ce.IInvokableActivity;
import org.openl.util.ce.IScheduledActivity;
import org.openl.util.ce.IScheduler;
import org.openl.util.ce.conf.ServiceMTConfiguration;

public class Scheduler implements IScheduler {

	ServiceMTConfiguration config;

	public Scheduler(ServiceMTConfiguration config, long singleCellLength) {
		this.config = config;
		this.parLevel = config.getTotalParallelLevel();
		this.minSeqLength = Math.max(
				(int) (config.getMinSequenceLengthNs() / singleCellLength), 1);
	}

	int parLevel = 4;
	int minSeqLength = 5;

	@Override
	public IScheduledActivity[] prepare(IActivity[] activities) {

		Map all = prepareActivities(activities);

		List orderedActivities = orderActivities(all);

		markCriticalTime(orderedActivities, all);

		IScheduledActivity[] ary = orderedActivities
				.toArray(new IScheduledActivity[orderedActivities.size()]);
		Arrays.sort(ary, IScheduledActivity.comparator);

		markIds(ary);

		IScheduledActivity[] seqAry = makeSequences(ary);

		markIds(seqAry);

		return seqAry;
	}

	private IScheduledActivity[] makeSequences(IScheduledActivity[] ary) {

		boolean isInvokable = ary.length == 0
				|| ary[0].activity() instanceof IInvokableActivity;

		if (ary.length <= minSeqLength * 2) {
			return new IScheduledActivity[] { new SequenceActivity(ary,
					isInvokable) };
		}

		int nParBuckets = Math.min(ary.length / minSeqLength, parLevel);

		List[] buckets = new List[nParBuckets];
		List extraBucket = new ArrayList();
		

		for (int i = 0; i < buckets.length; i++) {
			buckets[i] = new ArrayList();
		}

		for (int i = 0; i < ary.length; i++) {
			if (ary[i].getPrecedentSize() == 0)
				selectMinSizeBucket(buckets).add(ary[i]);
			else if (ary[i].getPrecedentSize() == 1)
				selectBucketWithPrecedentOf(ary[i], buckets, extraBucket).add(ary[i]);
			else selectBucketWIthAllPrecedentsOf(ary[i], buckets, extraBucket).add(ary[i]);

		}

		List list = new ArrayList();
		SequenceActivity extraAct = extraBucket.size() > 0 ? 
				new SequenceActivity(extraBucket.toArray(new IScheduledActivity[0]), isInvokable) : null;
		for (int i = 0; i < buckets.length; i++) {
			if (buckets[i].size() == 0) continue;
			IScheduledActivity newAct = new SequenceActivity(buckets[i].toArray(new IScheduledActivity[0]), isInvokable);
			
			if (extraAct != null)
			{	
				newAct.getDependents().add(extraAct);
				extraAct.setPrecedentSize(extraAct.getPrecedentSize() + 1);
			}
			
			list.add(newAct);
			
		}
		
		if (extraAct != null)
			list.add(extraAct);
		
		return list.toArray(new IScheduledActivity[0]);
	}

	private List selectBucketWIthAllPrecedentsOf(
			IScheduledActivity iScheduledActivity,
			List[] buckets,
			List extraBucket) {

		for (int i = 0; i < buckets.length; i++) {
			int sumPrecedents = 0;
			for (IScheduledActivity act : buckets[i]) {
				if (act.getDependents().contains(iScheduledActivity))
					sumPrecedents++;
			}
			if (sumPrecedents == iScheduledActivity.getPrecedentSize())
				return buckets[i];
		}

		return extraBucket;
		
	}

	private List selectBucketWithPrecedentOf(
			IScheduledActivity iScheduledActivity,
			List[] buckets, List extraBucket) {
		for (int i = 0; i < buckets.length; i++) {
			for (IScheduledActivity act : buckets[i]) {
				if (act.getDependents().contains(iScheduledActivity))
					return buckets[i];
			}
		}
		return extraBucket;
	}

	private List selectMinSizeBucket(
			List[] buckets) {
		int min = 0;
		for (int i = 1; i < buckets.length; i++) {
			if (buckets[i].size() < buckets[min].size()) {
				min = i;
			}
		}

		return buckets[min];

	}

	protected static void markIds(IScheduledActivity[] orderedActivities) {
		int i = 0;
		for (IScheduledActivity scheduledActivity : orderedActivities) {
			scheduledActivity.setId(i++);
		}
	}

	private void markCriticalTime(List orderedActivities,
			Map all) {
		int size = orderedActivities.size();

		for (int i = 0; i < size; i++) {
			ScheduledActivity act = orderedActivities.get(size - 1 - i);

			boolean changed = act.increaseCriticalDistanceFromDependent(0);

			if (!changed)
				continue;

			updateActivityPredecessors(act, all);

		}
	}

	private void updateActivityPredecessors(ScheduledActivity act,
			Map all) {

		List dependsOn = act.activity().dependsOn();
		if (dependsOn == null)
			return;

		for (IActivity iActivity : dependsOn) {
			ScheduledActivity iact = all.get(iActivity);

			boolean changed = iact.increaseCriticalDistanceFromDependent(act
					.getCriticalDistance());

			if (!changed)
				continue;

			updateActivityPredecessors(iact, all);
		}
	}

	/**
	 * Orders activities in topological order and sets dependents
	 * 
	 * @param all
	 * @return
	 */

	private List orderActivities(
			Map all) {

		TopoSort ts = new TopoSort();

		for (ScheduledActivity root : all.values()) {
			ts.addOrderedPair(root, null);
		}

		for (ScheduledActivity leaf : all.values()) {

			List dependsOn = leaf.activity().dependsOn();

			if (dependsOn != null)
				for (IActivity ia : dependsOn) {
					ScheduledActivity root = all.get(ia);
					root.addDependent(leaf);
					ts.addOrderedPair(root, leaf);
				}
		}

		return ts.sort();
	}

	private Map prepareActivities(
			IActivity[] activities) {

		Map map = new HashMap(
				activities.length);

		for (IActivity activity : activities) {
			map.put(activity, new ScheduledActivity(activity));
		}

		return map;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy