/* ---- This file is part of SECONDO. Copyright (C) 2015, 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 #include #include #include "DArray.h" #include "Dist2Helper.h" #include #include #include using namespace std; namespace distributed2{ /* 1.1 Implementation of Class ~DArrayElement~ This class represents information about a single worker of a DArray. */ DArrayElement::DArrayElement(const string& _server, const int _port, const int _num, const string& _config): server(_server), port(_port), num(_num),config(_config) {} DArrayElement::DArrayElement(const DArrayElement& src): server(src.server), port(src.port), num(src.num), config(src.config) {} DArrayElement& DArrayElement::operator=(const DArrayElement& src){ this->server = src.server; this->port = src.port; this->num = src.num; this->config = src.config; return *this; } DArrayElement::~DArrayElement() {} void DArrayElement::set(const string& server, const int port, const int num, const string& config){ this->server = server; this->port = port; this->num = num; this->config = config; } bool DArrayElement::operator==(const DArrayElement& other) const{ return (this->port == other.port) && (this->num == other.num) && (this->server == other.server) && (this->config == other.config); } bool DArrayElement::operator<(const DArrayElement& other) const { if(this->port < other.port) return true; if(this->port > other.port) return false; if(this->num < other.num) return true; if(this->num > other.num) return false; if(this->server < other.server) return true; if(this->server > other.server) return false; if(this->config < other.config) return true; // equal or greater return false; } bool DArrayElement::operator>(const DArrayElement& other) const { if(this->port > other.port) return true; if(this->port < other.port) return false; if(this->num > other.num) return true; if(this->num < other.num) return false; if(this->server > other.server) return true; if(this->server < other.server) return false; if(this->config > other.config) return true; // equal or greater return false; } ListExpr DArrayElement::toListExpr() const{ return nl->ThreeElemList( nl->TextAtom(server), nl->IntAtom(port), nl->TextAtom(config)); } bool DArrayElement::readFrom(SmiRecord& valueRecord, size_t& offset){ string s; if(!readVar(s,valueRecord,offset)){ return false; } uint32_t p; if(!readVar(p,valueRecord,offset)){ return false; } string c; if(!readVar(c,valueRecord,offset)){ return false; } server = s; port = p; num = -1; config = c; return true; } bool DArrayElement::saveTo(SmiRecord& valueRecord, size_t& offset) const{ if(!writeVar(server,valueRecord,offset)){ return false; } if(!writeVar(port,valueRecord,offset)){ return false; } if(!writeVar(config,valueRecord,offset)){ return false; } return true; } void DArrayElement::print(ostream& out)const{ out << "( S: " << server << ", P : " << port << "Num : " << num << ", C : " << config << ")"; } bool InDArrayElement(ListExpr list, DArrayElement& result){ if(!nl->HasLength(list,3)){ return false; } ListExpr e1 = nl->First(list); ListExpr e2 = nl->Second(list); ListExpr e4 = nl->Third(list); string server; int port; int num; string config; if(nl->AtomType(e1) == StringType){ server = nl->StringValue(e1); } else if(nl->AtomType(e1) == TextType){ server = nl->Text2String(e1); } else { return false; } stringutils::trim(server); if(server.empty()){ return false; } if(nl->AtomType(e2) != IntType){ return false; } port = nl->IntValue(e2); if(port <=0){ return false; } if(nl->AtomType(e4) == StringType){ config = nl->StringValue(e4); } else if(nl->AtomType(e4) == TextType){ config = nl->Text2String(e4); } else { return false; } stringutils::trim(config); if(config.empty()){ return false; } num = -1; result.set(server,port,num,config); return true; } std::string getName(const arrayType a){ switch(a){ case DARRAY: return "darray"; case DFARRAY: return "dfarray"; case DFMATRIX: return "dfmatrix"; case SDARRAY: return "sdarray"; } assert(false); return "unknown"; } std::string getPName(const arrayType a){ switch(a){ case DARRAY: return "pdarray"; case DFARRAY: return "pdfarray"; case SDARRAY: return "psdarray"; case DFMATRIX : return "unknown";//partially type of dmatrix does not exist } assert(false); return "unknown"; } ListExpr wrapType(const arrayType a, ListExpr subtype){ return nl->TwoElemList( nl->SymbolAtom(getName(a)), subtype); } ListExpr wrapPType(const arrayType a, ListExpr subtype){ return nl->TwoElemList( nl->SymbolAtom(getPName(a)), subtype); } /* 3.1 Implementation of DistTypeBase 3.1.1 Constructors */ DistTypeBase::DistTypeBase(const std::vector& _worker, const string& _name): worker(_worker), name(_name), defined(true),keepRemoteObjects(false){} DistTypeBase::DistTypeBase( const string& _name): worker(), name(_name), defined(true),keepRemoteObjects(false){} DistTypeBase::DistTypeBase( const DistTypeBase& src): worker(src.worker), name(src.name), defined(src.defined), keepRemoteObjects(src.keepRemoteObjects) {} DistTypeBase& DistTypeBase::operator=(const DistTypeBase& src){ worker = src.worker; name = src.name; defined = src.defined; keepRemoteObjects = src.keepRemoteObjects; return *this; } void DistTypeBase::set(const std::string& name, const std::vector& worker){ if(!stringutils::isIdent(name)){ // invalid this->name = ""; this->defined = false; return; } defined = true; this->name = name; this->worker = worker; } bool DistTypeBase::equalWorkers(const DistTypeBase& other) const{ return equalWorkers(other.worker); } bool DistTypeBase::equalWorkers(const std::vector& w) const{ if(worker.size() != w.size()){ return false; } for(size_t i=0;i= (int) worker.size()){ assert(false); // throw "Invalid worker number"; } return worker[i]; } std::string DistTypeBase::getName() const{ return name; } void DistTypeBase::makeUndefined(){ worker.clear(); name = ""; defined = false; } bool DistTypeBase::setName( const std::string& n){ if(!stringutils::isIdent(n)){ return false; } name = n; return true; } /* 3.2 Implementation of DArrayT */ DArrayBase::DArrayBase(const std::vector& _map, const std::string& _name): DistTypeBase(_name), map(_map){ if(!stringutils::isIdent(name) || map.size() ==0 ){ // invalid makeUndefined(); return; } defined = true; } DArrayBase::DArrayBase(const std::vector& _map, const std::string& _name, const std::vector& _worker): DistTypeBase(_worker, _name), map(_map){ if(!stringutils::isIdent(name) || map.size() ==0 || !checkMap()){ // invalid name = ""; defined = false; return; } defined = true; } DArrayBase::DArrayBase(const DArrayBase& src): DistTypeBase(src), map(src.map) {} DArrayBase& DArrayBase::operator=(const DArrayBase& src) { boost::lock_guard guard(mapmtx); DistTypeBase::operator=(src); this->map = src.map; return *this; } void DArrayBase::set(const std::string& name, const std::vector& worker){ boost::lock_guard guard(mapmtx); DistTypeBase::set(name, worker); this->map = createStdMap(worker.size(),worker.size()); } void DArrayBase::set(const size_t size, const std::string& name, const std::vector& worker){ boost::lock_guard guard(mapmtx); DistTypeBase::set(name, worker); this->map = createStdMap(size,worker.size()); } bool DArrayBase::equalMapping(DArrayBase& a, bool ignoreSize )const{ if(getType()==DFMATRIX){ return false; } boost::lock_guard guard(mapmtx); const vector m = a.getMap(); if(!ignoreSize && (map.size()!=m.size())){ return false; } size_t minV = std::min(map.size(), m.size()); for(size_t i=0;i& m, const std::string& name, const std::vector& worker){ if(!stringutils::isIdent(name) || m.size() ==0){ // invalid makeUndefined(); return; } boost::lock_guard guard(mapmtx); defined = true; this->name = name; this->map = m; this->worker = worker; if(!checkMap()){ makeUndefined(); } } void DArrayBase::setStdMap(size_t size){ boost::lock_guard guard(mapmtx); map = createStdMap(size, worker.size()); } const DArrayElement& DArrayBase::getWorkerForSlot(int i) const{ if(i<0 || i>= (int) map.size()){ cerr << "access for worker " << i << endl; cerr << "number of workers is " << map.size() << endl; assert(false); } boost::lock_guard guard(mapmtx); return getWorker(map[i]); } size_t DArrayBase::getWorkerIndexForSlot(int i){ boost::lock_guard guard(mapmtx); if(i<0 || i>= (int)map.size()){ assert(false); } return map[i]; } void DArrayBase::setResponsible(size_t slot, size_t _worker){ boost::lock_guard guard(mapmtx); assert(slot < map.size()); assert(_worker < worker.size()); map[slot] = _worker; } ListExpr DArrayBase::toListExpr() const{ if(!defined){ return listutils::getUndefined(); } ListExpr wl; if(worker.empty()){ wl = nl->TheEmptyList(); } else { wl = nl->OneElemList( worker[0].toListExpr()); ListExpr last = wl; for(size_t i=1;iAppend(last, worker[i].toListExpr()); } } boost::lock_guard guard(mapmtx); ListExpr usedSlots = nl->TheEmptyList(); ListExpr uslast = nl->TheEmptyList(); bool usfirst = true; if(this->isPartially()){ for(size_t i=0;igetSize(); i++){ if(this->isSlotUsed(i)){ if(usfirst){ usedSlots = nl->OneElemList( nl->IntAtom(i)); uslast = usedSlots; usfirst = false; } else { uslast = nl->Append(uslast, nl->IntAtom(i)); } } } } if(isStdMap()){ if(!this->isPartially()){ return nl->ThreeElemList(nl->SymbolAtom(name), nl->IntAtom(getSize()), wl); } else { return nl->FourElemList(nl->SymbolAtom(name), nl->IntAtom(getSize()), wl, usedSlots); } } else if(map.empty()) { if(!this->isPartially()){ return nl->ThreeElemList(nl->SymbolAtom(name), nl->TheEmptyList(), wl); } else { return nl->FourElemList(nl->SymbolAtom(name), nl->TheEmptyList(), wl, usedSlots); } } else { ListExpr lmap = nl->OneElemList(nl->IntAtom(map[0])); ListExpr last = lmap; for(size_t i=1;iAppend(last, nl->IntAtom(map[i])); } if(!this->isPartially()){ return nl->ThreeElemList(nl->SymbolAtom(name), lmap, wl); } else { return nl->FourElemList(nl->SymbolAtom(name), lmap, wl, usedSlots); } } } template R* DArrayBase::readFrom(ListExpr list, bool isPartially){ if(listutils::isSymbolUndefined(list)){ std::vector m; return new R(m,""); } int requiredLength = isPartially?4:3; if(!nl->HasLength(list,requiredLength)){ return 0; } ListExpr Name = nl->First(list); ListExpr Workers = nl->Third(list); if( (nl->AtomType(Name) != SymbolType) ||(nl->AtomType(Workers)!=NoAtom)){ return 0; } std::string name = nl->SymbolValue(Name); if(!stringutils::isIdent(name)){ return 0; } std::vector v; int wn = 0; while(!nl->IsEmpty(Workers)){ DArrayElement elem("",0,0,""); if(!InDArrayElement(nl->First(Workers), elem)){ return 0; } elem.setNum(wn); wn++; v.push_back(elem); Workers = nl->Rest(Workers); } std::vector m; if(nl->AtomType(nl->Second(list))==IntType){ int size = nl->IntValue(nl->Second(list)); if(size <=0){ return 0; } m = createStdMap(size,v.size()); } else if(nl->AtomType(nl->Second(list))!=NoAtom){ return 0; } else { ListExpr lm = nl->Second(list); while(!nl->IsEmpty(lm)){ ListExpr first = nl->First(lm); lm = nl->Rest(lm); if(nl->AtomType(first)!=IntType){ return 0; } int mv = nl->IntValue(first); if(mv<0 || mv>=(int)v.size()){ return 0; } m.push_back(mv); } } std::set usedSlots; if(isPartially){ ListExpr usedSlotsList = nl->Fourth(list); if(nl->AtomType(usedSlotsList) != NoAtom){ return 0; } while(!nl->IsEmpty(usedSlotsList)){ ListExpr slot = nl->First(usedSlotsList); usedSlotsList = nl->Rest(usedSlotsList); if(nl->AtomType(slot) != IntType){ return 0; } int s = nl->IntValue(slot); if(s<0 || (size_t) s >= m.size()){ return 0; } usedSlots.insert(s); } } R* result = new R(m,name); result->setUsedSlots(usedSlots); swap(result->worker,v); result->defined = true; return result; } template bool DArrayBase::open(SmiRecord& valueRecord, size_t& offset, const ListExpr __attribute__((unused)) typeInfo, Word& result){ bool defined; result.addr = 0; if(!readVar(defined,valueRecord,offset)){ return false; } if(!defined){ std::vector m; result.addr = new R(m,""); return true; } bool keepRemoteObjects; if(!readVar(keepRemoteObjects,valueRecord,offset)){ return false; } // array in smirecord is defined, read size size_t size; if(!readVar(size,valueRecord,offset)){ return false; } // read name std::string name; if(!readVar(name,valueRecord, offset)){ return false; } // read map uint32_t me; std::vector m; DArrayBase* res = 0; for(size_t i=0;i(me,valueRecord,offset)){ return false; } m.push_back(me); } res = new R(m,name); res->setKeepRemoteObjects(keepRemoteObjects); int wn = 0; // append workers size_t numWorkers; if(!readVar(numWorkers,valueRecord, offset)){ delete res; return false; } for(size_t i=0; i< numWorkers; i++){ DArrayElement elem("",0,0,""); if(!elem.readFrom(valueRecord, offset)){ delete res; return false; } elem.setNum(wn); wn++; res->worker.push_back(elem); } if(partially){ size_t numUsedSlots; if(!readVar(numUsedSlots, valueRecord,offset)){ delete res; return false; } std::set used; int us; for(size_t i=0;i(us, valueRecord,offset)){ delete res; return false; } if(us >=0 && (size_t)us < res->getSize()){ used.insert(us); } } res->setUsedSlots(used); } result.addr = res; return true; } template bool DArrayBase::save(SmiRecord& valueRecord, size_t& offset, const ListExpr __attribute__((unused)) typeInfo, Word& value) { DArrayBase* a = (DArrayBase*) value.addr; // defined flag if(!writeVar(a->defined,valueRecord,offset)){ return false; } if(!a->defined){ return true; } if(!writeVar(a->keepRemoteObjects,valueRecord,offset)){ return false; } // size size_t s = a->getSize(); if(!writeVar(s,valueRecord,offset)){ return false; } // name if(!writeVar(a->name, valueRecord, offset)){ return false; } // map boost::lock_guard guard(a->mapmtx); for(size_t i=0;imap.size();i++){ if(!writeVar(a->map[i], valueRecord,offset)){ return false; } } // workers if(!writeVar(a->worker.size(), valueRecord, offset)){ return false; } for(size_t i=0;iworker.size();i++){ if(!a->worker[i].saveTo(valueRecord,offset)){ return false; } } if(partially){ std::set used = a->getUsedSlots(); size_t s = used.size(); if(!writeVar(s,valueRecord,offset)){ return false; } int c = 0; for(auto it = used.begin();it!=used.end();it++){ int slot = *it; c++; if(!writeVar(slot,valueRecord,offset)){ return false; } } } return true; } // instatiations template bool DArrayBase::save(SmiRecord&, size_t& , const ListExpr __attribute__((unused)) , Word& ); template bool DArrayBase::save(SmiRecord&, size_t& , const ListExpr __attribute__((unused)) , Word& ); std::vector DArrayBase::createStdMap(const uint32_t size, const int numWorkers){ std::vector map; for(uint32_t i=0;i guard(mapmtx); out << "Name : " << name <<", size : " << map.size() << " workers : [" ; for(size_t i =0;i0) out << ", "; worker[i].print(out); } out << "]"; out << "map = ["; for(uint32_t i=0;i0){ out << ", "; } out << i << " -> " << map[i]; } out << "]"; } void DArrayBase::makeUndefined(){ boost::lock_guard guard(mapmtx); DistTypeBase::makeUndefined(); map.clear(); } bool DArrayBase::checkMap(){ boost::lock_guard guard(mapmtx); for(size_t i=0;i= worker.size()){ return false; } } return true; } bool DArrayBase::isStdMap() const{ boost::lock_guard guard(mapmtx); int s = worker.size(); for(size_t i=0;i bool DArrayT::checkType(const ListExpr list){ if(!nl->HasLength(list,2)){ return false; } if(!listutils::isSymbol(nl->First(list), BasicType())){ return false; } // for other than DARRAY, only relations are allowed as a // subtype if(T!=DARRAY){ return Relation::checkType(nl->Second(list)); } // check that second arghument is an valid tyoe SecondoCatalog* ctl = SecondoSystem::GetCatalog(); std::string name; int algid, type; if(!ctl->LookUpTypeExpr(nl->Second(list), name, algid, type)){ return false; } AlgebraManager* am = SecondoSystem::GetAlgebraManager(); ListExpr errorInfo = listutils::emptyErrorInfo(); if(!am->TypeCheck(algid,type,nl->Second(list),errorInfo)){ return false; } return true; } template bool PDArrayT::checkType(const ListExpr list){ if(!nl->HasLength(list,2)){ return false; } if(!listutils::isSymbol(nl->First(list), BasicType())){ return false; } // for other than DARRAY, only relations are allowed as a // subtype if(T!=DARRAY){ return Relation::checkType(nl->Second(list)); } // check that second arghument is an valid tyoe SecondoCatalog* ctl = SecondoSystem::GetCatalog(); std::string name; int algid, type; if(!ctl->LookUpTypeExpr(nl->Second(list), name, algid, type)){ return false; } AlgebraManager* am = SecondoSystem::GetAlgebraManager(); ListExpr errorInfo = listutils::emptyErrorInfo(); if(!am->TypeCheck(algid,type,nl->Second(list),errorInfo)){ return false; } return true; } // instantiation template bool PDArrayT::checkType(const ListExpr list); template bool PDArrayT::checkType(const ListExpr list); /* Implementation of ~DMatrix~ */ const std::string DFMatrix::BasicType(){ return "dfmatrix"; } DFMatrix::DFMatrix(const size_t _size , const std::string& _name): DistTypeBase(_name), size(_size) { if(!stringutils::isIdent(name) || size ==0 ){ // invalid name = ""; defined = false; size = 0; return; } defined = true; } DFMatrix::DFMatrix(const size_t _size, const std::string& _name, const std::vector& _worker): DistTypeBase(_worker, _name), size(_size) { if(!stringutils::isIdent(name) || size ==0 ){ // invalid name = ""; defined = false; size = 0; return; } defined = true; } void DFMatrix::setSize(size_t newSize){ assert(newSize > 0); this->size = newSize; } bool DFMatrix::open(SmiRecord& valueRecord, size_t& offset, const ListExpr __attribute__((unused)) typeInfo, Word& result){ bool defined; result.addr = 0; if(!readVar(defined,valueRecord,offset)){ return false; } if(!defined){ std::vector m; result.addr = new DFMatrix(0,""); return true; } bool keepRemoteObjects; if(!readVar(keepRemoteObjects,valueRecord,offset)){ return false; } // array in smirecord is defined, read size size_t size; if(!readVar(size,valueRecord,offset)){ return false; } // read name std::string name; if(!readVar(name,valueRecord, offset)){ return false; } DFMatrix* res = new DFMatrix(size,name); res->setKeepRemoteObjects(keepRemoteObjects); int wn = 0; // append workers size_t numWorkers; if(!readVar(numWorkers,valueRecord, offset)){ return false; } for(size_t i=0; i< numWorkers; i++){ DArrayElement elem("",0,0,""); if(!elem.readFrom(valueRecord, offset)){ delete res; return false; } elem.setNum(wn); wn++; res->worker.push_back(elem); } result.addr = res; return true; } bool DFMatrix::save(SmiRecord& valueRecord, size_t& offset, const ListExpr __attribute__((unused)) typeInfo, Word& value) { DFMatrix* a = (DFMatrix*) value.addr; // defined flag if(!writeVar(a->defined,valueRecord,offset)){ return false; } if(!a->defined){ return true; } if(!writeVar(a->keepRemoteObjects,valueRecord,offset)){ return false; } // size size_t s = a->size; if(!writeVar(s,valueRecord,offset)){ return false; } // name if(!writeVar(a->name, valueRecord, offset)){ return false; } // workers if(!writeVar(a->worker.size(), valueRecord, offset)){ return false; } for(size_t i=0;iworker.size();i++){ if(!a->worker[i].saveTo(valueRecord,offset)){ return false; } } return true; } bool DFMatrix::checkType(ListExpr e){ if(!nl->HasLength(e,2)) { return false; } if(!listutils::isSymbol(nl->First(e), BasicType())){ return false; } return Relation::checkType(nl->Second(e)); } ListExpr DFMatrix::toListExpr()const{ if(!defined){ return listutils::getUndefined(); } ListExpr wl; if(worker.empty()){ wl = nl->TheEmptyList(); } else { wl = nl->OneElemList( worker[0].toListExpr()); ListExpr last = wl; for(size_t i=1;iAppend(last, worker[i].toListExpr()); } } return nl->ThreeElemList(nl->SymbolAtom(name), nl->IntAtom(size), wl); } DFMatrix* DFMatrix::readFrom(ListExpr list){ if(listutils::isSymbolUndefined(list)){ return new DFMatrix(0,""); } if(!nl->HasLength(list,3)){ return 0; } ListExpr Name = nl->First(list); ListExpr Workers = nl->Third(list); if( (nl->AtomType(Name) != SymbolType) ||(nl->AtomType(Workers)!=NoAtom)){ return 0; } std::string name = nl->SymbolValue(Name); if(!stringutils::isIdent(name)){ return 0; } std::vector v; int wn = 0; while(!nl->IsEmpty(Workers)){ DArrayElement elem("",0,0,""); if(!InDArrayElement(nl->First(Workers), elem)){ return 0; } elem.setNum(wn); wn++; v.push_back(elem); Workers = nl->Rest(Workers); } std::vector m; size_t s; if(nl->AtomType(nl->Second(list))==IntType){ int size = nl->IntValue(nl->Second(list)); if(size <=0){ return 0; } s = size; } else { return 0; } DFMatrix* result = new DFMatrix(s, name, v); result->defined = true; return result; } // template instantiaons template bool DArrayBase::open(SmiRecord&, size_t&, const ListExpr, Word&); template bool DArrayBase::open(SmiRecord&, size_t&, const ListExpr, Word&); template bool DArrayBase::open(SmiRecord&, size_t&, const ListExpr, Word&); template bool DArrayBase::open(SmiRecord&, size_t&, const ListExpr, Word&); template DArray* DArrayBase::readFrom(ListExpr, bool); template DFArray* DArrayBase::readFrom(ListExpr, bool); template PDArray* DArrayBase::readFrom(ListExpr, bool); template PDFArray* DArrayBase::readFrom(ListExpr, bool); template class DArrayT; template class DArrayT; ListExpr SDArray::Property(){ 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("-> SIMPLE"), nl->StringAtom(SDArray::BasicType()), nl->StringAtom("(name (worker1 worker2 ...))"), nl->StringAtom("(sda (('127.0.0.1', 1234, 'SecondoConfig.ini')))") ))); } Word SDArray::IN( const ListExpr typeInfo, const ListExpr instance, const int errorPos, ListExpr& errorInfo, bool& correct ) { correct = false; if(listutils::isSymbolUndefined(instance)){ SDArray* sd = new SDArray(""); sd->makeUndefined(); Word res(sd); correct = true; return res; } if(!nl->HasLength(instance,2)){ cmsg.inFunError("two Elem list expected"); return SetWord((void*)0); } ListExpr nameList = nl->First(instance); if(nl->AtomType(nameList)!=SymbolType){ cmsg.inFunError("invalid name (not a symbol)"); return SetWord((void*)0); } string name = nl->SymbolValue(nameList); ListExpr workerList = nl->Second(instance); if(nl->AtomType(workerList)!=NoAtom){ cmsg.inFunError("invalid worker list (not a list)"); return SetWord((void*)0); } vector workers; std::set > usedServers; while(!nl->IsEmpty(workerList)){ ListExpr singleWorker = nl->First(workerList); workerList = nl->Rest(workerList); DArrayElement worker("",0,0,""); if(!InDArrayElement(singleWorker,worker)){ cmsg.inFunError("found invalid worker definition"); return SetWord((void*)0); } pair con(worker.getHost(), worker.getPort()); if(usedServers.find(con)!=usedServers.end()){ cmsg.inFunError("found connection twice"); return SetWord((void*)0); } usedServers.insert(con); workers.push_back(worker); } SDArray* res = new SDArray(workers,name); correct = true; return SetWord(res); } ListExpr SDArray::Out( ListExpr typeInfo, Word value ) { SDArray* a = (SDArray*) value.addr; if(!a->IsDefined()){ return listutils::getUndefined(); } ListExpr nameList = nl->SymbolAtom(a->getName()); int s = a->getSize(); ListExpr workers = nl->TheEmptyList(); if(s>0){ workers = nl->OneElemList(a->getWorker(0).toListExpr()); ListExpr last = workers; for(int i=1;iAppend(last, a->getWorker(i).toListExpr()); } } return nl->TwoElemList(nameList, workers); } bool SDArray::Open( SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value ) { // check whether defined bool def; valueRecord.Read(&def, sizeof(bool), offset); offset+=sizeof(bool); if(!def){ SDArray* res = new SDArray(""); res->makeUndefined(); value.addr = res; return true; } bool keepRemoteObjects; if(!readVar(keepRemoteObjects,valueRecord,offset)){ return false; } // read number of workers and size of the name size_t size; valueRecord.Read(&size,sizeof(size_t), offset); offset += sizeof(size_t); size_t namesize; valueRecord.Read(&namesize,sizeof(size_t),offset); offset += sizeof(size_t); // read the name char* buffer = new char[namesize]; valueRecord.Read(buffer,namesize,offset); offset += namesize; string name(buffer,namesize); delete[] buffer; // read the workers vector workers; for(size_t i=0;isetKeepRemoteObjects(keepRemoteObjects); value.addr = res; return true; } bool SDArray::Save( SmiRecord& valueRecord, size_t& offset, const ListExpr typeInfo, Word& value ) { SDArray* a = (SDArray*) value.addr; bool def = a->IsDefined(); valueRecord.Write(&def,sizeof(bool),offset); offset+=sizeof(bool); if(!def) return true; if(!writeVar(a->keepRemoteObjects,valueRecord,offset)){ return false; } size_t size = a->getSize(); string name = a->getName(); size_t namesize = name.length(); const char* buffer = name.c_str(); valueRecord.Write(&size,sizeof(size_t),offset); offset += sizeof(size_t); valueRecord.Write(&namesize,sizeof(size_t), offset); offset += sizeof(size_t); valueRecord.Write(buffer,namesize,offset); offset += namesize; for(size_t i=0;igetWorker(i).saveTo(valueRecord,offset); } return true; } } // end of namespace distributed2