/* 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; 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 << "): " <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 ( typeInfo, LE, 0, errorInfo, mp_correct ); if (!mp_correct) return false; temporalalgebra::MPoint* mpoint = static_cast (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(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(attr)) << ")\n"; operator=( *((MPoint2*) attr)); cout << *this << "::CopyFrom(" << *(static_cast(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 ); //memSort(UnitCompare) //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 */