/*  execseq3.C   */
/*  Copyright 1991 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <math.h>
#include <stdlib.h>
#include <stream.h>
#include "cgidbg.h"
#include "netlnk.h"
#include "strmstr.h"
#include "yacintfc.h"
#include "tarparm.h"
#include "travparm.h"
#include "network.h"
#include "cmpseq.h"
#include "buffer.h"
#include "adjust.h"
#include "gcd.h"
#include "execseq.h"
#include "bufstat.h"

void ExecutionSequence::ComputeUsage()
{
/*
 *	LogOut << "ComputeUsage::DataNeeded =" << DataNeeded <<
 *		", LeftOver = " << LeftOver << "\n" ;
 *	LogOut << "OutputPerExec = " << OutputPerExecution << "\n";
 */
 
	ProviderCountNeeded = (DataNeeded - OrigLeftOver) / OutputPerExecution ;
	if (ProviderCountNeeded * OutputPerExecution != DataNeeded -
		OrigLeftOver) ProviderCountNeeded++ ;
	// LogOut << "ProviderCountNeeded = " << ProviderCountNeeded << "\n" ;
	NeededBufSize = ProviderCountNeeded * OutputPerExecution +
		OrigLeftOver ;
	MinBufSize = OutputPerExecution + OrigLeftOver ;
	if (MinBufSize < 0) MinBufSize = 0 ;
/*
 *	LogOut << "NeededBufSize = " << NeededBufSize << ", MinBufSize = "
 *		<< MinBufSize << "\n" ;
 */
}

// Returns 1 if sequence is set and no additonal processing needed.
int ExecutionSequence::SelectBufferSize()
{

/*
 *	LogOut << "OutBufSize = " << OutBufSize << 
 *		", NeededBufSize = " << NeededBufSize << "\n" ;
 */

	if (OutBufSize < NeededBufSize) {
		int32 NewSize ;
		if ((NewSize = BufStat->AllowedSize(NeededBufSize,
		    NeededBufSize)) < NeededBufSize)
			NewSize=BufStat->AllowedSize(MinBufSize,NeededBufSize);
		if (NewSize > OutBufSize) {
			// LogOut << "EnlargeBuffer from SelectBufferSize\n" ;
			TargetAdjustState Check=EnlargeBuffer(NewSize,NewSize) ;
			if (Check == TargetAdjustFail)
			  DbgError("ExecutionSequence","enlarge buffer failed");
		}
		if (NewSize < NeededBufSize) return 0 ;
	}
	if (!CurrentSize) DbgError("ExecutionSequence::SelectBufferSize",
		"null sequence");
	if (ProviderCountNeeded < Count(SeqIndex)) DbgError(
		"ExecutionSequence::SelectBufferSize","counts off");
	TryToBorrow(ProviderCountNeeded-Count(SeqIndex),SeqIndex);
	SetValue(ProviderCountNeeded,SeqIndex) ;
/*
 *	LogOut << "Setting Sequence[" << SeqIndex << "] = "
 *		<< ProviderCountNeeded << ", OutBufSize = " << OutBufSize
 *		<< "\n" ;
 */
	DataAvailable += ProviderCountNeeded * OutputPerExecution ;
	LeftOver -= ProviderCountNeeded * OutputPerExecution ;
/*
 *	LogOut << "DataAvailable = " << DataAvailable << ", LeftOver = " <<
 *		LeftOver << "\n" ;
 */
	return 1 ;
}

void ExecutionSequence::UpdateBufferType()
{
}

