// JapX001.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "JapX001.h"
#include <ios>
#include <fstream>


#ifdef _DEBUG
#define new DEBUG_NEW
#endif



CWinApp theApp;

using namespace std;

////////////

class CMyExc : public CException{
public:
	const CString Text;
	CMyExc(LPCTSTR S);
};
class CJapXWConstrait{
	const static char MAX_I=50, MAX_J=50;
	

	char IVals [MAX_J];
	char JVals [MAX_I];
	char ILen,JLen;
	char IfMask;
	char MaskLen;
	char Mask [MAX_J];
public :
	int i;
	static const unsigned int SERIAL_LENGTH=MAX_I+MAX_J+2+1+1+MAX_J;

	void FromSerial(char *b);
	CJapXWConstrait();
	CJapXWConstrait(ifstream &ifsF);
	/*CJapXWConstrait(CJapXWConstrait &src){
		for(int i=0;i<MAX_I;i++){
			IVals[i]=src.IVals[i];
		}
		for(int i=0;i<MAX_J;i++){
			JVals[i]=src.JVals[i];
			Mask[i]=src.Mask[i];
		}
		ILen=src.ILen;
		JLen=src.JLen;
			MaskLen=src.MaskLen;

	};*/

	void LoadMask(char *mask, char len);
	void ToSerial(char *b);
	friend class CJapXW;
};
class CJapXW{
	const static char MAX_I=50, MAX_J=50;
	char val[MAX_I][MAX_J];
	CJapXWConstrait Constrait;
public:
	static const unsigned int SerialLength=CJapXWConstrait::SERIAL_LENGTH+MAX_I*MAX_J;
	void ToSerial(char *b);
	void FromSerial(char *b);
	CJapXW(CJapXWConstrait &c);
	bool Iterate();
	bool IfFit();
	void FormatOutput(CString *S);
};
class CClient{
	bool IfConnected;
	const HANDLE hPipe;
	char Buf[CJapXW::SerialLength];
	ofstream ofsLog;
	ofstream ofsSolLog;
public:
	~CClient();
	void Connect();
	CClient(HANDLE phPipe);
	void TransmitData(CJapXW *JX,bool IfStopServer);
	void Disconnect();
	void Run(CJapXW *JX,bool IfStopServer);
};
class CServer{
public:
	const static char MSG_SOLUTION_NEXT_FOLLOWS='A';
	const static char MSG_SOLUTION_LAST_SEND='B';
	const static char MSG_CMD_RESUME='C';
	const static char MSG_CMD_STOP='D';	

	const static char BASE_PIPE_NAME[];

private:
	CString RealPipeName;
	bool ifConnected;
	HANDLE hPipe;	
	char Buf[CJapXW::SerialLength];

	ifstream &ifsParams;
	ofstream &ofsLog;


	void CreateAndConnect();
	void ReceiveSubTask(CJapXW &W);

	void TransmitSolution(CJapXW &W);
	bool ReportSubTaskEnd();
	void WaitForData();
	void Disconnect();
public:	
	CServer(ifstream &pifsParams,ofstream &pofsLog);
	~CServer();
	void Run();
};



class CThreadParams{
public:
	CJapXWConstrait *Task;
	unsigned int i;
	HANDLE *PipeHandles;
	unsigned int ReallyPipes;
	unsigned int NumOfQuants;
};
class CSolver{
	CJapXWConstrait Task;
	const static unsigned int AbsMaxPipes=10;

	HANDLE PipeHandles[AbsMaxPipes];
	CThreadParams ThParams[AbsMaxPipes];

	unsigned int ReallyPipes;
	ifstream &ifsParams;
	ofstream &ofsLog;
	unsigned int NumOfQuants;
	unsigned int QuantRemainer;

public:
	CSolver(ifstream &pifsParams,ofstream &pofsLog,CJapXWConstrait cnt/*,unsigned int n*/);
	void ConnectPipes();
	HANDLE UseSinglePipe(CThreadParams *thP);
	void UsePipes();
//	LPTHREAD_START_ROUTINE PipeThread(LPVOID lpvParam);
};
class CJapXApp{
	const static char FILENAME_PARAMS[];
	const static char FILENAME_LOG[];
	const static char FILENAME_TASK[];
	const static char FILENAME_SOLUTIONS[];

