5672 lines
147 KiB
C++
5672 lines
147 KiB
C++
|
|
/*
|
||
|
|
----
|
||
|
|
This file is part of SECONDO.
|
||
|
|
|
||
|
|
Copyright (C) 2004, 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] DistributedAlgebra
|
||
|
|
|
||
|
|
April 2012 Thomas Achmann
|
||
|
|
|
||
|
|
November 2010 Tobias Timmerscheidt
|
||
|
|
|
||
|
|
This algebra implements a distributed array. This type of array
|
||
|
|
keeps its element on remote servers, called worker. Upon creation
|
||
|
|
of the array all elements are transfered to the respective workers.
|
||
|
|
The list of workers must be specified in terms of a relation in any
|
||
|
|
operator that gives back a darray.
|
||
|
|
Operations on the darray-elements are carried out on the remote machines.
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
1. Preliminaries
|
||
|
|
|
||
|
|
1.1 Includes
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "Algebra.h"
|
||
|
|
#include "NestedList.h"
|
||
|
|
#include "NList.h"
|
||
|
|
#include "QueryProcessor.h"
|
||
|
|
#include "StandardTypes.h"
|
||
|
|
#include "SecondoCatalog.h"
|
||
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
||
|
|
#include "TypeMapUtils.h"
|
||
|
|
#include "Remote.h"
|
||
|
|
#include "DSecondoMonitorComm.h"
|
||
|
|
#include "DServer.h"
|
||
|
|
#include "DServerManager.h"
|
||
|
|
#include "DServerCmdCopy.h"
|
||
|
|
#include "DServerCmdDelete.h"
|
||
|
|
#include "DServerCmdExecute.h"
|
||
|
|
#include "DServerCmdRead.h"
|
||
|
|
#include "DServerCmdReadRel.h"
|
||
|
|
#include "DServerCmdWrite.h"
|
||
|
|
#include "DServerCmdWriteRel.h"
|
||
|
|
#include "DServerCmdShuffleRec.h"
|
||
|
|
#include "DServerCmdShuffleSend.h"
|
||
|
|
#include "DServerCmdShuffleMultipleConn.h"
|
||
|
|
#include "DServerShuffleSender.h"
|
||
|
|
#include "DServerShuffleReceiver.h"
|
||
|
|
#include "DServerCmdCallBackComm.h"
|
||
|
|
#include "zthread/ThreadedExecutor.h"
|
||
|
|
#include "zthread/Mutex.h"
|
||
|
|
#include "Algebras/FText/FTextAlgebra.h"
|
||
|
|
#include "Algebras/Array/ArrayAlgebra.h"
|
||
|
|
#include "DistributedAlgebra.h"
|
||
|
|
#include "DBAccessGuard.h"
|
||
|
|
#include "StringUtils.h"
|
||
|
|
#include "Symbols.h"
|
||
|
|
#include "Stream.h"
|
||
|
|
#include "ThreadedMemoryCntr.h"
|
||
|
|
#include <sys/timeb.h>
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
using namespace mappings;
|
||
|
|
|
||
|
|
extern NestedList* nl;
|
||
|
|
extern QueryProcessor *qp;
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
3 Auxiliary Functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
//Uses Function from ArrayAlgebra
|
||
|
|
namespace arrayalgebra{
|
||
|
|
void extractIds(const ListExpr,int&,int&);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//Converts int to string
|
||
|
|
string toString_ul(unsigned long i)
|
||
|
|
{
|
||
|
|
std::string s;
|
||
|
|
std::stringstream out;
|
||
|
|
out << i;
|
||
|
|
s = out.str();
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//Creates an unique identifier for a new distributed array
|
||
|
|
string getArrayName(int number)
|
||
|
|
{
|
||
|
|
struct timeval t1;
|
||
|
|
gettimeofday(&t1, NULL);
|
||
|
|
unsigned long tm = t1.tv_sec*1000+t1.tv_usec/1000;
|
||
|
|
string t = toString_ul(tm) + int2Str(number);
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
//Converts a pair (algID typID) to the corresponding
|
||
|
|
//type name (used by converType)
|
||
|
|
ListExpr convertSingleType( ListExpr type)
|
||
|
|
{
|
||
|
|
if(nl->ListLength(type) != 2)
|
||
|
|
return nl->SymbolAtom("ERROR");
|
||
|
|
if(!nl->IsAtom(nl->First(type)) || !nl->IsAtom(nl->Second(type)))
|
||
|
|
return nl->SymbolAtom("ERROR");
|
||
|
|
|
||
|
|
int algID, typID;
|
||
|
|
|
||
|
|
arrayalgebra::extractIds(type,algID,typID);
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
if(algID < 0 || typID < 0) return nl->SymbolAtom("ERROR");
|
||
|
|
|
||
|
|
return nl->SymbolAtom(sc->GetTypeName(algID,typID));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//Converts a numerical type to its text representation
|
||
|
|
ListExpr convertType( ListExpr type, bool isOneElList = false)
|
||
|
|
{
|
||
|
|
ListExpr result,result2;
|
||
|
|
|
||
|
|
//Is it not a type expression but an attribute name?
|
||
|
|
if(nl->ListLength(type) < 2)
|
||
|
|
{
|
||
|
|
if(nl->IsAtom(type) || nl->IsEmpty(type))
|
||
|
|
{
|
||
|
|
return type;
|
||
|
|
}
|
||
|
|
//Only one element that is not atomic
|
||
|
|
else
|
||
|
|
{
|
||
|
|
result = convertType(nl->First(type), true);
|
||
|
|
if (isOneElList)
|
||
|
|
result = nl -> OneElemList(result);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//Single type expression
|
||
|
|
if(nl->ListLength(type) == 2 &&
|
||
|
|
nl->IsAtom(nl->First(type)) &&
|
||
|
|
nl->IsAtom(nl->Second(type)))
|
||
|
|
{
|
||
|
|
result = convertSingleType(type);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
//It's a list with more than three elements, proceed recursively
|
||
|
|
result = convertType(nl->First(type), false);
|
||
|
|
result2 = convertType(nl->Rest(type), false);
|
||
|
|
|
||
|
|
if(nl->ListLength(type) == 2)
|
||
|
|
{
|
||
|
|
return nl->TwoElemList(result,result2);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return nl->Cons(result,result2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool RunCmdPopen(const string& inCmd,
|
||
|
|
string &outResult)
|
||
|
|
{
|
||
|
|
//cout << "RunCmdPopen:" << inCmd << endl;
|
||
|
|
|
||
|
|
bool ret_val = true;
|
||
|
|
FILE *fs;
|
||
|
|
char qBuf[1024];
|
||
|
|
memset(qBuf, '\0', sizeof(qBuf));
|
||
|
|
fs = popen(inCmd.c_str(), "r");
|
||
|
|
|
||
|
|
if (fs == NULL)
|
||
|
|
{
|
||
|
|
perror(("ERROR: Cannot start Command:" + inCmd).c_str());
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
else if (fgets(qBuf, sizeof(qBuf), fs) != NULL)
|
||
|
|
{
|
||
|
|
outResult = string(qBuf);
|
||
|
|
pclose(fs);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
pclose(fs);
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout << "Popen Res:" << ret_val << outResult << endl;
|
||
|
|
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool RunCmdSSH(const string& inHost,
|
||
|
|
const string& inCmd,
|
||
|
|
string &outResult)
|
||
|
|
{
|
||
|
|
string cmd;
|
||
|
|
bool retval = false;
|
||
|
|
if (inHost != "localhost" &&
|
||
|
|
inHost != "127.0.0.")
|
||
|
|
{
|
||
|
|
string tmpCmd = stringutils::replaceAll(inCmd,"$","\\$");
|
||
|
|
cmd = "ssh " + inHost + " \"bash -c '" + tmpCmd + "'\"";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
cmd = "bash -c 'cd ${HOME}; " + inCmd + "'";
|
||
|
|
}
|
||
|
|
|
||
|
|
retval = RunCmdPopen(cmd, outResult);
|
||
|
|
|
||
|
|
return retval;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
4. Type Constructor ~DArray~
|
||
|
|
|
||
|
|
4.2 Implementation of basic functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
//Definition of static variable
|
||
|
|
int DArray::no = 0;
|
||
|
|
|
||
|
|
//Creates an undefined DArray
|
||
|
|
DArray::DArray(bool isDefined)
|
||
|
|
: m_name()
|
||
|
|
{
|
||
|
|
//cout << "C-TOR1" << endl;
|
||
|
|
SetDefined(isDefined);
|
||
|
|
setNoRelType();
|
||
|
|
m_size=0;
|
||
|
|
alg_id=0;
|
||
|
|
typ_id=0;
|
||
|
|
no++;
|
||
|
|
m_serverlist = nl -> TheEmptyList();
|
||
|
|
m_serverManager = NULL;
|
||
|
|
// m_watch.start();
|
||
|
|
//cout << "DArray::DArray():" << no << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
//Creates a defined DArray
|
||
|
|
//A DArray is defined by its name, type, size and serverlist
|
||
|
|
//It can be defined while all its elements are undefined
|
||
|
|
DArray::DArray(ListExpr inType,
|
||
|
|
const string& inName, int s, ListExpr inServerlist)
|
||
|
|
: m_name(inName)
|
||
|
|
{
|
||
|
|
//cout << "C-TOR2" << endl;
|
||
|
|
m_type = inType;
|
||
|
|
|
||
|
|
arrayalgebra::extractIds( m_type, alg_id, typ_id);
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
if(sc->GetTypeName(alg_id,typ_id) == Relation::BasicType())
|
||
|
|
setRelType();
|
||
|
|
else
|
||
|
|
setNoRelType();
|
||
|
|
|
||
|
|
|
||
|
|
m_size = s;
|
||
|
|
|
||
|
|
m_elements = vector<Word>(getSize());
|
||
|
|
m_present = vector<bool>(getSize(), false);
|
||
|
|
|
||
|
|
m_serverlist = inServerlist;
|
||
|
|
m_serverManager =
|
||
|
|
new DServerManager(m_serverlist, m_name,m_type,getSize());
|
||
|
|
|
||
|
|
no++;
|
||
|
|
|
||
|
|
if (!(m_serverManager -> isOk()))
|
||
|
|
SetUndefined();
|
||
|
|
else
|
||
|
|
SetDefined(true);
|
||
|
|
//cout << "DArray::DArray(...):" << no << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
DArray::~DArray()
|
||
|
|
{
|
||
|
|
//cout << "DArray::~DArray:" << no << endl;
|
||
|
|
//cout <<"Time:" << m_watch.diffTimes() << endl;
|
||
|
|
assert(no > 0);
|
||
|
|
no--;
|
||
|
|
//if(IsDefined())
|
||
|
|
{
|
||
|
|
for(int i=0;i< getSize();i++)
|
||
|
|
{
|
||
|
|
//Elements that are present on the master are deleted
|
||
|
|
//note that this deletes NOT the Secondo-objects on the
|
||
|
|
//workers.
|
||
|
|
//they need to be deleted seperately which can be done by
|
||
|
|
//the remove-function
|
||
|
|
if(m_present[i])
|
||
|
|
{
|
||
|
|
//cout << "DEL EL: " << i << endl;
|
||
|
|
|
||
|
|
(am->DeleteObj(alg_id,typ_id))(m_type,m_elements[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
m_present.clear();
|
||
|
|
m_elements.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
delete m_serverManager;
|
||
|
|
m_serverManager = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DArray::remove()
|
||
|
|
{
|
||
|
|
//cout << "DArray::remove()" << endl;
|
||
|
|
if(getServerManager() != NULL )
|
||
|
|
{
|
||
|
|
|
||
|
|
DServerCmdDeleteParam delParam;
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor exec;
|
||
|
|
|
||
|
|
bool ret_val = runCommandThreaded<DServerCmdDelete,
|
||
|
|
DServerCmdDeleteParam>(exec,
|
||
|
|
delParam);
|
||
|
|
|
||
|
|
const int nrOfWorkers = getServerManager()->getNoOfUsedWorkers(getSize());
|
||
|
|
|
||
|
|
for(int i= 0;i<nrOfWorkers;i++)
|
||
|
|
{
|
||
|
|
if (getServerManager()->
|
||
|
|
getServerByID(i) ->
|
||
|
|
hasError())
|
||
|
|
{
|
||
|
|
getServerManager() ->
|
||
|
|
setErrorText(string("Error Worker " +
|
||
|
|
int2Str( i ) + ": " +
|
||
|
|
getServerManager()->getServerByID(i)
|
||
|
|
-> getErrorText()));
|
||
|
|
cerr << "ERROR: Deleting DArray!" << endl;
|
||
|
|
cerr << getServerManager() -> getErrorText() << endl;
|
||
|
|
SetUndefined();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!ret_val)
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not delete data from Worker:" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
//cout << "DArray::remove() ... done" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
const string&
|
||
|
|
DArray::getHostNameByIndex(int inIdx)
|
||
|
|
{
|
||
|
|
DServer* server = getServerManager()->getServerByIndex(inIdx);
|
||
|
|
return server -> getServerHostName();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void DArray::refresh(int i)
|
||
|
|
{
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
if(m_present[i])
|
||
|
|
(am->DeleteObj(alg_id,typ_id))(m_type,m_elements[i]);
|
||
|
|
|
||
|
|
if(isRelType())
|
||
|
|
{
|
||
|
|
m_elements[i].addr =
|
||
|
|
(am->CreateObj(alg_id,typ_id))(m_type).addr;
|
||
|
|
|
||
|
|
DServerCmdReadRelParam readRelParam(&m_elements,
|
||
|
|
&m_present,
|
||
|
|
nl -> Second(getType()));
|
||
|
|
|
||
|
|
ret_val = runCommand<DServerCmdReadRel,
|
||
|
|
DServerCmdReadRelParam>(readRelParam, i);
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DServerCmdReadParam readParam(&m_elements, &m_present, getType());
|
||
|
|
|
||
|
|
ret_val = runCommand<DServerCmdRead,
|
||
|
|
DServerCmdReadParam>(readParam, i);
|
||
|
|
}
|
||
|
|
|
||
|
|
DServer* server = getServerManager() -> getServerByIndex(i);
|
||
|
|
if (!ret_val || server -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not get data from Worker:" << endl;
|
||
|
|
cerr << server -> getErrorText() << endl;
|
||
|
|
m_present[i] = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void DArray::refresh()
|
||
|
|
{
|
||
|
|
//cout << "DArray::refresh S:" << getSize()
|
||
|
|
// << " (Rel:" << isRelType() << ")" << endl
|
||
|
|
// << " T:" << nl -> ToString(getType()) << endl;
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor exec;
|
||
|
|
|
||
|
|
//Elements are deleted if they were present
|
||
|
|
//If the darray has a relation-type new relations must be created
|
||
|
|
assert(m_elements.size() == (unsigned int)getSize());
|
||
|
|
|
||
|
|
for (int i = 0; i < getSize(); ++i)
|
||
|
|
{
|
||
|
|
if(m_present[i])
|
||
|
|
{
|
||
|
|
(am->DeleteObj(alg_id,typ_id))(m_type,m_elements[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(isRelType())
|
||
|
|
{
|
||
|
|
m_elements[i].addr =
|
||
|
|
(am->CreateObj(alg_id,typ_id))(m_type).addr;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
bool success = true;
|
||
|
|
|
||
|
|
if (isRelType())
|
||
|
|
{
|
||
|
|
DServerCmdReadRelParam readRelParam(&m_elements,
|
||
|
|
&m_present,
|
||
|
|
nl -> Second(getType()));
|
||
|
|
|
||
|
|
success = runCommandThreaded<DServerCmdReadRel,
|
||
|
|
DServerCmdReadRelParam>(exec,
|
||
|
|
readRelParam);
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DServerCmdReadParam readParam(&m_elements,
|
||
|
|
&m_present, getType());
|
||
|
|
|
||
|
|
success = runCommandThreaded<DServerCmdRead,
|
||
|
|
DServerCmdReadParam>(exec,
|
||
|
|
readParam);
|
||
|
|
}
|
||
|
|
|
||
|
|
//All elements are present now
|
||
|
|
//cout << "DArray::refresh ...done" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DArray::refresh(TFQ tfqOut, ThreadedMemoryCounter *inMemCntr)
|
||
|
|
{
|
||
|
|
if (!(getServerManager() -> checkServers(true)))
|
||
|
|
{
|
||
|
|
SetUndefined();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor exec;
|
||
|
|
|
||
|
|
//Elements are deleted if they were present
|
||
|
|
//If the darray has a relation-type new relations must be created
|
||
|
|
assert(m_elements.size() == (unsigned int)getSize());
|
||
|
|
assert(isRelType());
|
||
|
|
|
||
|
|
DServerCmdReadRelParam readRelParam(tfqOut, inMemCntr,
|
||
|
|
nl -> Second(getType()));
|
||
|
|
|
||
|
|
bool success =
|
||
|
|
runCommandThreaded<DServerCmdReadRel,
|
||
|
|
DServerCmdReadRelParam>(exec,
|
||
|
|
readRelParam);
|
||
|
|
|
||
|
|
//tfqRefreshDone();
|
||
|
|
|
||
|
|
//dummy element to release collector thread
|
||
|
|
tfqOut -> put(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool DArray::initialize(ListExpr inType,
|
||
|
|
const string& inName, int s,
|
||
|
|
ListExpr inServerlist,
|
||
|
|
const vector<Word> &n_elem)
|
||
|
|
{
|
||
|
|
//cout << "INIT2" << endl;
|
||
|
|
// initializes an undefined array, all
|
||
|
|
// elements are present on the master
|
||
|
|
SetDefined(true);
|
||
|
|
m_type = inType;
|
||
|
|
|
||
|
|
arrayalgebra::extractIds( m_type , alg_id, typ_id);
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
//check if type is relation-type
|
||
|
|
if(sc->GetTypeName(alg_id,typ_id) == Relation::BasicType())
|
||
|
|
{
|
||
|
|
setRelType();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
setNoRelType();
|
||
|
|
}
|
||
|
|
|
||
|
|
m_name = inName;
|
||
|
|
m_size = s;
|
||
|
|
m_serverlist = inServerlist;
|
||
|
|
|
||
|
|
//create DServerManager, and
|
||
|
|
//thereby also the DServer (worker connections)
|
||
|
|
m_serverManager =
|
||
|
|
new DServerManager(m_serverlist, m_name, m_type, getSize());
|
||
|
|
|
||
|
|
//Set the elements-array
|
||
|
|
m_elements = n_elem;
|
||
|
|
m_present = vector<bool>(getSize(), true); // all true
|
||
|
|
|
||
|
|
const int max_servers =
|
||
|
|
getServerManager()->getNoOfUsedWorkers(getSize());
|
||
|
|
|
||
|
|
// the elements to the respective workers
|
||
|
|
ZThread::ThreadedExecutor exec;
|
||
|
|
|
||
|
|
bool success = true;
|
||
|
|
|
||
|
|
if(!isRelType())
|
||
|
|
{
|
||
|
|
|
||
|
|
DServerCmdWriteParam writeParam(&m_elements);
|
||
|
|
|
||
|
|
success = runCommandThreaded<DServerCmdWrite,
|
||
|
|
DServerCmdWriteParam>(exec,
|
||
|
|
writeParam);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DServerCmdWriteRelParam writeRelParam(&m_elements);
|
||
|
|
|
||
|
|
success = runCommandThreaded<DServerCmdWriteRel,
|
||
|
|
DServerCmdWriteRelParam>(exec,
|
||
|
|
writeRelParam);
|
||
|
|
}
|
||
|
|
for(int i= 0;i<max_servers;i++)
|
||
|
|
{
|
||
|
|
if (getServerManager()->
|
||
|
|
getServerByID(i) ->
|
||
|
|
hasError())
|
||
|
|
{
|
||
|
|
getServerManager() ->
|
||
|
|
setErrorText(string("Error Worker " +
|
||
|
|
int2Str( i ) + ": " +
|
||
|
|
getServerManager()->getServerByID(i)
|
||
|
|
-> getErrorText()));
|
||
|
|
cerr << "ERROR: Initialize DArray!" << endl;
|
||
|
|
cerr << getServerManager() -> getErrorText() << endl;
|
||
|
|
SetUndefined();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout <<"Init1:" << m_watch.diffTimes() << endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool DArray::initialize(ListExpr inType,
|
||
|
|
const string& inName,
|
||
|
|
int s,
|
||
|
|
ListExpr inServerlist)
|
||
|
|
{
|
||
|
|
//cout << "INIT1" << endl;
|
||
|
|
//initializes an undefined, no elements are given
|
||
|
|
//all elements must already exist on the workers
|
||
|
|
if (nl -> IsEmpty(inServerlist))
|
||
|
|
{
|
||
|
|
SetDefined(false);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
SetDefined(true);
|
||
|
|
m_type = inType;
|
||
|
|
|
||
|
|
arrayalgebra::extractIds( m_type , alg_id, typ_id);
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
//ceck whether array of relation?
|
||
|
|
if(sc->GetTypeName(alg_id,typ_id) == Relation::BasicType())
|
||
|
|
{
|
||
|
|
setRelType();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
setNoRelType();
|
||
|
|
|
||
|
|
m_name = inName;
|
||
|
|
m_size = s;
|
||
|
|
|
||
|
|
//elements-array is empty, no elements are present on the master
|
||
|
|
m_elements = vector<Word>(getSize());
|
||
|
|
m_present = vector<bool>(getSize(), false); // all false!;
|
||
|
|
|
||
|
|
//creates DServerManager, which creates the
|
||
|
|
//DServer-objects for all workers
|
||
|
|
m_serverlist = inServerlist;
|
||
|
|
m_serverManager =
|
||
|
|
new DServerManager(m_serverlist, m_name,m_type,getSize());
|
||
|
|
//cout <<"Init2:" << m_watch.diffTimes() << endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
const Word& DArray::get(int i)
|
||
|
|
{
|
||
|
|
//returns an element of the elements-array
|
||
|
|
if(IsDefined() && i >=0 && i < getSize())
|
||
|
|
{
|
||
|
|
if (!m_present[i])
|
||
|
|
refresh(i);
|
||
|
|
|
||
|
|
if (!m_present[i])
|
||
|
|
{
|
||
|
|
SetUndefined();
|
||
|
|
cerr << "ERROR: Could not retrieve Element " << i << endl;
|
||
|
|
|
||
|
|
return DServer::ms_emptyWord;
|
||
|
|
}
|
||
|
|
|
||
|
|
return m_elements[i];
|
||
|
|
}
|
||
|
|
// else:
|
||
|
|
|
||
|
|
cerr << "ERROR: ";
|
||
|
|
if (!IsDefined())
|
||
|
|
cerr << "Array is not defined!!";
|
||
|
|
else if ( i < 0 || i >= getSize())
|
||
|
|
cerr << "Index out of scope!!";
|
||
|
|
else
|
||
|
|
cerr << "Element is not present!!";
|
||
|
|
|
||
|
|
cerr << " (Index: " << i << ")" << endl;
|
||
|
|
return DServer::ms_emptyWord;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void DArray::set(Word n_elem, int i)
|
||
|
|
{
|
||
|
|
//sets an element of the array
|
||
|
|
//the element is subsequently written to the corresponding worker
|
||
|
|
vector<int> l;
|
||
|
|
l.push_back(i);
|
||
|
|
|
||
|
|
if(IsDefined())
|
||
|
|
{
|
||
|
|
m_elements[i].addr = n_elem.addr;
|
||
|
|
bool success = false;
|
||
|
|
|
||
|
|
if(!isRelType())
|
||
|
|
{
|
||
|
|
DServerCmdWriteParam writeParam(&m_elements);
|
||
|
|
|
||
|
|
success = runCommand<DServerCmdWrite,
|
||
|
|
DServerCmdWriteParam>(writeParam, i);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DServerCmdWriteRelParam writeRelParam(&m_elements);
|
||
|
|
|
||
|
|
success = runCommand<DServerCmdWriteRel,
|
||
|
|
DServerCmdWriteRelParam>(writeRelParam, i);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!success)
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not send data to Worker:" << endl;
|
||
|
|
cerr << getServerManager()->getServerByIndex(i) -> getErrorText()
|
||
|
|
<< endl;
|
||
|
|
m_present[i] = false;
|
||
|
|
SetUndefined();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//This element is now present on the master
|
||
|
|
m_present[i] = true; //true
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
4.3 In and Out functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
Word DArray::In( const ListExpr inTypeInfo, const ListExpr instance,
|
||
|
|
const int errorPos, ListExpr& errorInfo,
|
||
|
|
bool& correct )
|
||
|
|
{
|
||
|
|
//cout << "DArray::In" << endl;
|
||
|
|
Word e;
|
||
|
|
int algID, typID;
|
||
|
|
|
||
|
|
arrayalgebra::extractIds(nl->Second(inTypeInfo),algID,typID);
|
||
|
|
DArray* a = new DArray(nl->Second(inTypeInfo),
|
||
|
|
getArrayName(DArray::no),
|
||
|
|
nl->ListLength(instance)-1,
|
||
|
|
nl->First(instance));
|
||
|
|
|
||
|
|
ListExpr listOfElements = nl->Rest(instance);
|
||
|
|
ListExpr element;
|
||
|
|
int i = 0;
|
||
|
|
|
||
|
|
do
|
||
|
|
{
|
||
|
|
element = nl->First(listOfElements);
|
||
|
|
listOfElements = nl->Rest(listOfElements);
|
||
|
|
e = ((am->InObj(algID,typID))
|
||
|
|
(nl->Second(inTypeInfo),
|
||
|
|
element,errorPos,errorInfo,correct));
|
||
|
|
|
||
|
|
a->set(e,i);
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
while(!nl->IsEmpty(listOfElements) && correct);
|
||
|
|
|
||
|
|
if(correct)
|
||
|
|
{
|
||
|
|
//cout << " -> OK" << endl;
|
||
|
|
return SetWord(a);
|
||
|
|
}
|
||
|
|
a -> remove();
|
||
|
|
delete a;
|
||
|
|
|
||
|
|
//cout << "-> Error!" << endl;
|
||
|
|
correct=false;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ListExpr DArray::Out( ListExpr inTypeInfo, Word value )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Out" << endl;
|
||
|
|
DArray* a = (DArray*)value.addr;
|
||
|
|
|
||
|
|
if(a == NULL || !(a->IsDefined()))
|
||
|
|
{
|
||
|
|
//cout << " -> ERROR!" << endl;
|
||
|
|
return nl->SymbolAtom(Symbol::UNDEFINED());
|
||
|
|
}
|
||
|
|
if( a -> getServerManager() == NULL ||
|
||
|
|
!(a -> getServerManager() -> checkServers(true)))
|
||
|
|
{
|
||
|
|
return nl->SymbolAtom(Symbol::UNDEFINED());
|
||
|
|
}
|
||
|
|
ListExpr list;
|
||
|
|
ListExpr last;
|
||
|
|
ListExpr element;
|
||
|
|
list = nl->OneElemList(a->getServerList());
|
||
|
|
last=list;
|
||
|
|
|
||
|
|
a->refresh();
|
||
|
|
|
||
|
|
if(a->IsDefined())
|
||
|
|
{
|
||
|
|
for(int i = 0; i<a->getSize();i++)
|
||
|
|
{
|
||
|
|
Word org = (Word)a->get(i);
|
||
|
|
|
||
|
|
if(a->IsDefined())
|
||
|
|
{
|
||
|
|
element = ((am->OutObj(a->getAlgID(),a->getTypID()))
|
||
|
|
(nl->Second(inTypeInfo),
|
||
|
|
org));
|
||
|
|
|
||
|
|
last=nl->Append(last,element);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
assert(0);
|
||
|
|
return nl->SymbolAtom(Symbol::UNDEFINED());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
4.4 Persistent Storage Functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
Word DArray::Create( const ListExpr inTypeInfo )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Create" << endl;
|
||
|
|
return SetWord(new DArray());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//Note: The Delete-function deletes the
|
||
|
|
//entire DArray, therefore the remote
|
||
|
|
//obejcts are delete and thereafter the local
|
||
|
|
//data structure. The Close-function only
|
||
|
|
//removes the local data structure
|
||
|
|
|
||
|
|
void DArray::Delete( const ListExpr inTypeInfo, Word& w )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Delete" << endl;
|
||
|
|
DArray *da = (DArray*)w.addr;
|
||
|
|
if (da != NULL)
|
||
|
|
{
|
||
|
|
((DArray*)w.addr)->remove();
|
||
|
|
delete (DArray*)w.addr;
|
||
|
|
}
|
||
|
|
w.addr = 0;
|
||
|
|
//cout << " -> OK" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
void DArray::Close( const ListExpr inTypeInfo, Word& w )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Close" << endl;
|
||
|
|
DArray *da = (DArray*)w.addr;
|
||
|
|
if (da != 0)
|
||
|
|
{
|
||
|
|
delete (DArray*)w.addr;
|
||
|
|
}
|
||
|
|
w.addr = 0;
|
||
|
|
//cout << " -> OK" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
//A new DArray is created locally with the
|
||
|
|
//same type, size and serverlist. It is given a
|
||
|
|
//new name and all the elements of the old
|
||
|
|
//array are copied on the workers
|
||
|
|
Word DArray::Clone( const ListExpr inTypeInfo, const Word& w )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Clone" << endl;
|
||
|
|
DArray* alt = (DArray*)w.addr;
|
||
|
|
DArray* neu;
|
||
|
|
|
||
|
|
neu = new DArray(nl->Second(inTypeInfo),
|
||
|
|
getArrayName(DArray::no),
|
||
|
|
alt->getSize(),
|
||
|
|
alt->getServerList());
|
||
|
|
|
||
|
|
DServerCmdCopyParam param (neu -> getName(), -1 );
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
if (alt -> runCommandThreaded <DServerCmdCopy,
|
||
|
|
DServerCmdCopyParam> (poolEx, param) )
|
||
|
|
{
|
||
|
|
//cout << " -> OK" << endl;
|
||
|
|
return SetWord(neu);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (alt -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR:" << alt -> getErrorText() << endl;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
cerr << "ERROR: Cannot copy darray!" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
return SetWord(new DArray (false) );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool DArray::Open( SmiRecord& valueRecord ,
|
||
|
|
size_t& offset ,
|
||
|
|
const ListExpr inTypeInfo ,
|
||
|
|
Word& value )
|
||
|
|
{
|
||
|
|
//cout << "DArray::Open" << endl;
|
||
|
|
char* buffer;
|
||
|
|
string name, type, server;
|
||
|
|
int length;
|
||
|
|
int size;
|
||
|
|
int da_revision;
|
||
|
|
bool is_defined = true;
|
||
|
|
|
||
|
|
//Size of the array is read
|
||
|
|
valueRecord.Read(&da_revision,sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
if (da_revision == -1)
|
||
|
|
{
|
||
|
|
//cout << "READING NEW FORMAT!" << endl;
|
||
|
|
// this is new fromat as of March 2012
|
||
|
|
// format March 2012: size: -1
|
||
|
|
|
||
|
|
// reading defined / not defined
|
||
|
|
int tmp = 0;
|
||
|
|
valueRecord.Read(&tmp,sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
if (tmp == 0)
|
||
|
|
is_defined = false;
|
||
|
|
|
||
|
|
//Size of the array is read
|
||
|
|
valueRecord.Read(&size,sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
//cout << "READING OLD FORMAT!" << endl;
|
||
|
|
// old format:
|
||
|
|
size = da_revision;
|
||
|
|
}
|
||
|
|
|
||
|
|
//type-expression (string) is read
|
||
|
|
valueRecord.Read(&length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
buffer = new char[length];
|
||
|
|
valueRecord.Read(buffer, length, offset);
|
||
|
|
offset += length;
|
||
|
|
type.assign(buffer, length);
|
||
|
|
delete [] buffer;
|
||
|
|
|
||
|
|
//Workerlist is read
|
||
|
|
valueRecord.Read(&length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
buffer = new char[length];
|
||
|
|
valueRecord.Read(buffer, length, offset);
|
||
|
|
offset += length;
|
||
|
|
server.assign(buffer, length);
|
||
|
|
delete [] buffer;
|
||
|
|
|
||
|
|
//name is read
|
||
|
|
valueRecord.Read(&length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
buffer = new char[length];
|
||
|
|
valueRecord.Read(buffer, length, offset);
|
||
|
|
offset += length;
|
||
|
|
name.assign(buffer, length);
|
||
|
|
delete [] buffer;
|
||
|
|
|
||
|
|
ListExpr typeList;
|
||
|
|
nl->ReadFromString( type, typeList);
|
||
|
|
|
||
|
|
ListExpr serverlist = nl -> TheEmptyList();
|
||
|
|
DArray *da = NULL;
|
||
|
|
if (server.length() > 0 && server != "()")
|
||
|
|
{
|
||
|
|
nl->ReadFromString(server,serverlist);
|
||
|
|
da = new DArray(typeList,name,size,serverlist);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
da = new DArray(false);
|
||
|
|
|
||
|
|
if (!is_defined)
|
||
|
|
da -> SetUndefined();
|
||
|
|
|
||
|
|
value.addr = ((Word)da).addr;
|
||
|
|
|
||
|
|
//cout << " -> OK" << endl;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool DArray::Save( SmiRecord& valueRecord ,
|
||
|
|
size_t& offset ,
|
||
|
|
const ListExpr inTypeInfo ,
|
||
|
|
Word& value )
|
||
|
|
{
|
||
|
|
int length;
|
||
|
|
DArray* darray = ((DArray*)value.addr);
|
||
|
|
assert (darray != NULL);
|
||
|
|
|
||
|
|
// This is using a new fromat as of March 2012.
|
||
|
|
// Format March 2012: revision = -1
|
||
|
|
// all new formats must have negative numbers!
|
||
|
|
// since zero value and positive values are used
|
||
|
|
// by the original format
|
||
|
|
int da_revision = -1;
|
||
|
|
|
||
|
|
//current format revision is saved
|
||
|
|
valueRecord.Write(&da_revision, sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
//defined / not defined is saved
|
||
|
|
int defined = darray->IsDefined() ? 1 : 0;
|
||
|
|
valueRecord.Write(&defined, sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
//Size of the array is saved
|
||
|
|
int size = darray->getSize();
|
||
|
|
valueRecord.Write(&size, sizeof(int),offset);
|
||
|
|
offset+=sizeof(int);
|
||
|
|
|
||
|
|
//element-type of the array is saved
|
||
|
|
string type;
|
||
|
|
nl->WriteToString( type, nl->Second(inTypeInfo) );
|
||
|
|
length = type.length();
|
||
|
|
valueRecord.Write( &length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
valueRecord.Write ( type.data(), length, offset);
|
||
|
|
offset += length;
|
||
|
|
|
||
|
|
|
||
|
|
//Workerlist of the array is saved
|
||
|
|
string server;
|
||
|
|
nl->WriteToString( server, darray->getServerList());
|
||
|
|
length = server.length();
|
||
|
|
valueRecord.Write( &length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
valueRecord.Write ( server.data(), length, offset);
|
||
|
|
offset += length;
|
||
|
|
|
||
|
|
//Name of the array is saved
|
||
|
|
string name = darray->getName();
|
||
|
|
length = name.length();
|
||
|
|
valueRecord.Write( &length, sizeof(length), offset);
|
||
|
|
offset += sizeof(length);
|
||
|
|
valueRecord.Write ( name.data(), length, offset);
|
||
|
|
offset += length;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
4.5 Kind Checking
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool DArray::KindCheck( ListExpr inType, ListExpr& errorInfo )
|
||
|
|
{
|
||
|
|
if(nl->ListLength(inType) == 2)
|
||
|
|
{
|
||
|
|
if(nl->IsEqual(nl->First(inType),DArray::BasicType()))
|
||
|
|
{
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
if(sc->KindCorrect(nl->Second(inType),errorInfo))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
int DArray::SizeOfObj()
|
||
|
|
{
|
||
|
|
return sizeof(DArray);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool
|
||
|
|
DArray::hasError() const
|
||
|
|
{
|
||
|
|
if (getServerManager() != NULL)
|
||
|
|
{
|
||
|
|
for(int i =0; i < getSize();i++)
|
||
|
|
if (getServerManager()->getServerByIndex(i) -> hasError())
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string
|
||
|
|
DArray::getErrorText() const
|
||
|
|
{
|
||
|
|
if (getServerManager() != NULL)
|
||
|
|
{
|
||
|
|
for(int i =0; i < getSize();i++)
|
||
|
|
if (getServerManager()->getServerByIndex(i) -> hasError())
|
||
|
|
return getServerManager()->
|
||
|
|
getServerByIndex(i) -> getErrorText();
|
||
|
|
}
|
||
|
|
return string();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool DArray::destroyAnyChilds()
|
||
|
|
{
|
||
|
|
bool ret_val = true;
|
||
|
|
if (getServerManager() != NULL)
|
||
|
|
for(int k = 0; k < getServerManager() -> getNoOfAllWorkers(); k++)
|
||
|
|
if (getServerManager() ->getServerByID(k) != NULL)
|
||
|
|
getServerManager() ->getServerByID(k)->DestroyChilds();
|
||
|
|
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool
|
||
|
|
DArray::multiplyWorkers(vector<DServer*>* outServerList,
|
||
|
|
bool startChilds)
|
||
|
|
{
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
DServerManager* man = getServerManager();
|
||
|
|
DServer* server = 0;
|
||
|
|
|
||
|
|
if (man == NULL || !(man -> isOk()))
|
||
|
|
{
|
||
|
|
cerr << "Cannot start workers!" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
int server_no = man -> getNoOfMultiWorkers(getSize());
|
||
|
|
int rel_server = man -> getRelativeNrOfChildsPerWorker(getSize());
|
||
|
|
int workerWithMoreChilds =
|
||
|
|
man -> getNrOfWorkersWithMoreChilds(getSize());
|
||
|
|
if (startChilds)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor threadEx;
|
||
|
|
cout << "Multiplying worker connections... " << endl;
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0; i<server_no;i++)
|
||
|
|
{
|
||
|
|
int childCnt = rel_server;
|
||
|
|
if (i < workerWithMoreChilds)
|
||
|
|
childCnt ++;
|
||
|
|
server = man->getServerByID(i);
|
||
|
|
threadEx.execute(new DServerMultiplyer(server,
|
||
|
|
childCnt));
|
||
|
|
}
|
||
|
|
threadEx.wait();
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
cerr << "Could not multiply DServers!" << endl;
|
||
|
|
cerr << e.what() << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0; ret_val && i < getSize(); i++)
|
||
|
|
{
|
||
|
|
server = man->getServerByIndex(i);
|
||
|
|
int child = man->getMultipleServerIndex(i);
|
||
|
|
|
||
|
|
if(child > -1)
|
||
|
|
{
|
||
|
|
assert((unsigned int)child <
|
||
|
|
server->getChilds().size());
|
||
|
|
server = (server->getChilds())[child];
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(server -> checkServer(true)) ||
|
||
|
|
server -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Multiplying darrays" << endl;
|
||
|
|
cerr << server -> getErrorText() << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ret_val && outServerList != NULL)
|
||
|
|
(*outServerList)[i] = server;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!ret_val)
|
||
|
|
{
|
||
|
|
destroyAnyChilds();
|
||
|
|
|
||
|
|
if (outServerList != NULL)
|
||
|
|
outServerList -> clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <class T, class P>
|
||
|
|
bool DArray::runCommand(const P& inParam,
|
||
|
|
int inServerIndex)
|
||
|
|
{
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
if (inServerIndex < 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
DServer* worker = getServerManager()->getServerByIndex(inServerIndex);
|
||
|
|
DServerCmd *cmd =
|
||
|
|
new T ();
|
||
|
|
|
||
|
|
cmd -> setWorker(worker);
|
||
|
|
cmd -> setIndex(inServerIndex);
|
||
|
|
cmd -> setParam<P>(&inParam);
|
||
|
|
|
||
|
|
cmd -> run();
|
||
|
|
|
||
|
|
if (worker -> hasError())
|
||
|
|
{
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
delete cmd;
|
||
|
|
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <class T, class P>
|
||
|
|
bool DArray::runCommandThreaded(ZThread::ThreadedExecutor& inExec,
|
||
|
|
const P& inParam,
|
||
|
|
bool inWaitForThreadToEnd,
|
||
|
|
bool startChilds)
|
||
|
|
{
|
||
|
|
// this command can run in 2 modes:
|
||
|
|
// a) run a command for each worker
|
||
|
|
// (worker can contain multiple indexes)
|
||
|
|
|
||
|
|
// b) run a command for each child
|
||
|
|
// (each index is starte as a separate thread)
|
||
|
|
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
const int arraySize = getSize();
|
||
|
|
const int workerSize = getServerManager()->getNoOfUsedWorkers(arraySize);
|
||
|
|
|
||
|
|
int runSize = 0;
|
||
|
|
|
||
|
|
bool runForChilds = inParam.useChilds();
|
||
|
|
|
||
|
|
vector<DServer*> serverList;
|
||
|
|
|
||
|
|
if (runForChilds)
|
||
|
|
{
|
||
|
|
serverList.resize(arraySize, NULL);
|
||
|
|
runSize = arraySize;
|
||
|
|
|
||
|
|
if (!(multiplyWorkers(&serverList, startChilds)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not multiply workers!" << endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
serverList.resize(workerSize);
|
||
|
|
runSize = workerSize;
|
||
|
|
for (int ds = 0; ds < workerSize; ++ds)
|
||
|
|
serverList[ds] = getServerManager()->getServerByID(ds);
|
||
|
|
}
|
||
|
|
|
||
|
|
DServer* worker = NULL;
|
||
|
|
for(int i =0; ret_val && i < runSize; i++)
|
||
|
|
{
|
||
|
|
worker = serverList[i];
|
||
|
|
|
||
|
|
if (worker != NULL)
|
||
|
|
{
|
||
|
|
// cmd ist destroyed automatically at end of thread
|
||
|
|
// no need to delete it!
|
||
|
|
DServerCmd *cmd = new T ();
|
||
|
|
cmd -> setWorker(worker);
|
||
|
|
cmd -> setIndex(i);
|
||
|
|
if (!runForChilds)
|
||
|
|
cmd -> setAllIndex(getServerManager()->getIndexList(i));
|
||
|
|
|
||
|
|
cmd -> setParam<P>(&inParam);
|
||
|
|
|
||
|
|
//cout << "RUN CMD THREADED " << i << cmd -> getInfo() << endl;
|
||
|
|
inExec.execute(cmd);
|
||
|
|
|
||
|
|
if (worker -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Worker has errors!" << endl;
|
||
|
|
cerr << worker -> getErrorText() << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Worker not defined!" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (inWaitForThreadToEnd)
|
||
|
|
{
|
||
|
|
//cout << "RUN CMD THREADED: wait for finshed" << endl;
|
||
|
|
inExec.wait();
|
||
|
|
if (runForChilds && startChilds)
|
||
|
|
destroyAnyChilds();
|
||
|
|
//cout << " ... done";
|
||
|
|
}
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
|
||
|
|
4.6 Type Constructor
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
struct darrayInfo : ConstructorInfo
|
||
|
|
{
|
||
|
|
|
||
|
|
darrayInfo()
|
||
|
|
{
|
||
|
|
|
||
|
|
name = DArray::BasicType();
|
||
|
|
signature = "typeconstructor -> ARRAY" ;
|
||
|
|
typeExample = "darray int";
|
||
|
|
listRep = "(a1 a2 a3)";
|
||
|
|
valueExample = "(4 12 2 8)";
|
||
|
|
remarks = "A darray keeps all its element on remote systems";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
struct darrayFunctions : ConstructorFunctions<DArray>
|
||
|
|
{
|
||
|
|
|
||
|
|
darrayFunctions()
|
||
|
|
{
|
||
|
|
|
||
|
|
create = DArray::Create;
|
||
|
|
in = DArray::In;
|
||
|
|
out = DArray::Out;
|
||
|
|
close = DArray::Close;
|
||
|
|
deletion = DArray::Delete;
|
||
|
|
clone = DArray::Clone;
|
||
|
|
kindCheck = DArray::KindCheck;
|
||
|
|
open = DArray::Open;
|
||
|
|
save = DArray::Save;
|
||
|
|
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
darrayInfo dai;
|
||
|
|
darrayFunctions daf;
|
||
|
|
TypeConstructor darrayTC( dai, daf );
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.1 Operator makeDarray
|
||
|
|
|
||
|
|
Typemap (rel() t t t...) -> darray t
|
||
|
|
Creates a new DArray. The first parameter must be a workerlist of
|
||
|
|
format rel(tuple([Server: string, Port: int]))
|
||
|
|
The other elements in the list form the elements of the array
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr makeDarrayTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//test whether workerlist-format is correct
|
||
|
|
if (nl -> IsEmpty(args))
|
||
|
|
return NList::typeError( "Empty input! Expecting \
|
||
|
|
((rel(tuple([Server: string, Port: int]))) t t ... t)" );
|
||
|
|
|
||
|
|
NList workers (nl->First(args));
|
||
|
|
|
||
|
|
// check worker rel
|
||
|
|
if (!workers.isList() ||
|
||
|
|
!listutils::isRelDescription(workers.listExpr()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
first().
|
||
|
|
second().isSymbol(CcString::BasicType()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError
|
||
|
|
("Worker relation not in the correct format (string, int)");
|
||
|
|
}
|
||
|
|
//all other types must be the same
|
||
|
|
args = nl->Rest(args);
|
||
|
|
if (nl -> IsEmpty(args))
|
||
|
|
return NList::typeError( "Only workers given! Expecting \
|
||
|
|
((rel(tuple([Server: string, Port: int]))) t t ... t)" );
|
||
|
|
|
||
|
|
ListExpr first = nl->First(args);
|
||
|
|
ListExpr rest = nl->Rest(args);
|
||
|
|
|
||
|
|
while(!(nl->IsEmpty(rest)))
|
||
|
|
{
|
||
|
|
if(!nl->Equal(nl->First(rest),first))
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
rest = nl->Rest(rest);
|
||
|
|
}
|
||
|
|
|
||
|
|
return
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->SymbolAtom(DArray::BasicType()),nl->First(args));
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
makeDarrayfun( Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s )
|
||
|
|
{
|
||
|
|
//determine element type
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
ListExpr type = qp->GetType(s);
|
||
|
|
ListExpr typeOfElement = sc->NumericType(nl->Second(type));
|
||
|
|
|
||
|
|
|
||
|
|
int algID, typID;
|
||
|
|
arrayalgebra::extractIds( typeOfElement, algID, typID);
|
||
|
|
|
||
|
|
//determine size of the array
|
||
|
|
int size = qp->GetNoSons(s)-1;
|
||
|
|
|
||
|
|
vector<Word> cloned(size);
|
||
|
|
|
||
|
|
//Objects need to be cloned to be persistent after the query ends
|
||
|
|
for(int i = 0;i<size;i++)
|
||
|
|
{
|
||
|
|
cloned[i] =
|
||
|
|
(am->CloneObj(algID,typID))(typeOfElement,args[i+1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
//Generate serverlist as ListExpr from Relation
|
||
|
|
GenericRelation* r = (GenericRelation*)args[0].addr;
|
||
|
|
GenericRelationIterator* rit = r->MakeScan();
|
||
|
|
ListExpr reltype;
|
||
|
|
nl->
|
||
|
|
ReadFromString("(rel (tuple ((Server string) (Port int))))",
|
||
|
|
reltype);
|
||
|
|
ListExpr serverlist = Relation::Out(reltype,rit);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
bool rc =
|
||
|
|
((DArray*)result.addr)->initialize(typeOfElement,
|
||
|
|
getArrayName(DArray::no),
|
||
|
|
size,serverlist,
|
||
|
|
cloned);
|
||
|
|
if (!rc)
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not initialize DArray!" << endl;
|
||
|
|
((DArray*)result.addr)->SetUndefined();
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string makeDarraySpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>(rel(tuple([Server: string, Port: int])) t t ...)"
|
||
|
|
" -> darray t</text---><text>makeDarray ( _, _ )</text--->"
|
||
|
|
"<text>Returns a distributed Array"
|
||
|
|
" containing x element</text--->"
|
||
|
|
"<text>query makeDarray(server_rel,1,2,3)</text---> ))";
|
||
|
|
|
||
|
|
Operator makeDarray(
|
||
|
|
"makeDarray",
|
||
|
|
makeDarraySpec,
|
||
|
|
makeDarrayfun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
makeDarrayTypeMap);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.2 Operator get
|
||
|
|
|
||
|
|
((darray t) int) -> t
|
||
|
|
|
||
|
|
Returns an element of a DArray.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr getTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//There must be 2 parameters
|
||
|
|
if(nl->ListLength(args) == 2)
|
||
|
|
{
|
||
|
|
ListExpr arg1 = nl->First(args);
|
||
|
|
ListExpr arg2 = nl->Second(args);
|
||
|
|
|
||
|
|
//The first one needs to a DArray and the second int
|
||
|
|
if(!nl->IsAtom(arg1) &&
|
||
|
|
nl->IsEqual(nl->First(arg1),DArray::BasicType()) &&
|
||
|
|
nl->IsEqual(arg2,CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
//The return-type of get is the element-type of the array
|
||
|
|
ListExpr resulttype = nl->Second(arg1);
|
||
|
|
return resulttype;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
static int getFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
DArray* array = ((DArray*)args[0].addr);
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
if ( array == 0 ||
|
||
|
|
!(array -> IsDefined()) ||
|
||
|
|
!(array -> getServerManager() -> checkServers(false)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DArray is not defined correctly!" << endl;
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
CcInt* index = ((CcInt*)args[1].addr);
|
||
|
|
|
||
|
|
int i = index->GetIntval();
|
||
|
|
|
||
|
|
int n = array -> getSize();
|
||
|
|
|
||
|
|
if (i < 0 || i >= n)
|
||
|
|
{
|
||
|
|
cerr << "ERROR: invalid array index!" << endl;
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//Determine type
|
||
|
|
ListExpr resultType = array->getType();
|
||
|
|
|
||
|
|
int algID,typID;
|
||
|
|
arrayalgebra::extractIds(resultType,algID,typID);
|
||
|
|
|
||
|
|
//retrieve element from worker
|
||
|
|
array->refresh(i);
|
||
|
|
//copy the element
|
||
|
|
|
||
|
|
|
||
|
|
if (array -> isRelType())
|
||
|
|
{
|
||
|
|
result.addr = ((Word)array->get(i)).addr;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Word org = (Word)array->get(i);
|
||
|
|
/*
|
||
|
|
Word cloned =
|
||
|
|
(am->CloneObj(algID,typID))
|
||
|
|
(resultType,org);
|
||
|
|
|
||
|
|
result.addr = cloned.addr;
|
||
|
|
*/
|
||
|
|
result.addr = org.addr;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string getSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) int) -> t</text--->"
|
||
|
|
"<text>get ( _, _ )</text--->"
|
||
|
|
"<text>Returns an element from a distributed Array</text--->"
|
||
|
|
"<text>query get(makeDarray(server_rel,1,2,3),1)"
|
||
|
|
"</text---> ))";
|
||
|
|
|
||
|
|
Operator getA(
|
||
|
|
"get",
|
||
|
|
getSpec,
|
||
|
|
getFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
getTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.3 Operator put
|
||
|
|
|
||
|
|
((darray t), t, int) -> (darray t)
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr putTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
if(nl->ListLength(args) == 3)
|
||
|
|
{
|
||
|
|
ListExpr arg1 = nl->First(args);
|
||
|
|
ListExpr arg2 = nl->Second(args);
|
||
|
|
ListExpr arg3 = nl->Third(args);
|
||
|
|
|
||
|
|
//The first argument needs to be a darray, the second
|
||
|
|
//one of the same type as the array-elements and the
|
||
|
|
//third one int
|
||
|
|
if(!nl->IsAtom(arg1) &&
|
||
|
|
nl->IsEqual(nl->First(arg1), DArray::BasicType())
|
||
|
|
&& nl->Equal(nl->Second(arg1),arg2)
|
||
|
|
&& nl->IsEqual(arg3,CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return arg1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
static int putFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
DArray* array_alt = ((DArray*)args[0].addr);
|
||
|
|
Word element = args[1];
|
||
|
|
int idx = ((CcInt*)args[2].addr)->GetIntval();
|
||
|
|
|
||
|
|
//new array is initialized
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
DArray* da = (DArray*)result.addr;
|
||
|
|
|
||
|
|
if (array_alt == NULL ||
|
||
|
|
!(array_alt -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DArray object is not defined!" << endl;
|
||
|
|
da -> SetUndefined();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//new elements needs to be copied
|
||
|
|
Word elem_n = ((am->CloneObj(array_alt->getAlgID(),
|
||
|
|
array_alt->getTypID()))
|
||
|
|
(array_alt->getType(),element));
|
||
|
|
|
||
|
|
// check, if valid object
|
||
|
|
if (da != NULL &&
|
||
|
|
// check, if valid index
|
||
|
|
idx >= 0 && idx < array_alt -> getSize())
|
||
|
|
{
|
||
|
|
da->initialize(array_alt->getType(),
|
||
|
|
getArrayName(DArray::no),
|
||
|
|
array_alt->getSize(),
|
||
|
|
array_alt->getServerList());
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
DServerCmdCopyParam param (da -> getName(), idx );
|
||
|
|
|
||
|
|
if (array_alt ->
|
||
|
|
runCommandThreaded <DServerCmdCopy,
|
||
|
|
DServerCmdCopyParam> (poolEx, param) )
|
||
|
|
{
|
||
|
|
//The substituted element is set
|
||
|
|
da -> set(elem_n, idx);
|
||
|
|
|
||
|
|
// all is ok
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (array_alt -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< array_alt -> getErrorText() << endl;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
cerr << "ERROR: Operator put - unknown error!" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// error msg
|
||
|
|
if (da == NULL || !(da -> IsDefined()))
|
||
|
|
cerr << "Error: undefined darray object!" << endl;
|
||
|
|
else if (idx < 0 || idx >= array_alt -> getSize())
|
||
|
|
cerr << "Error: invalid index: 0 <= "
|
||
|
|
<< idx << " < " << array_alt -> getSize()
|
||
|
|
<< " is not a valid index!" << endl;
|
||
|
|
else
|
||
|
|
cerr << "Error in put function!" << endl;
|
||
|
|
}
|
||
|
|
// error: invalidate result
|
||
|
|
da -> SetUndefined();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string putSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) t int) -> darray t</text--->"
|
||
|
|
"<text>put ( _, _, _ )</text--->"
|
||
|
|
"<text>Returns a distributed array where"
|
||
|
|
"one element is altered</text--->"
|
||
|
|
"<text>query put(makeDarray(server_rel,1,2,3),2,2)</text---> ))";
|
||
|
|
|
||
|
|
Operator putA(
|
||
|
|
"put",
|
||
|
|
putSpec,
|
||
|
|
putFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
putTypeMap);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.4 Operator send
|
||
|
|
|
||
|
|
Internal Usage for Data Transfer between Master and Worker
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr sendTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//Always return int
|
||
|
|
//Hostname and Port are appended for the value-mapping
|
||
|
|
|
||
|
|
int len = nl->ListLength(args);
|
||
|
|
if(len < 2){
|
||
|
|
return listutils::typeError("at least two arguments required");
|
||
|
|
}
|
||
|
|
string s1 = nl->ToString(nl->First(args));
|
||
|
|
string s2 = nl->ToString(nl->Second(args));
|
||
|
|
|
||
|
|
if(s1.size()>MAX_STRINGSIZE || s2.size()>MAX_STRINGSIZE){
|
||
|
|
return listutils::typeError("type is too long");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr ret =
|
||
|
|
nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->StringAtom(s1),
|
||
|
|
nl->StringAtom(s2)),
|
||
|
|
nl->SymbolAtom(CcInt::BasicType()));
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int sendFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
//retrieve Hostname and Port
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[3].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[4].addr)->GetStringval();
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
//Connect to master
|
||
|
|
DServerCmdCallBackCommunication callBack(host, port);
|
||
|
|
if (!callBack.createGlobalSocket())
|
||
|
|
{
|
||
|
|
// error on stream
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
string line;
|
||
|
|
if (!callBack.getTextFromCallBack("TYPE", line))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
ListExpr type;
|
||
|
|
nl->ReadFromString(line,type);
|
||
|
|
|
||
|
|
int algID,typID;
|
||
|
|
arrayalgebra::extractIds(type,algID,typID);
|
||
|
|
|
||
|
|
Attribute* attr =static_cast<Attribute*>
|
||
|
|
((am->Cast(algID,typID))(args[2].addr));
|
||
|
|
if (attr == NULL || !(attr -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR SENDING:";
|
||
|
|
if (attr == NULL)
|
||
|
|
cerr << "empty attribute";
|
||
|
|
else
|
||
|
|
cerr << "attribute not defined";
|
||
|
|
cerr << "!" << endl;
|
||
|
|
callBack.sendTagToCallBack("UNDEFINED");
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (!callBack.sendTagToCallBack("DATA"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
SmiRecordFile recF(false,0);
|
||
|
|
SmiRecord rec;
|
||
|
|
SmiRecordId recID;
|
||
|
|
|
||
|
|
recF.Open("sendop");
|
||
|
|
recF.AppendRecord(recID,rec);
|
||
|
|
size_t size = 0;
|
||
|
|
am->SaveObj(algID,typID,rec,size,type,args[2]);
|
||
|
|
char* buffer = new char[size];
|
||
|
|
|
||
|
|
rec.Read(buffer,size,0);
|
||
|
|
|
||
|
|
rec.Truncate(3);
|
||
|
|
recF.DeleteRecord(recID);
|
||
|
|
recF.Close();
|
||
|
|
|
||
|
|
if (!callBack.sendTextToCallBack("SIZE", size))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!callBack.Write(buffer,size))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
delete buffer;
|
||
|
|
|
||
|
|
TypeConstructor* t = am->GetTC(algID,typID);
|
||
|
|
Attribute* a = NULL;
|
||
|
|
if(t->NumOfFLOBs() > 0 )
|
||
|
|
a = static_cast<Attribute*>
|
||
|
|
((am->Cast(algID,typID))(args[2].addr));
|
||
|
|
|
||
|
|
Flob::clearCaches();
|
||
|
|
for(int i = 0; i < t->NumOfFLOBs(); i++)
|
||
|
|
{
|
||
|
|
Flob* f = a->GetFLOB(i);
|
||
|
|
|
||
|
|
SmiSize si = f->getSize();
|
||
|
|
int n_blocks = si / 1024 + 1;
|
||
|
|
char* buf = new char[n_blocks*1024];
|
||
|
|
memset(buf,0,1024*n_blocks);
|
||
|
|
|
||
|
|
f->read(buf,si,0);
|
||
|
|
|
||
|
|
if (!callBack.sendTagToCallBack("FLOB"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (!callBack.sendTextToCallBack("FSIZE", si))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
for(int j = 0; j<n_blocks;j++)
|
||
|
|
{
|
||
|
|
if (! callBack.Write(buf+j*1024,1024))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
delete buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!callBack.sendTagToCallBack("CLOSE"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!callBack.getTagFromCallBack("FINISH"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
callBack.closeCallBackCommunication();
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
((CcInt*)result.addr)->Set(1);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
const string sendSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator sendA(
|
||
|
|
"sendD",
|
||
|
|
sendSpec,
|
||
|
|
sendFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
sendTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.5 Operator receive
|
||
|
|
|
||
|
|
Internal Usage for Data Transfer between Master and Worker
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr receiveTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
|
||
|
|
int len = nl->ListLength(args);
|
||
|
|
if(len < 2){
|
||
|
|
return listutils::typeError("at least 2 args required");
|
||
|
|
}
|
||
|
|
|
||
|
|
string host = nl->ToString(nl->First(args));
|
||
|
|
string port = nl->ToString(nl->Second(args));
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication* callBack =
|
||
|
|
new DServerCmdCallBackCommunication (host, port);
|
||
|
|
|
||
|
|
if (!(callBack -> createGlobalSocket()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not connect to Server!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(callBack -> getTextFromCallBack("TYPE", line)))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Received invalid token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr type;
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,type);
|
||
|
|
|
||
|
|
if (!(callBack -> sendTagToCallBack("CLOSE")))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not send token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
delete callBack;
|
||
|
|
|
||
|
|
|
||
|
|
string s1 = nl->ToString(nl->First(args));
|
||
|
|
string s2 = nl->ToString(nl->Second(args));
|
||
|
|
if(s1.size() > MAX_STRINGSIZE || s2.size() > MAX_STRINGSIZE){
|
||
|
|
return listutils::typeError("arguments types too long");
|
||
|
|
}
|
||
|
|
return
|
||
|
|
nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->StringAtom(s1),
|
||
|
|
nl->StringAtom(s2)),
|
||
|
|
convertType(type));
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static int receiveFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[2].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[3].addr)->GetStringval();
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication *recCallBack =
|
||
|
|
new DServerCmdCallBackCommunication(host, port
|
||
|
|
#ifdef RECEIVE_FUN_DEBUG
|
||
|
|
, "REC_VM"
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
if(!(recCallBack -> createGlobalSocket()))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("TYPE", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr type;
|
||
|
|
size_t size =0;
|
||
|
|
int algID,typID;
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,type);
|
||
|
|
|
||
|
|
arrayalgebra::extractIds(type,algID,typID);
|
||
|
|
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("GOTTYPE")))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("SIZE", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
size = atoi(line.data());
|
||
|
|
|
||
|
|
|
||
|
|
char* buffer = new char[size];
|
||
|
|
|
||
|
|
if (!(recCallBack ->Read(buffer,size)))
|
||
|
|
{
|
||
|
|
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
SmiRecordFile recF(false,0);
|
||
|
|
SmiRecord rec;
|
||
|
|
SmiRecordId recID;
|
||
|
|
|
||
|
|
recF.Open("receiveop");
|
||
|
|
recF.AppendRecord(recID,rec);
|
||
|
|
size_t s0 = 0;
|
||
|
|
|
||
|
|
rec.Write(buffer,size,0);
|
||
|
|
Word w;
|
||
|
|
am->OpenObj(algID,typID,rec,s0,type,w);
|
||
|
|
|
||
|
|
result.addr = w.addr;
|
||
|
|
rec.Truncate(3);
|
||
|
|
recF.DeleteRecord(recID);
|
||
|
|
recF.Close();
|
||
|
|
|
||
|
|
bool noFlobError = true;
|
||
|
|
int flobs = 0;
|
||
|
|
|
||
|
|
while (noFlobError &&
|
||
|
|
recCallBack -> getTagFromCallBackTF("FLOB", "CLOSE", noFlobError))
|
||
|
|
{
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("FLOBSIZE", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (noFlobError)
|
||
|
|
{
|
||
|
|
SmiSize si = atoi(line.data());
|
||
|
|
|
||
|
|
int n_blocks = si / 1024 + 1;
|
||
|
|
char* buf = new char[n_blocks*1024];
|
||
|
|
memset(buf,0,1024*n_blocks);
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0; i< n_blocks; i++)
|
||
|
|
if (!(recCallBack -> Read(buf+1024*i,1024)))
|
||
|
|
noFlobError = false;
|
||
|
|
|
||
|
|
if (noFlobError)
|
||
|
|
{
|
||
|
|
Attribute* a = static_cast<Attribute*>
|
||
|
|
((am->Cast(algID,typID))(result.addr));
|
||
|
|
|
||
|
|
|
||
|
|
Flob* f = a->GetFLOB(flobs);
|
||
|
|
f->write(buf,si,0);
|
||
|
|
|
||
|
|
delete buf;
|
||
|
|
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("GOTFLOB")))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
delete buf;
|
||
|
|
}
|
||
|
|
} // if (noFlobError)
|
||
|
|
|
||
|
|
if (!noFlobError)
|
||
|
|
{
|
||
|
|
recCallBack -> sendTagToCallBack("ERROR");
|
||
|
|
}
|
||
|
|
flobs ++;
|
||
|
|
} // while "FLOB" ...
|
||
|
|
|
||
|
|
Flob::clearCaches();
|
||
|
|
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("FINISH")))
|
||
|
|
{
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
delete recCallBack;
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
const string receiveSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator receiveA(
|
||
|
|
"receiveD",
|
||
|
|
receiveSpec,
|
||
|
|
receiveFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
receiveTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.6 Operator d\_receive\_rel
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr receiverelTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
|
||
|
|
if(nl->ListLength(args) < 2){
|
||
|
|
return listutils::typeError("at least two elements required");
|
||
|
|
}
|
||
|
|
string host = nl->ToString(nl->First(args));
|
||
|
|
string port = nl->ToString(nl->Second(args));
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication* callBack =
|
||
|
|
new DServerCmdCallBackCommunication (host, port);
|
||
|
|
|
||
|
|
if (!(callBack -> createGlobalSocket()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not connect to Server!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(callBack -> getTextFromCallBack("TYPE", line)))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Received invalid token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr type;
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,type);
|
||
|
|
|
||
|
|
if (!(callBack -> sendTagToCallBack("CLOSE")))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not send token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
delete callBack;
|
||
|
|
|
||
|
|
#ifdef RECEIVE_REL_MAP_DEBUG
|
||
|
|
cout << "receiverelTypeMap - done " << endl;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
string s1 = nl->ToString(nl->First(args));
|
||
|
|
string s2 = nl->ToString(nl->Second(args));
|
||
|
|
|
||
|
|
if((s1.size()>MAX_STRINGSIZE) || (s2.size()>MAX_STRINGSIZE)){
|
||
|
|
return listutils::typeError("argument types too long");
|
||
|
|
}
|
||
|
|
|
||
|
|
return nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->StringAtom(nl->ToString(nl->First(args))),
|
||
|
|
nl->StringAtom(nl->ToString(nl->Second(args)))),
|
||
|
|
convertType(type));
|
||
|
|
}
|
||
|
|
|
||
|
|
class RecContainer
|
||
|
|
: public DServerCmdCallBackCommunication::ReadTupleContainer
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
RecContainer(TupleType *inTT,
|
||
|
|
GenericRelation* inRel,
|
||
|
|
int inDelAttrIdx)
|
||
|
|
: DServerCmdCallBackCommunication::ReadTupleContainer()
|
||
|
|
, m_saveTupleType(inTT)
|
||
|
|
, m_rel(inRel)
|
||
|
|
, m_delAttrIndex(inDelAttrIdx) {}
|
||
|
|
|
||
|
|
virtual ~RecContainer() {}
|
||
|
|
|
||
|
|
bool storeTuple(Tuple *t) const
|
||
|
|
{
|
||
|
|
Tuple* saveTuple = new Tuple(m_saveTupleType);
|
||
|
|
int j = 0;
|
||
|
|
for(int i = 0; i < t->GetNoAttributes(); i++)
|
||
|
|
{
|
||
|
|
if(i != m_delAttrIndex)
|
||
|
|
saveTuple->CopyAttribute(i,t,j++);
|
||
|
|
}
|
||
|
|
|
||
|
|
DBAccessGuard::getInstance() -> REL_AppendTuple(m_rel,saveTuple);
|
||
|
|
DBAccessGuard::getInstance() -> T_DeleteIfAllowed(saveTuple);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
TupleType *m_saveTupleType;
|
||
|
|
GenericRelation* m_rel;
|
||
|
|
int m_delAttrIndex;
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
static int receiverelFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
#ifdef RECEIVE_REL_FUN_DEBUG
|
||
|
|
cout << " receiverelFun - start" << endl;
|
||
|
|
#endif
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[2].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[3].addr)->GetStringval();
|
||
|
|
|
||
|
|
ListExpr resultType, sendType;
|
||
|
|
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication *recCallBack =
|
||
|
|
new DServerCmdCallBackCommunication(host, port
|
||
|
|
#ifdef RECEIVE_REL_FUN_DEBUG
|
||
|
|
, "REL_REC_VM"
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
|
||
|
|
if(!(recCallBack -> createGlobalSocket()))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("TYPE", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,resultType);
|
||
|
|
resultType = nl->Second(resultType);
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("INTYPE", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (line == "EMPTY")
|
||
|
|
{
|
||
|
|
sendType = resultType;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,sendType);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(recCallBack -> getTextFromCallBack("DELIDX", line)))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int darrIndex = -1;
|
||
|
|
|
||
|
|
if (line != "EMPTY")
|
||
|
|
{
|
||
|
|
darrIndex = atoi(line.data());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("GOTALL")))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
TupleType* sendTT = DBAccess::getInstance() -> TT_New(sendType);
|
||
|
|
TupleType* tupleType = DBAccess::getInstance() -> TT_New(resultType);
|
||
|
|
GenericRelation* myRel = (Relation*)result.addr;
|
||
|
|
|
||
|
|
RecContainer recContainer(tupleType, myRel, darrIndex);
|
||
|
|
|
||
|
|
bool noTupleError = true;
|
||
|
|
bool runIt = true;
|
||
|
|
while (runIt)
|
||
|
|
{
|
||
|
|
runIt = recCallBack ->
|
||
|
|
getTagFromCallBackTF("TUPLE", "CLOSE", noTupleError);
|
||
|
|
|
||
|
|
if (runIt)
|
||
|
|
{
|
||
|
|
if (!( recCallBack -> readTupleFromCallBack(sendTT, &recContainer)))
|
||
|
|
noTupleError = false;
|
||
|
|
|
||
|
|
if (noTupleError)
|
||
|
|
{
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("OK")))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("ERROR")))
|
||
|
|
{
|
||
|
|
delete recCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
runIt = false;
|
||
|
|
}
|
||
|
|
} // if (runIt)
|
||
|
|
}// while (runIT)
|
||
|
|
|
||
|
|
if (!(recCallBack -> sendTagToCallBack("FINISH")))
|
||
|
|
{
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
DBAccess::getInstance() -> TT_DeleteIfAllowed(tupleType);
|
||
|
|
DBAccess::getInstance() -> TT_DeleteIfAllowed(sendTT);
|
||
|
|
|
||
|
|
delete recCallBack;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string receiverelSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator receiverelA(
|
||
|
|
"d_receive_rel",
|
||
|
|
receiverelSpec,
|
||
|
|
receiverelFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
receiverelTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
|
||
|
|
5.7 Operator d\_send\_rel
|
||
|
|
|
||
|
|
Internal Usage for Data Transfer between Master and Worker
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
static ListExpr sendrelTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
|
||
|
|
if(nl->ListLength(args) < 2){
|
||
|
|
return listutils::typeError("at least two arguments required");
|
||
|
|
}
|
||
|
|
|
||
|
|
string s1 = nl->ToString(nl->First(args));
|
||
|
|
string s2 = nl->ToString(nl->Second(args));
|
||
|
|
if(s1.size()>MAX_STRINGSIZE || s2.size()>MAX_STRINGSIZE){
|
||
|
|
return listutils::typeError("arguments too long");
|
||
|
|
}
|
||
|
|
return nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->StringAtom(s1),
|
||
|
|
nl->StringAtom(s2)),
|
||
|
|
nl->SymbolAtom(CcInt::BasicType()));
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static int sendrelFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[3].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[4].addr)->GetStringval();
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
//Connect to master
|
||
|
|
DServerCmdCallBackCommunication callBack(host, port);
|
||
|
|
if (!callBack.createGlobalSocket())
|
||
|
|
{
|
||
|
|
// error on stream
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
GenericRelation* rel = (Relation*)args[2].addr;
|
||
|
|
GenericRelationIterator* iter = rel->MakeScan();
|
||
|
|
Tuple* t;
|
||
|
|
bool runIt = true;
|
||
|
|
bool noError = true;
|
||
|
|
while(runIt && (t=iter->GetNextTuple()) != 0)
|
||
|
|
{
|
||
|
|
if (!callBack.sendTagToCallBack("NEXTTUPLE"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (!callBack.writeTupleToCallBack(t))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
runIt = callBack.getTagFromCallBackTF("OK", "ERROR", noError);
|
||
|
|
|
||
|
|
if (!noError || !runIt)
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!callBack.sendTagToCallBack("CLOSE"))
|
||
|
|
{
|
||
|
|
((CcInt*)result.addr)->Set(0);
|
||
|
|
((Attribute*)result.addr)->SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
delete iter;
|
||
|
|
|
||
|
|
((CcInt*)result.addr)->Set(1);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
const string sendrelSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator sendrelA(
|
||
|
|
"d_send_rel",
|
||
|
|
sendrelSpec,
|
||
|
|
sendrelFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
sendrelTypeMap);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.8 Operator d\_receive\_shuffle
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr receiveShuffleTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//NList myAargs (args);
|
||
|
|
|
||
|
|
#ifdef RECEIVE_SHUFFLE_MAP_DEBUG
|
||
|
|
cout << "ReceiveShuffleTM:"
|
||
|
|
<< myAargs.convertToString() << endl;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(nl->ListLength(args) < 2){
|
||
|
|
return listutils::typeError("at least 2 arguments required");
|
||
|
|
}
|
||
|
|
|
||
|
|
string host = nl->ToString(nl->First(args));
|
||
|
|
string port = nl->ToString(nl->Second(args));
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication* callBack =
|
||
|
|
new DServerCmdCallBackCommunication(host,
|
||
|
|
port
|
||
|
|
#ifdef RECEIVE_SHUFFLE_MAP_DEBUG
|
||
|
|
,"SHUFFLE_REC_TM"
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!(callBack -> createGlobalSocket()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not connect to Server!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(callBack -> getTextFromCallBack("TYPE", line)))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Received invalid token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr type;
|
||
|
|
DBAccessGuard::getInstance() -> NL_ReadFromString(line,type);
|
||
|
|
|
||
|
|
if (!(callBack -> sendTagToCallBack("CLOSE")))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Could not send token!\n" +
|
||
|
|
callBack -> getErrorText());
|
||
|
|
delete callBack;
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
delete callBack;
|
||
|
|
|
||
|
|
#ifdef RECEIVE_SHUFFLE_MAP_DEBUG
|
||
|
|
cout << "receive shuffle TM - done " << endl;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ListExpr typeLE = convertType(type);
|
||
|
|
|
||
|
|
string s1 = nl->ToString(nl->First(args));
|
||
|
|
string s2 = nl->ToString(nl->Second(args));
|
||
|
|
if(s1.size()>MAX_STRINGSIZE || s2.size()>MAX_STRINGSIZE){
|
||
|
|
return listutils::typeError("arguments too long");
|
||
|
|
}
|
||
|
|
ListExpr res = nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->StringAtom(s1),
|
||
|
|
nl->StringAtom(s2)),
|
||
|
|
typeLE);
|
||
|
|
|
||
|
|
//cout << nl -> ToString(res) << endl;
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int receiveShuffleFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
#ifdef RECEIVE_SHUFFLE_FUN_DEBUG
|
||
|
|
cout << " receiveShuffleFun - start" << endl;
|
||
|
|
#endif
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[2].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[3].addr)->GetStringval();
|
||
|
|
|
||
|
|
|
||
|
|
//cout << "REC-SHUFFLE on " << host << ":" << port << endl;
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
ListExpr resultType = nl->Second(qp->GetType(s));
|
||
|
|
resultType = sc->NumericType(resultType);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
string line;
|
||
|
|
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
// create callBack w/ worker
|
||
|
|
// this is done in DServerCmdShuffleRec
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication *dscCallBack =
|
||
|
|
new DServerCmdCallBackCommunication(host, port
|
||
|
|
#ifdef RECEIVE_SHUFFLE_FUN_DEBUG
|
||
|
|
, "SHUFFLERECVM"
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
|
||
|
|
if(dscCallBack -> createGlobalSocket())
|
||
|
|
{
|
||
|
|
|
||
|
|
//cout << "REC-SHUFFLE on " << host << ":" << port
|
||
|
|
// << " - connected" << endl;
|
||
|
|
// now connected to the DServerCmdShuffleMultipleConn
|
||
|
|
if (!(dscCallBack -> getTagFromCallBack("STARTMULTIPLYCONN")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:" << dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("OK")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:" << dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// get the number of workers, which will be sending
|
||
|
|
// data
|
||
|
|
if (!(dscCallBack -> getTextFromCallBack("SRCWSIZE", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:" << dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int srcSize = atoi(line.data());
|
||
|
|
|
||
|
|
vector<string> srcHost(srcSize);
|
||
|
|
vector<int> srcToPort(srcSize);
|
||
|
|
int expectedstate = 0; // 0 - host, 1 - fromPort, 2 - toPort
|
||
|
|
unsigned long srcCnt = 0;
|
||
|
|
bool runIt = true;
|
||
|
|
bool noError = true;
|
||
|
|
string errMsg;
|
||
|
|
|
||
|
|
do{
|
||
|
|
if (expectedstate == 0)
|
||
|
|
{
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
getTextFromCallBack("SRCWHOST", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
srcHost[srcCnt] = line;
|
||
|
|
expectedstate = 1;
|
||
|
|
}
|
||
|
|
else if (expectedstate == 1)
|
||
|
|
{
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
getTextFromCallBack("SRCWTPORT", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
srcToPort[srcCnt] = atoi(line.data());
|
||
|
|
srcCnt ++;
|
||
|
|
expectedstate = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("OK")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
runIt =
|
||
|
|
dscCallBack -> getTagFromCallBackTF("NEXT", "DONE",
|
||
|
|
noError);
|
||
|
|
|
||
|
|
if (!noError)
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
} while (runIt);
|
||
|
|
|
||
|
|
//cout << "REC-SHUFFLE on " << host << ":" << port
|
||
|
|
// << " - got hosts: << " << srcCnt
|
||
|
|
// << " - emit ready" << endl;
|
||
|
|
//for(int i = 0; i < srcSize; i++)
|
||
|
|
// cout << "REC-SHUFFLE on " << host << ":" << port
|
||
|
|
// << " - " << srcHost[i] << ":" << srcToPort[i] << endl;
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("READY")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// setup CommandQueue for each server;
|
||
|
|
vector<DServerShuffleReceiver*> serverCommand(srcSize);
|
||
|
|
|
||
|
|
GenericRelation* rel = (Relation*)result.addr;
|
||
|
|
|
||
|
|
//cout << "REC-SHUFFLE on " << host << ":" << port
|
||
|
|
// << " - starting receivers" << endl;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
|
||
|
|
for(int i = 0; i < srcSize; i++)
|
||
|
|
{
|
||
|
|
serverCommand[i] =
|
||
|
|
new DServerShuffleReceiver(srcHost[i],
|
||
|
|
int2Str(srcToPort[i]),
|
||
|
|
rel,
|
||
|
|
resultType);
|
||
|
|
|
||
|
|
poolEx.execute(serverCommand[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
//dscCallBack -> sendTagToCallBack("RUNNING");
|
||
|
|
|
||
|
|
poolEx.wait();
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
cerr << "Could not distribute data!" << endl;
|
||
|
|
cerr << e.what() << endl;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout << "REC-SHUFFLE on " << host << ":" << port
|
||
|
|
// << " - sending DONE" << endl;
|
||
|
|
|
||
|
|
if (!noError)
|
||
|
|
{
|
||
|
|
cout << "RECEIVER on SENDING ERROR!" << endl;
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("ERROR")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
string errorMsg ="Shuffle: error receiving tuples!";
|
||
|
|
if (!errMsg.empty())
|
||
|
|
errorMsg += "Reason: " + errMsg;
|
||
|
|
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
sendTextToCallBack("ERRORDESC", errorMsg)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("DONE")))
|
||
|
|
{
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute*) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//dscCallBack -> forceCloseSavedCommunication();
|
||
|
|
delete dscCallBack;
|
||
|
|
|
||
|
|
}
|
||
|
|
else // if(dscCallBack -> createGlobalSocket())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not connect receivers and senders!"
|
||
|
|
<<endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
} //static int receiveShuffleFun(...)
|
||
|
|
|
||
|
|
const string receiveShuffleSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator receiveShuffle(
|
||
|
|
"d_receive_shuffle",
|
||
|
|
receiveShuffleSpec,
|
||
|
|
receiveShuffleFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
receiveShuffleTypeMap);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
|
||
|
|
5.7 Operator d\_send\_shuffle
|
||
|
|
|
||
|
|
Internal Usage for Data Transfer between Master and Worker
|
||
|
|
for the shuffle operator
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
static ListExpr sendShuffleTypeMap( ListExpr inArgs )
|
||
|
|
{
|
||
|
|
NList args (inArgs);
|
||
|
|
|
||
|
|
#ifdef SEND_SHUFFLE_MAP_DEBUG
|
||
|
|
cout << "HERE!: SendShuffleTM:" << args.convertToString()
|
||
|
|
<< endl;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ListExpr errLE = nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
if (args.length() != 4)
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError
|
||
|
|
("Wrong number of arguments for d_shuffle_send operator!");
|
||
|
|
return errLE;
|
||
|
|
}
|
||
|
|
NList mapDesc = args.second();
|
||
|
|
|
||
|
|
if (mapDesc.third() != NList(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError
|
||
|
|
("Function return type must be of type <int>!!");
|
||
|
|
return errLE;
|
||
|
|
}
|
||
|
|
|
||
|
|
string s1 = args.third().convertToString();
|
||
|
|
string s2 = args.fourth().convertToString();
|
||
|
|
if(s1.size()>MAX_STRINGSIZE || s2.size()>MAX_STRINGSIZE){
|
||
|
|
return listutils::typeError("arguments too long");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr ret = nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->StringAtom(s1),
|
||
|
|
nl->StringAtom(s2)),
|
||
|
|
nl->SymbolAtom(CcInt::BasicType()));
|
||
|
|
|
||
|
|
#ifdef SEND_SHUFFLE_MAP_DEBUG
|
||
|
|
cout << "SendShuffleTM Done:"
|
||
|
|
<< NList(ret).convertToString() << endl;
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static int sendShuffleFun( Word* args,
|
||
|
|
Word& result,
|
||
|
|
int message,
|
||
|
|
Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
string host =
|
||
|
|
(string)(char*)((CcString*)args[4].addr)->GetStringval();
|
||
|
|
string port =
|
||
|
|
(string)(char*)((CcString*)args[5].addr)->GetStringval();
|
||
|
|
string line;
|
||
|
|
|
||
|
|
bool invalidIndex = false;
|
||
|
|
host = stringutils::replaceAll(host,"_",".");
|
||
|
|
host = stringutils::replaceAll(host,"h","");
|
||
|
|
port = stringutils::replaceAll(port,"p","");
|
||
|
|
|
||
|
|
DServerCmdCallBackCommunication *dscCallBack =
|
||
|
|
new DServerCmdCallBackCommunication(host, port
|
||
|
|
#ifdef SEND_SHUFFLE_FUN_DEBUG
|
||
|
|
, "SHUFFLESEND"
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
// cout << "SENDER "
|
||
|
|
//<< host << ":" << port << " connecting!" << endl;
|
||
|
|
|
||
|
|
if(dscCallBack -> createGlobalSocket())
|
||
|
|
{
|
||
|
|
// now connected to the DServerCmdShuffleMultipleConn
|
||
|
|
if (!(dscCallBack -> getTagFromCallBack("STARTMULTIPLYCONN")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("OK")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR2" << dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// get the number of workers, which will be receiving
|
||
|
|
// data
|
||
|
|
if (!(dscCallBack -> getTextFromCallBack("SRCWSIZE", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR3" << dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int srcSize = atoi(line.data());
|
||
|
|
|
||
|
|
vector<string> destHost(srcSize);
|
||
|
|
vector<int> destToPort(srcSize);
|
||
|
|
int expectedstate = 0; // 0 - host, 1 - toPort
|
||
|
|
unsigned long destCnt = 0;
|
||
|
|
bool runIt = true;
|
||
|
|
bool noError = true;
|
||
|
|
string errMsg;
|
||
|
|
|
||
|
|
do{
|
||
|
|
if (expectedstate == 0)
|
||
|
|
{
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
getTextFromCallBack("SRCWHOST", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
destHost[destCnt] = line;
|
||
|
|
expectedstate = 1;
|
||
|
|
}
|
||
|
|
else if (expectedstate == 1)
|
||
|
|
{
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
getTextFromCallBack("SRCWTPORT", line)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
destToPort[destCnt] = atoi(line.data());
|
||
|
|
destCnt ++;
|
||
|
|
expectedstate = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("OK")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
runIt =
|
||
|
|
dscCallBack ->
|
||
|
|
getTagFromCallBackTF("NEXT", "DONE", noError);
|
||
|
|
if (!noError)
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
} while (runIt);
|
||
|
|
|
||
|
|
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("READY")))
|
||
|
|
{
|
||
|
|
cerr << "ERRORA:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// now sending tuples
|
||
|
|
ThreadedMemoryCounter memCntr (qp->GetMemorySize(s) * 1024 * 1024);
|
||
|
|
|
||
|
|
Word current = SetWord( Address (0) );
|
||
|
|
|
||
|
|
Stream<Tuple> inTupleStream(args[0]);
|
||
|
|
inTupleStream.open();
|
||
|
|
|
||
|
|
Tuple* tuple1;
|
||
|
|
// setup CommandQueue for each server;
|
||
|
|
vector<DServerShuffleSender*> serverCommand(srcSize);
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
//ZThread::PoolExecutor poolEx(2);
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
|
||
|
|
for(int i = 0; i < srcSize; i++)
|
||
|
|
{
|
||
|
|
serverCommand[i] =
|
||
|
|
new DServerShuffleSender(destHost[i],
|
||
|
|
int2Str(destToPort[i]),
|
||
|
|
&memCntr);
|
||
|
|
|
||
|
|
poolEx.execute(serverCommand[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
Word value;
|
||
|
|
ArgVectorPointer funargs;
|
||
|
|
|
||
|
|
while( !invalidIndex &&
|
||
|
|
(tuple1 =
|
||
|
|
DBAccess::getInstance() ->
|
||
|
|
TS_Request(inTupleStream)) != 0)
|
||
|
|
{
|
||
|
|
// ArrayIndex
|
||
|
|
int arrIndex = 0;
|
||
|
|
|
||
|
|
funargs = qp->Argument(args[1].addr);
|
||
|
|
((*funargs)[0]).setAddr(tuple1);
|
||
|
|
qp->Request(args[1].addr, value);
|
||
|
|
if ( ((CcInt*)value.addr)->IsDefined())
|
||
|
|
arrIndex = ((CcInt*)value.addr)->GetIntval();
|
||
|
|
|
||
|
|
if (arrIndex >= srcSize ||
|
||
|
|
arrIndex < 0)
|
||
|
|
{
|
||
|
|
errMsg = "INVALID INDEX (" +
|
||
|
|
int2Str(arrIndex) + ")";
|
||
|
|
noError = false;
|
||
|
|
invalidIndex = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
memCntr.request(tuple1 -> GetSize());
|
||
|
|
|
||
|
|
serverCommand[arrIndex] -> AppendTuple(tuple1);
|
||
|
|
}
|
||
|
|
//number ++;
|
||
|
|
} // while (...)
|
||
|
|
|
||
|
|
for(int i = 0; i < srcSize; i++)
|
||
|
|
{
|
||
|
|
//cout << "DONE: " << i << endl;
|
||
|
|
serverCommand[i] -> done();
|
||
|
|
}
|
||
|
|
|
||
|
|
poolEx.wait();
|
||
|
|
|
||
|
|
inTupleStream.close();
|
||
|
|
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
cerr << "Could not distribute data!" << endl;
|
||
|
|
cerr << e.what() << endl;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!noError)
|
||
|
|
{
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("ERROR")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
string errorMsg ="Shuffle: error sending tuples!";
|
||
|
|
if (!errMsg.empty())
|
||
|
|
errorMsg += "Reason: " + errMsg;
|
||
|
|
|
||
|
|
if (!(dscCallBack ->
|
||
|
|
sendTextToCallBack("ERRORDESC", errorMsg)))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!(dscCallBack -> sendTagToCallBack("DONE")))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:"
|
||
|
|
<< dscCallBack -> getErrorText() << endl;
|
||
|
|
delete dscCallBack;
|
||
|
|
((Attribute *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
delete dscCallBack;
|
||
|
|
}
|
||
|
|
|
||
|
|
((CcInt*)result.addr)->Set(1);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
const string sendShuffleSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>-</text--->"
|
||
|
|
"<text>-</text--->"
|
||
|
|
"<text>Internal Usage by DistributedAlgebra</text--->"
|
||
|
|
"<text>-</text---> ))";
|
||
|
|
|
||
|
|
Operator sendShuffle(
|
||
|
|
"d_send_shuffle",
|
||
|
|
sendShuffleSpec,
|
||
|
|
sendShuffleFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
sendShuffleTypeMap);
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
|
||
|
|
5.8 Operator distribute
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
static ListExpr distributeTypeMap( ListExpr inargs )
|
||
|
|
{
|
||
|
|
NList args(inargs);
|
||
|
|
if( args.length() == 4)
|
||
|
|
{
|
||
|
|
NList stream_desc = args.first();
|
||
|
|
ListExpr attr_desc = args.second().listExpr();
|
||
|
|
|
||
|
|
NList workers = args.fourth();
|
||
|
|
|
||
|
|
// check worker rel
|
||
|
|
if (!workers.isList() ||
|
||
|
|
!listutils::isRelDescription(workers.listExpr()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
first().
|
||
|
|
second().isSymbol(CcString::BasicType()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
args.typeError
|
||
|
|
("workers must be of type\
|
||
|
|
(rel(tuple([Server:string, Port:int]))) )");
|
||
|
|
}
|
||
|
|
|
||
|
|
if( stream_desc.isList() &&
|
||
|
|
stream_desc.first().isSymbol(Symbol::STREAM())
|
||
|
|
&& (stream_desc.length() == 2)
|
||
|
|
&& (nl->AtomType(attr_desc) == SymbolType))
|
||
|
|
{
|
||
|
|
ListExpr tuple_desc = stream_desc.second().listExpr();
|
||
|
|
string attr_name = nl->SymbolValue(attr_desc);
|
||
|
|
|
||
|
|
if(nl->IsEqual(nl->First(tuple_desc),Tuple::BasicType()) &&
|
||
|
|
nl->ListLength(tuple_desc) == 2)
|
||
|
|
{
|
||
|
|
ListExpr attrL = nl->Second(tuple_desc);
|
||
|
|
|
||
|
|
if(IsTupleDescription(attrL))
|
||
|
|
{
|
||
|
|
int attrIndex;
|
||
|
|
ListExpr attrType;
|
||
|
|
|
||
|
|
attrIndex = FindAttribute(attrL,attr_name,attrType);
|
||
|
|
|
||
|
|
if(nl->ListLength(attrL > 1) && attrIndex > 0
|
||
|
|
&& nl->IsEqual(attrType,CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr attrL2 = nl -> TheEmptyList();
|
||
|
|
ListExpr last = nl -> TheEmptyList();
|
||
|
|
|
||
|
|
while(!nl->IsEmpty(attrL))
|
||
|
|
{
|
||
|
|
ListExpr attr = nl->First(attrL);
|
||
|
|
|
||
|
|
if(nl->SymbolValue(nl->First(attr)) !=
|
||
|
|
attr_name)
|
||
|
|
{
|
||
|
|
if(nl->IsEmpty(attrL2))
|
||
|
|
{
|
||
|
|
attrL2 = nl->OneElemList(attr);
|
||
|
|
last = attrL2;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
last = nl->Append(last,attr);
|
||
|
|
}
|
||
|
|
|
||
|
|
attrL = nl->Rest(attrL);
|
||
|
|
}
|
||
|
|
return
|
||
|
|
nl->ThreeElemList(
|
||
|
|
nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->IntAtom(attrIndex),
|
||
|
|
NList(NList(tuple_desc).convertToString(),
|
||
|
|
true, true).listExpr()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->SymbolAtom(DArray::BasicType()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->SymbolAtom(Relation::BasicType()),
|
||
|
|
nl->TwoElemList(
|
||
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
||
|
|
attrL2))));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return args.typeError("input is not (stream(tuple(y))) x ...");
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
distributeFun (Word* args, Word& result,
|
||
|
|
int message, Word& local,
|
||
|
|
Supplier s)
|
||
|
|
{
|
||
|
|
int size = ((CcInt*)(args[2].addr))->GetIntval();
|
||
|
|
|
||
|
|
GenericRelation* r = (GenericRelation*)args[3].addr;
|
||
|
|
GenericRelationIterator* rit = r->MakeScan();
|
||
|
|
ListExpr reltype;
|
||
|
|
nl->ReadFromString("(rel (tuple ((Server string) (Port int))))",
|
||
|
|
reltype);
|
||
|
|
ListExpr serverlist = Relation::Out(reltype,rit);
|
||
|
|
|
||
|
|
int attrIndex = ((CcInt*)(args[4].addr))->GetIntval() - 1;
|
||
|
|
string attrIndexStr (int2Str(attrIndex));
|
||
|
|
|
||
|
|
string sendTType = ((FText*)args[5].addr)->GetValue();
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
ListExpr sendTypeNum;
|
||
|
|
nl->ReadFromString(sendTType,sendTypeNum);
|
||
|
|
sendTypeNum = sc->NumericType(sendTypeNum);
|
||
|
|
sendTType = nl -> ToString(sendTypeNum);
|
||
|
|
|
||
|
|
ListExpr restype = nl->Second(qp->GetType(s));
|
||
|
|
restype = sc->NumericType(restype);
|
||
|
|
DArray* array = (DArray*)(qp->ResultStorage(s)).addr;
|
||
|
|
|
||
|
|
array->initialize(restype,getArrayName(DArray::no),
|
||
|
|
size, serverlist);
|
||
|
|
|
||
|
|
// setup tuple queue for each server;
|
||
|
|
ThreadedMemoryCounter memCntr (qp->GetMemorySize(s) * 1024 * 1024);
|
||
|
|
vector<DServerMultiCommand*> serverCommand(size);
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0; i < size; i++)
|
||
|
|
{
|
||
|
|
serverCommand[i] =
|
||
|
|
new DServerMultiCommand(&memCntr);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
DServerCmdWriteRelParam writeRelParam(&serverCommand,
|
||
|
|
sendTType,
|
||
|
|
attrIndexStr);
|
||
|
|
bool success = true;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
success = array -> runCommandThreaded<DServerCmdWriteRel,
|
||
|
|
DServerCmdWriteRelParam>(poolEx,
|
||
|
|
writeRelParam,
|
||
|
|
false);
|
||
|
|
if (success)
|
||
|
|
{
|
||
|
|
Stream<Tuple> inTupleStream(args[0]);
|
||
|
|
inTupleStream.open();
|
||
|
|
|
||
|
|
Tuple* tuple1;
|
||
|
|
|
||
|
|
cout << "Reading Data ..." << endl;
|
||
|
|
|
||
|
|
while( (tuple1 =
|
||
|
|
DBAccess::getInstance() ->
|
||
|
|
TS_Request(inTupleStream)) != 0)
|
||
|
|
{
|
||
|
|
DBAccessGuard::getInstance() -> T_IncReference(tuple1);
|
||
|
|
// ArrayIndex
|
||
|
|
int arrIndex =
|
||
|
|
((CcInt*)(tuple1->
|
||
|
|
GetAttribute(attrIndex)))->GetIntval();
|
||
|
|
|
||
|
|
assert (arrIndex >= 0);
|
||
|
|
|
||
|
|
arrIndex = arrIndex % size;
|
||
|
|
|
||
|
|
memCntr.request(tuple1 -> GetSize());
|
||
|
|
|
||
|
|
serverCommand[arrIndex] -> AppendTuple(tuple1);
|
||
|
|
DBAccessGuard::getInstance() -> T_DeleteIfAllowed(tuple1);
|
||
|
|
|
||
|
|
} // while (...)
|
||
|
|
|
||
|
|
inTupleStream.close();
|
||
|
|
|
||
|
|
cout << "Reading Data done ..." << endl;
|
||
|
|
}
|
||
|
|
for(int i = 0; i < size; i++)
|
||
|
|
{
|
||
|
|
serverCommand[i] -> done();
|
||
|
|
}
|
||
|
|
|
||
|
|
poolEx.wait();
|
||
|
|
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
cerr << "Could not distribute data!" << endl;
|
||
|
|
cerr << e.what() << endl;
|
||
|
|
array -> SetUndefined();
|
||
|
|
result = SetWord(array);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!success)
|
||
|
|
{
|
||
|
|
cerr << "Could not distribute data!" << endl;
|
||
|
|
array -> SetUndefined();
|
||
|
|
result = SetWord(array);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
cout << "Closing connections ..." << endl;
|
||
|
|
array -> destroyAnyChilds();
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0; i < size; i++)
|
||
|
|
delete serverCommand[i];
|
||
|
|
|
||
|
|
|
||
|
|
result.addr = array;
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
const string distributeSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((stream (tuple ((x1 t1) ... (xn tn)))) xi int (rel(tuple("
|
||
|
|
"[Server:string, Port: int]))) ) -> "
|
||
|
|
"(darray (rel (tuple ((x1 t1) ... (xi-1 ti-1)"
|
||
|
|
"(xi+1 ti+1) ... (xn tn)))))</text--->"
|
||
|
|
"<text>_ ddistribute [ _ , _ , _]</text--->"
|
||
|
|
"<text>Distributes a stream of tuples"
|
||
|
|
"into a darray of relations.</text--->"
|
||
|
|
"<text>plz feed ddistribute [pkg,3,server_rel]</text--->))";
|
||
|
|
|
||
|
|
Operator distributeA (
|
||
|
|
"ddistribute",
|
||
|
|
distributeSpec,
|
||
|
|
distributeFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
distributeTypeMap );
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
|
||
|
|
5.8 Operator shuffle
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
template<int dim>
|
||
|
|
static ListExpr shuffleTypeMap( ListExpr inargs )
|
||
|
|
{
|
||
|
|
ListExpr errRes = nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
NList m_args(inargs);
|
||
|
|
NList params;
|
||
|
|
|
||
|
|
if(m_args.length() == dim + 1)
|
||
|
|
{
|
||
|
|
|
||
|
|
NList mapdesc = m_args.elem(2);
|
||
|
|
|
||
|
|
if (mapdesc.first().length() != 3 )
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Invalid function description");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
if (mapdesc.first().first() != NList(Symbol::MAP()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError(
|
||
|
|
"First argument must be a function!");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
if (mapdesc.first().elem(3) == NList(Symbol::TYPEERROR()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError("Function contains an error!");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
if (mapdesc.first().elem(3) != NList(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError
|
||
|
|
("Function return value must be of type <int>!");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
NList funcExpr = mapdesc.second().third();
|
||
|
|
|
||
|
|
params = NList();
|
||
|
|
|
||
|
|
params.append(NList(NList(NList(funcExpr.
|
||
|
|
convertToString(),
|
||
|
|
true, true))));
|
||
|
|
|
||
|
|
NList darraydesc = m_args.first().elem(1);
|
||
|
|
|
||
|
|
// check for correct types
|
||
|
|
if (darraydesc.length() != 2)
|
||
|
|
{
|
||
|
|
ErrorReporter::ReportError(
|
||
|
|
"First object must be of type <darray>!");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!darraydesc.first().isSymbol(DArray::BasicType()))
|
||
|
|
{
|
||
|
|
|
||
|
|
ErrorReporter::ReportError(
|
||
|
|
"First object must be of type <darray>!");
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (dim == 3)
|
||
|
|
{
|
||
|
|
NList workers = m_args.fourth().first();
|
||
|
|
|
||
|
|
// check worker rel
|
||
|
|
if (!workers.isList() ||
|
||
|
|
!listutils::isRelDescription(workers.listExpr()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
first().
|
||
|
|
second().isSymbol(CcString::BasicType()) ||
|
||
|
|
!workers.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
second().isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
m_args.typeError
|
||
|
|
("workers must be of type\
|
||
|
|
(rel(tuple([Server:string, Port:int]))) )");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
NList res =
|
||
|
|
NList(NList(Symbols::APPEND()),
|
||
|
|
NList(params),
|
||
|
|
|
||
|
|
darraydesc);
|
||
|
|
|
||
|
|
return res.listExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Arguments (for dim == 3):
|
||
|
|
// 0 - source DArray
|
||
|
|
// 1 - index function (unused)
|
||
|
|
// 2 - destination size (optional)
|
||
|
|
// 3 - worker relation (optional)
|
||
|
|
// appended args:
|
||
|
|
// 4 - index function (string)
|
||
|
|
|
||
|
|
template<int dim>
|
||
|
|
static int
|
||
|
|
shuffleFun (Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
DArray* sourceArray = (DArray *)(args[0].addr);
|
||
|
|
DArray* destArray = (DArray*)(qp->ResultStorage(s)).addr;
|
||
|
|
|
||
|
|
// check source DArray
|
||
|
|
if (sourceArray == 0 ||
|
||
|
|
sourceArray -> getServerManager() == 0 ||
|
||
|
|
!(sourceArray -> getServerManager() -> isOk()) )
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DArray not initialized corretly!" << endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(sourceArray -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "Undefined DArray!" << endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// setup size of source and destination DArray
|
||
|
|
const int srcSize = sourceArray -> getSize();
|
||
|
|
int destSize = -1;
|
||
|
|
|
||
|
|
if (dim > 1)
|
||
|
|
destSize = ((CcInt*)(args[2].addr))->GetIntval();
|
||
|
|
else
|
||
|
|
// destination size was not set
|
||
|
|
destSize = srcSize;
|
||
|
|
|
||
|
|
if (destSize < 1)
|
||
|
|
{
|
||
|
|
cerr << "Undefined DArray size!" << endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if (destSize > 36 ||
|
||
|
|
srcSize > 36 )
|
||
|
|
{
|
||
|
|
cerr << "DArray size may not be larger than 36!" << endl;
|
||
|
|
destArray -> SetUndefined();
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
ListExpr serverlist = nl -> TheEmptyList();
|
||
|
|
|
||
|
|
if (dim == 3) // worker relation is given; read it!
|
||
|
|
{
|
||
|
|
GenericRelation* r = (GenericRelation*)args[3].addr;
|
||
|
|
GenericRelationIterator* rit = r->MakeScan();
|
||
|
|
ListExpr reltype;
|
||
|
|
nl->
|
||
|
|
ReadFromString("(rel (tuple ((Server string) (Port int))))",
|
||
|
|
reltype);
|
||
|
|
serverlist = Relation::Out(reltype,rit);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
serverlist = sourceArray -> getServerList();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nl -> IsEmpty(serverlist))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: No workers defined!" << endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
string sendFunc = ((FText*)args[dim + 1].addr)->GetValue();
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
|
||
|
|
ListExpr restype = nl->Second(qp->GetType(s));
|
||
|
|
restype = sc->NumericType(restype);
|
||
|
|
|
||
|
|
destArray->initialize(restype,getArrayName(DArray::no),
|
||
|
|
destSize, serverlist);
|
||
|
|
|
||
|
|
if (!(destArray -> getServerManager() -> isOk() ))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DArray not initialized correctly!" << endl;
|
||
|
|
cerr << destArray -> getServerManager() -> getErrorText()
|
||
|
|
<< endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(destArray -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "Undefined DArray!" << endl;
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// mapping for source <--> destination
|
||
|
|
vector<vector<string> > sourceWorker (destSize);
|
||
|
|
vector<vector<int> > sourceToDestWorkerIdx (destSize);
|
||
|
|
vector<vector<int> > sourceToDestFromPort (destSize);
|
||
|
|
|
||
|
|
// mapping for destination <--> source
|
||
|
|
vector<vector<string> >destWorker (srcSize);
|
||
|
|
vector<vector<int> > destToSourceToPort (srcSize);
|
||
|
|
|
||
|
|
int basePort = 1900;
|
||
|
|
// init vecotrs of inner loop
|
||
|
|
for (unsigned long destWorkerSize = 0;
|
||
|
|
destWorkerSize < (unsigned long) destSize; ++destWorkerSize)
|
||
|
|
{
|
||
|
|
sourceWorker[destWorkerSize] = vector<string> (srcSize);
|
||
|
|
sourceToDestFromPort[destWorkerSize] = vector<int> (srcSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (unsigned long srcWorkerSize = 0;
|
||
|
|
srcWorkerSize < (unsigned long) srcSize; ++srcWorkerSize)
|
||
|
|
{
|
||
|
|
destWorker[srcWorkerSize] =
|
||
|
|
vector<string>(destSize);
|
||
|
|
destToSourceToPort[srcWorkerSize] =
|
||
|
|
vector<int> (destSize);
|
||
|
|
for (unsigned long destWorkerSize = 0;
|
||
|
|
destWorkerSize < (unsigned long) destSize;
|
||
|
|
++destWorkerSize)
|
||
|
|
{
|
||
|
|
string worker =
|
||
|
|
sourceArray -> getHostNameByIndex(srcWorkerSize);
|
||
|
|
int fromPort = basePort++;
|
||
|
|
|
||
|
|
// compile information for the destination worker
|
||
|
|
// source -> destination
|
||
|
|
// first index: destination worker idx
|
||
|
|
// second index: source worker idx
|
||
|
|
// source host
|
||
|
|
sourceWorker[destWorkerSize][srcWorkerSize] = worker;
|
||
|
|
// source port
|
||
|
|
sourceToDestFromPort[destWorkerSize][srcWorkerSize] =
|
||
|
|
fromPort;
|
||
|
|
|
||
|
|
// compile information for the source worker
|
||
|
|
// destination -> source
|
||
|
|
// first index: source worker idx
|
||
|
|
// second index: destination worker idx
|
||
|
|
// destination host
|
||
|
|
destWorker[srcWorkerSize][destWorkerSize] = worker;
|
||
|
|
|
||
|
|
// source port (same as for destination worker
|
||
|
|
destToSourceToPort[srcWorkerSize][destWorkerSize] =
|
||
|
|
fromPort;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// initiate source workers
|
||
|
|
if (!(sourceArray -> getServerManager() -> isOk()))
|
||
|
|
{
|
||
|
|
//Close additional connections
|
||
|
|
destArray -> destroyAnyChilds();
|
||
|
|
sourceArray -> destroyAnyChilds();
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const int srcBasePort = 1700;
|
||
|
|
const int destBasePort = 1800;
|
||
|
|
|
||
|
|
bool abort = false;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
ZThread::ThreadedExecutor poolEx2;
|
||
|
|
|
||
|
|
DServerCmdShuffleRecParam destParams (destBasePort);
|
||
|
|
|
||
|
|
if (!(destArray ->
|
||
|
|
runCommandThreaded <DServerCmdShuffleRec,
|
||
|
|
DServerCmdShuffleRecParam>
|
||
|
|
( poolEx2, // Executor
|
||
|
|
destParams, // Parameters
|
||
|
|
false))) // NOT wait for thread to end
|
||
|
|
{
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!abort)
|
||
|
|
{
|
||
|
|
DServerCmdShuffleSendParam sourceParams
|
||
|
|
(sendFunc, // sender function
|
||
|
|
srcBasePort); // base port number
|
||
|
|
|
||
|
|
if (!(sourceArray ->
|
||
|
|
runCommandThreaded <DServerCmdShuffleSend,
|
||
|
|
DServerCmdShuffleSendParam>
|
||
|
|
( poolEx2, // Executor
|
||
|
|
sourceParams, // Parameters
|
||
|
|
false))) // NOT wait for thread to end
|
||
|
|
{
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout << "DSHUFFLE - Sender and Reciver started" << endl;
|
||
|
|
|
||
|
|
// create connectoions betweem source and destination servers;
|
||
|
|
// and start shuffleing!
|
||
|
|
if (! abort)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
ZThread::ThreadedExecutor poolEx4;
|
||
|
|
DServerCmdShuffleMultiConnParam srcMulitParams
|
||
|
|
(DServerCmdShuffleMultiConnParam::DSC_SMC_P_SENDER,
|
||
|
|
srcBasePort, destWorker, destToSourceToPort);
|
||
|
|
|
||
|
|
//cout << " START Source Multiplyer" << endl;
|
||
|
|
if (!(sourceArray ->
|
||
|
|
runCommandThreaded<DServerCmdShuffleMultiConn,
|
||
|
|
DServerCmdShuffleMultiConnParam>
|
||
|
|
( poolEx4, // Executor
|
||
|
|
srcMulitParams, // Parameters
|
||
|
|
false, // NOT wait for thread to end
|
||
|
|
false))) // Do Not multiply workers again
|
||
|
|
{
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout << " START dest Multiplyer" << endl;
|
||
|
|
DServerCmdShuffleMultiConnParam destMulitParams
|
||
|
|
(DServerCmdShuffleMultiConnParam::DSC_SMC_P_RECEIVER,
|
||
|
|
destBasePort, sourceWorker, sourceToDestFromPort);
|
||
|
|
|
||
|
|
if (!(destArray ->
|
||
|
|
runCommandThreaded <DServerCmdShuffleMultiConn,
|
||
|
|
DServerCmdShuffleMultiConnParam>
|
||
|
|
( poolEx4, // Executor
|
||
|
|
destMulitParams, // Parameters
|
||
|
|
false, // NOT wait for thread to end
|
||
|
|
false))) // Do Not multiply workers again
|
||
|
|
{
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
poolEx4.wait();
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if (abort)
|
||
|
|
{
|
||
|
|
//Close additional connections
|
||
|
|
destArray -> destroyAnyChilds();
|
||
|
|
sourceArray -> destroyAnyChilds();
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
poolEx2.wait(); // command threads
|
||
|
|
}
|
||
|
|
catch(ZThread::Synchronization_Exception& e)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
DServerManager* destMan = destArray->getServerManager();
|
||
|
|
DServerManager* sourceMan = sourceArray->getServerManager();
|
||
|
|
|
||
|
|
|
||
|
|
for(int i = 0;
|
||
|
|
(i < (sourceMan -> getNoOfUsedWorkers(sourceArray->getSize()))) &&
|
||
|
|
!abort; i++)
|
||
|
|
{
|
||
|
|
DServer* w = sourceMan -> getServerByID(i);
|
||
|
|
|
||
|
|
if (w -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DShuffle encountered errors:\n"
|
||
|
|
<< endl;
|
||
|
|
cerr << w -> getErrorText() << endl;
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for(int i = 0;
|
||
|
|
(i < (destMan -> getNoOfUsedWorkers(destArray->getSize()))) &&
|
||
|
|
!abort; i++)
|
||
|
|
{
|
||
|
|
DServer* w = destMan -> getServerByID(i);
|
||
|
|
if (w -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DShuffle encountered errors:\n"
|
||
|
|
<< endl;
|
||
|
|
cerr << w -> getErrorText() << endl;
|
||
|
|
abort = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int dest_server_no = destMan -> getNoOfMultiWorkers(destSize);
|
||
|
|
int src_server_no = sourceMan -> getNoOfMultiWorkers(srcSize);
|
||
|
|
|
||
|
|
if (abort)
|
||
|
|
{
|
||
|
|
cout << "ERROR! CLEAN IT UP!" << endl;
|
||
|
|
|
||
|
|
//Close additional connections
|
||
|
|
for(int k = 0; k<dest_server_no;k++)
|
||
|
|
destArray ->getServerManager()->
|
||
|
|
getServerByID(k)->DestroyChilds();
|
||
|
|
|
||
|
|
//Close additional connections
|
||
|
|
for(int k = 0; k<src_server_no;k++)
|
||
|
|
sourceMan->getServerByID(k)->DestroyChilds();
|
||
|
|
|
||
|
|
destArray -> SetDefined(false);
|
||
|
|
result.addr = destArray;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
cout << "DShuffle finished! " << endl;
|
||
|
|
|
||
|
|
//Close additional connections
|
||
|
|
destArray -> destroyAnyChilds();
|
||
|
|
sourceArray -> destroyAnyChilds();
|
||
|
|
|
||
|
|
result.addr = destArray;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string shuffleSpec3 =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) ((map t int) int (rel(tuple("
|
||
|
|
"[Server:string, Port: int]))) ) -> darray t</text>"
|
||
|
|
"<text>_ dshuffle [fun, _ , _]</text--->"
|
||
|
|
"<text>Redistributes a distirbuted array.</text--->"
|
||
|
|
"<text>query darr dschuffle [randint(3), 3,server_rel]</text--->))";
|
||
|
|
|
||
|
|
Operator shuffle3 (
|
||
|
|
"dshuffle",
|
||
|
|
shuffleSpec3,
|
||
|
|
shuffleFun<3>,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
shuffleTypeMap<3> );
|
||
|
|
|
||
|
|
const string shuffleSpec2 =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) ((map t int) int )) -> darray t</text>"
|
||
|
|
"<text>_ dshuffle2 [fun, _ , _]</text--->"
|
||
|
|
"<text>Redistributes a distirbuted array.</text--->"
|
||
|
|
"<text>query darr dschuffle2 [randint(3), 3]</text--->))";
|
||
|
|
|
||
|
|
Operator shuffle2 (
|
||
|
|
"dshuffle2",
|
||
|
|
shuffleSpec2,
|
||
|
|
shuffleFun<2>,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
shuffleTypeMap<2> );
|
||
|
|
|
||
|
|
const string shuffleSpec1 =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) ((map t int))) -> darray t</text>"
|
||
|
|
"<text>_ dshuffle1 [fun, _ , _]</text--->"
|
||
|
|
"<text>Redistributes a distirbuted array.</text--->"
|
||
|
|
"<text>query darr dschuffle1 [randint(3)]</text--->))";
|
||
|
|
|
||
|
|
Operator shuffle1 (
|
||
|
|
"dshuffle1",
|
||
|
|
shuffleSpec1,
|
||
|
|
shuffleFun<1>,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
shuffleTypeMap<1> );
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.9 Operator loop
|
||
|
|
|
||
|
|
*/
|
||
|
|
template< int dim>
|
||
|
|
static ListExpr loopTypeMap(ListExpr args)
|
||
|
|
{
|
||
|
|
|
||
|
|
//cout << "LoopTM " << dim << " :" << nl -> ToString(args) << " -> ";
|
||
|
|
ListExpr errRes = nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
|
||
|
|
NList m_args(args);
|
||
|
|
NList params;
|
||
|
|
|
||
|
|
if(m_args.length() == dim + 1)
|
||
|
|
{
|
||
|
|
NList mapdesc = m_args.elem(dim + 1);
|
||
|
|
|
||
|
|
if (mapdesc.first().length() != dim + 2 )
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mapdesc.first().first() != NList(Symbol::MAP()))
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
if (mapdesc.first().elem(dim+2) == NList(Symbol::TYPEERROR()))
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
params = NList(dim).enclose();
|
||
|
|
|
||
|
|
params.append(NList(NList(NList(mapdesc.
|
||
|
|
second().
|
||
|
|
elem(dim + 2).
|
||
|
|
convertToString(),
|
||
|
|
true, true))));
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < dim; ++i)
|
||
|
|
{
|
||
|
|
NList darraydesc = m_args.elem(i + 1);
|
||
|
|
|
||
|
|
// check for correct types
|
||
|
|
if (darraydesc.length() != 2)
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
if(darraydesc.first() == (DArray::BasicType()))
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
//check, if darray and map are equal
|
||
|
|
if (darraydesc.first().second() !=
|
||
|
|
mapdesc.first().elem(i + 2))
|
||
|
|
{
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
params.append(NList
|
||
|
|
(NList
|
||
|
|
(mapdesc.second().
|
||
|
|
elem(i + 2).first().
|
||
|
|
convertToString(), true)));
|
||
|
|
}
|
||
|
|
|
||
|
|
NList res =
|
||
|
|
NList(NList(Symbols::APPEND()),
|
||
|
|
params,
|
||
|
|
|
||
|
|
NList(NList(DArray::BasicType()),
|
||
|
|
mapdesc.first().elem(dim + 2)));
|
||
|
|
|
||
|
|
//cout << res.convertToString() << endl;
|
||
|
|
return res.listExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
return errRes;
|
||
|
|
}
|
||
|
|
|
||
|
|
template< int dim>
|
||
|
|
static int loopValueMap
|
||
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
ListExpr type = sc->NumericType(nl->Second((qp->GetType(s))));
|
||
|
|
string command = ((FText*)args[dim + 2].addr)->GetValue();
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor exec;
|
||
|
|
DServer* server;
|
||
|
|
|
||
|
|
int size = 0;
|
||
|
|
ListExpr serverList;
|
||
|
|
vector<string> from;
|
||
|
|
|
||
|
|
string rpl = "!";
|
||
|
|
for (int i = 0; i < dim; i ++)
|
||
|
|
{
|
||
|
|
DArray* alt = (DArray*)args[i].addr;
|
||
|
|
if (alt == NULL ||
|
||
|
|
!(alt -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Input DArray is not defined!" << endl;
|
||
|
|
((DArray *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (size == 0)
|
||
|
|
{
|
||
|
|
size = alt -> getSize();
|
||
|
|
}
|
||
|
|
|
||
|
|
size = min(size, alt -> getSize());
|
||
|
|
|
||
|
|
serverList = alt->getServerList();
|
||
|
|
|
||
|
|
if (nl -> IsEmpty(serverList))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Input DArray worker list is empty!"
|
||
|
|
<< endl;
|
||
|
|
((DArray *) result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
from.push_back(alt->getName());
|
||
|
|
// TODO: need to compare server lists!
|
||
|
|
|
||
|
|
string elementname =
|
||
|
|
((CcString*)args[i+ dim + 3].addr) -> GetValue();
|
||
|
|
command = stringutils::replaceAll(command, elementname, rpl);
|
||
|
|
rpl += "!";
|
||
|
|
}
|
||
|
|
|
||
|
|
//cout << "CMD:" << command << endl;
|
||
|
|
|
||
|
|
string name = getArrayName(DArray::no);
|
||
|
|
|
||
|
|
DArray* neu = ((DArray*)(result.addr));
|
||
|
|
neu ->initialize(type,
|
||
|
|
name,
|
||
|
|
size,
|
||
|
|
serverList);
|
||
|
|
|
||
|
|
ZThread::ThreadedExecutor poolEx;
|
||
|
|
|
||
|
|
DServerCmdExecuteParam execParam(command,
|
||
|
|
from);
|
||
|
|
|
||
|
|
|
||
|
|
bool containsError = false;
|
||
|
|
|
||
|
|
if (neu -> runCommandThreaded<DServerCmdExecute,
|
||
|
|
DServerCmdExecuteParam>(poolEx,
|
||
|
|
execParam))
|
||
|
|
{
|
||
|
|
// all ok
|
||
|
|
for (int i = 0;
|
||
|
|
i < neu -> getServerManager() ->
|
||
|
|
getNoOfUsedWorkers(neu -> getSize()); ++i)
|
||
|
|
{
|
||
|
|
DServer *w = neu -> getServerManager() -> getServerByID(i);
|
||
|
|
if (w -> hasError())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Worker " << i << " reports:" << endl
|
||
|
|
<< w -> getErrorText() << endl;
|
||
|
|
containsError = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
containsError = true;
|
||
|
|
cerr << "ERROR: loop command reported an error" << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if (containsError)
|
||
|
|
{
|
||
|
|
((DArray*)(result.addr)) -> SetUndefined();
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
const string loopSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) (map t u)) -> (darray u)</text--->"
|
||
|
|
"<text>_ dloopa_old [ fun ]</text--->"
|
||
|
|
"<text>Evaluates each element with a function, "
|
||
|
|
"that needs to be given"
|
||
|
|
"as paremeter function </text--->"
|
||
|
|
"<text>query plz_a20 dloop_old[. count]</text--->))";
|
||
|
|
struct loopaSpec : OperatorInfo {
|
||
|
|
loopaSpec() : OperatorInfo() {
|
||
|
|
name = "dloopa_old";
|
||
|
|
signature = "((darray t) (darray u) (map t u r)) -> (darray r)";
|
||
|
|
syntax = "_ _ dloopa_old [ fun ]";
|
||
|
|
meaning =
|
||
|
|
"Evaluates each element of each darray with a function, "
|
||
|
|
"that needs to be given as paremeter function";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
Operator loopA (
|
||
|
|
"dloop_old",
|
||
|
|
loopSpec,
|
||
|
|
loopValueMap<1>,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
loopTypeMap <1>);
|
||
|
|
|
||
|
|
Operator dloopA (loopaSpec(),
|
||
|
|
loopValueMap<2>,
|
||
|
|
loopTypeMap <2>);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.10.1 Type Operator DELEMENT
|
||
|
|
(derived from Operator ELEMENT of the ArrayAlgebra)
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr delementTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//cout << "DelTM:" << nl -> ToString(args) << " -> ";
|
||
|
|
if(nl->ListLength(args) >= 1)
|
||
|
|
{
|
||
|
|
ListExpr first = nl->First(args);
|
||
|
|
if (nl->ListLength(first) == 2)
|
||
|
|
{
|
||
|
|
if (nl->IsEqual(nl->First(first), DArray::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr res = nl->Second(first);
|
||
|
|
//cout << nl -> ToString(res) << endl;
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
const string DELEMENTSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Remarks\" )"
|
||
|
|
"( <text>((array t) ... ) -> t</text--->"
|
||
|
|
"<text>type operator</text--->"
|
||
|
|
"<text>Extracts the type of the elements "
|
||
|
|
"from a darray type given "
|
||
|
|
"as the first argument.</text--->"
|
||
|
|
"<text>not for use with sos-syntax</text---> ))";
|
||
|
|
|
||
|
|
Operator dElementA (
|
||
|
|
"DELEMENT",
|
||
|
|
DELEMENTSpec,
|
||
|
|
0,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
delementTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.10.2 Type Operator DELEMENT2
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr delement2TypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//cout << "Del2TM:" << nl -> ToString(args) << " -> ";
|
||
|
|
if(nl->ListLength(args) >= 2)
|
||
|
|
{
|
||
|
|
ListExpr second = nl->Second(args);
|
||
|
|
if (nl->ListLength(second) == 2)
|
||
|
|
{
|
||
|
|
if (nl->IsEqual(nl->First(second), DArray::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr res = nl->Second(second);
|
||
|
|
cout << nl -> ToString(res) << endl;
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
const string DELEMENT2Spec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Remarks\" )"
|
||
|
|
"( <text>((array t) ... ) -> t</text--->"
|
||
|
|
"<text>type operator</text--->"
|
||
|
|
"<text>Extracts the type of the elements "
|
||
|
|
"from a darray type given "
|
||
|
|
"as the second argument.</text--->"
|
||
|
|
"<text>not for use with sos-syntax</text---> ))";
|
||
|
|
|
||
|
|
Operator dElementA2 (
|
||
|
|
"DELEMENT2",
|
||
|
|
DELEMENT2Spec,
|
||
|
|
0,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
delement2TypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.10.2 Type Operator DRELATION
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr dRelTypeMap( ListExpr inArgs )
|
||
|
|
{
|
||
|
|
NList args (inArgs);
|
||
|
|
//cout << "DRELTM:" << args.convertToString() << " -> ";
|
||
|
|
args = args.first();
|
||
|
|
|
||
|
|
if(args.length() >= 2)
|
||
|
|
{
|
||
|
|
|
||
|
|
if (args.first().isSymbol(DArray::BasicType()))
|
||
|
|
{
|
||
|
|
NList second = args.second();
|
||
|
|
|
||
|
|
if (second.length() == 2 &&
|
||
|
|
second.first().isSymbol(Relation::BasicType()))
|
||
|
|
{
|
||
|
|
NList res = second.second();
|
||
|
|
//cout << res.convertToString() << endl;
|
||
|
|
return res.listExpr();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ErrorReporter::ReportError(
|
||
|
|
"Only DArrays of type Relation allowed here!");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
const string DRELSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Remarks\" )"
|
||
|
|
"( <text>DRELATION</text--->"
|
||
|
|
"<text>type operator</text--->"
|
||
|
|
"<text>Internal operator for darray. "
|
||
|
|
"Is replaced by current index</text--->"
|
||
|
|
"<text>not for use with sos-syntax</text---> ))";
|
||
|
|
|
||
|
|
Operator drel (
|
||
|
|
"DRELATION",
|
||
|
|
DRELSpec,
|
||
|
|
0,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
dRelTypeMap );
|
||
|
|
/*
|
||
|
|
|
||
|
|
5.10.2 Type Operator d[_]idx
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr dindexTypeMap( ListExpr inArgs )
|
||
|
|
{
|
||
|
|
NList args (inArgs);
|
||
|
|
//cout << "dindex:" << args.convertToString() << " -> ";
|
||
|
|
if(args.length() == 0)
|
||
|
|
{
|
||
|
|
NList result = NList(NList(CcInt::BasicType()));
|
||
|
|
//cout << result.convertToString() << endl;
|
||
|
|
return result.listExpr();
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
static int dindexValueMap
|
||
|
|
(Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((CcInt*)result.addr)->Set(1);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string DINDEXSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Remarks\" )"
|
||
|
|
"( <text>d_idx() -> int</text--->"
|
||
|
|
"<text>type operator</text--->"
|
||
|
|
"<text>Internal operator for darray. "
|
||
|
|
"Is replaced by current index</text--->"
|
||
|
|
"<text>not for use with sos-syntax</text---> ))";
|
||
|
|
|
||
|
|
Operator dIndex (
|
||
|
|
"d_idx",
|
||
|
|
DINDEXSpec,
|
||
|
|
dindexValueMap,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
dindexTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.11 Operator ~dtie~
|
||
|
|
|
||
|
|
The operator calculates a single "value" of an
|
||
|
|
darray by evaluating the elements of an darray
|
||
|
|
with a given function from left to right, e.g.
|
||
|
|
|
||
|
|
dtie ( (a1, a2, ... , an), + ) = a1 + a2 + ... + an
|
||
|
|
|
||
|
|
The formal specification of type mapping is:
|
||
|
|
|
||
|
|
---- ((darray t) (map t t t)) -> t
|
||
|
|
----
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr
|
||
|
|
dtieTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//cout << "DTieTM:" << nl -> ToString(args) << " -> ";
|
||
|
|
if (nl->ListLength(args) == 2)
|
||
|
|
{
|
||
|
|
ListExpr arrayDesc = nl->First(args);
|
||
|
|
ListExpr mapDesc = nl->Second(args);
|
||
|
|
|
||
|
|
if ((nl->ListLength(arrayDesc) == 2)
|
||
|
|
&& (nl->ListLength(mapDesc) == 4))
|
||
|
|
{
|
||
|
|
if (nl->IsEqual(nl->First(arrayDesc), DArray::BasicType())
|
||
|
|
&& nl->IsEqual(nl->First(mapDesc), Symbol::MAP()))
|
||
|
|
{
|
||
|
|
ListExpr elementDesc = nl->Second(arrayDesc);
|
||
|
|
|
||
|
|
if (nl->Equal(elementDesc, nl->Second(mapDesc))
|
||
|
|
&& nl->Equal(elementDesc, nl->Third(mapDesc))
|
||
|
|
&& nl->Equal(elementDesc, nl->Fourth(mapDesc)))
|
||
|
|
{
|
||
|
|
//cout<< "DTie ResultType:"
|
||
|
|
// << nl -> ToString(elementDesc) << endl;
|
||
|
|
return elementDesc;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
dtieFun( Word* args, Word& result, int message,
|
||
|
|
Word& local, Supplier s )
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
DArray* array = ((DArray*)args[0].addr);
|
||
|
|
|
||
|
|
if (!array || !(array -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Input DArray is not defined correctly!" << endl;
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
||
|
|
ArgVectorPointer funargs = qp->Argument(args[1].addr);
|
||
|
|
Word funresult;
|
||
|
|
|
||
|
|
ListExpr typeOfElement = sc->NumericType(qp->GetType(s));
|
||
|
|
|
||
|
|
int algebraId;
|
||
|
|
int typeId;
|
||
|
|
arrayalgebra::extractIds(typeOfElement, algebraId, typeId);
|
||
|
|
|
||
|
|
const int n = array->getSize();
|
||
|
|
|
||
|
|
if (n == 0)
|
||
|
|
{
|
||
|
|
cerr << "ERROR: DArray is empty !" << endl;
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
array->refresh();
|
||
|
|
|
||
|
|
if ( !(array -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Could not transfer data of input DArray !" << endl;
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//copy the first element
|
||
|
|
Word partResult =
|
||
|
|
(am->CloneObj(algebraId, typeId))(typeOfElement,
|
||
|
|
(Word)array->get(0));
|
||
|
|
|
||
|
|
|
||
|
|
Attribute* a = static_cast<Attribute*>
|
||
|
|
((am->Cast(algebraId,typeId))(partResult.addr));
|
||
|
|
|
||
|
|
if (a == NULL ||
|
||
|
|
!(a -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Partial result is not defined1!" << endl;
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
for (int i=1; i<n; i++)
|
||
|
|
{
|
||
|
|
Word ielem =
|
||
|
|
(am->CloneObj(algebraId, typeId))(typeOfElement,
|
||
|
|
(Word)array->get(i));
|
||
|
|
|
||
|
|
a = static_cast<Attribute*>
|
||
|
|
((am->Cast(algebraId,typeId))(ielem.addr));
|
||
|
|
|
||
|
|
if ( a == NULL ||
|
||
|
|
!(a -> IsDefined()))
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Partial result is not defined2!" << endl;
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
((Attribute *)result.addr) -> SetDefined(false);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//copy the next element
|
||
|
|
|
||
|
|
(*funargs)[0] = partResult;
|
||
|
|
(*funargs)[1] = ielem;
|
||
|
|
|
||
|
|
// calculate the intermediate result;
|
||
|
|
qp->Request(args[1].addr, funresult);
|
||
|
|
|
||
|
|
if (funresult.addr != partResult.addr) {
|
||
|
|
|
||
|
|
// delete the previous intermediate result
|
||
|
|
(am->DeleteObj(algebraId, typeId))
|
||
|
|
(typeOfElement, partResult);
|
||
|
|
|
||
|
|
// assign the next intermediate result
|
||
|
|
partResult =
|
||
|
|
arrayalgebra::Array::genericClone(algebraId, typeId,
|
||
|
|
typeOfElement, funresult);
|
||
|
|
}
|
||
|
|
// delete the current element
|
||
|
|
(am->DeleteObj(algebraId, typeId))(typeOfElement,ielem);
|
||
|
|
}
|
||
|
|
// In the next statement the (by the Query Processor)
|
||
|
|
// provided place forthe result is not used in order
|
||
|
|
// to be flexible with regard to the result type.
|
||
|
|
|
||
|
|
result.addr = partResult.addr;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string dtieSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray t) (map t t u)) -> u</text--->"
|
||
|
|
"<text>_ tie [ fun ]</text--->"
|
||
|
|
"<text>Calculates the \"value\" of an darray "
|
||
|
|
"evaluating the elements of "
|
||
|
|
"the darray with a given function from left to right.</text--->"
|
||
|
|
"<text>query ai tie[fun(i:int,l:int)(i+l)]</text---> ))";
|
||
|
|
|
||
|
|
Operator dtie(
|
||
|
|
"dtie",
|
||
|
|
dtieSpec,
|
||
|
|
dtieFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
dtieTypeMap );
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.12 Operator ~dsummarize[_]old~
|
||
|
|
|
||
|
|
The operator ~dsummarize[_]old~ provides a stream of tuples from a
|
||
|
|
darray of relations. For this purpose, the operator scans
|
||
|
|
all relations beginning with the first relation of the array.
|
||
|
|
|
||
|
|
The formal specification of type mapping is:
|
||
|
|
|
||
|
|
---- ((darray (rel t))) -> (stream t)
|
||
|
|
|
||
|
|
at which t is of the type tuple
|
||
|
|
----
|
||
|
|
|
||
|
|
Note that the operator ~dsummarize[_]old~ is not exactly inverse
|
||
|
|
to the operator ~ddistribute~ because the indexy of the relation
|
||
|
|
is not appended to the attributes of the outgoing tuples. If the
|
||
|
|
darray has been constructed by the operator ~ddistribute~ the
|
||
|
|
order of the resulting stream in most cases does not correspond
|
||
|
|
to the order of the input stream of the operator ~ddistribute~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static ListExpr
|
||
|
|
dsummarizeTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//cout << "dsummarizeTM:" << nl -> ToString(args) << endl;
|
||
|
|
if (nl->ListLength(args) == 1)
|
||
|
|
{
|
||
|
|
ListExpr arrayDesc = nl->First(args);
|
||
|
|
|
||
|
|
if (nl->ListLength(arrayDesc) == 2
|
||
|
|
&& nl->IsEqual(nl->First(arrayDesc), DArray::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr relDesc = nl->Second(arrayDesc);
|
||
|
|
|
||
|
|
if (nl->ListLength(relDesc) == 2
|
||
|
|
&& nl->IsEqual(nl->First(relDesc), Relation::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr tupleDesc = nl->Second(relDesc);
|
||
|
|
if (nl->IsEqual(nl->First(tupleDesc), Tuple::BasicType()))
|
||
|
|
{
|
||
|
|
ListExpr ret = nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
||
|
|
nl->Second(relDesc));
|
||
|
|
//out << nl -> ToString(ret) << endl;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ErrorReporter::ReportError(
|
||
|
|
"dsummarize_old: Input type darray( rel( tuple(...))) expected!");
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
class DArrayIteratorRefreshThread : public ZThread::Runnable
|
||
|
|
{
|
||
|
|
|
||
|
|
public:
|
||
|
|
DArray *d;
|
||
|
|
TFQ tfqOut;
|
||
|
|
ThreadedMemoryCounter *memCntr;
|
||
|
|
|
||
|
|
DArrayIteratorRefreshThread()
|
||
|
|
: ZThread::Runnable() {}
|
||
|
|
|
||
|
|
void run()
|
||
|
|
{
|
||
|
|
d -> refresh(tfqOut, memCntr);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
~DArrayIteratorRefreshThread() { }
|
||
|
|
};
|
||
|
|
|
||
|
|
static int
|
||
|
|
dsummarizeFun( Word* args, Word& result, int message,
|
||
|
|
Word& local, Supplier s )
|
||
|
|
{
|
||
|
|
//cout << "dsummarizeFun" << endl;
|
||
|
|
struct DArrayIterator
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
DArray *da;
|
||
|
|
TFQ m_tfqOut;
|
||
|
|
ZThread::ThreadedExecutor m_exe;
|
||
|
|
bool m_error;
|
||
|
|
ThreadedMemoryCounter m_memCntr;
|
||
|
|
|
||
|
|
public:
|
||
|
|
DArrayIterator(DArray* d, size_t allowed_mem_size)
|
||
|
|
: da(d)
|
||
|
|
, m_tfqOut(new TupleFifoQueue())
|
||
|
|
, m_memCntr(allowed_mem_size)
|
||
|
|
{
|
||
|
|
assert (da != NULL);
|
||
|
|
m_error = false;
|
||
|
|
|
||
|
|
if ( d == 0 ||
|
||
|
|
!(d -> IsDefined()) ||
|
||
|
|
!(d -> getServerManager() -> checkServers(false)))
|
||
|
|
|
||
|
|
{
|
||
|
|
//cout << "DSFI ERROR!" << endl;
|
||
|
|
m_error = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
DArrayIteratorRefreshThread *darrRefresh =
|
||
|
|
new DArrayIteratorRefreshThread();
|
||
|
|
//cout << "DSFI init!" << endl;
|
||
|
|
|
||
|
|
darrRefresh -> d = d;
|
||
|
|
darrRefresh -> tfqOut = m_tfqOut;
|
||
|
|
|
||
|
|
// see below, why this is NULL
|
||
|
|
darrRefresh -> memCntr = NULL; // &m_memCntr
|
||
|
|
|
||
|
|
//start collector thread
|
||
|
|
m_exe.execute(darrRefresh);
|
||
|
|
|
||
|
|
// all Done!;
|
||
|
|
|
||
|
|
// need to first store all the data on the master
|
||
|
|
// this is really bad, since we cannot use threads
|
||
|
|
// for streams nor memory allocation checking.
|
||
|
|
// the reason is, that post commands (eg. count)
|
||
|
|
// are not implemented threadsave!
|
||
|
|
|
||
|
|
m_exe.wait();
|
||
|
|
// all Done!;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
~DArrayIterator()
|
||
|
|
{
|
||
|
|
delete m_tfqOut;
|
||
|
|
}
|
||
|
|
|
||
|
|
Tuple* getNextTuple()
|
||
|
|
{
|
||
|
|
if (m_error)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
//cout << "NEXT TUPLE:" << endl;
|
||
|
|
// no threads are running, no need for DBAccessGuard
|
||
|
|
Tuple* t = m_tfqOut -> get();
|
||
|
|
|
||
|
|
//
|
||
|
|
// we cannot check for allocated memory!
|
||
|
|
//if (t != NULL)
|
||
|
|
// {
|
||
|
|
// cout << "TFQ GET:" << t -> GetSize() << endl;
|
||
|
|
// m_memCntr.put_back(t -> GetSize());
|
||
|
|
// }
|
||
|
|
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool hasError() const { return m_error; }
|
||
|
|
};
|
||
|
|
|
||
|
|
DArrayIterator* dait = 0;
|
||
|
|
dait = (DArrayIterator*)local.addr;
|
||
|
|
|
||
|
|
switch (message) {
|
||
|
|
case OPEN : {
|
||
|
|
//cout << "OPEN" << endl;
|
||
|
|
DArray *da = (DArray*)args[0].addr;
|
||
|
|
assert (da != NULL);
|
||
|
|
|
||
|
|
dait =
|
||
|
|
new DArrayIterator(da, qp->GetMemorySize(s) * 1024 * 1024);
|
||
|
|
local.addr = dait;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
case REQUEST : {
|
||
|
|
|
||
|
|
//cout << "RQUEST" << endl;
|
||
|
|
if (dait -> hasError())
|
||
|
|
{
|
||
|
|
//cout << " -> send Cancel1" << endl;
|
||
|
|
result.setAddr(0);
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
|
||
|
|
Tuple* t = dait->getNextTuple();
|
||
|
|
|
||
|
|
if (t != 0) {
|
||
|
|
result = SetWord(t);
|
||
|
|
//DBAccessGuard::getInstance() -> T_DeleteIfAllowed(t);
|
||
|
|
return YIELD;
|
||
|
|
}
|
||
|
|
//cout << "RQUEST DONE" << endl;
|
||
|
|
//cout << " -> send Cancel2" << endl;
|
||
|
|
result.setAddr(0);
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
case CLOSE : {
|
||
|
|
//cout << "CLOSE" << endl;
|
||
|
|
if(local.addr)
|
||
|
|
{
|
||
|
|
dait = (DArrayIterator*)local.addr;
|
||
|
|
delete dait;
|
||
|
|
local.setAddr(0);
|
||
|
|
}
|
||
|
|
qp->Close(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
default : {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string dsummarizeSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"( <text>((darray (rel t))) -> (stream t)</text--->"
|
||
|
|
"<text>_ dsummarize_old</text--->"
|
||
|
|
"<text>Produces a stream of the tuples from all relations in the "
|
||
|
|
"darray.</text--->"
|
||
|
|
"<text>query prel dsummarize_old consume</text---> ))";
|
||
|
|
|
||
|
|
Operator dsummarize (
|
||
|
|
"dsummarize_old",
|
||
|
|
dsummarizeSpec,
|
||
|
|
dsummarizeFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
dsummarizeTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.14 Operator ~checkworkers~
|
||
|
|
|
||
|
|
The operator ~ceckworkers~ takes a relation of
|
||
|
|
type host:string, port:int and checks, if there
|
||
|
|
exists a running instance of SecondoMonitor at
|
||
|
|
the specified host, listening at the specified port
|
||
|
|
It also checks, if the database distributed is available.
|
||
|
|
|
||
|
|
*/
|
||
|
|
static bool
|
||
|
|
sendCommandToWorker(Socket *inServer,
|
||
|
|
const string inCmd,
|
||
|
|
const string inExpectedResponse,
|
||
|
|
string &outMsg)
|
||
|
|
{
|
||
|
|
if(inServer == 0 || !inServer->IsOk())
|
||
|
|
{
|
||
|
|
outMsg = "Cannot connect to worker";
|
||
|
|
if (inServer != 0)
|
||
|
|
{
|
||
|
|
outMsg += ":" + inServer -> GetErrorText();
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
iostream &iosock = inServer -> GetSocketStream();
|
||
|
|
|
||
|
|
// check db distributed available
|
||
|
|
if (!iosock.good())
|
||
|
|
{
|
||
|
|
outMsg = "(5) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// cout << "OUT:" << "<Secondo>" << endl << "1" << endl
|
||
|
|
// << inCmd << endl
|
||
|
|
// << "</Secondo>" << endl;
|
||
|
|
|
||
|
|
iosock << "<Secondo>" << endl << "1" << endl
|
||
|
|
<< inCmd << endl
|
||
|
|
<< "</Secondo>" << endl;
|
||
|
|
|
||
|
|
if (!iosock.good())
|
||
|
|
{
|
||
|
|
outMsg = "(6) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string line;
|
||
|
|
getline( iosock, line );
|
||
|
|
//cout << "GOT:" << line << endl;
|
||
|
|
|
||
|
|
bool foundResult = inExpectedResponse.empty()? true : false;
|
||
|
|
bool gotError = false;
|
||
|
|
stringstream allLines;
|
||
|
|
if(line=="<SecondoResponse>")
|
||
|
|
{
|
||
|
|
do
|
||
|
|
{
|
||
|
|
if (!iosock.good())
|
||
|
|
{
|
||
|
|
outMsg =
|
||
|
|
"(7) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
getline( iosock, line );
|
||
|
|
if (line.find("</SecondoResponse>") == string::npos)
|
||
|
|
allLines << line << endl;
|
||
|
|
|
||
|
|
|
||
|
|
if(line.find("ERROR") != string::npos ||
|
||
|
|
line.find("Error") != string::npos ||
|
||
|
|
line.find("error") != string::npos)
|
||
|
|
{
|
||
|
|
//cout << " -> GOT ERROR!";
|
||
|
|
gotError = true;
|
||
|
|
}
|
||
|
|
else if (line.find(inExpectedResponse) != string::npos)
|
||
|
|
{
|
||
|
|
//cout << " -> GOT IT!";
|
||
|
|
foundResult = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
while(line.find("</SecondoResponse>") == string::npos);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
outMsg = "Unexpected response from worker";
|
||
|
|
|
||
|
|
if (gotError)
|
||
|
|
{
|
||
|
|
outMsg = allLines.str();
|
||
|
|
//cerr << "GOT ERROR:" << outMsg;
|
||
|
|
foundResult = false;
|
||
|
|
}
|
||
|
|
return foundResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool
|
||
|
|
openConnection(Socket *inServer,
|
||
|
|
string &outMsg)
|
||
|
|
{
|
||
|
|
string line;
|
||
|
|
if(inServer == 0 || !inServer->IsOk())
|
||
|
|
{
|
||
|
|
outMsg = "Cannot connect to worker";
|
||
|
|
if (inServer != 0)
|
||
|
|
{
|
||
|
|
outMsg += ":" + inServer -> GetErrorText();
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
iostream &ioSock = inServer->GetSocketStream();
|
||
|
|
|
||
|
|
if (!inServer -> IsOk())
|
||
|
|
{
|
||
|
|
outMsg = "Cannot access worker socket";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
do
|
||
|
|
{
|
||
|
|
if (!ioSock.good())
|
||
|
|
{
|
||
|
|
outMsg = "(1):";
|
||
|
|
switch (ioSock.rdstate())
|
||
|
|
{
|
||
|
|
default:
|
||
|
|
outMsg += " nospecified";
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
outMsg += " Communication is blocked! Restart Worker:";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
getline( ioSock, line );
|
||
|
|
|
||
|
|
} while (line.empty());
|
||
|
|
|
||
|
|
bool startupOK = true;
|
||
|
|
|
||
|
|
if(line=="<SecondoOk/>")
|
||
|
|
{
|
||
|
|
if (!ioSock.good())
|
||
|
|
{
|
||
|
|
outMsg = "(2) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
ioSock << "<Connect>" << endl << endl
|
||
|
|
<< endl << "</Connect>" << endl;
|
||
|
|
if (!ioSock.good())
|
||
|
|
{
|
||
|
|
outMsg = "(3) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
getline( ioSock, line );
|
||
|
|
|
||
|
|
if( line == "<SecondoIntro>")
|
||
|
|
{
|
||
|
|
do
|
||
|
|
{
|
||
|
|
if (!ioSock.good())
|
||
|
|
{
|
||
|
|
outMsg =
|
||
|
|
"(4) Communication is blocked! Restart Worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
getline( ioSock, line);
|
||
|
|
|
||
|
|
} while(line != "</SecondoIntro>");
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
startupOK = false;
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
startupOK = false;
|
||
|
|
|
||
|
|
if (!startupOK)
|
||
|
|
{
|
||
|
|
outMsg = "Unexpected response from worker";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(inServer -> IsOk()))
|
||
|
|
{
|
||
|
|
outMsg = "Cannot Connect to Worker";
|
||
|
|
return false;
|
||
|
|
} // if (!(inServer -> IsOk()))
|
||
|
|
|
||
|
|
return startupOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void closeConnection(Socket *ioServer)
|
||
|
|
{
|
||
|
|
iostream &ioSock = ioServer -> GetSocketStream();
|
||
|
|
ioSock << "<Disconnect/>" << endl;
|
||
|
|
ioServer->Close();
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool
|
||
|
|
checkWorkerRunning(const string &host, int port,
|
||
|
|
const string &cmd, string &msg)
|
||
|
|
{
|
||
|
|
cout << "checking worker on " << host << ":" << port << endl;
|
||
|
|
// check worker running
|
||
|
|
string line;
|
||
|
|
|
||
|
|
Socket* server = Socket::Connect( host, int2Str(port),
|
||
|
|
Socket::SockGlobalDomain,
|
||
|
|
5,
|
||
|
|
1);
|
||
|
|
|
||
|
|
if (server == 0)
|
||
|
|
{
|
||
|
|
msg = "Unable to open connection to Worker!";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (!openConnection(server, msg))
|
||
|
|
{
|
||
|
|
if (server != 0)
|
||
|
|
{
|
||
|
|
server->Close();
|
||
|
|
delete server;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!sendCommandToWorker(server,
|
||
|
|
"open database distributed",
|
||
|
|
"",
|
||
|
|
msg))
|
||
|
|
{
|
||
|
|
if (server != 0)
|
||
|
|
{
|
||
|
|
server->Close();
|
||
|
|
delete server;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!sendCommandToWorker(server,
|
||
|
|
cmd,
|
||
|
|
"",
|
||
|
|
msg))
|
||
|
|
{
|
||
|
|
if (server != 0)
|
||
|
|
{
|
||
|
|
server->Close();
|
||
|
|
delete server;
|
||
|
|
}
|
||
|
|
msg =
|
||
|
|
"Database \"distributed\" in use";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
closeConnection(server);
|
||
|
|
delete server;
|
||
|
|
server=0;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ListExpr
|
||
|
|
checkWorkersTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
//cout << "CheckWorkersTM" << nl -> ToString(args) << " -> ";
|
||
|
|
NList myargs = NList(args).first();
|
||
|
|
|
||
|
|
if (myargs.hasLength(2) && myargs.first().isSymbol(sym.STREAM()))
|
||
|
|
{
|
||
|
|
NList tupTypeL( myargs.second().second());
|
||
|
|
|
||
|
|
if (tupTypeL.length() >= 2)
|
||
|
|
{
|
||
|
|
if (!tupTypeL.
|
||
|
|
first().
|
||
|
|
second().
|
||
|
|
isSymbol(CcString::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError(
|
||
|
|
"First attribute must be the server name");
|
||
|
|
}
|
||
|
|
if (!tupTypeL.
|
||
|
|
second().
|
||
|
|
second().
|
||
|
|
isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError(
|
||
|
|
"Second attribute must be the port number");
|
||
|
|
}
|
||
|
|
//The return-type of checkWorkers is
|
||
|
|
// a stream of workers each appended w/ a status msg;
|
||
|
|
NList app (NList("Status"), NList(CcString::BasicType()));
|
||
|
|
|
||
|
|
NList tuple =
|
||
|
|
NList(tupTypeL.first(), tupTypeL.second(), app);
|
||
|
|
|
||
|
|
NList result = NList().tupleStreamOf(tuple);
|
||
|
|
//cout << result.convertToString() << endl;
|
||
|
|
return result.listExpr();
|
||
|
|
}
|
||
|
|
return
|
||
|
|
NList::typeError("Tuple stream has not enough attributes");
|
||
|
|
}
|
||
|
|
|
||
|
|
return
|
||
|
|
NList::typeError(
|
||
|
|
"Expecting a stream of tuples(Server:string, port:int)");
|
||
|
|
}
|
||
|
|
|
||
|
|
struct CwLocalInfo
|
||
|
|
{
|
||
|
|
TupleType *resTupleType;
|
||
|
|
vector<pair<string, int> > hostport;
|
||
|
|
string cmd;
|
||
|
|
|
||
|
|
CwLocalInfo(ListExpr inTT){ resTupleType = new TupleType(inTT); }
|
||
|
|
~CwLocalInfo() { resTupleType -> DeleteIfAllowed(); }
|
||
|
|
};
|
||
|
|
|
||
|
|
static int
|
||
|
|
checkWorkersFun (Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
CwLocalInfo *localInfo;
|
||
|
|
Tuple *curTuple;
|
||
|
|
Tuple *resTuple;
|
||
|
|
Word cTupleWord;
|
||
|
|
|
||
|
|
switch (message)
|
||
|
|
{
|
||
|
|
case OPEN:
|
||
|
|
{
|
||
|
|
cout << "Checking workers" << endl;
|
||
|
|
qp->Open(args[0].addr);
|
||
|
|
|
||
|
|
ListExpr resultTupleNL = GetTupleResultType(s);
|
||
|
|
|
||
|
|
localInfo = new CwLocalInfo(nl->Second(resultTupleNL));
|
||
|
|
|
||
|
|
localInfo -> cmd = "let test1 = \"test\"";
|
||
|
|
|
||
|
|
local.setAddr(localInfo);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
case REQUEST:
|
||
|
|
{
|
||
|
|
if (local.addr == 0)
|
||
|
|
return CANCEL;
|
||
|
|
|
||
|
|
localInfo = (CwLocalInfo*)local.addr;
|
||
|
|
|
||
|
|
|
||
|
|
qp->Request(args[0].addr, cTupleWord);
|
||
|
|
if (qp->Received(args[0].addr))
|
||
|
|
{
|
||
|
|
curTuple = (Tuple*)cTupleWord.addr;
|
||
|
|
string host =
|
||
|
|
((CcString*)(curTuple->GetAttribute(0)))->GetValue();
|
||
|
|
int port =
|
||
|
|
((CcInt*)(curTuple->GetAttribute(1)))->GetValue();
|
||
|
|
curTuple -> DeleteIfAllowed();
|
||
|
|
string msg = "OK";
|
||
|
|
|
||
|
|
bool retVal = checkWorkerRunning(host, port,
|
||
|
|
localInfo -> cmd, msg);
|
||
|
|
if (!retVal)
|
||
|
|
{
|
||
|
|
msg = "ERROR: " + msg + "!";
|
||
|
|
}
|
||
|
|
|
||
|
|
resTuple = new Tuple(localInfo->resTupleType);
|
||
|
|
resTuple->PutAttribute(0, new CcString(true, host));
|
||
|
|
resTuple->PutAttribute(1, new CcInt(true, port));
|
||
|
|
resTuple->PutAttribute(2, new CcString(true, msg));
|
||
|
|
|
||
|
|
localInfo ->
|
||
|
|
hostport.push_back(
|
||
|
|
make_pair<string, int>(host, port));
|
||
|
|
|
||
|
|
result.setAddr(resTuple);
|
||
|
|
return YIELD;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
case CLOSE:
|
||
|
|
{
|
||
|
|
if (local.addr == 0)
|
||
|
|
return CANCEL;
|
||
|
|
|
||
|
|
localInfo = (CwLocalInfo*)local.addr;
|
||
|
|
localInfo -> cmd = "delete test1";
|
||
|
|
|
||
|
|
while( !localInfo -> hostport.empty() )
|
||
|
|
{
|
||
|
|
string msg = "OK";
|
||
|
|
checkWorkerRunning(localInfo -> hostport.back().first,
|
||
|
|
localInfo -> hostport.back().second,
|
||
|
|
localInfo -> cmd, msg);
|
||
|
|
|
||
|
|
localInfo -> hostport.pop_back();
|
||
|
|
}
|
||
|
|
|
||
|
|
delete localInfo;
|
||
|
|
local.setAddr(0);
|
||
|
|
qp->Close(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string checkWorkersSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"(<text>((stream (tuple ((Server string) (Port int))))) -> "
|
||
|
|
"((stream (tuple ((Server string) "
|
||
|
|
"(Port int) (Status string)))))</text--->"
|
||
|
|
"<text>_ check_workers</text--->"
|
||
|
|
"<text>checks workers, if running and database 'distributed'"
|
||
|
|
"exists</text--->"
|
||
|
|
"<text>query workers check_workers</text---> ))";
|
||
|
|
|
||
|
|
Operator checkWorkers (
|
||
|
|
"check_workers",
|
||
|
|
checkWorkersSpec,
|
||
|
|
checkWorkersFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
checkWorkersTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.15 Operator ~startup~
|
||
|
|
|
||
|
|
The operator ~startup~ takes host, port, configfile, createDistrDBFlag,
|
||
|
|
user, password, bindir, and starts a SecondoServer at the specified location.
|
||
|
|
It returns true, if server start was successful
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static bool createRemoteDistrDB(string host, int port)
|
||
|
|
{
|
||
|
|
bool retVal = true;
|
||
|
|
|
||
|
|
cout << " -> Creating Remote DB 'distributed' "
|
||
|
|
<< "on host " << host << " port:" << port << endl;
|
||
|
|
|
||
|
|
DSecondoMonitorCommunication secondoMonitor( host, int2Str(port));
|
||
|
|
|
||
|
|
if (retVal &&
|
||
|
|
!secondoMonitor.openConnection())
|
||
|
|
{
|
||
|
|
cerr << "ERROR:" << secondoMonitor.getErrorText() << endl;
|
||
|
|
retVal = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (retVal &&
|
||
|
|
!secondoMonitor.sendSecondoCmdToWorkerSOS("delete database distributed"))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:";
|
||
|
|
if (secondoMonitor.hasCmdError())
|
||
|
|
cerr << secondoMonitor.getCmdErrorText();
|
||
|
|
else
|
||
|
|
cerr << secondoMonitor.getErrorText();
|
||
|
|
cerr << endl;
|
||
|
|
|
||
|
|
retVal = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (retVal &&
|
||
|
|
!secondoMonitor.sendSecondoCmdToWorkerSOS("create database distributed"))
|
||
|
|
{
|
||
|
|
cerr << "ERROR:";
|
||
|
|
if (secondoMonitor.hasCmdError())
|
||
|
|
cerr << secondoMonitor.getCmdErrorText();
|
||
|
|
else
|
||
|
|
cerr << secondoMonitor.getErrorText();
|
||
|
|
cerr << endl;
|
||
|
|
|
||
|
|
retVal = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (retVal)
|
||
|
|
cout << " ... successfully";
|
||
|
|
else
|
||
|
|
cout << " ... failed";
|
||
|
|
cout << endl;
|
||
|
|
|
||
|
|
return retVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ListExpr
|
||
|
|
startupTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
NList myargs (args);
|
||
|
|
//cout << "StartupTM:" << myargs.convertToString() << " -> ";
|
||
|
|
if (myargs.length() >= 2 && myargs.length() <= 7)
|
||
|
|
{
|
||
|
|
if (!myargs.first().isSymbol(CcString::BasicType()))
|
||
|
|
{
|
||
|
|
return NList::typeError(
|
||
|
|
"First parameter must be the server name");
|
||
|
|
}
|
||
|
|
if (!myargs.second().isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return NList::typeError(
|
||
|
|
"Second parameter must be the port number");
|
||
|
|
}
|
||
|
|
if (!myargs.third().isSymbol(CcString::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError
|
||
|
|
("Third parameter must be the name of the SecondoConfigFile");
|
||
|
|
}
|
||
|
|
|
||
|
|
NList result = NList(NList(CcBool::BasicType()));
|
||
|
|
//cout << result.convertToString() << endl;
|
||
|
|
return result.listExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
return
|
||
|
|
NList::typeError
|
||
|
|
("Expecting at least server name, port and configuration file");
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
startupFun (Word* args, Word& result, int message,
|
||
|
|
Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
int args_cnt = qp->GetNoSons(s);
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
string host = ((CcString*)args[0].addr)->GetValue();
|
||
|
|
int port = ((CcInt*)args[1].addr)->GetValue();
|
||
|
|
string secConf = ((CcString*)args[2].addr)->GetValue();
|
||
|
|
bool createDB = false;
|
||
|
|
|
||
|
|
// checking optional parameters
|
||
|
|
// don't enter breaks here!
|
||
|
|
switch (args_cnt)
|
||
|
|
{
|
||
|
|
case 5:
|
||
|
|
// something to do ...
|
||
|
|
case 4:
|
||
|
|
createDB = ((CcBool*)args[3].addr)->GetValue();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (host.empty())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Please specify the host" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
else if (secConf.empty())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Please specify the SecondoConfig file" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ret_val)
|
||
|
|
{
|
||
|
|
cout << "Starting: SecondoMonitor on host "
|
||
|
|
<< host << ":" << port
|
||
|
|
<< " with " << secConf << endl;
|
||
|
|
|
||
|
|
string lckfile = "/tmp/SM_" + int2Str(port) + ".lck";
|
||
|
|
string devnull = "< /dev/null > /dev/null 2>&1";
|
||
|
|
|
||
|
|
string exportConf =
|
||
|
|
" export SECONDO_CONFIG=${HOME}/secondo/bin/" +
|
||
|
|
secConf + ";";
|
||
|
|
|
||
|
|
//string secondoBinDir =
|
||
|
|
// " export DISTR_SECONDO_BINDIR=/opt/psec/achmann-secondo/bin/;";
|
||
|
|
|
||
|
|
string lckfileexist = "if [ -r " + lckfile +
|
||
|
|
" ]; then echo 0; else echo 1; fi;";
|
||
|
|
string cddir = ". .bashrc; cd secondo/bin; ";
|
||
|
|
string cmd =
|
||
|
|
cddir +
|
||
|
|
lckfileexist +
|
||
|
|
exportConf +
|
||
|
|
//secondoBinDir +
|
||
|
|
" ./StartMonitor.remote " + devnull + " & ";
|
||
|
|
|
||
|
|
string retVal;
|
||
|
|
bool success = RunCmdSSH(host, cmd, retVal);
|
||
|
|
if (!success ||
|
||
|
|
retVal.empty() || retVal[0] != '1')
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Lock file '" + lckfile + "' exists!"
|
||
|
|
<< endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
string waitForLockFileCnt = "CNT=0 ;";
|
||
|
|
string waitForLockFileWhile = " until ";
|
||
|
|
string lckFileExistCond = "[ -e " + lckfile + " ]";
|
||
|
|
string waitForLockFileWhileCond =
|
||
|
|
"[ ${CNT} -gt 10 ] || " + lckFileExistCond + ";";
|
||
|
|
string waitForLockFileDo = "do sleep 1;";
|
||
|
|
string waitForLockFileWhileDone = "let CNT=CNT+1; done; ";
|
||
|
|
string retValCond = " if " + lckFileExistCond +
|
||
|
|
"; then echo 1; else echo 0; fi;";
|
||
|
|
|
||
|
|
|
||
|
|
cmd =
|
||
|
|
waitForLockFileCnt +
|
||
|
|
waitForLockFileWhile +
|
||
|
|
waitForLockFileWhileCond +
|
||
|
|
waitForLockFileDo +
|
||
|
|
waitForLockFileWhileDone +
|
||
|
|
retValCond;
|
||
|
|
|
||
|
|
success = RunCmdSSH(host, cmd, retVal);
|
||
|
|
if (!success ||
|
||
|
|
retVal.empty() || retVal[0] != '1')
|
||
|
|
{
|
||
|
|
cerr << "ERROR: Lock file '" + lckfile + "' not created!"
|
||
|
|
<< endl;
|
||
|
|
cout << "RET:" << retVal << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (//ret_val &&
|
||
|
|
createDB)
|
||
|
|
{
|
||
|
|
createRemoteDistrDB(host, port);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
cout << endl;
|
||
|
|
((CcBool*) (result.addr))->Set(true, ret_val);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string startupSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"(<text>startup (Server:string , Port:int,"
|
||
|
|
"SecondoConf:string, CreateDistrDB: bool) "
|
||
|
|
"-> bool</text--->"
|
||
|
|
"<text>startup (_, _, _)</text--->"
|
||
|
|
"<text>Starts a worker on a given host. On that host there "
|
||
|
|
"must be a directory ${HOME}/secondo/bin. In this directory "
|
||
|
|
"there must exists the StartMonitor.remote script. The given "
|
||
|
|
"SecondoConfig.ini file must exist there, too, with "
|
||
|
|
"a matching SecondoPort number."
|
||
|
|
"If the optional parameter CreateDistrDB is set to true, the"
|
||
|
|
"database 'distributed' will be restored</text--->"
|
||
|
|
"<text>startup (\"localhost\", 1234, "
|
||
|
|
"\"SecondoConfig.ini\" )</text---> ))";
|
||
|
|
|
||
|
|
Operator startUp (
|
||
|
|
"startup",
|
||
|
|
startupSpec,
|
||
|
|
startupFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
startupTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
5.16 Operator ~shutdown~
|
||
|
|
|
||
|
|
The operator ~shutdown~ takes host and port
|
||
|
|
and stops a SecondoServer at the
|
||
|
|
specified location.
|
||
|
|
It returns true, if server was stopped successfully.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
static ListExpr
|
||
|
|
shutdownTypeMap( ListExpr args )
|
||
|
|
{
|
||
|
|
NList myargs (args);
|
||
|
|
//cout << "ShutdownTM:" << myargs.convertToString() << " -> ";
|
||
|
|
if (myargs.length() >= 2 )
|
||
|
|
{
|
||
|
|
if (!myargs.first().isSymbol(CcString::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError(
|
||
|
|
"First parameter must be the server name");
|
||
|
|
}
|
||
|
|
if (!myargs.second().isSymbol(CcInt::BasicType()))
|
||
|
|
{
|
||
|
|
return
|
||
|
|
NList::typeError(
|
||
|
|
"Second parameter must be the port number");
|
||
|
|
}
|
||
|
|
|
||
|
|
NList result = NList(NList(CcBool::BasicType()));
|
||
|
|
//cout << result.convertToString() << endl;
|
||
|
|
return result.listExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
return
|
||
|
|
NList::typeError("Expecting at least server name and port");
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
shutdownFun (Word* args, Word& result,
|
||
|
|
int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
bool ret_val = true;
|
||
|
|
|
||
|
|
string host = ((CcString*)args[0].addr)->GetValue();
|
||
|
|
int port = ((CcInt*)args[1].addr)->GetValue();
|
||
|
|
|
||
|
|
// retrieving pid for SecondoMonitor
|
||
|
|
// stored in /tmp/SM_<port>.lck on that host
|
||
|
|
string killPid; // store pid of SecondoMonitor
|
||
|
|
string lckfile = "/tmp/SM_" + int2Str(port) + ".lck";
|
||
|
|
string cat_cmd = "cat " + lckfile;
|
||
|
|
bool success = RunCmdSSH(host, cat_cmd, killPid);
|
||
|
|
|
||
|
|
if (!success || killPid.empty())
|
||
|
|
{
|
||
|
|
cerr << "ERROR: No lock file '" + lckfile + "' found!" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ret_val)
|
||
|
|
{
|
||
|
|
// now killing that process w/ kill -SIGTERM <pid>
|
||
|
|
// and removing the lockfile /tmp/SM_<port>.lck
|
||
|
|
killPid = stringutils::replaceAll(killPid,"\n","");
|
||
|
|
|
||
|
|
string kill_cmd = "kill -SIGTERM " + killPid + ";";
|
||
|
|
string rm_cmd = " /bin/rm " + lckfile + ";";
|
||
|
|
|
||
|
|
string cmd = "if [ ! -r "+ lckfile +
|
||
|
|
" ]; then echo 0; else " +
|
||
|
|
kill_cmd + rm_cmd + " echo 1; fi";
|
||
|
|
|
||
|
|
string retVal;
|
||
|
|
success = RunCmdSSH(host, cmd, retVal);
|
||
|
|
|
||
|
|
if (!success || retVal.empty() || retVal[0] != '1')
|
||
|
|
{
|
||
|
|
cerr << "ERROR: No lock file '" + lckfile +
|
||
|
|
"' found!" << endl;
|
||
|
|
ret_val = false;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
cout << "Stopped SecondoMonitor on "
|
||
|
|
<< host << ":" << port << endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
((CcBool*) (result.addr))->Set(true, ret_val);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const string shutdownSpec =
|
||
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
||
|
|
"(<text>shutdown (Server:string , Port:int) -> bool</text--->"
|
||
|
|
"<text>shutdown (_, _)</text--->"
|
||
|
|
"<text>kills worker on a host given in input </text--->"
|
||
|
|
"<text>shutdown(\"localhost\", 1234)</text---> ))";
|
||
|
|
|
||
|
|
Operator shutDown (
|
||
|
|
"shutdown",
|
||
|
|
shutdownSpec,
|
||
|
|
shutdownFun,
|
||
|
|
Operator::SimpleSelect,
|
||
|
|
shutdownTypeMap );
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
6 Creating the Algebra
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
class DistributedAlgebra : public Algebra
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
DistributedAlgebra() : Algebra()
|
||
|
|
{
|
||
|
|
AddTypeConstructor( &darrayTC );
|
||
|
|
darrayTC.AssociateKind(Kind::ARRAY());
|
||
|
|
AddOperator( &makeDarray );
|
||
|
|
AddOperator( &getA );
|
||
|
|
AddOperator( &putA );
|
||
|
|
AddOperator( &sendA );
|
||
|
|
AddOperator( &receiveA);
|
||
|
|
AddOperator( &receiverelA);
|
||
|
|
AddOperator( &sendrelA);
|
||
|
|
AddOperator( &shuffle3);
|
||
|
|
shuffle3.SetUsesArgsInTypeMapping();
|
||
|
|
AddOperator( &shuffle2);
|
||
|
|
shuffle2.SetUsesArgsInTypeMapping();
|
||
|
|
AddOperator( &shuffle1);
|
||
|
|
shuffle1.SetUsesArgsInTypeMapping();
|
||
|
|
AddOperator( &receiveShuffle);
|
||
|
|
AddOperator( &sendShuffle);
|
||
|
|
sendShuffle.SetUsesMemory();
|
||
|
|
AddOperator( &distributeA);
|
||
|
|
distributeA.SetUsesMemory();
|
||
|
|
AddOperator( &loopA); loopA.SetUsesArgsInTypeMapping();
|
||
|
|
AddOperator( &dloopA); dloopA.SetUsesArgsInTypeMapping();
|
||
|
|
AddOperator( &dElementA);
|
||
|
|
AddOperator( &dElementA2);
|
||
|
|
AddOperator( &drel);
|
||
|
|
AddOperator( &dIndex);
|
||
|
|
AddOperator( &dtie);
|
||
|
|
AddOperator( &dsummarize );
|
||
|
|
dsummarize.SetUsesMemory();
|
||
|
|
AddOperator( &checkWorkers );
|
||
|
|
AddOperator( &startUp );
|
||
|
|
AddOperator( &shutDown );
|
||
|
|
}
|
||
|
|
~DistributedAlgebra() {}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
7 Initialization
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
extern "C"
|
||
|
|
Algebra*
|
||
|
|
InitializeDistributedAlgebra(NestedList *nlRef,
|
||
|
|
QueryProcessor *qpRef)
|
||
|
|
{
|
||
|
|
nl = nlRef;
|
||
|
|
qp = qpRef;
|
||
|
|
return new DistributedAlgebra();
|
||
|
|
}
|
||
|
|
|
||
|
|
|