TargetAdjustState ExecutionSequence::CheckForNoChange(int ProviderCount,
	int ConsumerCount)
{
	if (ProviderCount || ConsumerCount) return TargetAdjustOK ;
	if (!ProviderCountNeeded && !ConsumerCountNeeded)
		return TargetAdjustOK ;

	int32 MinData ;
	int32 MinInput = InputPerExecution + OverlapWords ;
	int32 MinOutput = LeftOver + OutputPerExecution ;
	if (MinInput < MinOutput)  MinData = MinOutput ;
		else MinData = MinInput ;
	if (InputPerExecution < 1) DbgError(
		"ExecutionSequence::CheckForNoChange",
		"no input per");
	if (MinData <= OutBufSize) {
		MinData = MinInput ;
		while(MinData <= OutBufSize) MinData += InputPerExecution ;
		// force buffer expansion
	}
/*
 *	LogOut << "MinData = " << MinData << ", OutBufSize = " <<
 *		OutBufSize << "\n" ;
 */
		
	
	const char * NodeName ;
	int Channel ;
	ReasonForFailure::ChannelType Type ;

	if (BufStat->AllowedSize(MinData,MinData) >= MinData) {
		// LogOut << "EnlargeBuffer from CheckForNoChange\n" ;
		EnlargeBuffer(MinData,MinData);
		return TargetAdjustChange ;
	}

	if (MinInput < MinOutput) {
		Type = ReasonForFailure::Output ;
		Channel = ConsumerInLink->GetDriverOutputChannel()->
			GetNodeOutputChannel();
		NodeName = ConsumerInLink->GetDriverNodeName();
	} else {
		Type = ReasonForFailure::Input ;
		Channel = ConsumerInLink->GetNodeInputChannel();
		NodeName = ConsumerInLink->GetOutputNodeName();
	}
	BufStat->SetReason(new ReasonForFailure (
		"upper limit is too small to set sequence",
		NodeName,MinData,Channel,Type));
	return TargetAdjustFail ;
}


