/*  execseq2.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 "tarnodpar.h"
#include "bufstat.h"

TargetAdjustState ExecutionSequence::EnlargeBuffer(int32 minimum,
	int32 maximum)
{
/*
 *	LogOut << "EnlargeBuffer(" << minimum << ", " << maximum <<
 *		") for " << GetNode().GetName() << "\n" ;
 */
	int32 SizeUse ;
	int32 CurrentBufSize = 0 ;
	
	TargetBufferParameters * BufParam = ConsumerInLink->GetTargetBuffer();
	if (BufParam) CurrentBufSize = BufParam->GetSize();
	// LogOut << "CurrentBufSize = " << CurrentBufSize << "\n" ;
	if (minimum <= CurrentBufSize) return TargetAdjustOK ;
	if ((SizeUse = BufStat->AllowedSize(minimum,maximum))> 0) {
		ConsumerInLink->AdjustTargetBuffer(SizeUse);
		BufParam = ConsumerInLink->GetTargetBuffer();
		// LogOut << "Setting size to " << SizeUse << "\n" ;
		// if (SizeUse < MinAllowedSize) SizeUse = MinAllowedSize ;
		// if (SizeUse > CurrentBufSize) OutBufSize = SizeUse ;
		// else OutBufSize = CurrentBufSize ;
		OutBufSize = BufParam->GetSize();
		// LogOut << "New buf size is " << OutBufSize << "\n" ;
	}
	else {
		// LogOut << "Buffer failure 4 setting reason\n" ;
		BufStat->SetReason(new ReasonForFailure (
			"maximum buffer size is too small to adjust",
			ConsumerInLink->GetOutputNodeName(),
			minimum,
			ConsumerInLink->GetNodeInputChannel(),
			ReasonForFailure::Input,1));
		return TargetAdjustFail ;
	}	
	return TargetAdjustChange ;
}

TargetAdjustState ExecutionSequence::ZeroPadSequence(int& SeqIndex, int& SeqEnd)
{
	// In provider insert 0's starting just before buffer overflows
	// and up to the point where the first consumer value is not 0
	// In consumer insert the same number of 0's just after the
	// first non-zero consumer.

/*
 *	LogOut << "ZeroPadSequence(" << SeqIndex << ", " << SeqEnd<<
 *		")\n" ;
 */
	int Index = SeqIndex ;
	int Increment = 1 ;
	Adjustment TheAdjustment(*Obj, Adjustment::EnlargeSequence,
		Index,Increment,CurrentSize+Increment,
		BufStat->GetExecutionSequenceIndex());
	TargetAdjustState Return = GetNode().AdjustBackward(TheAdjustment);
	if (Return >= TargetAdjustFail) return Return ;

	// TheAdjustment.ChangeBase(TheEnd+1);
	TargetAdjustState LocReturn =
		ConsumerSequence->GetNode().AdjustForward(TheAdjustment) ;
	if (Return < LocReturn) Return = LocReturn ;
	return Return ;
}
/*
 *	// find point where overflow first occurs
 *	int32 RemainingExcess = ExcessData ;
 *	int TheEnd = SeqEnd ;
 *	int32 LocDataAvailable = DataAvailable ;
 *	int i = TheEnd ;
 *	if (CurrentSize == SeqEnd) TheEnd = CurrentSize -1 ;
 *	else {
 *		if (!ConsumerSequence->Count(SeqEnd)) {
 *			TheEnd++ ;
 *			int32 Extra = Count(TheEnd) * InputPerExecution ;
 *			if (!Extra) DbgError(
 *				"ExecutionSequence::ZeroPadSequence",
 *				"no extra");
 *			LocDataAvailable += Extra ;
 *			ExcessData += Extra ;
 *		}
 *	}
 *	for (i = TheEnd; i >= SeqIndex ; i--) {
 *		ExcessData -= Count(i) * InputPerExecution ;
 *		if (ExcessData <= 0) break ;
 *	}
 * 	ComputeDataUsage(-1);
 *	int Increment = TheEnd - i + 1 ;
 *	int Index = i ;
 *	LogOut << "ZeroPadding at " << i - 1 << ", Increment = " << Increment
 *		<< "\n" ;
 *	if (ExcessData > 0) DbgError("ExecutionSequence::ZeroPadSequence",
 *		"cannot clear excess");
 *	if (!i) {
 *		Index = 1 ;
 *		Increment = 1 ;
 *	}
 *
 *	Adjustment TheAdjustment(*Obj, Adjustment::EnlargeSequence,
 *		Index,Increment,CurrentSize+Increment,
 *		BufStat->GetExecutionSequenceIndex());
 *	TargetAdjustState Return = GetNode().AdjustBackward(TheAdjustment);
 *	if (Return >= TargetAdjustFail) return Return ;
 *
 *	LogOut << "ZeroPadding Consumer starting at " << TheEnd+1 << "\n" ;
 *	TheAdjustment.ChangeBase(TheEnd+1);
 *	TargetAdjustState LocReturn =
 *		ConsumerSequence->GetNode().AdjustForward(TheAdjustment) ;
 *	if (Return < LocReturn) Return = LocReturn ;
 * 	ComputeDataUsage(-2);
 *
 *	if (Return < TargetAdjustMajorChange) return TargetAdjustMajorChange ;
 *	return Return ;
 * }
 */