	ifstream ifsParams;		
	ofstream ofsLog;
	ifstream ifsTask;
	ofstream ofsSolutions;

	bool ifServer;

	void LoadParams();

public:
	void Run();
	CJapXApp();
	~CJapXApp();
	bool GetIfServer();
};



//params
const  char CJapXApp::FILENAME_PARAMS[]="params.txt";
const  char CJapXApp::FILENAME_LOG[]="log.txt";
const  char CJapXApp::FILENAME_TASK[]="task.txt";
const  char CJapXApp::FILENAME_SOLUTIONS[]="solutions.txt";
const char CServer::BASE_PIPE_NAME[]="paispipe";

CMyExc :: CMyExc(LPCTSTR S):Text(S){
	return;
}


void CJapXWConstrait::FromSerial(char *b){
	int j=0,i=0;
	for ( i=0; i<MAX_J; i++){
		IVals[i]=b[j+i];
	}
	j+=i;
	for ( i=0; i<MAX_I; i++){
		JVals[i]=b[j+i];
	}
	j+=i;
	ILen=b[j+0];
	j++;
	JLen=b[j+0];
	j++;
	IfMask=b[j+0];
	j++;
	MaskLen=b[j+0];
	j++;
	for ( i=0; i<MAX_J; i++){
		Mask[i]=b[j+i];
	}
	j+=i;
	if((j)!=SERIAL_LENGTH){
		throw (new CMyExc("!?!?"));
	}
}
CJapXWConstrait::CJapXWConstrait(){
	return;
}
CJapXWConstrait::CJapXWConstrait(ifstream &ifsF):ILen(0),JLen(0),IfMask(0){
	int i=0;
	int t=0;
	/*ifstream ifsF;
	ifsF.open(S);
	*///CFile in;
	MaskLen=0;

	//CFileException e;
	/*if(!in.Open(S,CFile::modeRead, &e)){
	TCHAR szError[1024];
	e.GetErrorMessage(szError, 1024);
	throw (new CMyExc( "Couldn't open constraits file"));			
	}*/
	//char c;
	//char buf[11]={'0','0','0',0};
	//		int i=0;
	int L=0;
	//		int res[2]={0,0};
	/*while (in.Read(&c,1)){
	cout<<"<"<<(int)c<<" - "<<c<<">\n";
	}*/
	while ((L==0)||(L<JLen+ILen+2)){
		if(!ifsF.good()){
			throw(new CMyExc("Bad constraits file\n"));
		}
		t=-1;
		ifsF>>t;
		if(t<0){
			throw(new CMyExc("Negative input\n"));
		}

		//buf[3]=0;
		//if(/*c!='\n'&&*/c<='9'&&c>='0'&&i<=9){
		//	cout<<"c="<<c<<"\n";
		//	buf[i]=c;
		//	i++;
		//}else if(c==13){
		//	//			in.Read(&c,1);
		/*int i=atoi(buf);
		cout<<"i="<<i<<"\n";*/

		if(L==0){
			ILen=t;
		}else if(L==1){
			JLen=t;
		}else if(L<ILen+2){
			IVals[L-2]=t;
		}else if(L<JLen+ILen+2){
			JVals[L-ILen-2]=t;
		}else{
			throw(new CMyExc("Incorrect input file"));
		}
		/*	for ( int i=0;i<=9;i++){
		buf[9-i]='0';
		}*/
		L++;
		//i=0;
		//}else{
		//	i=0;
		//	//				cout<<"i="<<i<<"\n";
		//	//throw(new CMyExc("Incorrect input file: uncnown symbol"));
		//}
	}
	//ifsF.close();
}
void CJapXWConstrait::LoadMask(char *mask, char len){
	MaskLen=len;
	for (int i=0;i<MaskLen;i++){
		Mask[i]=mask[i];
	}
	IfMask=1;
}
void CJapXWConstrait::ToSerial(char *b){
	int j=0,i=0;
	for ( i=0; i<MAX_J; i++){
		b[j+i]=IVals[i];
	}
	j+=i;
	for ( i=0; i<MAX_I; i++){
		b[j+i]=JVals[i];
	}
	j+=i;
	b[j+0]=ILen;
	j++;
	b[j+0]=JLen;
	j++;
	b[j+0]=IfMask;
	j++;
	b[j+0]=MaskLen;
	j++;
	for ( i=0; i<MAX_J; i++){
		b[j+i]=Mask[i];
	}
	j+=i;
	if((j)!=SERIAL_LENGTH){
		throw (new CMyExc("!?!?"));
	}
}