TargetAdjustState ExecutionSequence::UpdateSequenceList()
{
	// LogOut << "UpdateSequenceList for index " << SeqEnd << "\n" ;
	TargetAdjustState Return = TargetAdjustOK ;
	// TargetAdjustState Return = MakeEqualLength();
	// if (Return > TargetAdjustFail) return Return ;
	int32 TheDelayWords = 0 ;
	if (!SeqIndex) if (!BufStat->GetExecutionSequenceIndex())
	    if (ConsumerInLink->GetDelay()) {
		TheDelayWords = ConsumerInLink->GetDelay() *
			ConsumerInLink->GetChunkSize();
		DataAvailable += TheDelayWords ;
	}
					
	ConsumerCountNeeded = (DataNeeded - OverlapWords + TheDelayWords) /
		InputPerExecution ;
	// if (TheDelayWords) LogOut << "Delay = " << TheDelayWords << "\n" ;
	// LogOut << "ConsumerCountNeeded = " << ConsumerCountNeeded << "\n" ;
	// LogOut << "ProviderCountNeeded = " << ProviderCountNeeded << "\n" ;
	int Index = SeqIndex ;
	int32 SaveOrigLeftOver = OrigLeftOver ;
	int32 SaveDataNeeded = DataNeeded ;
	int32 SaveConsumerCountNeeded = ConsumerCountNeeded ;
	int32 SaveProviderCountNeeded = ProviderCountNeeded ;
	int32 SaveIndex = Index ;
	ExecutionSequence SaveProvider = ExecutionSequence(*this);
	ExecutionSequence SaveConsumer = ExecutionSequence(*ConsumerSequence);
	int SaveSeqEnd = SeqEnd ;
	// LogOut << "SaveSeqEnd = " << SaveSeqEnd << "\n" ;
	int Exit = 0 ;
	for (;;) {
	for(;;) {
		if (State.IsError()) return TargetAdjustFail ;
		int32 ProviderCountThisPass = (OutBufSize - OrigLeftOver) /
			OutputPerExecution;
		if (ProviderCountThisPass <0) ProviderCountThisPass = 0 ;
		if (ProviderCountThisPass > ProviderCountNeeded)
			ProviderCountThisPass = ProviderCountNeeded ;
		ProviderCountNeeded -= ProviderCountThisPass ;
		DataNeeded -= ProviderCountThisPass * OutputPerExecution ;

		int32 DataThisPass = OrigLeftOver + ProviderCountThisPass *
			OutputPerExecution ;
/*
 *		LogOut << "OrigLeftOver = " << OrigLeftOver <<
 *			", DataThisPass = " << DataThisPass << "\n" ;
 */
		int ConsumerCountThisPass = (DataThisPass - OverlapWords + TheDelayWords)
			/ InputPerExecution ;
		if (ConsumerCountThisPass < 0) ConsumerCountThisPass = 0 ;
		if (ConsumerCountThisPass > ConsumerCountNeeded)
			ConsumerCountThisPass = ConsumerCountNeeded ;
		ConsumerCountNeeded -= ConsumerCountThisPass ;

/*
 *		LogOut << "DataNeeded = " << DataNeeded <<
 *			", ProviderCount = " << ProviderCountThisPass <<
 *			", ConsumerCount = " << ConsumerCountThisPass << "\n" ;
 */

			
		OrigLeftOver = DataThisPass -
			ConsumerCountThisPass * InputPerExecution ;

		Return = CheckForNoChange(ProviderCountThisPass,
			ConsumerCountThisPass);
		// LogOut<<"After CheckForNoChange Return = "<< Return << "\n" ;
		if (Return == TargetAdjustChange) break ;
		if (Return > TargetAdjustChange) return Return ;
		if (!ProviderCountThisPass && !ConsumerCountThisPass) {
			// LogOut << "Exiting after CheckForNoChange\n" ;
			Exit =1 ;
			break ;
		}
		if (Index > SeqEnd) {
			// LogOut << "Expanding Sequence\n" ;
			// Enlarge length of both sequences
			Adjustment TheAdjustment(*Obj,
				Adjustment::EnlargeSequence,
				Index,1,1+CurrentSize,
				BufStat->GetExecutionSequenceIndex());
			TargetAdjustState LocReturn ;
			if (!BufStat->IsForwardFlag()) LocReturn =
				GetNode().AdjustForward(TheAdjustment);
			else LocReturn =
				ConsumerSequence->GetNode().AdjustBackward(
				TheAdjustment);
			if (Return < LocReturn) Return = LocReturn ;
			if (Return < TargetAdjustChange)
				Return = TargetAdjustChange ;
			SeqEnd++ ;
		} else {
/*
 *			LogOut << "Sequence[" << Index << "] = " <<
 *				ProviderCountThisPass<< "\n" ;
 */
			SetValue(ProviderCountThisPass,Index);
			ConsumerSequence->SetValue(ConsumerCountThisPass,Index);
/*
 *			LogOut << "ConsumerSequence->Sequence[" << Index <<
 *				"] = " << ConsumerCountThisPass << "\n" ;
 */
		}
 


		Index++ ;
		TheDelayWords = 0 ;
		if (State.IsError()) return TargetAdjustFail ;

	}
		if (Exit) break ;
		OrigLeftOver = SaveOrigLeftOver ;
		DataNeeded = SaveDataNeeded ;
		ConsumerCountNeeded = SaveConsumerCountNeeded ;
		ProviderCountNeeded = SaveProviderCountNeeded ;
		Index=SaveIndex ;
		SeqEnd = SaveSeqEnd ;
		// LogOut << "Restore local\n" ;
		Restore(SaveProvider);
		// LogOut << "Restore Consumer\n" ;
		ConsumerSequence->Restore(SaveConsumer);
	}
	// LogOut << "Index = " << Index << ", SeqEnd = " << SeqEnd << "\n" ;

	if (Index < SeqEnd) {
		for (int i = Index ; i <= SeqEnd;i++) {
			SetValue(0,i);
			ConsumerSequence->SetValue(0,i);
		}
	}
	return Return ;
}

TargetAdjustState ExecutionSequence::TryToBorrow(int MissingCount,
	int Seq_Index)
{
	TargetAdjustState Return = TargetAdjustOK ;
	for (int i = Seq_Index+1; i < GetSize(); i++) {
		if (!MissingCount) break ;
		int ToTake = Count(i) ;
		if (!ToTake) continue ;
		if (ToTake > MissingCount) ToTake = MissingCount ;
		BufStat->UpdateState(TargetAdjustChange);
		SetValue(Count(i) - ToTake,i);
		MissingCount -=ToTake ;
		Return = TargetAdjustChange ;
	}
/*
 *	if (MissingCount) LogOut << "Borrowing failed by " << MissingCount
 *		<< "\n" ;
 */
	return Return ;
}