int ExecutionSequence::Decrement(int ExcessCount, int index)
{
	int ToClear = Count(index) ;
	if (ToClear > ExcessCount) ToClear = ExcessCount ;
	SetValue(Count(index)-ToClear,index);
	return ToClear ;
}

void ExecutionSequence::Increment(int SaveExcessCount, int index)
{
	SetValue(Count(index)+SaveExcessCount,index);
/*
 *	LogOut << "Added " << SaveExcessCount << " to "
 *		<< index << " for total of " << Count(index)
 *		<< "\n" ;
 */
}

TargetAdjustState ExecutionSequence::CheckForExcess(int& SeqIndex, int& )
{
/*
 *	LogOut << "CheckForExcess(" << SeqIndex << ", " << SeqEnd <<
 *		") ExcessData = " << ExcessData << "\n" ;
 */
	if (ExcessData <= 0) return TargetAdjustOK ;
	// See if we can expand buffer size
	TargetAdjustState Return = TargetAdjustOK ;
	int DoZeroPad = 1 ;
	if (DataAvailable > 0 && OutBufSize < DataAvailable)
		if (BufStat->AllowedSize(DataAvailable,DataAvailable)> 0)  {
			int32 Save = OutBufSize ;
			// LogOut << "EnlargeBuffer from CheckForExcess\n" ;
			Return = EnlargeBuffer(DataAvailable,DataAvailable);
/*
 *			LogOut << "Buffer " << GetNode().GetName() <<
 *				" enlarged to " << DataAvailable <<
 *				" from " << Save << "\n" ;
 */
			DoZeroPad = 0 ;
	}
	int32 SizeRequired ;
	if (DoZeroPad) {
		int32 TestMax = ConsumerSequence->Count(SeqEnd) ;
		if (!TestMax && CurrentSize > SeqEnd + 1) TestMax =
			ConsumerSequence->Count(SeqEnd+1);
		SizeRequired = OverlapWords + TestMax * InputPerExecution ;
		int32 BadSizeRequired = OverlapWords + TestMax * OutputPerExecution ;
/*
 *		LogOut << "SizeRequired = " << SizeRequired << "\n" ;
 *		LogOut << "BadSizeRequired = " << BadSizeRequired << "\n" ;
 *		LogOut << "OutBufSize = " << OutBufSize << " for " <<
 *			GetNode().GetName() << "\n" ;
 */
		if (SizeRequired > OutBufSize) 
	    	    if (BufStat->AllowedSize(SizeRequired,SizeRequired)> 0) {
			// LogOut << "EnlargeBuffer from CheckForExcess 2\n" ;
			Return = EnlargeBuffer(SizeRequired, SizeRequired);
/*
 *			LogOut << "2:Buffer enlarged to " << SizeRequired
 *				<< "\n" ;
 */
			DoZeroPad = 0 ;
		}
	}
	if (DoZeroPad) {
		int32 SmallSizeRequired = OverlapWords + InputPerExecution * 2 ;
		if (SmallSizeRequired > OutBufSize)
	    	    if (BufStat->AllowedSize(SmallSizeRequired,
			SizeRequired)> 0) {
			Return = EnlargeBuffer(SmallSizeRequired, SizeRequired);
/*
 *			LogOut << "3:Buffer enlarged to " << SizeRequired
 *				<< "\n" ;
 */
			DoZeroPad = 0 ;
		}
	}
	if (DoZeroPad) {
		// Check to see if we can move provider and consumer
		// forward
		int Next = SeqEnd + 1 ;
		if (CurrentSize > Next) if (!Count(Next) &&
			!ConsumerSequence->Count(Next)) {
			int MoveFrom = SeqEnd ;
			int ToMove = Count(MoveFrom) ;
			if (ToMove * OutputPerExecution > ExcessData) {
				ToMove = ExcessData/OutputPerExecution;
				if (ToMove*OutputPerExecution !=
					ExcessData) ToMove++ ;
			}
			SetValue(ToMove,Next);
			SetValue(Count(MoveFrom) - ToMove, MoveFrom);
			if (DataNeeded >= DataAvailable) {
				int32 DataMoved = ToMove * OutputPerExecution;
				ToMove = DataMoved/InputPerExecution;
				int ConsumerCount = ConsumerSequence->
					Count(MoveFrom) ;
				if (ConsumerCount < ToMove)
					ToMove = ConsumerCount ;
				ConsumerSequence->SetValue(ToMove,Next);
				ConsumerSequence->SetValue(ConsumerCount -
					ToMove,MoveFrom);
			}
			DoZeroPad = 0 ;
			if (Return < TargetAdjustMajorChange)
				Return = TargetAdjustMajorChange ;
		}
	}
	if (DoZeroPad) if (CurrentSize > SeqEnd + 1) {
		// LogOut << "Moving excess\n"  ;
		// Move all excess count to next free location
		int ExcessCount = ExcessData / OutputPerExecution ;
		if (ExcessCount * OutputPerExecution != ExcessData)
			ExcessCount++;
		int SaveExcessCount = ExcessCount ;
		int32 ExcessConsumption = ExcessData 
			- DataAvailable + DataNeeded ;
		if (ExcessConsumption < 0) ExcessConsumption = 0 ;
		int ExcessConsumptionCount =
			ExcessConsumption / InputPerExecution;
		if (ExcessConsumptionCount * InputPerExecution !=
			ExcessConsumption) ExcessConsumptionCount ++ ;
		int SaveExcessConsumptionCount = ExcessConsumptionCount ;
		for (int i = SeqEnd; i >= SeqIndex; i--) {
			ExcessCount -= Decrement(ExcessCount,i);
			ExcessConsumptionCount -=
				ConsumerSequence->
				Decrement(ExcessConsumptionCount,i);
		}
		if (ExcessCount || ExcessConsumptionCount) {
			BufStat->SetReason(new ReasonForFailure (
			"cannot eliminate excess",
				GetNode().GetName(), -1 ));
			return TargetAdjustFail ;
			// DbgError("ExecutionSequence::CheckForExcess", "residual excess");
		}
		Increment(SaveExcessCount,SeqEnd+1);
		ConsumerSequence->Increment(SaveExcessConsumptionCount,
			SeqEnd+1);
		DoZeroPad = 0 ;
	}
	if (DoZeroPad) {
		// LogOut << "CheckForExcess DoZeroPad\n";
 		// ComputeDataUsage(-1);
		int Temp = SeqEnd + 1 ;
		Return = ZeroPadSequence(Temp,Temp);
 		// ComputeDataUsage(-2);
	}
/*
 *	LogOut << "ExecutionSequence::CheckForExcess returning " <<
 *		Return << "\n" ;
 */
	if (Return < TargetAdjustMajorChange) return TargetAdjustMajorChange ;
	return Return ;
}

