CollectiveRecord.java

package edu.udel.cis.vsl.tass.state.impl;

import java.io.PrintWriter;

import edu.udel.cis.vsl.tass.model.IF.CollectiveAssertionIF;
import edu.udel.cis.vsl.tass.model.IF.ProcessIF;
import edu.udel.cis.vsl.tass.morph.Morphic;
import edu.udel.cis.vsl.tass.morph.MorphicArray;
import edu.udel.cis.vsl.tass.morph.MorphicArrayFactory;
import edu.udel.cis.vsl.tass.morph.MorphicObject;
import edu.udel.cis.vsl.tass.state.IF.CollectiveRecordIF;
import edu.udel.cis.vsl.tass.state.IF.ProcessStateIF;

public class CollectiveRecord extends MorphicObject implements
		CollectiveRecordIF {

	private CollectiveAssertionIF assertion;

	private MorphicArray<ProcessStateIF> snapshots;

	/**
	 * Note: the assertion may be null. This is used in special cases.
	 * 
	 * Note: a null snapshots indicates the record is complete, i.e., has been
	 * reached by every process.
	 * 
	 * If snapshots is non-null, then assertion must also be non-null, and the
	 * length of the snapshots must equal assertion.numProcs().
	 * 
	 * @param assertion
	 * @param snapshots
	 */
	public CollectiveRecord(CollectiveAssertionIF assertion,
			MorphicArray<ProcessStateIF> snapshots) {
		this.assertion = assertion;
		this.snapshots = snapshots;
		assert snapshots == null
				|| (assertion != null && snapshots.length() == assertion
						.numProcs());
	}

	@Override
	public CollectiveAssertionIF assertion() {
		return assertion;
	}

	@Override
	public MorphicArray<ProcessStateIF> snapshots() {
		return snapshots;
	}

	@Override
	public ProcessStateIF getSnapshot(ProcessIF process) {
		int index = assertion.indexOf(process);

		return snapshots.get(index);
	}

	public void setSnapshots(MorphicArray<ProcessStateIF> snapshots) {
		assert !isCommitted();
		this.snapshots = snapshots;
	}

	public void setSnapshot(int index, ProcessStateIF snapshot) {
		snapshots.set(index, snapshot);
	}

	public void setSnapshot(ProcessIF process, ProcessStateIF snapshot) {
		setSnapshot(assertion.indexOf(process), snapshot);
	}

	public void print(PrintWriter out, String prefix) {
		out.println(prefix + "begin collective record " + descriptor());
		out.println(prefix + "  assertion: " + assertion);
		for (int i = 0; i < snapshots.length(); i++) {
			out.println(prefix + "  snapshot " + i + ": " + snapshots.get(i));
		}
		out.println(prefix + "end collective record ");
		out.flush();
	}

	public boolean isComplete() {
		if (snapshots == null)
			return true;
		for (ProcessStateIF processState : snapshots)
			if (processState == null)
				return false;
		return true;
	}

	public boolean reachedBy(ProcessIF process) {
		if (snapshots == null)
			return true;
		return getSnapshot(process) != null;
	}

	@Override
	protected boolean computeEquals(Morphic component) {
		if (component instanceof CollectiveRecord) {
			CollectiveRecord that = (CollectiveRecord) component;

			if (assertion == null) {
				if (that.assertion != null)
					return false;
			} else {
				if (that.assertion == null)
					return false;
				if (!assertion.equals(that.assertion))
					return false;
			}
			if (snapshots == null) {
				if (that.snapshots != null)
					return false;
			} else {
				if (that.snapshots == null)
					return false;
				if (!snapshots.equals(that.snapshots))
					return false;
			}
			return true;
		}
		return false;
	}

	@Override
	protected int computeHashCode() {
		return (assertion == null ? 0 : assertion.hashCode())
				+ (snapshots == null ? 0 : snapshots.hashCode());
	}

	@Override
	protected void commitChildren() {
		if (snapshots != null)
			snapshots.commit();
	}

	void canonicalizeChildren(
			MorphicArrayFactory<ProcessStateIF> processStateArrayFactory) {
		if (snapshots != null) {
			snapshots = processStateArrayFactory.canonic(snapshots);
		}
	}
}