788 lines
19 KiB
C++
788 lines
19 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2015, University in Hagen, Faculty of Mathematics and
|
|
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
|
|
----
|
|
|
|
Jan Kristof Nidzwetzki
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
[TOC]
|
|
|
|
0 Overview
|
|
|
|
This file contains an algebra with auxiliary operators. These
|
|
operators provide some general query processing features.
|
|
|
|
|
|
1 Includes and defines
|
|
|
|
*/
|
|
#include <cstdlib>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <unistd.h>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <time.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include "Algebra.h"
|
|
#include "NestedList.h"
|
|
#include "QueryProcessor.h"
|
|
#include "AlgebraManager.h"
|
|
#include "ListUtils.h"
|
|
#include "StandardTypes.h"
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
|
#include "Attribute.h"
|
|
#include "Algebras/FText/FTextAlgebra.h"
|
|
#include "Stream.h"
|
|
#include "Progress.h"
|
|
#include "Profiles.h"
|
|
#include "Algebras/Spatial/RegionTools.h"
|
|
|
|
extern NestedList* nl;
|
|
extern QueryProcessor *qp;
|
|
extern AlgebraManager *am;
|
|
|
|
using namespace std;
|
|
|
|
|
|
#ifndef timersub
|
|
#define timersub(a, b, result) \
|
|
do { \
|
|
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
|
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
|
if ((result)->tv_usec < 0) { \
|
|
--(result)->tv_sec; \
|
|
(result)->tv_usec += 1000000; \
|
|
} \
|
|
} while (0)
|
|
#endif // timersub
|
|
|
|
// Activate debug messages
|
|
//#define __DEBUG__
|
|
|
|
//namespace to avoid name conflicts
|
|
namespace auxiliary
|
|
{
|
|
|
|
/*
|
|
2.1 Operator ~Sleep~
|
|
|
|
This operator sleeps for a configurable time
|
|
|
|
2.1.1 Type mapping function of operator ~sleep~
|
|
|
|
Type mapping for ~sleep~ is
|
|
|
|
---- ((stream (tuple ((x1 t1)...(xn tn))) int) ->
|
|
((stream (tuple ((x1 t1)...(xn tn))))
|
|
|
|
or ((stream T) int) -> (stream T) for T in kind DATA
|
|
----
|
|
|
|
*/
|
|
ListExpr SleepTypeMap( ListExpr args )
|
|
{
|
|
|
|
if(nl->ListLength(args) != 2){
|
|
return listutils::typeError("two arguments expected");
|
|
}
|
|
|
|
string err = " stream(tuple(...) x int or stream(DATA) x int expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr delay = nl->Second(args);
|
|
|
|
if(( !Stream<Tuple>::checkType(stream) &&
|
|
!Stream<Attribute>::checkType(stream) ) ||
|
|
!CcInt::checkType(delay) ){
|
|
return listutils::typeError(err);
|
|
}
|
|
return stream;
|
|
}
|
|
|
|
/*
|
|
2.1.2 Generic Cost Estimation Function
|
|
|
|
This class will forward the progess of the predecessor
|
|
|
|
*/
|
|
class ForwardCostEstimation : public CostEstimation {
|
|
|
|
public:
|
|
|
|
ForwardCostEstimation() {
|
|
}
|
|
|
|
virtual int requestProgress(Word* args, ProgressInfo* pRes, void* localInfo,
|
|
bool argsAvialable) {
|
|
|
|
ProgressInfo p1;
|
|
Supplier sonOfFeed;
|
|
|
|
sonOfFeed = qp->GetSupplierSon(supplier, 0);
|
|
|
|
if ( qp->RequestProgress(sonOfFeed, &p1) ) {
|
|
pRes->Card = p1.Card;
|
|
pRes->CopySizes(p1);
|
|
// Add delay per tuple (default 0)
|
|
pRes->Time = p1.Time + (p1.Card * getDelay(localInfo));
|
|
pRes->Progress = p1.Progress;
|
|
pRes->BTime = p1.BTime;
|
|
pRes->BProgress = p1.BProgress;
|
|
|
|
return YIELD;
|
|
} else {
|
|
return CANCEL;
|
|
}
|
|
|
|
return CANCEL;
|
|
}
|
|
|
|
// Template Method, can be used in subclasses
|
|
virtual int getDelay(void* localInfo) { return 0; }
|
|
|
|
/*
|
|
2.1.2 init our class
|
|
|
|
*/
|
|
virtual void init(Word* args, void* localInfo) {
|
|
|
|
}
|
|
};
|
|
|
|
struct SleepLocalInfo
|
|
{
|
|
SleepLocalInfo( const int numDelay = 0 ): delay( numDelay ) {
|
|
|
|
}
|
|
|
|
int delay; // in ms
|
|
};
|
|
|
|
/*
|
|
2.1.2 Specialized Cost Estimation function for operator ~sleep~
|
|
|
|
Multiplies the delay with the estimated time of
|
|
the predecessor
|
|
|
|
*/
|
|
class SleepCostEstimation : public ForwardCostEstimation {
|
|
|
|
public:
|
|
|
|
virtual int getDelay(void* localInfo) {
|
|
SleepLocalInfo* li = (SleepLocalInfo*) localInfo;
|
|
|
|
if(li == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
// delay per tuple in ms
|
|
return li -> delay;
|
|
}
|
|
};
|
|
|
|
CostEstimation* SleepCostEstimationFunc() {
|
|
return new SleepCostEstimation();
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.3 Value mapping function of operator ~sleep~
|
|
|
|
*/
|
|
int Sleep(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
SleepLocalInfo *sli;
|
|
Word tupleWord;
|
|
|
|
sli = (SleepLocalInfo*)local.addr;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
|
|
if ( sli ) delete sli;
|
|
|
|
sli =
|
|
new SleepLocalInfo( ((CcInt*)args[1].addr)->GetIntval() );
|
|
local.setAddr( sli );
|
|
|
|
qp->Open(args[0].addr);
|
|
return 0;
|
|
|
|
case REQUEST:
|
|
|
|
// Operator not ready
|
|
if ( ! sli ) {
|
|
return CANCEL;
|
|
}
|
|
|
|
// Delay is in ms
|
|
usleep(sli -> delay * 1000);
|
|
|
|
|
|
qp->Request(args[0].addr, tupleWord);
|
|
if(qp->Received(args[0].addr))
|
|
{
|
|
result = tupleWord;
|
|
return YIELD;
|
|
} else {
|
|
return CANCEL;
|
|
}
|
|
|
|
case CLOSE:
|
|
qp->Close(args[0].addr);
|
|
if(sli) {
|
|
delete sli;
|
|
sli = NULL;
|
|
local.setAddr( sli );
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.4 Specification of operator ~sleep~
|
|
|
|
*/
|
|
const string SleepSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( "
|
|
"<text>((stream (tuple([a1:d1, ... ,an:dn]"
|
|
"))) x int) -> (stream (tuple([a1:d1, ... ,"
|
|
"an:dn]))) or \n"
|
|
"((stream T) int) -> (stream T), "
|
|
"for T in kind DATA.</text--->"
|
|
"<text>_ sleep [ _ ]</text--->"
|
|
"<text> This operator forwards the stream with "
|
|
" a configurable delay. Delay must be specified "
|
|
" in ms</text--->"
|
|
"<text>query cities feed sleep[10] consume"
|
|
"</text--->"
|
|
") )";
|
|
|
|
/*
|
|
2.1.5 Definition of operator ~sleep~
|
|
|
|
*/
|
|
Operator auxiliarysleep (
|
|
"sleep", // name
|
|
SleepSpec, // specification
|
|
Sleep, // value mapping
|
|
Operator::SimpleSelect, // trivial selection function
|
|
SleepTypeMap, // type mapping
|
|
SleepCostEstimationFunc // Cost estimation
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
2.1 Operator ~faultcrash~
|
|
|
|
This operator crashes after forwarning n tuples
|
|
|
|
2.1.1 Type mapping function of operator ~faultcrash~
|
|
|
|
Type mapping for ~faultcrash~ is
|
|
|
|
---- ((stream (tuple ((x1 t1)...(xn tn))) int) ->
|
|
((stream (tuple ((x1 t1)...(xn tn))))
|
|
|
|
or ((stream T) int) -> (stream T) for T in kind DATA
|
|
----
|
|
|
|
*/
|
|
ListExpr FaultCrashTypeMap( ListExpr args )
|
|
{
|
|
|
|
if(nl->ListLength(args) != 2){
|
|
return listutils::typeError("two arguments expected");
|
|
}
|
|
|
|
string err = " stream(tuple(...) x int or stream(DATA) x int expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr delay = nl->Second(args);
|
|
|
|
if(( !Stream<Tuple>::checkType(stream) &&
|
|
!Stream<Attribute>::checkType(stream) ) ||
|
|
!CcInt::checkType(delay) ){
|
|
return listutils::typeError(err);
|
|
}
|
|
return stream;
|
|
}
|
|
|
|
/*
|
|
2.1.2 Cost estimation
|
|
|
|
*/
|
|
CostEstimation* FaultCostEstimation() {
|
|
return new ForwardCostEstimation();
|
|
}
|
|
|
|
/*
|
|
2.1.2 Local Info for fault function
|
|
|
|
*/
|
|
enum CrashType {CRASH, LOOP};
|
|
|
|
template <CrashType crashType>
|
|
class FaultLocalInfo {
|
|
|
|
public:
|
|
FaultLocalInfo(size_t myCrashAfter) :
|
|
crashAfter(myCrashAfter), forwardedTuples(0) {
|
|
|
|
// Init random number generator
|
|
srand(time(NULL));
|
|
}
|
|
|
|
void forwardTuple() {
|
|
forwardedTuples++;
|
|
int randValue = rand();
|
|
if(randValue % crashAfter == 0) {
|
|
if(crashType == CRASH) {
|
|
__builtin_trap();
|
|
exit(1);
|
|
} else {
|
|
// Loop forever!
|
|
while(true) {
|
|
sleep(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
size_t crashAfter;
|
|
size_t forwardedTuples;
|
|
};
|
|
|
|
/*
|
|
2.1.3 Value mapping function of operator ~faultcrash~
|
|
|
|
*/
|
|
template <CrashType crashType>
|
|
int InjectFault(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
FaultLocalInfo<crashType> *li;
|
|
size_t crashAfter = 0;
|
|
Word tupleWord;
|
|
|
|
li = (FaultLocalInfo<crashType>*) local.addr;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
|
|
if(li) delete li;
|
|
|
|
crashAfter = (size_t) ((CcInt*)args[1].addr)->GetIntval();
|
|
li = new FaultLocalInfo<crashType>(crashAfter);
|
|
local.setAddr( li );
|
|
|
|
qp->Open(args[0].addr);
|
|
return 0;
|
|
|
|
case REQUEST:
|
|
li -> forwardTuple();
|
|
qp->Request(args[0].addr, tupleWord);
|
|
if(qp->Received(args[0].addr))
|
|
{
|
|
result = tupleWord;
|
|
return YIELD;
|
|
} else {
|
|
return CANCEL;
|
|
}
|
|
|
|
case CLOSE:
|
|
if(li) {
|
|
delete li;
|
|
li = NULL;
|
|
local.setAddr( li );
|
|
}
|
|
qp->Close(args[0].addr);
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
2.1.4 Specification of operator ~faultloop~
|
|
|
|
*/
|
|
const string FaultLoopSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( "
|
|
"<text>((stream (tuple([a1:d1, ... ,an:dn]"
|
|
"))) x int) -> (stream (tuple([a1:d1, ... ,"
|
|
"an:dn]))) or \n"
|
|
"((stream T) int) -> (stream T), "
|
|
"for T in kind DATA.</text--->"
|
|
"<text>_ faultloop [ _ ]</text--->"
|
|
"<text> This operator enters a endless loop "
|
|
" on average after forwarding n tuples "
|
|
" </text--->"
|
|
"<text>query cities feed faultloop[100] consume"
|
|
"</text--->"
|
|
") )";
|
|
|
|
|
|
/*
|
|
2.1.4 Specification of operator ~faultcrash~
|
|
|
|
*/
|
|
const string FaultCrashSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( "
|
|
"<text>((stream (tuple([a1:d1, ... ,an:dn]"
|
|
"))) x int) -> (stream (tuple([a1:d1, ... ,"
|
|
"an:dn]))) or \n"
|
|
"((stream T) int) -> (stream T), "
|
|
"for T in kind DATA.</text--->"
|
|
"<text>_ faultcrash [ _ ]</text--->"
|
|
"<text> This operator crashes the whole system "
|
|
" on average after forwarding n tuples "
|
|
" </text--->"
|
|
"<text>query cities feed faultcrash[10] consume"
|
|
"</text--->"
|
|
") )";
|
|
|
|
/*
|
|
2.1.5 Definition of operator ~faultcrash~
|
|
|
|
*/
|
|
Operator faultcrash (
|
|
"faultcrash", // name
|
|
FaultCrashSpec, // specification
|
|
InjectFault<CRASH>, // value mapping
|
|
Operator::SimpleSelect, // trivial selection function
|
|
FaultCrashTypeMap, // type mapping
|
|
FaultCostEstimation // Cost estimation
|
|
);
|
|
|
|
/*
|
|
2.1.6 Definition of operator ~faultloop~
|
|
|
|
*/
|
|
Operator faultloop (
|
|
"faultloop", // name
|
|
FaultLoopSpec, // specification
|
|
InjectFault<LOOP>, // value mapping
|
|
Operator::SimpleSelect, // trivial selection function
|
|
FaultCrashTypeMap, // type mapping
|
|
FaultCostEstimation // Cost estimation
|
|
);
|
|
|
|
/*
|
|
2.2 Operator ~statistics~
|
|
|
|
The operator ~statistics~ generates tuple flow statistics.
|
|
The first parameter is the output file for the
|
|
operator. The second parameter is the interval for
|
|
the statistics.
|
|
|
|
2.2.1 Type mapping function of operator ~statistics~
|
|
|
|
Type mapping for ~statistics~ is
|
|
|
|
----
|
|
|
|
stream ( tuple ( (a1 t1) ... (an tn))) x text x
|
|
int -> stream (tuple(...))
|
|
|
|
----
|
|
|
|
*/
|
|
ListExpr StatisticsTypeMap( ListExpr args )
|
|
{
|
|
|
|
if(nl->ListLength(args) != 3){
|
|
return listutils::typeError("three arguments expected");
|
|
}
|
|
|
|
string err = " stream(tuple(...) x text x int expected";
|
|
|
|
ListExpr stream = nl->First(args);
|
|
ListExpr filename = nl->Second(args);
|
|
ListExpr interval = nl->Third(args);
|
|
|
|
if(( !Stream<Tuple>::checkType(stream) &&
|
|
!Stream<Attribute>::checkType(stream) ) ||
|
|
!FText::checkType(filename) ||
|
|
!CcInt::checkType(interval)) {
|
|
return listutils::typeError(err);
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
/*
|
|
2.2.2 Cost estimation
|
|
|
|
*/
|
|
CostEstimation* StatisticsCostEstimationFunc() {
|
|
return new ForwardCostEstimation();
|
|
}
|
|
|
|
/*
|
|
2.2.3 Value mapping function of operator ~statistics~
|
|
|
|
*/
|
|
class StatisticsLocalInfo {
|
|
public:
|
|
StatisticsLocalInfo(string myFilename, int myInterval)
|
|
: interval(myInterval), iteration(0), filename(myFilename),
|
|
seenTuples(0), totalTuples(0) {
|
|
|
|
//cout << "Filename is " << filename
|
|
// << " interval is " << interval << endl;
|
|
|
|
// Open file for output
|
|
filehandle.open(filename.c_str());
|
|
if(! filehandle.is_open() ) {
|
|
cout << "Unable to open file: " << filename << endl;
|
|
} else {
|
|
filehandle << "Time,Current Tuples,Total Tuples" << endl;
|
|
}
|
|
|
|
// Init interval
|
|
reset();
|
|
}
|
|
|
|
virtual ~StatisticsLocalInfo() {
|
|
dumpTuples();
|
|
close();
|
|
}
|
|
|
|
// We received a new tuple
|
|
// Register and dump
|
|
void tupleReceived() {
|
|
timeval curtime, difference;
|
|
gettimeofday(&curtime, NULL);
|
|
|
|
timersub(&curtime, &lastdump, &difference);
|
|
|
|
|
|
int miliseconds = difference.tv_sec * 1000 + (difference.tv_usec / 1000);
|
|
|
|
if(miliseconds >= interval) {
|
|
dumpTuples();
|
|
reset();
|
|
}
|
|
|
|
seenTuples++;
|
|
}
|
|
|
|
// Reset seenTuples counter
|
|
void reset() {
|
|
gettimeofday(&lastdump, NULL);
|
|
totalTuples = totalTuples + seenTuples;
|
|
seenTuples = 0;
|
|
}
|
|
|
|
// Close file
|
|
void close() {
|
|
filehandle.close();
|
|
}
|
|
|
|
// Dump seen tuples to output file
|
|
void dumpTuples() {
|
|
//cout << "Cur tuples " << seenTuples << endl;
|
|
filehandle << iteration * interval << "," << seenTuples
|
|
<< "," << (totalTuples + seenTuples) << endl;
|
|
reset();
|
|
iteration++;
|
|
}
|
|
|
|
// Are we ready?
|
|
bool isReady() {
|
|
return filehandle.is_open();
|
|
}
|
|
|
|
private:
|
|
int interval; // Intervall in sec for dumping
|
|
int iteration; // Current iteration
|
|
string filename; // Filename for statistics
|
|
timeval lastdump; // When did we the last dump?
|
|
size_t seenTuples; // Seen tuples since last dump
|
|
size_t totalTuples; // Total seen tuples
|
|
ofstream filehandle; // Filehandle
|
|
};
|
|
|
|
int Statistics(Word* args, Word& result, int message, Word& local, Supplier s)
|
|
{
|
|
StatisticsLocalInfo *sli;
|
|
Word tupleWord;
|
|
|
|
sli = (StatisticsLocalInfo*)local.addr;
|
|
|
|
switch(message)
|
|
{
|
|
case OPEN:
|
|
|
|
if ( sli ) delete sli;
|
|
|
|
if(! ((FText*)args[1].addr)->IsDefined()) {
|
|
cout << "Filename is not defined" << endl;
|
|
} else {
|
|
sli = new StatisticsLocalInfo((((FText*)args[1].addr)->GetValue()),
|
|
(((CcInt*)args[2].addr)->GetIntval()));
|
|
|
|
// Is statistics class ready (file open...)
|
|
if(sli -> isReady()) {
|
|
local.setAddr( sli );
|
|
qp->Open(args[0].addr);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case REQUEST:
|
|
|
|
// Operator not ready
|
|
if ( ! sli ) {
|
|
return CANCEL;
|
|
}
|
|
|
|
qp->Request(args[0].addr, tupleWord);
|
|
if(qp->Received(args[0].addr))
|
|
{
|
|
sli -> tupleReceived();
|
|
result = tupleWord;
|
|
return YIELD;
|
|
} else {
|
|
return CANCEL;
|
|
}
|
|
|
|
case CLOSE:
|
|
qp->Close(args[0].addr);
|
|
if(sli) {
|
|
delete sli;
|
|
sli = NULL;
|
|
local.setAddr( sli );
|
|
}
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
2.2.4 Specification of operator ~statistics~
|
|
|
|
*/
|
|
const string StatisticsSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" ) "
|
|
"( "
|
|
"<text>((stream (tuple([a1:d1, ... ,an:dn]"
|
|
"))) y string x int) -> (stream (tuple([a1:d1, ... ,"
|
|
"an:dn]))) or \n"
|
|
"((stream T) text x int) -> (stream T), "
|
|
"for T in kind DATA.</text--->"
|
|
"<text>_ statistics [ _ , _ ]</text--->"
|
|
"<text> The operator statistics generates tuple flow "
|
|
"statistics. The first parameter is the output file "
|
|
"for the operator. The second parameter is the "
|
|
"interval for the statistics (msec). </text--->"
|
|
"<text>query intstream(1,10) transformstream "
|
|
"statistics['/tmp/statistics.csv', 10] count</text--->"
|
|
") )";
|
|
|
|
/*
|
|
2.2.5 Definition of operator ~statistics~
|
|
|
|
*/
|
|
Operator auxiliarystatistics (
|
|
"statistics", // name
|
|
StatisticsSpec, // specification
|
|
Statistics, // value mapping
|
|
Operator::SimpleSelect, // trivial selection function
|
|
StatisticsTypeMap, // type mapping
|
|
StatisticsCostEstimationFunc // Cost estimation
|
|
);
|
|
|
|
|
|
/*
|
|
7 Creating the Algebra
|
|
|
|
*/
|
|
class AuxiliaryAlgebra: public Algebra
|
|
{
|
|
public:
|
|
AuxiliaryAlgebra() :
|
|
Algebra()
|
|
{
|
|
|
|
/*
|
|
7.2 Registration of Operators
|
|
|
|
*/
|
|
AddOperator(&faultloop);
|
|
AddOperator(&faultcrash);
|
|
AddOperator(&auxiliarysleep);
|
|
AddOperator(&auxiliarystatistics);
|
|
}
|
|
|
|
;
|
|
};
|
|
|
|
/*
|
|
8 Initialization
|
|
|
|
Each algebra module needs an initialization function. The algebra
|
|
manager has a reference to this function if this algebra is
|
|
included in the list of required algebras, thus forcing the linker
|
|
to include this module.
|
|
|
|
The algebra manager invokes this function to get a reference to the
|
|
instance of the algebra class and to provide references to the
|
|
global nested list container (used to store constructor, type,
|
|
operator and object information) and to the query processor.
|
|
|
|
The function has a C interface to make it possible to load the
|
|
algebra dynamically at runtime.
|
|
|
|
*/
|
|
|
|
} // end of namespace ~auxiliary~
|
|
|
|
extern "C" Algebra*
|
|
InitializeAuxiliaryAlgebra(NestedList* nlRef, QueryProcessor* qpRef,
|
|
AlgebraManager* amRef)
|
|
{
|
|
nl = nlRef;
|
|
qp = qpRef;
|
|
am = amRef;
|
|
|
|
return (new auxiliary::AuxiliaryAlgebra());
|
|
|
|
}
|
|
|