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

1582 lines
42 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]
May 2008, Victor Almeida
[1] Implementation of MON-Tree Algebra
[TOC]
1 Includes and Defines
*/
#include <iostream>
#include "./MONTreeAlgebra.h"
#include "../Rectangle/RectangleAlgebra.h"
#include "../TupleIdentifier/TupleIdentifier.h"
#include "../Spatial/SpatialAlgebra.h"
#include "../Hash/HashAlgebra.h"
#include "../Network/NetworkAlgebra.h"
#include "../Temporal/TemporalAlgebra.h"
#include "../TemporalNet/TemporalNetAlgebra.h"
#include "Symbols.h"
#include "ListUtils.h"
using namespace std;
using namespace temporalalgebra;
template<class BottomR_TreeLeafInfo>
MON_Tree<BottomR_TreeLeafInfo>::MON_Tree():
index( true, 4000 ),
routeHash( new Hash(SmiKey::Integer) ),
network( NULL ),
top_RTree( NULL ),
bottom_RTree( NULL )
{
index.Create();
top_RTree = new R_Tree<2, TopR_TreeLeafInfo>( &index );
}
template<class BottomR_TreeLeafInfo>
void MON_Tree<BottomR_TreeLeafInfo>::SetNetwork( network::Network *network )
{
this->network = network;
}
template<class BottomR_TreeLeafInfo>
MON_Tree<BottomR_TreeLeafInfo>::MON_Tree( network::Network *network,
SmiFileId indexFileId,
SmiFileId hashFileId ):
index( true ),
routeHash( new Hash(SmiKey::Integer, hashFileId) ),
network( network ),
top_RTree( NULL ),
bottom_RTree( NULL )
{
index.Open( indexFileId );
top_RTree = new R_Tree<2, TopR_TreeLeafInfo>( &index, 1 );
}
template<class BottomR_TreeLeafInfo>
MON_Tree<BottomR_TreeLeafInfo>::~MON_Tree()
{
delete routeHash;
if( bottom_RTree != NULL )
delete bottom_RTree;
delete top_RTree;
if( index.IsOpen() )
index.Close();
}
template<class BottomR_TreeLeafInfo>
void MON_Tree<BottomR_TreeLeafInfo>::Insert( const int routeId,
const SmiRecordId bottomId )
{
routeHash->Append( SmiKey((int64_t)routeId), bottomId );
}
template<class BottomR_TreeLeafInfo>
void MON_Tree<BottomR_TreeLeafInfo>::Insert(
const temporalnet::MGPoint& mgpoint,
const BottomR_TreeLeafInfo& info )
{
assert( network != NULL );
for( int i = 0; i < mgpoint.GetNoComponents(); i++ )
{
temporalnet::UGPoint ugpoint;
mgpoint.Get( i, ugpoint );
Insert( ugpoint, info );
}
}
template<class BottomR_TreeLeafInfo>
void MON_Tree<BottomR_TreeLeafInfo>::Insert(
const temporalnet::UGPoint& ugpoint,
const BottomR_TreeLeafInfo& info )
{
int routeId = ugpoint.p0.GetRouteId();
CcInt key( true, routeId );
HashIterator *iter = routeHash->ExactMatch( &key );
Rectangle<3> box3D = ugpoint.NetBoundingBox3d();
double minMax[] = {box3D.MinD(1), box3D.MaxD(1),
box3D.MinD(2), box3D.MaxD(2) };
Rectangle<2> box2D = BBox<2>( true, minMax);
// box is constructed first with the position, then the interval.
R_TreeLeafEntry<2, BottomR_TreeLeafInfo>
entry( box2D, info );
if( iter->Next() )
{
assert( iter->GetId() > 0 );
bottom_RTree = new R_Tree<2, BottomR_TreeLeafInfo>( &index, iter->GetId() );
}
else
{
Tuple *t = network->GetRoute( routeId );
Line *curve = (Line*)t->GetAttribute( network::ROUTE_CURVE );
Rectangle<2> routeBox = curve->BoundingBox();
assert( bottom_RTree == NULL );
bottom_RTree = new R_Tree<2, BottomR_TreeLeafInfo>( &index );
routeHash->Append( SmiKey( key.GetIntval() ),
bottom_RTree->HeaderRecordId() );
TopR_TreeLeafInfo info( routeId, bottom_RTree->HeaderRecordId() );
top_RTree->Insert( R_TreeLeafEntry<2, TopR_TreeLeafInfo>( routeBox,
info ) );
t->DeleteIfAllowed();
}
delete iter;
bottom_RTree->Insert( entry );
delete bottom_RTree; bottom_RTree = NULL;
}
template<class BottomR_TreeLeafInfo>
void MON_Tree<BottomR_TreeLeafInfo>::
CalculateSearchBoxSet( const Rectangle<2>& box,
const SimpleLine& curve,
const Interval<Instant>& timeInterval,
RectangleSet<2>& result ) const
{
assert( box.Intersects( curve.BoundingBox() ) );
if( box.Contains( curve.BoundingBox() ) )
{
double minMax[] = { 0.0, curve.Length(),
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble()};
result.Add( BBox<2>( true,minMax) );
}
else
{
double p1 = -1,
p2 = -1;
for( int i = 0; i < curve.Size()/2; i++ )
{
LRS lrs;
curve.Get( i, lrs );
HalfSegment hs;
curve.Get( lrs.hsPos, hs );
if( box.Intersects( hs.BoundingBox() ) )
{
if( p1 < 0 )
{
assert( p2 < 0 );
p1 = lrs.lrsPos;
p2 = p1;
}
p2 += hs.Length();
}
else
{
if( p2 >= 0 )
{
assert( p1 >= 0 );
double minMax[] = {p1, p2,
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble() };
result.Add( BBox<2>( true,minMax) );
}
p1 = -1;
p2 = -1;
}
}
if( p2 >= 0 )
{
assert( p1 >= 0 );
double minMax[] = {p1, p2,
timeInterval.start.ToDouble(),
timeInterval.end.ToDouble() };
result.Add( BBox<2>( true,minMax) );
}
}
}
template<class BottomR_TreeLeafInfo>
bool MON_Tree<BottomR_TreeLeafInfo>::First( const Rectangle<2>& box,
const Interval<Instant>& timeInterval,
R_TreeLeafEntry<2, BottomR_TreeLeafInfo>& result )
{
assert( network != NULL );
R_TreeLeafEntry<2, TopR_TreeLeafInfo> entry;
if( !top_RTree->First( box, entry ) )
return false;
assert( bottom_RTree == NULL );
searchBox = box;
searchTimeInterval = timeInterval;
begin = true;
assert( entry.info.childTreeId > 0 );
bottom_RTree =
new R_Tree<2, BottomR_TreeLeafInfo>( &index, entry.info.childTreeId );
Tuple *t = network->GetRoute( entry.info.routeId );
SimpleLine *curve = (SimpleLine*)t->GetAttribute( network::ROUTE_CURVE );
searchBoxSet.Clear();
CalculateSearchBoxSet( searchBox,
*curve,
searchTimeInterval,
searchBoxSet );
t->DeleteIfAllowed();
return Next( result );
}
template<class BottomR_TreeLeafInfo>
bool MON_Tree<BottomR_TreeLeafInfo>::
Next( R_TreeLeafEntry<2, BottomR_TreeLeafInfo>& result )
{
assert( network != NULL );
R_TreeLeafEntry<2, TopR_TreeLeafInfo> topEntry;
bool found = false;
do
{
if( begin )
{
if( bottom_RTree == NULL )
found = false;
else
{
found = bottom_RTree->First( searchBoxSet, result );
begin = false;
}
}
else
{
assert( bottom_RTree != NULL );
found = bottom_RTree->Next( result );
}
if( !found )
{
if( !top_RTree->Next( topEntry ) )
{
delete bottom_RTree;
bottom_RTree = NULL;
return false;
}
delete bottom_RTree;
bottom_RTree = NULL;
begin = true;
assert( topEntry.info.childTreeId > 0 );
bottom_RTree =
new R_Tree<2, BottomR_TreeLeafInfo>( &index,
topEntry.info.childTreeId );
Tuple *t = network->GetRoute( topEntry.info.routeId );
SimpleLine *curve = (SimpleLine*)t->GetAttribute( network::ROUTE_CURVE );
searchBoxSet.Clear();
CalculateSearchBoxSet( searchBox,
*curve,
searchTimeInterval,
searchBoxSet );
t->DeleteIfAllowed();
}
} while( !found );
return true;
}
/*
1 Type constructor ~montree~
1.1 Type property of type constructor ~montree~
*/
ListExpr MON_TreeProp()
{
ListExpr examplelist = nl->TextAtom();
nl->AppendText(examplelist,
"<network> <relation> createmontree [<attrname>]"
" where <attrname> is the key of type mgpoint");
return
(nl->TwoElemList(
nl->TwoElemList(nl->StringAtom("Creation"),
nl->StringAtom("Example Creation")),
nl->TwoElemList(examplelist,
nl->StringAtom("(let mon = net1 trains1"
" createmontree [trip])"))));
}
/*
1.8 ~Check~-function of type constructor ~montree~
*/
bool CheckMON_Tree(ListExpr type, ListExpr& errorInfo)
{
AlgebraManager* algMgr;
if((!nl->IsAtom(type))
&& (nl->ListLength(type) == 4)
&& nl->Equal(nl->First(type), nl->SymbolAtom("montree")))
{
algMgr = SecondoSystem::GetAlgebraManager();
return
algMgr->CheckKind(Kind::TUPLE(), nl->Second(type), errorInfo) &&
nl->IsEqual(nl->Third(type), "mgpoint") &&
nl->IsAtom(nl->Fourth(type)) &&
nl->AtomType(nl->Fourth(type)) == BoolType;
}
errorInfo = nl->Append(errorInfo,
nl->ThreeElemList(
nl->IntAtom(60),
nl->SymbolAtom("MONTREE"),
type));
return false;
}
/*
6 Functions for the type constructors
6.1 ~Out~-function
It does not make sense to have an index as an independent value
since the record ids stored in it become obsolete as soon as
the underlying relation is deleted. Therefore this function
does nothing.
*/
ListExpr OutMON_Tree(ListExpr typeInfo, Word value)
{
return nl->StringAtom("OutMON_Tree");
}
/*
6.2 ~In~-function
Reading an index from a list does not make sense because it
is not an independent value. Therefore calling this function leads
to program abort.
*/
Word InMON_Tree( ListExpr typeInfo, ListExpr value,
int errorPos, ListExpr& errorInfo, bool& correct )
{
correct = false;
return SetWord(Address(0));
}
/*
6.3 ~Create~-function
*/
Word CreateMON_Tree( const ListExpr typeInfo )
{
if( nl->BoolValue(nl->Fourth(typeInfo)) == true )
return SetWord( new MON_Tree<BottomR_TreeLeafInfo>() );
else
return SetWord( new MON_Tree<SmiRecordId>() );
}
/*
6.4 ~Close~-function
*/
void CloseMON_Tree( const ListExpr typeInfo, Word& w )
{
if( nl->BoolValue(nl->Fourth(typeInfo)) == true )
{
MON_Tree<BottomR_TreeLeafInfo> *montree =
(MON_Tree<BottomR_TreeLeafInfo>*)w.addr;
delete montree;
}
else
{
MON_Tree<SmiRecordId> *montree =
(MON_Tree<SmiRecordId>*)w.addr;
delete montree;
}
}
/*
6.5 ~Clone~-function
Not implemented yet.
*/
Word CloneMON_Tree( const ListExpr typeInfo, const Word& w )
{
return SetWord( Address(0) );
}
/*
6.6 ~Delete~-function
*/
void DeleteMON_Tree( const ListExpr typeInfo, Word& w )
{
if( nl->BoolValue(nl->Fourth(typeInfo)) == true )
{
MON_Tree<BottomR_TreeLeafInfo> *montree =
(MON_Tree<BottomR_TreeLeafInfo>*)w.addr;
delete montree;
}
else
{
MON_Tree<SmiRecordId> *montree =
(MON_Tree<SmiRecordId>*)w.addr;
delete montree;
}
}
/*
6.7 ~Cast~-function
*/
void* CastMON_Tree( void* addr)
{
return ( 0 );
}
/*
6.8 ~Open~-function
*/
bool OpenMON_Tree( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
SmiFileId indexFileId;
valueRecord.Read( &indexFileId, sizeof( SmiFileId ), offset );
offset += sizeof( SmiFileId );
SmiRecordId hashFileId;
valueRecord.Read( &hashFileId, sizeof( SmiFileId ), offset );
offset += sizeof( SmiFileId );
if( nl->BoolValue(nl->Fourth(typeInfo)) == true )
{
MON_Tree<BottomR_TreeLeafInfo> *montree =
new MON_Tree<BottomR_TreeLeafInfo>( NULL,
indexFileId,
hashFileId );
value = SetWord( montree );
}
else
{
MON_Tree<SmiRecordId> *montree =
new MON_Tree<SmiRecordId>( NULL,
indexFileId,
hashFileId );
value = SetWord( montree );
}
return true;
}
/*
6.9 ~Save~-function
*/
bool SaveMON_Tree( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
SmiFileId indexFileId, hashFileId;
if( nl->BoolValue(nl->Fourth(typeInfo)) == true )
{
MON_Tree<BottomR_TreeLeafInfo> *montree =
(MON_Tree<BottomR_TreeLeafInfo> *)value.addr;
indexFileId = montree->GetIndexFileId();
hashFileId = montree->GetHashFileId();
}
else
{
MON_Tree<SmiRecordId> *montree =
(MON_Tree<SmiRecordId> *)value.addr;
indexFileId = montree->GetIndexFileId();
hashFileId = montree->GetHashFileId();
}
valueRecord.Write( &indexFileId, sizeof( SmiFileId ), offset );
offset += sizeof( SmiFileId );
valueRecord.Write( &hashFileId, sizeof( SmiFileId ), offset );
offset += sizeof( SmiFileId );
return true;
}
/*
6.10 ~SizeOf~-function
*/
int SizeOfMON_Tree()
{
return 0;
}
/*
1.12 Type Constructor object for type constructor ~montree~
*/
TypeConstructor montree( "montree",
MON_TreeProp,
OutMON_Tree,
InMON_Tree,
0,
0,
CreateMON_Tree,
DeleteMON_Tree,
OpenMON_Tree,
SaveMON_Tree,
CloseMON_Tree,
CloneMON_Tree,
CastMON_Tree,
SizeOfMON_Tree,
CheckMON_Tree );
/*
7 Operators of the MON-Tree Algebra
7.1 Operator ~createmontree~
7.1.1 Type Mapping of operator ~createmontree~
*/
ListExpr CreateMONTreeTypeMap(ListExpr args)
{
string attrName, relDescriptionStr, argstr;
string errmsg = "Incorrect input for operator createmontree.";
int attrIndex;
ListExpr attrType;
if(nl->ListLength(args) != 3){
return listutils::typeError(errmsg +
"\nOperator createmontree expects three arguments.");
}
if(!nl->IsEqual(nl->First(args), "network")){
return listutils::typeError( errmsg +
"\nThe first argument must be of type network.");
}
ListExpr relDescription = nl->Second(args),
attrNameLE = nl->Third(args);
if(!nl->IsAtom(attrNameLE) || (nl->AtomType(attrNameLE) != SymbolType)){
return listutils::typeError( errmsg +
"\nThe third argument must be the name of "
"the attribute to index.");
}
attrName = nl->SymbolValue(attrNameLE);
// Check for relation or tuplestream as first argument
if( !IsRelDescription(relDescription) &&
!IsStreamDescription(relDescription) )
{
nl->WriteToString (relDescriptionStr, relDescription);
ErrorReporter::ReportError( "\nOperator createmontree expects a relation "
" or a stream of tuples as its second argument, but gets '"
+ relDescriptionStr + "'.");
return nl->TypeError();
}
// Test for index attribute
ListExpr tupleDescription = nl->Second(relDescription);
ListExpr attrList = nl->Second(tupleDescription);
attrIndex = FindAttribute(attrList, attrName, attrType);
if( attrIndex <= 0 ){
return listutils::typeError( errmsg +
"\nOperator createmontree expects the attribute " +
attrName + "\npassed as third argument to be part of "
"the relation or stream description\n'" +
relDescriptionStr + "'.");
}
if(!nl->IsEqual(attrType, "mgpoint") &&
!nl->IsEqual(attrType, "ugpoint")){
return listutils::typeError(errmsg +
"\nOperator createmontree expects that attribute "+attrName+"\n"
"belongs to type mgpoint or ugpoint.");
}
bool mgpoint = nl->IsEqual(attrType, "mgpoint");
if( nl->IsEqual(nl->First(relDescription), Relation::BasicType()) )
{
return
nl->ThreeElemList(
nl->SymbolAtom(Symbol::APPEND()),
nl->OneElemList(
nl->IntAtom(attrIndex)),
nl->FourElemList(
nl->SymbolAtom("montree"),
tupleDescription,
attrType,
nl->BoolAtom(mgpoint)));
}
else
{
/*
Here we can have two possibilities:
- multi-entry indexing, or
- double indexing
For multi-entry indexing, one and only one of the attributes
must be a tuple identifier. In the latter, together with
a tuple identifier, the last two attributes must be of
integer type (~int~).
In the first case, a standard MON-Tree is created
containing several entries to the same tuple identifier, and
in the latter, a double index MON-Tree is created using as low
and high parameters these two last integer numbers.
*/
ListExpr first = nl->TheEmptyList();
ListExpr rest = nl->TheEmptyList();
ListExpr newAttrList = nl->TheEmptyList();
ListExpr lastNewAttrList = nl->TheEmptyList();
int tidIndex = 0;
string type;
bool firstcall = true,
doubleIndex = false;
int nAttrs = nl->ListLength( attrList );
rest = attrList;
int j = 1;
while (!nl->IsEmpty(rest))
{
first = nl->First(rest);
rest = nl->Rest(rest);
type = nl->SymbolValue(nl->Second(first));
if (type == TupleIdentifier::BasicType())
{
if( tidIndex != 0){
return listutils::typeError(
"Operator createmontree expects as first argument a stream "
"with\none and only one attribute of type 'tid'\n'"
"but gets\n'" + relDescriptionStr + "'.");
}
tidIndex = j;
}
else if( j == nAttrs - 1 && type == CcInt::BasicType() &&
nl->SymbolValue(
nl->Second(nl->First(rest))) == CcInt::BasicType() )
{ // the last two attributes are integers
doubleIndex = true;
}
else
{
if (firstcall)
{
firstcall = false;
newAttrList = nl->OneElemList(first);
lastNewAttrList = newAttrList;
}
else
{
lastNewAttrList = nl->Append(lastNewAttrList, first);
}
}
j++;
}
if( tidIndex == 0){
return listutils::typeError(
"Operator createmontree expects as first argument a stream "
"with\none and only one attribute of type 'tid'\n'"
"but gets\n'" + relDescriptionStr + "'.");
}
return
nl->ThreeElemList(
nl->SymbolAtom(Symbol::APPEND()),
nl->TwoElemList(
nl->IntAtom(attrIndex),
nl->IntAtom(tidIndex)),
nl->FourElemList(
nl->SymbolAtom("montree"),
nl->TwoElemList(
nl->SymbolAtom(Tuple::BasicType()),
newAttrList),
attrType,
nl->BoolAtom(doubleIndex)));
}
}
/*
4.1.2 Selection function of operator ~createmontree~
*/
int
CreateMONTreeSelect (ListExpr args)
{
ListExpr relDescription = nl->Second(args),
attrNameLE = nl->Third(args),
tupleDescription = nl->Second(relDescription),
attrList = nl->Second(tupleDescription);
string attrName = nl->SymbolValue(attrNameLE);
ListExpr attrType;
FindAttribute(attrList, attrName, attrType);
int doubleUp = 0;
if(nl->IsEqual(attrType, "ugpoint"))
doubleUp = 3;
if( nl->SymbolValue(nl->First(relDescription)) == Relation::BasicType())
return doubleUp + 0;
if( nl->SymbolValue(nl->First(relDescription)) == Symbol::STREAM())
{
ListExpr first = nl->TheEmptyList();
ListExpr rest = attrList;
while (!nl->IsEmpty(rest))
{
first = nl->First(rest);
rest = nl->Rest(rest);
}
if( nl->IsEqual( nl->Second( first ), CcInt::BasicType() ) )
// Double indexing
return doubleUp + 2;
else
// Multi-entry indexing
return doubleUp + 1;
}
return -1;
}
/*
4.1.3 Value mapping function of operator ~createmontree~
*/
int CreateMONTreeRelMGPoint(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Relation* relation;
int attrIndex;
GenericRelationIterator* iter;
Tuple* tuple;
network::Network *network;
MON_Tree<BottomR_TreeLeafInfo> *montree =
(MON_Tree<BottomR_TreeLeafInfo> *)qp->ResultStorage(s).addr;
result.setAddr( montree );
network = (network::Network*)args[0].addr;
relation = (Relation*)args[1].addr;
attrIndex = ((CcInt*)args[3].addr)->GetIntval() - 1;
montree->SetNetwork( network );
iter = relation->MakeScan();
while( (tuple = iter->GetNextTuple()) != 0 )
{
temporalnet::MGPoint* mgpoint =
(temporalnet::MGPoint*)tuple->GetAttribute(attrIndex);
if( mgpoint->IsDefined() )
{
for( int i = 0; i < mgpoint->GetNoComponents(); i++ )
{
BottomR_TreeLeafInfo info(tuple->GetTupleId(), i, i);
temporalnet::UGPoint ugpoint;
mgpoint->Get( i, ugpoint );
montree->Insert( ugpoint, info );
}
}
tuple->DeleteIfAllowed();
}
delete iter;
return 0;
}
int CreateMONTreeRelUGPoint(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Relation* relation;
int attrIndex;
GenericRelationIterator* iter;
Tuple* tuple;
network::Network *network;
MON_Tree<SmiRecordId> *montree =
(MON_Tree<SmiRecordId> *)qp->ResultStorage(s).addr;
result.setAddr( montree );
network = (network::Network*)args[0].addr;
relation = (Relation*)args[1].addr;
attrIndex = ((CcInt*)args[3].addr)->GetIntval() - 1;
montree->SetNetwork( network );
iter = relation->MakeScan();
while( (tuple = iter->GetNextTuple()) != 0 )
{
temporalnet::UGPoint* ugpoint =
(temporalnet::UGPoint*)tuple->GetAttribute(attrIndex);
if( ugpoint->IsDefined() )
montree->Insert( *ugpoint, tuple->GetTupleId() );
tuple->DeleteIfAllowed();
}
delete iter;
return 0;
}
template<class T>
int CreateMONTreeStream(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Word wTuple;
MON_Tree<SmiRecordId> *montree =
(MON_Tree<SmiRecordId> *)qp->ResultStorage(s).addr;
result.setAddr( montree );
int attrIndex = ((CcInt*)args[2].addr)->GetIntval() - 1,
tidIndex = ((CcInt*)args[3].addr)->GetIntval() - 1;
qp->Open(args[0].addr);
qp->Request(args[0].addr, wTuple);
while (qp->Received(args[0].addr))
{
Tuple* tuple = (Tuple*)wTuple.addr;
T *t = (T*)tuple->GetAttribute(attrIndex);
TupleIdentifier *tupleId = (TupleIdentifier *)tuple->GetAttribute(tidIndex);
if( t->IsDefined() && tupleId->IsDefined() )
{
montree->Insert( *t, tupleId->GetTid() );
}
tuple->DeleteIfAllowed();
qp->Request(args[0].addr, wTuple);
}
qp->Close(args[0].addr);
return 0;
}
template<class T>
int CreateMONTreeDblStream(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Word wTuple;
MON_Tree<BottomR_TreeLeafInfo> *montree =
(MON_Tree<BottomR_TreeLeafInfo> *)qp->ResultStorage(s).addr;
result.setAddr( montree );
int attrIndex = ((CcInt*)args[2].addr)->GetIntval() - 1,
tidIndex = ((CcInt*)args[3].addr)->GetIntval() - 1;
qp->Open(args[0].addr);
qp->Request(args[0].addr, wTuple);
while (qp->Received(args[0].addr))
{
Tuple* tuple = (Tuple*)wTuple.addr;
T *t = (T*)tuple->GetAttribute(attrIndex);
TupleIdentifier *tupleId =
(TupleIdentifier *)tuple->GetAttribute(tidIndex);
CcInt *low = (CcInt*)tuple->GetAttribute(tuple->GetNoAttributes()-2),
*high = (CcInt*)tuple->GetAttribute(tuple->GetNoAttributes()-1);
if( t->IsDefined() &&
tupleId->IsDefined() &&
low->IsDefined() &&
high->IsDefined() )
{
BottomR_TreeLeafInfo info( tupleId->GetTid(),
low->GetIntval(),
high->GetIntval() );
montree->Insert( *t, info );
}
tuple->DeleteIfAllowed();
qp->Request(args[0].addr, wTuple);
}
qp->Close(args[0].addr);
return 0;
}
/*
4.1.5 Definition of value mapping vectors
*/
ValueMapping createmontreemap [] = {
CreateMONTreeRelMGPoint,
CreateMONTreeStream<temporalnet::MGPoint>,
CreateMONTreeDblStream<temporalnet::MGPoint>,
CreateMONTreeRelUGPoint,
CreateMONTreeStream<temporalnet::UGPoint>,
CreateMONTreeDblStream<temporalnet::UGPoint> };
/*
4.1.6 Specification of operator ~createmontree~
*/
const string CreateMONTreeSpec =
"( ( \"1st Signature\""
" \"Syntax\" \"Meaning\" "
"\"Example\" ) "
"( <text>((rel (tuple (x1 t1)...(xn tn)))) xi)"
" -> (montree (tuple ((x1 t1)...(xn tn))) ti)\n"
"((stream (tuple (x1 t1)...(xn tn) (id tid))) xi)"
" -> (montree (tuple ((x1 t1)...(xn tn))) ti)\n"
"<text>_ createmontree [ _ ]</text--->"
"<text>Creates a montree. The key type ti must "
"be of type mgpoint.</text--->"
"<text>let mymontree = Trains "
"createmontree[Trip]</text--->"
") )";
/*
4.1.7 Definition of operator ~createmontree~
*/
Operator createmontree (
"createmontree", // name
CreateMONTreeSpec, // specification
6, // Number of overloaded functions
createmontreemap, // value mapping
CreateMONTreeSelect, // trivial selection function
CreateMONTreeTypeMap // type mapping
);
/*
7.2 Operator ~windowtimeintersects~
7.2.1 Type mapping function of operator ~windowtimeintersects~
*/
ListExpr MON_WindowTimeIntersectsTypeMap(ListExpr args)
{
string errmsg = "Incorrect input for operator windowtimeintersects.";
string monDescriptionStr, relDescriptionStr;
if(nl->ListLength(args) != 6){
return listutils::typeError(errmsg);
}
/* Split argument in three parts */
ListExpr networkDescription = nl->First(args),
monDescription = nl->Second(args),
relDescription = nl->Third(args),
searchWindow = nl->Fourth(args),
searchStart = nl->Fifth(args),
searchEnd = nl->Sixth(args);
if(!nl->IsEqual(networkDescription, "network")){
return listutils::typeError(
"Operator windowtimeintersects expects the first argument\n"
"to be of type network.");
}
/* Query window: find out type of key */
if(!nl->IsEqual(searchWindow, Rectangle<2>::BasicType())){
return listutils::typeError(
"Operator windowtimeintersects expects that the search window\n"
"is of type rect.");
}
// Handling of the time interval
if(!nl->IsEqual(searchStart, Instant::BasicType()) ||
!nl->IsEqual(searchEnd, Instant::BasicType())){
return listutils::typeError(
"Operator windowtimeintersects expects the fifth and sixth\n"
"arguments to be a time interval.");
}
/* handle montree part of argument */
nl->WriteToString (monDescriptionStr, monDescription);
if(nl->ListLength(monDescription) != 4){
return listutils::typeError(
"Operator windowtimeintersects expects a MON-Tree with structure "
"(montree (tuple ((a1 t1)...(an tn))) attrtype bool)\n"
"\nbut gets the following '"
+monDescriptionStr+"'.");
}
ListExpr monSymbol = nl->First(monDescription);
/* handle rtree type constructor */
if(!nl->IsEqual(monSymbol, "montree")){
return listutils::typeError(
"Operator windowtimeintersects expects a MON-Tree \n"
"as second argument.");
}
ListExpr monTupleDescription = nl->Second(monDescription);
/* handle rtree type constructor */
/* if(nl->IsEqual(monSymbol, "montree")){
return listutils::typeError(
"Operator windowtimeintersects expects a MON-Tree \n"
"as second argument.);
}*/
/* handle rel part of argument */
nl->WriteToString (relDescriptionStr, relDescription);
if(!IsRelDescription(relDescription)){
return listutils::typeError(
"Operator windowtimeintersects expects a "
"relation as its third argument, but gets '"
+ relDescriptionStr + "'.");
}
return
nl->TwoElemList(
nl->SymbolAtom(Symbol::STREAM()),
monTupleDescription);
}
/*
5.1.3 Value mapping function of operator ~windowintersects~
*/
struct MON_WindowTimeIntersectsLocalInfo
{
Relation* relation;
MON_Tree<SmiRecordId>* montree;
BBox<2> searchBox;
Interval<Instant> searchTimeInterval;
bool first;
};
int MON_WindowTimeIntersects( Word* args, Word& result,
int message, Word& local,
Supplier s )
{
MON_WindowTimeIntersectsLocalInfo *localInfo;
switch (message)
{
case OPEN :
{
localInfo = new MON_WindowTimeIntersectsLocalInfo;
localInfo->montree = (MON_Tree<SmiRecordId>*)args[1].addr;
localInfo->montree->SetNetwork( (network::Network*)args[0].addr );
localInfo->relation = (Relation*)args[2].addr;
localInfo->first = true;
localInfo->searchBox = *(BBox<2>*)args[3].addr;
localInfo->searchTimeInterval =
Interval<Instant>( *(Instant*)args[4].addr,
*(Instant*)args[5].addr,
true, true );
assert(localInfo->montree != 0);
assert(localInfo->relation != 0);
local.setAddr(localInfo);
return 0;
}
case REQUEST :
{
localInfo = (MON_WindowTimeIntersectsLocalInfo*)local.addr;
R_TreeLeafEntry<2, SmiRecordId> e;
if ( !localInfo->searchBox.IsDefined() ||
!localInfo->searchTimeInterval.IsValid() )
{
return CANCEL;
}
else
{
if(localInfo->first)
{
localInfo->first = false;
if( localInfo->montree->First( localInfo->searchBox,
localInfo->searchTimeInterval,
e ) )
{
Tuple *tuple = localInfo->relation->GetTuple(e.info, false);
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
else
{
if( localInfo->montree->Next( e ) )
{
Tuple *tuple = localInfo->relation->GetTuple(e.info, false);
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
}
}
case CLOSE :
{
if(local.addr)
{
localInfo = (MON_WindowTimeIntersectsLocalInfo*)local.addr;
delete localInfo;
local.setAddr(Address(0));
}
return 0;
}
}
return 0;
}
/*
5.1.5 Specification of operator ~windowintersects~
*/
const string windowintersectsSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>montree(tuple ((x1 t1)...(xn tn))"
" ti) x rel(tuple ((x1 t1)...(xn tn))) "
"x rect x instant x instant ->\n"
" (stream (tuple ((x1 t1)...(xn tn))))\n</text--->"
"<text>_ _ windowintersects [ _, _, _ ]</text--->"
"<text>Uses the given MON-Tree to find all tuples"
" in the given relation with .xi intersects the "
" argument value's bounding box within "
" the time interval argument.</text--->"
"<text>query trainsInd trains windowintersects"
" [r, t1, t2] consume; where trainsInd "
"is e.g. created with 'let trainsInd = "
"net trains createmontree [trip]'</text--->"
") )";
/*
5.1.6 Definition of operator ~windowintersects~
*/
Operator windowtimeintersects (
"windowtimeintersects", // name
windowintersectsSpec, // specification
MON_WindowTimeIntersects,
Operator::SimpleSelect, // trivial selection function
MON_WindowTimeIntersectsTypeMap // type mapping
);
/*
7.2 Operator ~windowtimeintersectsS~
7.2.1 Type mapping function of operator ~windowtimeintersectsS~
*/
ListExpr MON_WindowTimeIntersectsSTypeMap(ListExpr args)
{
string errmsg = "Incorrect input for operator windowtimeintersectsS.";
string monDescriptionStr, relDescriptionStr;
if(nl->ListLength(args) != 6){
return listutils::typeError(errmsg);
}
/* Split argument in three parts */
ListExpr networkDescription = nl->First(args),
monDescription = nl->Second(args),
relDescription = nl->Third(args),
searchWindow = nl->Fourth(args),
searchStart = nl->Fifth(args),
searchEnd = nl->Sixth(args);
if(!nl->IsEqual(networkDescription, "network")){
return listutils::typeError(
"Operator windowtimeintersectsS expects the first argument\n"
"to be of type network.");
}
/* Query window: find out type of key */
if(!nl->IsEqual(searchWindow, Rectangle<2>::BasicType())){
return listutils::typeError(
"Operator windowtimeintersectsS expects that the search window\n"
"is of type rect.");
}
// Handling of the time interval
if(!nl->IsEqual(searchStart, Instant::BasicType()) ||
!nl->IsEqual(searchEnd, Instant::BasicType())){
return listutils::typeError(
"Operator windowtimeintersectsS expects the fifth and sixth\n"
"arguments to be a time interval.");
}
/* handle montree part of argument */
nl->WriteToString (monDescriptionStr, monDescription);
if( nl->ListLength(monDescription) != 4 ){
return listutils::typeError(
"Operator windowtimeintersectsS expects a MON-Tree with structure "
"(montree (tuple ((a1 t1)...(an tn))) attrtype\n"
"\nbut gets the following '"
+monDescriptionStr+"'.");
}
ListExpr monSymbol = nl->First(monDescription);
/* handle rtree type constructor */
if(!nl->IsEqual(monSymbol, "montree")){
return listutils::typeError(
"Operator windowtimeintersectsS expects a MON-Tree \n"
"as second argument.");
}
/* handle rel part of argument */
nl->WriteToString (relDescriptionStr, relDescription);
if(!IsRelDescription(relDescription)){
return listutils::typeError(
"Operator windowtimeintersectsS expects a "
"relation as its third argument, but gets '"
+ relDescriptionStr + "'.");
}
ListExpr isDouble = nl->BoolValue(nl->Fourth(monDescription));
if(!isDouble)
{
return
nl->TwoElemList(
nl->SymbolAtom(Symbol::STREAM()),
nl->TwoElemList(
nl->SymbolAtom(Tuple::BasicType()),
nl->OneElemList(
nl->TwoElemList(
nl->SymbolAtom("id"),
nl->SymbolAtom(TupleIdentifier::BasicType())))));
}
else
{
return
nl->TwoElemList(
nl->SymbolAtom(Symbol::STREAM()),
nl->TwoElemList(
nl->SymbolAtom(Tuple::BasicType()),
nl->ThreeElemList(
nl->TwoElemList(
nl->SymbolAtom("id"),
nl->SymbolAtom(TupleIdentifier::BasicType())),
nl->TwoElemList(
nl->SymbolAtom("low"),
nl->SymbolAtom(CcInt::BasicType())),
nl->TwoElemList(
nl->SymbolAtom("high"),
nl->SymbolAtom(CcInt::BasicType())))));
}
}
/*
5.1.3 Value mapping function of operator ~windowintersectsS~
*/
template<class BottomR_TreeLeafInfo>
struct MON_WindowTimeIntersectsSLocalInfo
{
Relation* relation;
MON_Tree<BottomR_TreeLeafInfo>* montree;
BBox<2> searchBox;
Interval<Instant> searchTimeInterval;
bool first;
TupleType *resultTupleType;
};
int MON_WindowTimeIntersectsS( Word* args, Word& result,
int message, Word& local,
Supplier s )
{
MON_WindowTimeIntersectsSLocalInfo<SmiRecordId> *localInfo;
switch (message)
{
case OPEN :
{
localInfo = new MON_WindowTimeIntersectsSLocalInfo<SmiRecordId>;
localInfo->montree = (MON_Tree<SmiRecordId>*)args[1].addr;
localInfo->montree->SetNetwork( (network::Network*)args[0].addr );
localInfo->relation = (Relation*)args[2].addr;
localInfo->first = true;
localInfo->searchBox = *(BBox<2>*)args[3].addr;
localInfo->searchTimeInterval =
Interval<Instant>( *(Instant*)args[4].addr,
*(Instant*)args[5].addr,
true, true );
localInfo->resultTupleType =
new TupleType(nl->Second(GetTupleResultType(s)));
assert(localInfo->montree != 0);
assert(localInfo->relation != 0);
local.setAddr(localInfo);
return 0;
}
case REQUEST :
{
localInfo = (MON_WindowTimeIntersectsSLocalInfo<SmiRecordId>*)local.addr;
R_TreeLeafEntry<2, SmiRecordId> e;
if ( !localInfo->searchBox.IsDefined() ||
!localInfo->searchTimeInterval.IsValid() )
{
return CANCEL;
}
else
{
if(localInfo->first)
{
localInfo->first = false;
if( localInfo->montree->First( localInfo->searchBox,
localInfo->searchTimeInterval,
e ) )
{
Tuple *tuple = new Tuple( localInfo->resultTupleType );
tuple->PutAttribute(0, new TupleIdentifier(true, e.info));
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
else
{
if( localInfo->montree->Next( e ) )
{
Tuple *tuple = new Tuple( localInfo->resultTupleType );
tuple->PutAttribute(0, new TupleIdentifier(true, e.info));
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
}
}
case CLOSE :
{
if(local.addr)
{
localInfo =
(MON_WindowTimeIntersectsSLocalInfo<SmiRecordId>*)local.addr;
delete localInfo;
local.setAddr(Address(0));
}
return 0;
}
}
return 0;
}
int MON_WindowTimeIntersectsSDbl( Word* args, Word& result,
int message, Word& local,
Supplier s )
{
MON_WindowTimeIntersectsSLocalInfo<BottomR_TreeLeafInfo> *localInfo;
switch (message)
{
case OPEN :
{
localInfo = new MON_WindowTimeIntersectsSLocalInfo<BottomR_TreeLeafInfo>;
localInfo->montree = (MON_Tree<BottomR_TreeLeafInfo>*)args[1].addr;
localInfo->montree->SetNetwork( (network::Network*)args[0].addr );
localInfo->relation = (Relation*)args[2].addr;
localInfo->first = true;
localInfo->searchBox = *(BBox<2>*)args[3].addr;
localInfo->searchTimeInterval =
Interval<Instant>( *(Instant*)args[4].addr,
*(Instant*)args[5].addr,
true, true );
localInfo->resultTupleType =
new TupleType(nl->Second(GetTupleResultType(s)));
assert(localInfo->montree != 0);
assert(localInfo->relation != 0);
local.setAddr(localInfo);
return 0;
}
case REQUEST :
{
localInfo =
(MON_WindowTimeIntersectsSLocalInfo<BottomR_TreeLeafInfo>*)local.addr;
R_TreeLeafEntry<2, BottomR_TreeLeafInfo> e;
if ( !localInfo->searchBox.IsDefined() ||
!localInfo->searchTimeInterval.IsValid() )
{
return CANCEL;
}
else
{
if(localInfo->first)
{
localInfo->first = false;
if( localInfo->montree->First( localInfo->searchBox,
localInfo->searchTimeInterval,
e ) )
{
Tuple *tuple = new Tuple( localInfo->resultTupleType );
tuple->PutAttribute(
0, new TupleIdentifier( true, e.info.tupleId ) );
tuple->PutAttribute( 1, new CcInt( true, e.info.low ) );
tuple->PutAttribute( 2, new CcInt( true, e.info.high ) );
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
else
{
if( localInfo->montree->Next( e ) )
{
Tuple *tuple = new Tuple( localInfo->resultTupleType );
tuple->PutAttribute(
0, new TupleIdentifier( true, e.info.tupleId ) );
tuple->PutAttribute( 1, new CcInt( true, e.info.low ) );
tuple->PutAttribute( 2, new CcInt( true, e.info.high ) );
result.setAddr(tuple);
return YIELD;
}
else
return CANCEL;
}
}
}
case CLOSE :
{
if(local.addr)
{
localInfo =
(MON_WindowTimeIntersectsSLocalInfo<BottomR_TreeLeafInfo>*)local.addr;
if(localInfo->resultTupleType){
localInfo->resultTupleType->DeleteIfAllowed();
}
delete localInfo;
local.setAddr(Address(0));
}
return 0;
}
}
return 0;
}
/*
5.1.2 Selection function of operator ~windowintersectsS~
*/
int
WindowTimeIntersectsSSelection( ListExpr args )
{
if(nl->BoolValue(nl->Fourth(nl->Second(args))))
return 1;
return 0;
}
/*
5.1.5 Specification of operator ~windowintersectsS~
*/
const string windowtimeintersectsSSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
"( <text>montree(tuple ((x1 t1)...(xn tn))"
" ti) x rel(tuple ((x1 t1)...(xn tn))) "
"x rect x instant x instant ->\n"
" (stream (tuple ((id tid))))\n</text--->"
"<text>_ _ windowintersectsS [ _, _, _ ]</text--->"
"<text>Uses the given MON-Tree to find all tuples"
" in the given relation with .xi intersects the "
" argument value's bounding box within "
" the time interval argument.</text--->"
"<text>query trainsInd trains windowintersects"
" [r, t1, t2] consume; where trainsInd "
"is e.g. created with 'let trainsInd = "
"net trains createmontree [trip]'</text--->"
") )";
/*
4.1.5 Definition of value mapping vectors
*/
ValueMapping windowtimeintersectss [] = { MON_WindowTimeIntersectsS,
MON_WindowTimeIntersectsSDbl };
/*
5.1.6 Definition of operator ~windowtimeintersectsS~
*/
Operator windowtimeintersectsS (
"windowtimeintersectsS",
windowtimeintersectsSSpec,
3,
windowtimeintersectss,
WindowTimeIntersectsSSelection,
MON_WindowTimeIntersectsSTypeMap
);
/*
6 Definition and initialization of MON-Tree Algebra
*/
class MONTreeAlgebra : public Algebra
{
public:
MONTreeAlgebra() : Algebra()
{
AddTypeConstructor( &montree );
AddOperator( &createmontree );
AddOperator( &windowtimeintersects );
AddOperator( &windowtimeintersectsS );
}
~MONTreeAlgebra() {};
};
extern "C"
Algebra*
InitializeMONTreeAlgebra( NestedList* nlRef, QueryProcessor* qpRef )
{
nl = nlRef;
qp = qpRef;
return (new MONTreeAlgebra);
}