void ExecutionSequence::MakeSpace(int SeqIndex)
{
/*
 *	LogOut << "ExecutionSequence::MakeSpace(" << SeqIndex <<
 *		"), CurrentSize = " << CurrentSize << "\n" ;
 */
	if (SeqIndex <0 || SeqIndex > CurrentSize -1 || Sequence[CurrentSize-1]
		> 0)
		DbgError("ExecutionSequence::MakeSpace","bad index");
	for (int i = CurrentSize - 1 ; i > SeqIndex ; i--)
		Sequence[i] = Sequence[i-1] ;
	Sequence[SeqIndex] = 0 ;
}



TargetAdjustState ExecutionSequence::ComputeDataUsage(int32 InitData)
{
	TargetAdjustState Return = TargetAdjustOK ;
/*
 *	LogOut << "DataUsage for " << GetNode().GetName() << 
 *		" InitData = " << InitData << "\n" ;
 */ 
	int32 TotalWritten = InitData ;
	if (TotalWritten < 0) TotalWritten = 0 ;
	int32 TotalRead = 0 ;
	int MaxSize = ConsumerSequence->GetSize();
	// LogOut << "MaxSize = " << MaxSize << "\n" ;
	if (MaxSize != GetSize()) {
		if (MaxSize < GetSize()) MaxSize = GetSize();
/*
 *		if (MaxSize < GetSize()) MaxSize = GetSize() ;
 *		TargetAdjustState LocReturn = SetSequence(MaxSize);
 *		if (LocReturn > Return) Return = LocReturn ;
 *		LocReturn = ConsumerSequence->SetSequence(MaxSize);
 *		if (LocReturn > Return) Return = LocReturn ;
 */
	}
	// LogOut << "MaxSize = " << MaxSize << "\n" ;
	for (int i = 0 ; i < MaxSize ; i++) {
		int TheCount = CountZero(i) ;
		int ConsumerCount = ConsumerSequence->CountZero(i) ;
		if (!TheCount && !ConsumerCount) continue ;
		TotalWritten += TheCount * OutputPerExecution ;
		TotalRead += ConsumerCount * InputPerExecution ;
/*
 *		LogOut << i << ":" << CountPast(i) << " [" << TotalWritten
 *			<< "] " <<  ConsumerSequence->CountPast(i) <<
 *			" [" << TotalRead << "] {" << TotalWritten - TotalRead
 *			<< "}\n" ;
 */
	}
/*
 *	LogOut << (InitData < 0 ? "XTotals " : "Totals ") <<
 *		GetNode().GetName() <<
 *		" in = " << TotalWritten << ", out = " << TotalRead <<
 *		" (" << OverlapWords << "),  [" << GetSize() << "]\n" ;
 *	LogOut << "Provider sequence = 0x" << hex << (void *) this <<
 *		", for " << GetNode().GetName() << dec << "\n" ;
 *	LogOut << "Consumer sequence = 0x" << hex << (void *) ConsumerSequence
 *		<< ", for " << ConsumerSequence->GetNode().GetName() << dec <<
 *		 "\n" ;
 */
	return Return ;
}