void CJapXW::ToSerial(char *b){

	int j=0,i=0;
	Constrait.ToSerial(b);
	for ( i=0; i<MAX_I; i++){
		for (j=0; j< MAX_J;j++){
			b[CJapXWConstrait::SERIAL_LENGTH+i*MAX_J+j]=val[i][j];
		}
	}
}
void CJapXW::FromSerial(char *b){

	int j=0,i=0;
	Constrait.FromSerial(b);
	for ( i=0; i<MAX_I; i++){
		for (j=0; j< MAX_J;j++){
			val[i][j]=b[CJapXWConstrait::SERIAL_LENGTH+i*MAX_J+j];
		}
	}
}
CJapXW::CJapXW(CJapXWConstrait &c): Constrait(c){
	for (int i=0;i<Constrait.ILen;i++){
		for (int j=0; j<Constrait.JLen; j++){
			val[i][j]=0;
		}
	}
	if(Constrait.IfMask){
		for (int i=0;i<Constrait.MaskLen;i++){
			val[0][i]=Constrait.Mask[i];
		}
	}

}
bool CJapXW::Iterate(){
	char Carry=1;
	for (int i=(Constrait.MaskLen==Constrait.JLen?1:0);(i<Constrait.ILen)&&Carry;i++){
		for (int j=(i?0:Constrait.IfMask?(Constrait.MaskLen==Constrait.JLen?0:Constrait.MaskLen):0); (j<Constrait.JLen)&&Carry; j++){
			if (val[i][j]==1){
				val[i][j]=0;
				Carry=1;
			}else{
				val[i][j]=1;
				Carry=0;
			}
		}
	}
	if(Carry){
		return 0;
	}else {
		return 1;
	}
}
bool CJapXW::IfFit(){
	char IVals [MAX_J];
	char JVals [MAX_I];
	for (int i=0;(i<Constrait.ILen);i++){
		for (int j=0; (j<Constrait.JLen); j++){
			IVals[j]=0;
			JVals[i]=0;
		}
	}
	for (int i=0;(i<Constrait.ILen);i++){
		for (int j=0; (j<Constrait.JLen); j++){
			IVals[j]+=val[i][j];
			JVals[i]+=val[i][j];
		}
	}
	for (int i=0;(i<Constrait.ILen);i++){
		if(JVals[i]!=Constrait.JVals[i]){
			return false;
		}
	}
	for (int j=0; (j<Constrait.JLen); j++){
		if(IVals[j]!=Constrait.IVals[j]){
			return false;
		}
	}
	return true;
}
void CJapXW::FormatOutput(CString *S){
	S->Format("");
	CString A(""),B(""),C("");
	for (int i=0;(i<Constrait.ILen+1);i++){
		//			B.Format("str #%i:",i);
		B.Format("");
		for (int j=0; (j<Constrait.JLen+1); j++){
			if(i==0){
				if(j==0){
					A.Format("%03i\t",(int)0);
				}else{
					A.Format("%03i\t",(int)Constrait.IVals[j-1]);
				}
			}else {
				if(j==0){
					A.Format("%03i\t",(int)Constrait.JVals[i-1]);
				}else{
					A.Format("%01i\t",(int)val[i-1][j-1]);
				}
			}
			B=B+A;
		}
		A.Format("\n");
		B=B+A;
		C=C+B;
	}
	S->Format((LPCTSTR)C);
	return;
}


