Files
secondo/Algebras/ContinuousQueries/LoopStrategy/WorkerLoop.cpp

305 lines
6.9 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
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 loop worker.
[toc]
1 WorkerLoop class implementation
*/
#include "WorkerLoop.h"
#include <boost/algorithm/string.hpp>
extern NestedList* nl;
extern QueryProcessor* qp;
namespace continuousqueries {
/*
1.1 Constructor
Creates a new WorkerLoop object.
*/
WorkerLoop::WorkerLoop(int id, std::string attrliststr,
TcpClient* coordinationClient):
WorkerGen::WorkerGen(id, attrliststr, coordinationClient)
{
_type = "loop";
// Build TupleType once to speed up Tuple creation
nl->ReadFromString(attrliststr, _attrlist);
ListExpr resultTupleType = nl->TwoElemList(
nl->SymbolAtom(Tuple::BasicType()),
_attrlist
);
ListExpr numResultTupleType = SecondoSystem::GetCatalog()->
NumericType(resultTupleType);
_tt = new TupleType(numResultTupleType);
_monitor = new Monitor(id, "worker", "loop", coordinationClient,
2 * 60 * 1000, 5000);
}
/*
1.2 Destructor
Destroys the WorkerLoop object.
*/
WorkerLoop::~WorkerLoop() {
_tt->DeleteIfAllowed();
}
/*
1.3 addQuery
Adds a user query.
*/
void WorkerLoop::addQuery(int id, std::string function)
{
LOG << "Adding Query " << id << "|" << function << ENDL;
queryStruct toAdd;
toAdd.id = id;
toAdd.funText = function;
// build funList
ListExpr funList;
if( !nl->ReadFromString(function, funList)) {
std::cout << "Error building funList" << endl;
return;
}
// 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;
return;
}
toAdd.tree = tree;
// get the funargs
toAdd.funargs = qp->Argument(tree);
_queries.insert( std::pair<int, queryStruct>(id, toAdd));
}
/*
1.4 TightLoop
Waits for new tuples and checks all registered queries against them.
*/
void WorkerLoop::TightLoop()
{
// wait for new tuple
bool hasMsg = false;
ProtocolHelpers::Message msg;
_monitor->startBatch();
while (_running)
{
std::unique_lock<std::mutex> lock(_tupleServer.mqMutex);
hasMsg = _tupleServer.mqCondition.wait_for(
lock,
std::chrono::milliseconds(5000),
[this] {
return !_tupleServer.messages.empty();
});
if (!_running)
{
_monitor->checkBatch();
lock.unlock();
continue;
}
if (hasMsg)
{
msg = ProtocolHelpers::decodeMessage(
_tupleServer.messages.front()
);
_tupleServer.messages.pop();
} else {
msg.valid = false;
}
lock.unlock();
if (hasMsg && msg.valid && msg.cmd==StSuGenP::tuple())
{
_monitor->startWorkRound();
// extract informations
int tupleId = 0;
std::string tupleString = "";
std::vector<std::string> parts;
boost::split(parts, msg.params, boost::is_any_of(
std::string(1, ProtocolHelpers::seperator)
));
try
{
tupleId = std::stoi(parts[0]);
tupleString = parts[1];
}
catch(...)
{
tupleId = 0;
std::cout << "failed to extract id or tuple" << endl;
}
if (!tupleId) {
_monitor->endWorkRound(0, 0, 0);
continue;
}
// create tuple
Tuple* tuple = new Tuple(_tt);
tuple->ReadFromBinStr(0, tupleString);
// loop over Queries, check for hits
std::string hitlist = "";
int hits = 0;
int queries = 0;
for (std::map<int, queryStruct>::iterator it = _queries.begin();
it != _queries.end(); it++)
{
queries++;
if (filterTuple(tuple, it->second.tree, it->second.funargs))
{
hits++;
hitlist += std::to_string(it->first);
hitlist += ",";
}
}
tuple->DeleteIfAllowed();
hitlist = hitlist.substr(0, hitlist.size()-1);
std::cout << "Tpl: " << tupleId << " | Hits: " << hits << endl;
// notify all nomos
if (hits) notifyAllNoMos(tupleId, tupleString, hitlist);
_monitor->endWorkRound(1, queries, hits);
}
_monitor->checkBatch();
}
}
/*
1.5 filterTuple
This function checks wether the filterfunction is true for a given tuple.
True is returned when the result of the function is true.
*/
bool WorkerLoop::filterTuple(Tuple* tuple, OpTree& tree,
ArgVectorPointer& funargs)
{
(*funargs)[0] = tuple;
Word result;
try
{
qp->EvalS(tree, result, REQUEST);
if ((Attribute*)result.addr&&((Attribute*)result.addr)->IsDefined()) {
return ((CcBool*)result.addr)->GetBoolval();
}
}
catch(const std::exception& e)
{
return false;
}
return false;
}
/*
1.6 showStatus
Prints out some information.
*/
void WorkerLoop::showStatus()
{
std::cout << "**************************************************" << endl;
std::cout << "WorkerLoop::Status" << endl << endl;
std::cout << "Number of Queries: " << (int)_queries.size() << endl;
std::cout << "**************************************************" << endl;
}
}