/*
 * static void dump_both(ExecutionSequence * th,
 * 		ExecutionSequence * ConsumerSequence,const char * where)
 *{
 *	LogOut << "After " << where << " this is:\n" ;
 *	th->dump();
 *	LogOut << "\nConsumerSequence is:\n" ;
 *	ConsumerSequence->dump();
 * }
 */

TargetAdjustState ExecutionSequence::AdjustSequence(int32 InitData)
{
	// InitData is data that is already in buffer
	// Make sure consumer and provider sequences are consistent
/*
 *	LogOut << "ExecutionSequence::AdjustSequence(" << InitData
 *		<< ")\n" ;
 */
	StateOut = TargetAdjustOK ;
	BufStat = Obj->GetBufferStatus();
	// MakeEqualLength();

	if (!ConsumerInLink) DbgError("ExecutionSequence::AdjustSequence",
		"no input link");
	// LogOut << "OverlapWords = " << OverlapWords << "\n" ;
	// ComputeDataUsage(InitData);

	if (OverlapWords && ! CurrentSize) {
/*
 *		LogOut <<
 *	"ExecutionSequence::AdjustSequence setting initial for overlap\n";
 */
		Adjustment TheAdjustment(*Obj,
			Adjustment::EnlargeSequence,0,1,1,
			BufStat->GetExecutionSequenceIndex());
		TargetAdjustState LocReturn ;
		if (!BufStat->IsForwardFlag()) LocReturn =
			GetNode().AdjustForward(TheAdjustment);
		else LocReturn =
			ConsumerSequence->GetNode().AdjustBackward(
			TheAdjustment);
		// LogOut << "Adjustment returned " << LocReturn << "\n" ;
		if (UpdateStateOut(LocReturn) >= TargetAdjustFail)
			return StateOut ;
	}


	// Algorithm must insure that buffer does not overflow or underflow
	// for each iteration. If either is detected that the sequence
	// or buffers size is updated to fix discrepancy. Fix can only be
	// done by increasing sizes, never by decreasing them.

	int OuterNotDone = 1 ;
	while (OuterNotDone) {
		LeftOver = InitData ;
		DataAvailable = LeftOver ;
		OuterNotDone = 0 ;
		if (State.IsError()) return TargetAdjustFail ;
		// LogOut << "Before CheckAlignment\n" ;
		switch (UpdateStateOut(CheckAlignment())) {
case TargetAdjustOK:
case TargetAdjustChange:
			break ;
case TargetAdjustMajorChange:
			// LogOut << "NotDone CheckAlignment\n" ;
			OuterNotDone = 1 ;
			break ;
case TargetAdjustFail:
			return StateOut ;
default:
			DbgError("ExecutionSequence::AdjustSequence",
				"bad case in align");
		}
		LeftOver = InitData ;
		DataAvailable = LeftOver ;
		for (int i = 0 ; i < CurrentSize ; i++) {
			int NotDone = 1 ;
			int j = 0 ;
			while (NotDone) {
				if (UpdateStateOut(MakeEqualLength()) >= TargetAdjustFail)
					return StateOut ;
				// dump_both(this,ConsumerSequence,"made equal");
				NotDone = 0 ;
				for (j= i; j< CurrentSize ; j++) {
					if (State.IsError()) return
						TargetAdjustFail ;
/*
 *					LogOut << "Count(" << j << ") = "
 *						<< Count(j) << "\n" ;
 *					LogOut << "ConsumerSequence->Count("
 *						<< j << ") = " <<
 *						ConsumerSequence->Count(j) 
 *						<< "\n" ;
 */
					if (ConsumerSequence->Count(j))
						break ;
				}
				if (j > i) j-- ;
				ComputeConsumptionAndBuffer(i,j);
				// LogOut << "BeforeCheckForExcess\n" ;
				switch (UpdateStateOut(CheckForExcess(i,j)))
				{
case TargetAdjustOK:
case TargetAdjustChange:
					break ;
case TargetAdjustMajorChange:
					// LogOut << "NotDone CheckForExcess\n";
					OuterNotDone = 2 ;
					NotDone = 0 ;
					break ;
case TargetAdjustFail:
					return StateOut ;
default:
					DbgError(
					"ExecutionSequence::AdjustSequence",
						"bad case from excess");
				}
				if (OuterNotDone==2) break ;
				// LogOut << "Before CheckForUnderflow\n";
				switch (UpdateStateOut(CheckForUnderflow(i,j)))
				{
case TargetAdjustOK:
case TargetAdjustChange:
					break ;
case TargetAdjustMajorChange:
					// LogOut<<"NotDone CheckForUnderflow\n";
					OuterNotDone = 2 ;
					NotDone = 0 ;
					continue ;
case TargetAdjustFail:
					return StateOut ;
default:
					DbgError(
					"ExecutionSequence::AdjustSequence",
						"bad case from underflow");
				}
			}
			if (OuterNotDone == 2) break ;
			if (j > i) i = j ;
			LeftOver = DataAvailable - DataNeeded + OverlapWords ;
/*
 *			LogOut << "DataAvailable = " << DataAvailable << "\n" ;
 *			LogOut << "LeftOver = " << LeftOver <<
 *				", DataNeeded = " << DataNeeded <<
 *				", OverlapWords = " << OverlapWords << "\n" ;
 */
		}
	}
	 // LogOut << "Before AdjustSequence exit\n" ;
	// ComputeDataUsage(InitData);
	return StateOut ;
}