CClient::CClient(/*LPCTSTR S,*/HANDLE phPipe)
:hPipe(phPipe)
//,PipeName(S)
//		,pfOut()
//		,Tmp("")
{
	IfConnected=false;
	CString Tmp("");
	Tmp.Format("%08X_log.txt",hPipe);
    ofsLog.open((LPCTSTR)Tmp,ios_base::app);
	Tmp=Tmp+"This is a solve client thtread log:\n\n";
	ofsLog<<Tmp;
	Tmp.Format("%08X_sol.txt",hPipe);
	ofsSolLog.open((LPCTSTR)Tmp,ios_base::app);
	Tmp=Tmp+" This is a solve client thtread solution log:\n\n";
	ofsSolLog<<Tmp;

	//CFile in;
	//int i=0;
	//CFileException e;
	//if(!in.Open(S,CFile::modeRead, &e)){
	//	TCHAR szError[1024];
	//	e.GetErrorMessage(szError, 1024);
	//	throw (new CMyExc( "Couldn't open constraits file"));			
	//}
	//char c;
	//char buf[4]={'0','0','0',0};
	////		int L=0;
	//while (in.Read(&c,1)){

	//	buf[3]=0;
	//	if(c<='9'&&c>='0'&&i<=3){

	//		buf[i]=c;
	//		i++;
	//	}else {
	//		int i=atoi(buf);
	//		RealPipeName.Format("%03i",i);
	//		RealPipeName=BasePipeName+RealPipeName;
	//		break;
	//	}
	//}
	//in.Close();
	//cout<<RealPipeName<<'\n';
}
CClient::~CClient(){
	ofsLog<<"~CCLient\n";
	ofsLog.flush();
	//ofsLog.close();
	//ofsSolLog.close();
}
void CClient::Connect(){		
	if(hPipe!=INVALID_HANDLE_VALUE){
//		cout<<"pipe opened:"<<hPipe<<"\n";
		ofsLog<<"pipe opened:\n";
		IfConnected=true;
	}else {
		throw  new CMyExc("found pipe not opened:");
	}
	return ;
}
void CClient::TransmitData(CJapXW *JX,bool IfStopServer){
	JX->ToSerial(Buf);

	CJapXWConstrait x;
	CJapXW cjxwTmp(x);

	DWORD i=0;
	int r=0;
	//CString S;

	/*Tmp.Format("");
	Tmp=Tmp+"sendung data\n";
	pfOut.Write((LPCTSTR)Tmp,Tmp.GetLength());*/


	/*JX->FormatOutput(&S);
	cout<<S<<"\n";
	*//*Tmp.Format("");
	Tmp=Tmp+S+"\n";
	pfOut.Write((LPCTSTR)Tmp,Tmp.GetLength());*/


	r=WriteFile(hPipe,Buf,CJapXW::SerialLength,&i,0);
	FlushFileBuffers(hPipe);
	do{
		r=ReadFile(hPipe,Buf,1,&i,0);
		if(Buf[0]==CServer::MSG_SOLUTION_NEXT_FOLLOWS){
			r=ReadFile(hPipe,Buf,CJapXW::SerialLength,&i,0);
			if(i!=CJapXW::SerialLength){
				throw new CMyExc("incorrect read length");
			}
			cjxwTmp.FromSerial(Buf);
			CString A;
			cjxwTmp.FormatOutput(&A);
			ofsSolLog<<"New Solution Found:\n";
			ofsSolLog<<A;
			//cout<<"\n new solvation found\n"<<A;
			//		Tmp.Format("");
			/*		Tmp=Tmp+"\n new solvation found\n"+A;
			pfOut.Write((LPCTSTR)Tmp,Tmp.GetLength());*/

		}else if(Buf[0]==CServer::MSG_SOLUTION_LAST_SEND){
			if(IfStopServer){
				Buf[0]=CServer::MSG_CMD_STOP;
				r=WriteFile(hPipe,Buf,1,&i,0);
				FlushFileBuffers(hPipe);
			}else{
				Buf[0]=CServer::MSG_CMD_RESUME;
				r=WriteFile(hPipe,Buf,1,&i,0);
				FlushFileBuffers(hPipe);
			}
			
			/*CloseHandle(hPipe);*/
			//cout<<"server stopped\n";
			/*Tmp.Format("");
			Tmp=Tmp+"server stopped\n";
			pfOut.Write((LPCTSTR)Tmp,Tmp.GetLength());*/
			return;
		}else {
			throw  new CMyExc("incorrect cmd\n");
		}
	}while(1);
}