int ExecutionSequence::OverlapHandled(int SeqIndex)
{
	for (int i = 0 ; i <= SeqIndex; i++)
		if (ConsumerSequence->Count(i)) return 0 ;
	for (i = SeqIndex + 1 ; i < CurrentSize; i++)
		if (ConsumerSequence->Count(i)) return 1 ;
	return 0 ;
}
		
TargetAdjustState ExecutionSequence::CheckForUnderflow(int Seq_Index,
	int Seq_End)
{
/*
 *	LogOut << "ExecutionSequence::CheckForUnderflow(" <<
 *		Seq_Index << ", " << Seq_End << ")\n" ;
 *	LogOut << GetNode().GetName() << ":C:DataNeeded = " << DataNeeded <<
 *		", Available = " << DataAvailable << "\n" ;
 */

	// Check if output has been zero padded
	TargetAdjustState Return = TargetAdjustOK ;
	if (DataNeeded <= DataAvailable) return Return ;
	if (OverlapHandled(Seq_Index)) return Return ;
	int32 ExtraConsumption = DataNeeded - DataAvailable ;
	if (BufStat->IsForwardFlag()) {
		// we never increase execution count when forward flag is sent
		// we must only move execution counts
		// move the consumption up to the next spot in list
		int ConsumerCount = ConsumerSequence->Count(Seq_End) ;
		int ToMove = ConsumerCount ;
		int32 DataToMove = ToMove * InputPerExecution ;
		if (DataToMove > ExtraConsumption) {
			int CheckToMove = ExtraConsumption / InputPerExecution ;
			if (CheckToMove * InputPerExecution != ExtraConsumption)
				CheckToMove++ ;
			if (CheckToMove < ToMove) ToMove = CheckToMove ;
		}
/*
 *		LogOut << "ConsumerCount = " << ConsumerCount <<
 *			", DataToMove = " << DataToMove << "\n" ;
 */
		ConsumerSequence->SetValue(ConsumerCount-ToMove, Seq_End); 
/*
 *		LogOut << "Consumer[" << SeqEnd << "] decremented by " <<
 *			ToMove << " to " << ConsumerSequence->Count(Seq_End)
 *			<< "\n " ;
 */
		if (CurrentSize < Seq_End + 2) {
			int tmp = CurrentSize ;
			ZeroPadSequence(tmp,tmp);
		}
		ConsumerSequence->SetValue(ConsumerSequence->Count(Seq_End+1)
			+ToMove, Seq_End+1); 
/*
 *		LogOut << "Consumer[" << SeqEnd + 1 << "] incremented by " <<
 *			ToMove << " to " << ConsumerSequence->Count(Seq_End+1)
 *			<< "\n " ;
 */
		return TargetAdjustMajorChange ;
	}
	SeqIndex = Seq_Index ;
	SeqEnd = Seq_End ;

	// LogOut << "Seq_End = " << Seq_End << "\n" ;
	int32 MissingData = DataNeeded - DataAvailable ;
	int MissingCount = MissingData/OutputPerExecution ;
	if (MissingCount * OutputPerExecution < MissingData) MissingCount++ ;
	// LogOut << "MissingCount = " << MissingCount << "\n" ;
	if (MissingCount > 0) {
		SetValue(MissingCount + Count(Seq_End), Seq_End);
		return TargetAdjustMajorChange ;
	}
	int32 SpaceNeeded = MissingCount * OutputPerExecution ;

/*
 *	LogOut << "MissingData = " << MissingData << ", SpaceNeeded = "
 *		<< SpaceNeeded << "\n" ;
 */
	
	if (DataAvailable + SpaceNeeded >= OutBufSize) {
		ComputeUsage();
		if (!CurrentSize) {
			if(!ConsumerSequence->GetSize()) DbgError(
				"ExecutionSequence::CheckForUnderflow",
				"null size");
			SetSequence(1);
		}
		if (!SelectBufferSize()) {
			// LogOut << "SelectBufferSize returned 0\n" ;
			TargetAdjustState temp = UpdateSequenceList();
			if (temp > Return) Return = temp ;
			// if (Return > TargetAdjustChange) return Return ;
		}
		return Return ;
	}
	// We only need to increase provider count
	// LogOut << "MissingCount = " << MissingCount << "\n" ;
	TryToBorrow(MissingCount,Seq_Index);
	// LogOut << "MissingCount = " << MissingCount << "\n" ;
	SetValue(Count(Seq_Index)+MissingCount,Seq_Index);
	DataAvailable += MissingCount * OutputPerExecution ;
/*
 *	LogOut << "Incremented DataAvailable by " <<
 *		MissingCount * OutputPerExecution << " to " <<
 *		DataAvailable << "\n" ;
 */
	// Sequence[Seq_Index]+= MissingCount ;
/*
 *	LogOut << "Incremented provider count(" << Seq_Index <<
 *		") by " << MissingCount << " to " << Count(Seq_Index)
 *		<< "\n"  ;
 *	LogOut << "DataAvailable after increasing count is " <<
 *		DataAvailable << "\n" ;
 */
	if (Return < TargetAdjustChange) Return = TargetAdjustChange ;
	return Return ;

}

