Files
secondo/Algebras/Management/AlgebraManager.cpp
2026-01-23 17:03:45 +08:00

869 lines
24 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
----
August 2004, M. Spiekermann. This comment was inserted to make it a PD-File.
Moreover, implementation of ~GetAlgebraName~ was done.
December 2005, Victor Almeida deleted the deprecated algebra levels
(~executable~, ~descriptive~, and ~hybrid~). Only the executable
level remains. Models are also removed from type constructors.
January 2006. M. Spiekermann TypeCheck will now return a boolean value instead
of a pointer to a function.
*/
#include <string>
#include <utility>
#include <algorithm>
#include <fstream>
#include "AlgebraManager.h"
#include "Algebra.h"
#include "CharTransform.h"
#include "SecondoSystem.h"
#include "DynamicLibrary.h"
#include "SystemTables.h"
#include "Symbols.h"
#include "StringUtils.h"
using namespace std;
AlgebraManager::AlgebraManager( NestedList& nlRef,
GetAlgebraEntryFunction getAlgebraEntryFunc )
{
int j = 0;
nl = &nlRef;
getAlgebraEntry = getAlgebraEntryFunc;
maxAlgebraId = 0;
for ( j = 0; (*getAlgebraEntry)( j ).algebraId > 0; j++ )
{
if ( (*getAlgebraEntry)( j ).useAlgebra )
{
if ( (*getAlgebraEntry)( j ).algebraId > maxAlgebraId )
{
maxAlgebraId = (*getAlgebraEntry)( j ).algebraId;
}
}
}
algebra.resize( maxAlgebraId+1 );
for ( j = 0; j <= maxAlgebraId; j++ )
algebra[j] = 0;
}
AlgebraManager::~AlgebraManager()
{
UnloadAlgebras();
// delete algebra pointers
for(unsigned int i=0;i<algebra.size();i++){
delete algebra[i];
algebra[i] = 0;
}
}
ListExpr
AlgebraManager::ListAlgebras()
{
int j = 0;
ListExpr list = nl->Empty();
ListExpr lastElem = nl->Empty();
for ( j = 0; (*getAlgebraEntry)( j ).algebraId > 0; j++ )
{
if ( (*getAlgebraEntry)( j ).useAlgebra )
{
if ( (*getAlgebraEntry)( j ).algebraInit != 0 )
{
ListExpr alg = nl->SymbolAtom( (*getAlgebraEntry)( j ).algebraName );
if ( list == nl->TheEmptyList() )
{
list = nl->OneElemList( alg );
lastElem = list;
}
else
{
lastElem = nl->Append( lastElem, alg );
}
}
}
}
return (list);
}
int
AlgebraManager::GetAlgebraId(const string& algName)
{
int j;
for ( j = 0; (*getAlgebraEntry)( j ).algebraId > 0; j++ )
{
if ( (*getAlgebraEntry)( j ).useAlgebra )
{
if ( (*getAlgebraEntry)( j ).algebraInit != 0 )
{
if ( !(algName.compare( (*getAlgebraEntry)( j ).algebraName )) )
return (*getAlgebraEntry)( j ).algebraId;
}
}
}
return 0;
}
const string&
AlgebraManager::GetAlgebraName( const int algId ) {
static const string unknown("UnknownAlgebra");
assert( algId >= 0 && algId <= maxAlgebraId );
map<int, string>::const_iterator it = algebraNames.find(algId);
if ( it != algebraNames.end() ) {
return it->second;
} else {
return unknown;
}
}
void
AlgebraManager::LoadAlgebras()
{
QueryProcessor* qp = SecondoSystem::GetQueryProcessor();
TypeConstructor* tc = 0;
int j = 0, k = 0;
for ( j = 0; (*getAlgebraEntry)( j ).algebraId > 0; j++ )
{
string algNameStr = (*getAlgebraEntry)( j ).algebraName;
int algId = (*getAlgebraEntry)( j ).algebraId;
if ( (*getAlgebraEntry)( j ).useAlgebra )
{
if ( (*getAlgebraEntry)( j ).algebraInit != 0 )
{
// Prevent duplicate loading of an algebra
if ( algebraNames.find(algId) != algebraNames.end() ) {
cerr << endl
<< "WARNING: Algebra " << algNameStr << " is already loaded. "
<< "Please check your algebra setup for duplicates."
<< endl;
} else {
algebraNames[algId] = algNameStr;
algebra[algId] = ((*getAlgebraEntry)( j ).algebraInit)
( nl, qp, this );
}
}
else
{
bool loaded = false;
string libraryName = string( "lib" ) + algNameStr;
string initFuncName = string( "Initialize" ) + algNameStr;
(*getAlgebraEntry)( j ).dynlib = new DynamicLibrary();
transform( libraryName.begin(), libraryName.end(),
libraryName.begin(), ToLowerProperFunction );
if ( (*getAlgebraEntry)( j ).dynlib->Load( libraryName ) )
{
AlgebraInitFunction initFunc =
(AlgebraInitFunction) (*getAlgebraEntry)( j ).dynlib
->GetFunctionAddress( initFuncName );
if ( initFunc != 0 )
{
algebra[(*getAlgebraEntry)( j ).algebraId]
= (initFunc)( nl, qp, this );
loaded = true;
}
else
{
(*getAlgebraEntry)( j ).dynlib->Unload();
}
}
if ( !loaded )
{
delete (*getAlgebraEntry)( j ).dynlib;
(*getAlgebraEntry)( j ).dynlib = 0;
continue;
}
}
for ( k = 0;
k < algebra[(*getAlgebraEntry)( j ).algebraId]->GetNumTCs(); k++ )
{
tc = algebra[(*getAlgebraEntry)( j ).algebraId]
->GetTypeConstructor( k );
NList::setNLRef(nl);
//tc ->initKindDataProperties();
for ( vector<string>::size_type idx = 0;
idx < tc->kinds.size(); idx++ )
{
if ( tc->kinds[idx] != "" )
{
kindTable.insert( make_pair( tc->kinds[idx], tc->typeCheckFunc ) );
}
}
}
}
}
InitOpPtrField();
}
void
AlgebraManager::UnloadAlgebras()
{
for ( int j = 0; (*getAlgebraEntry)( j ).algebraId > 0; j++ )
{
if ( (*getAlgebraEntry)( j ).useAlgebra
&& (*getAlgebraEntry)( j ).dynlib != 0 )
{
(*getAlgebraEntry)( j ).dynlib->Unload();
delete (*getAlgebraEntry)( j ).dynlib;
(*getAlgebraEntry)( j ).dynlib = 0;
}
}
}
bool
AlgebraManager::IsAlgebraLoaded( const int algebraId )
{
return algebraNames.find( algebraId ) != algebraNames.end();
}
int
AlgebraManager::CountAlgebra()
{
int count = 0;
for ( int j = 1; j <= maxAlgebraId; j++ )
{
if( IsAlgebraLoaded( j ) )
count++;
}
return (count);
}
bool
AlgebraManager::NextAlgebraId( int& algebraId )
{
bool found = false;
algebraId++;
if ( algebraId > 0 && algebraId <= maxAlgebraId )
{
while ( !found && algebraId <= maxAlgebraId )
{
if( IsAlgebraLoaded( algebraId ) )
{
found = true;
}
else
{
algebraId++;
}
}
}
else
algebraId = 0;
return (found);
}
int
AlgebraManager::OperatorNumber( int algebraId )
{
return (algebra[algebraId]->GetNumOps());
}
void
AlgebraManager::InitOpPtrField() {
opPtrField.resize(maxAlgebraId+1);
for ( int alg = 0; alg <= maxAlgebraId; alg++ ) {
int numOps = 0;
if (algebra[alg] != 0) {
numOps = algebra[alg]->GetNumOps();
opPtrField[alg].resize(numOps+1);
for ( int op = 0; op < numOps; op++ ) {
opPtrField[alg][op] = algebra[alg]->GetOperator( op );
}
}
}
}
int
AlgebraManager::ConstrNumber( int algebraId )
{
return (algebra[algebraId]->GetNumTCs());
}
TypeConstructor*
AlgebraManager::GetTC( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId ));
}
Operator*
AlgebraManager::GetOP( int algebraId, int opId )
{
if(algebraId < 0 || algebraId >= (int)algebra.size()){
return 0;
}
Algebra* alg = algebra[algebraId];
if(!alg){
return 0;
}
return alg->GetOperator(opId);
}
InObject
AlgebraManager::InObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->inFunc);
}
OutObject
AlgebraManager::OutObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->outFunc);
}
OutObject
AlgebraManager::SaveToListObj( int algebraId, int typeId )
{
if( algebra[algebraId]->GetTypeConstructor( typeId )
->saveToListFunc != 0 )
return (algebra[algebraId]->GetTypeConstructor( typeId )
->saveToListFunc);
else
return (algebra[algebraId]->GetTypeConstructor( typeId )->outFunc);
}
InObject
AlgebraManager::RestoreFromListObj( int algebraId, int typeId )
{
if( algebra[algebraId]->GetTypeConstructor( typeId )
->restoreFromListFunc != 0 )
return (algebra[algebraId]->GetTypeConstructor( typeId )
->restoreFromListFunc);
else
return (algebra[algebraId]->GetTypeConstructor( typeId )->inFunc);
}
ObjectCreation
AlgebraManager::CreateObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->createFunc);
}
ObjectDeletion
AlgebraManager::DeleteObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->deleteFunc);
}
bool
AlgebraManager::OpenObj( const int algebraId, const int typeId,
SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->
Open( valueRecord, offset, typeInfo, value ));
}
bool
AlgebraManager::SaveObj( const int algebraId, const int typeId,
SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->
Save( valueRecord, offset, typeInfo, value ));
}
ObjectClose
AlgebraManager::CloseObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->closeFunc);
}
ObjectClone
AlgebraManager::CloneObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->cloneFunc);
}
ObjectCast
AlgebraManager::Cast( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->castFunc);
}
ObjectSizeof
AlgebraManager::SizeOfObj( int algebraId, int typeId )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )->sizeofFunc);
}
bool
AlgebraManager::TypeCheck( int algebraId, int typeId,
const ListExpr type, ListExpr& errorInfo )
{
return (algebra[algebraId]->GetTypeConstructor( typeId )
->TypeCheck(type, errorInfo));
}
bool
AlgebraManager::CheckKind( const string& kindName,
const ListExpr type,
ListExpr& errorInfo )
{
ListExpr tempErrorInfo = errorInfo;
multimap<string,TypeCheckFunction>::iterator pos;
for ( pos = kindTable.lower_bound( kindName );
pos != kindTable.upper_bound( kindName );
pos++ )
{
if ( (pos->second)( type, errorInfo ) )
{
errorInfo = tempErrorInfo;
return (true);
}
}
errorInfo = nl->Append(
errorInfo,
nl->ThreeElemList(
nl->IntAtom( 60 ),
nl->SymbolAtom( kindName ),
type ) );
return (false);
}
void
AlgebraManager::UpdateOperatorUsage(SystemInfoRel* table) {
table->clear();
int algId = 0;
while ( NextAlgebraId( algId ) )
{
const int N = OperatorNumber(algId);
for (int opId = 0; opId < N; opId++) {
string name = GetAlgebraName(algId);
string algebra = GetOP(algId, opId)->GetName();
Operator* op = opPtrField[algId][opId];
if(op){
for(int i=0;i<op->GetNumOfFun();i++){
OperatorUsageTuple* t = new OperatorUsageTuple;
t->algebra = algebra;
t->name = name;
t->vmid = i;
t->calls = op->GetCalls(i);
table->append(t,false);
}
}
}
}
}
vector< pair< pair<int, int>, ListExpr> >
AlgebraManager::matchingOperators(const ListExpr arguments){
vector< pair< pair<int,int>, ListExpr> > result;
result.clear();
for(unsigned int a=1 ; a<algebra.size() ; a++){ // algId=0 is prohibited
matchingOperators(a, arguments, result);
}
return result;
}
void AlgebraManager::matchingOperators(const int algId,
const ListExpr arguments,
vector< pair< pair<int,int>, ListExpr> >& result){
assert( (algId>0) && (algId<(int)algebra.size()) ); // 0 is an invalid algId!
ListExpr typeError = nl->SymbolAtom(Symbol::TYPEERROR());
Algebra* alg = algebra[algId];
if(alg!=0){
for(int o=0 ; o<alg->GetNumOps() ; o++){
Operator* op = alg->GetOperator(o);
try{
ListExpr res = op->CallTypeMapping(arguments);
// cout << "Check finished" << endl << endl;
if(!nl->Equal(res,typeError)){
pair<int, int> p1(algId,o);
pair<pair<int, int>, ListExpr> p(p1, res);
result.push_back(p);
}
} catch (...){
cerr << "Problem in Typemapping of operator " << op->GetName()
<< " in Algebra" << GetAlgebraName(algId) << endl;
cerr << "Throws an exception when called with "
<< nl->ToString(arguments) << endl;
}
}
}
}
void AlgebraManager::findTMExceptions(const string& algName,
const ListExpr argList,
queue<pair<string,string> >& q,
const bool print) {
if(algName.size()==0){
for(unsigned int a=1 ; a<algebra.size() ; a++){ // algId=0 is prohibited
Algebra* alg = algebra[a];
if(alg!=0){
if(print){
cout << "process algebra" << GetAlgebraName(a) << endl;
}
for(int o=0;o<alg->GetNumOps(); o++){
Operator* op = alg->GetOperator(o);
if(print){
cout << "process operator " << op->GetName() << endl;
}
try{
op->CallTypeMapping(argList);
} catch(...){
pair<string,string> p(GetAlgebraName(a), op->GetName());
q.push(p);
}
}
}
}
} else {
int a = GetAlgebraId(algName);
if(a<1){
if(print){
cout << "Algebra " << algName << " not found" << endl;
}
return;
}
if(print){
cout << "process algebra" << GetAlgebraName(a) << endl;
}
Algebra* alg = algebra[a];
for(int o=0;o<alg->GetNumOps(); o++){
Operator* op = alg->GetOperator(o);
if(print){
cout << "process operator " << op->GetName() << endl;
}
try{
op->CallTypeMapping(argList);
} catch(...){
pair<string,string> p(GetAlgebraName(a), op->GetName());
q.push(p);
}
}
}
}
bool AlgebraManager::findOperator(const string& name,
const ListExpr argList,
ListExpr& resultList,
int& algId,
int& opId){
int funId=0;
return findOperator(name,argList, resultList, algId, opId,funId);
}
bool AlgebraManager::findOperator(const string& name,
const ListExpr argList,
ListExpr& resultList,
int& algId,
int& opId,
int& funId){
ListExpr typeError = nl->SymbolAtom(Symbol::TYPEERROR());
NestedList* nl_orig = NList::getNLRef();
NList::setNLRef(nl);
int mode = 0; // normal mode, search for matching arglist
string algName ="";
if(nl->HasLength(argList,2)){
if(nl->IsEqual(nl->First(argList),"algebra")
&& nl->AtomType(nl->Second(argList)==SymbolType)){
mode = 1; // search within a specific algebra
algName = nl->SymbolValue(nl->Second(argList));
stringutils::toLower(algName);
if(algName=="all"){
mode = 2; // search all algebras, return first hit
}
}
}
for(unsigned int a=0;a<algebra.size();a++){
Algebra* alg = algebra[a];
if(alg!=0){
string an = algebraNames[a];
stringutils::toLower(an);
if(mode==0 || mode==2 || an==algName){
for(int o=0; o< alg->GetNumOps(); o++){
Operator* op = alg->GetOperator(o);
if(op->GetName() == name){
if(mode==0){
try{
ListExpr res = op->CallTypeMapping(argList);
if(!nl->Equal(res,typeError)){ // appropriate operator found
algId = a;
opId = o;
funId = op->Select(argList);
resultList = res;
NList::setNLRef(nl_orig);
return true;
}
} catch (...){
cerr << "Problem in Typemapping of operator " << op->GetName()
<< " in Algebra" << GetAlgebraName(a) << endl;
cerr << "Throws an exception when called with "
<< nl->ToString(argList) << endl;
}
} else { // mode <>0
algId = a;
opId = o;
funId = 0;
resultList = nl->TheEmptyList();
NList::setNLRef(nl_orig);
return true;
}
}
}
} // fitting algebra name
}
}
algId = 0;
opId = 0;
resultList = nl->TheEmptyList();
NList::setNLRef(nl_orig);
return false;
}
/*
~getCostEstimation~
Returns the costestimation for a specified value mapping.
If there is no one, null is returned.
*/
CostEstimation* AlgebraManager::getCostEstimation( const int algId,
const int opId,
const int funId){
Operator* op = getOperator(algId,opId);
return op?op->getCostEstimation(funId):0;
}
/*
~getCosts~
The next functions return costs for a specified operator when number of tuples
and size of a single tuple is given. If the operator does not provide a
cost estimation function or the getCost function is not implemented,
the return value is false.
*/
bool AlgebraManager::getCosts(
const int algId, const int opId, const int funId,
const size_t noTuples, const size_t sizeOfTuple,
const size_t noAttributes,
const double selectivity, const size_t memoryMB, size_t& costs){
CostEstimation* ce = getCostEstimation(algId,opId,funId);
costs = 0;
double mem=memoryMB; double co=0;
bool res = ce?ce->getCosts(noTuples,sizeOfTuple,noAttributes,
selectivity, mem,co)
:false;
if(co>0 && co <1){
costs = 1;
} else {
costs = (size_t) co;
}
return res;
}
bool AlgebraManager::getCosts(const int algId,
const int opId,
const int funId,
const size_t noTuples1,
const size_t sizeOfTuple1,
const size_t noAttributes1,
const size_t noTuples2,
const size_t sizeOfTuple2,
const size_t noAttributes2,
const double selectivity,
const size_t memoryMB,
size_t& costs) {
CostEstimation* ce = getCostEstimation(algId,opId,funId);
costs = 0;
double mem = memoryMB;
double co=0;
bool res = ce?ce->getCosts(noTuples1,sizeOfTuple1,noAttributes1,
noTuples2,sizeOfTuple2,noAttributes2,
selectivity, mem,co)
:false;
if(co>0 && co <1){
costs = 1;
} else {
costs = (size_t) co;
}
return res;
}
/*
~getLinearParams~
Retrieves the parameters for estimating the cost function of an operator
in a linear way.
*/
bool AlgebraManager::getLinearParams( const int algId,
const int opId,
const int funId,
const size_t noTuples1,
const size_t sizeOfTuple1,
const size_t noAttributes1,
const double selectivity,
double& sufficientMemory,
double& timeAtSuffMemory,
double& timeAt16MB) {
CostEstimation* ce = getCostEstimation(algId,opId,funId);
sufficientMemory = 0;
timeAtSuffMemory = 0;
timeAt16MB = 0;
return ce?ce->getLinearParams(noTuples1, sizeOfTuple1, noAttributes1,
selectivity,
sufficientMemory, timeAtSuffMemory,
timeAt16MB)
:false;
}
bool AlgebraManager::getLinearParams( const int algId,
const int opId,
const int funId,
const size_t noTuples1,
const size_t sizeOfTuple1,
const size_t noAttributes1,
const size_t noTuples2,
const size_t sizeOfTuple2,
const size_t noAttributes2,
const double selectivity,
double& sufficientMemory,
double& timeAtSuffMemory,
double& timeAt16MB){
CostEstimation* ce = getCostEstimation(algId,opId,funId);
sufficientMemory = 0;
timeAtSuffMemory = 0;
timeAt16MB = 0;
return ce?ce->getLinearParams(noTuples1, sizeOfTuple1, noAttributes1,
noTuples2, sizeOfTuple2, noAttributes2,
selectivity,
sufficientMemory, timeAtSuffMemory,
timeAt16MB)
:false;
}
/*
~getFunction~
Returns an approximation of the cost function of a specified value mapping as
a parametrized function.
*/
bool AlgebraManager::getFunction(
const int algId,
const int opId,
const int funId,
const size_t noTuples,
const size_t sizeOfTuple,
const size_t noAttributes1,
const double selectivity,
int& funType,
double& sufficientMemory,
double& timeAtSuffMemory,
double& timeAt16MB,
double& a, double& b, double&c, double& d){
CostEstimation* ce = getCostEstimation(algId,opId,funId);
funType = -1;
sufficientMemory = 0;
timeAtSuffMemory = 0;
timeAt16MB = 0;
a = b = c = d = 0;
return ce?ce->getFunction(noTuples, sizeOfTuple, noAttributes1,
selectivity,
funType, sufficientMemory,
timeAtSuffMemory, timeAt16MB,
a,b,c,d)
: false;
}
bool AlgebraManager::getFunction(const int algId,
const int opId,
const int funId,
const size_t noTuples1,
const size_t sizeOfTuple1,
const size_t noAttributes1,
const size_t noTuples2,
const size_t sizeOfTuple2,
const size_t noAttributes2,
const double selectivity,
int& funType,
double& sufficientMemory,
double& timeAtSuffMemory,
double& timeAt16MB,
double& a, double& b, double&c, double& d) {
CostEstimation* ce = getCostEstimation(algId,opId,funId);
funType = -1;
sufficientMemory = 0;
timeAtSuffMemory = 0;
timeAt16MB = 0;
a = b = c = d = 0;
return ce?ce->getFunction(noTuples1, sizeOfTuple1,noAttributes1,
noTuples2, sizeOfTuple2,noAttributes2,
selectivity,
funType, sufficientMemory,
timeAtSuffMemory, timeAt16MB,
a,b,c,d)
: false;
}
/*
Return maxAlgebraId
*/
int AlgebraManager::getMaxAlgebraId() const {
return maxAlgebraId;
}