void CClient::Disconnect(){
	if(IfConnected){
		IfConnected=false;
	}
}
void CClient::Run(CJapXW *JX,bool IfStopServer){
	try{
		ofsLog<<"RunStarted:\nIfStopServer"<<IfStopServer<<"\n";
		ofsLog.flush();
		Connect();
		ofsLog<<"Connect();\n";
		ofsLog.flush();
		TransmitData(JX,IfStopServer);
		ofsLog<<"TransmitData(JX,IfStopServer);\n";
		ofsLog.flush();
		Disconnect();
		ofsLog<<"Disconnect();\n";
		ofsLog.flush();
	}catch(CMyExc *e){
		ofsLog<<"!!!"<<e->Text;
		ofsLog.flush();
	}
}


void CServer::CreateAndConnect(){

	SECURITY_ATTRIBUTES sa ={0};
	SECURITY_DESCRIPTOR sd={0};
	InitializeSecurityDescriptor( 
		&sd,
		SECURITY_DESCRIPTOR_REVISION);

	SetSecurityDescriptorDacl( 
		&sd, 
		TRUE, 
		NULL, 
		FALSE);
	sa.bInheritHandle =false;
	sa.lpSecurityDescriptor =&sd;
	sa.nLength =sizeof( sa);

	hPipe=CreateNamedPipe((LPCTSTR)RealPipeName,
		PIPE_ACCESS_DUPLEX|FILE_FLAG_WRITE_THROUGH,       // read/write access 
		PIPE_TYPE_BYTE |       
		PIPE_READMODE_BYTE |   
		PIPE_WAIT,                // blocking mode 
		PIPE_UNLIMITED_INSTANCES, //!!
		10000,                  // output buffer size 
		10000,                  // input buffer size 
		NMPWAIT_WAIT_FOREVER,// NMPWAIT_USE_DEFAULT_WAIT, // client time-out 
		&sa);           

	if(hPipe!=INVALID_HANDLE_VALUE){
		cout<<"Create pipe succeded\n";
		if((ConnectNamedPipe(hPipe, NULL) ?    TRUE : (GetLastError() == ERROR_PIPE_CONNECTED))){
			ifConnected=true;
			ofsLog<<"Named pipe created:"<<RealPipeName<<"\n";
			return;
		}
	}
	throw (new CMyExc ("Create pipe failed\n"));
	return ;
}

void CServer::ReceiveSubTask(CJapXW &W){
	DWORD i=0;
	int r=0;
	CString S("");
	r=ReadFile(hPipe,Buf,CJapXW::SerialLength,&i,0);
	if(i!=CJapXW::SerialLength){
		throw (new CMyExc("Incorrect read\n"));
	}			

	W.FromSerial(Buf);		

	W.FormatOutput(&S);
	//cout<<"data received:\n"<<S<<"\n";
}

void CServer::TransmitSolution(CJapXW &W){
	DWORD i=0;
	int r=0;
	CString S("");

	W.ToSerial(Buf);

	r=WriteFile(hPipe,&MSG_SOLUTION_NEXT_FOLLOWS,1,&i,0);
	r=WriteFile(hPipe,Buf,CJapXW::SerialLength,&i,0);
	FlushFileBuffers(hPipe);

	W.FormatOutput(&S);
	//cout<<"\nNew solution found:\n"<<S<<"\n";
}