TargetAdjustState ExecutionSequence::CheckAdjustElement(int i)
{
	// Adjust the consumer count for one pair of entrys if needed.
	// This routine will not change the total count but will
	// decrease the count at one entry and increase it in the next
	// to prevent buffer overflow in the first entry. It trys to
	// to make the first entry as small as possible (ideally 0).
	//
	int ConsumerCount = ConsumerSequence->Count(i);
	TargetAdjustState Return = TargetAdjustOK ;
/*	
 *	LogOut << "CheckAdjustElement(" << i << ") count = " <<
 *		ConsumerCount << "\n" ;
 *
 *	LogOut << "DataAvailable = " << DataAvailable << ", LeftOver = "
 *		<< LeftOver << "\n" ;
 */
	
	int32 InitialDataAvailable = DataAvailable ;
	DataAvailable += Count(i) * OutputPerExecution ;
	DataAvailable -= ConsumerCount * InputPerExecution ;
/*	
 *	LogOut << "Count = " << Count(i) << ", ConsumerCount = " <<
 *		ConsumerCount << ", Available = " << DataAvailable << "\n" ;
 */

	if (DataAvailable >= 0)
		if (DataAvailable < OverlapWords && !OverlapHandled(i)) {
/*
 *		LogOut << "CheckAdjustElement(" << i << ") count = " <<
 *			ConsumerCount << "\n" ;
 *		LogOut << "DataAvailable = " << DataAvailable << ", LeftOver = "
 *			<< LeftOver << "\n" ;
 *		LogOut << "Count = " << Count(i) << ", ConsumerCount = " <<
 *			ConsumerCount << ", Available = " << DataAvailable <<
 *			"\n" ;
 */
		if (!ConsumerCount) return TargetAdjustOK ;
		Return = TargetAdjustMajorChange ;
		int MinCountChange = CountNeeded(-DataAvailable + OverlapWords,
			InputPerExecution);
		int CountChange = MinCountChange ;
		if (GetSize() < i+2) {
			if (!Count(i)) return TargetAdjustOK ;
			Adjustment TheAdjustment(*Obj,
				Adjustment::EnlargeSequence,
				CurrentSize,1,1+CurrentSize,
				BufStat->GetExecutionSequenceIndex());
			TargetAdjustState LocReturn ;
			if (!BufStat->IsForwardFlag()) LocReturn =
				GetNode().AdjustForward(TheAdjustment);
			else LocReturn =
				ConsumerSequence->GetNode().AdjustBackward(
				TheAdjustment);
			if (Return < LocReturn) Return = LocReturn ;
/*
 *			TargetAdjustState temp = SetSequence(i+2);
 *			if (temp > Return) Return = temp ;
 *			temp = ConsumerSequence->SetSequence(i+2);
 *			if (temp > Return) Return = temp ;
 *			if (Return >= TargetAdjustFail) return Return ;
 */
		}
/*
 *		// Try to put all the comsumer count forward on step
 *		int32 DataGeneratedInTwoCounts = InitialDataAvailable +
 *			(Count(i) + Count(i+1)) * OutputPerExecution ;
 *		if (DataGeneratedInTwoCounts > MinCountChange)
 *			DataGeneratedInTwoCounts = MinCountChange ;
 *		int32 ExcessData = DataGeneratedInTwoCounts - OutBufSize ;
 *	
 *		LogOut << "MinChange = " << MinCountChange << ", TwoCounts = "
 *			<< DataGeneratedInTwoCounts << ", Excess = "
 *			<< ExcessData << "\n" ;
 *	
 *		if (ExcessData> 0) {
 *			// Cannot move all the count forward or we will
 *			// overflow the buffer so move only minimum
 *			CountChange = MinCountChange ;
 *			
 *
 *			int ExcessChange = CountNeeded(ExcessData,
 *				InputPerExecution);
 *			CountChange -=ExcessChange ;
 *			if (CountChange < MinCountChange) CountChange =
 *				MinCountChange ;
 *		}
 */
		DataAvailable += CountChange * InputPerExecution ;
/*	
 *		LogOut << "DataAvailable = " << DataAvailable << 
 *			", CountChange = " << CountChange << "\n" ;
 */
	
		BufStat->UpdateState(TargetAdjustChange);
		ConsumerSequence->SetValue(ConsumerCount - CountChange,i);
		ConsumerSequence->SetValue(CountChange +
			ConsumerSequence->Count(i+1),i+1);
	}
	return Return ;
}