TargetAdjustState ExecutionSequence::FlushExcess(int32 ExtraData)
{
/*
 *	LogOut << "ExecutionSequence::FlushExcess(" << ExtraData <<
 *		") for " << GetNode().GetName() << "\n" ;
 */
	if (ExtraData < InputPerExecution) return TargetAdjustOK ;
	int32 WordDelay = ConsumerInLink->GetDelay()*
		ConsumerInLink->GetChunkSize();
	// ComputeDataUsage(WordDelay);
	int32 NewFlushSize = (ExtraData/InputPerExecution);
/*
 *	LogOut << "LeftOver = " << LeftOver <<", ExtraData = "
 *		<< ExtraData << ", InputPer = " <<
 *		InputPerExecution << "\n" ;
 *	LogOut << "NewFlushSize = " << NewFlushSize << "\n" ;
 */
	Adjustment TheAdjustment(*Obj,
		Adjustment::SetFlushSize, NewFlushSize);
	TheAdjustment.SetInLink(ConsumerInLink);
	return ConsumerSequence->GetNode().AdjustForward(
		TheAdjustment);
}

static int32 MinIncBufferSize(int32 Min, int32 Inc)
{
	int Fac = Min / Inc ;
	int32 Return = Fac * Inc ;
	if (Return < Min ) Return += Inc ;
	return Return ;
}

