/* ---- This file is part of SECONDO. Copyright (C) 2018, 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 "Tools/DFS/dfs/remotedfs.h" #include "Tools/DFS/dfs/dfs.h" #include "QueryProcessor.h" #include "NestedList.h" #include "StandardTypes.h" #include "ListUtils.h" #include "Algebras/FText/FTextAlgebra.h" #include "Algebras/Standard-C++/LongInt.h" #include using namespace std; extern QueryProcessor* qp; extern NestedList* nl; namespace dfsalg{ #define REMOTE_FILESYSTEM // pointer to the currently used file system // may be this will be changed later to an uri #ifdef REMOTE_FILESYSTEM static dfs::remote::RemoteFilesystem* filesystem = 0; #else static dfs::Filesystem* filesystem = 0; #endif static dfs::log::Logger* logger = new dfs::log::DefaultOutLogger(); /* 2 Operators */ /* 2.1 ~connectDFS~ */ ListExpr connectDFSTM(ListExpr args){ if(!nl->HasLength(args,2)){ return listutils::typeError("two arguments expected"); } ListExpr host = nl->First(args); if(!CcString::checkType(host) && !FText::checkType(host)){ return listutils::typeError("first argument must be of type " "string or text"); } if(!CcInt::checkType(nl->Second(args))){ return listutils::typeError("second argument must be of type int"); } return listutils::basicSymbol(); } template int connectDFSVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ // prepare result result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; // delete existing remote filesystem if(filesystem) { delete filesystem; filesystem = 0; } // check arguments T* host = (T*) args[0].addr; CcInt* port = (CcInt*) args[1].addr; if(!host->IsDefined() || !port->IsDefined()){ res->SetDefined(false); return 0; } stringstream ss; ss << "dfs-index://"<GetValue()<<":"<GetValue(); URI uri = URI::fromString(ss.str().c_str()); filesystem = new dfs::remote::RemoteFilesystem(uri,logger); // check whether connection is successful bool success = false; try{ // if there is no connection, some exception will // be thrown by the next command filesystem->countFiles(); success = true; } catch(...){ success = false; } res->Set(true,success); return 0; } ValueMapping connectDFSVM[] = { connectDFSVMT, connectDFSVMT }; int connectDFSSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec connectDFSSpec( "string x int -> bool", "connectDFS(_)", "Connects tto a distributed file system. Arguments are " " hostname and port of the index node.", " query connectDFS('localhost', 4444)" ); Operator connectDFSOp( "connectDFS", connectDFSSpec.getStr(), 2, connectDFSVM, connectDFSSelect, connectDFSTM ); /* 2.1 disconnectDFS */ ListExpr disconnectDFSTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("no arguments expected"); } return listutils::basicSymbol(); } int disconnectDFSVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); ((CcBool*) result.addr)->Set(true, filesystem!=0); if(filesystem){ delete filesystem; filesystem = 0; } return 0; } OperatorSpec disconnectDFSSpec( "-> bool", "disconnectDFS()", "Disconnects a distributed filesystem. Returns true " " if there was a distributed filesystem before", "query disconnectDFS() " ); Operator disconnectDFSOp( "disconnectDFS", disconnectDFSSpec.getStr(), disconnectDFSVM, Operator::SimpleSelect, disconnectDFSTM ); /* 2.2 ~deleteDFSFile~ */ ListExpr deleteDFSFileTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argument expected"); } ListExpr arg1 = nl->First(args); if(!CcString::checkType(arg1)&&!FText::checkType(arg1)){ return listutils::typeError("string or text required"); } return listutils::basicSymbol(); } template int deleteDFSFileVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; T* id = (T*) args[0].addr; if(!id->IsDefined()){ res->SetDefined(false); return 0; } if(!filesystem){ res->Set(true,false); return 0; } try{ string name = id->GetValue(); if(!filesystem->hasFile(name.c_str())){ res->Set(true,false); return 0; } filesystem->deleteFile(name.c_str()); res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } ValueMapping deleteDFSFileVM[] = { deleteDFSFileVMT, deleteDFSFileVMT }; int deleteDFSFileSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec deleteDFSFileSpec( "{string,text} -> bool", "deleteDFSFile(_)", "removes a file from connected dfs and returns success.", "query deleteDFSFile('myfile')" ); Operator deleteDFSFileOp( "deleteDFSFile", deleteDFSFileSpec.getStr(), 2, deleteDFSFileVM, deleteDFSFileSelect, deleteDFSFileTM ); /* 2.3 Operator ~storeTextAsDFSFile~ */ ListExpr storeTextAsDFSFileTM(ListExpr args){ // text x {string,text} [ x string ] -> bool if(!nl->HasLength(args,2) && !nl->HasLength(args,3)){ return listutils::typeError("2 or 3 arguments required"); } if(!FText::checkType(nl->First(args))){ return listutils::typeError("fisrt arg is not a text"); } ListExpr arg2 = nl->Second(args); if(!CcString::checkType(arg2) && !FText::checkType(arg2)){ return listutils::typeError("second arg must be a string or a text"); } if(nl->HasLength(args,3)){ if(!CcString::checkType(nl->Third(args))){ return listutils::typeError("third arg must be a string"); } } return listutils::basicSymbol(); } template int storeTextAsDFSFileVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; FText* content = (FText*) args[0].addr; T* name = (T*) args[1].addr; if(!content->IsDefined() || !name->IsDefined()){ res->SetDefined(false); return 0; } string contentstr = content->GetValue(); string namestr = name->GetValue(); string catstr; if(qp->GetNoSons(s)==3){ CcString* cat = (CcString*) args[2].addr; if(!cat->IsDefined()) { res->SetDefined(false); return 0; } catstr = cat->GetValue(); } if(!filesystem){ res->Set(true,false); return 0; } try{ if(catstr.length()>0){ filesystem->storeFile(namestr.c_str(),contentstr.c_str(), contentstr.length(), catstr.c_str()); } else { filesystem->storeFile(namestr.c_str(),contentstr.c_str(), contentstr.length()); } res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } ValueMapping storeTextAsDFSFileVM[] = { storeTextAsDFSFileVMT, storeTextAsDFSFileVMT }; int storeTextAsDFSFileSelect(ListExpr args){ return CcString::checkType(nl->Second(args))?0:1; } OperatorSpec storeTextAsDFSFileSpec( "text x {string,text} [x string] -> bool", " storeTextAsDFSFile(content, filename [,category]) ", "Stores the content of a text into the currently " " connected dfs. ", "query storeTextAsDFSFile('My content', 'myfirstfile')" ); Operator storeTextAsDFSFileOp( "storeTextAsDFSFile", storeTextAsDFSFileSpec.getStr(), 2, storeTextAsDFSFileVM, storeTextAsDFSFileSelect, storeTextAsDFSFileTM ); /* 2.4 Operator ~storeLocalFileToDFS~ */ ListExpr storeLocalFileToDFSTM(ListExpr args){ if(!nl->HasLength(args,2) && !nl->HasLength(args,3)){ return listutils::typeError("2 or 3 arguments expected"); } ListExpr arg = nl->First(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("string or text as 1st arg expected"); } arg = nl->Second(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("string or text as 2nd arg expected"); } if(nl->HasLength(args,3)){ if(!CcString::checkType(nl->Third(args))){ return listutils::typeError("3rd arg not of type string"); } } return listutils::basicSymbol(); } template int storeLocalFileToDFSVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; L* localName = (L*) args[0].addr; R* remoteName = (R*) args[1].addr; if(!localName->IsDefined() || !remoteName->IsDefined()){ res->SetDefined(false); return 0; } string cat; if(qp->GetNoSons(s)==3){ CcString* Cat = (CcString*) args[2].addr; if(!Cat->IsDefined()){ res->SetDefined(false); return 0; } cat = Cat->GetValue(); } string localN = localName->GetValue(); string remoteN = remoteName->GetValue(); if(!filesystem){ // no dfs connected res->Set(true,false); return 0; } // arguments are checked // the file file be transmitted in several parts ifstream in(localN.c_str(), ios::binary); if(!in){ // local file could ot be opened res->Set(true,false); return 0; } in.close(); try{ if(cat.length()>0){ filesystem->storeFileFromLocal(remoteN.c_str(), localN.c_str(), cat.c_str()); } else { filesystem->storeFileFromLocal(remoteN.c_str(), localN.c_str()); } res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } ValueMapping storeLocalFileToDFSVM[] = { storeLocalFileToDFSVMT, storeLocalFileToDFSVMT, storeLocalFileToDFSVMT, storeLocalFileToDFSVMT }; int storeLocalFileToDFSSelect(ListExpr args){ int n1 = CcString::checkType(nl->First(args))?0:2; int n2 = CcString::checkType(nl->Second(args))?0:1; return n1+n2; } OperatorSpec storeLocalFileToDFSSpec( "{string,text} x {string, text} [ x string] -> bool", "storeLocalFileToDFS( localName, remoteName [,category]", "Brings a local file into the dfs. ", " query storeLocalFileToDFS('berlintest', 'berlintest')" ); Operator storeLocalFileToDFSOp( "storeLocalFileToDFS", storeLocalFileToDFSSpec.getStr(), 4, storeLocalFileToDFSVM, storeLocalFileToDFSSelect, storeLocalFileToDFSTM ); /* 2.5 Operator ~storeDFSFile~ */ ListExpr storeDFSFileTM(ListExpr args){ if(!nl->HasLength(args,2)){ return listutils::typeError("2 args expected"); } ListExpr arg = nl->First(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("1st arg not of type string or text"); } arg = nl->Second(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("2nd arg not of type string or text"); } return listutils::basicSymbol(); } template int storeDFSFileVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; R* remoteName = (R*) args[0].addr; L* localName = (L*) args[1].addr; if(!remoteName->IsDefined() || !localName->IsDefined()){ res->SetDefined(false); return 0; } if(!filesystem){ res->Set(true,false); return 0; } string remoteN = remoteName->GetValue(); string localN = localName->GetValue(); char* buffer = 0; try{ if(!filesystem->hasFile(remoteN.c_str())){ res->Set(true,false); return 0; } if(!partially){ filesystem->receiveFileToLocal(remoteN.c_str(), localN.c_str()); res->Set(true,true); } else { size_t buffersize = 1024*1024; buffer = new char[buffersize]; size_t toRead = filesystem->fileSize(remoteN.c_str()); ofstream out(localN.c_str(), ios::binary| ios::trunc); if(!out){ res->Set(true,false); return 0; } size_t pos = 0; while(toRead>0){ size_t r = buffersizereceiveFilePartially(remoteN.c_str(),pos, r, buffer); out.write(buffer,r); toRead -= r; pos += r; } out.close(); res->Set(true,true); } } catch(...){ res->Set(true,false); } if(buffer){ delete[] buffer; } return 0; } ValueMapping storeDFSFileVM[] = { storeDFSFileVMT, storeDFSFileVMT, storeDFSFileVMT, storeDFSFileVMT }; ValueMapping storeDFSFile2VM[] = { storeDFSFileVMT, storeDFSFileVMT, storeDFSFileVMT, storeDFSFileVMT }; int storeDFSFileSelect(ListExpr args){ int n1 = CcString::checkType(nl->First(args))?0:2; int n2 = CcString::checkType(nl->Second(args))?0:1; return n1+n2; } OperatorSpec storeDFSFileSpec( "{string,text} x {string,text} -> bool", "storeDFSFile(remoteName, localName)", "Copies a file from a connected dfs to the local file system.", "query storeDFSFile('myRemoteFile', 'myLocalFile')" ); OperatorSpec storeDFSFile2Spec( "{string,text} x {string,text} -> bool", "storeDFSFile2(remoteName, localName)", "Copies a file from a connected dfs to the local file system.", "query storeDFSFile2('myRemoteFile', 'myLocalFile')" ); Operator storeDFSFileOp( "storeDFSFile", storeDFSFileSpec.getStr(), 4, storeDFSFileVM, storeDFSFileSelect, storeDFSFileTM ); Operator storeDFSFile2Op( "storeDFSFile2", storeDFSFile2Spec.getStr(), 4, storeDFSFile2VM, storeDFSFileSelect, storeDFSFileTM ); /* 2.6 Operator ~isDFSFile~ */ ListExpr isDFSFileTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argument expected"); } ListExpr arg = nl->First(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("string or text expected"); } return listutils::basicSymbol(); } template int isDFSFileVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; R* Id = (R*) args[0].addr; if(!Id->IsDefined()){ res->SetDefined(false); return 0; } string id = Id->GetValue(); if(!filesystem){ res->Set(true,false); return 0; } try{ res->Set(true,filesystem->hasFile(id.c_str())); } catch(...){ res->Set(true,false); } return 0; } ValueMapping isDFSFileVM[] = { isDFSFileVMT, isDFSFileVMT }; int isDFSFileSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec isDFSFileSpec( "{string,text} -> bool", "isDFSFile(name)", "Check whether the file is part of the connected dfs", "query isDFSFile('myRemoteFile')" ); Operator isDFSFileOp( "isDFSFile", isDFSFileSpec.getStr(), 2, isDFSFileVM, isDFSFileSelect, isDFSFileTM ); /* 2.7 Operator ~nextDFSWritePosition~ */ ListExpr nextDFSWritePositionTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argument expected"); } ListExpr arg = nl->First(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("string or text expected"); } return listutils::basicSymbol(); } template int nextDFSWritePositionVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; R* Id = (R*) args[0].addr; if(!Id->IsDefined()){ res->SetDefined(false); return 0; } string id = Id->GetValue(); if(!filesystem){ res->Set(true,-1); return 0; } try{ res->Set(true,filesystem->nextWritePosition(id.c_str())); } catch(...){ res->Set(true,-1); } return 0; } ValueMapping nextDFSWritePositionVM[] = { nextDFSWritePositionVMT, nextDFSWritePositionVMT }; int nextDFSWritePositionSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec nextDFSWritePositionSpec( "{string,text} -> bool", "nextDFSWritePosition(name)", "Returns the append position of a dfs file (its length).", "query nextDFSWritePosition('myRemoteFile')" ); Operator nextDFSWritePositionOp( "nextDFSWritePosition", nextDFSWritePositionSpec.getStr(), 2, nextDFSWritePositionVM, nextDFSWritePositionSelect, nextDFSWritePositionTM ); /* 2.8 Operator ~getDFSFileAsText~ */ ListExpr getDFSFileAsTextTM(ListExpr args){ if(!nl->HasLength(args,1) && !nl->HasLength(args,3)){ return listutils::typeError("one or three args expected"); } ListExpr arg1 = nl->First(args); if(!CcString::checkType(arg1) && !FText::checkType(arg1)){ return listutils::typeError("first arg must be of type string or text"); } if(nl->HasLength(args,3)){ if(!CcInt::checkType(nl->Second(args)) || !CcInt::checkType(nl->Third(args))){ return listutils::typeError("2nd and 3rd arg must be of type int"); } } return listutils::basicSymbol(); } template int getDFSFileAsTextVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result=qp->ResultStorage(s); FText* res = (FText*) result.addr; R* Fname = (R*) args[0].addr; if(!Fname->IsDefined() || filesystem==0){ res->SetDefined(false); return 0; } string fname = Fname->GetValue(); if(!filesystem->hasFile(fname.c_str())){ res->SetDefined(false); return 0; } int min=0; int max=filesystem->fileSize(fname.c_str()); if(qp->GetNoSons(s)==3){ CcInt* Min = (CcInt*) args[1].addr; CcInt* Max = (CcInt*) args[2].addr; if(!Min->IsDefined() || !Max->IsDefined()){ res->SetDefined(false); return 0; } min = Min->GetValue(); int m = Max->GetValue(); if(m max){ res->SetDefined(false); return 0; } } size_t bufferlength = max-min; char* buffer = new char[bufferlength]; try{ filesystem->receiveFilePartially(fname.c_str(), min, bufferlength,buffer); string bufferstr(buffer, bufferlength); res->Set(true,bufferstr); } catch(...){ res->SetDefined(false); } delete[] buffer; return 0; } ValueMapping getDFSFileAsTextVM[] = { getDFSFileAsTextVMT, getDFSFileAsTextVMT }; int getDFSFileAsTextSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec getDFSFileAsTextSpec( "{string,text} [x int x int] -> text", "getDFSFileAsText(filename, min, max) ", "Receives a portion of a file from connected remote " "file system. If the min and max is missing, the whole " " file is taken.", "query getDFSFileAsText('myRemoteFile')" ); Operator getDFSFileAsTextOp( "getDFSFileAsText", getDFSFileAsTextSpec.getStr(), 2, getDFSFileAsTextVM, getDFSFileAsTextSelect, getDFSFileAsTextTM ); /* 2.9 Operator ~deleteAllDFSFiles~ */ ListExpr deleteAllDFSFilesTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("don't bother me with arguments"); } return listutils::basicSymbol(); } int deleteAllDFSFilesVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result=qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; if(!filesystem){ res->SetDefined(false); return 0; } try{ filesystem->deleteAllFiles(); res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } OperatorSpec deleteAllDFSFilesSpec( "-> bool", "deleteAllDFSFiles()", "Removes all files from a connected dfs", "query deleteAllDFSFiles() " ); Operator deleteAllDFSFilesOp( "deleteAllDFSFiles", deleteAllDFSFilesSpec.getStr(), deleteAllDFSFilesVM, Operator::SimpleSelect, deleteAllDFSFilesTM ); /* 2.10 Operator ~deleteAllDFSFilesWithCat~ */ ListExpr deleteAllDFSFilesWithCatTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one arg expected"); } if(!CcString::checkType(nl->First(args))){ return listutils::typeError("string expected"); } return listutils::basicSymbol(); } int deleteAllDFSFilesWithCatVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; CcString* Cat = (CcString*) args[0].addr; if(!Cat->IsDefined()){ res->SetDefined(false); return 0; } string cat = Cat->GetValue(); if(!filesystem){ res->Set(true,false); return 0; } try{ filesystem->deleteAllFilesOfCategory(cat.c_str()); res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } OperatorSpec deleteAllDFSFilesWithCatSpec( "string -> bool", "deleteAllDFSFilesWithCat(category)", "Removes all files belonging to a certain category " " from the connected dfs", " query deleteAllDFSFilesWithCat(\"deprecated\")" ); Operator deleteAllDFSFilesWithCatOp( "deleteAllDFSFilesWithCat", deleteAllDFSFilesWithCatSpec.getStr(), deleteAllDFSFilesWithCatVM, Operator::SimpleSelect, deleteAllDFSFilesWithCatTM ); /* 2.11 Operator ~countDFSFiles~ */ ListExpr countDFSFilesTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("what should i do with an argument?"); } return listutils::basicSymbol(); } int countDFSFilesVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcInt* res = (CcInt*) result.addr; if(!filesystem){ res->SetDefined(false); return 0; } try{ res->Set(true, filesystem->countFiles()); } catch(...){ res->SetDefined(false); } return 0; } OperatorSpec countDFSFilesSpec( "-> int", "countDFSFiles()", "Returns the number of files in the connected dfs.", " query countDFSFiles()" ); Operator countDFSFilesOp( "countDFSFiles", countDFSFilesSpec.getStr(), countDFSFilesVM, Operator::SimpleSelect, countDFSFilesTM ); /* 2.12 Operator ~totalDFSSize~ */ ListExpr totalDFSSizeTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("pfui, an argument. put it away!"); } return listutils::basicSymbol(); } int totalDFSSizeVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; if(!filesystem){ res->SetDefined(false); return 0; } try{ res->Set(true, filesystem->totalSize()); } catch(...){ res->SetDefined(false); } return 0; } OperatorSpec totalDFSSizeSpec( "-> int", "totalDFSSize()", "Returns the amount of hdd space aquired by the dfs.", "query totalDFSSize()" ); Operator totalDFSSizeOp( "totalDFSSize", totalDFSSizeSpec.getStr(), totalDFSSizeVM, Operator::SimpleSelect, totalDFSSizeTM ); /* 2.13 Operator ~dfsFileSize~ */ ListExpr dfsFileSizeTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argument expected"); } ListExpr arg = nl->First(args); if(!CcString::checkType(arg) && !FText::checkType(arg)){ return listutils::typeError("string or text expected"); } return listutils::basicSymbol(); } template int dfsFileSizeVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; R* Id = (R*) args[0].addr; if(!Id->IsDefined()){ res->SetDefined(false); return 0; } string id = Id->GetValue(); if(!filesystem){ res->Set(true,-1); return 0; } try{ res->Set(true,filesystem->fileSize(id.c_str())); } catch(...){ res->Set(true,-1); } return 0; } ValueMapping dfsFileSizeVM[] = { dfsFileSizeVMT, dfsFileSizeVMT }; int dfsFileSizeSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec dfsFileSizeSpec( "{string,text} -> bool", "dfsFileSize(name)", "Returns the size of a file stored in a connected dfs.", "query dfsFileSize('myRemoteFile')" ); Operator dfsFileSizeOp( "dfsFileSize", dfsFileSizeSpec.getStr(), 2, dfsFileSizeVM, dfsFileSizeSelect, dfsFileSizeTM ); /* 2.14 Operator ~dfsFileNames~ */ ListExpr dfsFileNamesTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("you are crazy to give me an argument?"); } return nl->TwoElemList(nl->SymbolAtom(Symbols::STREAM()), listutils::basicSymbol()); } class dfsFileNamesInfo{ public: dfsFileNamesInfo(dfs::Filesystem* fs): pos(0){ if(fs){ try{ names = fs->listFileNames(); } catch(...){ } } } FText* next(){ FText* res = pos>=names.size()?0:new FText(true,names[pos]); pos++; return res; } private: size_t pos; vector names; }; int dfsFileNamesVM( Word* args, Word& result, int message, Word& local, Supplier s ){ dfsFileNamesInfo* li = (dfsFileNamesInfo*) local.addr; switch(message){ case OPEN: if(li) delete li; local.addr = new dfsFileNamesInfo(filesystem); return 0; case REQUEST: result.addr = li?li->next():0; return result.addr?YIELD:CANCEL; case CLOSE : if(li){ delete li; local.addr = 0; } return 0; } return -1; } OperatorSpec dfsFileNamesSpec( " -> stream(text)", " dfsFileNames() ", " Feeds the names of all stored files into a stream of text.", " query dfsFileNames() count" ); Operator dfsFileNamesOp( "dfsFileNames", dfsFileNamesSpec.getStr(), dfsFileNamesVM, Operator::SimpleSelect, dfsFileNamesTM ); /* 2.15 Operator ~changeDFSChunkSize~ */ ListExpr changeDFSChunkSizeTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argument expected"); } if(!CcInt::checkType(nl->First(args))){ return listutils::typeError("int expected"); } return listutils::basicSymbol(); } int changeDFSChunkSizeVM( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; CcInt* newSize = (CcInt*) args[0].addr; if(!newSize->IsDefined()){ res->SetDefined(false); return 0; } int ns = newSize->GetValue(); if(ns < 1){ res->SetDefined(false); return 0; } if(!filesystem){ res->Set(true,false); return 0; } try{ filesystem->changeChunkSize(ns); res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } OperatorSpec changeDFSChunkSizeSpec( "int -> bool", "changeDFSChunkSize(newSize)", "Changes the chunk size in a connected dfs.", " query changeDFSChunkSize(4096)" ); Operator changeDFSChunkSizeOp( "changeDFSChunkSize", changeDFSChunkSizeSpec.getStr(), changeDFSChunkSizeVM, Operator::SimpleSelect, changeDFSChunkSizeTM ); #ifdef REMOTE_FILESYSTEM /* 2.16 Operator ~registerDFSDataNode~ */ ListExpr registerDFSDataNodeTM(ListExpr args){ if(!nl->HasLength(args,2)){ return listutils::typeError("2 args required"); } ListExpr arg1 = nl->First(args); if(!CcString::checkType(arg1) && !FText::checkType(arg1)){ return listutils::typeError("string or text expected as the first arg"); } if(!CcInt::checkType(nl->Second(args))){ return listutils::typeError("second arguemnt must be an int"); } return listutils::basicSymbol(); } template int registerDFSDataNodeVMT( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; T* Host = (T*) args[0].addr; CcInt* Port = (CcInt*) args[1].addr; if(!Host->IsDefined() || !Port->IsDefined()){ res->SetDefined(false); return 0; } string host = Host->GetValue(); int port = Port->GetValue(); if(port < 1){ res->SetDefined(false); return 0; } if(!filesystem){ res->SetDefined(false); return 0; } stringstream ss; ss << "dfs-data://"<registerDataNode(uri); res->Set(true,true); } catch(...){ res->Set(true,false); } return 0; } ValueMapping registerDFSDataNodeVM[] = { registerDFSDataNodeVMT, registerDFSDataNodeVMT }; int registerDFSDataNodeSelect(ListExpr args){ return CcString::checkType(nl->First(args))?0:1; } OperatorSpec registerDFSDataNodeSpec( "{string,text} x int -> bool ", "registerDFSDataNode(host, port)", "Registers a new data node to the currently connected dfs.", " query registerDFSDataNode('remotehost', 4445) " ); Operator registerDFSDataNodeOp( "registerDFSDataNode", registerDFSDataNodeSpec.getStr(), 2, registerDFSDataNodeVM, registerDFSDataNodeSelect, registerDFSDataNodeTM ); #endif /* 3 Algebra definition 3.1 Algebra class */ class DFSAlgebra: public Algebra{ public: DFSAlgebra(){ AddOperator(&connectDFSOp); AddOperator(&deleteDFSFileOp); AddOperator(&storeTextAsDFSFileOp); AddOperator(&storeLocalFileToDFSOp); AddOperator(&storeDFSFileOp); AddOperator(&storeDFSFile2Op); AddOperator(&isDFSFileOp); AddOperator(&nextDFSWritePositionOp); AddOperator(&getDFSFileAsTextOp); AddOperator(&deleteAllDFSFilesOp); AddOperator(&deleteAllDFSFilesWithCatOp); AddOperator(&countDFSFilesOp); AddOperator(&totalDFSSizeOp); AddOperator(&dfsFileSizeOp); AddOperator(&dfsFileNamesOp); AddOperator(&changeDFSChunkSizeOp); #ifdef REMOTE_FILESYSTEM AddOperator(®isterDFSDataNodeOp); #endif AddOperator(&disconnectDFSOp); } ~DFSAlgebra(){ if(filesystem){ delete filesystem; filesystem = 0; } if(logger){ delete logger; logger = 0; } } }; } // end of namespace dfsalg /* 3.2 Algebra registration */ extern "C" Algebra* InitializeDFSAlgebra( NestedList* nlRef, QueryProcessor* qpRef, AlgebraManager* amRef ) { return new dfsalg::DFSAlgebra(); }