TargetAdjustState ExecutionSequence::SlideProviderDataForward()
{
	return TargetAdjustOK ;
}

TargetAdjustState ExecutionSequence::CheckAlignment()
{

/*
 *	We have two constraints to deal with:
 *		1. The provider execution sequence.
 *		2. The consumer execution sequence.
 *		We must make sure the consumer sequence does not
 *		get ahead of the data in the buffer. If it does
 *		we zero pad the provider sequence. If the consumer
 *		sequence runs out of data completely we exit and
 *		allow CheckForUnderflow to handle this.
 */
	// LogOut << "CheckAlignment\n" ;



	// try to move data generation up to where consumption begins
	TargetAdjustState Return = TargetAdjustOK ;
	Return = MakeEqualLength();
	if (Return >= TargetAdjustFail) return Return ;
	TargetAdjustState LocReturn = TargetAdjustOK ;
	if (Return < LocReturn) Return = LocReturn ;
	if (Return >= TargetAdjustFail) return Return ;
	DataAvailable = LeftOver ;
	for (int i = 0; i < CurrentSize;i++) if (Count(i)) break ;
	// Do not adjust if all providers are 0
	if (i < CurrentSize) for (i = 0; i < GetSize(); i++) {
		TargetAdjustState temp = CheckAdjustElement(i);
		if (State.IsError()) return TargetAdjustFail ;
		if (temp > Return) Return = temp ;
	}
	return Return ;
}


TargetAdjustState ExecutionSequence::SetFlushCount(Adjustment& Adjust)
{
/*
 *	LogOut << "ExecutionSequence::SetFlushCount for " << GetNode().GetName()
 *		<< "\n" ;
 */
	DfNodeInLink * LocConsumerInLink = Adjust.GetInLink();
	if (!LocConsumerInLink) DbgError("ExecutionSequence::SetFlushCount",
			"null in link");
	int32 FeederCount = Adjust.GetEnlargeBase() ;
	DfNodeOutLink * LocDriverOutLink =
		LocConsumerInLink->GetDriverOutputChannel();
	if (!LocDriverOutLink) DbgError("ExecutionSequence::SetFlushCount",
			"null out link");
	
	int32 LocInputPerExecution = LocConsumerInLink->GetChunkSize() *
		LocConsumerInLink->GetIncrementIn() ;
	int32 LocOutputPerExecution = LocDriverOutLink->GetChunkSize() *
		LocDriverOutLink->GetIncrementOut() ;
/*
 *	LogOut << "LocInput = " << LocInputPerExecution << ", LocOut = "
 *		<< LocOutputPerExecution << "\n" ;
 */
	int32 FeederOutput = FeederCount * LocOutputPerExecution ;
	int32 FlushCountThisNode = FeederOutput / LocInputPerExecution ;
/*
 *	LogOut << "FeederCount = " << FeederCount << ", FeederOut = " <<
 *		FeederOutput << "\n" ;
 *	LogOut << "FlushCountThisNode = " << FlushCountThisNode << ", for `"
 *		<< GetNode().GetName() << "'.\n" ;
 */
	TargetAdjustState Return = SetFlushCount(FlushCountThisNode,
		LocConsumerInLink);
	if (Return < TargetAdjustFail) Adjust.ChangeBase(FlushCountThisNode);
	return Return ;
}