bool CServer::ReportSubTaskEnd(){
	DWORD i=0;
	int r=0;

	r=WriteFile(hPipe,&MSG_SOLUTION_LAST_SEND,1,&i,0);
	FlushFileBuffers(hPipe);
	//cout<<"subtask ended\n";

	r=ReadFile(hPipe,Buf,1,&i,0);
	switch(Buf[0]){
		case MSG_CMD_RESUME:
			return true;
		case MSG_CMD_STOP:
            cout << "MSG_CMD_STOP received\n";
			return false;
		default:
			throw (new CMyExc("Unknown request to MSG_LAST_SOLUTION_SEND\n"));
	}
}

void CServer::WaitForData(){		
	do{
		CJapXWConstrait C;
		CJapXW W(C);
		ReceiveSubTask(W);	
		while (W.Iterate()){
			if(W.IfFit()){
				TransmitSolution(W);
			}
		}			
	}while(ReportSubTaskEnd());
}

void CServer::Disconnect(){
	if(ifConnected){
		FlushFileBuffers(hPipe);
		DisconnectNamedPipe(hPipe);
		CloseHandle(hPipe);
	}
}


CServer::CServer(ifstream &pifsParams,ofstream &pofsLog)
:RealPipeName("")
,ifsParams(pifsParams)
,ofsLog(pofsLog)
//	,BASE_PIPE_NAME((LPCTSTR)"A")

{
	cout<<"Server starts.\n";
	char buff[100];
	int i=0;
	DWORD dw=100;
	ifConnected=false;

	CString Base("");
	Base.Format("\\\\.\\PIPE\\%s",BASE_PIPE_NAME);
    ifsParams>>buff;
	if(strcmp(buff,"ServerName:")){
		throw new CMyExc("ServerName: expected\n");
	}
	ifsParams>>i;
	RealPipeName.Format("%03i",i);

	RealPipeName=Base+RealPipeName;
    
	GetComputerName(buff,&dw);
	Base.Format(buff);
    cout<<"Server name is: "<<(LPCTSTR)Base<<"\n";
	cout<<"Server pipe name is: "<<(LPCTSTR)RealPipeName<<"\n";
}
CServer::~CServer(){
	cout<<"Server ends.\n";
}

void CServer::Run(){
	CreateAndConnect();
	WaitForData();
	Disconnect();
}

CSolver::CSolver(ifstream &pifsParams,ofstream &pofsLog,CJapXWConstrait cnt/*,unsigned int n*/)
:ReallyPipes(0)
,ifsParams(pifsParams)
,ofsLog(pofsLog)
,Task(cnt)
//,BasePipeName("\\\\D201-A\\PIPE\\A")
/*,MaxPipes(n)*/{
	
/*if(MaxPipes>AbsMaxPipes){
throw  new CMyExc("Too many pipes requested A\n");
}*/
return;
}
void CSolver::ConnectPipes(){
	CString Tmp("");
	CString RealPipeName("");
	char buff[100]="////";
	int i=0;
	HANDLE hPipe;
	ifsParams>>buff;
	cout<<"buff"<<buff<<"\n";

	if(strcmp(buff,"ServerList:")){			
		throw (new CMyExc ("ServerList expected\n"));
	}
	
	for (int i=0; (i<AbsMaxPipes)&&(ifsParams.good());i++){
		
		
		ifsParams>>buff;
		if(!strcmp(buff,"ServerListEnd")){			
			break;
		}
		ifsParams>>i;

		RealPipeName.Format("\\\\%s\\PIPE\\%s%03i",buff,CServer::BASE_PIPE_NAME,i);                

		hPipe = CreateFile( 
			(LPCTSTR)RealPipeName,   // pipe name 
			GENERIC_READ |  // read and write access 
			GENERIC_WRITE, 
			0,              // no sharing 
			NULL,           // no security attributes
			OPEN_EXISTING,  // opens existing pipe 
			0,              // default attributes 
			NULL
			);          // no template file

		if(hPipe!=INVALID_HANDLE_VALUE){
			cout<<"found pipe: #:"<<hPipe<<" name:"<<RealPipeName<<"\n";

			PipeHandles[ReallyPipes]=hPipe;
			ReallyPipes++;

			CString fileName("");

			fileName.Format("%08X_log.txt",hPipe);
			ofstream oF;
			oF.open((LPCTSTR)fileName);
			oF<<"This pipe name:\n"<<RealPipeName;
			fileName.Format("%08Xh",hPipe);
			oF<<"This pipe handle:\n"<<fileName;
			oF.close();
			
			fileName.Format("%08X_sol.txt",hPipe);
			oF.open((LPCTSTR)fileName);
			oF.close();
			
		}else {
			cout<<"no pipe:"<<(LPCTSTR)RealPipeName<<"\n";
			DWORD dw = GetLastError(); 

			LPVOID lpMsgBuf;
			//				LPVOID lpDisplayBuf;
			if(FormatMessage  (
				FORMAT_MESSAGE_ALLOCATE_BUFFER | 
				FORMAT_MESSAGE_FROM_SYSTEM |
				FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,
				dw,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
				,
				(LPTSTR) &lpMsgBuf,
				0, NULL ))
			{
				CString g;
				g.Format((LPTSTR)lpMsgBuf);
				cout<<"Error:"<<"#"<<dw<<"\n";
				ofsLog<<"Error opening file :"<<"#"<<dw<<g<<"\n";
			}else {
				cout<<"format message failed\n";
			}
		}			



	}

	if(!ReallyPipes){
		throw  new CMyExc("no pipes found\n");
	}
}

