243 lines
5.6 KiB
C++
243 lines
5.6 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}}]
|
||
|
|
//characters [1] Type: [] []
|
||
|
|
//characters [2] Type: [] []
|
||
|
|
//[ae] [\"{a}]
|
||
|
|
//[oe] [\"{o}]
|
||
|
|
//[ue] [\"{u}]
|
||
|
|
//[ss] [{\ss}]
|
||
|
|
//[Ae] [\"{A}]
|
||
|
|
//[Oe] [\"{O}]
|
||
|
|
//[Ue] [\"{U}]
|
||
|
|
//[x] [$\times $]
|
||
|
|
//[->] [$\rightarrow $]
|
||
|
|
//[toc] [\tableofcontents]
|
||
|
|
|
||
|
|
[1] Implementation of the Coordinator (Worker type: Loop)
|
||
|
|
|
||
|
|
[toc]
|
||
|
|
|
||
|
|
1 CoordinatorLoop class implementation
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "CoordinatorLoop.h"
|
||
|
|
|
||
|
|
extern QueryProcessor* qp;
|
||
|
|
|
||
|
|
namespace continuousqueries {
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Constructor.
|
||
|
|
|
||
|
|
Creates the object.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
CoordinatorLoop::CoordinatorLoop(int port, std::string tupledescr):
|
||
|
|
CoordinatorGen::CoordinatorGen(port, tupledescr)
|
||
|
|
{
|
||
|
|
_type = "loop";
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.2 Destructor.
|
||
|
|
|
||
|
|
Destroys the object.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
CoordinatorLoop::~CoordinatorLoop()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.3 setupNetwork
|
||
|
|
|
||
|
|
Decides what an idle worker should become.
|
||
|
|
Current strategy: Greedy worker. After creating one NoMo, all new confirmed
|
||
|
|
idle handler will become a worker.
|
||
|
|
Will be called with the id of a new idle handler. If not, this is probably
|
||
|
|
the place to implement the logic for restructuring the network.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void CoordinatorLoop::setupNetwork(int newHandlerId)
|
||
|
|
{
|
||
|
|
if (!newHandlerId) return;
|
||
|
|
|
||
|
|
// create a nomo, if neccessary
|
||
|
|
if (countHandlers(handlerType::nomo, handlerStatus::all) == 0)
|
||
|
|
{
|
||
|
|
createNoMo(newHandlerId);
|
||
|
|
} else {
|
||
|
|
createWorker(newHandlerId, "loop");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (_lifecyle == coordinatorStatus::initialze)
|
||
|
|
{
|
||
|
|
if ((countHandlers(handlerType::worker, handlerStatus::active)>0)
|
||
|
|
and (countHandlers(
|
||
|
|
handlerType::nomo, handlerStatus::active) > 0)
|
||
|
|
and (countHandlers(
|
||
|
|
handlerType::streamsupplier, handlerStatus::active) > 0
|
||
|
|
))
|
||
|
|
{
|
||
|
|
_lifecyle = coordinatorStatus::run;
|
||
|
|
std::cout << "All needed handler available."
|
||
|
|
<< " System is running. \n";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.4 registerQuery
|
||
|
|
|
||
|
|
This function informs one worker and one nomo in the network about
|
||
|
|
the new query.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
void CoordinatorLoop::registerQuery(queryStruct query)
|
||
|
|
{
|
||
|
|
int w = selectWorker();
|
||
|
|
if (!w) return;
|
||
|
|
|
||
|
|
_queries[query.id].worker = w;
|
||
|
|
_handlers[w].ownqueries.push_back(query.id);
|
||
|
|
|
||
|
|
LOG << "Adding query " << query.function << " to worker "
|
||
|
|
<< w << "." << ENDL;
|
||
|
|
|
||
|
|
(void) _coordinationServer.Send(
|
||
|
|
_handlers[w].socket,
|
||
|
|
CoordinatorGenP::addquery(query.id, query.function, true)
|
||
|
|
);
|
||
|
|
|
||
|
|
int n = selectNoMo();
|
||
|
|
if (!n) return;
|
||
|
|
|
||
|
|
LOG << "Adding query " << query.function << " to nomo "
|
||
|
|
<< n << "." << ENDL;
|
||
|
|
|
||
|
|
(void) _coordinationServer.Send(
|
||
|
|
_handlers[n].socket,
|
||
|
|
CoordinatorGenP::addquery(
|
||
|
|
query.id,
|
||
|
|
query.function,
|
||
|
|
query.userhash,
|
||
|
|
_users[query.userhash].email,
|
||
|
|
true
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.5 selectWorker
|
||
|
|
|
||
|
|
Returns the id of the worker who should work a query, 0 if there is none.
|
||
|
|
Current strategy: the worker with the least amount of queries should get
|
||
|
|
a new query assigned.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int CoordinatorLoop::selectWorker()
|
||
|
|
{
|
||
|
|
int candidateId = 0;
|
||
|
|
int candidateQueries = 0;
|
||
|
|
|
||
|
|
for (std::map<int, handlerStruct>::iterator it = _handlers.begin();
|
||
|
|
it != _handlers.end(); it++)
|
||
|
|
{
|
||
|
|
if ((it->second.type == handlerType::worker) and
|
||
|
|
(it->second.status == handlerStatus::active))
|
||
|
|
{
|
||
|
|
if ((candidateId == 0) || ((int) it->second.ownqueries.size()
|
||
|
|
< candidateQueries)) {
|
||
|
|
candidateQueries = (int) it->second.ownqueries.size();
|
||
|
|
candidateId = it->first;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return candidateId;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.6 checkNewFunction
|
||
|
|
|
||
|
|
Checks if the provided function is a valid representation for this
|
||
|
|
coordinator type. In this case, it has to be a valid function for the
|
||
|
|
Secondo Query Processor.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool CoordinatorLoop::checkNewFunction(std::string function, std::string &err)
|
||
|
|
{
|
||
|
|
// return true;
|
||
|
|
|
||
|
|
err = "???";
|
||
|
|
|
||
|
|
// build funList
|
||
|
|
ListExpr funList;
|
||
|
|
if( !nl->ReadFromString(function, funList)) {
|
||
|
|
std::cout << "Error building funList" << endl;
|
||
|
|
err = "Error building funList";
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// QueryProcessor* tqp = new QueryProcessor(nl,
|
||
|
|
// SecondoSystem::GetAlgebraManager());
|
||
|
|
|
||
|
|
// build the tree
|
||
|
|
OpTree tree = 0;
|
||
|
|
ListExpr resultType;
|
||
|
|
bool correct = false;
|
||
|
|
bool evaluable = false;
|
||
|
|
bool defined = false;
|
||
|
|
bool isFunction = false;
|
||
|
|
|
||
|
|
try {
|
||
|
|
qp->Construct(
|
||
|
|
funList,
|
||
|
|
correct,
|
||
|
|
evaluable,
|
||
|
|
defined,
|
||
|
|
isFunction,
|
||
|
|
tree,
|
||
|
|
resultType );
|
||
|
|
}
|
||
|
|
catch(SI_Error ERR_IN_QUERY_EXPR) {
|
||
|
|
std::cout << "Error building tree" << endl;
|
||
|
|
err = "Error building tree";
|
||
|
|
// delete tqp;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// delete tqp;
|
||
|
|
|
||
|
|
return (correct && defined && isFunction);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|