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

1147 lines
29 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2019,
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
----
*/
#include <string>
#include "CollectionAlgebra.h"
using namespace std;
namespace collection{
/*
3.2 Implementation of class functions
*/
/*
Create a Collection of type (vector, set, multiset or undef) with typeInfo.
*/
Collection::Collection(const CollectionType type, const ListExpr typeInfo,
const int buckets /* = 10 */):
Attribute(false),
size(0), hashValue(0), collType(type),
elemFLOBDataOffset(0), elemCount(0), elemArrayIndex(0),
firstElemHashValue(0), nextElemHashValue(0),
elements(0), elementData(0)
{
#ifdef DEBUGHEAD
cout << "Collection(1)" << endl;
#endif
SetDefined(false);
GetIds(elemAlgId, elemTypeId, typeInfo);
numOfBuckets = buckets;
if(buckets < 10) {
numOfBuckets = 10;
}
for(int i=0;i<numOfBuckets;i++) {
firstElemHashValue.Append(-1);
}
}
/*
Create a Collection by copying all data from coll.
*/
Collection::Collection(const Collection& coll, const bool empty /* =false */):
Attribute(false),
elemFLOBDataOffset(0), elemCount(0), elemArrayIndex(0),
firstElemHashValue(0), nextElemHashValue(0), elements(0), elementData(0)
{
#ifdef DEBUGHEAD
cout << "Collection(2)" << endl;
#endif
size = 0;
elemAlgId = coll.elemAlgId;
elemTypeId = coll.elemTypeId;
collType = coll.collType;
if(empty) {
SetDefined(false);
hashValue = 0;
numOfBuckets = 10;
for(int i=0;i<numOfBuckets;i++) {
firstElemHashValue.Append(-1);
}
} else {
SetDefined( coll.IsDefined() );
hashValue = coll.hashValue;
numOfBuckets = coll.numOfBuckets;
elemFLOBDataOffset.copyFrom(coll.elemFLOBDataOffset);
elemCount.copyFrom(coll.elemCount);
elemArrayIndex.copyFrom(coll.elemArrayIndex);
firstElemHashValue.copyFrom(coll.firstElemHashValue);
nextElemHashValue.copyFrom(coll.nextElemHashValue);
elements.copyFrom(coll.elements);
elementData.copyFrom(coll.elementData);
}
}
/*
Create a Collection of type.
Only to be used by Create function, since we don't know algebraId and typeId
of our subtype there.
*/
Collection::Collection(CollectionType type):
Attribute(false),
elemAlgId(0), elemTypeId(0), size(0), numOfBuckets(0),
hashValue(0), collType(type), elemFLOBDataOffset(0),
elemCount(0), elemArrayIndex(0), firstElemHashValue(0),
nextElemHashValue(0), elements(0), elementData(0)
{
#ifdef DEBUGHEAD
cout << "Collection(3)" << endl;
#endif
SetDefined(false);
}
Collection::~Collection() {}
Word Collection::In(const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct) {
#ifdef DEBUGHEAD
cout << "In" << endl << " TypeInfo: " << nl->ToString(typeInfo) << endl;
#endif
Word w = SetWord(Address(0));
bool defined = true;
correct = true;
if(nl->IsAtom(typeInfo) || nl->ListLength(typeInfo)!=2) {
correct = false;
return w;
}
CollectionType collType = GetCollType(nl->First(typeInfo));
if( collType == undef ) {
correct = false;
return w;
}
if ( listutils::isSymbolUndefined(instance) ){
defined = false;
} else if( nl->IsAtom(instance) ){
correct = false;
return w;
}
Collection* coll = new Collection(collType, typeInfo,
nl->ListLength(instance));
coll->SetDefined( defined );
if(!defined){
w.addr = coll;
return w;
}
ListExpr first = nl->TheEmptyList();
ListExpr rest = instance;
ListExpr subtypeInfo = nl->Second(typeInfo);
ListExpr elemList;
int count;
correct = true;
Word elemWord;
while(!nl->IsEmpty(rest) && correct) {
first = nl->First(rest);
rest = nl->Rest(rest);
if(collType==multiset) {
if(nl->IsAtom(first) || nl->ListLength(first)!=2) {
correct = false;
} else {
elemList = nl->First(first);
count = nl->IntValue(nl->Second(first));
}
} else {
elemList = first;
count = 1;
}
if(correct) {
elemWord = (am->InObj(coll->elemAlgId, coll->elemTypeId))
(subtypeInfo, elemList, errorPos, errorInfo, correct);
}
if(correct) {
coll->Insert(static_cast<Attribute*>(elemWord.addr), count);
(static_cast<Attribute*>(elemWord.addr))->DeleteIfAllowed(true);
}
}
if(correct) {
coll->Finish();
w.addr = coll;
} else {
coll->DeleteIfAllowed(true);
}
return w;
}
/*
Out function of our collection.
Creates a ListExpr consisting of the ListExpressions returned by the
outfunctions of the elements.
*/
ListExpr Collection::Out(ListExpr typeInfo, Word value) {
#ifdef DEBUGHEAD
cout << "Out" << endl
<< " TypeInfo: " << nl->ToString(typeInfo) << endl;
#endif
Collection* coll = static_cast<Collection*>(value.addr);
if(!coll->IsDefined()) {
return nl->SymbolAtom(Symbol::UNDEFINED());
}
int size = coll->GetNoUniqueComponents();
if(size == 0) {
return nl->TheEmptyList();
}
ListExpr subtypeInfo = nl->Second(typeInfo);
Attribute* elem = coll->GetComponent(0);
ListExpr elemExpr = (am->OutObj(coll->elemAlgId, coll->elemTypeId))
(subtypeInfo, SetWord(elem));
ListExpr ret;
if(coll->GetMyCollType() == multiset) {
ret = nl->OneElemList(nl->TwoElemList(elemExpr,
nl->IntAtom(coll->GetComponentCount(0))));
} else {
ret = nl->OneElemList(elemExpr);
}
ListExpr last = ret;
for(int i=1;i<size;i++) {
elem->DeleteIfAllowed(true);
elem = coll->GetComponent(i);
elemExpr = (am->OutObj(coll->elemAlgId, coll->elemTypeId))
(subtypeInfo, SetWord(elem));
ListExpr app;
if(coll->GetMyCollType() == multiset) {
app = nl->TwoElemList(elemExpr,
nl->IntAtom(coll->GetComponentCount(i)));
} else {
app = elemExpr;
}
last = nl->Append(last, app);
}
if(elem){
elem->DeleteIfAllowed(true);
}
return ret;
}
/*
Creates an empty, undefined collection without subtype for the Query Processor.
*/
Word Collection::Create(const ListExpr typeInfo) {
#ifdef DEBUGHEAD
cout << "Create: " << nl->ToString(typeInfo) << endl;
#endif
if (nl -> IsEmpty(typeInfo))
{
#ifdef DEBUGHEAD
cout << "returning Empty Collection" << endl;
#endif
// cout << "returning Empty Collection" << endl;
return (SetWord(new Collection(undef))); // create an undefined collection
}
Word w = SetWord(Address(0));
if(nl->ListLength(typeInfo)!=2) {
cout << " Statusbericht Create: Liste != 2!" << endl;
assert(false);
return w;
}
ListExpr collTypeInfo;
if(nl->IsAtom(nl->First(typeInfo))) {
#ifdef DEBUG
cout << " Statusbericht Create: ohne Subtyp!" << endl;
#endif
collTypeInfo = typeInfo;
} else {
collTypeInfo = nl->First(typeInfo);
}
CollectionType collType = GetCollType(collTypeInfo);
if(collType==undef) {
#ifdef DEBUG
cout << " Statusbericht Create: undefiniert!" << endl;
#endif
cout << " Statusbericht Create: undefiniert!" << endl;
return w;
}
Collection* coll;
if(nl->IsAtom(nl->First(typeInfo))) {
coll = new Collection(collType);
} else {
coll = new Collection(collType, typeInfo);
}
coll->SetDefined(true);
w.addr = coll;
return w;
}
void Collection::Delete(const ListExpr typeInfo, Word& w) {
#ifdef DEBUGHEAD
cout << "Delete" << endl;
#endif
delete static_cast<Collection*>(w.addr);
w.addr = 0;
}
void Collection::Close(const ListExpr typeInfo, Word& w) {
#ifdef DEBUGHEAD
cout << "Close" << endl;
#endif
delete static_cast<Collection*>(w.addr);
w.addr = 0;
}
Word Collection::Clone(const ListExpr typeInfo , const Word& w) {
#ifdef DEBUGHEAD
cout << "Clone" << endl;
#endif
Collection* c = static_cast<Collection*>(w.addr);
return SetWord(new Collection(*c));
}
bool Collection::KindCheck(ListExpr type, ListExpr& errorInfo) {
#ifdef DEBUGHEAD
cout << "KindCheck"<< endl
<< " typeInfo: " << nl->ToString(type) << endl;
#endif
string coll;
/*
if(nl->IsAtom(type)) {
coll = nl->SymbolValue(type);
if((coll==Vector::BasicType())||(coll==Set::BasicType())||
(coll==Multiset::BasicType())) {
return true;
}
}
*/
if((nl->ListLength(type)==2) && (nl->IsAtom(nl->First(type)))) {
coll = nl->SymbolValue(nl->First(type));
if((coll==Multiset::BasicType()) || (coll==Vector::BasicType()) ||
(coll==Set::BasicType())) {
return am->CheckKind(Kind::DATA(), nl->Second(type), errorInfo);
}
}
return false;
}
int Collection::SizeOfObj() {
#ifdef DEBUGHEAD
cout << "SizeObj" << endl;
#endif
return sizeof(Collection);
}
size_t Collection::Sizeof() const {
#ifdef DEBUGHEAD
cout << "Size" << endl;
#endif
return sizeof(*this);
}
int Collection::NumOfFLOBs() const {
#ifdef DEBUGHEAD
cout << "NumOfFLOBs" << endl;
#endif
return 7;
}
Flob* Collection::GetFLOB(const int i) {
#ifdef DEBUGHEAD
cout << "GetFLOB: " << i << endl;
#endif
assert(i>=0 && i<7);
switch(i){
case 0:
return &elemFLOBDataOffset;
case 1:
return &elemCount;
case 2:
return &elemArrayIndex;
case 3:
return &firstElemHashValue;
case 4:
return &nextElemHashValue;
case 5:
return &elements;
default: //i == 6
return &elementData;
}
}
bool Collection::Open(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
#ifdef DEBUGHEAD
cout << "Open" << endl;
#endif
Collection* coll = static_cast<Collection*>(Attribute::Open(valueRecord,
offset, nl->First(typeInfo)));
value = SetWord(coll);
return true;
}
bool Collection::Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
#ifdef DEBUGHEAD
cout << "Save: " << nl->ToString(typeInfo) << endl;
#endif
Collection* coll = static_cast<Collection*>(value.addr);
Attribute::Save(valueRecord, offset, nl->First(typeInfo), coll);
return true;
}
/*NOCH ZU MACHEN:
Collection* Delete(Attribute* elem) const;
Collection* Union(Collection* coll) const;
Collection* Intersection(Collection* coll) const;
Collection* Difference(Collection* coll) const;*/
/*
Returns -1 if this is less than arg, 0 if arg = this and 1 if this is more than
arg.
*/
int Collection::Compare(const Attribute* arg) const {
#ifdef DEBUGHEAD
cout << "Compare" << endl;
#endif
Collection* collToCompare = (Collection*)arg;
assert(collType == collToCompare->collType);
if(!IsDefined() && !collToCompare->IsDefined()){
return 0;
}else if(!IsDefined()){
return -1;
}else if(!collToCompare->IsDefined()){
return 1;
}
if(collToCompare->GetNoComponents() != GetNoComponents()){
return collToCompare->GetNoComponents() > GetNoComponents()
? -1 : 1;
}else if(collToCompare->GetNoUniqueComponents() != GetNoUniqueComponents()){
return collToCompare->GetNoComponents() > GetNoComponents() ? -1 : 1;
}else{
int countCompareElem = 0;
int countOwnElem = 0;
int compareResult;
for(int eCnt = 0; eCnt < GetNoUniqueComponents(); eCnt++){
countCompareElem = collToCompare->GetComponentCount(eCnt);
countOwnElem = GetComponentCount(eCnt);
Attribute* elem1 = GetComponent(eCnt);
Attribute* elem2 = collToCompare->GetComponent(eCnt);
compareResult = elem1->Compare(elem2);
elem1->DeleteIfAllowed(true);
elem2->DeleteIfAllowed(true);
if(compareResult != 0){
return compareResult;
}
if(countCompareElem != countOwnElem){
return countCompareElem > countOwnElem ? 1 : -1;
}
}
}
return 0;
}
size_t Collection::HashValue() const {
#ifdef DEBUGHEAD
cout << "HashValue" << endl;
#endif
return hashValue;
}
void Collection::Sort() {
#ifdef DEBUGHEAD
cout << "Sort" << endl;
#endif
SortMerge(0, GetNoUniqueComponents()-1);
}
void Collection::CopyFrom(const Attribute* right) {
#ifdef DEBUGHEAD
cout << "CopyFrom" << endl;
#endif
const Collection* coll = static_cast<const Collection*>(right);
this->collType = coll->collType;
this->elemAlgId = coll->elemAlgId;
this->elemTypeId = coll->elemTypeId;
this->SetDefined( coll->IsDefined() );
if( !coll->IsDefined() ){
this->Clear();
} else {
this->size = coll->size;
this->numOfBuckets = coll->numOfBuckets;
this->hashValue = coll->hashValue;
this->elemFLOBDataOffset.copyFrom(coll->elemFLOBDataOffset);
this->elemCount.copyFrom(coll->elemCount);
this->elemArrayIndex.copyFrom(coll->elemArrayIndex);
this->firstElemHashValue.copyFrom(coll->firstElemHashValue);
this->nextElemHashValue.copyFrom(coll->nextElemHashValue);
this->elements.copyFrom(coll->elements);
this->elementData.copyFrom(coll->elementData);
}
}
bool Collection::Adjacent(const Attribute* arg) const {
#ifdef DEBUGHEAD
cout << "Adjacent" << endl;
#endif
return false;
}
Collection* Collection::Clone() const {
#ifdef DEBUGHEAD
cout << "Clone" << endl;
#endif
return new Collection(*this);
}
void Collection::Finish() {
#ifdef DEBUGHEAD
cout << "Finish" << endl;
#endif
SetDefined(true);
if(collType != vector) {
Sort();
}
}
ostream& Collection::Print( ostream& os ) const {
#ifdef DEBUGHEAD
cout << "Print" << endl;
#endif
os << "Collection: ";
switch(collType){
case vector:
os << Vector::BasicType();
break;
case set:
os << Set::BasicType();
break;
case multiset:
os << Multiset::BasicType();
break;
case undef:
os << "undef";
break;
default:
os << "ERROR" << endl;
return (os);
}
os << "(" << elemAlgId << "," << elemTypeId << "): ";
os << "\t" << (IsDefined() ? "defined." : "UNDEFINED." ) << endl;
os << "Number of contained Elements: " << GetNoComponents() << " ("
<< GetNoUniqueComponents() << " unique)." << endl;
os << "--- Elements: begin ---" << endl;
Attribute* elem;
int times;
for(int i=0; i<GetNoUniqueComponents(); i++){
elem = GetComponent(i);
os << i << ":\t";
elem->Print(os);
if(collType == multiset){
times = GetComponentCount(i);
os << "(contained " << times << " times).";
}
os << endl;
elem->DeleteIfAllowed(true);
}
os << "--- Elements: end ---" << endl;
#ifdef DEBUG
os << "\tContains size = " << size << " elements." << endl;
os << "\tUses numOfBuckets = " << numOfBuckets << " buckets." << endl;
os << "\thashValue = " << hashValue << endl;
os << "\t\telemCount.Size() = " << elemCount.Size() << endl;
os << "\t\telemArrayIndex.Size() = " << elemArrayIndex.Size() << endl;
os << "\t\tfirstElemHashValue.Size() = " << firstElemHashValue.Size()<<endl;
os << "\t\tnextElemHashValue.Size() = " << nextElemHashValue.Size() << endl;
os << "\t\telemFLOBDataOffset.Size() = " <<elemFLOBDataOffset.Size()<< endl;
os << "\t\telements.getSize() = " << elements.getSize() << endl;
os << "\t\telementData.getSize() = " << elementData.getSize() << endl;
#endif
return (os);
}
void* Collection::Cast(void* addr) {
#ifdef DEBUGHEAD
//cout << "Cast" << endl;
#endif
return (new (addr) Collection);
}
void Collection::Insert(Attribute* elem, const int count) {
#ifdef DEBUGHEAD
cout << "Insert" << endl;
#endif
int index = GetIndex(elem);
if(index > -1) {
if(collType==vector) {
for(int i=0;i<count;i++) {
elemArrayIndex.Append(index);
}
AddHashValue((static_cast<Attribute*>(elem))->HashValue(),count);
} else if (collType==multiset) {
int cnt;
elemCount.Get(index, &cnt);
elemCount.Put(index, (cnt+count));
size += count;
AddHashValue((static_cast<Attribute*>(elem))->HashValue(),
count);
}
//there's nothing to do if we've got a set since in a set
//every element only appears once.
return;
}
SaveComponent(elem, count);
}
CollectionType Collection::GetMyCollType() const {
#ifdef DEBUGHEAD
cout << "GetMyCollType" << endl;
#endif
return collType;
}
int Collection::Contains(const Attribute* elem) const {
#ifdef DEBUGHEAD
cout << "Contains" << endl;
#endif
int index = GetIndex(elem);
if(index > -1) {
if(collType == multiset) {
int count;
elemCount.Get(index, &count);
return count;
} else {
return 1;
}
}
return 0;
}
Attribute* Collection::GetComponent(int pos) const {
#ifdef DEBUGHEAD
cout << "GetComponent" << endl;
#endif
assert(0<=pos);
assert(pos<elemArrayIndex.Size());
int index;
elemArrayIndex.Get(pos, &index);
return RestoreComponent(index);
}
int Collection::GetComponentCount(const int pos) const {
#ifdef DEBUGHEAD
cout << "GetComponentCount" << endl;
#endif
assert(0<=pos);
assert(pos<elemArrayIndex.Size());
if(collType!=multiset) {
return 1;
}
int index;
elemArrayIndex.Get(pos, &index);
int count;
elemCount.Get(index, &count);
return count;
}
int Collection::GetNoComponents() const {
#ifdef DEBUGHEAD
cout << "GetNo" << endl;
#endif
if(collType == undef) {
return 0;
}
if(collType==multiset) {
return size;
}
return elemArrayIndex.Size();
}
int Collection::GetNoUniqueComponents() const {
//needed for iterations with GetComponent(i) since for a multiset
//GetNoComponents returns the number of all components, including
//duplicates, but GetComponent doesn't regard duplicates.
#ifdef DEBUGHEAD
cout << "GetNoUnique" << endl;
#endif
if(collType==undef) {
return 0;
}
return elemArrayIndex.Size();
}
Collection* Collection::Union(const Collection* coll) const {
#ifdef DEBUGHEAD
cout << "Union" << endl;
#endif
return new Collection();
}
Collection* Collection::Intersection(const Collection* coll) const {
#ifdef DEBUGHEAD
cout << "Intersection" << endl;
#endif
return new Collection();
}
Collection* Collection::Difference(const Collection* coll) const {
#ifdef DEBUGHEAD
cout << "Difference" << endl;
#endif
return new Collection();
}
Collection* Collection::Delete(const Attribute* elem) const {
#ifdef DEBUGHEAD
cout << "Delete" << endl;
#endif
return new Collection();
}
void Collection::GetIds(int& algebraId, int& typeId,
const ListExpr typeInfo) {
#ifdef DEBUGHEAD
cout << "GetIds" << endl;
cout << " " << nl->ToString(typeInfo) << endl;
#endif
if(nl->IsAtom(typeInfo) || nl->ListLength(typeInfo)!=2) {
return;
}
ListExpr subtypeInfo = nl->Second(typeInfo);
if(nl->IsAtom(subtypeInfo)) {
return;
}
ListExpr b1 = nl->First(subtypeInfo);
if(nl->IsAtom(b1)) {
//subtypeInfo = type = (algId ...)
if (nl->ListLength(subtypeInfo)!=2) {
return;
}
//list = (algid typeid)
algebraId = nl->IntValue(nl->First(subtypeInfo));
typeId = nl->IntValue(nl->Second(subtypeInfo));
} else {
//subtypeInfo = (type1 type2).
//We only need type1 since a collection can only be of one type.
//type1 is b1 (nl->First(subtypeInfo)), so b1 is (algId typeId).
if (nl->ListLength(b1)!=2) {
return;
}
//b1 = (algId typeId)
algebraId = nl->IntValue(nl->First(b1));
typeId = nl->IntValue(nl->Second(b1));
}
}
void Collection::SortMerge(const int start, const int end) {
#ifdef DEBUGHEAD
cout << "SortMerge" << endl;
#endif
if(start>=end) {
return;
}
if(collType==vector) {
return;
}
int middle = (start+end-1)/2;
SortMerge(start, middle);
SortMerge(middle+1, end);
int pointer1 = start;
int pointer2 = middle+1;
int* help = new int[((end-start)+1)];
int index;
int pointer3 = 0;
Attribute* elem1 = GetComponent(pointer1);
Attribute* elem2 = GetComponent(pointer2);
bool finished = false;
while(!finished) {
int compare = elem1->Compare(elem2);
if(compare>0) {
elemArrayIndex.Get(pointer2, &index);
pointer2++;
if(pointer2<=end) {
elem2->DeleteIfAllowed(true);
elem2 = GetComponent(pointer2);
} else {
finished = true;
}
} else {
elemArrayIndex.Get(pointer1, &index);
pointer1++;
if(pointer1<=middle) {
elem1->DeleteIfAllowed(true);
elem1 = GetComponent(pointer1);
} else {
finished = true;
}
}
help[pointer3] = index;
pointer3++;
}
while(pointer1 <= middle) {
elemArrayIndex.Get(pointer1, &index);
help[pointer3] = index;
pointer1++;
pointer3++;
}
while(pointer2 <= end) {
elemArrayIndex.Get(pointer2, &index);
help[pointer3] = index;
pointer2++;
pointer3++;
}
pointer3 = 0;
pointer1 = start;
while(pointer1 <= end) {
elemArrayIndex.Put(pointer1, help[pointer3]);
pointer1++;
pointer3++;
}
delete[] help;
if(elem1){
elem1->DeleteIfAllowed(true);
}
if(elem2){
elem2->DeleteIfAllowed(true);
}
}
CollectionType Collection::GetCollType(const ListExpr collTypeInfo) {
#ifdef DEBUGHEAD
cout << "GetCollType" << endl;
#endif
if(nl->ListLength(collTypeInfo) != 2) {
return undef;
}
if(!nl->IsAtom(nl->First(collTypeInfo))
|| !(nl->AtomType(nl->First(collTypeInfo)) == IntType)
|| !nl->IsAtom(nl->Second(collTypeInfo))
|| !(nl->AtomType(nl->Second(collTypeInfo)) == IntType)) {
return undef;
}
int algId = nl->IntValue(nl->First(collTypeInfo));
int typeId = nl->IntValue(nl->Second(collTypeInfo));
string collType = am->GetTC(algId, typeId)->Name();
if(collType==Vector::BasicType()) {
return vector;
} else if(collType==Set::BasicType()) {
return set;
} else if(collType==Multiset::BasicType()) {
return multiset;
}
return undef;
}
void Collection::SaveComponent(Attribute* elem, const int count) {
#ifdef DEBUGHEAD
cout << "SaveComponent" << endl;
#endif
// step1 backup original flob data from elem into
std::vector<Flob> origFlobs;
for(int i=0;i<elem->NumOfFLOBs();i++){
Flob* tmpFlob = elem->GetFLOB(i);
origFlobs.push_back(*tmpFlob);
}
SmiFileId fid = elementData.getFileId();
SmiRecordId rid = elementData.getRecordId();
char mode = elementData.getMode();
// save FLOBs
size_t offset = elementData.getSize();
size_t index = elemFLOBDataOffset.Size();
elemFLOBDataOffset.Append(offset);
for(int i=0;i<elem->NumOfFLOBs();i++) {
Flob* tempFLOB = elem->GetFLOB(i);
size = tempFLOB->getSize();
elementData.resize(offset+size);
char data[size];
tempFLOB->read(data, size, 0);
elementData.write(data, size, offset);
offset += size;
// change flob in Elem
Flob changedFlob = Flob::createFrom(fid,rid,offset, mode, size);
*elem->GetFLOB(i) = changedFlob;
}
// store elements
size_t size = (size_t)(am->SizeOfObj(elemAlgId, elemTypeId))();
offset = index*size;
if(elements.getSize()<(offset+size)) {
if(elements.getSize()<(8*size)) {
elements.resize(8*size);
} else {
elements.resize(elements.getSize()*2);
}
}
elements.write( (char*)(elem), size, offset );
// restore flob
for(int i=0;i<elem->NumOfFLOBs();i++){
*elem->GetFLOB(i) = origFlobs[i];
}
if(collType == multiset) {
assert((size_t)elemCount.Size()==index);
elemCount.Append(count);
this->size += count;
}
elemArrayIndex.Append(index);
if(collType == vector && count>1) {
for(int i=0;i<(count-1);i++) {
elemArrayIndex.Append(index);
}
}
if(collType==set) {
AddHashValue((static_cast<Attribute*>(elem))->HashValue(), 1);
} else {
AddHashValue((static_cast<Attribute*>(elem))->HashValue(), count);
}
InsertIndex(elem, index);
}
Attribute* Collection::RestoreComponent(const int pos) const {
#ifdef DEBUGHEAD
cout << "RestoreComponent" << endl;
#endif
assert(pos>=0);
assert(pos<elemFLOBDataOffset.Size());
ListExpr typeInfo = nl->TwoElemList(nl->IntAtom(elemAlgId),
nl->IntAtom(elemTypeId));
Attribute* elem = static_cast<Attribute*>
((am->CreateObj(elemAlgId, elemTypeId))(typeInfo).addr);
/*
size_t n1 = elem->Sizeof();
size_t n2 = am->SizeOfObj(elemAlgId, elemTypeId)();
cout << "n1 = " << n1 << " n2 =" << n2 << endl;
assert( n1 == n2);
*/
std::vector<Flob> ff; /* freshflobs */
for(int i=0;i<elem->NumOfFLOBs();i++) {
ff.push_back( *elem->GetFLOB(i) );
}
size_t offset = (size_t)(pos*(am->SizeOfObj(elemAlgId, elemTypeId))());
elements.read((char*)(elem), elem->Sizeof(), offset);
elem = static_cast<Attribute*>((am->Cast(elemAlgId, elemTypeId))(elem));
for(int i=0;i<elem->NumOfFLOBs();i++) {
SmiSize fs = elem->GetFLOB(i)->getSize();
*elem->GetFLOB(i) = ff[i];
elem->GetFLOB(i)->resize(fs);
}
size_t temp = 0;
elemFLOBDataOffset.Get(pos, &temp);
offset = temp;
for(int i=0;i<elem->NumOfFLOBs();i++) {
Flob* tempFLOB = elem->GetFLOB(i);
size_t size = tempFLOB->getSize();
//#define X1_DEBUG
#ifdef X1_DEBUG
cout << " offset: " << offset << endl;
cout << " size(" << i << "): " << size << endl;
#endif
char tempData[size];
elementData.read(tempData, size, offset);
tempFLOB->write(tempData, size, 0);
offset += size;
}
return elem;
}
int Collection::GetIndex(const Attribute* elem) const {
#ifdef DEBUGHEAD
cout << "GetIndex" << endl;
#endif
size_t tmp = (static_cast<const Attribute*>(elem))->HashValue();
int hashsum = (int) tmp;
hashsum = hashsum % numOfBuckets;
if(hashsum<0) {
hashsum += numOfBuckets;
}
int index = -1;
firstElemHashValue.Get(hashsum, &index);
#ifdef DEBUG
cout << " Statusbericht GetIndex-Funktion:" << endl
<< " Hashsum: " << hashsum << endl
<< " Index: " << index << endl;
#endif
while(index>-1) {
Attribute* elem2 = RestoreComponent(index);
int comp = elem->Compare(elem2);
elem2->DeleteIfAllowed(true);
if(comp==0) {
return index;
}
nextElemHashValue.Get(index, &index);
#ifdef DEBUG
cout << " Statusbericht GetIndex-Funktion:" << endl
<< " Index: " << index << endl;
#endif
}
return -1;
}
void Collection::InsertIndex(const Attribute* elem, const int index) {
#ifdef DEBUGHEAD
cout << "InsertIndex" << endl;
#endif
assert(nextElemHashValue.Size()==index);
//nextElemHashValue(index) must not exist!
int hashsum = (static_cast<const Attribute*>(elem))->HashValue();
hashsum = hashsum % numOfBuckets;
if(hashsum<0) {
hashsum += numOfBuckets;
}
int index2 = -1;
firstElemHashValue.Get(hashsum, &index2);
#ifdef DEBUG
cout << " Statusbericht InsertIndex-Funktion" << endl
<< " Hashsum: " << hashsum << endl
<< " Index: " << index2 << endl;
#endif
if(index2<0) {
firstElemHashValue.Put(hashsum, index);
} else {
int indexOld(0);
while(index2>-1) {
#ifdef DEBUG
cout << " Statusbericht InsertIndex-Funktion" << endl
<< " Index: " << index2 << endl;
#endif
indexOld = index2;
nextElemHashValue.Get(indexOld, &index2);
}
nextElemHashValue.Put(indexOld, index);
}
nextElemHashValue.Put(index, -1);
}
void Collection::AddHashValue(const int value, const int count) {
hashValue += count*value;
}
void Collection::Clear() {
elemFLOBDataOffset.clean();
elemCount.clean();
elemArrayIndex.clean();
firstElemHashValue.clean();
nextElemHashValue.clean();
elements.clean();
elementData.clean();
size = 0;
hashValue = 0;
numOfBuckets = 10;
firstElemHashValue.resize(numOfBuckets);
for(int i=0;i<numOfBuckets;i++) {
firstElemHashValue.Append(-1);
}
}
}