Files
secondo/Algebras/Temporal2/MPoint2.cpp

613 lines
16 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
implementation of MPoint2
*/
#include "MPoint2.h"
#include "SecondoSMI.h"
#include "MovingCalculations.h"
#include "MemStorageManager.h"
#include "GenericTC.h"
#include "TemporalAlgebraFunctions.h"
namespace temporal2algebra {
using temporalalgebra::UPoint;
using temporalalgebra::IPoint;
TypeConstructor* getMPoint2TypePtr() {
TypeConstructor* type = new GenTC<MPoint2>;
type->AssociateKind( Kind::TEMPORAL() );
type->AssociateKind( Kind::DATA() );
return type;
}
bool CheckMPoint2( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, MPoint2::BasicType() ));
}
ListExpr MPoint2Property() {
return (nl->TwoElemList(
nl->FourElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List")),
nl->FourElemList(nl->StringAtom("-> MAPPING"),
nl->StringAtom("(mpoint2) "),
nl->StringAtom("( u1 ... un ) "),
nl->StringAtom("(((i1 i2 TRUE FALSE)"
" (1.0 2.2 2.5 2.1)) ...)"))));
}
void MPoint2::memClear() {
cout << "MPoint2::memClear["<< id << "]()\n";
if (hasMemoryUnits()) {
MemStorageManager* storage = MemStorageManager::getInstance();
storage->clear(id);
id = 0;
} else {
//TODO: only allow memClear if we have memUnits???
cout << "no MemoryUnits present\n";
//assert(false);
}
}
// required in OpAppendPositions to explicitly write to sharedMem:
// if data is pushed to mem, no commit on the containing tuple and relation
// is required.
void MPoint2::memAppend(const temporalalgebra::UPoint& upoint) {
cout << "MPoint2::memAppend[" << id << "](" << upoint << ")\n";
assert(hasMemoryUnits());
MemStorageManager* storage = MemStorageManager::getInstance();
storage->append(id, upoint);
}
void MPoint2::SetBackReference(const BackReference& backReference) {
assert(!hasMemoryUnits());
MemStorageManager* storage = MemStorageManager::getInstance();
assert(id==0);
id = storage->createId();
int indexLastUnit = units2.Size() -1;
Unit finalUnit(0);
if (indexLastUnit >= 0)
units2.Get(indexLastUnit, finalUnit);
else
finalUnit = Unit(0);
storage->setBackRef(id, backReference, finalUnit);
}
bool MPoint2::hasMemoryUnits() const {
return id > 0;
}
/*static*/ bool MPoint2::hasMemoryUnits(const BackReference& backRef) {
return findMemStorageId(backRef) > 0;
}
/*static*/ MemStorageId MPoint2::findMemStorageId(const BackReference& backRef) {
MemStorageManager* storage = MemStorageManager::getInstance();
MemStorageId my_id = storage->getId(backRef);
cout << " MPoint2::findMemStorageId(" << backRef << "): "
<<my_id << endl;
return my_id;
}
/*static*/ Unit MPoint2::getFinalUnit(const MemStorageId& id) {
MemStorageManager* storage = MemStorageManager::getInstance();
Unit finalUnit = storage->getFinalUnit(id);
cout << "MPoint2::getFinalUnit(id: " << id << "): "
<< finalUnit << endl;
return finalUnit;
}
/*static*/ void MPoint2::appendUnit(const MemStorageId& id, const Unit& unit){
MemStorageManager* storage = MemStorageManager::getInstance();
cout << "MPoint2::appendUnit(id: " << id
<< ", unit: " << unit << ")" << endl;
storage->append(id, unit);
}
const MemStorageId MPoint2::getMemId() const {
return id;
}
void MPoint2::setMemId(const MemStorageId new_id) {
id = new_id;
}
/*virtual*/ void MPoint2::Initialize( SmiFileId fileId,
TupleId tupleId,
int attrno) {
cout << *this << "::Initialize("
<< "fileId:" << fileId
<< ", tupleId: " << tupleId
<< ", attrno: " << attrno
<< ")\n";
}
/*virtual*/ void MPoint2::Finalize() {
cout << *this << "::Finalize()\n";
}
std::ostream& MPoint2::Print(std::ostream &os) const {
os << "[mpoint2 id: " << id << ", del.refs: " << del.refs
<< ", this: " << this
<< "]";
return os;
}
MPoint2::MPoint2() {
cout << "MPoint2(): " << *this << endl;
} // should do nothing
MPoint2::MPoint2( const MPoint2& rhs ) :
Attribute(rhs.IsDefined()),
id(0),
units2(0),
bbox2(rhs.bbox2.IsDefined())
{
if (!rhs.IsDefined()) {
cout << "Undefined\n";
return;
}
cout << "MPoint2( "<< rhs << " )\n";
//optimized Flob-Copy for persistent data
// TODO: check if resizing to total size makes sense
units2.copyFrom(rhs.units2);
//Add Memory Units:
if (rhs.hasMemoryUnits()) {
size_t firstMemIndex = rhs.units2.Size();
size_t numComps = (size_t)rhs.GetNoComponents();
for (size_t i = firstMemIndex; i < numComps; ++i) {
UPoint unit;
rhs.Get(i, unit);
units2.Append(unit);
}
}
bbox2 = rhs.GetBBox();
cout << "MPoint2("<< rhs << "): " << *this << endl;
}
/*explicit*/ MPoint2::MPoint2(const bool defined):
Attribute(defined),
id(0),
units2(0),
bbox2(false)
{
cout << "MPoint2(defined: " << defined << "): " << *this << endl;
// Do not allocate ID/Mem slot if no units2 are present:
// - work around issue that first MPoint2 is created without open DB
// - save some resources
// - not all instances allow for backreferences (eg. temp objects)
}
/*explicit*/ MPoint2::MPoint2(const int dummy):
Attribute(true),
id(0),
units2(0),
bbox2(false)
{
cout << "MPoint2(dummy: " << dummy << "): " << *this << endl;
}
MPoint2::~MPoint2() {
cout << "~MPoint2(): " << *this << endl;
}
MPoint2& MPoint2::operator=(const MPoint2& rhs){
cout << *this << ".operator= (" << rhs << ")\n";
if (&rhs == this) {
return *this;
}
Clear();
if( !rhs.IsDefined() ){
SetDefined(false);
return *this;
}
SetDefined(true);
//optimized Flob-Copy for persistent data
units2.copyFrom(rhs.units2);
//Add Memory Units:
if (rhs.hasMemoryUnits()) {
size_t firstMemIndex = rhs.units2.Size();
size_t numComps = (size_t)rhs.GetNoComponents();
for (size_t i = firstMemIndex; i < numComps; ++i) {
UPoint unit;
rhs.Get(i, unit);
units2.Append(unit);
}
}
bbox2 = rhs.GetBBox();
cout << "operator=(): " << *this << endl;
return *this;
}
ListExpr MPoint2::ToListExpr(const ListExpr& typeInfo) const{
cout << "MPoint2::ToListExpr[" << id << "]( .. )\n";
cout << "IsDefined()=" << IsDefined() << endl;
temporalalgebra::MPoint* mpoint = new temporalalgebra::MPoint(0);
if (IsDefined()) {
mpoint->Clear();
mpoint->SetDefined(true);
mpoint->StartBulkLoad();
size_t numComps = (size_t)GetNoComponents();
for (size_t i = 0; i < numComps; ++i) {
UPoint unit;
Get(i, unit);
mpoint->Add(unit);
}
mpoint->EndBulkLoad(false);
mpoint->SetDefined(true);
cout << *mpoint << endl;
} else {
mpoint->SetDefined(false);
}
ListExpr res = temporalalgebra::OutMapping<
temporalalgebra::MPoint,
temporalalgebra::UPoint,
temporalalgebra::OutUPoint>
( typeInfo, SetWord( mpoint ) );
mpoint->DeleteIfAllowed();
return res;
}
bool MPoint2::ReadFrom(const ListExpr LE, const ListExpr& typeInfo) {
cout << "MPoint2::ReadFrom[" << id << "]( "
+ nl->ToString(LE) + ", .. )\n";
Clear();
if (listutils::isSymbolUndefined(LE)) {
SetDefined(false);
return true;
}
bool mp_correct = false;
ListExpr errorInfo;
Word mp_ptr = temporalalgebra::InMapping
<temporalalgebra::MPoint,
temporalalgebra::UPoint,
temporalalgebra::InUPoint>(
typeInfo, LE, 0, errorInfo, mp_correct
);
if (!mp_correct) return false;
temporalalgebra::MPoint* mpoint =
static_cast<temporalalgebra::MPoint*> (mp_ptr.addr);
cout << "MPoint2::ReadFrom( .. )" << *mpoint << endl;
if (mpoint->IsDefined()) {
temporalalgebra::UPoint unit(false);
int noOfComponents = mpoint->GetNoComponents();
for ( int i = 0; i < noOfComponents; i++) {
mpoint->Get(i, unit);
units2.Append(unit);
}
bbox2 = mpoint->BoundingBox();
SetDefined(true);
} else {
SetDefined(false);
}
mpoint->DeleteIfAllowed();
cout << "IsDefined()=" << IsDefined() << endl;
return true;
}
std::string MPoint2::toString() const{
std::stringstream ss;
ss << id;
return ss.str();
}
int MPoint2::Compare(const Attribute* rhs1) const{
if(!IsDefined()){
if(!rhs1->IsDefined()){
return 0;
} else {
return -1;
}
}
if(!rhs1->IsDefined()){
return 1;
}
const MPoint2* rhs = static_cast<const MPoint2*>(rhs1);
if(id < rhs->id){
return -1;
} else if(id > rhs->id){
return 1;
}
//TODO: FIX comparison - we no longer always have an Id
return 0;
}
bool MPoint2::Adjacent(const Attribute* rhs) const{
return false;
}
size_t MPoint2::HashValue() const{
//TODO: FIX HashValue - we no longer always have an Id
return id;
}
void MPoint2::CopyFrom(const Attribute* attr) {
cout << *this << "::CopyFrom("
<< *(static_cast<const MPoint2*>(attr)) << ")\n";
operator=( *((MPoint2*) attr));
cout << *this << "::CopyFrom("
<< *(static_cast<const MPoint2*>(attr)) << ")\n";
}
MPoint2* MPoint2::Clone() const{
cout << *this << "::Clone()\n";
MPoint2* res = new MPoint2(*this);
cout << *this << "::Clone(): " << *res << endl;
return res;
}
size_t MPoint2::Sizeof() const {
return sizeof(*this);
}
/*static*/ const std::string MPoint2::BasicType(){
return "mpoint2";
}
/*static*/ const bool MPoint2::checkType(const ListExpr type){
return listutils::isSymbol(type, BasicType());
}
/*static*/ ListExpr MPoint2::Property(){
return gentc::GenProperty("-> MAPPING",
BasicType(),
"( u1 ... un )",
"(((i1 i2 TRUE FALSE) (1.0 2.2 2.5 2.1)) ...)");
}
/*static*/ bool MPoint2::CheckKind(ListExpr type, ListExpr& errorInfo){
return nl->IsEqual(type,BasicType());
}
// NumOfFLOBs
// this class has one FLOB in form of a DbArray
inline /*virtual*/ int MPoint2::NumOfFLOBs () const {
return 1;
}
// return the flob if index is correct
inline /*virtual*/ Flob* MPoint2::GetFLOB ( const int i ) {
assert ( i == 0);
return &units2;
}
// Functions added to replace direct member access from TemporalAlgebra
Rectangle<3> MPoint2::GetBBox() const {
Rectangle<3> res(bbox2);
cout << "GetBBox()\n";
if (hasMemoryUnits()) { // currently this implies #units2 > 0
MemStorageManager* storage = MemStorageManager::getInstance();
int storageSize = storage->Size(id);
for (int pos = 0;
pos < storageSize;
++pos) {
Rectangle<3> unitBBox = storage->Get(id, pos).BoundingBox();
cout << "before: res=" << res << endl;
cout << "adding: bbx=" << unitBBox << endl;
if (!bbox2.IsDefined()) {
res = unitBBox;
} else {
res.Extend(unitBBox);
}
cout << "after: res=" << res << endl << endl;
}
}
return res;
}
// Functions copied and adapted from temporalalgebra::MPoint
void MPoint2::Get( const int i, Unit &unit ) const
{
assert( IsDefined() );
assert(i >= 0);
assert(i < GetNoComponents());
int flobSize = units2.Size();
if ( i >= flobSize) {
assert(hasMemoryUnits());
// requested unit is in memory
int memPos = i - flobSize;
MemStorageManager* storage = MemStorageManager::getInstance();
unit = storage->Get(id, memPos);
} else {
bool ok = units2.Get( i, unit );
if(!ok){
cout << "Problem in getting data from " << units2 << std::endl;
assert(ok);
}
}
if ( !unit.IsValid() )
{
cout << __FILE__ << "," << __LINE__ << ":"
<< __PRETTY_FUNCTION__
<< " Get(" << i << ", Unit): Unit is invalid:";
unit.Print(cout); cout << std::endl;
assert( unit.IsValid());
}
}
int MPoint2::GetNoComponents() const
{
assert( IsDefined() );
int res = units2.Size();
if (hasMemoryUnits()) {
MemStorageManager* storage = MemStorageManager::getInstance();
res += storage->Size(id);
}
return res;
}
bool MPoint2::IsEmpty() const
{
return !IsDefined() || (GetNoComponents() == 0);
}
void MPoint2::Clear()
{
ordered = true;
units2.clean();
memClear();
del.isDefined = true;
}
void MPoint2::StartBulkLoad() //TODO
{
assert( IsDefined() );
assert( ordered );
ordered = false;
}
void MPoint2::Add( const UPoint& unit ) //TODO only during BulkLoad??
{
assert( unit.IsDefined() );
assert( unit.IsValid() );
if(!IsDefined() || !unit.IsDefined()){
SetDefined( false );
memClear();
return;
}
if (hasMemoryUnits()) {
MemStorageManager* storage = MemStorageManager::getInstance();
storage->append(id, unit);
} else {
units2.Append(unit);
if (bbox2.IsDefined()) {
bbox2.Extend(unit.BoundingBox());
} else {
bbox2 = unit.BoundingBox();
}
}
RestoreBoundingBox(false); // TODO needed? should be class invariant
}
bool MPoint2::EndBulkLoad(const bool sort, const bool checkvalid) //TODO
{
bool res = true;
//start: from Mapping::EndBulkLoad
assert( !ordered ); // check for active bulk load
if( !IsDefined() ){
units2.clean();
memClear();
} else if( sort ){
cout << "not fully impelemented yet\n";
// assert(false);
units2.Sort( temporalalgebra::UnitCompare<UPoint> );
//memSort(UnitCompare<Unit>) //TODO
}
ordered = true;
units2.TrimToSize();
if( checkvalid && !IsValid(*this) ){
units2.clean();
memClear();
SetDefined( false );
res = false;
}
//end: from Mapping::EndbulkLoad
if(res){
RestoreBoundingBox();
}
return res;
}
void MPoint2::RestoreBoundingBox(const bool force /*=false*/) // TODO
{
if(!IsDefined() || units2.Size() == 0)
{ // invalidate bbox
bbox2.SetDefined(false);
}
else if(force || !bbox2.IsDefined())
{ // construct bbox
UPoint unit;
int size = units2.Size(); //TODO: bbox in Attribute: only for pers. data
Get( 0, unit ); // safe, since (this) contains at least 1 unit
bbox2 = unit.BoundingBox();
for( int i = 1; i < size; i++ ){
Get( i, unit );
bbox2 = bbox2.Union(unit.BoundingBox());
}
} // else: bbox unchanged and still correct
}
void MPoint2::Resize(size_t n){
// TODO: how to Handle invariant?!
// shrinkToFit may be better??
// or only reduce size if the existing units fit?
if (n < (size_t)GetNoComponents()) {
cout << "cannot Resize() to " << n
<< ", as requested size is smaller than current size "
<< GetNoComponents() << endl;
assert(false);
return;
}
if (n == 0) {
Clear();
return;
}
if (hasMemoryUnits())
{
// memUnits don't need to be resized
return;
}
units2.resize(n);
}
bool MPoint2::IsOrdered() const {
return true; //TODO: fix this...
//return ordered;
}
} /* temporal2algebra */