void PipeThread(LPVOID lpvParam) {
	CThreadParams &thP= *(CThreadParams*)lpvParam;
	char mask[6]={0,0,0,0,0,0};
	for(unsigned int j=0;(j<thP.NumOfQuants)||((thP.i==thP.ReallyPipes-1)&&j<64);j++){
		unsigned int k=thP.i*thP.NumOfQuants+j;		
		mask[0]=(k>>0)&1;
		mask[1]=(k>>1)&1;
		mask[2]=(k>>2)&1;
		mask[3]=(k>>3)&1;
		mask[4]=(k>>4)&1;
		mask[5]=(k>>4)&1;
		//CJapXWConstrait *tmpCon=new CJapXWConstrait(*(thP.Task));
		CJapXWConstrait tmpCon(*(thP.Task));
		tmpCon.LoadMask(mask,6);
		CJapXW JX(tmpCon);

		CClient A(thP.PipeHandles[thP.i]);
        
		if(((j==(thP.NumOfQuants-1))&&(thP.i!=thP.ReallyPipes-1))||((thP.i==thP.ReallyPipes-1)&&k==63)){
			A.Run(&JX,true);
		}else {
			A.Run(&JX,false);
		}
	}
}

HANDLE CSolver::UseSinglePipe(CThreadParams *thP/*,CJapXWConstrait x*/){
	HANDLE hThread;
	DWORD dw;
	
	// Create a thread for this subclient. 
    hThread = CreateThread( 
		NULL,              // no security attribute 
		0,                 // default stack size 
		(LPTHREAD_START_ROUTINE) PipeThread, 
		(LPVOID) thP,    // thread parameter 
		0,                 // not suspended 
		&dw);      // returns thread ID 

    if (hThread == NULL) {
		printf("CreateThread failed"); 
		return NULL;
	} else{
		cout <<"pipe #"<<thP->i<<" usage started \n";
		return (hThread);
	}
		
	
}