int ExecutionSequence::InitCheck()
{
	if (InitCheckDone) return 1 ;

	int32 Common = GreatestCommonDivisor(InputPerExecution,
		OutputPerExecution);
	int32 Max = InputPerExecution ;
	if (Max < OutputPerExecution) Max = OutputPerExecution ;
	int32 Residual = Max - Common ;
/*
 *	LogOut << "InitCheck Common = " << Common << ", Max = "
 *		<< Max << ", Residual = " << Residual << "\n" ;
 *	LogOut << "For " << GetNode().GetName() << ", IPE = " <<
 *		InputPerExecution << ", OPE = " << OutputPerExecution
 *		<< "\n" ;
 */

	int32 MinOutputBuf = MinIncBufferSize(OverlapWords + InputPerExecution +
		Residual, OutputPerExecution) ;
	int32 MinInputBuf = MinIncBufferSize(OverlapWords + OutputPerExecution +
		Residual, InputPerExecution) ;
	
	int32 MinSize = BufStat->GetMaxSize() ;

	if (MinInputBuf > MinOutputBuf) MinOutputBuf = MinInputBuf ;
/*
 *	LogOut << "MinSize = " << MinSize << ", MinOutputBuff = " <<
 *		MinOutputBuf << "\n" ;
 */

	if (MinOutputBuf > MinSize) {
		// LogOut << "FAILURE\n" ;
		BufStat->SetReason(new ReasonForFailure (
		"maximum buffer is too small to write minimum data required",
			GetNode().GetName(), MinOutputBuf,
			ConsumerInLink->GetNodeInputChannel(),
			ReasonForFailure::Input,1));
		return 0 ;
	}
	InitCheckDone = 1 ;
	return 1 ;
}

