fileservices.cpp 95 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #pragma warning (disable : 4786)
  15. #pragma warning (disable : 4297) // function assumed not to throw an exception but does
  16. #include "platform.h"
  17. #include "fileservices.hpp"
  18. #include "workunit.hpp"
  19. #include "agentctx.hpp"
  20. #include "jio.hpp"
  21. #include "jmisc.hpp"
  22. #include "daft.hpp"
  23. #include "dasess.hpp"
  24. #include "dautils.hpp"
  25. #include "daaudit.hpp"
  26. #include "dfuwu.hpp"
  27. #include "ws_fs_esp.ipp"
  28. #include "rmtsmtp.hpp"
  29. #include "dfuplus.hpp"
  30. #include "daclient.hpp"
  31. #include "dasds.hpp"
  32. #define USE_DALIDFS
  33. #define SDS_LOCK_TIMEOUT 10000
  34. #define FILESERVICES_VERSION "FILESERVICES 2.1.3"
  35. static const char * compatibleVersions[] = {
  36. "FILESERVICES 2.1 [a68789cfb01d00ef6dc362e52d5eac0e]", // linux version
  37. "FILESERVICES 2.1.1",
  38. "FILESERVICES 2.1.2",
  39. "FILESERVICES 2.1.3",
  40. NULL };
  41. const char * EclDefinition =
  42. "export FsFilenameRecord := record string name{maxlength(1023)}; integer8 size; string19 modified; end; \n"
  43. "export FsLogicalFileName := string{maxlength(255)}; \n"
  44. "export FsLogicalFileNameRecord := record FsLogicalFileName name; end; \n"
  45. "export FsLogicalFileInfoRecord := record(FsLogicalFileNameRecord) boolean superfile; integer8 size; integer8 rowcount; string19 modified; string owner{maxlength(255)}; string cluster{maxlength(255)}; end; \n"
  46. "export FsLogicalSuperSubRecord := record string supername{maxlength(255)}; string subname{maxlength(255)}; end; \n"
  47. "export FsFileRelationshipRecord := record string primaryfile {maxlength(1023)}; string secondaryfile {maxlength(1023)}; string primaryflds {maxlength(1023)}; string secondaryflds {maxlength(1023)}; string kind {maxlength(16)}; string cardinality {maxlength(16)}; boolean payload; string description {maxlength(1023)}; end; \n"
  48. "export integer4 RECFMV_RECSIZE := -2; // special value for SprayFixed record size \n"
  49. "export integer4 RECFMVB_RECSIZE := -1; // special value for SprayFixed record size \n"
  50. "export integer4 PREFIX_VARIABLE_RECSIZE := -3; // special value for SprayFixed record size \n"
  51. "export integer4 PREFIX_VARIABLE_BIGENDIAN_RECSIZE := -4; // special value for SprayFixed record size \n"
  52. "export FileServices := SERVICE\n"
  53. " boolean FileExists(const varstring lfn, boolean physical=false) : c,context,entrypoint='fsFileExists'; \n"
  54. " DeleteLogicalFile(const varstring lfn,boolean ifexists=false) : c,action,context,entrypoint='fsDeleteLogicalFile'; \n"
  55. " SetReadOnly(const varstring lfn, boolean ro) : c,action,context,entrypoint='fsSetReadOnly'; \n"
  56. " RenameLogicalFile(const varstring oldname, const varstring newname) : c,action,context,entrypoint='fsRenameLogicalFile'; \n"
  57. " varstring GetBuildInfo() : c,pure,entrypoint='fsGetBuildInfo';\n"
  58. " SendEmail(const varstring to, const varstring subject, const varstring body, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress')) : c,action,context,entrypoint='fsSendEmail'; \n"
  59. " SendEmailAttachText(const varstring to, const varstring subject, const varstring body, const varstring attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress')) : c,action,context,entrypoint='fsSendEmailAttachText'; \n"
  60. " SendEmailAttachData(const varstring to, const varstring subject, const varstring body, const data attachment, const varstring mimeType, const varstring attachmentName, const varstring mailServer=GETENV('SMTPserver'), unsigned4 port=(unsigned4) GETENV('SMTPport', '25'), const varstring sender=GETENV('emailSenderAddress')) : c,action,context,entrypoint='fsSendEmailAttachData'; \n"
  61. " varstring CmdProcess(const varstring prog, const varstring src) : c,action,entrypoint='fsCmdProcess'; \n"
  62. " string CmdProcess2(const varstring prog, const string src) : c,action,entrypoint='fsCmdProcess2'; \n"
  63. " SprayFixed(const varstring sourceIP, const varstring sourcePath, integer4 recordSize, const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false) : c,action,context,entrypoint='fsSprayFixed'; \n"
  64. " SprayVariable(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceCsvSeparate='\\\\,', const varstring sourceCsvTerminate='\\\\n,\\\\r\\\\n', const varstring sourceCsvQuote='\\'', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false) : c,action,context,entrypoint='fsSprayVariable'; \n"
  65. " SprayXml(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowTag, const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false,boolean compress=false) : c,action,context,entrypoint='fsSprayXml'; \n"
  66. " Despray(const varstring logicalName, const varstring destinationIP, const varstring destinationPath, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false) : c,action,context,entrypoint='fsDespray'; \n"
  67. " Copy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0) : c,action,context,entrypoint='fsCopy'; \n"
  68. " Replicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsReplicate'; \n"
  69. " CreateSuperFile(const varstring lsuperfn, boolean sequentialparts=false,boolean ifdoesnotexist=false) : c,action,context,entrypoint='fsCreateSuperFile'; \n"
  70. " boolean SuperFileExists(const varstring lsuperfn) : c,context,entrypoint='fsSuperFileExists'; \n"
  71. " DeleteSuperFile(const varstring lsuperfn,boolean deletesub=false) : c,action,context,entrypoint='fsDeleteSuperFile'; \n"
  72. " unsigned4 GetSuperFileSubCount(const varstring lsuperfn) : c,context,entrypoint='fsGetSuperFileSubCount'; \n"
  73. " varstring GetSuperFileSubName(const varstring lsuperfn,unsigned4 filenum,boolean abspath=false) : c,context,entrypoint='fsGetSuperFileSubName'; \n"
  74. " unsigned4 FindSuperFileSubName(const varstring lsuperfn,const varstring lfn) : c,context,entrypoint='fsFindSuperFileSubName'; \n"
  75. " StartSuperFileTransaction() : c,action,globalcontext,entrypoint='fsStartSuperFileTransaction'; \n"
  76. " AddSuperFile(const varstring lsuperfn,const varstring lfn,unsigned4 atpos=0,boolean addcontents=false, boolean strict=false) : c,action,globalcontext,entrypoint='fsAddSuperFile'; \n"
  77. " RemoveSuperFile(const varstring lsuperfn,const varstring lfn,boolean del=false,boolean remcontents=false) : c,action,globalcontext,entrypoint='fsRemoveSuperFile'; \n"
  78. " ClearSuperFile(const varstring lsuperfn,boolean del=false) : c,action,globalcontext,entrypoint='fsClearSuperFile'; \n"
  79. " SwapSuperFile(const varstring lsuperfn1,const varstring lsuperfn2) : c,action,globalcontext,entrypoint='fsSwapSuperFile'; \n"
  80. " ReplaceSuperFile(const varstring lsuperfn,const varstring lfn,const varstring bylfn) : c,action,globalcontext,entrypoint='fsReplaceSuperFile'; \n"
  81. " FinishSuperFileTransaction(boolean rollback=false) : c,action,globalcontext,entrypoint='fsFinishSuperFileTransaction'; \n"
  82. " varstring ForeignLogicalFileName(const varstring name, const varstring foreigndali='', boolean abspath=false) : c,context,entrypoint='fsForeignLogicalFileName'; \n"
  83. " varstring WaitDfuWorkunit(const varstring wuid, integer4 timeOut=-1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,globalcontext,entrypoint='fsWaitDfuWorkunit'; \n"
  84. " AbortDfuWorkunit(const varstring wuid,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,globalcontext,entrypoint='fsAbortDfuWorkunit'; \n"
  85. " MonitorLogicalFileName(const varstring eventname, const varstring name, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsMonitorLogicalFileName'; \n"
  86. " MonitorFile(const varstring eventname, const varstring ip, const varstring filename, boolean subdirs=false, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsMonitorFile'; \n"
  87. " varstring fSprayFixed(const varstring sourceIP, const varstring sourcePath, integer4 recordSize, const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean compress=false) : c,action,context,entrypoint='fsfSprayFixed'; \n"
  88. " varstring fSprayVariable(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceCsvSeparate='\\\\,', const varstring sourceCsvTerminate='\\\\n,\\\\r\\\\n', const varstring sourceCsvQuote='\\'', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean compress=false) : c,action,context,entrypoint='fsfSprayVariable'; \n"
  89. " varstring fSprayXml(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowTag, const varstring sourceEncoding='utf8', const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean compress=false) : c,action,context,entrypoint='fsfSprayXml'; \n"
  90. " varstring fDespray(const varstring logicalName, const varstring destinationIP, const varstring destinationPath, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false) : c,action,context,entrypoint='fsfDespray'; \n"
  91. " varstring fCopy(const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, const varstring sourceDali='', integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server'), integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false, boolean compress=false, boolean forcePush=false, integer4 transferBufferSize=0) : c,action,context,entrypoint='fsfCopy'; \n"
  92. " varstring fMonitorLogicalFileName(const varstring eventname, const varstring name, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfMonitorLogicalFileName'; \n"
  93. " varstring fMonitorFile(const varstring eventname, const varstring ip, const varstring filename, boolean subdirs=false, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfMonitorFile'; \n"
  94. " varstring fReplicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfReplicate'; \n"
  95. " varstring GetFileDescription(const varstring lfn) : c,context,entrypoint='fsGetFileDescription'; \n"
  96. " SetFileDescription(const varstring lfn,const varstring val) : c,action,context,entrypoint='fsSetFileDescription'; \n"
  97. " dataset(FsFilenameRecord) RemoteDirectory(const varstring machineIP,const varstring dir,const varstring mask='*',boolean sub=false) : c,entrypoint='fsRemoteDirectory';\n"
  98. " dataset(FsLogicalFileInfoRecord) LogicalFileList(const varstring namepattern='*',boolean includenormal=true,boolean includesuper=false,boolean unknownszero=false,const varstring foreigndali='') : c,context,entrypoint='fsLogicalFileList';\n"
  99. " dataset(FsLogicalFileNameRecord) SuperFileContents(const varstring lsuperfn,boolean recurse=false) : c,context,entrypoint='fsSuperFileContents';\n"
  100. " dataset(FsLogicalFileNameRecord) LogicalFileSuperOwners(const varstring lfn) : c,context,entrypoint='fsLogicalFileSuperOwners';\n"
  101. " varstring ExternalLogicalFileName(const varstring location, const varstring path,boolean abspath=true) : c,entrypoint='fsExternalLogicalFileName'; \n"
  102. " integer4 CompareFiles(const varstring lfn1, const varstring lfn2,boolean logicalonly=true,boolean usecrcs=false) : c,context,entrypoint='fsCompareFiles'; \n"
  103. " varstring VerifyFile(const varstring lfn, boolean usecrcs) : c,action,context,entrypoint='fsVerifyFile'; \n"
  104. " RemotePull( const varstring remoteEspFsURL, const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false,boolean forcePush=false, integer4 transferBufferSize=0,boolean wrap=false,boolean compress=false): c,action,context,entrypoint='fsRemotePull'; \n"
  105. " varstring fRemotePull( const varstring remoteEspFsURL, const varstring sourceLogicalName, const varstring destinationGroup, const varstring destinationLogicalName, integer4 timeOut=-1, integer4 maxConnections=-1, boolean allowoverwrite=false, boolean replicate=false, boolean asSuperfile=false,boolean forcePush=false, integer4 transferBufferSize=0,boolean wrap=false,boolean compress=false): c,action,context,entrypoint='fsfRemotePull'; \n"
  106. " dataset(FsLogicalSuperSubRecord) LogicalFileSuperSubList() : c,context,entrypoint='fsLogicalFileSuperSubList';\n"
  107. " PromoteSuperFileList(const set of varstring lsuperfns,const varstring addhead='',boolean deltail=false,boolean createonlyonesuperfile=false,boolean reverse=false) : c,action,context,entrypoint='fsPromoteSuperFileList'; \n"
  108. " varstring fPromoteSuperFileList(const set of varstring lsuperfns,const varstring addhead='', boolean deltail=false,boolean createonlyonesuperfile=false, boolean reverse=false) : c,action,context,entrypoint='fsfPromoteSuperFileList'; \n"
  109. " unsigned8 getUniqueInteger(const varstring foreigndali='') : c,entrypoint='fsGetUniqueInteger'; \n"
  110. " AddFileRelationship(const varstring primary, const varstring secondary, const varstring primaryflds, const varstring secondaryflds, const varstring kind='link', const varstring cardinality, boolean payload, const varstring description='') : c,action,context,entrypoint='fsAddFileRelationship'; \n"
  111. " dataset(FsFileRelationshipRecord) FileRelationshipList(const varstring primary, const varstring secondary, const varstring primflds='', const varstring secondaryflds='', const varstring kind='link') : c,action,context,entrypoint='fsFileRelationshipList'; \n"
  112. " RemoveFileRelationship(const varstring primary, const varstring secondary, const varstring primaryflds='', const varstring secondaryflds='', const varstring kind='link') : c,action,context,entrypoint='fsRemoveFileRelationship'; \n"
  113. " varstring GetColumnMapping( const varstring LogicalFileName): c,context,entrypoint='fsfGetColumnMapping'; \n"
  114. " SetColumnMapping( const varstring LogicalFileName, const varstring mapping): c,context,entrypoint='fsSetColumnMapping'; \n"
  115. " varstring RfsQuery( const varstring server, const varstring query): c,entrypoint='fsfRfsQuery'; \n"
  116. " RfsAction( const varstring server, const varstring query): c,entrypoint='fsRfsAction'; \n"
  117. " varstring GetHostName( const varstring ipaddress ): c,entrypoint='fsfGetHostName'; \n"
  118. " varstring ResolveHostName( const varstring hostname ): c,entrypoint='fsfResolveHostName'; \n"
  119. " MoveExternalFile(const varstring location, const varstring frompath, const varstring topath): c,action,context,entrypoint='fsMoveExternalFile'; \n"
  120. " DeleteExternalFile(const varstring location, const varstring path): c,action,context,entrypoint='fsDeleteExternalFile'; \n"
  121. " CreateExternalDirectory(const varstring location, const varstring path): c,action,context,entrypoint='fsCreateExternalDirectory'; \n"
  122. " varstring GetLogicalFileAttribute(const varstring lfn,const varstring attrname) : c,context,entrypoint='fsfGetLogicalFileAttribute'; \n"
  123. " ProtectLogicalFile(const varstring lfn,boolean set=true) : c,context,entrypoint='fsProtectLogicalFile'; \n"
  124. " DfuPlusExec(const varstring cmdline) : c,context,entrypoint='fsDfuPlusExec'; \n"
  125. "END;";
  126. #define WAIT_SECONDS 30
  127. FILESERVICES_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  128. {
  129. if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
  130. {
  131. ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
  132. pbx->compatibleVersions = compatibleVersions;
  133. }
  134. else if (pb->size != sizeof(ECLPluginDefinitionBlock))
  135. return false;
  136. pb->magicVersion = PLUGIN_VERSION;
  137. pb->version = FILESERVICES_VERSION;
  138. pb->moduleName = "lib_fileservices";
  139. pb->ECL = EclDefinition;
  140. pb->flags = PLUGIN_IMPLICIT_MODULE;
  141. pb->description = "FileServices library";
  142. return true;
  143. }
  144. namespace nsFileservices {
  145. IPluginContext * parentCtx = NULL;
  146. static IConstWorkUnit * getWorkunit(ICodeContext * ctx)
  147. {
  148. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  149. StringAttr wuid;
  150. wuid.setown(ctx->getWuid());
  151. return factory->openWorkUnit(wuid, false);
  152. }
  153. static IWorkUnit * updateWorkunit(ICodeContext * ctx)
  154. {
  155. // following bit of a kludge, as
  156. // 1) eclagent keeps WU locked, and
  157. // 2) rtti not available in generated .so's to convert to IAgentContext
  158. IAgentContext * actx = dynamic_cast<IAgentContext *>(ctx);
  159. if (actx == NULL) { // fall back to pure ICodeContext
  160. // the following works for thor only
  161. char * platform = ctx->getPlatform();
  162. if (strcmp(platform,"thor")==0) {
  163. CTXFREE(parentCtx, platform);
  164. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  165. StringAttr wuid;
  166. wuid.setown(ctx->getWuid());
  167. return factory->updateWorkUnit(wuid);
  168. }
  169. CTXFREE(parentCtx, platform);
  170. return NULL;
  171. }
  172. return actx->updateWorkUnit();
  173. }
  174. static IPropertyTree *getEnvironment()
  175. {
  176. Owned<IPropertyTree> env;
  177. if (daliClientActive()) {
  178. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  179. if (conn)
  180. env.setown(createPTreeFromIPT(conn->queryRoot())); // we don't really need to copy here
  181. }
  182. if (!env.get())
  183. env.setown(getHPCCenvironment());
  184. return env.getClear();
  185. }
  186. static const char *getEspServerURL(const char *param)
  187. {
  188. if (param&&*param)
  189. return param;
  190. static StringAttr espurl;
  191. if (espurl.isEmpty()) {
  192. Owned<IPropertyTree> env = getEnvironment();
  193. StringBuffer tmp;
  194. if (env.get()) {
  195. Owned<IPropertyTreeIterator> iter1 = env->getElements("Software/EspProcess");
  196. ForEach(*iter1) {
  197. Owned<IPropertyTreeIterator> iter2 = iter1->query().getElements("EspBinding");
  198. ForEach(*iter2) {
  199. Owned<IPropertyTreeIterator> iter3 = iter2->query().getElements("AuthenticateFeature");
  200. ForEach(*iter3) {
  201. // if any enabled feature has service ws_fs then use this binding
  202. if (iter3->query().getPropBool("@authenticate")&&
  203. iter3->query().getProp("@service",tmp.clear())&&
  204. (strcmp(tmp.str(),"ws_fs")==0)) {
  205. if (iter2->query().getProp("@protocol",tmp.clear())) {
  206. tmp.append("://");
  207. StringBuffer espname;
  208. if (iter1->query().getProp("@name",espname)) {
  209. StringBuffer espinst;
  210. if (iter1->query().getProp("Instance[1]/@computer",espinst)) {
  211. StringBuffer ipq;
  212. if (env->getProp(ipq.appendf("Hardware/Computer[@name=\"%s\"]/@netAddress",espinst.str()).str(),tmp)) {
  213. tmp.append(':').append(iter2->query().getPropInt("@port",8010)).append("/FileSpray"); // FileSpray seems to be fixed
  214. espurl.set(tmp);
  215. PROGLOG("fileservices using esp URL: %s",espurl.get());
  216. break;
  217. }
  218. }
  219. }
  220. }
  221. }
  222. }
  223. if (!espurl.isEmpty())
  224. break;
  225. }
  226. if (!espurl.isEmpty())
  227. break;
  228. }
  229. }
  230. }
  231. if (espurl.isEmpty())
  232. throw MakeStringException(-1,"Cannot determine ESP Url");
  233. return espurl.get();
  234. }
  235. StringBuffer & constructLogicalName(IConstWorkUnit * wu, const char * partialLogicalName, StringBuffer & result)
  236. {
  237. if (partialLogicalName == NULL)
  238. throw MakeStringException(0, "Logical Name Cannot be blank");
  239. if (*partialLogicalName == '~')
  240. ++partialLogicalName;
  241. else
  242. {
  243. StringBuffer prefix;
  244. wu->getScope(StringBufferAdaptor(prefix));
  245. if (prefix.length())
  246. result.append(prefix).append("::");
  247. }
  248. result.append(partialLogicalName);
  249. if ((result.length()>0)&&(strstr(result.str(),"::")==NULL)&&(result.charAt(0)!='#'))
  250. result.insert(0,".::");
  251. return result;
  252. }
  253. StringBuffer & constructLogicalName(ICodeContext * ctx, const char * partialLogicalName, StringBuffer & result)
  254. {
  255. Owned<IConstWorkUnit> wu;
  256. if (partialLogicalName&&(*partialLogicalName != '~'))
  257. wu.setown(getWorkunit(ctx));
  258. return constructLogicalName(wu, partialLogicalName, result);
  259. }
  260. static void WUmessage(ICodeContext *ctx, WUExceptionSeverity sev, const char *fn, const char *msg)
  261. {
  262. StringBuffer s;
  263. s.append("fileservices");
  264. if (fn)
  265. s.append(", ").append(fn);
  266. IAgentContext * actx = dynamic_cast<IAgentContext *>(ctx); // doesn't work if called from helper .so (no rtti)
  267. if (actx)
  268. actx->addWuException(msg,0,sev,s.str());
  269. else {
  270. Owned<IWorkUnit> wu = updateWorkunit(ctx);
  271. if (wu.get()) {
  272. Owned<IWUException> we = wu->createException();
  273. we->setSeverity(sev);
  274. we->setExceptionMessage(msg);
  275. we->setExceptionSource(s.str());
  276. }
  277. else {
  278. s.append(" : ").append(msg);
  279. ctx->addWuException(s.str(),0,sev); // use plain code context
  280. }
  281. }
  282. }
  283. static void AuditMessage(ICodeContext *ctx,
  284. const char *func,
  285. const char *lfn1,
  286. const char *lfn2=NULL)
  287. {
  288. // FileServices,WUID,user,function,LFN1,LFN2
  289. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  290. StringBuffer aln;
  291. StringAttr wuid;
  292. wuid.setown(ctx->getWuid());
  293. aln.append(",FileAccess,FileServices,").append(func).append(',').append(wuid).append(',');
  294. if (udesc)
  295. udesc->getUserName(aln);
  296. if (lfn1&&*lfn1) {
  297. aln.append(',').append(lfn1);
  298. if (lfn2&&*lfn2) {
  299. aln.append(',').append(lfn2);
  300. }
  301. }
  302. LOG(daliAuditLogCat,"%s",aln.str());
  303. }
  304. }//namespace
  305. using namespace nsFileservices;
  306. FILESERVICES_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
  307. FILESERVICES_API char * FILESERVICES_CALL fsGetBuildInfo(void)
  308. {
  309. return CTXSTRDUP(parentCtx, FILESERVICES_VERSION);
  310. }
  311. //-------------------------------------------------------------------------------------------------------------------------------------------
  312. FILESERVICES_API void FILESERVICES_CALL fsDeleteLogicalFile(ICodeContext *ctx, const char *name,bool ifexists)
  313. {
  314. StringBuffer lfn;
  315. constructLogicalName(ctx, name, lfn);
  316. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  317. StringBuffer uname;
  318. PrintLog("Deleting NS logical file %s for user %s", lfn.str(),udesc?udesc->getUserName(uname).str():"");
  319. if (queryDistributedFileDirectory().removePhysical(lfn.str(),0,NULL,NULL,udesc))
  320. {
  321. StringBuffer s("DeleteLogicalFile ('"); // ** TBD use removephysical (handles cluster)
  322. s.append(lfn).append("') done");
  323. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  324. AuditMessage(ctx,"DeleteLogicalFile",lfn.str());
  325. }
  326. else if (!ifexists) {
  327. throw MakeStringException(0, "Could not delete file %s", lfn.str());
  328. }
  329. }
  330. FILESERVICES_API bool FILESERVICES_CALL fsFileExists(ICodeContext *ctx, const char *name, bool physical)
  331. {
  332. StringBuffer lfn;
  333. constructLogicalName(ctx, name, lfn);
  334. if (physical)
  335. return queryDistributedFileDirectory().existsPhysical(lfn.str(),ctx->queryUserDescriptor());
  336. return queryDistributedFileDirectory().exists(lfn.str(),false,false,ctx->queryUserDescriptor());
  337. }
  338. FILESERVICES_API bool FILESERVICES_CALL fsFileValidate(ICodeContext *ctx, const char *name)
  339. {
  340. StringBuffer lfn;
  341. constructLogicalName(ctx, name, lfn);
  342. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  343. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  344. if (df)
  345. {
  346. Owned<IDistributedFilePartIterator> partIter = df->getIterator();
  347. ForEach(*partIter)
  348. {
  349. IDistributedFilePart & part = partIter->query();
  350. unsigned numCopies = part.numCopies();
  351. bool gotone = false;
  352. offset_t partSize;
  353. for (unsigned copy=0; copy < numCopies; copy++)
  354. {
  355. RemoteFilename remote;
  356. part.getFilename(remote,copy);
  357. OwnedIFile file = createIFile(remote);
  358. if (file->exists())
  359. {
  360. offset_t thisSize = file->size();
  361. if (gotone && (partSize != thisSize))
  362. throw MakeStringException(0, "Inconsistent file sizes for %s", lfn.str());
  363. partSize = thisSize;
  364. gotone = true;
  365. }
  366. }
  367. if (!gotone)
  368. return false;
  369. }
  370. return true;
  371. }
  372. return false;
  373. }
  374. FILESERVICES_API void FILESERVICES_CALL fsSetReadOnly(ICodeContext *ctx, const char *name, bool ro)
  375. {
  376. StringBuffer lfn;
  377. constructLogicalName(ctx, name, lfn);
  378. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  379. Owned<IException> error;
  380. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, true);
  381. if (df)
  382. {
  383. Owned<IDistributedFilePartIterator> partIter = df->getIterator();
  384. ForEach(*partIter)
  385. {
  386. IDistributedFilePart & part = partIter->query();
  387. unsigned numCopies = part.numCopies();
  388. for (unsigned copy=0; copy < numCopies; copy++)
  389. {
  390. RemoteFilename remote;
  391. part.getFilename(remote,copy);
  392. OwnedIFile file = createIFile(remote);
  393. try
  394. {
  395. file->setReadOnly(ro);
  396. }
  397. catch (IException * e)
  398. {
  399. EXCLOG(e);
  400. e->Release();
  401. }
  402. }
  403. }
  404. return;
  405. }
  406. if (!error)
  407. error.setown(MakeStringException(0, "Could not find logical file %s", lfn.str()));
  408. throw error.getClear();
  409. }
  410. FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile(ICodeContext *ctx, const char *oldname, const char *newname)
  411. {
  412. StringBuffer lfn, nlfn;
  413. constructLogicalName(ctx, oldname, lfn);
  414. constructLogicalName(ctx, newname, nlfn);
  415. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  416. Owned<IMultiException> exceptions = MakeMultiException();
  417. if (queryDistributedFileDirectory().renamePhysical(lfn.str(),nlfn.str(),0,exceptions,udesc)) {
  418. StringBuffer s("RenameLogicalFile ('");
  419. s.append(lfn).append(", '").append(nlfn).append("') done");
  420. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  421. AuditMessage(ctx,"RenameLogicalFile",lfn.str(),nlfn.str());
  422. }
  423. else { // failed
  424. unsigned n = exceptions->ordinality();
  425. for (unsigned i=0;i<n;i++) {
  426. StringBuffer s;
  427. exceptions->item(i).errorMessage(s);
  428. WUmessage(ctx,ExceptionSeverityWarning,"RenameLogicalFile",s.str());
  429. }
  430. throw MakeStringException(0, "Could not rename logical file %s to %s", lfn.str(), nlfn.str());
  431. }
  432. }
  433. FILESERVICES_API void FILESERVICES_CALL fsSendEmail(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender)
  434. {
  435. StringArray warnings;
  436. sendEmail( to, subject, body, mailServer, port, sender, &warnings);
  437. ForEachItemIn(i,warnings)
  438. WUmessage(ctx, ExceptionSeverityWarning, "SendEmail", warnings.item(i));
  439. }
  440. FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender)
  441. {
  442. StringArray warnings;
  443. sendEmailAttachText(to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings);
  444. ForEachItemIn(i,warnings)
  445. WUmessage(ctx, ExceptionSeverityWarning, "SendEmailAttachText", warnings.item(i));
  446. }
  447. FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData(ICodeContext * ctx, const char * to, const char * subject, const char * body, size32_t lenAttachment, const void * attachment, const char * mimeType, const char * attachmentName, const char * mailServer, unsigned int port, const char * sender)
  448. {
  449. StringArray warnings;
  450. sendEmailAttachData(to, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings);
  451. ForEachItemIn(i,warnings)
  452. WUmessage(ctx, ExceptionSeverityWarning, "SendEmailAttachData", warnings.item(i));
  453. }
  454. FILESERVICES_API char * FILESERVICES_CALL fsCmdProcess(const char *prog, const char *src)
  455. {
  456. StringBuffer in, out;
  457. in.append(src);
  458. callExternalProgram(prog, in, out);
  459. return CTXSTRDUP(parentCtx, out.str());
  460. }
  461. FILESERVICES_API void FILESERVICES_CALL fsCmdProcess2(unsigned & tgtLen, char * & tgt, const char *prog, unsigned srcLen, const char * src)
  462. {
  463. StringBuffer in, out;
  464. in.append(srcLen, src);
  465. callExternalProgram(prog, in, out);
  466. tgtLen = out.length();
  467. tgt = (char *)CTXDUP(parentCtx, out.str(), out.length());
  468. }
  469. static void blockUntilComplete(const char * label, IClientFileSpray &server, ICodeContext *ctx, const char * wuid, int timeOut, StringBuffer *stateout=NULL, bool monitoringok=false)
  470. {
  471. if (!wuid || strcmp(wuid, "") == 0)
  472. return;
  473. if (timeOut == 0)
  474. return;
  475. CTimeMon time(timeOut);
  476. unsigned polltime = 1;
  477. while(true)
  478. {
  479. Owned<IWorkUnit> wu = updateWorkunit(ctx); // may return NULL
  480. Owned<IClientGetDFUWorkunit> req = server.createGetDFUWorkunitRequest();
  481. req->setWuid(wuid);
  482. Linked<IClientGetDFUWorkunitResponse> result = server.GetDFUWorkunit(req);
  483. const IMultiException* excep = &result->getExceptions();
  484. if(excep != NULL && excep->ordinality() > 0)
  485. {
  486. StringBuffer errmsg;
  487. excep->errorMessage(errmsg);
  488. throw MakeStringException(0, "%s", errmsg.str());
  489. }
  490. IConstDFUWorkunit & dfuwu = result->getResult();
  491. if (wu.get()) { // if updatable (e.g. not hthor with no agent context)
  492. StringBuffer ElapsedLabel, RemainingLabel;
  493. ElapsedLabel.appendf("%s-%s (Elapsed) ", label, dfuwu.getID());
  494. RemainingLabel.appendf("%s-%s (Remaining) ", label, dfuwu.getID());
  495. wu->setTimerInfo(ElapsedLabel.str(), "", time.elapsed(), 1, 0);
  496. wu->setTimerInfo(RemainingLabel.str(), "", dfuwu.getSecsLeft()*1000, 1, 0);
  497. wu->setApplicationValue(label, dfuwu.getID(), dfuwu.getSummaryMessage(), true);
  498. wu->commit();
  499. }
  500. DFUstate state = (DFUstate)dfuwu.getState();
  501. if (stateout)
  502. stateout->clear().append(dfuwu.getStateMessage());
  503. switch(state)
  504. {
  505. case DFUstate_unknown:
  506. case DFUstate_scheduled:
  507. case DFUstate_queued:
  508. case DFUstate_started:
  509. case DFUstate_aborting:
  510. break;
  511. case DFUstate_monitoring:
  512. if (monitoringok)
  513. return;
  514. break;
  515. case DFUstate_aborted:
  516. case DFUstate_failed:
  517. throw MakeStringException(0, "DFUServer Error %s", dfuwu.getSummaryMessage());
  518. return;
  519. case DFUstate_finished:
  520. return;
  521. }
  522. if (wu.get()&&wu->aborting())
  523. {
  524. Owned<IClientAbortDFUWorkunit> abortReq = server.createAbortDFUWorkunitRequest();
  525. abortReq->setWuid(wuid);
  526. Linked<IClientAbortDFUWorkunitResponse> abortResp = server.AbortDFUWorkunit(abortReq);
  527. { // Add warning of DFU Abort Request - should this be information ---
  528. StringBuffer s("DFU Workunit Abort Requested for ");
  529. s.append(wuid);
  530. WUmessage(ctx,ExceptionSeverityWarning,"blockUntilComplete",s.str());
  531. }
  532. wu->setState(WUStateAborting);
  533. throw MakeStringException(0, "Workunit abort request received");
  534. }
  535. wu.clear();
  536. if (time.timedout()) {
  537. unsigned left = dfuwu.getSecsLeft();
  538. if (left)
  539. throw MakeStringException(0, "%s timed out, DFU Secs left: %d)", label, left);
  540. throw MakeStringException(0, "%s timed out)", label);
  541. }
  542. Sleep(polltime*1000);
  543. polltime *= 2;
  544. if (polltime>WAIT_SECONDS)
  545. polltime = WAIT_SECONDS;
  546. }
  547. }
  548. static void setServerAccess(CClientFileSpray &server, IConstWorkUnit * wu)
  549. {
  550. StringBuffer user, password, wuid, token;
  551. wu->getSecurityToken(StringBufferAdaptor(token));
  552. wu->getWuid(StringBufferAdaptor(wuid));
  553. extractToken(token.str(), wuid.str(), StringBufferAdaptor(user), StringBufferAdaptor(password));
  554. server.setUsernameToken(user.str(), password.str(), "");
  555. }
  556. FILESERVICES_API void FILESERVICES_CALL fsSprayFixed(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int recordSize, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  557. {
  558. CTXFREE(parentCtx, fsfSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress));
  559. }
  560. FILESERVICES_API char * FILESERVICES_CALL fsfSprayFixed(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int recordSize, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  561. {
  562. PrintLog("Spray: %s", destinationLogicalName);
  563. CClientFileSpray server;
  564. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  565. server.addServiceUrl(getEspServerURL(espServerIpPort));
  566. setServerAccess(server, wu);
  567. Owned<IClientSprayFixed> req = server.createSprayFixedRequest();
  568. StringBuffer logicalName;
  569. constructLogicalName(wu, destinationLogicalName, logicalName);
  570. req->setSourceIP(sourceIP);
  571. req->setSourcePath(sourcePath);
  572. req->setSourceRecordSize(recordSize);
  573. req->setDestGroup(destinationGroup);
  574. req->setDestLogicalName(logicalName.str());
  575. req->setOverwrite(overwrite);
  576. req->setReplicate(replicate);
  577. req->setCompress(compress);
  578. Owned<IClientSprayFixedResponse> result = server.SprayFixed(req);
  579. StringBuffer wuid(result->getWuid());
  580. if(!wuid.length())
  581. {
  582. const IMultiException* excep = &result->getExceptions();
  583. if(excep != NULL && excep->ordinality() > 0)
  584. {
  585. StringBuffer errmsg;
  586. excep->errorMessage(errmsg);
  587. throw MakeStringException(0, "%s", errmsg.str());
  588. }
  589. else
  590. {
  591. throw MakeStringException(0, "Result's dfu WUID is empty");
  592. }
  593. }
  594. wu.clear();
  595. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  596. return wuid.detach();
  597. }
  598. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char * sourceCsvSeparate, const char * sourceCsvTerminate, const char * sourceCsvQuote, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  599. {
  600. CTXFREE(parentCtx, fsfSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress));
  601. }
  602. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char * sourceCsvSeparate, const char * sourceCsvTerminate, const char * sourceCsvQuote, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  603. {
  604. PrintLog("Spray: %s", destinationLogicalName);
  605. CClientFileSpray server;
  606. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  607. server.addServiceUrl(getEspServerURL(espServerIpPort));
  608. setServerAccess(server, wu);
  609. Owned<IClientSprayVariable> req = server.createSprayVariableRequest();
  610. StringBuffer logicalName;
  611. constructLogicalName(wu, destinationLogicalName, logicalName);
  612. req->setSourceIP(sourceIP);
  613. req->setSourcePath(sourcePath);
  614. req->setSourceMaxRecordSize(sourceMaxRecordSize);
  615. req->setSourceFormat(DFUff_csv);
  616. req->setSourceCsvSeparate(sourceCsvSeparate);
  617. req->setSourceCsvTerminate(sourceCsvTerminate);
  618. req->setSourceCsvQuote(sourceCsvQuote);
  619. req->setDestGroup(destinationGroup);
  620. req->setDestLogicalName(logicalName.str());
  621. req->setOverwrite(overwrite);
  622. req->setReplicate(replicate);
  623. req->setCompress(compress);
  624. Owned<IClientSprayResponse> result = server.SprayVariable(req);
  625. StringBuffer wuid(result->getWuid());
  626. if(!wuid.length())
  627. {
  628. const IMultiException* excep = &result->getExceptions();
  629. if(excep != NULL && excep->ordinality() > 0)
  630. {
  631. StringBuffer errmsg;
  632. excep->errorMessage(errmsg);
  633. throw MakeStringException(0, "%s", errmsg.str());
  634. }
  635. else
  636. {
  637. throw MakeStringException(0, "Result's dfu WUID is empty");
  638. }
  639. }
  640. wu.clear();
  641. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  642. return wuid.detach();
  643. }
  644. FILESERVICES_API void FILESERVICES_CALL fsSprayXml(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char *sourceRowTag, const char *sourceEncoding, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  645. {
  646. CTXFREE(parentCtx, fsfSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress));
  647. }
  648. FILESERVICES_API char * FILESERVICES_CALL fsfSprayXml(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char *sourceRowTag, const char *sourceEncoding, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress)
  649. {
  650. PrintLog("Spray: %s", destinationLogicalName);
  651. CClientFileSpray server;
  652. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  653. server.addServiceUrl(getEspServerURL(espServerIpPort));
  654. setServerAccess(server, wu);
  655. Owned<IClientSprayVariable> req = server.createSprayVariableRequest();
  656. StringBuffer logicalName;
  657. constructLogicalName(wu, destinationLogicalName, logicalName);
  658. DFUfileformat dfufmt;
  659. if(sourceEncoding == NULL)
  660. dfufmt = DFUff_utf8;
  661. else
  662. dfufmt = CDFUfileformat::decode(sourceEncoding);
  663. req->setSourceIP(sourceIP);
  664. req->setSourcePath(sourcePath);
  665. req->setSourceMaxRecordSize(sourceMaxRecordSize);
  666. req->setSourceFormat(dfufmt);
  667. req->setSourceRowTag(sourceRowTag);
  668. req->setDestGroup(destinationGroup);
  669. req->setDestLogicalName(logicalName.str());
  670. req->setOverwrite(overwrite);
  671. req->setReplicate(replicate);
  672. req->setCompress(compress);
  673. Owned<IClientSprayResponse> result = server.SprayVariable(req);
  674. StringBuffer wuid(result->getWuid());
  675. if(!wuid.length())
  676. {
  677. const IMultiException* excep = &result->getExceptions();
  678. if(excep != NULL && excep->ordinality() > 0)
  679. {
  680. StringBuffer errmsg;
  681. excep->errorMessage(errmsg);
  682. throw MakeStringException(0, "%s", errmsg.str());
  683. }
  684. else
  685. {
  686. throw MakeStringException(0, "Result's dfu WUID is empty");
  687. }
  688. }
  689. wu.clear();
  690. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  691. return wuid.detach();
  692. }
  693. FILESERVICES_API void FILESERVICES_CALL fsDespray(ICodeContext *ctx, const char * sourceLogicalName, const char * destinationIP, const char * destinationPath, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite)
  694. {
  695. CTXFREE(parentCtx, fsfDespray(ctx, sourceLogicalName, destinationIP, destinationPath, timeOut, espServerIpPort, maxConnections, overwrite));
  696. }
  697. FILESERVICES_API char * FILESERVICES_CALL fsfDespray(ICodeContext *ctx, const char * sourceLogicalName, const char * destinationIP, const char * destinationPath, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite)
  698. {
  699. PrintLog("Despray: %s", sourceLogicalName);
  700. CClientFileSpray server;
  701. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  702. server.addServiceUrl(getEspServerURL(espServerIpPort));
  703. setServerAccess(server, wu);
  704. Owned<IClientDespray> req = server.createDesprayRequest();
  705. StringBuffer logicalName;
  706. constructLogicalName(wu, sourceLogicalName, logicalName);
  707. req->setSourceLogicalName(logicalName.str());
  708. req->setDestIP(destinationIP);
  709. req->setDestPath(destinationPath);
  710. req->setOverwrite(overwrite);
  711. Owned<IClientDesprayResponse> result = server.Despray(req);
  712. StringBuffer wuid(result->getWuid());
  713. if(!wuid.length())
  714. {
  715. const IMultiException* excep = &result->getExceptions();
  716. if(excep != NULL && excep->ordinality() > 0)
  717. {
  718. StringBuffer errmsg;
  719. excep->errorMessage(errmsg);
  720. throw MakeStringException(0, "%s", errmsg.str());
  721. }
  722. else
  723. {
  724. throw MakeStringException(0, "Result's dfu WUID is empty");
  725. }
  726. }
  727. wu.clear();
  728. blockUntilComplete("Despray", server, ctx, wuid, timeOut);
  729. return wuid.detach();
  730. }
  731. FILESERVICES_API void FILESERVICES_CALL fsCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize)
  732. {
  733. CTXFREE(parentCtx, fsfCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize));
  734. }
  735. FILESERVICES_API char * FILESERVICES_CALL fsfCopy(ICodeContext *ctx, const char * sourceLogicalName, const char *destinationGroup, const char * destinationLogicalName, const char * sourceDali, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool asSuperfile, bool compress, bool forcePush, int transferBufferSize)
  736. {
  737. PrintLog("Copy: %s%s", sourceLogicalName,asSuperfile?" as superfile":"");
  738. CClientFileSpray server;
  739. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  740. server.addServiceUrl(getEspServerURL(espServerIpPort));
  741. setServerAccess(server, wu);
  742. Owned<IClientCopy> req = server.createCopyRequest();
  743. if (asSuperfile)
  744. req->setSuperCopy(true);
  745. StringBuffer _sourceLogicalName, _destinationLogicalName;
  746. constructLogicalName(wu, sourceLogicalName, _sourceLogicalName);
  747. constructLogicalName(wu, destinationLogicalName, _destinationLogicalName);
  748. req->setSourceLogicalName(_sourceLogicalName.str());
  749. req->setDestLogicalName(_destinationLogicalName.str());
  750. if(destinationGroup != NULL && *destinationGroup != '\0')
  751. req->setDestGroup(destinationGroup);
  752. if(sourceDali != NULL && *sourceDali != '\0')
  753. req->setSourceDali(sourceDali);
  754. req->setOverwrite(overwrite);
  755. req->setReplicate(replicate);
  756. if (compress)
  757. req->setCompress(true);
  758. if (forcePush)
  759. req->setPush(true);
  760. if (transferBufferSize>0)
  761. req->setTransferBufferSize(transferBufferSize);
  762. Owned<IClientCopyResponse> result = server.Copy(req);
  763. StringBuffer wuid(result->getResult());
  764. if(!wuid.length())
  765. {
  766. const IMultiException* excep = &result->getExceptions();
  767. if(excep != NULL && excep->ordinality() > 0)
  768. {
  769. StringBuffer errmsg;
  770. excep->errorMessage(errmsg);
  771. throw MakeStringException(0, "%s", errmsg.str());
  772. }
  773. else
  774. {
  775. throw MakeStringException(0, "Result's dfu WUID is empty");
  776. }
  777. }
  778. wu.clear();
  779. blockUntilComplete("Copy", server, ctx, wuid, timeOut);
  780. return wuid.detach();
  781. }
  782. FILESERVICES_API void FILESERVICES_CALL fsReplicate(ICodeContext *ctx, const char * sourceLogicalName,int timeOut, const char * espServerIpPort)
  783. {
  784. CTXFREE(parentCtx, fsfReplicate(ctx, sourceLogicalName, timeOut, espServerIpPort));
  785. }
  786. FILESERVICES_API char * FILESERVICES_CALL fsfReplicate(ICodeContext *ctx, const char * sourceLogicalName, int timeOut, const char * espServerIpPort)
  787. {
  788. PrintLog("REPLICATE: %s", sourceLogicalName);
  789. CClientFileSpray server;
  790. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  791. server.addServiceUrl(getEspServerURL(espServerIpPort));
  792. setServerAccess(server, wu);
  793. Owned<IClientReplicate> req = server.createReplicateRequest();
  794. StringBuffer logicalName;
  795. constructLogicalName(wu, sourceLogicalName, logicalName);
  796. req->setSourceLogicalName(logicalName.str());
  797. Owned<IClientReplicateResponse> result = server.Replicate(req);
  798. StringBuffer wuid(result->getWuid());
  799. if(!wuid.length())
  800. {
  801. const IMultiException* excep = &result->getExceptions();
  802. if(excep != NULL && excep->ordinality() > 0)
  803. {
  804. StringBuffer errmsg;
  805. excep->errorMessage(errmsg);
  806. throw MakeStringException(0, "%s", errmsg.str());
  807. }
  808. else
  809. {
  810. throw MakeStringException(0, "Result's dfu WUID is empty");
  811. }
  812. }
  813. wu.clear();
  814. blockUntilComplete("Replicate", server, ctx, wuid, timeOut);
  815. return wuid.detach();
  816. }
  817. //===========================================================================================
  818. // SuperFile API
  819. /*
  820. CreateSuperFile(const varstring lsuperfn, boolean sequentialparts=false);
  821. boolean SuperFileExists(const varstring lsuperfn);
  822. DeleteSuperFile(const varstring lsuperfn,boolean deletesub=false);
  823. unsigned4 GetSuperFileSubCount(const varstring lsuperfn);
  824. varstring GetSuperFileSubName(const varstring lsuperfn,unsigned4 filenum);
  825. unsigned4 FindSuperFileSubName(const varstring lsuperfn,const varstring lfn);
  826. StartSuperFileTransaction();
  827. AddSuperFile(const varstring lsuperfn,const varstring lfn,unsigned4 atpos=0);
  828. RemoveSuperFile(const varstring lsuperfn,const varstring lfn,boolean del=false);
  829. ClearSuperFile(const varstring lsuperfn,boolean del=false);
  830. SwapSuperFile(const varstring lsuperfn1,const varstring lsuperfn2);
  831. ReplaceSuperFile(const varstring lsuperfn,const varstring lfn,const varstring bylfn);
  832. FinishSuperFileTransaction(boolean rollback=false);
  833. */
  834. static bool lookupSuperFile(ICodeContext *ctx, const char *lsuperfn, Owned<IDistributedSuperFile> &file, bool throwerr, StringBuffer &lsfn, bool fixmissing, bool allowforeign, bool cacheFiles=false)
  835. {
  836. lsfn.clear();
  837. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  838. constructLogicalName(ctx, lsuperfn, lsfn);
  839. if (!allowforeign) {
  840. CDfsLogicalFileName dlfn;
  841. dlfn.set(lsfn.str());
  842. if (dlfn.isForeign())
  843. throw MakeStringException(0, "Foreign superfile not allowed: %s", lsfn.str());
  844. }
  845. if (cacheFiles)
  846. {
  847. struct CTempActiveTransaction
  848. {
  849. CTempActiveTransaction(IDistributedFileTransaction *_transaction, bool onOff) : transaction(_transaction)
  850. {
  851. prev = transaction->setActive(onOff);
  852. }
  853. ~CTempActiveTransaction()
  854. {
  855. transaction->setActive(prev);
  856. }
  857. IDistributedFileTransaction *transaction;
  858. bool prev;
  859. } temp(transaction, true);
  860. file.setown(transaction->lookupSuperFile(lsfn.str(),fixmissing));
  861. }
  862. else
  863. file.setown(transaction->lookupSuperFile(lsfn.str(),fixmissing));
  864. if (file.get())
  865. return true;
  866. if (throwerr)
  867. throw MakeStringException(0, "Could not locate superfile: %s", lsfn.str());
  868. return false;
  869. }
  870. static ISimpleSuperFileEnquiry *getSimpleSuperFileEnquiry(ICodeContext *ctx, const char *lsuperfn)
  871. {
  872. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  873. if (transaction&&transaction->active())
  874. return NULL;
  875. StringBuffer lsfn;
  876. constructLogicalName(ctx, lsuperfn, lsfn);
  877. return queryDistributedFileDirectory().getSimpleSuperFileEnquiry(lsfn.str(),"Fileservices");
  878. }
  879. static void CheckNotInTransaction(ICodeContext *ctx, const char *fn)
  880. {
  881. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  882. if (transaction&&transaction->active()) {
  883. StringBuffer s("Operation not part of transaction : ");
  884. s.append(fn);
  885. WUmessage(ctx,ExceptionSeverityWarning,fn,s.str());
  886. }
  887. }
  888. FILESERVICES_API void FILESERVICES_CALL fsCreateSuperFile(ICodeContext *ctx, const char *lsuperfn, bool sequentialparts, bool ifdoesnotexist)
  889. {
  890. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  891. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  892. StringBuffer lsfn;
  893. constructLogicalName(ctx, lsuperfn, lsfn);
  894. Owned<IDistributedSuperFile> file = queryDistributedFileDirectory().createSuperFile(lsfn,!sequentialparts,ifdoesnotexist,udesc,transaction);
  895. StringBuffer s("CreateSuperFile ('");
  896. s.append(lsfn).append("') done");
  897. AuditMessage(ctx,"CreateSuperFile",lsfn.str());
  898. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  899. }
  900. FILESERVICES_API bool FILESERVICES_CALL fsSuperFileExists(ICodeContext *ctx, const char *lsuperfn)
  901. {
  902. StringBuffer lsfn;
  903. constructLogicalName(ctx, lsuperfn, lsfn);
  904. return queryDistributedFileDirectory().exists(lsfn,false,true);
  905. }
  906. FILESERVICES_API void FILESERVICES_CALL fsDeleteSuperFile(ICodeContext *ctx, const char *lsuperfn,bool deletesub)
  907. {
  908. // Note because deleting a superfile, not within transaction (currently)
  909. Owned<IDistributedSuperFile> file;
  910. StringBuffer lsfn;
  911. bool found = lookupSuperFile(ctx, lsuperfn, file, false, lsfn, true, false);
  912. if (found) {
  913. CheckNotInTransaction(ctx,"DeleteSuperFile");
  914. if (deletesub)
  915. file->removeSubFile(NULL,true,true,false);
  916. file->detach();
  917. }
  918. StringBuffer s("DeleteSuperFile ('");
  919. s.append(lsfn).appendf("') %s",found?"done":"not found");
  920. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  921. if (found)
  922. AuditMessage(ctx,"DeleteSuperFile",lsfn.str());
  923. }
  924. FILESERVICES_API unsigned FILESERVICES_CALL fsGetSuperFileSubCount(ICodeContext *ctx, const char *lsuperfn)
  925. {
  926. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  927. if (enq)
  928. return enq->numSubFiles();
  929. Owned<IDistributedSuperFile> file;
  930. StringBuffer lsfn;
  931. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  932. return file->numSubFiles();
  933. }
  934. FILESERVICES_API char * FILESERVICES_CALL fsGetSuperFileSubName(ICodeContext *ctx, const char *lsuperfn,unsigned filenum, bool abspath)
  935. {
  936. StringBuffer ret;
  937. if (abspath)
  938. ret.append('~');
  939. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  940. if (enq) {
  941. if (!filenum||!enq->getSubFileName(filenum-1,ret))
  942. return CTXSTRDUP(parentCtx, "");
  943. return ret.detach();
  944. }
  945. Owned<IDistributedSuperFile> file;
  946. StringBuffer lsfn;
  947. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  948. if (!filenum||filenum>file->numSubFiles())
  949. return CTXSTRDUP(parentCtx, "");
  950. ret.append(file->querySubFile(filenum-1).queryLogicalName());
  951. return ret.detach();
  952. }
  953. FILESERVICES_API unsigned FILESERVICES_CALL fsFindSuperFileSubName(ICodeContext *ctx, const char *lsuperfn,const char *_lfn)
  954. {
  955. StringBuffer lfn;
  956. constructLogicalName(ctx, _lfn, lfn);
  957. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  958. if (enq) {
  959. unsigned n = enq->findSubName(lfn.str());
  960. return (n==NotFound)?0:n+1;
  961. }
  962. Owned<IDistributedSuperFile> file;
  963. StringBuffer lsfn;
  964. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  965. unsigned n = 0;
  966. // could do with better version of this TBD
  967. Owned<IDistributedFileIterator> iter = file->getSubFileIterator();
  968. ForEach(*iter) {
  969. n++;
  970. if (stricmp(iter->query().queryLogicalName(),lfn.str())==0)
  971. return n;
  972. }
  973. return 0;
  974. }
  975. FILESERVICES_API void FILESERVICES_CALL fsStartSuperFileTransaction(IGlobalCodeContext *gctx)
  976. {
  977. fslStartSuperFileTransaction(gctx->queryCodeContext());
  978. }
  979. FILESERVICES_API void FILESERVICES_CALL fslStartSuperFileTransaction(ICodeContext *ctx)
  980. {
  981. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  982. if (transaction)
  983. transaction->start();
  984. WUmessage(ctx,ExceptionSeverityInformation,NULL,"StartSuperFileTransaction");
  985. }
  986. FILESERVICES_API void FILESERVICES_CALL fsAddSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *_lfn,unsigned atpos,bool addcontents, bool strict)
  987. {
  988. fslAddSuperFile(gctx->queryCodeContext(),lsuperfn,_lfn,atpos,addcontents,strict);
  989. }
  990. FILESERVICES_API void FILESERVICES_CALL fslAddSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *_lfn,unsigned atpos,bool addcontents, bool strict)
  991. {
  992. Owned<IDistributedSuperFile> file;
  993. StringBuffer lsfn;
  994. // NB: if adding contents, tell lookupSuperFile to cache the subfiles in the transaction
  995. if (!lookupSuperFile(ctx, lsuperfn, file, strict, lsfn, false, false, addcontents)) {
  996. // auto create
  997. fsCreateSuperFile(ctx,lsuperfn,false,false);
  998. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, false);
  999. }
  1000. // Never add super file to itself
  1001. StringBuffer lfn;
  1002. constructLogicalName(ctx, _lfn, lfn);
  1003. if (stricmp(file->queryLogicalName(), lfn.str()) == 0) {
  1004. throw MakeStringException(0, "AddSuperFile: Adding super file %s to itself!", file->queryLogicalName());
  1005. }
  1006. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1007. if (strict||addcontents) {
  1008. Owned<IDistributedSuperFile> subfile;
  1009. subfile.setown(transaction->lookupSuperFile(lfn.str()));
  1010. if (!subfile.get())
  1011. throw MakeStringException(0, "AddSuperFile%s: Could not locate super file %s", addcontents?"(addcontents)":"",lfn.str());
  1012. if (strict&&(subfile->numSubFiles()<1))
  1013. throw MakeStringException(0, "AddSuperFile: Adding empty super file %s", lfn.str());
  1014. }
  1015. StringBuffer other;
  1016. if (atpos>1)
  1017. other.append("#").append(atpos);
  1018. file->addSubFile(lfn.str(),atpos>0,(atpos>1)?other.str():NULL,addcontents,transaction);
  1019. StringBuffer s("AddSuperFile ('");
  1020. s.append(lsfn).append("', '");
  1021. s.append(lfn).append('\'');
  1022. if (atpos)
  1023. s.append(", ").append(atpos);
  1024. if (addcontents)
  1025. s.append(", addcontents");
  1026. s.append(") ");
  1027. if (transaction&&transaction->active())
  1028. s.append("trans");
  1029. else
  1030. s.append("done");
  1031. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1032. AuditMessage(ctx,"AddSuperFile",lsfn.str(),lfn.str());
  1033. }
  1034. FILESERVICES_API void FILESERVICES_CALL fsRemoveSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *_lfn,bool del,bool remcontents)
  1035. {
  1036. fslRemoveSuperFile(gctx->queryCodeContext(),lsuperfn,_lfn,del,remcontents);
  1037. }
  1038. FILESERVICES_API void FILESERVICES_CALL fslRemoveSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *_lfn,bool del,bool remcontents)
  1039. {
  1040. Owned<IDistributedSuperFile> file;
  1041. StringBuffer lsfn;
  1042. StringBuffer lfn;
  1043. if (_lfn)
  1044. constructLogicalName(ctx, _lfn, lfn);
  1045. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, true, false);
  1046. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1047. file->removeSubFile(_lfn?lfn.str():NULL,del,del,remcontents,transaction);
  1048. StringBuffer s;
  1049. if (_lfn)
  1050. s.append("RemoveSuperFile ('");
  1051. else
  1052. s.append("ClearSuperFile ('");
  1053. s.append(lsfn).append('\'');
  1054. if (_lfn)
  1055. s.append(", '").append(lfn.str()).append('\'');
  1056. if (del)
  1057. s.append(", del");
  1058. if (remcontents)
  1059. s.append(", remcontents");
  1060. s.append(") ");
  1061. if (transaction&&transaction->active())
  1062. s.append("trans");
  1063. else
  1064. s.append("done");
  1065. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1066. AuditMessage(ctx,"RemoveSuperFile",lsfn.str(),lfn.str());
  1067. }
  1068. FILESERVICES_API void FILESERVICES_CALL fsClearSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,bool del)
  1069. {
  1070. fsRemoveSuperFile(gctx,lsuperfn,NULL,del);
  1071. }
  1072. FILESERVICES_API void FILESERVICES_CALL fslClearSuperFile(ICodeContext *ctx, const char *lsuperfn,bool del)
  1073. {
  1074. fslRemoveSuperFile(ctx,lsuperfn,NULL,del);
  1075. }
  1076. FILESERVICES_API void FILESERVICES_CALL fsSwapSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn1,const char *lsuperfn2)
  1077. {
  1078. fslSwapSuperFile(gctx->queryCodeContext(),lsuperfn1,lsuperfn2);
  1079. }
  1080. FILESERVICES_API void FILESERVICES_CALL fslSwapSuperFile(ICodeContext *ctx, const char *lsuperfn1,const char *lsuperfn2)
  1081. {
  1082. StringBuffer lsfn1;
  1083. StringBuffer lsfn2;
  1084. Owned<IDistributedSuperFile> file1;
  1085. Owned<IDistributedSuperFile> file2;
  1086. lookupSuperFile(ctx, lsuperfn1, file1, true, lsfn1,false,false);
  1087. lookupSuperFile(ctx, lsuperfn2, file2, true,lsfn2,false,false);
  1088. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1089. file1->swapSuperFile(file2,transaction);
  1090. StringBuffer s("SwapSuperFile ('");
  1091. s.append(lsfn1).append("', '");
  1092. s.append(lsfn2).append("') '");
  1093. if (transaction&&transaction->active())
  1094. s.append("trans");
  1095. else
  1096. s.append("done");
  1097. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1098. AuditMessage(ctx,"SwapSuperFile",lsfn1.str(),lsfn2.str());
  1099. }
  1100. FILESERVICES_API void FILESERVICES_CALL fsReplaceSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *lfn,const char *bylfn)
  1101. {
  1102. fslReplaceSuperFile(gctx->queryCodeContext(),lsuperfn,lfn,bylfn);
  1103. }
  1104. FILESERVICES_API void FILESERVICES_CALL fslReplaceSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *lfn,const char *bylfn)
  1105. {
  1106. unsigned at = fsFindSuperFileSubName(ctx,lsuperfn,lfn);
  1107. if (!at)
  1108. return;
  1109. fslRemoveSuperFile(ctx,lsuperfn,lfn);
  1110. fslAddSuperFile(ctx,lsuperfn,bylfn,at);
  1111. }
  1112. FILESERVICES_API void FILESERVICES_CALL fsFinishSuperFileTransaction(IGlobalCodeContext *gctx, bool rollback)
  1113. {
  1114. fslFinishSuperFileTransaction(gctx->queryCodeContext(),rollback);
  1115. }
  1116. FILESERVICES_API void FILESERVICES_CALL fslFinishSuperFileTransaction(ICodeContext *ctx, bool rollback)
  1117. {
  1118. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1119. if (transaction) {
  1120. if (rollback)
  1121. transaction->rollback();
  1122. else
  1123. transaction->commit();
  1124. StringBuffer s("FinishSuperFileTransaction ");
  1125. if (rollback)
  1126. s.append("rollback");
  1127. else
  1128. s.append("done");
  1129. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1130. }
  1131. }
  1132. FILESERVICES_API char * FILESERVICES_CALL fsForeignLogicalFileName(ICodeContext *ctx, const char *_lfn,const char *foreigndali,bool abspath)
  1133. {
  1134. StringBuffer lfns;
  1135. constructLogicalName(ctx, _lfn, lfns);
  1136. CDfsLogicalFileName lfn;
  1137. lfn.set(lfns.str());
  1138. if (foreigndali&&*foreigndali) {
  1139. SocketEndpoint ep(foreigndali);
  1140. lfn.setForeign(ep,false);
  1141. }
  1142. else
  1143. lfn.clearForeign();
  1144. StringBuffer ret;
  1145. if (abspath)
  1146. ret.append('~');
  1147. lfn.get(ret);
  1148. return ret.detach();
  1149. }
  1150. FILESERVICES_API char * FILESERVICES_CALL fsExternalLogicalFileName(const char *location,const char *path,bool abspath)
  1151. {
  1152. StringBuffer ret;
  1153. if (abspath)
  1154. ret.append('~');
  1155. CDfsLogicalFileName lfn;
  1156. lfn.setExternal(location,path);
  1157. return lfn.get(ret).detach();
  1158. }
  1159. FILESERVICES_API char * FILESERVICES_CALL fsWaitDfuWorkunit(IGlobalCodeContext *gctx, const char *wuid, int timeout, const char * espServerIpPort)
  1160. {
  1161. return fslWaitDfuWorkunit(gctx->queryCodeContext(),wuid,timeout,espServerIpPort);
  1162. }
  1163. FILESERVICES_API char * FILESERVICES_CALL fslWaitDfuWorkunit(ICodeContext *ctx, const char *wuid, int timeout, const char * espServerIpPort)
  1164. {
  1165. CClientFileSpray server;
  1166. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1167. server.addServiceUrl(getEspServerURL(espServerIpPort));
  1168. setServerAccess(server, wu);
  1169. StringBuffer s("Waiting for DFU Workunit ");
  1170. s.append(wuid);
  1171. WUmessage(ctx,ExceptionSeverityInformation,"WaitDfuWorkunit",s.str());
  1172. StringBuffer state;
  1173. wu.clear();
  1174. blockUntilComplete("WaitDfuWorkunit", server, ctx, wuid, timeout, &state);
  1175. s.clear().append("Finished waiting for DFU Workunit ").append(wuid).append(" state=").append(state.str());
  1176. WUmessage(ctx,ExceptionSeverityInformation,"WaitDfuWorkunit",s.str());
  1177. return state.detach();
  1178. }
  1179. FILESERVICES_API void FILESERVICES_CALL fsAbortDfuWorkunit(IGlobalCodeContext *gctx, const char *wuid, const char * espServerIpPort)
  1180. {
  1181. fslAbortDfuWorkunit(gctx->queryCodeContext(),wuid,espServerIpPort);
  1182. }
  1183. FILESERVICES_API void FILESERVICES_CALL fslAbortDfuWorkunit(ICodeContext *ctx, const char *wuid, const char * espServerIpPort)
  1184. {
  1185. CClientFileSpray server;
  1186. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1187. server.addServiceUrl(getEspServerURL(espServerIpPort));
  1188. setServerAccess(server, wu);
  1189. Owned<IClientAbortDFUWorkunit> abortReq = server.createAbortDFUWorkunitRequest();
  1190. abortReq->setWuid(wuid);
  1191. Linked<IClientAbortDFUWorkunitResponse> abortResp = server.AbortDFUWorkunit(abortReq);
  1192. StringBuffer s("DFU Workunit Abort Requested for ");
  1193. s.append(wuid);
  1194. WUmessage(ctx,ExceptionSeverityInformation,"AbortDfuWorkunit",s.str());
  1195. }
  1196. FILESERVICES_API void FILESERVICES_CALL fsMonitorLogicalFileName(ICodeContext *ctx, const char *eventname, const char *_lfn,int shotcount, const char * espServerIpPort)
  1197. {
  1198. CTXFREE(parentCtx, fsfMonitorLogicalFileName(ctx, eventname, _lfn,shotcount, espServerIpPort));
  1199. }
  1200. FILESERVICES_API char * FILESERVICES_CALL fsfMonitorLogicalFileName(ICodeContext *ctx, const char *eventname, const char *_lfn,int shotcount, const char * espServerIpPort)
  1201. {
  1202. CClientFileSpray server;
  1203. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1204. server.addServiceUrl(getEspServerURL(espServerIpPort));
  1205. setServerAccess(server, wu);
  1206. StringBuffer lfn;
  1207. constructLogicalName(ctx, _lfn, lfn);
  1208. if (shotcount == 0)
  1209. shotcount = -1;
  1210. Owned<IClientDfuMonitorRequest> req = server.createDfuMonitorRequest();
  1211. req->setEventName(eventname);
  1212. req->setLogicalName(lfn);
  1213. req->setShotLimit(shotcount);
  1214. Owned<IClientDfuMonitorResponse> result = server.DfuMonitor(req);
  1215. StringBuffer res(result->getWuid());
  1216. StringBuffer s("MonitorLogicalFileName ('");
  1217. s.append(lfn).append("'): ").append(res);
  1218. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1219. wu.clear();
  1220. if (res.length()!=0)
  1221. blockUntilComplete("MonitorLogicalFileName",server,ctx,res.str(),1000*60*60,NULL,true);
  1222. return res.detach();
  1223. }
  1224. FILESERVICES_API void FILESERVICES_CALL fsMonitorFile(ICodeContext *ctx, const char *eventname,const char *ip, const char *filename, bool sub, int shotcount, const char * espServerIpPort)
  1225. {
  1226. CTXFREE(parentCtx, fsfMonitorFile(ctx, eventname,ip, filename, sub, shotcount, espServerIpPort));
  1227. }
  1228. FILESERVICES_API char * FILESERVICES_CALL fsfMonitorFile(ICodeContext *ctx, const char *eventname,const char *ip, const char *filename, bool sub, int shotcount, const char * espServerIpPort)
  1229. {
  1230. CClientFileSpray server;
  1231. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1232. server.addServiceUrl(getEspServerURL(espServerIpPort));
  1233. setServerAccess(server, wu);
  1234. if (shotcount == 0)
  1235. shotcount = -1;
  1236. Owned<IClientDfuMonitorRequest> req = server.createDfuMonitorRequest();
  1237. req->setEventName(eventname);
  1238. req->setIp(ip);
  1239. req->setFilename(filename);
  1240. req->setShotLimit(shotcount);
  1241. Owned<IClientDfuMonitorResponse> result = server.DfuMonitor(req);
  1242. StringBuffer res(result->getWuid());
  1243. StringBuffer s("MonitorFile (");
  1244. s.append(ip).append(", '").append(filename).append("'): '").append(res);
  1245. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1246. wu.clear();
  1247. if (res.length()!=0)
  1248. blockUntilComplete("MonitorFile",server,ctx,res.str(),1000*60*60,NULL,true);
  1249. return res.detach();
  1250. }
  1251. FILESERVICES_API void FILESERVICES_CALL fsSetFileDescription(ICodeContext *ctx, const char *logicalfilename, const char *value)
  1252. {
  1253. StringBuffer lfn;
  1254. constructLogicalName(ctx, logicalfilename, lfn);
  1255. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1256. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  1257. if (df) {
  1258. df->lockProperties();
  1259. df->queryAttributes().setProp("@description",value);
  1260. df->unlockProperties();
  1261. }
  1262. else
  1263. throw MakeStringException(0, "SetFileDescription: Could not locate file %s", lfn.str());
  1264. }
  1265. FILESERVICES_API char * FILESERVICES_CALL fsGetFileDescription(ICodeContext *ctx, const char *logicalfilename)
  1266. {
  1267. StringBuffer lfn;
  1268. constructLogicalName(ctx, logicalfilename, lfn);
  1269. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1270. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  1271. if (!df)
  1272. throw MakeStringException(0, "GetFileDescription: Could not locate file %s", lfn.str());
  1273. const char * ret = df->queryAttributes().queryProp("@description");
  1274. if (ret)
  1275. return CTXSTRDUP(parentCtx, ret);
  1276. else
  1277. return CTXSTRDUP(parentCtx, "");
  1278. }
  1279. FILESERVICES_API void FILESERVICES_CALL fsRemoteDirectory(size32_t & __lenResult,void * & __result, const char *machine, const char *dir, const char *mask, bool sub)
  1280. {
  1281. MemoryBuffer mb;
  1282. RemoteFilename rfn;
  1283. SocketEndpoint ep(machine);
  1284. if (ep.isNull()){
  1285. if (machine)
  1286. throw MakeStringException(-1, "GetFileDescription: Could not resolve %s", machine);
  1287. ep.setLocalHost(0);
  1288. }
  1289. rfn.setPath(ep,dir);
  1290. Owned<IFile> f = createIFile(rfn);
  1291. if (f) {
  1292. StringBuffer s;
  1293. StringBuffer ds;
  1294. Owned<IDirectoryIterator> di = f->directoryFiles(mask,sub);
  1295. if (di) {
  1296. ForEach(*di) {
  1297. di->getName(s.clear());
  1298. __int64 fsz = di->getFileSize();
  1299. CDateTime dt;
  1300. di->getModifiedTime(dt);
  1301. size32_t sz = s.length();
  1302. dt.getString(ds.clear());
  1303. ds.padTo(19);
  1304. mb.append(sz).append(sz,s.str()).append(fsz).append(19,ds.str());
  1305. }
  1306. }
  1307. }
  1308. __lenResult = mb.length();
  1309. __result = mb.detach();
  1310. }
  1311. FILESERVICES_API void FILESERVICES_CALL fsLogicalFileList(ICodeContext *ctx, size32_t & __lenResult,void * & __result, const char *mask, bool includenormal, bool includesuper, bool unknownszero, const char *foreigndali)
  1312. {
  1313. MemoryBuffer mb;
  1314. if (!mask||!*mask)
  1315. mask ="*";
  1316. StringBuffer masklower(mask);
  1317. masklower.toLowerCase();
  1318. Owned<IDFAttributesIterator> iter = queryDistributedFileDirectory().getForeignDFAttributesIterator(masklower.str(),true,includesuper,foreigndali,ctx->queryUserDescriptor());
  1319. if (iter) {
  1320. StringBuffer s;
  1321. ForEach(*iter) {
  1322. IPropertyTree &attr=iter->query();
  1323. const char *name = attr.queryProp("@name");
  1324. if (!name||!*name)
  1325. continue;
  1326. int numsub = attr.getPropInt("@numsubfiles",-1);
  1327. bool issuper = numsub>=0;
  1328. if (issuper) {
  1329. if (!includesuper)
  1330. continue;
  1331. }
  1332. else {
  1333. if (!includenormal)
  1334. continue;
  1335. }
  1336. size32_t sz = strlen(name);
  1337. mb.append(sz).append(sz,name);
  1338. mb.append(issuper);
  1339. __int64 i64;
  1340. __int64 fsz = attr.getPropInt64("@size",-1);
  1341. if ((fsz==-1)&&(unknownszero||(numsub==0)))
  1342. fsz = 0;
  1343. mb.append(fsz);
  1344. i64 = attr.getPropInt64("@recordCount",-1);
  1345. if ((i64==-1)&&(fsz!=-1)) {
  1346. int rsz = attr.getPropInt("@recordSize",0);
  1347. if (rsz>0)
  1348. i64 = fsz/rsz;
  1349. }
  1350. if ((i64==-1)&&(unknownszero||(numsub==0)))
  1351. i64 = 0;
  1352. mb.append(i64);
  1353. attr.getProp("@modified",s.clear());
  1354. s.padTo(19);
  1355. mb.append(19,s.str());
  1356. attr.getProp("@owner",s.clear());
  1357. sz = s.length();
  1358. mb.append(sz).append(sz,s.str());
  1359. attr.getProp("@group",s.clear());
  1360. sz = s.length();
  1361. mb.append(sz).append(sz,s.str());
  1362. }
  1363. }
  1364. __lenResult = mb.length();
  1365. __result = mb.detach();
  1366. }
  1367. FILESERVICES_API void FILESERVICES_CALL fsSuperFileContents(ICodeContext *ctx, size32_t & __lenResult,void * & __result, const char *lsuperfn, bool recurse)
  1368. {
  1369. MemoryBuffer mb;
  1370. Owned<ISimpleSuperFileEnquiry> enq;
  1371. if (!recurse)
  1372. enq.setown(getSimpleSuperFileEnquiry(ctx, lsuperfn));
  1373. if (enq) {
  1374. StringArray subs;
  1375. enq->getContents(subs);
  1376. ForEachItemIn(i,subs) {
  1377. const char *name = subs.item(i);
  1378. size32_t sz = strlen(name);
  1379. if (!sz)
  1380. continue;
  1381. mb.append(sz).append(sz,name);
  1382. }
  1383. }
  1384. else {
  1385. Owned<IDistributedSuperFile> file;
  1386. StringBuffer lsfn;
  1387. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  1388. Owned<IDistributedFileIterator> iter = file->getSubFileIterator(recurse);
  1389. StringBuffer name;
  1390. ForEach(*iter) {
  1391. iter->getName(name.clear());
  1392. size32_t sz = name.length();
  1393. if (!sz)
  1394. continue;
  1395. mb.append(sz).append(sz,name.str());
  1396. }
  1397. }
  1398. __lenResult = mb.length();
  1399. __result = mb.detach();
  1400. }
  1401. FILESERVICES_API void FILESERVICES_CALL fsLogicalFileSuperOwners(ICodeContext *ctx,size32_t & __lenResult,void * & __result, const char *logicalfilename)
  1402. {
  1403. MemoryBuffer mb;
  1404. StringBuffer lfn;
  1405. constructLogicalName(ctx, logicalfilename, lfn);
  1406. StringArray owners;
  1407. if (queryDistributedFileDirectory().getFileSuperOwners(lfn.str(),owners)) {
  1408. ForEachItemIn(i,owners) {
  1409. const char *name = owners.item(i);
  1410. size32_t sz = strlen(name);
  1411. if (!sz)
  1412. continue;
  1413. mb.append(sz).append(sz,name);
  1414. }
  1415. }
  1416. else {
  1417. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1418. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  1419. if (df) {
  1420. Owned<IDistributedSuperFileIterator> iter = df->getOwningSuperFiles();
  1421. ForEach(*iter) {
  1422. const char *name = iter->queryName();
  1423. size32_t sz = strlen(name);
  1424. if (!sz)
  1425. continue;
  1426. mb.append(sz).append(sz,name);
  1427. }
  1428. }
  1429. else
  1430. throw MakeStringException(0, "LogicalFileSuperOwners: Could not locate file %s", lfn.str());
  1431. }
  1432. __lenResult = mb.length();
  1433. __result = mb.detach();
  1434. }
  1435. FILESERVICES_API int FILESERVICES_CALL fsCompareFiles(ICodeContext *ctx,const char *name1, const char *name2,bool logicalonly, bool usecrcs)
  1436. {
  1437. StringBuffer lfn1;
  1438. constructLogicalName(ctx, name1, lfn1);
  1439. StringBuffer lfn2;
  1440. constructLogicalName(ctx, name2, lfn2);
  1441. StringBuffer retstr;
  1442. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1443. int ret = queryDistributedFileDirectory().fileCompare(lfn1.str(),lfn2.str(),usecrcs?DFS_COMPARE_FILES_PHYSICAL_CRCS:(logicalonly?DFS_COMPARE_FILES_LOGICAL:DFS_COMPARE_FILES_PHYSICAL),retstr,udesc);
  1444. if (ret==DFS_COMPARE_RESULT_FAILURE)
  1445. throw MakeStringException(ret,"CompareLogicalFiles: %s",retstr.str());
  1446. return ret;
  1447. }
  1448. FILESERVICES_API char * FILESERVICES_CALL fsVerifyFile(ICodeContext *ctx,const char *name,bool usecrcs)
  1449. {
  1450. StringBuffer lfn;
  1451. constructLogicalName(ctx, name, lfn);
  1452. StringBuffer retstr;
  1453. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1454. if (queryDistributedFileDirectory().filePhysicalVerify(lfn.str(),usecrcs,retstr,udesc))
  1455. retstr.append("OK");
  1456. return retstr.detach();
  1457. }
  1458. // RemotePull
  1459. /*
  1460. varstring RemotePull(
  1461. const varstring remoteEspFsURL, // remote ESP URL e.g. 'http://10.173.34.60:8010/FileSpray'
  1462. const varstring sourceLogicalName, // local
  1463. const varstring destinationGroup, // remote
  1464. const varstring destinationLogicalName, // remote (NB full name required)
  1465. integer4 timeOut=-1,
  1466. integer4 maxConnections=-1,
  1467. boolean allowoverwrite=false,
  1468. boolean replicate=false,
  1469. boolean asSuperfile=false);
  1470. */
  1471. FILESERVICES_API void FILESERVICES_CALL fsRemotePull(ICodeContext *ctx,
  1472. const char * remoteEspFsURL,
  1473. const char * sourceLogicalName,
  1474. const char *destinationGroup,
  1475. const char * destinationLogicalName,
  1476. int timeOut,
  1477. int maxConnections,
  1478. bool overwrite,
  1479. bool replicate,
  1480. bool asSuperfile,
  1481. bool forcePush,
  1482. int transferBufferSize,
  1483. bool wrap,
  1484. bool compress)
  1485. {
  1486. CTXFREE(parentCtx, fsfRemotePull(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress));
  1487. }
  1488. FILESERVICES_API char * FILESERVICES_CALL fsfRemotePull(ICodeContext *ctx,
  1489. const char * remoteEspFsURL,
  1490. const char * sourceLogicalName,
  1491. const char *destinationGroup,
  1492. const char * destinationLogicalName,
  1493. int timeOut,
  1494. int maxConnections,
  1495. bool overwrite,
  1496. bool replicate,
  1497. bool asSuperfile,
  1498. bool forcePush,
  1499. int transferBufferSize,
  1500. bool wrap,
  1501. bool compress)
  1502. {
  1503. PrintLog("RemotePull(%s): %s%s", remoteEspFsURL,sourceLogicalName,asSuperfile?" as superfile":"");
  1504. CClientFileSpray server;
  1505. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1506. server.addServiceUrl(remoteEspFsURL);
  1507. setServerAccess(server, wu);
  1508. Owned<IClientCopy> req = server.createCopyRequest();
  1509. if (asSuperfile)
  1510. req->setSuperCopy(true);
  1511. StringBuffer _sourceLogicalName, _destinationLogicalName;
  1512. constructLogicalName(wu, sourceLogicalName, _sourceLogicalName);
  1513. // destination name assumed complete (so just skip ~ *)
  1514. while ((*destinationLogicalName=='~')||isspace(*destinationLogicalName))
  1515. destinationLogicalName++;
  1516. _destinationLogicalName.append(destinationLogicalName);
  1517. if (strstr(_destinationLogicalName.str(),"::")==NULL)
  1518. _destinationLogicalName.insert(0,".::");
  1519. StringBuffer _destGroup;
  1520. _destGroup.append(destinationGroup);
  1521. req->setSourceLogicalName(_sourceLogicalName.str());
  1522. req->setDestLogicalName(_destinationLogicalName.str());
  1523. req->setDestGroup(_destGroup.str());
  1524. if (compress)
  1525. req->setCompress(true);
  1526. if (wrap)
  1527. req->setWrap(true);
  1528. StringBuffer sourceDali;
  1529. queryCoven().queryComm().queryGroup().queryNode(0).endpoint().getUrlStr(sourceDali);
  1530. req->setSourceDali(sourceDali);
  1531. req->setOverwrite(overwrite);
  1532. req->setReplicate(replicate);
  1533. if (forcePush)
  1534. req->setPush(true);
  1535. if (transferBufferSize>0)
  1536. req->setTransferBufferSize(transferBufferSize);
  1537. Owned<IClientCopyResponse> result = server.Copy(req);
  1538. StringBuffer wuid(result->getResult());
  1539. if(!wuid.length())
  1540. {
  1541. const IMultiException* excep = &result->getExceptions();
  1542. if(excep != NULL && excep->ordinality() > 0)
  1543. {
  1544. StringBuffer errmsg;
  1545. excep->errorMessage(errmsg);
  1546. throw MakeStringException(0, "%s", errmsg.str());
  1547. }
  1548. else
  1549. {
  1550. throw MakeStringException(0, "Result's dfu WUID is empty");
  1551. }
  1552. }
  1553. wu.clear();
  1554. blockUntilComplete("RemotePull", server, ctx, wuid, timeOut);
  1555. return wuid.detach();
  1556. }
  1557. FILESERVICES_API void FILESERVICES_CALL fsLogicalFileSuperSubList(ICodeContext *ctx, size32_t & __lenResult,void * & __result)
  1558. {
  1559. MemoryBuffer mb;
  1560. getLogicalFileSuperSubList(mb);
  1561. __lenResult = mb.length();
  1562. __result = mb.detach();
  1563. }
  1564. FILESERVICES_API void FILESERVICES_CALL fsPromoteSuperFileList(ICodeContext * ctx,bool isAllLsuperfns,size32_t lenLsuperfns,const void * lsuperfns,const char * addhead,bool deltail,bool createonlyonesuperfile,bool reverse)
  1565. {
  1566. CTXFREE(parentCtx, fsfPromoteSuperFileList(ctx,isAllLsuperfns,lenLsuperfns,lsuperfns,addhead,deltail,createonlyonesuperfile,reverse));
  1567. }
  1568. FILESERVICES_API char * FILESERVICES_CALL fsfPromoteSuperFileList(ICodeContext * ctx,bool isAllLsuperfns,size32_t lenLsuperfns,const void * lsuperfns,const char * addhead,bool deltail,bool createonlyonesuperfile,bool reverse)
  1569. {
  1570. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1571. MemoryBuffer mb;
  1572. StringBuffer lfn;
  1573. UnsignedArray lfnofs;
  1574. const char *s = (const char *)lsuperfns;
  1575. while ((size32_t)(s-(const char *)lsuperfns)<lenLsuperfns) {
  1576. constructLogicalName(wu,s,lfn.clear());
  1577. lfnofs.append(mb.length());
  1578. mb.append(lfn);
  1579. s = s+strlen(s)+1;
  1580. }
  1581. PointerArray lfns;
  1582. ForEachItemIn(i,lfnofs) {
  1583. lfns.append((void *)(mb.toByteArray()+lfnofs.item(reverse?(lfnofs.ordinality()-i-1):i)));
  1584. }
  1585. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1586. StringArray toadd;
  1587. CslToStringArray(addhead,toadd,true);
  1588. StringBuffer addlist;
  1589. ForEachItemIn(i1,toadd) {
  1590. if (addlist.length())
  1591. addlist.append(',');
  1592. constructLogicalName(wu,toadd.item(i1),addlist);
  1593. }
  1594. toadd.kill();
  1595. queryDistributedFileDirectory().promoteSuperFiles(lfns.ordinality(),(const char **)lfns.getArray(),addlist.str(),deltail,createonlyonesuperfile,udesc.get(),(unsigned)-1,toadd);
  1596. addlist.clear();
  1597. ForEachItemIn(i2,toadd) {
  1598. if (addlist.length())
  1599. addlist.append(',');
  1600. constructLogicalName(wu,toadd.item(i2),addlist);
  1601. }
  1602. return addlist.detach();
  1603. }
  1604. FILESERVICES_API unsigned __int64 FILESERVICES_CALL fsGetUniqueInteger(const char *foreigndali)
  1605. {
  1606. SocketEndpoint ep;
  1607. if (foreigndali&&*foreigndali)
  1608. ep.set(foreigndali);
  1609. return getGlobalUniqueIds(1,&ep);
  1610. }
  1611. FILESERVICES_API void FILESERVICES_CALL fsAddFileRelationship(ICodeContext * ctx,const char *primary, const char *secondary, const char *primflds, const char *secflds, const char *kind, const char *cardinality, bool payload, const char *description)
  1612. {
  1613. StringBuffer pfn;
  1614. constructLogicalName(ctx, primary, pfn);
  1615. StringBuffer sfn;
  1616. constructLogicalName(ctx, secondary, sfn);
  1617. queryDistributedFileDirectory().addFileRelationship(pfn.str(),sfn.str(),primflds,secflds,kind,cardinality,payload,description);
  1618. StringBuffer s("AddFileRelationship('");
  1619. s.append(pfn.str()).append("','").append(sfn.str()).append("','").append(primflds?primflds:"").append("','").append(secflds?secflds:"").append("','").append(kind?kind:"").append("') done");
  1620. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1621. }
  1622. static inline void addmbstr(MemoryBuffer &mb,const char *s)
  1623. {
  1624. size32_t sz = strlen(s);
  1625. mb.append(sz).append(sz,s);
  1626. }
  1627. FILESERVICES_API void FILESERVICES_CALL fsFileRelationshipList(ICodeContext * ctx,size32_t & __lenResult,void * & __result,const char *primary, const char *secondary, const char *primflds, const char *secflds, const char *kind)
  1628. {
  1629. StringBuffer pfn;
  1630. if (primary&&*primary)
  1631. constructLogicalName(ctx, primary, pfn);
  1632. StringBuffer sfn;
  1633. if (secondary&&*secondary)
  1634. constructLogicalName(ctx, secondary, sfn);
  1635. MemoryBuffer mb;
  1636. Owned<IFileRelationshipIterator> iter = queryDistributedFileDirectory().lookupFileRelationships(pfn.str(),sfn.str(),primflds,secflds,kind);
  1637. if (iter) {
  1638. StringBuffer s;
  1639. ForEach(*iter) {
  1640. IFileRelationship &rel=iter->query();
  1641. addmbstr(mb,rel.queryPrimaryFilename());
  1642. addmbstr(mb,rel.querySecondaryFilename());
  1643. addmbstr(mb,rel.queryPrimaryFields());
  1644. addmbstr(mb,rel.querySecondaryFields());
  1645. addmbstr(mb,rel.queryKind());
  1646. addmbstr(mb,rel.queryCardinality());
  1647. mb.append((byte)(rel.isPayload()?1:0));
  1648. addmbstr(mb,rel.queryDescription());
  1649. }
  1650. }
  1651. __lenResult = mb.length();
  1652. __result = mb.detach();
  1653. }
  1654. FILESERVICES_API void FILESERVICES_CALL fsRemoveFileRelationship(ICodeContext * ctx,const char *primary, const char *secondary, const char *primflds, const char *secflds, const char *kind)
  1655. {
  1656. StringBuffer pfn;
  1657. if (primary&&*primary)
  1658. constructLogicalName(ctx, primary, pfn);
  1659. StringBuffer sfn;
  1660. if (secondary&&*secondary)
  1661. constructLogicalName(ctx, secondary, sfn);
  1662. queryDistributedFileDirectory().removeFileRelationships(pfn.str(),sfn.str(),primflds,secflds,kind);
  1663. }
  1664. FILESERVICES_API void FILESERVICES_CALL fsSetColumnMapping(ICodeContext * ctx,const char *filename, const char *mapping)
  1665. {
  1666. StringBuffer lfn;
  1667. constructLogicalName(ctx, filename, lfn);
  1668. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),ctx->queryUserDescriptor(),true);
  1669. if (df)
  1670. df->setColumnMapping(mapping);
  1671. else
  1672. throw MakeStringException(-1, "SetColumnMapping: Could not find logical file %s", lfn.str());
  1673. }
  1674. FILESERVICES_API char * FILESERVICES_CALL fsfGetColumnMapping(ICodeContext * ctx,const char *filename)
  1675. {
  1676. StringBuffer lfn;
  1677. constructLogicalName(ctx, filename, lfn);
  1678. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),ctx->queryUserDescriptor(),true);
  1679. if (df) {
  1680. StringBuffer mapping;
  1681. df->getColumnMapping(mapping);
  1682. return mapping.detach();
  1683. }
  1684. throw MakeStringException(-1, "GetColumnMapping: Could not find logical file %s", lfn.str());
  1685. return NULL;
  1686. }
  1687. FILESERVICES_API char * FILESERVICES_CALL fsfRfsQuery(const char *server, const char *query)
  1688. {
  1689. StringBuffer ret;
  1690. ret.append('~');
  1691. CDfsLogicalFileName lfn;
  1692. lfn.setQuery(server,query);
  1693. if (!lfn.isSet())
  1694. throw MakeStringException(-1, "RfsQuery invalid parameter");
  1695. return lfn.get(ret).detach();
  1696. }
  1697. FILESERVICES_API void FILESERVICES_CALL fsRfsAction(const char *server, const char *query)
  1698. {
  1699. CDfsLogicalFileName lfn;
  1700. lfn.setQuery(server,query);
  1701. if (!lfn.isSet())
  1702. throw MakeStringException(-1, "RfsAction invalid parameter");
  1703. RemoteFilename rfn;
  1704. lfn.getExternalFilename(rfn);
  1705. Owned<IFile> file = createIFile(rfn);
  1706. Owned<IFileIO> fileio = file->open(IFOread);
  1707. if (fileio) {
  1708. // lets just try reading a byte to cause action
  1709. byte b;
  1710. fileio->read(0,sizeof(b),&b);
  1711. }
  1712. }
  1713. FILESERVICES_API char * FILESERVICES_CALL fsfGetHostName(const char *ipaddress)
  1714. {
  1715. // not a common routine (no Jlib function!) only support IPv4 initially
  1716. StringBuffer ret;
  1717. if (ipaddress&&*ipaddress) {
  1718. IpAddress ip(ipaddress);
  1719. lookupHostName(ip,ret);
  1720. }
  1721. else
  1722. GetHostName(ret);
  1723. return ret.detach();
  1724. }
  1725. FILESERVICES_API char * FILESERVICES_CALL fsfResolveHostName(const char *hostname)
  1726. {
  1727. StringBuffer ret;
  1728. SocketEndpoint ep(hostname);
  1729. ep.getIpText(ret);
  1730. return ret.detach();
  1731. }
  1732. static void checkExternalFileRights(ICodeContext *ctx, CDfsLogicalFileName &lfn, bool rd,bool wr)
  1733. {
  1734. StringAttr extpath;
  1735. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1736. unsigned auditflags = 0;
  1737. if (rd)
  1738. auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_READ_WANTED);
  1739. if (wr)
  1740. auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_WRITE_WANTED);
  1741. int perm = queryDistributedFileDirectory().getFilePermissions(extpath.get(),udesc,auditflags);
  1742. if (wr) {
  1743. if (!HASWRITEPERMISSION(perm)) {
  1744. throw MakeStringException(-1,"Write permission denied for %s",extpath.get());
  1745. }
  1746. }
  1747. else if (rd) {
  1748. if (!HASREADPERMISSION(perm)) {
  1749. throw MakeStringException(-1,"Read permission denied for %s",extpath.get());
  1750. }
  1751. }
  1752. }
  1753. FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext * ctx,const char *location,const char *frompath,const char *topath)
  1754. {
  1755. SocketEndpoint ep(location);
  1756. if (ep.isNull())
  1757. throw MakeStringException(-1,"fsMoveExternalFile: Cannot resolve location %s",location);
  1758. CDfsLogicalFileName from;
  1759. from.setExternal(location,frompath);
  1760. CDfsLogicalFileName to;
  1761. to.setExternal(location,topath);
  1762. checkExternalFileRights(ctx,from,true,true);
  1763. checkExternalFileRights(ctx,to,false,true);
  1764. RemoteFilename fromrfn;
  1765. fromrfn.setPath(ep,frompath);
  1766. RemoteFilename torfn;
  1767. torfn.setPath(ep,topath);
  1768. Owned<IFile> fileto = createIFile(torfn);
  1769. if (fileto->exists())
  1770. throw MakeStringException(-1,"fsMoveExternalFile: Destination %s already exists",frompath);
  1771. fileto.clear();
  1772. Owned<IFile> file = createIFile(fromrfn);
  1773. file->move(topath);
  1774. StringBuffer s("MoveExternalFile ('");
  1775. s.append(location).append(',').append(frompath).append(',').append(topath).append(") done");
  1776. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1777. AuditMessage(ctx,"MoveExternalFile",frompath,topath);
  1778. }
  1779. FILESERVICES_API void FILESERVICES_CALL fsDeleteExternalFile(ICodeContext * ctx,const char *location,const char *path)
  1780. {
  1781. SocketEndpoint ep(location);
  1782. if (ep.isNull())
  1783. throw MakeStringException(-1,"fsDeleteExternalFile: Cannot resolve location %s",location);
  1784. CDfsLogicalFileName lfn;
  1785. lfn.setExternal(location,path);
  1786. checkExternalFileRights(ctx,lfn,false,true);
  1787. RemoteFilename rfn;
  1788. rfn.setPath(ep,path);
  1789. Owned<IFile> file = createIFile(rfn);
  1790. file->remove();
  1791. StringBuffer s("DeleteExternalFile ('");
  1792. s.append(location).append(',').append(path).append(") done");
  1793. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1794. AuditMessage(ctx,"DeleteExternalFile",path);
  1795. }
  1796. FILESERVICES_API void FILESERVICES_CALL fsCreateExternalDirectory(ICodeContext * ctx,const char *location,const char *path)
  1797. {
  1798. SocketEndpoint ep(location);
  1799. if (ep.isNull())
  1800. throw MakeStringException(-1,"fsCreateExternalDirectory: Cannot resolve location %s",location);
  1801. CDfsLogicalFileName lfn;
  1802. lfn.setExternal(location,path);
  1803. checkExternalFileRights(ctx,lfn,false,true);
  1804. RemoteFilename rfn;
  1805. rfn.setPath(ep,path);
  1806. Owned<IFile> file = createIFile(rfn);
  1807. file->createDirectory();
  1808. StringBuffer s("CreateExternalDirectory ('");
  1809. s.append(location).append(',').append(path).append(") done");
  1810. WUmessage(ctx,ExceptionSeverityInformation,NULL,s.str());
  1811. AuditMessage(ctx,"CreateExternalDirectory",path);
  1812. }
  1813. FILESERVICES_API char * FILESERVICES_CALL fsfGetLogicalFileAttribute(ICodeContext * ctx,const char *_lfn,const char *attrname)
  1814. {
  1815. StringBuffer lfn;
  1816. constructLogicalName(ctx, _lfn, lfn);
  1817. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1818. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  1819. StringBuffer ret;
  1820. if (df) {
  1821. if (strcmp(attrname,"ECL")==0)
  1822. df->getECL(ret);
  1823. else if (strcmp(attrname,"clusterName")==0)
  1824. df->getClusterName(0,ret);
  1825. else if (strcmp(attrname,"partmask")==0)
  1826. ret.append(df->queryPartMask());
  1827. else if (strcmp(attrname,"directory")==0)
  1828. ret.append(df->queryDefaultDir());
  1829. else if (strcmp(attrname,"numparts")==0)
  1830. ret.append(df->numParts());
  1831. else if (strcmp(attrname,"name")==0)
  1832. ret.append(df->queryLogicalName());
  1833. else if (strcmp(attrname,"modified")==0) {
  1834. CDateTime dt;
  1835. df->getModificationTime(dt);
  1836. dt.getString(ret);
  1837. }
  1838. else if (strcmp(attrname,"protected")==0) {
  1839. IPropertyTree &attr = df->queryAttributes();
  1840. Owned<IPropertyTreeIterator> piter = attr.getElements("Protect");
  1841. ForEach(*piter) {
  1842. const char *name = piter->get().queryProp("@name");
  1843. if (name&&*name) {
  1844. unsigned count = piter->get().getPropInt("@count");
  1845. if (count) {
  1846. if (ret.length())
  1847. ret.append(',');
  1848. ret.append(name);
  1849. }
  1850. }
  1851. }
  1852. }
  1853. else {
  1854. StringBuffer xpath("@");
  1855. xpath.append(attrname);
  1856. IPropertyTree &attr = df->queryAttributes();
  1857. attr.getProp(xpath.str(),ret);
  1858. }
  1859. }
  1860. else
  1861. throw MakeStringException(0, "GetLogicalFileAttribute: Could not find logical file %s", lfn.str());
  1862. return ret.detach();
  1863. }
  1864. FILESERVICES_API void FILESERVICES_CALL fsProtectLogicalFile(ICodeContext * ctx,const char *_lfn,bool set)
  1865. {
  1866. StringBuffer lfn;
  1867. constructLogicalName(ctx, _lfn, lfn);
  1868. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1869. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc);
  1870. StringBuffer ret;
  1871. if (df) {
  1872. StringBuffer u("user:");
  1873. udesc->getUserName(u);
  1874. df->setProtect(u.str(),set);
  1875. }
  1876. else if(set)
  1877. throw MakeStringException(0, "ProtectLogicalFile: Could not find logical file %s", lfn.str());
  1878. }
  1879. static bool build_dfuplus_globals(int argc, const char *argv[], IProperties * globals)
  1880. {
  1881. for (int i = 1; i < argc; i++)
  1882. if (strchr(argv[i],'='))
  1883. globals->loadProp(argv[i]);
  1884. StringBuffer tmp;
  1885. if(globals->hasProp("encrypt")) {
  1886. encrypt(tmp.clear(),globals->queryProp("encrypt") ); // basic encryption at this stage
  1887. globals->setProp("encrypt",tmp.str());
  1888. }
  1889. if(globals->hasProp("decrypt")) {
  1890. encrypt(tmp.clear(),globals->queryProp("decrypt") ); // basic encryption at this stage
  1891. globals->setProp("decrypt",tmp.str());
  1892. }
  1893. return true;
  1894. }
  1895. FILESERVICES_API void FILESERVICES_CALL fsDfuPlusExec(ICodeContext * ctx,const char *_cmd)
  1896. {
  1897. if (!_cmd||!*_cmd)
  1898. return;
  1899. MemoryBuffer mb;
  1900. const char **argv;
  1901. StringBuffer cmdline;
  1902. if (strcmp(_cmd,"dfuplus ")!=0)
  1903. cmdline.append("dfuplus ");
  1904. cmdline.append(_cmd);
  1905. int argc = parseCommandLine(cmdline.str(),mb,argv);
  1906. Owned<IProperties> globals = createProperties(true);
  1907. if(!build_dfuplus_globals(argc, argv, globals))
  1908. throw MakeStringException(-1,"DfuPlusExec: invalid command line");
  1909. const char* server = globals->queryProp("server");
  1910. if (!server || !*server)
  1911. throw MakeStringException(-1,"DfuPlusExec: server url not specified");
  1912. const char* action = globals->queryProp("action");
  1913. if(!action || !*action)
  1914. throw MakeStringException(-1,"DfuPlusExec: no action specified");
  1915. if (ctx) {
  1916. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1917. StringBuffer tmp;
  1918. const char* username = globals->queryProp("username");
  1919. if (!username || !*username)
  1920. globals->setProp("username",udesc->getUserName(tmp.clear()).str());;
  1921. const char* passwd = globals->queryProp("password");
  1922. if (!passwd || !*passwd)
  1923. globals->setProp("password",udesc->getPassword(tmp.clear()).str());;
  1924. }
  1925. class cMsg: implements CDfuPlusMessagerIntercept
  1926. {
  1927. ICodeContext * ctx;
  1928. unsigned limit;
  1929. public:
  1930. cMsg(ICodeContext *_ctx)
  1931. {
  1932. limit = 0;
  1933. ctx = _ctx;
  1934. }
  1935. void info(const char *msg)
  1936. {
  1937. if (ctx&&(++limit<100))
  1938. WUmessage(ctx,ExceptionSeverityInformation,NULL,msg);
  1939. }
  1940. void err(const char *msg)
  1941. {
  1942. throw MakeStringException(-1,"DfuPlusExec: %s",msg);
  1943. }
  1944. } cmsg(ctx);
  1945. try {
  1946. Owned<CDfuPlusHelper> helper = new CDfuPlusHelper(LINK(globals.get()));
  1947. helper->msgintercept = &cmsg;
  1948. helper->doit();
  1949. }
  1950. catch(IException* e) {
  1951. EXCLOG(e,"fsDfuPlusExec");
  1952. throw;
  1953. }
  1954. }