542 lines
11 KiB
C++
542 lines
11 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2012, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
|
//[TOC] [\tableofcontents]
|
|
//[_] [\_]
|
|
//[&] [\&]
|
|
//[x] [\ensuremath{\times}]
|
|
//[->] [\ensuremath{\rightarrow}]
|
|
//[>] [\ensuremath{>}]
|
|
//[<] [\ensuremath{<}]
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
[1] Class DServerCmdCommunication Definition
|
|
|
|
\begin{center}
|
|
April 2012 Thomas Achmann
|
|
\end{center}
|
|
|
|
[TOC]
|
|
|
|
0 Description
|
|
|
|
The class ~DServerCmdCommunication~ is a helper class for communication
|
|
between master and workers. It implements basic communication functinonality
|
|
with another host via an iostream. The socket connection itself
|
|
is established in another class.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
1 Preliminaries
|
|
|
|
1.1 Defines
|
|
|
|
*/
|
|
#ifndef H_DSERVERCMDCOMMUNICATION_H
|
|
#define H_DSERVERCMDCOMMUNICATION_H
|
|
|
|
/*
|
|
1.2 Debug Output
|
|
|
|
uncomment the following line, if debug output should
|
|
be written to stdout
|
|
|
|
*/
|
|
//#define DS_CMD_COMM_DEBUG 1
|
|
|
|
|
|
/*
|
|
1.3 Includes
|
|
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <assert.h>
|
|
|
|
|
|
/*
|
|
|
|
2 Class ~DServerCmdCommunication~
|
|
|
|
*/
|
|
class DServerCmdCommunication
|
|
{
|
|
public:
|
|
|
|
/*
|
|
|
|
2.1 Default Constructor
|
|
|
|
*/
|
|
DServerCmdCommunication()
|
|
: m_iostr(NULL)
|
|
, m_debugMSG ("") {}
|
|
/*
|
|
|
|
2.2 Constructor
|
|
|
|
* const string[&] DBGMSG - adds a string infront of any debug msg
|
|
|
|
*/
|
|
DServerCmdCommunication(const std::string& DBGMSG)
|
|
: m_iostr(NULL)
|
|
, m_debugMSG (DBGMSG) {}
|
|
|
|
/*
|
|
|
|
2.3 Destructor
|
|
|
|
*/
|
|
virtual ~DServerCmdCommunication() {}
|
|
|
|
/*
|
|
|
|
2.4 Method ~bool setStream~
|
|
|
|
* iostream[&] inStream - the stream used for communication
|
|
|
|
* returns true, if stream is usable
|
|
|
|
*/
|
|
|
|
bool setStream(std::iostream &inStream)
|
|
{
|
|
m_iostr = &inStream;
|
|
|
|
if (m_iostr == NULL ||
|
|
!(m_iostr -> good()))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.5 Sending
|
|
|
|
methods for sending data via iostream to remote secondo system
|
|
|
|
2.5.1 Method ~bool sendSecondoCmd~
|
|
|
|
sends a secondo command to the worker.
|
|
|
|
* int inCmdTyp - command type (0 - NetstedList; 1 - cmd line text)
|
|
|
|
* const string[&] inCmd - command for secondo
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
bool sendSecondoCmd(int inCmdType,
|
|
const std::string& inCmd,
|
|
bool inDebugFlag = false)
|
|
|
|
// secondo does not acknowledge tokens!
|
|
{
|
|
assert(inCmdType == 1 || inCmdType == 0);
|
|
|
|
if (inDebugFlag)
|
|
std::cout << "SECONDO SEND:<Secondo>" << std::endl;
|
|
|
|
if (! sendIOS("<Secondo>", false))
|
|
return false;
|
|
|
|
if (inDebugFlag)
|
|
std::cout << "SECONDO SEND:" << inCmdType << std::endl;
|
|
|
|
if (!sendIOS(inCmdType, false) )
|
|
return false;
|
|
|
|
if (inDebugFlag)
|
|
std::cout << "SECONDO SEND:" << inCmd << std::endl;
|
|
|
|
if (!sendIOS(inCmd, false) )
|
|
return false;
|
|
|
|
if (inDebugFlag)
|
|
std::cout << "SECONDO SEND:</Secondo>" << std::endl;
|
|
|
|
if (! sendIOS("</Secondo>", false))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.5.2 Method ~bool sendIOS~
|
|
|
|
sends a tagged line to secondo
|
|
|
|
* const string[&] inOpenTag - opening tag (e.g. '[<]CMD[>]'
|
|
|
|
* const string[&] inLine - line for secondo
|
|
|
|
* const string[&] inCloseTag - closing tag (e.g. '[<]/CMD[>]'
|
|
|
|
* bool reqAck - expect '[<]ACK/[>]' token after sending a line
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool sendIOS(const std::string& inOpenTag,
|
|
const std::string& inLine,
|
|
const std::string& inCloseTag,
|
|
bool reqAck = true)
|
|
{
|
|
if (! sendIOS(inOpenTag, reqAck))
|
|
return false;
|
|
if (! sendIOS(inLine, reqAck))
|
|
return false;
|
|
if (! sendIOS(inCloseTag, reqAck))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.5.3 Method ~bool sendIOS~
|
|
|
|
sends a tagged line to secondo
|
|
|
|
* const string[&] inOpenTag - opening tag (e.g. '[<]CMD[>]'
|
|
|
|
* int inLine - line for secondo
|
|
|
|
* const string[&] inCloseTag - closing tag (e.g. '[<]/CMD[>]'
|
|
|
|
* bool reqAck - expect '[<]ACK/[>]' token after sending a line
|
|
|
|
* returns true: success; false: error
|
|
|
|
*/
|
|
|
|
bool sendIOS(const std::string& inOpenTag,
|
|
int inLine,
|
|
const std::string& inCloseTag,
|
|
bool reqAck = true)
|
|
{
|
|
if (! sendIOS(inOpenTag, reqAck))
|
|
return false;
|
|
if (! sendIOS(inLine, reqAck))
|
|
return false;
|
|
if (! sendIOS(inCloseTag, reqAck))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.5.4 Method ~bool sendIOS~
|
|
|
|
sends a single line to secondo
|
|
|
|
* const string[&] inLine - line for secondo
|
|
|
|
* bool checkRet - expect '[<]ACK/[>]' token after sending a line
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
|
|
bool sendIOS(const std::string& inLine,
|
|
bool checkRet)
|
|
{
|
|
if (m_iostr -> good())
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " SEND1: "
|
|
<< std::endl << inLine << std::endl;
|
|
if (checkRet)
|
|
std::cout << "w/ ACK" << std::endl;
|
|
else
|
|
std::cout << "w/o ACK" << std::endl;
|
|
|
|
#endif
|
|
(*m_iostr) << inLine << std::endl;
|
|
}
|
|
|
|
if (!(m_iostr -> good()))
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " ERROR: stream is not available!"
|
|
<< std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
if (checkRet)
|
|
{
|
|
std::string line;
|
|
getline(*m_iostr, line);
|
|
|
|
if (line.find("<ACK/>") != std::string::npos)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.5.5 Method ~bool sendIOS~
|
|
|
|
sends a single line to secondo
|
|
|
|
* int inLine - line for secondo
|
|
|
|
* bool checkRet - expect '[<]ACK/[>]' token after sending a line
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
bool sendIOS(int inLine,
|
|
bool checkRet)
|
|
{
|
|
if (m_iostr -> good())
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " SEND: "
|
|
<< std::endl << inLine << std::endl;
|
|
if (checkRet)
|
|
std::cout << "w/ ACK" << std::endl;
|
|
else
|
|
std::cout << "w/o ACK" << std::endl;
|
|
#endif
|
|
(*m_iostr) << (int)inLine << std::endl;
|
|
}
|
|
|
|
if (!(m_iostr -> good()))
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " ERROR: stream is not available!"
|
|
<< std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
if (checkRet)
|
|
{
|
|
std::string line;
|
|
getline(*m_iostr, line);
|
|
if (line.find("<ACK/>") != std::string::npos)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.6 Receiving
|
|
|
|
receiving data from a remote secondo system via iostream
|
|
|
|
|
|
2.6.1 Method ~bool receiveIOS~
|
|
|
|
receives a single line from secondo
|
|
|
|
* string[&] outLine - line, which will be received
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
|
|
bool receiveIOS(std::string& outLine)
|
|
{
|
|
if (m_iostr -> good())
|
|
{
|
|
getline(*m_iostr, outLine);
|
|
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " RECIOS: " << std::endl
|
|
<< outLine << std::endl;
|
|
#endif
|
|
if (!(m_iostr -> good()))
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << "ERROR: stream is not available!"
|
|
<< std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
|
|
2.6.2 Method ~bool receiveIOS~
|
|
|
|
expects a certain ~inTag~ from the iostream and stores the data
|
|
in ~outLine~
|
|
|
|
* const string[&] inTag - expected Tag from the remote system
|
|
|
|
* string[&] outLine - line, which will be received
|
|
|
|
* bool reqAck - require acknowledge; send '[<]ACK/[>]' token
|
|
after receiving a line; send '[<]ERROR/[>]' token in case of an error
|
|
|
|
* returns true: success; false: error
|
|
|
|
|
|
*/
|
|
bool receiveIOS(const std::string& inTag,
|
|
std::string& outLine,
|
|
bool reqAck = true)
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << m_debugMSG << " RECIOS: " << std::endl;
|
|
#endif
|
|
const std::string openTag = "<" + inTag + ">";
|
|
const std::string closeTag = "</" + inTag + ">";
|
|
const std::string finishTag = "<" + inTag + "/>";
|
|
|
|
if (m_iostr -> good())
|
|
{
|
|
std::string tagLine;
|
|
if (!receiveIOS(tagLine))
|
|
{
|
|
if (reqAck) sendIOS("<ERROR/>", false);
|
|
return false;
|
|
}
|
|
if (tagLine == finishTag)
|
|
{
|
|
if (reqAck) sendIOS("<ACK/>", false);
|
|
return true; // receive only one tag: <.../>
|
|
}
|
|
else if (tagLine != openTag)
|
|
{
|
|
if (reqAck) sendIOS("<ERROR/>", false);
|
|
return false;
|
|
}
|
|
|
|
if (reqAck) sendIOS("<ACK/>", false);
|
|
|
|
if (!receiveIOS(outLine))
|
|
{
|
|
if (reqAck) sendIOS("<ERROR/>", false);
|
|
return false;
|
|
}
|
|
|
|
if (reqAck) sendIOS("<ACK/>", false);
|
|
|
|
if (!receiveIOS(tagLine))
|
|
{
|
|
if (reqAck) sendIOS("<ERROR/>", false);
|
|
return false;
|
|
}
|
|
if (tagLine != closeTag)
|
|
{
|
|
if (reqAck) sendIOS("<ERROR/>", false);
|
|
return false;
|
|
}
|
|
|
|
if (!(m_iostr -> good()))
|
|
{
|
|
#ifdef DS_CMD_COMM_DEBUG
|
|
if (!m_debugMSG.empty())
|
|
std::cout << "ERROR: stream is not available!"<< std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
if (reqAck) sendIOS("<ACK/>", false);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
2.7 Method ~void SetDebugHeader()~
|
|
|
|
sets the output string of debug output
|
|
|
|
* const string[&] inStr - new debug header string
|
|
|
|
*/
|
|
void SetDebugHeader(const std::string& inStr) { m_debugMSG = inStr; }
|
|
|
|
|
|
std::iostream* rentStream()
|
|
{
|
|
return m_iostr;
|
|
}
|
|
|
|
void restoreStream(std::iostream* inStr) { m_iostr = inStr; }
|
|
|
|
/*
|
|
|
|
2.8 Private Section
|
|
|
|
2.8.1 Private Methods
|
|
|
|
*/
|
|
private:
|
|
// n/a
|
|
|
|
/*
|
|
|
|
2.9 Private Members
|
|
|
|
*/
|
|
// the socket stream
|
|
std::iostream* m_iostr;
|
|
|
|
// debug message header
|
|
std::string m_debugMSG;
|
|
|
|
/*
|
|
|
|
2.10 End of Class
|
|
|
|
*/
|
|
};
|
|
|
|
#endif // H_DSERVERCMDCOMMUNICATION_H
|