TargetAdjustState ExecutionSequence::AdjustInit(DfNodeOut * one_consumer,
	TraverseObject& obj)
{
/*
 *	LogOut << "ExecutionSequence::AdjustInit for " <<
 *		GetNode().GetName() << "\n" ;
 */
	if (State.IsError()) return TargetAdjustFail ;
	OneConsumer = one_consumer ;
	Obj= &obj ;
	InitLinks();
	if (!InitCheck()) {
		// LogOut << "AdjustInit fail \n" ;
		return UpdateStateOut(TargetAdjustFail) ;
	}
	ConsumerSequence = &(OneConsumer->GetNode()->GetTargetParameters()
		->GetInit());
	if (!ConsumerSequence) DbgError("ExecutionSequence::AdjustInit",
		"consumer sequence void");
/*
 *	LogOut << "Delay for the input to node `" <<GetNode().GetName() <<
 *		"'(" << ConsumerInLink->GetDriverNodeName() <<
 *		") is " << ConsumerInLink->GetDelay() << "\n" ;
 */
	int32 WordDelay = ConsumerInLink->GetDelay()*
		ConsumerInLink->GetChunkSize();
	TargetAdjustState Return = AdjustSequence(WordDelay);
	// LogOut << "Back from AdjustSequence(" << WordDelay << ")\n" ;
/*
 *	LogOut << "OverlapWords = " << OverlapWords << ", WordDelay = " <<
 *		WordDelay << "\n" ;
 *	LogOut << "TargetReader = " << TargetReader << "\n" ;
 *	LogOut << "Setting LeftOver to " << LeftOver << " for " <<
 *		GetNode().GetName() << " to " <<
 *		ConsumerSequence->GetNode().GetName() << "\n" ;
 */

	if (LeftOver < OverlapWords - WordDelay) {
		ComputeDataUsage(WordDelay);
		BufStat->SetReason(new ReasonForFailure (
			"left 0ver too small",
			GetNode().GetName(),-1));
		return TargetAdjustFail ;
		// DbgError( "ExecutionSequence::AdjustInit","LeftOver too small");
	}
	int32 ExtraData = LeftOver - OverlapWords + WordDelay ;
	if (Return < TargetAdjustChange &&
		BufStat->GetState() < TargetAdjustChange) {
/*
 *		LogOut << "Init - FlushExcess for " << GetNode().GetName()
 *			<< "\n" ;
 */
		TargetAdjustState LocReturn =  FlushExcess(ExtraData);
		if (Return < LocReturn) Return = LocReturn ;
		if (TargetReader) TargetReader->SetLeftOver(LeftOver);
	}
	// LogOut << "Exiting AdjustInit\n" ;
	UpdateStateOut(Return);
	return Return ;
} 

