/*
----
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{<}]
//[ast] [\ensuremath{\ast}]
*/
/*
[1] Class DServer Implementation
\begin{center}
April 2012 Thomas Achmann
November 2010 Tobias Timmerscheidt
\end{center}
[TOC]
0 Description
Implementation of the class ~DServer~
1 Preliminaries
1.1 Includes
*/
#include "DServer.h"
#include "SocketIO.h"
#include "zthread/Mutex.h"
#include "TupleFifoQueue.h"
#include "DBAccessGuard.h"
#include "ThreadedMemoryCntr.h"
/*
1.2 Debug Output
uncoment the following lines for debug output
*/
//#define DS_CMD_CLOSE_WRITE_REL_DEBUG 1
//#define DS_CMD_OPEN_WRITE_REL_DEBUG 1
//#define DS_CMD_WRITE_REL_DEBUG 1
//#define DS_CMD_READ_REL_DEBUG 1
//#define DS_CMD_READ_TB_REL_DEBUG 1
//#define DS_CMD_DELETE_DEBUG 1
/*
1.3 Global Definitions
1.3.1 Variables
*/
//IP-Adress of this system (Master)
string HostIP;
string HostIP_;
/*
1.3.2 Thread Mutex
*/
//Synchronisation of access to Flobs
ZThread::Mutex Flob_Mutex;
//Synchronisation of access to read non relations and write commands
ZThread::Mutex Cmd_Mutex;
/*
2 Implementation
2.1 Static Variables
Initialisation
*/
Word DServer::ms_emptyWord;
/*
2.2 Constructor
* const string[&] inHostName - host name, where the worker runs
* int inPortNumber - port number, where the worker listens to
* ListExpr inType
*/
DServer::DServer(const string& inHostName, int inPortNumber,
string inName, ListExpr inType)
: m_host(inHostName)
, m_port(inPortNumber)
, m_name(inName)
, m_server(NULL)
, m_error(false)
{
m_type = inType;
DBAccess::getInstance() -> NL_ToString(m_type, m_typeStr);
}
/*
2.3 Method ~bool connectToWorker~
connects to a SECONDO instance at a worker host
* returns bool - true: success;
*/
bool
DServer::connectToWorker()
{
//StopWatch watch;
string line;
m_server = Socket::Connect( getServerHostName(), getServerPortStr(),
Socket::SockGlobalDomain,
10,
1);
if(getServer()!=0 && getServer()->IsOk())
{
iostream& iosock = getServer()->GetSocketStream();
if (!getServer() -> IsOk())
{
string err = "Faild to establish socket for host ";
err += getServerHostName()+ ":";
err += getServerPort();
err += "!";
setErrorText(err);
}
do
{
getline( iosock, line );
} while (line.empty());
if (!getServer() -> IsOk())
{
string err = "Faild to establish socket for connection to host ";
err += getServerHostName() + ":";
err += getServerPort() + "!";
setErrorText(err);
}
if(line=="")
{
iosock << "" << endl
<< endl // user
<< endl // password
<< "" << endl;
getline( iosock, line );
if( line == "")
{
do
{
getline( iosock, line);
} while(line != "");
}
else
setErrorText("Unexpected response from worker (No )");
}
else
setErrorText("Unexpected response from worker (No )");
}
else
setErrorText("Connection to the worker couldn't be established!");
if (getServer() == 0)
{
// should never happen
// Socket::Connect always returns a pointer!
assert(0);
return false;
}
if (!(getServer() -> IsOk()))
{
cout << "Cannot Connect to Server:"
<< getServerHostName() << ":" << getServerPortStr() << endl;
cout << getServer() -> GetErrorText() << endl;
delete m_server;
m_server = 0;
return false;
} // if (!(server -> IsOk()))
iostream& iosock = getServer()->GetSocketStream();
iosock << "" << endl << "1" << endl
<< "open database distributed" << endl
<< "" << endl;
getline( iosock, line );
if(line=="")
{
do
{
getline( iosock, line );
//cout << " " << line << endl;
/*if (line[line.size() - 1] == '\r')
line.resize(line.size() - 1);*/
if(line.find("ERROR") != string::npos)
{
setErrorText(string("Opening of database \"distributed\" ") +
"on worker failed!");
return false;
}
}
while(line.find("") == string::npos);
}
else
setErrorText("Unexpected response from worker (No )");
HostIP = getServer()->GetSocketAddress();
HostIP_ = "h" + stringutils::replaceAll(HostIP,".","_");
//cout << "Connection to Worker on " << host << " established." << endl;
//cout << "ConnectTime:"
// << m_host <<":" << port << watch.diffTimes() << endl;
return true;
}
/*
2.4 Method ~void Terminate~
stops the SECONDO instance on the worker
*/
void DServer::Terminate()
{
//cout << "TERMINATE" << endl;
if(getServer() != 0)
{
if (!(getServer()->IsOk()))
{
cout << "Error: Cannot close connection to " << m_host << "!" << endl;
cout << getServer() -> GetErrorText() << endl;
}
else
{
iostream& iosock = getServer()->GetSocketStream();
iosock << "" << endl;
getServer()->Close();
}
delete m_server;
m_server=0;
}
else
{
cout << "ERROR: No Server Running!" << endl;
}
}
/*
2.6 Method ~const string[&] getMasterHostIP const~
* returns const string[&] - the host TCP/IP adress of the master server
* format: xxx.xxx.xxx.xxx
*/
const string& DServer::getMasterHostIP() const { return HostIP; }
/*
2.7 Method ~const string[&] getMasterHostIP[_] const~
* returns const string[&] - the host TCP/IP adress of the master server
* format: hxxx[_]xxx[_]xxx[_]xxx
*/
const string& DServer::getMasterHostIP_() const { return HostIP_; }
/*
2.10 Method ~bool Multiply~
multiplys the SECONDO instances at the worker. This is used to
store data of multiple darray indexes at one worker
* int count - number of additional instances
* returns bool - true: success
*/
bool DServer::Multiply(int count)
{
//cout << "MULTIPLY" << endl;
if(getNumChilds() > 0)
return false;
if(count < 1)
{
m_childs.clear();
return true;
}
for(int i = 0;i connectToWorker()))
return false;
}
catch(const exception &e)
{
cout << "Error starting DServer on "
<< getServerHostName() << ":" << getServerPortStr() << endl;
return false;
}
}
return true;
}
/*
2.11 Method ~void DestroyChilds~
stops workers created by the ~Multiply~ method
*/
void DServer::DestroyChilds()
{
//cout << "DESTROY" << endl;
for(int i = 0;iTerminate();
delete m_childs[i];
m_childs[i] = NULL;
}
}
m_childs.clear();
}
/*
2.12 Method ~bool checkServer~
performs a check on the worker
* bool writeError - writes an error to stderr
* returns bool - true: success
*/
bool
DServer::checkServer(bool writeError) const
{
if (m_server == 0)
{
if (writeError)
cerr << "ERROR: Not connected to worker on "
<< getServerHostName() << ":" << getServerPortStr() << endl;
return false;
}
if(!(m_server->IsOk()))
{
if (writeError)
cerr << "ERROR: Could not establish connection to worker on "
<< getServerHostName() << ":" << getServerPortStr() << endl;
return false;
}
if ((unsigned int)getNumChilds() != m_childs.size())
{
if (writeError)
cerr << "ERROR: Workers are not setup correctly, restart cluster"
<< endl;
return false;
}
return true;
}
/*
2.13 Method ~void print~
*/
void DServer::print() const
{
cout << (unsigned long)(this) << " : " << " "
<< getServerHostName() << " " << getServerPortStr() << endl;
}