void CSolver::UsePipes(){
	//CString RealPipeName;
	HANDLE allTheThreads[AbsMaxPipes];

	NumOfQuants=((64/ReallyPipes)-(64%ReallyPipes));
	QuantRemainer=(64%ReallyPipes);

	for (unsigned int i=0;i<ReallyPipes;i++){
		ThParams[i].i=i;
		ThParams[i].NumOfQuants=NumOfQuants;
		ThParams[i].PipeHandles=PipeHandles;
		ThParams[i].ReallyPipes=ReallyPipes;
		ThParams[i].Task=&Task;

		allTheThreads[i]=UseSinglePipe(&(ThParams[i]));
	//	CloseHandle(PipeHandles[i]);			
	}
	int y=WaitForMultipleObjects(ReallyPipes,allTheThreads,true,INFINITE);
	if((y>=WAIT_OBJECT_0)||(y<=(WAIT_OBJECT_0+ReallyPipes-1))){
		;
		//cout<< "Wait succeded;\n";
	}else{
		cout<< "Wait failed;\n";
		cin.get();
	}
	//Sleep(5000);
	//cout<<"Sleep(5000); ended\n";


	  
	FILETIME CreationTime;
	FILETIME ExitTime;
	FILETIME KernelTime;
	FILETIME UserTime;
	ULARGE_INTEGER uli1,uli2;
	for (unsigned int i=0;i<ReallyPipes;i++){
		GetThreadTimes(
			allTheThreads[i],
			&CreationTime,
			&ExitTime,
			&KernelTime,
			&UserTime);
		uli1.u.LowPart=CreationTime.dwLowDateTime;
		uli1.u.HighPart=CreationTime.dwHighDateTime;
		uli2.u.LowPart=CreationTime.dwLowDateTime;
		uli2.u.HighPart=CreationTime.dwHighDateTime;
		cout<<"Thread #"<<allTheThreads[i]<<"";

		cout<<" time is: "<<((ExitTime.dwLowDateTime-CreationTime.dwLowDateTime)/10000)<<" milliseconds\n";


		CloseHandle(allTheThreads[i]);//	UseSinglePipe(i,x);
		CloseHandle(PipeHandles[i]);			
		;
	}
}


void CJapXApp::LoadParams(){
	char buf[100];
	ifsParams>>buf;
	if(strcmp(buf,"AppType:")){			
		throw (new CMyExc ("AppType: expected\n"));
	}
	ifsParams>>buf;
	if(!strcmp(buf,"server")){
		ifServer=true;
	}else if(!strcmp(buf,"client")){
		ifServer=false;
	}else{
		throw (new CMyExc ("client/server expected\n"));
	}
}


void CJapXApp::Run(){
	DWORD ticks=GetTickCount();
	try{
		LoadParams();
		if(ifServer){
				CServer A(ifsParams,ofsLog);
				A.Run();				
		}else{
			char buf[100];			
			ifsParams>>buf;
			if(strcmp(buf,"ConstraitFileName:")){
				throw new CMyExc("ConstraitFileName: expected\n");
			}
			ifsParams>>buf;
			cout << "constrait file to load : " <<buf<<"\n";
			ifstream cnstrtFile;
			cnstrtFile.open(buf);
			CJapXWConstrait Task(cnstrtFile);
			cnstrtFile.close();
			CSolver A(ifsParams,ofsLog,Task);
			A.ConnectPipes();
			A.UsePipes();
		}
	}catch(CMyExc *e){
		cout<<e->Text;
	}
	ticks=GetTickCount()-ticks;
	cout<<"Run time is:              "<<ticks<<" milliseconds\n";


}
bool CJapXApp::GetIfServer(){
	return ifServer;
}
CJapXApp::CJapXApp():ifServer(false){
	cout<<"Application core starts.\n";
	ifsParams.open(FILENAME_PARAMS);
	ofsLog.open(FILENAME_LOG);
	ifsTask.open(FILENAME_TASK);
	ofsSolutions.open(FILENAME_SOLUTIONS);
	ofsLog<<"Log File Started\n";
	return;
}	
CJapXApp::~CJapXApp(){
	ifsParams.close();
	ofsLog.close();
	ifsTask.close();
	ofsSolutions.close();
	//cin.get();
	cout<<"Application core ended.\n";
	return;
}


int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
		nRetCode = 1;
	}
	else
	{
		do{
			CJapXApp A;
			A.Run();
			if(!A.GetIfServer()){
				break;
			}else{
				cout<<"\nServer restart initiated\n";
			}
		}while(1);
		cout<<"Exit Programm.\n";
		cin.get();
	}
	

	return nRetCode;
}
Соседние файлы в папке JapX001