TargetAdjustState ExecutionSequence::AdjustExecute(DfNodeOut * one_consumer,
	TraverseObject& obj)
{
/*
 *	LogOut << "ExecutionSequence::AdjustExecute for " <<
 *		GetNode().GetName() << ", state is " <<
 *		BufStat->StateToString() << "\n" ;
 *	LogOut << "Consumer is `" << one_consumer->GetNode()->GetName()
 *		<< "'.\n" ;
 */

	if (State.IsError()) return TargetAdjustFail ;
	OneConsumer = one_consumer ;
	Obj= &obj ;
	InitLinks();
	ConsumerSequence = &(OneConsumer->GetNode()->GetTargetParameters()
		->GetExecute());
	if (!ConsumerSequence) DbgError("ExecutionSequence::AdjustExecute",
		"consumer sequence void");
/*
 *	LogOut << "Consumer `" << ConsumerSequence->GetNode().GetName() <<
 *		"' has sequence size " << ConsumerSequence->GetSize() << "\n" ;
 */
	int32 InitData = TargetReader->GetLeftOver();
	int32 WordDelay = ConsumerInLink->GetDelay()*
		ConsumerInLink->GetChunkSize();
/*
 *	LogOut << "InitData = " << InitData << ", OverlapWords = " <<
 *		OverlapWords << ", WordDelay = "
 *		<< WordDelay << "\n" ;
 */
	if (InitData < OverlapWords - WordDelay)
		DbgError("ExecutionSequence::AdjustExecute","bad init data");
	TargetAdjustState Return = AdjustSequence(TargetReader->GetLeftOver());
	int32 ExtraData = LeftOver - OverlapWords + WordDelay ;
	int32 Diff = LeftOver - TargetReader->GetLeftOver() ;
	if (BufStat->IsFlushState()) {
		// LogOut << "Execute - FlushExcess for " << GetNode().GetName()<<"\n" ;
		TargetAdjustState LocReturn =  FlushExcess(ExtraData);
		if (Return < LocReturn) Return = LocReturn ;
		if (Return >= TargetAdjustFail) return Return ;
	} else if (BufStat->IsMultipleState()) {
/*
 *		LogOut << "MultipleProcessing - LeftOver = " << LeftOver <<
 *			", Diff = " << Diff << "\n" ;
 *		LogOut << "Old LeftOver = " << TargetReader->GetLeftOver() <<
 *			"\n" ;
 *		LogOut << "Connecting " << GetNode().GetName() << " to "
 *			<< ConsumerSequence->GetNode().GetName() << "\n" ;
 */
		// need to compute number of times to execute to get same
		// leftover value. Left over includes overlap plus residual
		// from incremental execution counts. 
		
		// We need to find integer to multiply Diff with to get
		// a multiple of InputPerExecution. 

		int32 ExtraData = LeftOver - OverlapWords + WordDelay ;
/*
 *		LogOut << "ExtraData = " << ExtraData << ", LeftOver = "
 *			<< LeftOver << ", WordDelay = " << WordDelay <<
 *			"\n" ;
 */
		if (ExtraData >= InputPerExecution) {
			int chan=ConsumerInLink->GetNodeInputChannel();
			BufStat->SetReason(new ReasonForFailure (
			"cannot flush extra data from all channels",
				GetNode().GetName(),
				-1, chan, ReasonForFailure::Input));
			return TargetAdjustFail ;
		}

		if (Diff) {
			Diff = abs(Diff) ;
			int32 Multiple = LeastCommonMultiple(Diff,
				InputPerExecution);
			int32 Factor = Multiple/Diff ;
/*
 *			LogOut << "Factor = " << Factor << ", Multiple = " <<
 *				Multiple << " for " << GetNode().GetName()
 *				<< "\n" ;
 */
			Adjustment TheAdjustment(*Obj,
			 	Adjustment::EnlargeMultiplier, Factor);
			TargetAdjustState LocReturn =
				GetNode().AdjustForward(TheAdjustment);
			if (Return < LocReturn) Return = LocReturn ;
		}
	} else if (BufStat->IsCheckState()) {
/*
 *		LogOut << "CheckState for " << GetNode().GetName() <<
 *			"Diff = " << Diff << "\n" ;
 */
		if (Diff) {
			TheLog << "LeftOver = " << LeftOver << ", should be "
				<< TargetReader->GetLeftOver() << " in "
				<< GetNode().GetName() << "\n" ;
			DbgError("ExecutionSequence::AdjustExecute",
				"inconsistent LeftOver");
		}
	}
	UpdateStateOut(Return);
	// LogOut << "AdjustExecute returning " << Return << "\n" ;
	return Return ;
} 


void ExecutionSequence::Emit(const char * Type, TraverseObject& obj)
{
	// LogOut << "ExecutionSequence::Emit\n" ;
	if (!CurrentSize || !Sequence) return ;
	// LogOut << "ExecutionSequence::Emit begin\n" ;
	OutTokens& Out = obj.GetOut();
	Out.NewLine();
	Out.NextOut("int ");
	Out.NextConcatToken(GetNode().GetName());
	Out.NextConcatToken(ExecutionSequenceSuffix) ;
	Out.NextConcatToken(Type);
	Out.NextConcatToken("[") ;
	Out.NextConcatToken(GetSize()+1);
	Out.NextOutToken("]") ;
	Out.NextOut("= {");
	Out.NewLine();
	Out.NextOut("\t");
	for (int i = 0 ; i < CurrentSize ; i++) {
		// LogOut << "Outputing entry " << i << " = " << Count(i) << "\n" ;
		Out.NextConcatToken(Count(i));
		Out.NextOutToken(",");
	}
	Out.NextOut("-1");
	Out.NewLine();
	Out.NextOut("};");
	Out.NewLine();
	// LogOut << "ExecutionSequence::Emit exit\n" ;
}

void ExecutionSequence::SetValue(int32 Value, int index)
{
/*
 * 	LogOut << "Setting Count[" << index << "] to " << Value << " for " <<
 *		GetNode().GetName() << "\n" ;
 */
	if (index >= Size()) DbgError("ExecutionSequence::SetValue",
		"bad index");
	Sequence[index] = Value ;
}