TargetAdjustState ExecutionSequence::SetFlushCount(int32 Flush_Count,
	DfNodeInLink * LocConsumerInLink)
{
/*
 *	LogOut << "ExecutionSequence::SetFlushCount(" << Flush_Count <<
 *		", InLink) for " << GetNode().GetName() << "\n" ;
 *	LogOut << "FlushCount = " << FlushCount << "\n" ;
 */
	if (FlushCountSet) if (Flush_Count > FlushCount) {
		int chan = LocConsumerInLink->GetNodeInputChannel() ;
		BufStat->SetReason(new ReasonForFailure (
		"cannot consistently flush the buffers",
			GetNode().GetName(),
			-1, chan, ReasonForFailure::Input));
		return TargetAdjustFail ;
	}
	if (Flush_Count <= FlushCount) return TargetAdjustOK ;
	FlushCount = Flush_Count ;
	// LogOut << "SetFlushCount returning change\n" ;
	return TargetAdjustChange ;
}

TargetAdjustState ExecutionSequence::MakeEqualLength()
{
	int ConsumerSize = ConsumerSequence->GetSize();
	if (!ConsumerSize && !GetSize() ||
		(ConsumerSize == GetSize())) return TargetAdjustOK ;
/*
 *	LogOut << "MakeEqualLength ConsumerSze  = " << ConsumerSize <<
 *		", CurrentSize = " << CurrentSize << "\n" ;
 */
	if (ConsumerSize > CurrentSize) {
		if (!CurrentSize) SetSequence(ConsumerSize) ;
		else {
			// LogOut << "Before EnlargeSequence\n" ;
			UpdateStateOut(EnlargeSequence(CurrentSize,
				ConsumerSize-CurrentSize));
		}
	} else {
		int Null = 1 ;
		for (int i = 0 ; i < CurrentSize ; i++) if (Count(i)) {
			Null = 0 ;
			break ;
		}
		if (Null) {
			return UpdateStateOut(ConsumerSequence->EnlargeSequence(
				ConsumerSize, CurrentSize - ConsumerSize)) ;
		}
/*
 *		LogOut <<
 *	"ExecutionSequence::AdjustSequence  enlarging consumer sequence\n";
 *		LogOut << "CurrentSize = " << CurrentSize << ", ConsumerSize = "
 *			<< ConsumerSize << "\n" ;
 */
		Adjustment TheAdjustment(*Obj,
			Adjustment::EnlargeSequence,
				0, CurrentSize-ConsumerSize, CurrentSize,
				BufStat->GetExecutionSequenceIndex());
		TargetAdjustState LocReturn ;
		if (!BufStat->IsForwardFlag()) LocReturn =
			ConsumerSequence->GetNode().AdjustBackward(
			TheAdjustment);
		else LocReturn =
			GetNode().AdjustForward(
			TheAdjustment);
		// LogOut << "MakeEqualLength returning " << LocReturn << "\n" ;
		UpdateStateOut(LocReturn) ;
	}
	return StateOut ;
}

void ExecutionSequence::dump()
{
	if (!Sequence) return ;
	TheLog << "ExecutionSequence::dump, CurrentSize = " << CurrentSize << "\n" ;
	for (int i = 0 ; i < CurrentSize ; i++) {
		TheLog << i << " : " << Sequence[i] << "\n" ;
	}
}
