fileservices.cpp 157 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #pragma warning (disable : 4786)
  14. #pragma warning (disable : 4297) // function assumed not to throw an exception but does
  15. #include "platform.h"
  16. #include "fileservices.hpp"
  17. #include "workunit.hpp"
  18. #include "jio.hpp"
  19. #include "jmisc.hpp"
  20. #include "daft.hpp"
  21. #include "dasess.hpp"
  22. #include "dautils.hpp"
  23. #include "daaudit.hpp"
  24. #include "dfuwu.hpp"
  25. #include "ws_fs_esp.ipp"
  26. #include "rmtsmtp.hpp"
  27. #include "dfuplus.hpp"
  28. #include "daclient.hpp"
  29. #include "dasds.hpp"
  30. #include "enginecontext.hpp"
  31. #include "environment.hpp"
  32. #define USE_DALIDFS
  33. #define SDS_LOCK_TIMEOUT 10000
  34. #define FILESERVICES_VERSION "FILESERVICES 2.1.4"
  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. "FILESERVICES 2.1.4",
  41. NULL };
  42. static const char * EclDefinition =
  43. "export FsFilenameRecord := record string name{maxlength(1023)}; integer8 size; string19 modified; end; \n"
  44. "export FsLogicalFileName := string{maxlength(255)}; \n"
  45. "export FsLogicalFileNameRecord := record FsLogicalFileName name; end; \n"
  46. "export FsLogicalFileInfoRecord := record(FsLogicalFileNameRecord) boolean superfile; integer8 size; integer8 rowcount; string19 modified; string owner{maxlength(255)}; string cluster{maxlength(255)}; end; \n"
  47. "export FsLogicalSuperSubRecord := record string supername{maxlength(255)}; string subname{maxlength(255)}; end; \n"
  48. "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"
  49. "export integer4 RECFMV_RECSIZE := -2; // special value for SprayFixed record size \n"
  50. "export integer4 RECFMVB_RECSIZE := -1; // special value for SprayFixed record size \n"
  51. "export integer4 PREFIX_VARIABLE_RECSIZE := -3; // special value for SprayFixed record size \n"
  52. "export integer4 PREFIX_VARIABLE_BIGENDIAN_RECSIZE := -4; // special value for SprayFixed record size \n"
  53. "export FsDropZone := string; \n"
  54. "export FsDropZoneRecord := record FsDropZone dropzone; end; \n"
  55. "export FileServices := SERVICE : time\n"
  56. " boolean FileExists(const varstring lfn, boolean physical=false) : c,context,entrypoint='fsFileExists'; \n"
  57. " DeleteLogicalFile(const varstring lfn,boolean ifexists=false) : c,action,context,entrypoint='fsDeleteLogicalFile'; \n"
  58. " SetReadOnly(const varstring lfn, boolean ro) : c,action,context,entrypoint='fsSetReadOnly'; \n"
  59. " RenameLogicalFile(const varstring oldname, const varstring newname, boolean allowoverwrite=false) : c,action,context,entrypoint='fsRenameLogicalFile_v2'; \n"
  60. " varstring GetBuildInfo() : c,pure,entrypoint='fsGetBuildInfo';\n"
  61. " 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'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmail_v2'; \n"
  62. " 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'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmailAttachText_v2'; \n"
  63. " 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'), const varstring cc='', const varstring bcc='', boolean highPriority=false) : c,action,context,entrypoint='fsSendEmailAttachData_v2'; \n"
  64. " varstring CmdProcess(const varstring prog, const varstring src) : c,action,entrypoint='fsCmdProcess'; \n"
  65. " string CmdProcess2(const varstring prog, const string src) : c,action,entrypoint='fsCmdProcess2'; \n"
  66. " 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsSprayFixed_v4'; \n"
  67. " 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,const varstring sourceCsvEscape='', boolean failIfNoSourceFile=false, boolean recordStructurePresent=false, boolean quotedTerminator=true, const varstring encoding='ascii', integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsSprayVariable_v8'; \n"
  68. " 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsSprayXml_v4'; \n"
  69. " SprayJson(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowPath='/', 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring username = '', const varstring userPw = '') : c,action,context,entrypoint='fsSprayJson'; \n"
  70. " 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"
  71. " 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, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1) : c,action,context,entrypoint='fsCopy_v3'; \n"
  72. " Replicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsReplicate'; \n"
  73. " CreateSuperFile(const varstring lsuperfn, boolean sequentialparts=false,boolean ifdoesnotexist=false) : c,action,context,entrypoint='fsCreateSuperFile'; \n"
  74. " boolean SuperFileExists(const varstring lsuperfn) : c,context,entrypoint='fsSuperFileExists'; \n"
  75. " DeleteSuperFile(const varstring lsuperfn,boolean deletesub=false) : c,action,context,entrypoint='fsDeleteSuperFile'; \n"
  76. " unsigned4 GetSuperFileSubCount(const varstring lsuperfn) : c,context,entrypoint='fsGetSuperFileSubCount'; \n"
  77. " varstring GetSuperFileSubName(const varstring lsuperfn,unsigned4 filenum,boolean abspath=false) : c,context,entrypoint='fsGetSuperFileSubName'; \n"
  78. " unsigned4 FindSuperFileSubName(const varstring lsuperfn,const varstring lfn) : c,context,entrypoint='fsFindSuperFileSubName'; \n"
  79. " StartSuperFileTransaction() : c,action,globalcontext,entrypoint='fsStartSuperFileTransaction'; \n"
  80. " AddSuperFile(const varstring lsuperfn,const varstring lfn,unsigned4 atpos=0,boolean addcontents=false, boolean strict=false) : c,action,globalcontext,entrypoint='fsAddSuperFile'; \n"
  81. " RemoveSuperFile(const varstring lsuperfn,const varstring lfn,boolean del=false,boolean remcontents=false) : c,action,globalcontext,entrypoint='fsRemoveSuperFile'; \n"
  82. " ClearSuperFile(const varstring lsuperfn,boolean del=false) : c,action,globalcontext,entrypoint='fsClearSuperFile'; \n"
  83. " RemoveOwnedSubFiles(const varstring lsuperfn,boolean del=false) : c,action,globalcontext,entrypoint='fsRemoveOwnedSubFiles'; \n"
  84. " DeleteOwnedSubFiles(const varstring lsuperfn) : c,action,globalcontext,entrypoint='fsDeleteOwnedSubFiles'; // Obsolete, use RemoveOwnedSubFiles\n"
  85. " SwapSuperFile(const varstring lsuperfn1,const varstring lsuperfn2) : c,action,globalcontext,entrypoint='fsSwapSuperFile'; \n"
  86. " ReplaceSuperFile(const varstring lsuperfn,const varstring lfn,const varstring bylfn) : c,action,globalcontext,entrypoint='fsReplaceSuperFile'; \n"
  87. " FinishSuperFileTransaction(boolean rollback=false) : c,action,globalcontext,entrypoint='fsFinishSuperFileTransaction'; \n"
  88. " varstring ForeignLogicalFileName(const varstring name, const varstring foreigndali='', boolean abspath=false, boolean omitClusterPrefix=false) : c,context,entrypoint='fsForeignLogicalFileName_v2'; \n"
  89. " varstring WaitDfuWorkunit(const varstring wuid, integer4 timeOut=-1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,globalcontext,entrypoint='fsWaitDfuWorkunit'; \n"
  90. " AbortDfuWorkunit(const varstring wuid,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,globalcontext,entrypoint='fsAbortDfuWorkunit'; \n"
  91. " MonitorLogicalFileName(const varstring event_name, const varstring name, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsMonitorLogicalFileName'; \n"
  92. " MonitorFile(const varstring event_name, 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"
  93. " 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsfSprayFixed_v4'; \n"
  94. " 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,const varstring sourceCsvEscape='', boolean failIfNoSourceFile=false, boolean recordStructurePresent=false, boolean quotedTerminator=true, varstring encoding='ascii', integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsfSprayVariable_v8'; \n"
  95. " 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false) : c,action,context,entrypoint='fsfSprayXml_v4'; \n"
  96. " varstring fSprayJson(const varstring sourceIP, const varstring sourcePath, integer4 sourceMaxRecordSize=8192, const varstring sourceRowPath='/', 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, boolean failIfNoSourceFile=false, integer4 expireDays=-1, const varstring dfuServerQueue='', boolean noSplit=false, const varstring username = '', const varstring userPw = '') : c,action,context,entrypoint='fsfSprayJson'; \n"
  97. " 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"
  98. " 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, boolean preserveCompression=true, boolean noSplit=false, integer4 expireDays=-1) : c,action,context,entrypoint='fsfCopy_v3'; \n"
  99. " varstring fMonitorLogicalFileName(const varstring event_name, const varstring name, integer4 shotcount=1,const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfMonitorLogicalFileName'; \n"
  100. " varstring fMonitorFile(const varstring event_name, 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"
  101. " varstring fReplicate(const varstring logicalName, integer4 timeOut=-1, const varstring espServerIpPort=GETENV('ws_fs_server')) : c,action,context,entrypoint='fsfReplicate'; \n"
  102. " varstring GetFileDescription(const varstring lfn) : c,context,entrypoint='fsGetFileDescription'; \n"
  103. " SetFileDescription(const varstring lfn,const varstring val) : c,action,context,entrypoint='fsSetFileDescription'; \n"
  104. " dataset(FsFilenameRecord) RemoteDirectory(const varstring machineIP,const varstring dir,const varstring mask='*',boolean sub=false) : c,entrypoint='fsRemoteDirectory';\n"
  105. " dataset(FsLogicalFileInfoRecord) LogicalFileList(const varstring namepattern='*',boolean includenormal=true,boolean includesuper=false,boolean unknownszero=false,const varstring foreigndali='') : c,context,entrypoint='fsLogicalFileList';\n"
  106. " dataset(FsLogicalFileNameRecord) SuperFileContents(const varstring lsuperfn,boolean recurse=false) : c,context,entrypoint='fsSuperFileContents';\n"
  107. " dataset(FsLogicalFileNameRecord) LogicalFileSuperOwners(const varstring lfn) : c,context,entrypoint='fsLogicalFileSuperOwners';\n"
  108. " varstring ExternalLogicalFileName(const varstring location, const varstring path,boolean abspath=true) : c,entrypoint='fsExternalLogicalFileName'; \n"
  109. " integer4 CompareFiles(const varstring lfn1, const varstring lfn2,boolean logicalonly=true,boolean usecrcs=false) : c,context,entrypoint='fsCompareFiles'; \n"
  110. " varstring VerifyFile(const varstring lfn, boolean usecrcs) : c,action,context,entrypoint='fsVerifyFile'; \n"
  111. " 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, boolean noSplit=false, integer4 expireDays=-1, const varstring username = '', const varstring userPw = ''): c,action,context,entrypoint='fsRemotePull_v3'; \n"
  112. " 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, boolean noSplit=false, integer4 expireDays=-1, const varstring username = '', const varstring userPw = ''): c,action,context,entrypoint='fsfRemotePull_v3'; \n"
  113. " dataset(FsLogicalSuperSubRecord) LogicalFileSuperSubList() : c,context,entrypoint='fsLogicalFileSuperSubList';\n"
  114. " PromoteSuperFileList(const set of varstring lsuperfns,const varstring addhead='',boolean deltail=false,boolean createonlyonesuperfile=false,boolean reverse=false) : c,action,context,entrypoint='fsPromoteSuperFileList'; \n"
  115. " 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"
  116. " unsigned8 getUniqueInteger(const varstring foreigndali='') : c,context,entrypoint='fsGetUniqueInteger'; \n"
  117. " 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"
  118. " 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"
  119. " RemoveFileRelationship(const varstring primary, const varstring secondary, const varstring primaryflds='', const varstring secondaryflds='', const varstring kind='link') : c,action,context,entrypoint='fsRemoveFileRelationship'; \n"
  120. " varstring GetColumnMapping( const varstring LogicalFileName): c,context,entrypoint='fsfGetColumnMapping'; \n"
  121. " SetColumnMapping( const varstring LogicalFileName, const varstring mapping): c,context,entrypoint='fsSetColumnMapping'; \n"
  122. " varstring RfsQuery( const varstring server, const varstring query): c,entrypoint='fsfRfsQuery'; \n"
  123. " RfsAction( const varstring server, const varstring query): c,entrypoint='fsRfsAction'; \n"
  124. " varstring GetHostName( const varstring ipaddress ): c,entrypoint='fsfGetHostName'; \n"
  125. " varstring ResolveHostName( const varstring hostname ): c,entrypoint='fsfResolveHostName'; \n"
  126. " MoveExternalFile(const varstring location, const varstring frompath, const varstring topath): c,action,context,entrypoint='fsMoveExternalFile'; \n"
  127. " DeleteExternalFile(const varstring location, const varstring path): c,action,context,entrypoint='fsDeleteExternalFile'; \n"
  128. " CreateExternalDirectory(const varstring location, const varstring path): c,action,context,entrypoint='fsCreateExternalDirectory'; \n"
  129. " varstring GetLogicalFileAttribute(const varstring lfn,const varstring attrname) : c,context,entrypoint='fsfGetLogicalFileAttribute'; \n"
  130. " ProtectLogicalFile(const varstring lfn,boolean set=true) : c,context,entrypoint='fsProtectLogicalFile'; \n"
  131. " DfuPlusExec(const varstring cmdline) : c,context,entrypoint='fsDfuPlusExec'; \n"
  132. " varstring GetEspURL(const varstring username = '', const varstring userPW = '') : c,once,entrypoint='fsGetEspURL'; \n"
  133. " varstring GetDefaultDropZone() : c,once,entrypoint='fsGetDefaultDropZone'; \n"
  134. " dataset(FsDropZoneRecord) GetDropZones() : c,context,entrypoint='fsGetDropZones'; \n"
  135. " integer4 GetExpireDays(const varstring lfn) : c,context,entrypoint='fsGetExpireDays'; \n"
  136. " SetExpireDays(const varstring lfn, integer4 expireDays) : c,context,entrypoint='fsSetExpireDays'; \n"
  137. " ClearExpireDays(const varstring lfn) : c,context,entrypoint='fsClearExpireDays'; \n"
  138. "END;";
  139. #define WAIT_SECONDS 30
  140. FILESERVICES_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  141. {
  142. if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
  143. {
  144. ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
  145. pbx->compatibleVersions = compatibleVersions;
  146. }
  147. else if (pb->size != sizeof(ECLPluginDefinitionBlock))
  148. return false;
  149. pb->magicVersion = PLUGIN_VERSION;
  150. pb->version = FILESERVICES_VERSION;
  151. pb->moduleName = "lib_fileservices";
  152. pb->ECL = EclDefinition;
  153. pb->flags = PLUGIN_IMPLICIT_MODULE;
  154. pb->description = "FileServices library";
  155. return true;
  156. }
  157. namespace nsFileservices {
  158. IPluginContext * parentCtx = NULL;
  159. static IConstWorkUnit * getWorkunit(ICodeContext * ctx)
  160. {
  161. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  162. StringAttr wuid;
  163. wuid.setown(ctx->getWuid());
  164. return factory->openWorkUnit(wuid);
  165. }
  166. static void setWorkunitState(ICodeContext * ctx, WUState state, const char * msg)
  167. {
  168. Owned<IWorkUnit> wu = ctx->updateWorkUnit();
  169. if (wu)
  170. {
  171. wu->setState(state);//resets stateEx
  172. if (msg)
  173. wu->setStateEx(msg);
  174. wu->commit();
  175. }
  176. }
  177. #ifndef _CONTAINERIZED
  178. static IConstEnvironment * openDaliEnvironment()
  179. {
  180. if (daliClientActive())
  181. {
  182. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  183. return factory->openEnvironment();
  184. }
  185. return NULL;
  186. }
  187. static IPropertyTree *getEnvironmentTree(IConstEnvironment * daliEnv)
  188. {
  189. if (daliEnv)
  190. return &daliEnv->getPTree(); // No need to clone since daliEnv ensures connection stays alive.
  191. return getHPCCEnvironment();
  192. }
  193. #endif
  194. static void setServerAccess(CClientFileSpray &server, IConstWorkUnit * wu)
  195. {
  196. SCMStringBuffer token;
  197. wu->getWorkunitDistributedAccessToken(token);
  198. server.setUsernameToken(wu->queryUser(), token.str(), "");//use workunit token as password
  199. }
  200. static StringArray availableWsFS;
  201. static CriticalSection espURLcrit;
  202. static void addConfiguredWsFSUrl(const char * url)
  203. {
  204. CriticalBlock b(espURLcrit);
  205. availableWsFS.appendUniq(url);
  206. }
  207. static void setContainerLocalCertificate(IEspClientRpcSettings &rpc)
  208. {
  209. #ifdef _CONTAINERIZED
  210. //will only affect HTTPS
  211. rpc.setMtlsSecretName("local");
  212. #endif
  213. }
  214. static bool contactWsFS(const char * espurl, IConstWorkUnit * wu)
  215. {
  216. CClientFileSpray server;
  217. server.addServiceUrl(espurl);
  218. setServerAccess(server, wu);
  219. try
  220. {
  221. Owned<IClientEchoDateTime> req = server.createEchoDateTimeRequest();
  222. setContainerLocalCertificate(req->rpc());
  223. Owned<IClientEchoDateTimeResponse> result = server.EchoDateTime(req);
  224. if (result->getResult())
  225. return true;
  226. }
  227. catch(IException *ie)
  228. {
  229. StringBuffer error;
  230. ie->errorMessage(error);
  231. PROGLOG("Could not contact WsFS: '%s': %s",espurl, error.str());
  232. ie->Release();
  233. }
  234. catch(...)
  235. {
  236. PROGLOG("Could not contact WsFS: '%s'",espurl);
  237. }
  238. return false;
  239. }
  240. static const char * getNextAliveWsFSURL(IConstWorkUnit * wu)
  241. {
  242. CriticalBlock b(espURLcrit);
  243. for (int index = 0; index < availableWsFS.length(); index++)
  244. {
  245. const char * currentUrl = availableWsFS.item(index);
  246. if (contactWsFS(currentUrl, wu))
  247. return currentUrl;
  248. }
  249. return nullptr;
  250. }
  251. static bool isUrlListEmpty()
  252. {
  253. CriticalBlock b(espURLcrit);
  254. return availableWsFS.length() == 0;
  255. }
  256. static const char *getAccessibleEspServerURL(const char *param, IConstWorkUnit * wu)
  257. {
  258. if (param&&*param)
  259. return param;
  260. #ifdef _CONTAINERIZED
  261. UNIMPLEMENTED_X("CONTAINERIZED(getAccessibleEspServerURL)");
  262. #else
  263. CriticalBlock b(espURLcrit);
  264. if (isUrlListEmpty())
  265. {
  266. Owned<IConstEnvironment> daliEnv = openDaliEnvironment();
  267. Owned<IPropertyTree> env = getEnvironmentTree(daliEnv);
  268. if (env.get())
  269. {
  270. StringBuffer wsFSUrl;
  271. StringBuffer espInstanceComputerName;
  272. StringBuffer bindingProtocol;
  273. StringBuffer xpath;
  274. StringBuffer instanceAddress;
  275. StringBuffer espServiceType;
  276. Owned<IPropertyTreeIterator> espProcessIter = env->getElements("Software/EspProcess");
  277. ForEach(*espProcessIter)
  278. {
  279. Owned<IPropertyTreeIterator> espBindingIter = espProcessIter->query().getElements("EspBinding");
  280. ForEach(*espBindingIter)
  281. {
  282. espBindingIter->query().getProp("@service",wsFSUrl.clear());
  283. xpath.setf("Software/EspService[@name=\"%s\"]/Properties/@type", wsFSUrl.str());
  284. if(env->getProp(xpath.str(), espServiceType.clear()))
  285. {
  286. if (!espServiceType.isEmpty() && (strieq(espServiceType.str(),"WsSMC")|| strieq(espServiceType.str(),"FileSpray_Serv")))
  287. {
  288. if (espBindingIter->query().getProp("@protocol",bindingProtocol.clear()))
  289. {
  290. Owned<IPropertyTreeIterator> espInstanceIter = espProcessIter->query().getElements("Instance");
  291. ForEach(*espInstanceIter)
  292. {
  293. if (espInstanceIter->query().getProp("@computer",espInstanceComputerName.clear()))
  294. {
  295. xpath.setf("Hardware/Computer[@name=\"%s\"]/@netAddress",espInstanceComputerName.str());
  296. if (env->getProp(xpath.str(),instanceAddress.clear()))
  297. {
  298. wsFSUrl.setf("%s://%s:%d/FileSpray", bindingProtocol.str(), instanceAddress.str(), espBindingIter->query().getPropInt("@port",8010)); // FileSpray seems to be fixed
  299. addConfiguredWsFSUrl(wsFSUrl.str());
  300. }
  301. }
  302. }
  303. }
  304. }//EclWatch || ws_fs binding
  305. }
  306. }//ESPBinding
  307. }//ESPProcess
  308. }
  309. if (isUrlListEmpty())
  310. throw MakeStringException(-1,"Could not find any WS FileSpray in the target HPCC configuration.");
  311. }
  312. const char * nextWsFSUrl = getNextAliveWsFSURL(wu);
  313. if (!nextWsFSUrl||!*nextWsFSUrl)
  314. throw MakeStringException(-1,"Could not contact any of the configured WS FileSpray instances, check HPCC configuration and system health.");
  315. PROGLOG("FileServices: Targeting ESP WsFileSpray URL: %s", nextWsFSUrl);
  316. return nextWsFSUrl;
  317. #endif
  318. }
  319. StringBuffer & constructLogicalName(IConstWorkUnit * wu, const char * partialLogicalName, StringBuffer & result)
  320. {
  321. if (partialLogicalName == NULL)
  322. throw MakeStringException(0, "Logical Name Cannot be blank");
  323. if (*partialLogicalName == '~')
  324. ++partialLogicalName;
  325. else if (wu)
  326. {
  327. StringBuffer prefix;
  328. wu->getScope(StringBufferAdaptor(prefix));
  329. if (prefix.length())
  330. result.append(prefix).append("::");
  331. }
  332. result.append(partialLogicalName);
  333. if ((result.length()>0)&&(strstr(result.str(),"::")==NULL)&&(result.charAt(0)!='#'))
  334. result.insert(0,".::");
  335. return result;
  336. }
  337. StringBuffer & constructLogicalName(ICodeContext * ctx, const char * partialLogicalName, StringBuffer & result)
  338. {
  339. Owned<IConstWorkUnit> wu;
  340. if (partialLogicalName&&(*partialLogicalName != '~'))
  341. wu.setown(getWorkunit(ctx));
  342. return constructLogicalName(wu, partialLogicalName, result);
  343. }
  344. static void WUmessage(ICodeContext *ctx, ErrorSeverity sev, const char *fn, const char *msg)
  345. {
  346. StringBuffer s("fileservices");
  347. if (fn)
  348. s.append(", ").append(fn);
  349. ctx->addWuExceptionEx(msg, 0, sev, MSGAUD_audit, s.str()); // use plain code context
  350. return;
  351. }
  352. static void AuditMessage(ICodeContext *ctx,
  353. const char *func,
  354. const char *lfn1,
  355. const char *lfn2=NULL)
  356. {
  357. // FileServices,WUID,user,function,LFN1,LFN2
  358. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  359. StringBuffer aln;
  360. StringAttr wuid;
  361. wuid.setown(ctx->getWuid());
  362. aln.append(",FileAccess,FileServices,").append(func).append(',').append(wuid).append(',');
  363. if (udesc)
  364. udesc->getUserName(aln);
  365. if (lfn1&&*lfn1) {
  366. aln.append(',').append(lfn1);
  367. if (lfn2&&*lfn2) {
  368. aln.append(',').append(lfn2);
  369. }
  370. }
  371. LOG(MCauditInfo,"%s",aln.str());
  372. }
  373. }//namespace
  374. using namespace nsFileservices;
  375. FILESERVICES_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
  376. FILESERVICES_API char * FILESERVICES_CALL fsGetBuildInfo(void)
  377. {
  378. return CTXSTRDUP(parentCtx, FILESERVICES_VERSION);
  379. }
  380. //-------------------------------------------------------------------------------------------------------------------------------------------
  381. FILESERVICES_API void FILESERVICES_CALL fsDeleteLogicalFile(ICodeContext *ctx, const char *name,bool ifexists)
  382. {
  383. StringBuffer lfn;
  384. constructLogicalName(ctx, name, lfn);
  385. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  386. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  387. StringBuffer uname;
  388. DBGLOG("Deleting NS logical file %s for user %s", lfn.str(),udesc?udesc->getUserName(uname).str():"");
  389. if (queryDistributedFileDirectory().removeEntry(lfn.str(),udesc,transaction, INFINITE, true))
  390. {
  391. StringBuffer s("DeleteLogicalFile ('");
  392. s.append(lfn);
  393. if (transaction->active())
  394. s.append("') added to transaction");
  395. else
  396. s.append("') done");
  397. WUmessage(ctx,SeverityInformation,NULL,s.str());
  398. AuditMessage(ctx,"DeleteLogicalFile",lfn.str());
  399. }
  400. else if (!ifexists)
  401. {
  402. throw MakeStringException(0, "Could not delete file %s", lfn.str());
  403. }
  404. }
  405. FILESERVICES_API bool FILESERVICES_CALL fsFileExists(ICodeContext *ctx, const char *name, bool physical)
  406. {
  407. StringBuffer lfn;
  408. constructLogicalName(ctx, name, lfn);
  409. if (physical)
  410. return queryDistributedFileDirectory().existsPhysical(lfn.str(),ctx->queryUserDescriptor());
  411. return queryDistributedFileDirectory().exists(lfn.str(),ctx->queryUserDescriptor(),false,false);
  412. }
  413. FILESERVICES_API bool FILESERVICES_CALL fsFileValidate(ICodeContext *ctx, const char *name)
  414. {
  415. StringBuffer lfn;
  416. constructLogicalName(ctx, name, lfn);
  417. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  418. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false, false, false, nullptr, defaultPrivilegedUser);
  419. if (df)
  420. {
  421. Owned<IDistributedFilePartIterator> partIter = df->getIterator();
  422. ForEach(*partIter)
  423. {
  424. IDistributedFilePart & part = partIter->query();
  425. unsigned numCopies = part.numCopies();
  426. bool gotone = false;
  427. offset_t partSize = (offset_t)-1;
  428. for (unsigned copy=0; copy < numCopies; copy++)
  429. {
  430. RemoteFilename remote;
  431. part.getFilename(remote,copy);
  432. OwnedIFile file = createIFile(remote);
  433. if (file->exists())
  434. {
  435. offset_t thisSize = file->size();
  436. if (gotone && (partSize != thisSize))
  437. throw MakeStringException(0, "Inconsistent file sizes for %s", lfn.str());
  438. partSize = thisSize;
  439. gotone = true;
  440. }
  441. }
  442. if (!gotone)
  443. return false;
  444. }
  445. return true;
  446. }
  447. return false;
  448. }
  449. FILESERVICES_API void FILESERVICES_CALL fsSetReadOnly(ICodeContext *ctx, const char *name, bool ro)
  450. {
  451. StringBuffer lfn;
  452. constructLogicalName(ctx, name, lfn);
  453. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  454. Owned<IException> error;
  455. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, true, false, false, nullptr, defaultPrivilegedUser);
  456. if (df)
  457. {
  458. LOG(MCauditInfo, "Set ReadOnly: %s", name);
  459. Owned<IDistributedFilePartIterator> partIter = df->getIterator();
  460. ForEach(*partIter)
  461. {
  462. IDistributedFilePart & part = partIter->query();
  463. unsigned numCopies = part.numCopies();
  464. for (unsigned copy=0; copy < numCopies; copy++)
  465. {
  466. RemoteFilename remote;
  467. part.getFilename(remote,copy);
  468. OwnedIFile file = createIFile(remote);
  469. try
  470. {
  471. file->setReadOnly(ro);
  472. }
  473. catch (IException * e)
  474. {
  475. EXCLOG(e);
  476. e->Release();
  477. }
  478. }
  479. }
  480. return;
  481. }
  482. if (!error)
  483. error.setown(MakeStringException(0, "Could not find logical file %s", lfn.str()));
  484. throw error.getClear();
  485. }
  486. FILESERVICES_API void FILESERVICES_CALL implementRenameLogicalFile(ICodeContext *ctx, const char *oldname, const char *newname, const bool overwrite)
  487. {
  488. StringBuffer oldLfn, newLfn;
  489. constructLogicalName(ctx, oldname, oldLfn);
  490. constructLogicalName(ctx, newname, newLfn);
  491. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  492. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  493. IDistributedFileDirectory &distributedDirectory = queryDistributedFileDirectory();
  494. if (!distributedDirectory.exists(oldLfn.str(), udesc, false, false))
  495. throw MakeStringException(0, "Old file %s doesn't exists.", oldLfn.str());
  496. if (overwrite && distributedDirectory.exists(newLfn.str(), udesc, false, false))
  497. fsDeleteLogicalFile(ctx, newname, true);
  498. try {
  499. distributedDirectory.renamePhysical(oldLfn.str(), newLfn.str(), udesc, transaction);
  500. StringBuffer s("RenameLogicalFile ('");
  501. s.append(oldLfn).append(", '").append(newLfn).append("') done");
  502. WUmessage(ctx, SeverityInformation, NULL, s.str());
  503. AuditMessage(ctx, "RenameLogicalFile", oldLfn.str(), newLfn.str());
  504. }
  505. catch (IException *e)
  506. {
  507. StringBuffer s;
  508. e->errorMessage(s);
  509. WUmessage(ctx, SeverityWarning, "RenameLogicalFile", s.str());
  510. throw e;
  511. }
  512. }
  513. FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile(ICodeContext *ctx, const char *oldname, const char *newname)
  514. {
  515. implementRenameLogicalFile(ctx, oldname, newname, false);
  516. }
  517. FILESERVICES_API void FILESERVICES_CALL fsRenameLogicalFile_v2(ICodeContext *ctx, const char *oldname, const char *newname, const bool overwrite)
  518. {
  519. implementRenameLogicalFile(ctx, oldname, newname, overwrite);
  520. }
  521. FILESERVICES_API void FILESERVICES_CALL fsSendEmail_v2(ICodeContext * ctx, const char * to, const char * subject, const char * body, const char * mailServer, unsigned port, const char * sender, const char *cc, const char *bcc, bool highPriority)
  522. {
  523. StringArray warnings;
  524. sendEmail( to, cc, bcc, subject, body, mailServer, port, sender, &warnings, highPriority);
  525. ForEachItemIn(i,warnings)
  526. WUmessage(ctx, SeverityWarning, "SendEmail", warnings.item(i));
  527. }
  528. 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)
  529. {
  530. fsSendEmail_v2(ctx, to, subject, body, mailServer, port, sender, nullptr, nullptr, false);
  531. }
  532. FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachText_v2(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, const char *cc, const char *bcc, bool highPriority)
  533. {
  534. StringArray warnings;
  535. sendEmailAttachText(to, cc, bcc, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority);
  536. ForEachItemIn(i,warnings)
  537. WUmessage(ctx, SeverityWarning, "SendEmailAttachText", warnings.item(i));
  538. }
  539. 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)
  540. {
  541. fsSendEmailAttachText_v2(ctx, to, subject, body, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false);
  542. }
  543. FILESERVICES_API void FILESERVICES_CALL fsSendEmailAttachData_v2(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, const char *cc, const char *bcc, bool highPriority)
  544. {
  545. StringArray warnings;
  546. sendEmailAttachData(to, cc, bcc, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, &warnings, highPriority);
  547. ForEachItemIn(i,warnings)
  548. WUmessage(ctx, SeverityWarning, "SendEmailAttachData", warnings.item(i));
  549. }
  550. 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)
  551. {
  552. fsSendEmailAttachData_v2(ctx, to, subject, body, lenAttachment, attachment, mimeType, attachmentName, mailServer, port, sender, nullptr, nullptr, false);
  553. }
  554. FILESERVICES_API char * FILESERVICES_CALL fsCmdProcess(const char *prog, const char *src)
  555. {
  556. StringBuffer in, out, err;
  557. in.append(src);
  558. runExternalCommand(out, err, prog, in);
  559. return CTXSTRDUP(parentCtx, out.str());
  560. }
  561. FILESERVICES_API void FILESERVICES_CALL fsCmdProcess2(unsigned & tgtLen, char * & tgt, const char *prog, unsigned srcLen, const char * src)
  562. {
  563. StringBuffer in, out, err;
  564. in.append(srcLen, src);
  565. runExternalCommand(out, err, prog, in);
  566. tgtLen = out.length();
  567. tgt = (char *)CTXDUP(parentCtx, out.str(), out.length());
  568. }
  569. static void blockUntilComplete(const char * label, IClientFileSpray &server, ICodeContext *ctx, const char * wuid, int timeOut, StringBuffer *stateout=NULL, bool monitoringok=false)
  570. {
  571. if (!wuid || strcmp(wuid, "") == 0)
  572. return;
  573. if (timeOut == 0)
  574. return;
  575. CTimeMon time(timeOut);
  576. unsigned polltime = 1;
  577. VStringBuffer reason("Blocked by fileservice activity: %s",label);
  578. setWorkunitState(ctx, WUStateBlocked, reason.str());
  579. while(true)
  580. {
  581. Owned<IClientGetDFUWorkunit> req = server.createGetDFUWorkunitRequest();
  582. setContainerLocalCertificate(req->rpc());
  583. req->setWuid(wuid);
  584. Owned<IClientGetDFUWorkunitResponse> result = server.GetDFUWorkunit(req);
  585. const IMultiException* excep = &result->getExceptions();
  586. if ((excep != NULL) && (excep->ordinality() > 0))
  587. {
  588. setWorkunitState(ctx, WUStateRunning, NULL);
  589. StringBuffer errmsg;
  590. excep->errorMessage(errmsg);
  591. throw MakeStringExceptionDirect(0, errmsg.str());
  592. }
  593. IConstDFUWorkunit & dfuwu = result->getResult();
  594. bool aborting = false;
  595. Owned<IWorkUnit> wu = ctx->updateWorkUnit(); // may return NULL
  596. if (wu.get()) { // if updatable (e.g. not hthor with no agent context)
  597. aborting = wu->aborting();
  598. StringBuffer wuScope, ElapsedLabel, RemainingLabel;
  599. wuScope.appendf("%s-%s", label, dfuwu.getID());
  600. ElapsedLabel.append(wuScope).append(" (Elapsed) ");
  601. RemainingLabel.append(wuScope).append(" (Remaining) ");
  602. //MORE: I think this are intended to replace the timing information, but will currently combine
  603. updateWorkunitStat(wu, SSTdfuworkunit, wuScope, StTimeElapsed, ElapsedLabel, milliToNano(time.elapsed()));
  604. updateWorkunitStat(wu, SSTdfuworkunit, wuScope, StTimeRemaining, RemainingLabel, milliToNano(dfuwu.getSecsLeft()*1000));
  605. wu->setApplicationValue(label, dfuwu.getID(), dfuwu.getSummaryMessage(), true);
  606. wu->commit();
  607. wu.clear();
  608. }
  609. DFUstate state = (DFUstate)dfuwu.getState();
  610. if (stateout)
  611. stateout->clear().append(dfuwu.getStateMessage());
  612. switch(state)
  613. {
  614. case DFUstate_unknown:
  615. case DFUstate_scheduled:
  616. case DFUstate_queued:
  617. case DFUstate_started:
  618. case DFUstate_aborting:
  619. break;
  620. case DFUstate_monitoring:
  621. if (monitoringok)
  622. {
  623. setWorkunitState(ctx, WUStateRunning, NULL);
  624. return;
  625. }
  626. break;
  627. case DFUstate_aborted:
  628. case DFUstate_failed:
  629. setWorkunitState(ctx, WUStateRunning, NULL);
  630. throw MakeStringException(0, "DFUServer Error %s", dfuwu.getSummaryMessage());
  631. case DFUstate_finished:
  632. setWorkunitState(ctx, WUStateRunning, NULL);
  633. return;
  634. }
  635. if (aborting)
  636. {
  637. Owned<IClientAbortDFUWorkunit> abortReq = server.createAbortDFUWorkunitRequest();
  638. setContainerLocalCertificate(abortReq->rpc());
  639. abortReq->setWuid(wuid);
  640. Linked<IClientAbortDFUWorkunitResponse> abortResp = server.AbortDFUWorkunit(abortReq);
  641. setWorkunitState(ctx, WUStateRunning, NULL);
  642. // Add warning of DFU Abort Request - should this be information ---
  643. StringBuffer s("DFU Workunit Abort Requested for ");
  644. s.append(wuid);
  645. WUmessage(ctx,SeverityWarning,"blockUntilComplete",s.str());
  646. throw MakeStringException(0, "Workunit abort request received");
  647. }
  648. if (time.timedout()) {
  649. unsigned left = dfuwu.getSecsLeft();
  650. setWorkunitState(ctx, WUStateRunning, NULL);
  651. if (left)
  652. throw MakeStringException(0, "%s timed out, DFU Secs left: %d)", label, left);
  653. throw MakeStringException(0, "%s timed out)", label);
  654. }
  655. Sleep(polltime*1000);
  656. polltime *= 2;
  657. if (polltime>WAIT_SECONDS)
  658. polltime = WAIT_SECONDS;
  659. }
  660. setWorkunitState(ctx, WUStateRunning, NULL);
  661. }
  662. //----------------------------------------------------------------------------------
  663. FILESERVICES_API char * FILESERVICES_CALL implementSprayFixed(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  664. {
  665. LOG(MCauditInfo, "Spray: %s", destinationLogicalName);
  666. CClientFileSpray server;
  667. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  668. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort, wu));
  669. setServerAccess(server, wu);
  670. Owned<IClientSprayFixed> req = server.createSprayFixedRequest();
  671. setContainerLocalCertificate(req->rpc());
  672. StringBuffer logicalName;
  673. constructLogicalName(wu, destinationLogicalName, logicalName);
  674. req->setSourceIP(sourceIP);
  675. req->setSourcePath(sourcePath);
  676. req->setSourceRecordSize(recordSize);
  677. req->setDestGroup(destinationGroup);
  678. req->setDestLogicalName(logicalName.str());
  679. req->setOverwrite(overwrite);
  680. req->setReplicate(replicate);
  681. req->setCompress(compress);
  682. if (maxConnections != -1)
  683. req->setMaxConnections(maxConnections);
  684. if (failIfNoSourceFile)
  685. req->setFailIfNoSourceFile(true);
  686. req->setExpireDays(expireDays);
  687. if (!isEmptyString(dfuServerQueue))
  688. req->setDFUServerQueue(dfuServerQueue);
  689. if (noSplit)
  690. req->setNosplit(true);
  691. Owned<IClientSprayFixedResponse> result = server.SprayFixed(req);
  692. StringBuffer wuid(result->getWuid());
  693. if (!wuid.length())
  694. {
  695. const IMultiException* excep = &result->getExceptions();
  696. if ((excep != NULL) && (excep->ordinality() > 0))
  697. {
  698. StringBuffer errmsg;
  699. excep->errorMessage(errmsg);
  700. throw MakeStringExceptionDirect(0, errmsg.str());
  701. }
  702. else
  703. {
  704. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  705. }
  706. }
  707. wu.clear();
  708. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  709. return wuid.detach();
  710. }
  711. 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, bool failIfNoSourceFile)
  712. {
  713. CTXFREE(parentCtx, implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, -1, nullptr, false));
  714. }
  715. FILESERVICES_API void FILESERVICES_CALL fsSprayFixed_v2(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, bool failIfNoSourceFile, int expireDays)
  716. {
  717. CTXFREE(parentCtx, implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, nullptr, false));
  718. }
  719. FILESERVICES_API void FILESERVICES_CALL fsSprayFixed_v3(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue)
  720. {
  721. CTXFREE(parentCtx, implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, false));
  722. }
  723. FILESERVICES_API void FILESERVICES_CALL fsSprayFixed_v4(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  724. {
  725. CTXFREE(parentCtx, implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit));
  726. }
  727. 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, bool failIfNoSourceFile)
  728. {
  729. return implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, -1, nullptr, false);
  730. }
  731. FILESERVICES_API char * FILESERVICES_CALL fsfSprayFixed_v2(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, bool failIfNoSourceFile, int expireDays)
  732. {
  733. return implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, nullptr, false);
  734. }
  735. FILESERVICES_API char * FILESERVICES_CALL fsfSprayFixed_v3(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue)
  736. {
  737. return implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, false);
  738. }
  739. FILESERVICES_API char * FILESERVICES_CALL fsfSprayFixed_v4(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  740. {
  741. return implementSprayFixed(ctx, sourceIP, sourcePath, recordSize, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit);
  742. }
  743. //----------------------------------------------------------------------------------
  744. static char * implementSprayVariable(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char * sourceCsvSeparate, const char * sourceCsvTerminate, const char * sourceCsvQuote, const char * sourceCsvEscape, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays, const char * dfuServerQueue, bool noSplit)
  745. {
  746. LOG(MCauditInfo, "Spray: %s", destinationLogicalName);
  747. CClientFileSpray server;
  748. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  749. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  750. setServerAccess(server, wu);
  751. Owned<IClientSprayVariable> req = server.createSprayVariableRequest();
  752. setContainerLocalCertificate(req->rpc());
  753. StringBuffer logicalName;
  754. constructLogicalName(wu, destinationLogicalName, logicalName);
  755. req->setSourceIP(sourceIP);
  756. req->setSourcePath(sourcePath);
  757. req->setSourceMaxRecordSize(sourceMaxRecordSize);
  758. req->setSourceFormat(CDFUfileformat::decode(encoding));
  759. req->setSourceCsvSeparate(sourceCsvSeparate);
  760. if (sourceCsvSeparate && *sourceCsvSeparate == '\0')
  761. req->setNoSourceCsvSeparator(true);
  762. req->setSourceCsvTerminate(sourceCsvTerminate);
  763. req->setSourceCsvQuote(sourceCsvQuote);
  764. if (sourceCsvEscape && *sourceCsvEscape)
  765. req->setSourceCsvEscape(sourceCsvEscape);
  766. req->setDestGroup(destinationGroup);
  767. req->setDestLogicalName(logicalName.str());
  768. req->setOverwrite(overwrite);
  769. req->setReplicate(replicate);
  770. req->setCompress(compress);
  771. if (maxConnections != -1)
  772. req->setMaxConnections(maxConnections);
  773. if (failIfNoSourceFile)
  774. req->setFailIfNoSourceFile(true);
  775. if (recordStructurePresent)
  776. req->setRecordStructurePresent(true);
  777. if (!quotedTerminator)
  778. req->setQuotedTerminator(false);
  779. req->setExpireDays(expireDays);
  780. if (!isEmptyString(dfuServerQueue))
  781. req->setDFUServerQueue(dfuServerQueue);
  782. if (noSplit)
  783. req->setNosplit(true);
  784. Owned<IClientSprayResponse> result = server.SprayVariable(req);
  785. StringBuffer wuid(result->getWuid());
  786. if (!wuid.length())
  787. {
  788. const IMultiException* excep = &result->getExceptions();
  789. if ((excep != NULL) && (excep->ordinality() > 0))
  790. {
  791. StringBuffer errmsg;
  792. excep->errorMessage(errmsg);
  793. throw MakeStringExceptionDirect(0, errmsg.str());
  794. }
  795. else
  796. {
  797. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  798. }
  799. }
  800. wu.clear();
  801. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  802. return wuid.detach();
  803. }
  804. 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, bool failIfNoSourceFile)
  805. {
  806. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, NULL, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, false, true, "ascii", -1, nullptr, false));
  807. }
  808. 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, bool failIfNoSourceFile)
  809. {
  810. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, NULL, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, false, true, "ascii", -1, nullptr, false);
  811. }
  812. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable2(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, const char * csvEscape, bool failIfNoSourceFile)
  813. {
  814. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, false, true, "ascii", -1, nullptr, false));
  815. }
  816. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable2(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, const char * csvEscape, bool failIfNoSourceFile)
  817. {
  818. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, false, true, "ascii", -1, nullptr, false);
  819. }
  820. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v3(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent)
  821. {
  822. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, true, "ascii", -1, nullptr, false));
  823. }
  824. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v3(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent)
  825. {
  826. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, true, "ascii", -1, nullptr, false);
  827. }
  828. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v4(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator)
  829. {
  830. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, "ascii", -1, nullptr, false));
  831. }
  832. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v4(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator)
  833. {
  834. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, "ascii", -1, nullptr, false);
  835. }
  836. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v5(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding)
  837. {
  838. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, -1, nullptr, false));
  839. }
  840. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v5(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding)
  841. {
  842. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, -1, nullptr, false);
  843. }
  844. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v6(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays)
  845. {
  846. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, nullptr, false));
  847. }
  848. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v6(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays)
  849. {
  850. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, nullptr, false);
  851. }
  852. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v7(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays, const char * dfuServerQueue)
  853. {
  854. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, dfuServerQueue, false));
  855. }
  856. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v7(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays, const char * dfuServerQueue)
  857. {
  858. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, dfuServerQueue, false);
  859. }
  860. FILESERVICES_API void FILESERVICES_CALL fsSprayVariable_v8(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays, const char * dfuServerQueue, bool noSplit)
  861. {
  862. CTXFREE(parentCtx, implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, dfuServerQueue, noSplit));
  863. }
  864. FILESERVICES_API char * FILESERVICES_CALL fsfSprayVariable_v8(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, const char * csvEscape, bool failIfNoSourceFile, bool recordStructurePresent, bool quotedTerminator, const char * encoding, int expireDays, const char * dfuServerQueue, bool noSplit)
  865. {
  866. return implementSprayVariable(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceCsvSeparate, sourceCsvTerminate, sourceCsvQuote, csvEscape, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, recordStructurePresent, quotedTerminator, encoding, expireDays, dfuServerQueue, noSplit);
  867. }
  868. //----------------------------------------------------------------------------------
  869. FILESERVICES_API char * FILESERVICES_CALL implementSprayXml(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  870. {
  871. LOG(MCauditInfo, "Spray: %s", destinationLogicalName);
  872. CClientFileSpray server;
  873. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  874. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  875. setServerAccess(server, wu);
  876. Owned<IClientSprayVariable> req = server.createSprayVariableRequest();
  877. setContainerLocalCertificate(req->rpc());
  878. StringBuffer logicalName;
  879. constructLogicalName(wu, destinationLogicalName, logicalName);
  880. DFUfileformat dfufmt;
  881. if (sourceEncoding == NULL)
  882. dfufmt = DFUff_utf8;
  883. else
  884. dfufmt = CDFUfileformat::decode(sourceEncoding);
  885. req->setSourceIP(sourceIP);
  886. req->setSourcePath(sourcePath);
  887. req->setSourceMaxRecordSize(sourceMaxRecordSize);
  888. req->setSourceFormat(dfufmt);
  889. req->setSourceRowTag(sourceRowTag);
  890. req->setDestGroup(destinationGroup);
  891. req->setDestLogicalName(logicalName.str());
  892. req->setOverwrite(overwrite);
  893. req->setReplicate(replicate);
  894. req->setCompress(compress);
  895. if (maxConnections != -1)
  896. req->setMaxConnections(maxConnections);
  897. if (failIfNoSourceFile)
  898. req->setFailIfNoSourceFile(true);
  899. req->setExpireDays(expireDays);
  900. if (!isEmptyString(dfuServerQueue))
  901. req->setDFUServerQueue(dfuServerQueue);
  902. if (noSplit)
  903. req->setNosplit(true);
  904. Owned<IClientSprayResponse> result = server.SprayVariable(req);
  905. StringBuffer wuid(result->getWuid());
  906. if (!wuid.length())
  907. {
  908. const IMultiException* excep = &result->getExceptions();
  909. if ((excep != NULL) && (excep->ordinality() > 0))
  910. {
  911. StringBuffer errmsg;
  912. excep->errorMessage(errmsg);
  913. throw MakeStringExceptionDirect(0, errmsg.str());
  914. }
  915. else
  916. {
  917. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  918. }
  919. }
  920. wu.clear();
  921. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  922. return wuid.detach();
  923. }
  924. 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, bool failIfNoSourceFile)
  925. {
  926. CTXFREE(parentCtx, implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, -1, nullptr, false));
  927. }
  928. FILESERVICES_API void FILESERVICES_CALL fsSprayXml_v2(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, bool failIfNoSourceFile, int expireDays)
  929. {
  930. CTXFREE(parentCtx, implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, nullptr, false));
  931. }
  932. FILESERVICES_API void FILESERVICES_CALL fsSprayXml_v3(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue)
  933. {
  934. CTXFREE(parentCtx, implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, false));
  935. }
  936. FILESERVICES_API void FILESERVICES_CALL fsSprayXml_v4(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  937. {
  938. CTXFREE(parentCtx, implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit));
  939. }
  940. 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, bool failIfNoSourceFile)
  941. {
  942. return implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, -1, nullptr, false);
  943. }
  944. FILESERVICES_API char * FILESERVICES_CALL fsfSprayXml_v2(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, bool failIfNoSourceFile, int expireDays)
  945. {
  946. return implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, nullptr, false);
  947. }
  948. FILESERVICES_API char * FILESERVICES_CALL fsfSprayXml_v3(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue)
  949. {
  950. return implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, false);
  951. }
  952. FILESERVICES_API char * FILESERVICES_CALL fsfSprayXml_v4(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, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit)
  953. {
  954. return implementSprayXml(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowTag, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit);
  955. }
  956. //----------------------------------------------------------------------------------
  957. FILESERVICES_API char * FILESERVICES_CALL implementSprayJson(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char *sourceRowPath, const char *sourceEncoding, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit, const char * username, const char * userPw)
  958. {
  959. LOG(MCauditInfo, "Spray JSON: %s", destinationLogicalName);
  960. CClientFileSpray server;
  961. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  962. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  963. setServerAccess(server, wu);
  964. Owned<IClientSprayVariable> req = server.createSprayVariableRequest();
  965. setContainerLocalCertificate(req->rpc());
  966. StringBuffer logicalName;
  967. constructLogicalName(wu, destinationLogicalName, logicalName);
  968. DFUfileformat dfufmt;
  969. if (sourceEncoding == NULL)
  970. dfufmt = DFUff_utf8;
  971. else
  972. dfufmt = CDFUfileformat::decode(sourceEncoding);
  973. req->setSourceIP(sourceIP);
  974. req->setSourcePath(sourcePath);
  975. req->setSourceMaxRecordSize(sourceMaxRecordSize);
  976. req->setSourceFormat(dfufmt);
  977. req->setSourceRowTag(sourceRowPath);
  978. req->setDestGroup(destinationGroup);
  979. req->setDestLogicalName(logicalName.str());
  980. req->setOverwrite(overwrite);
  981. req->setReplicate(replicate);
  982. req->setCompress(compress);
  983. if (maxConnections != -1)
  984. req->setMaxConnections(maxConnections);
  985. if (failIfNoSourceFile)
  986. req->setFailIfNoSourceFile(true);
  987. req->setIsJSON(true);
  988. req->setExpireDays(expireDays);
  989. if (!isEmptyString(dfuServerQueue))
  990. req->setDFUServerQueue(dfuServerQueue);
  991. if (noSplit)
  992. req->setNosplit(true);
  993. // Store username/psw
  994. if (!isEmptyString(username))
  995. {
  996. req->setSrcUsername(username);
  997. if (!isEmptyString(userPw))
  998. req->setSrcPassword(userPw);
  999. }
  1000. Owned<IClientSprayResponse> result = server.SprayVariable(req);
  1001. StringBuffer wuid(result->getWuid());
  1002. if (!wuid.length())
  1003. {
  1004. const IMultiException* excep = &result->getExceptions();
  1005. if ((excep != NULL) && (excep->ordinality() > 0))
  1006. {
  1007. StringBuffer errmsg;
  1008. excep->errorMessage(errmsg);
  1009. throw MakeStringExceptionDirect(0, errmsg.str());
  1010. }
  1011. else
  1012. {
  1013. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  1014. }
  1015. }
  1016. wu.clear();
  1017. blockUntilComplete("Spray", server, ctx, wuid, timeOut);
  1018. return wuid.detach();
  1019. }
  1020. FILESERVICES_API void FILESERVICES_CALL fsSprayJson(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char *sourceRowPath, const char *sourceEncoding, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit, const char * username, const char * userPw)
  1021. {
  1022. CTXFREE(parentCtx, implementSprayJson(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowPath, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit, username, userPw));
  1023. }
  1024. FILESERVICES_API char * FILESERVICES_CALL fsfSprayJson(ICodeContext *ctx, const char * sourceIP, const char * sourcePath, int sourceMaxRecordSize, const char *sourceRowPath, const char *sourceEncoding, const char * destinationGroup, const char * destinationLogicalName, int timeOut, const char * espServerIpPort, int maxConnections, bool overwrite, bool replicate, bool compress, bool failIfNoSourceFile, int expireDays, const char * dfuServerQueue, bool noSplit, const char * username, const char * userPw)
  1025. {
  1026. return implementSprayJson(ctx, sourceIP, sourcePath, sourceMaxRecordSize, sourceRowPath, sourceEncoding, destinationGroup, destinationLogicalName, timeOut, espServerIpPort, maxConnections, overwrite, replicate, compress, failIfNoSourceFile, expireDays, dfuServerQueue, noSplit, username, userPw);
  1027. }
  1028. //----------------------------------------------------------------------------------
  1029. 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)
  1030. {
  1031. CTXFREE(parentCtx, fsfDespray(ctx, sourceLogicalName, destinationIP, destinationPath, timeOut, espServerIpPort, maxConnections, overwrite));
  1032. }
  1033. 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)
  1034. {
  1035. LOG(MCauditInfo, "Despray: %s", sourceLogicalName);
  1036. CClientFileSpray server;
  1037. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1038. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1039. if (wu)
  1040. setServerAccess(server, wu);
  1041. Owned<IClientDespray> req = server.createDesprayRequest();
  1042. setContainerLocalCertificate(req->rpc());
  1043. StringBuffer logicalName;
  1044. constructLogicalName(wu, sourceLogicalName, logicalName);
  1045. req->setSourceLogicalName(logicalName.str());
  1046. req->setDestIP(destinationIP);
  1047. req->setDestPath(destinationPath);
  1048. req->setOverwrite(overwrite);
  1049. if (maxConnections != -1)
  1050. req->setMaxConnections(maxConnections);
  1051. Owned<IClientDesprayResponse> result = server.Despray(req);
  1052. StringBuffer wuid(result->getWuid());
  1053. if (!wuid.length())
  1054. {
  1055. const IMultiException* excep = &result->getExceptions();
  1056. if ((excep != NULL) && (excep->ordinality() > 0))
  1057. {
  1058. StringBuffer errmsg;
  1059. excep->errorMessage(errmsg);
  1060. throw MakeStringExceptionDirect(0, errmsg.str());
  1061. }
  1062. else
  1063. {
  1064. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  1065. }
  1066. }
  1067. wu.clear();
  1068. blockUntilComplete("Despray", server, ctx, wuid, timeOut);
  1069. return wuid.detach();
  1070. }
  1071. FILESERVICES_API char * FILESERVICES_CALL implementCopy(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, bool preserveCompression, bool noSplit, int expireDays)
  1072. {
  1073. LOG(MCauditInfo, "Copy: %s%s", sourceLogicalName,asSuperfile?" as superfile":"");
  1074. CClientFileSpray server;
  1075. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1076. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1077. setServerAccess(server, wu);
  1078. Owned<IClientCopy> req = server.createCopyRequest();
  1079. setContainerLocalCertificate(req->rpc());
  1080. if (asSuperfile)
  1081. req->setSuperCopy(true);
  1082. StringBuffer _sourceLogicalName, _destinationLogicalName;
  1083. constructLogicalName(wu, sourceLogicalName, _sourceLogicalName);
  1084. constructLogicalName(wu, destinationLogicalName, _destinationLogicalName);
  1085. req->setSourceLogicalName(_sourceLogicalName.str());
  1086. req->setDestLogicalName(_destinationLogicalName.str());
  1087. if ((destinationGroup != NULL) && (*destinationGroup != '\0'))
  1088. req->setDestGroup(destinationGroup);
  1089. if ((sourceDali != NULL) && (*sourceDali != '\0'))
  1090. req->setSourceDali(sourceDali);
  1091. req->setOverwrite(overwrite);
  1092. req->setReplicate(replicate);
  1093. if (compress)
  1094. req->setCompress(true);
  1095. req->setPreserveCompression(preserveCompression);
  1096. if (forcePush)
  1097. req->setPush(true);
  1098. if (transferBufferSize > 0)
  1099. req->setTransferBufferSize(transferBufferSize);
  1100. if (maxConnections != -1)
  1101. req->setMaxConnections(maxConnections);
  1102. if (noSplit)
  1103. req->setNosplit(true);
  1104. req->setExpireDays(expireDays);
  1105. Owned<IClientCopyResponse> result = server.Copy(req);
  1106. StringBuffer wuid(result->getResult());
  1107. if (!wuid.length())
  1108. {
  1109. const IMultiException* excep = &result->getExceptions();
  1110. if ((excep != NULL) && (excep->ordinality() > 0))
  1111. {
  1112. StringBuffer errmsg;
  1113. excep->errorMessage(errmsg);
  1114. throw MakeStringExceptionDirect(0, errmsg.str());
  1115. }
  1116. else
  1117. {
  1118. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  1119. }
  1120. }
  1121. wu.clear();
  1122. blockUntilComplete("Copy", server, ctx, wuid, timeOut);
  1123. return wuid.detach();
  1124. }
  1125. 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)
  1126. {
  1127. CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1));
  1128. }
  1129. FILESERVICES_API void FILESERVICES_CALL fsCopy_v2(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, bool preserveCompression)
  1130. {
  1131. CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false, -1));
  1132. }
  1133. FILESERVICES_API void FILESERVICES_CALL fsCopy_v3(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, bool preserveCompression, bool noSplit, int expireDays)
  1134. {
  1135. CTXFREE(parentCtx, implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays));
  1136. }
  1137. 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)
  1138. {
  1139. return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, true, false, -1);
  1140. }
  1141. FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v2(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, bool preserveCompression)
  1142. {
  1143. return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, false,-1);
  1144. }
  1145. FILESERVICES_API char * FILESERVICES_CALL fsfCopy_v3(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, bool preserveCompression, bool noSplit, int expireDays)
  1146. {
  1147. return implementCopy(ctx, sourceLogicalName, destinationGroup, destinationLogicalName, sourceDali, timeOut, espServerIpPort, maxConnections, overwrite, replicate, asSuperfile, compress, forcePush, transferBufferSize, preserveCompression, noSplit, expireDays);
  1148. }
  1149. FILESERVICES_API void FILESERVICES_CALL fsReplicate(ICodeContext *ctx, const char * sourceLogicalName,int timeOut, const char * espServerIpPort)
  1150. {
  1151. CTXFREE(parentCtx, fsfReplicate(ctx, sourceLogicalName, timeOut, espServerIpPort));
  1152. }
  1153. FILESERVICES_API char * FILESERVICES_CALL fsfReplicate(ICodeContext *ctx, const char * sourceLogicalName, int timeOut, const char * espServerIpPort)
  1154. {
  1155. LOG(MCauditInfo, "REPLICATE: %s", sourceLogicalName);
  1156. CClientFileSpray server;
  1157. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1158. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1159. setServerAccess(server, wu);
  1160. Owned<IClientReplicate> req = server.createReplicateRequest();
  1161. setContainerLocalCertificate(req->rpc());
  1162. StringBuffer logicalName;
  1163. constructLogicalName(wu, sourceLogicalName, logicalName);
  1164. req->setSourceLogicalName(logicalName.str());
  1165. Owned<IClientReplicateResponse> result = server.Replicate(req);
  1166. StringBuffer wuid(result->getWuid());
  1167. if (!wuid.length())
  1168. {
  1169. const IMultiException* excep = &result->getExceptions();
  1170. if ((excep != NULL) && (excep->ordinality() > 0))
  1171. {
  1172. StringBuffer errmsg;
  1173. excep->errorMessage(errmsg);
  1174. throw MakeStringExceptionDirect(0, errmsg.str());
  1175. }
  1176. else
  1177. {
  1178. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  1179. }
  1180. }
  1181. wu.clear();
  1182. blockUntilComplete("Replicate", server, ctx, wuid, timeOut);
  1183. return wuid.detach();
  1184. }
  1185. //===========================================================================================
  1186. // SuperFile API
  1187. /*
  1188. CreateSuperFile(const varstring lsuperfn, boolean sequentialparts=false);
  1189. boolean SuperFileExists(const varstring lsuperfn);
  1190. DeleteSuperFile(const varstring lsuperfn,boolean deletesub=false);
  1191. unsigned4 GetSuperFileSubCount(const varstring lsuperfn);
  1192. varstring GetSuperFileSubName(const varstring lsuperfn,unsigned4 filenum);
  1193. unsigned4 FindSuperFileSubName(const varstring lsuperfn,const varstring lfn);
  1194. StartSuperFileTransaction();
  1195. AddSuperFile(const varstring lsuperfn,const varstring lfn,unsigned4 atpos=0);
  1196. RemoveSuperFile(const varstring lsuperfn,const varstring lfn,boolean del=false);
  1197. ClearSuperFile(const varstring lsuperfn,boolean del=false);
  1198. RemoveOwnedSubFiles(const varstring lsuperfn,boolean del=false);
  1199. SwapSuperFile(const varstring lsuperfn1,const varstring lsuperfn2);
  1200. ReplaceSuperFile(const varstring lsuperfn,const varstring lfn,const varstring bylfn);
  1201. FinishSuperFileTransaction(boolean rollback=false);
  1202. */
  1203. class CImplicitSuperTransaction
  1204. {
  1205. IDistributedFileTransaction *transaction;
  1206. public:
  1207. CImplicitSuperTransaction(IDistributedFileTransaction *_transaction)
  1208. {
  1209. if (!_transaction->active()) // then created implicitly
  1210. {
  1211. transaction = _transaction;
  1212. transaction->start();
  1213. }
  1214. else
  1215. transaction = NULL;
  1216. }
  1217. ~CImplicitSuperTransaction() noexcept(false)
  1218. {
  1219. if (transaction)
  1220. transaction->commit();
  1221. }
  1222. };
  1223. static bool lookupSuperFile(ICodeContext *ctx, const char *lsuperfn, Owned<IDistributedSuperFile> &file, bool throwerr, StringBuffer &lsfn, bool allowforeign, bool cacheFiles=false)
  1224. {
  1225. lsfn.clear();
  1226. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1227. assertex(transaction);
  1228. constructLogicalName(ctx, lsuperfn, lsfn);
  1229. if (!allowforeign) {
  1230. CDfsLogicalFileName dlfn;
  1231. dlfn.set(lsfn.str());
  1232. if (dlfn.isForeign())
  1233. throw MakeStringException(0, "Foreign superfile not allowed: %s", lsfn.str());
  1234. }
  1235. file.setown(transaction->lookupSuperFile(lsfn.str()));
  1236. if (file.get())
  1237. return true;
  1238. if (throwerr)
  1239. throw MakeStringException(0, "Could not locate superfile: %s", lsfn.str());
  1240. return false;
  1241. }
  1242. static ISimpleSuperFileEnquiry *getSimpleSuperFileEnquiry(ICodeContext *ctx, const char *lsuperfn)
  1243. {
  1244. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1245. assertex(transaction);
  1246. if (transaction->active())
  1247. return NULL;
  1248. StringBuffer lsfn;
  1249. constructLogicalName(ctx, lsuperfn, lsfn);
  1250. return queryDistributedFileDirectory().getSimpleSuperFileEnquiry(lsfn.str(),"Fileservices",ctx->queryUserDescriptor());
  1251. }
  1252. static void CheckNotInTransaction(ICodeContext *ctx, const char *fn)
  1253. {
  1254. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1255. assertex(transaction);
  1256. if (transaction->active()) {
  1257. StringBuffer s("Operation not part of transaction : ");
  1258. s.append(fn);
  1259. WUmessage(ctx,SeverityWarning,fn,s.str());
  1260. }
  1261. }
  1262. FILESERVICES_API void FILESERVICES_CALL fsCreateSuperFile(ICodeContext *ctx, const char *lsuperfn, bool sequentialparts, bool ifdoesnotexist)
  1263. {
  1264. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1265. assertex(transaction);
  1266. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1267. StringBuffer lsfn;
  1268. constructLogicalName(ctx, lsuperfn, lsfn);
  1269. Owned<IDistributedSuperFile> file = queryDistributedFileDirectory().createSuperFile(lsfn,udesc,!sequentialparts,ifdoesnotexist,transaction);
  1270. StringBuffer s("CreateSuperFile ('");
  1271. s.append(lsfn).append("') done");
  1272. AuditMessage(ctx,"CreateSuperFile",lsfn.str());
  1273. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1274. }
  1275. FILESERVICES_API bool FILESERVICES_CALL fsSuperFileExists(ICodeContext *ctx, const char *lsuperfn)
  1276. {
  1277. StringBuffer lsfn;
  1278. constructLogicalName(ctx, lsuperfn, lsfn);
  1279. return queryDistributedFileDirectory().exists(lsfn,ctx->queryUserDescriptor(),false,true);
  1280. }
  1281. FILESERVICES_API void FILESERVICES_CALL fsDeleteSuperFile(ICodeContext *ctx, const char *lsuperfn,bool deletesub)
  1282. {
  1283. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1284. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1285. Owned<IDistributedSuperFile> file;
  1286. StringBuffer lsfn;
  1287. bool found = lookupSuperFile(ctx, lsuperfn, file, false, lsfn, false);
  1288. file.clear(); // MORE: this should really be exists(file)
  1289. StringBuffer s("DeleteSuperFile ('");
  1290. s.append(lsfn).appendf("')");
  1291. if (found) {
  1292. queryDistributedFileDirectory().removeSuperFile(lsfn.str(), deletesub, udesc, transaction);
  1293. if (transaction->active())
  1294. s.append(" action added to transaction");
  1295. else
  1296. s.append(" done");
  1297. } else {
  1298. s.append(" file not found");
  1299. }
  1300. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1301. if (found)
  1302. AuditMessage(ctx,"DeleteSuperFile",lsfn.str());
  1303. }
  1304. FILESERVICES_API unsigned FILESERVICES_CALL fsGetSuperFileSubCount(ICodeContext *ctx, const char *lsuperfn)
  1305. {
  1306. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  1307. if (enq)
  1308. return enq->numSubFiles();
  1309. CImplicitSuperTransaction implicitTransaction(ctx->querySuperFileTransaction());
  1310. Owned<IDistributedSuperFile> file;
  1311. StringBuffer lsfn;
  1312. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, true);
  1313. return file->numSubFiles();
  1314. }
  1315. FILESERVICES_API char * FILESERVICES_CALL fsGetSuperFileSubName(ICodeContext *ctx, const char *lsuperfn,unsigned filenum, bool abspath)
  1316. {
  1317. StringBuffer ret;
  1318. if (abspath)
  1319. ret.append('~');
  1320. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  1321. if (enq) {
  1322. if (!filenum||!enq->getSubFileName(filenum-1,ret))
  1323. return CTXSTRDUP(parentCtx, "");
  1324. return ret.detach();
  1325. }
  1326. CImplicitSuperTransaction implicitTransaction(ctx->querySuperFileTransaction());
  1327. Owned<IDistributedSuperFile> file;
  1328. StringBuffer lsfn;
  1329. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, true);
  1330. if (!filenum||filenum>file->numSubFiles())
  1331. return CTXSTRDUP(parentCtx, "");
  1332. ret.append(file->querySubFile(filenum-1).queryLogicalName());
  1333. return ret.detach();
  1334. }
  1335. FILESERVICES_API unsigned FILESERVICES_CALL fsFindSuperFileSubName(ICodeContext *ctx, const char *lsuperfn,const char *_lfn)
  1336. {
  1337. StringBuffer lfn;
  1338. constructLogicalName(ctx, _lfn, lfn);
  1339. Owned<ISimpleSuperFileEnquiry> enq = getSimpleSuperFileEnquiry(ctx, lsuperfn);
  1340. if (enq) {
  1341. unsigned n = enq->findSubName(lfn.str());
  1342. return (n==NotFound)?0:n+1;
  1343. }
  1344. CImplicitSuperTransaction implicitTransaction(ctx->querySuperFileTransaction());
  1345. Owned<IDistributedSuperFile> file;
  1346. StringBuffer lsfn;
  1347. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, true);
  1348. unsigned n = 0;
  1349. // could do with better version of this TBD
  1350. Owned<IDistributedFileIterator> iter = file->getSubFileIterator();
  1351. ForEach(*iter) {
  1352. n++;
  1353. if (stricmp(iter->query().queryLogicalName(),lfn.str())==0)
  1354. return n;
  1355. }
  1356. return 0;
  1357. }
  1358. FILESERVICES_API void FILESERVICES_CALL fsStartSuperFileTransaction(IGlobalCodeContext *gctx)
  1359. {
  1360. fslStartSuperFileTransaction(gctx->queryCodeContext());
  1361. }
  1362. FILESERVICES_API void FILESERVICES_CALL fslStartSuperFileTransaction(ICodeContext *ctx)
  1363. {
  1364. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1365. assertex(transaction);
  1366. transaction->start();
  1367. WUmessage(ctx,SeverityInformation,NULL,"StartSuperFileTransaction");
  1368. }
  1369. FILESERVICES_API void FILESERVICES_CALL fsAddSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *_lfn,unsigned atpos,bool addcontents, bool strict)
  1370. {
  1371. fslAddSuperFile(gctx->queryCodeContext(),lsuperfn,_lfn,atpos,addcontents,strict);
  1372. }
  1373. FILESERVICES_API void FILESERVICES_CALL fslAddSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *_lfn,unsigned atpos,bool addcontents, bool strict)
  1374. {
  1375. Owned<IDistributedSuperFile> file;
  1376. StringBuffer lsfn;
  1377. // NB: if adding contents, tell lookupSuperFile to cache the subfiles in the transaction
  1378. if (!lookupSuperFile(ctx, lsuperfn, file, strict, lsfn, false, addcontents)) {
  1379. // auto create
  1380. fsCreateSuperFile(ctx,lsuperfn,false,false);
  1381. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, addcontents);
  1382. }
  1383. // Never add super file to itself
  1384. StringBuffer lfn;
  1385. constructLogicalName(ctx, _lfn, lfn);
  1386. if (stricmp(file->queryLogicalName(), lfn.str()) == 0) {
  1387. throw MakeStringException(0, "AddSuperFile: Adding super file %s to itself!", file->queryLogicalName());
  1388. }
  1389. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1390. assertex(transaction);
  1391. if (strict||addcontents) {
  1392. Owned<IDistributedSuperFile> subfile;
  1393. subfile.setown(transaction->lookupSuperFile(lfn.str()));
  1394. if (!subfile.get())
  1395. throw MakeStringException(0, "AddSuperFile%s: Could not locate super file %s", addcontents?"(addcontents)":"",lfn.str());
  1396. if (strict&&(subfile->numSubFiles()<1))
  1397. throw MakeStringException(0, "AddSuperFile: Adding empty super file %s", lfn.str());
  1398. }
  1399. StringBuffer other;
  1400. if (atpos>1)
  1401. other.append("#").append(atpos);
  1402. {
  1403. CImplicitSuperTransaction implicitTransaction(transaction);
  1404. file->addSubFile(lfn.str(),atpos>0,(atpos>1)?other.str():NULL,addcontents,transaction);
  1405. file.clear(); // Must clear file before implicit transaction executed in destructor
  1406. }
  1407. StringBuffer s("AddSuperFile ('");
  1408. s.append(lsfn).append("', '");
  1409. s.append(lfn).append('\'');
  1410. if (atpos)
  1411. s.append(", ").append(atpos);
  1412. if (addcontents)
  1413. s.append(", addcontents");
  1414. s.append(") ");
  1415. if (transaction->active())
  1416. s.append("trans");
  1417. else
  1418. s.append("done");
  1419. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1420. AuditMessage(ctx,"AddSuperFile",lsfn.str(),lfn.str());
  1421. }
  1422. FILESERVICES_API void FILESERVICES_CALL fsRemoveSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *_lfn,bool del,bool remcontents)
  1423. {
  1424. fslRemoveSuperFile(gctx->queryCodeContext(),lsuperfn,_lfn,del,remcontents);
  1425. }
  1426. FILESERVICES_API void FILESERVICES_CALL fslRemoveSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *_lfn,bool del,bool remcontents)
  1427. {
  1428. Owned<IDistributedSuperFile> file;
  1429. StringBuffer lsfn;
  1430. StringBuffer lfn;
  1431. if (_lfn)
  1432. constructLogicalName(ctx, _lfn, lfn);
  1433. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  1434. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1435. assertex(transaction);
  1436. {
  1437. CImplicitSuperTransaction implicitTransaction(transaction);
  1438. file->removeSubFile(_lfn?lfn.str():NULL,del,remcontents,transaction);
  1439. file.clear(); // Must clear file before implicit transaction executed in destructor
  1440. }
  1441. StringBuffer s;
  1442. if (_lfn)
  1443. s.append("RemoveSuperFile ('");
  1444. else
  1445. s.append("ClearSuperFile ('");
  1446. s.append(lsfn).append('\'');
  1447. if (_lfn)
  1448. s.append(", '").append(lfn.str()).append('\'');
  1449. if (del)
  1450. s.append(", del");
  1451. if (remcontents)
  1452. s.append(", remcontents");
  1453. s.append(") ");
  1454. if (transaction->active())
  1455. s.append("trans");
  1456. else
  1457. s.append("done");
  1458. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1459. AuditMessage(ctx,"RemoveSuperFile",lsfn.str(),lfn.str());
  1460. }
  1461. FILESERVICES_API void FILESERVICES_CALL fsClearSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,bool del)
  1462. {
  1463. fsRemoveSuperFile(gctx,lsuperfn,NULL,del);
  1464. }
  1465. FILESERVICES_API void FILESERVICES_CALL fsDeleteOwnedSubFiles(IGlobalCodeContext *gctx, const char *lsuperfn) // Obsolete
  1466. {
  1467. fslRemoveOwnedSubFiles(gctx->queryCodeContext(), lsuperfn, false);
  1468. }
  1469. FILESERVICES_API void FILESERVICES_CALL fsRemoveOwnedSubFiles(IGlobalCodeContext *gctx, const char *lsuperfn, bool del)
  1470. {
  1471. fslRemoveOwnedSubFiles(gctx->queryCodeContext(), lsuperfn, del);
  1472. }
  1473. FILESERVICES_API void FILESERVICES_CALL fslRemoveOwnedSubFiles(ICodeContext *ctx, const char *lsuperfn, bool del)
  1474. {
  1475. Owned<IDistributedSuperFile> file;
  1476. StringBuffer lsfn;
  1477. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, false, true);
  1478. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1479. assertex(transaction);
  1480. {
  1481. CImplicitSuperTransaction implicitTransaction(transaction);
  1482. file->removeOwnedSubFiles(del,transaction);
  1483. file.clear(); // Must clear file before implicit transaction executed in destructor
  1484. }
  1485. VStringBuffer s("RemoveOwnedSubFiles ('%s'", lsfn.str());
  1486. if (del)
  1487. s.append(", del");
  1488. s.append(") ");
  1489. if (transaction->active())
  1490. s.append("trans");
  1491. else
  1492. s.append("done");
  1493. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1494. AuditMessage(ctx,"RemoveOwnedSubFiles",lsfn.str());
  1495. }
  1496. FILESERVICES_API void FILESERVICES_CALL fslClearSuperFile(ICodeContext *ctx, const char *lsuperfn,bool del)
  1497. {
  1498. fslRemoveSuperFile(ctx,lsuperfn,NULL,del);
  1499. }
  1500. FILESERVICES_API void FILESERVICES_CALL fsSwapSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn1,const char *lsuperfn2)
  1501. {
  1502. fslSwapSuperFile(gctx->queryCodeContext(),lsuperfn1,lsuperfn2);
  1503. }
  1504. FILESERVICES_API void FILESERVICES_CALL fslSwapSuperFile(ICodeContext *ctx, const char *lsuperfn1,const char *lsuperfn2)
  1505. {
  1506. StringBuffer lsfn1;
  1507. StringBuffer lsfn2;
  1508. Owned<IDistributedSuperFile> file1;
  1509. Owned<IDistributedSuperFile> file2;
  1510. lookupSuperFile(ctx, lsuperfn1, file1, true, lsfn1,false);
  1511. lookupSuperFile(ctx, lsuperfn2, file2, true,lsfn2,false);
  1512. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1513. assertex(transaction);
  1514. {
  1515. CImplicitSuperTransaction implicitTransaction(transaction);
  1516. file1->swapSuperFile(file2,transaction);
  1517. // Must clear files before implicit transaction executed in destructor
  1518. file1.clear();
  1519. file2.clear();
  1520. }
  1521. StringBuffer s("SwapSuperFile ('");
  1522. s.append(lsfn1).append("', '");
  1523. s.append(lsfn2).append("') '");
  1524. if (transaction->active())
  1525. s.append("trans");
  1526. else
  1527. s.append("done");
  1528. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1529. AuditMessage(ctx,"SwapSuperFile",lsfn1.str(),lsfn2.str());
  1530. }
  1531. FILESERVICES_API void FILESERVICES_CALL fsReplaceSuperFile(IGlobalCodeContext *gctx, const char *lsuperfn,const char *lfn,const char *bylfn)
  1532. {
  1533. fslReplaceSuperFile(gctx->queryCodeContext(),lsuperfn,lfn,bylfn);
  1534. }
  1535. FILESERVICES_API void FILESERVICES_CALL fslReplaceSuperFile(ICodeContext *ctx, const char *lsuperfn,const char *lfn,const char *bylfn)
  1536. {
  1537. unsigned at = fsFindSuperFileSubName(ctx,lsuperfn,lfn);
  1538. if (!at)
  1539. return;
  1540. fslRemoveSuperFile(ctx,lsuperfn,lfn);
  1541. fslAddSuperFile(ctx,lsuperfn,bylfn,at);
  1542. }
  1543. FILESERVICES_API void FILESERVICES_CALL fsFinishSuperFileTransaction(IGlobalCodeContext *gctx, bool rollback)
  1544. {
  1545. fslFinishSuperFileTransaction(gctx->queryCodeContext(),rollback);
  1546. }
  1547. FILESERVICES_API void FILESERVICES_CALL fslFinishSuperFileTransaction(ICodeContext *ctx, bool rollback)
  1548. {
  1549. IDistributedFileTransaction *transaction = ctx->querySuperFileTransaction();
  1550. assertex(transaction);
  1551. if (transaction->active()) {
  1552. if (rollback)
  1553. transaction->rollback();
  1554. else
  1555. transaction->commit();
  1556. StringBuffer s("FinishSuperFileTransaction ");
  1557. if (rollback)
  1558. s.append("rollback");
  1559. else
  1560. s.append("commit");
  1561. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1562. }
  1563. else {
  1564. StringBuffer s("Invalid FinishSuperFileTransaction ");
  1565. if (rollback)
  1566. s.append("rollback");
  1567. else
  1568. s.append("done");
  1569. s.append(", transaction not active");
  1570. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1571. }
  1572. }
  1573. static char * implementForeignLogicalFileName(ICodeContext *ctx, const char *_lfn, const char *foreigndali, bool abspath, bool omitClusterPrefix)
  1574. {
  1575. StringBuffer lfns;
  1576. Owned<IConstWorkUnit> wu;
  1577. if (!omitClusterPrefix && _lfn&&(*_lfn != '~'))
  1578. wu.setown(getWorkunit(ctx));
  1579. constructLogicalName(wu, _lfn, lfns);
  1580. CDfsLogicalFileName lfn;
  1581. lfn.set(lfns.str());
  1582. if (foreigndali&&*foreigndali) {
  1583. SocketEndpoint ep(foreigndali);
  1584. lfn.setForeign(ep,false);
  1585. }
  1586. else
  1587. lfn.clearForeign();
  1588. StringBuffer ret;
  1589. if (abspath)
  1590. ret.append('~');
  1591. lfn.get(ret);
  1592. return ret.detach();
  1593. }
  1594. FILESERVICES_API char * FILESERVICES_CALL fsForeignLogicalFileName(ICodeContext *ctx, const char *lfn, const char *foreigndali, bool abspath)
  1595. {
  1596. return implementForeignLogicalFileName(ctx, lfn, foreigndali, abspath, false);
  1597. }
  1598. FILESERVICES_API char * FILESERVICES_CALL fsForeignLogicalFileName_v2(ICodeContext *ctx, const char *lfn, const char *foreigndali, bool abspath, bool omitClusterPrefix)
  1599. {
  1600. return implementForeignLogicalFileName(ctx, lfn, foreigndali, abspath, omitClusterPrefix);
  1601. }
  1602. FILESERVICES_API char * FILESERVICES_CALL fsExternalLogicalFileName(const char *location,const char *path,bool abspath)
  1603. {
  1604. StringBuffer ret;
  1605. if (abspath)
  1606. ret.append('~');
  1607. CDfsLogicalFileName lfn;
  1608. lfn.setExternal(location,path);
  1609. return lfn.get(ret).detach();
  1610. }
  1611. FILESERVICES_API char * FILESERVICES_CALL fsWaitDfuWorkunit(IGlobalCodeContext *gctx, const char *wuid, int timeout, const char * espServerIpPort)
  1612. {
  1613. return fslWaitDfuWorkunit(gctx->queryCodeContext(),wuid,timeout,espServerIpPort);
  1614. }
  1615. FILESERVICES_API char * FILESERVICES_CALL fslWaitDfuWorkunit(ICodeContext *ctx, const char *wuid, int timeout, const char * espServerIpPort)
  1616. {
  1617. CClientFileSpray server;
  1618. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1619. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1620. setServerAccess(server, wu);
  1621. StringBuffer s("Waiting for DFU Workunit ");
  1622. s.append(wuid);
  1623. WUmessage(ctx,SeverityInformation,"WaitDfuWorkunit",s.str());
  1624. StringBuffer state;
  1625. wu.clear();
  1626. blockUntilComplete("WaitDfuWorkunit", server, ctx, wuid, timeout, &state);
  1627. s.clear().append("Finished waiting for DFU Workunit ").append(wuid).append(" state=").append(state.str());
  1628. WUmessage(ctx,SeverityInformation,"WaitDfuWorkunit",s.str());
  1629. return state.detach();
  1630. }
  1631. FILESERVICES_API void FILESERVICES_CALL fsAbortDfuWorkunit(IGlobalCodeContext *gctx, const char *wuid, const char * espServerIpPort)
  1632. {
  1633. fslAbortDfuWorkunit(gctx->queryCodeContext(),wuid,espServerIpPort);
  1634. }
  1635. FILESERVICES_API void FILESERVICES_CALL fslAbortDfuWorkunit(ICodeContext *ctx, const char *wuid, const char * espServerIpPort)
  1636. {
  1637. CClientFileSpray server;
  1638. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1639. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1640. setServerAccess(server, wu);
  1641. Owned<IClientAbortDFUWorkunit> abortReq = server.createAbortDFUWorkunitRequest();
  1642. setContainerLocalCertificate(abortReq->rpc());
  1643. abortReq->setWuid(wuid);
  1644. Linked<IClientAbortDFUWorkunitResponse> abortResp = server.AbortDFUWorkunit(abortReq);
  1645. StringBuffer s("DFU Workunit Abort Requested for ");
  1646. s.append(wuid);
  1647. WUmessage(ctx,SeverityInformation,"AbortDfuWorkunit",s.str());
  1648. }
  1649. FILESERVICES_API void FILESERVICES_CALL fsMonitorLogicalFileName(ICodeContext *ctx, const char *eventname, const char *_lfn,int shotcount, const char * espServerIpPort)
  1650. {
  1651. CTXFREE(parentCtx, fsfMonitorLogicalFileName(ctx, eventname, _lfn,shotcount, espServerIpPort));
  1652. }
  1653. FILESERVICES_API char * FILESERVICES_CALL fsfMonitorLogicalFileName(ICodeContext *ctx, const char *eventname, const char *_lfn,int shotcount, const char * espServerIpPort)
  1654. {
  1655. CClientFileSpray server;
  1656. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1657. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1658. setServerAccess(server, wu);
  1659. StringBuffer lfn;
  1660. constructLogicalName(ctx, _lfn, lfn);
  1661. if (shotcount == 0)
  1662. shotcount = -1;
  1663. Owned<IClientDfuMonitorRequest> req = server.createDfuMonitorRequest();
  1664. setContainerLocalCertificate(req->rpc());
  1665. req->setEventName(eventname);
  1666. req->setLogicalName(lfn);
  1667. req->setShotLimit(shotcount);
  1668. Owned<IClientDfuMonitorResponse> result = server.DfuMonitor(req);
  1669. StringBuffer res(result->getWuid());
  1670. StringBuffer s("MonitorLogicalFileName ('");
  1671. s.append(lfn).append("'): ").append(res);
  1672. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1673. wu.clear();
  1674. if (res.length()!=0)
  1675. blockUntilComplete("MonitorLogicalFileName",server,ctx,res.str(),1000*60*60,NULL,true);
  1676. return res.detach();
  1677. }
  1678. FILESERVICES_API void FILESERVICES_CALL fsMonitorFile(ICodeContext *ctx, const char *eventname,const char *ip, const char *filename, bool sub, int shotcount, const char * espServerIpPort)
  1679. {
  1680. CTXFREE(parentCtx, fsfMonitorFile(ctx, eventname,ip, filename, sub, shotcount, espServerIpPort));
  1681. }
  1682. FILESERVICES_API char * FILESERVICES_CALL fsfMonitorFile(ICodeContext *ctx, const char *eventname,const char *ip, const char *filename, bool sub, int shotcount, const char * espServerIpPort)
  1683. {
  1684. CClientFileSpray server;
  1685. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1686. server.addServiceUrl(getAccessibleEspServerURL(espServerIpPort,wu));
  1687. setServerAccess(server, wu);
  1688. if (shotcount == 0)
  1689. shotcount = -1;
  1690. Owned<IClientDfuMonitorRequest> req = server.createDfuMonitorRequest();
  1691. setContainerLocalCertificate(req->rpc());
  1692. req->setEventName(eventname);
  1693. req->setIp(ip);
  1694. req->setFilename(filename);
  1695. req->setShotLimit(shotcount);
  1696. Owned<IClientDfuMonitorResponse> result = server.DfuMonitor(req);
  1697. StringBuffer res(result->getWuid());
  1698. StringBuffer s("MonitorFile (");
  1699. s.append(ip).append(", '").append(filename).append("'): '").append(res);
  1700. WUmessage(ctx,SeverityInformation,NULL,s.str());
  1701. wu.clear();
  1702. if (res.length()!=0)
  1703. blockUntilComplete("MonitorFile",server,ctx,res.str(),1000*60*60,NULL,true);
  1704. return res.detach();
  1705. }
  1706. FILESERVICES_API void FILESERVICES_CALL fsSetFileDescription(ICodeContext *ctx, const char *logicalfilename, const char *value)
  1707. {
  1708. StringBuffer lfn;
  1709. constructLogicalName(ctx, logicalfilename, lfn);
  1710. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1711. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false, false, false, nullptr, defaultPrivilegedUser);
  1712. if (df) {
  1713. DistributedFilePropertyLock lock(df);
  1714. lock.queryAttributes().setProp("@description",value);
  1715. }
  1716. else
  1717. throw MakeStringException(0, "SetFileDescription: Could not locate file %s", lfn.str());
  1718. }
  1719. FILESERVICES_API char * FILESERVICES_CALL fsGetFileDescription(ICodeContext *ctx, const char *logicalfilename)
  1720. {
  1721. StringBuffer lfn;
  1722. constructLogicalName(ctx, logicalfilename, lfn);
  1723. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1724. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false, false, false, nullptr, defaultPrivilegedUser);
  1725. if (!df)
  1726. throw MakeStringException(0, "GetFileDescription: Could not locate file %s", lfn.str());
  1727. const char * ret = df->queryAttributes().queryProp("@description");
  1728. if (ret)
  1729. return CTXSTRDUP(parentCtx, ret);
  1730. else
  1731. return CTXSTRDUP(parentCtx, "");
  1732. }
  1733. FILESERVICES_API void FILESERVICES_CALL fsRemoteDirectory(size32_t & __lenResult,void * & __result, const char *machine, const char *dir, const char *mask, bool sub)
  1734. {
  1735. MemoryBuffer mb;
  1736. RemoteFilename rfn;
  1737. SocketEndpoint ep(machine);
  1738. if (ep.isNull()){
  1739. if (machine)
  1740. throw MakeStringException(-1, "RemoteDirectory: Could not resolve host '%s'", machine);
  1741. ep.setLocalHost(0);
  1742. }
  1743. rfn.setPath(ep,dir);
  1744. Owned<IFile> f = createIFile(rfn);
  1745. if (f) {
  1746. StringBuffer s;
  1747. StringBuffer ds;
  1748. Owned<IDirectoryIterator> di = f->directoryFiles(mask,sub);
  1749. if (di) {
  1750. ForEach(*di) {
  1751. di->getName(s.clear());
  1752. __int64 fsz = di->getFileSize();
  1753. CDateTime dt;
  1754. di->getModifiedTime(dt);
  1755. size32_t sz = s.length();
  1756. dt.getString(ds.clear());
  1757. ds.padTo(19);
  1758. mb.append(sz).append(sz,s.str()).append(fsz).append(19,ds.str());
  1759. }
  1760. }
  1761. }
  1762. __lenResult = mb.length();
  1763. __result = mb.detach();
  1764. }
  1765. 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)
  1766. {
  1767. IEngineContext *engineCtx = ctx->queryEngineContext();
  1768. if (engineCtx && !engineCtx->allowDaliAccess())
  1769. {
  1770. Owned<IException> e = MakeStringException(-1, "FileServices.LogicalFileList cannot access Dali in this context - this normally means it is being called from a thor slave");
  1771. EXCLOG(e, NULL);
  1772. throw e.getClear();
  1773. }
  1774. MemoryBuffer mb;
  1775. if (!mask||!*mask)
  1776. mask ="*";
  1777. StringBuffer masklower(mask);
  1778. masklower.toLowerCase();
  1779. Owned<IDFAttributesIterator> iter = queryDistributedFileDirectory().getForeignDFAttributesIterator(masklower.str(),ctx->queryUserDescriptor(),true,includesuper,foreigndali);
  1780. if (iter) {
  1781. StringBuffer s;
  1782. ForEach(*iter) {
  1783. IPropertyTree &attr=iter->query();
  1784. const char *name = attr.queryProp("@name");
  1785. if (!name||!*name)
  1786. continue;
  1787. int numsub = attr.getPropInt("@numsubfiles",-1);
  1788. bool issuper = numsub>=0;
  1789. if (issuper) {
  1790. if (!includesuper)
  1791. continue;
  1792. }
  1793. else {
  1794. if (!includenormal)
  1795. continue;
  1796. }
  1797. size32_t sz = strlen(name);
  1798. mb.append(sz).append(sz,name);
  1799. mb.append(issuper);
  1800. __int64 i64;
  1801. __int64 fsz = attr.getPropInt64("@size",-1);
  1802. if ((fsz==-1)&&(unknownszero||(numsub==0)))
  1803. fsz = 0;
  1804. mb.append(fsz);
  1805. i64 = attr.getPropInt64("@recordCount",-1);
  1806. if ((i64==-1)&&(fsz!=-1)) {
  1807. int rsz = attr.getPropInt("@recordSize",0);
  1808. if (rsz>0)
  1809. i64 = fsz/rsz;
  1810. }
  1811. if ((i64==-1)&&(unknownszero||(numsub==0)))
  1812. i64 = 0;
  1813. mb.append(i64);
  1814. attr.getProp("@modified",s.clear());
  1815. s.padTo(19);
  1816. mb.append(19,s.str());
  1817. attr.getProp("@owner",s.clear());
  1818. sz = s.length();
  1819. mb.append(sz).append(sz,s.str());
  1820. attr.getProp("@group",s.clear());
  1821. sz = s.length();
  1822. mb.append(sz).append(sz,s.str());
  1823. }
  1824. }
  1825. __lenResult = mb.length();
  1826. __result = mb.detach();
  1827. }
  1828. FILESERVICES_API void FILESERVICES_CALL fsSuperFileContents(ICodeContext *ctx, size32_t & __lenResult,void * & __result, const char *lsuperfn, bool recurse)
  1829. {
  1830. MemoryBuffer mb;
  1831. Owned<ISimpleSuperFileEnquiry> enq;
  1832. if (!recurse)
  1833. enq.setown(getSimpleSuperFileEnquiry(ctx, lsuperfn));
  1834. if (enq) {
  1835. StringArray subs;
  1836. enq->getContents(subs);
  1837. ForEachItemIn(i,subs) {
  1838. const char *name = subs.item(i);
  1839. size32_t sz = strlen(name);
  1840. if (!sz)
  1841. continue;
  1842. mb.append(sz).append(sz,name);
  1843. }
  1844. }
  1845. else {
  1846. CImplicitSuperTransaction implicitTransaction(ctx->querySuperFileTransaction());
  1847. Owned<IDistributedSuperFile> file;
  1848. StringBuffer lsfn;
  1849. lookupSuperFile(ctx, lsuperfn, file, true, lsfn, true);
  1850. Owned<IDistributedFileIterator> iter = file->getSubFileIterator(recurse);
  1851. StringBuffer name;
  1852. ForEach(*iter) {
  1853. iter->getName(name.clear());
  1854. size32_t sz = name.length();
  1855. if (!sz)
  1856. continue;
  1857. mb.append(sz).append(sz,name.str());
  1858. }
  1859. }
  1860. __lenResult = mb.length();
  1861. __result = mb.detach();
  1862. }
  1863. FILESERVICES_API void FILESERVICES_CALL fsLogicalFileSuperOwners(ICodeContext *ctx,size32_t & __lenResult,void * & __result, const char *logicalfilename)
  1864. {
  1865. MemoryBuffer mb;
  1866. StringBuffer lfn;
  1867. constructLogicalName(ctx, logicalfilename, lfn);
  1868. StringArray owners;
  1869. if (queryDistributedFileDirectory().getFileSuperOwners(lfn.str(),owners)) {
  1870. ForEachItemIn(i,owners) {
  1871. const char *name = owners.item(i);
  1872. size32_t sz = strlen(name);
  1873. if (!sz)
  1874. continue;
  1875. mb.append(sz).append(sz,name);
  1876. }
  1877. }
  1878. else {
  1879. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1880. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc,false,false,true, nullptr, defaultPrivilegedUser); // lock super-owners
  1881. if (df) {
  1882. Owned<IDistributedSuperFileIterator> iter = df->getOwningSuperFiles();
  1883. ForEach(*iter) {
  1884. const char *name = iter->queryName();
  1885. size32_t sz = strlen(name);
  1886. if (!sz)
  1887. continue;
  1888. mb.append(sz).append(sz,name);
  1889. }
  1890. }
  1891. else
  1892. throw MakeStringException(0, "LogicalFileSuperOwners: Could not locate file %s", lfn.str());
  1893. }
  1894. __lenResult = mb.length();
  1895. __result = mb.detach();
  1896. }
  1897. FILESERVICES_API int FILESERVICES_CALL fsCompareFiles(ICodeContext *ctx,const char *name1, const char *name2,bool logicalonly, bool usecrcs)
  1898. {
  1899. StringBuffer lfn1;
  1900. constructLogicalName(ctx, name1, lfn1);
  1901. StringBuffer lfn2;
  1902. constructLogicalName(ctx, name2, lfn2);
  1903. StringBuffer retstr;
  1904. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1905. 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);
  1906. if (ret==DFS_COMPARE_RESULT_FAILURE)
  1907. throw MakeStringException(ret,"CompareLogicalFiles: %s",retstr.str());
  1908. return ret;
  1909. }
  1910. FILESERVICES_API char * FILESERVICES_CALL fsVerifyFile(ICodeContext *ctx,const char *name,bool usecrcs)
  1911. {
  1912. StringBuffer lfn;
  1913. constructLogicalName(ctx, name, lfn);
  1914. StringBuffer retstr;
  1915. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  1916. if (queryDistributedFileDirectory().filePhysicalVerify(lfn.str(),udesc,usecrcs,retstr))
  1917. retstr.append("OK");
  1918. return retstr.detach();
  1919. }
  1920. // RemotePull
  1921. /*
  1922. varstring RemotePull(
  1923. const varstring remoteEspFsURL, // remote ESP URL e.g. 'http://10.173.34.60:8010/FileSpray'
  1924. const varstring sourceLogicalName, // local
  1925. const varstring destinationGroup, // remote
  1926. const varstring destinationLogicalName, // remote (NB full name required)
  1927. integer4 timeOut=-1,
  1928. integer4 maxConnections=-1,
  1929. boolean allowoverwrite=false,
  1930. boolean replicate=false,
  1931. boolean asSuperfile=false);
  1932. */
  1933. FILESERVICES_API char * FILESERVICES_CALL fsfRemotePull_impl(ICodeContext *ctx,
  1934. const char * remoteEspFsURL,
  1935. const char * sourceLogicalName,
  1936. const char *destinationGroup,
  1937. const char * destinationLogicalName,
  1938. int timeOut,
  1939. int maxConnections,
  1940. bool overwrite,
  1941. bool replicate,
  1942. bool asSuperfile,
  1943. bool forcePush,
  1944. int transferBufferSize,
  1945. bool wrap,
  1946. bool compress,
  1947. bool noSplit,
  1948. int expireDays,
  1949. const char *username,
  1950. const char *userPw)
  1951. {
  1952. LOG(MCauditInfo, "RemotePull(%s): %s%s", remoteEspFsURL,sourceLogicalName,asSuperfile?" as superfile":"");
  1953. CClientFileSpray server;
  1954. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  1955. server.addServiceUrl(remoteEspFsURL);
  1956. setServerAccess(server, wu);
  1957. Owned<IClientCopy> req = server.createCopyRequest();
  1958. setContainerLocalCertificate(req->rpc());
  1959. if (asSuperfile)
  1960. req->setSuperCopy(true);
  1961. StringBuffer _sourceLogicalName, _destinationLogicalName;
  1962. constructLogicalName(wu, sourceLogicalName, _sourceLogicalName);
  1963. // destination name assumed complete (so just skip ~ *)
  1964. while ((*destinationLogicalName=='~')||isspace(*destinationLogicalName))
  1965. destinationLogicalName++;
  1966. _destinationLogicalName.append(destinationLogicalName);
  1967. if (strstr(_destinationLogicalName.str(),"::")==NULL)
  1968. _destinationLogicalName.insert(0,".::");
  1969. StringBuffer _destGroup;
  1970. _destGroup.append(destinationGroup);
  1971. req->setSourceLogicalName(_sourceLogicalName.str());
  1972. req->setDestLogicalName(_destinationLogicalName.str());
  1973. req->setDestGroup(_destGroup.str());
  1974. if (compress)
  1975. req->setCompress(true);
  1976. if (wrap)
  1977. req->setWrap(true);
  1978. StringBuffer sourceDali;
  1979. queryCoven().queryComm().queryGroup().queryNode(0).endpoint().getUrlStr(sourceDali);
  1980. req->setSourceDali(sourceDali);
  1981. req->setOverwrite(overwrite);
  1982. req->setReplicate(replicate);
  1983. if (forcePush)
  1984. req->setPush(true);
  1985. if (transferBufferSize>0)
  1986. req->setTransferBufferSize(transferBufferSize);
  1987. if (noSplit)
  1988. req->setNosplit(true);
  1989. req->setExpireDays(expireDays);
  1990. // Handle username/psw
  1991. if (!isEmptyString(username))
  1992. {
  1993. server.setUsernameToken(username, userPw, nullptr);
  1994. req->setSrcusername(username);
  1995. if (!isEmptyString(userPw))
  1996. req->setSrcpassword(userPw);
  1997. }
  1998. Owned<IClientCopyResponse> result = server.Copy(req);
  1999. StringBuffer wuid(result->getResult());
  2000. if (!wuid.length())
  2001. {
  2002. const IMultiException* excep = &result->getExceptions();
  2003. if ((excep != NULL) && (excep->ordinality() > 0))
  2004. {
  2005. StringBuffer errmsg;
  2006. excep->errorMessage(errmsg);
  2007. throw MakeStringExceptionDirect(0, errmsg.str());
  2008. }
  2009. else
  2010. {
  2011. throw MakeStringExceptionDirect(0, "Result's dfu WUID is empty");
  2012. }
  2013. }
  2014. wu.clear();
  2015. blockUntilComplete("RemotePull", server, ctx, wuid, timeOut);
  2016. return wuid.detach();
  2017. }
  2018. FILESERVICES_API char * FILESERVICES_CALL fsfRemotePull(ICodeContext *ctx,
  2019. const char * remoteEspFsURL,
  2020. const char * sourceLogicalName,
  2021. const char *destinationGroup,
  2022. const char * destinationLogicalName,
  2023. int timeOut,
  2024. int maxConnections,
  2025. bool overwrite,
  2026. bool replicate,
  2027. bool asSuperfile,
  2028. bool forcePush,
  2029. int transferBufferSize,
  2030. bool wrap,
  2031. bool compress)
  2032. {
  2033. return fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, false, -1, nullptr, nullptr);
  2034. }
  2035. FILESERVICES_API void FILESERVICES_CALL fsRemotePull(ICodeContext *ctx,
  2036. const char * remoteEspFsURL,
  2037. const char * sourceLogicalName,
  2038. const char *destinationGroup,
  2039. const char * destinationLogicalName,
  2040. int timeOut,
  2041. int maxConnections,
  2042. bool overwrite,
  2043. bool replicate,
  2044. bool asSuperfile,
  2045. bool forcePush,
  2046. int transferBufferSize,
  2047. bool wrap,
  2048. bool compress)
  2049. {
  2050. CTXFREE(parentCtx, fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, false, -1, nullptr, nullptr));
  2051. }
  2052. FILESERVICES_API char * FILESERVICES_CALL fsfRemotePull_v2(ICodeContext *ctx,
  2053. const char * remoteEspFsURL,
  2054. const char * sourceLogicalName,
  2055. const char *destinationGroup,
  2056. const char * destinationLogicalName,
  2057. int timeOut,
  2058. int maxConnections,
  2059. bool overwrite,
  2060. bool replicate,
  2061. bool asSuperfile,
  2062. bool forcePush,
  2063. int transferBufferSize,
  2064. bool wrap,
  2065. bool compress,
  2066. bool noSplit,
  2067. int expireDays)
  2068. {
  2069. return fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, noSplit, expireDays, nullptr, nullptr);
  2070. }
  2071. FILESERVICES_API void FILESERVICES_CALL fsRemotePull_v2(ICodeContext *ctx,
  2072. const char * remoteEspFsURL,
  2073. const char * sourceLogicalName,
  2074. const char *destinationGroup,
  2075. const char * destinationLogicalName,
  2076. int timeOut,
  2077. int maxConnections,
  2078. bool overwrite,
  2079. bool replicate,
  2080. bool asSuperfile,
  2081. bool forcePush,
  2082. int transferBufferSize,
  2083. bool wrap,
  2084. bool compress,
  2085. bool noSplit,
  2086. int expireDays)
  2087. {
  2088. CTXFREE(parentCtx, fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, noSplit, expireDays, nullptr, nullptr));
  2089. }
  2090. FILESERVICES_API char * FILESERVICES_CALL fsfRemotePull_v3(ICodeContext *ctx,
  2091. const char * remoteEspFsURL,
  2092. const char * sourceLogicalName,
  2093. const char *destinationGroup,
  2094. const char * destinationLogicalName,
  2095. int timeOut,
  2096. int maxConnections,
  2097. bool overwrite,
  2098. bool replicate,
  2099. bool asSuperfile,
  2100. bool forcePush,
  2101. int transferBufferSize,
  2102. bool wrap,
  2103. bool compress,
  2104. bool noSplit,
  2105. int expireDays,
  2106. const char *username,
  2107. const char *userPw)
  2108. {
  2109. return fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, noSplit, expireDays, username, userPw);
  2110. }
  2111. FILESERVICES_API void FILESERVICES_CALL fsRemotePull_v3(ICodeContext *ctx,
  2112. const char * remoteEspFsURL,
  2113. const char * sourceLogicalName,
  2114. const char *destinationGroup,
  2115. const char * destinationLogicalName,
  2116. int timeOut,
  2117. int maxConnections,
  2118. bool overwrite,
  2119. bool replicate,
  2120. bool asSuperfile,
  2121. bool forcePush,
  2122. int transferBufferSize,
  2123. bool wrap,
  2124. bool compress,
  2125. bool noSplit,
  2126. int expireDays,
  2127. const char *username,
  2128. const char *userPw)
  2129. {
  2130. CTXFREE(parentCtx, fsfRemotePull_impl(ctx, remoteEspFsURL, sourceLogicalName, destinationGroup, destinationLogicalName, timeOut, maxConnections, overwrite, replicate, asSuperfile,forcePush,transferBufferSize, wrap, compress, noSplit, expireDays, username, userPw));
  2131. }
  2132. FILESERVICES_API void FILESERVICES_CALL fsLogicalFileSuperSubList(ICodeContext *ctx, size32_t & __lenResult,void * & __result)
  2133. {
  2134. MemoryBuffer mb;
  2135. getLogicalFileSuperSubList(mb, ctx->queryUserDescriptor());
  2136. __lenResult = mb.length();
  2137. __result = mb.detach();
  2138. }
  2139. 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)
  2140. {
  2141. CTXFREE(parentCtx, fsfPromoteSuperFileList(ctx,isAllLsuperfns,lenLsuperfns,lsuperfns,addhead,deltail,createonlyonesuperfile,reverse));
  2142. }
  2143. 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)
  2144. {
  2145. Owned<IConstWorkUnit> wu = getWorkunit(ctx);
  2146. MemoryBuffer mb;
  2147. StringBuffer lfn;
  2148. UnsignedArray lfnofs;
  2149. const char *s = (const char *)lsuperfns;
  2150. // MORE - For now, we need a local transaction
  2151. CheckNotInTransaction(ctx, "PromoteSuperFile");
  2152. while ((size32_t)(s-(const char *)lsuperfns)<lenLsuperfns) {
  2153. constructLogicalName(wu,s,lfn.clear());
  2154. lfnofs.append(mb.length());
  2155. mb.append(lfn);
  2156. s = s+strlen(s)+1;
  2157. }
  2158. PointerArray lfns;
  2159. ForEachItemIn(i,lfnofs) {
  2160. lfns.append((void *)(mb.toByteArray()+lfnofs.item(reverse?(lfnofs.ordinality()-i-1):i)));
  2161. }
  2162. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2163. StringArray toadd;
  2164. toadd.appendListUniq(addhead, ",");
  2165. StringBuffer addlist;
  2166. ForEachItemIn(i1,toadd) {
  2167. if (addlist.length())
  2168. addlist.append(',');
  2169. constructLogicalName(wu,toadd.item(i1),addlist);
  2170. }
  2171. toadd.kill();
  2172. queryDistributedFileDirectory().promoteSuperFiles(lfns.ordinality(),(const char **)lfns.getArray(),addlist.str(),deltail,createonlyonesuperfile,udesc.get(),(unsigned)-1,toadd);
  2173. addlist.clear();
  2174. ForEachItemIn(i2,toadd) {
  2175. if (addlist.length())
  2176. addlist.append(',');
  2177. constructLogicalName(wu,toadd.item(i2),addlist);
  2178. }
  2179. return addlist.detach();
  2180. }
  2181. FILESERVICES_API unsigned __int64 FILESERVICES_CALL fsGetUniqueInteger(ICodeContext * ctx, const char *foreigndali)
  2182. {
  2183. SocketEndpoint ep;
  2184. if (foreigndali&&*foreigndali)
  2185. ep.set(foreigndali);
  2186. IEngineContext *engineContext = ctx->queryEngineContext();
  2187. if (engineContext)
  2188. return engineContext->getGlobalUniqueIds(1,&ep);
  2189. return getGlobalUniqueIds(1,&ep);
  2190. }
  2191. 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)
  2192. {
  2193. StringBuffer pfn;
  2194. constructLogicalName(ctx, primary, pfn);
  2195. StringBuffer sfn;
  2196. constructLogicalName(ctx, secondary, sfn);
  2197. queryDistributedFileDirectory().addFileRelationship(pfn.str(),sfn.str(),primflds,secflds,kind,cardinality,payload,ctx->queryUserDescriptor(), description);
  2198. StringBuffer s("AddFileRelationship('");
  2199. s.append(pfn.str()).append("','").append(sfn.str()).append("','").append(primflds?primflds:"").append("','").append(secflds?secflds:"").append("','").append(kind?kind:"").append("') done");
  2200. WUmessage(ctx,SeverityInformation,NULL,s.str());
  2201. }
  2202. static inline void addmbstr(MemoryBuffer &mb,const char *s)
  2203. {
  2204. size32_t sz = strlen(s);
  2205. mb.append(sz).append(sz,s);
  2206. }
  2207. 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)
  2208. {
  2209. StringBuffer pfn;
  2210. if (primary&&*primary)
  2211. constructLogicalName(ctx, primary, pfn);
  2212. StringBuffer sfn;
  2213. if (secondary&&*secondary)
  2214. constructLogicalName(ctx, secondary, sfn);
  2215. MemoryBuffer mb;
  2216. Owned<IFileRelationshipIterator> iter = queryDistributedFileDirectory().lookupFileRelationships(pfn.str(),sfn.str(),primflds,secflds,kind);
  2217. if (iter) {
  2218. StringBuffer s;
  2219. ForEach(*iter) {
  2220. IFileRelationship &rel=iter->query();
  2221. addmbstr(mb,rel.queryPrimaryFilename());
  2222. addmbstr(mb,rel.querySecondaryFilename());
  2223. addmbstr(mb,rel.queryPrimaryFields());
  2224. addmbstr(mb,rel.querySecondaryFields());
  2225. addmbstr(mb,rel.queryKind());
  2226. addmbstr(mb,rel.queryCardinality());
  2227. mb.append((byte)(rel.isPayload()?1:0));
  2228. addmbstr(mb,rel.queryDescription());
  2229. }
  2230. }
  2231. __lenResult = mb.length();
  2232. __result = mb.detach();
  2233. }
  2234. FILESERVICES_API void FILESERVICES_CALL fsRemoveFileRelationship(ICodeContext * ctx,const char *primary, const char *secondary, const char *primflds, const char *secflds, const char *kind)
  2235. {
  2236. StringBuffer pfn;
  2237. if (primary&&*primary)
  2238. constructLogicalName(ctx, primary, pfn);
  2239. StringBuffer sfn;
  2240. if (secondary&&*secondary)
  2241. constructLogicalName(ctx, secondary, sfn);
  2242. queryDistributedFileDirectory().removeFileRelationships(pfn.str(),sfn.str(),primflds,secflds,kind);
  2243. }
  2244. FILESERVICES_API void FILESERVICES_CALL fsSetColumnMapping(ICodeContext * ctx,const char *filename, const char *mapping)
  2245. {
  2246. StringBuffer lfn;
  2247. constructLogicalName(ctx, filename, lfn);
  2248. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),ctx->queryUserDescriptor(),true,false,false,nullptr,defaultPrivilegedUser);
  2249. if (df)
  2250. df->setColumnMapping(mapping);
  2251. else
  2252. throw MakeStringException(-1, "SetColumnMapping: Could not find logical file %s", lfn.str());
  2253. }
  2254. FILESERVICES_API char * FILESERVICES_CALL fsfGetColumnMapping(ICodeContext * ctx,const char *filename)
  2255. {
  2256. StringBuffer lfn;
  2257. constructLogicalName(ctx, filename, lfn);
  2258. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),ctx->queryUserDescriptor(),true,false,false,nullptr,defaultPrivilegedUser);
  2259. if (df) {
  2260. StringBuffer mapping;
  2261. df->getColumnMapping(mapping);
  2262. return mapping.detach();
  2263. }
  2264. throw MakeStringException(-1, "GetColumnMapping: Could not find logical file %s", lfn.str());
  2265. return NULL;
  2266. }
  2267. FILESERVICES_API char * FILESERVICES_CALL fsfRfsQuery(const char *server, const char *query)
  2268. {
  2269. StringBuffer ret;
  2270. ret.append('~');
  2271. CDfsLogicalFileName lfn;
  2272. lfn.setQuery(server,query);
  2273. if (!lfn.isSet())
  2274. throw MakeStringException(-1, "RfsQuery invalid parameter");
  2275. return lfn.get(ret).detach();
  2276. }
  2277. FILESERVICES_API void FILESERVICES_CALL fsRfsAction(const char *server, const char *query)
  2278. {
  2279. CDfsLogicalFileName lfn;
  2280. lfn.setQuery(server,query);
  2281. if (!lfn.isSet())
  2282. throw MakeStringException(-1, "RfsAction invalid parameter");
  2283. RemoteFilename rfn;
  2284. lfn.getExternalFilename(rfn);
  2285. Owned<IFile> file = createIFile(rfn);
  2286. Owned<IFileIO> fileio = file->open(IFOread);
  2287. if (fileio) {
  2288. // lets just try reading a byte to cause action
  2289. byte b;
  2290. fileio->read(0,sizeof(b),&b);
  2291. }
  2292. }
  2293. FILESERVICES_API char * FILESERVICES_CALL fsfGetHostName(const char *ipaddress)
  2294. {
  2295. // not a common routine (no Jlib function!) only support IPv4 initially
  2296. StringBuffer ret;
  2297. if (ipaddress&&*ipaddress) {
  2298. IpAddress ip(ipaddress);
  2299. lookupHostName(ip,ret);
  2300. }
  2301. else
  2302. GetHostName(ret);
  2303. return ret.detach();
  2304. }
  2305. FILESERVICES_API char * FILESERVICES_CALL fsfResolveHostName(const char *hostname)
  2306. {
  2307. StringBuffer ret;
  2308. SocketEndpoint ep(hostname);
  2309. ep.getIpText(ret);
  2310. return ret.detach();
  2311. }
  2312. static void checkExternalFileRights(ICodeContext *ctx, CDfsLogicalFileName &lfn, bool rd,bool wr)
  2313. {
  2314. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2315. unsigned auditflags = 0;
  2316. if (rd)
  2317. auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_READ_WANTED);
  2318. if (wr)
  2319. auditflags |= (DALI_LDAP_AUDIT_REPORT|DALI_LDAP_WRITE_WANTED);
  2320. SecAccessFlags perm = queryDistributedFileDirectory().getFilePermissions(lfn.get(),udesc,auditflags);
  2321. if (wr) {
  2322. if (!HASWRITEPERMISSION(perm)) {
  2323. throw MakeStringException(-1,"Write permission denied for %s", lfn.get());
  2324. }
  2325. }
  2326. if (rd) {
  2327. if (!HASREADPERMISSION(perm)) {
  2328. throw MakeStringException(-1,"Read permission denied for %s", lfn.get());
  2329. }
  2330. }
  2331. }
  2332. FILESERVICES_API void FILESERVICES_CALL fsMoveExternalFile(ICodeContext * ctx,const char *location,const char *frompath,const char *topath)
  2333. {
  2334. SocketEndpoint ep(location);
  2335. if (ep.isNull())
  2336. throw MakeStringException(-1,"fsMoveExternalFile: Cannot resolve location %s",location);
  2337. CDfsLogicalFileName from;
  2338. from.setExternal(location,frompath);
  2339. CDfsLogicalFileName to;
  2340. to.setExternal(location,topath);
  2341. checkExternalFileRights(ctx,from,true,true);
  2342. checkExternalFileRights(ctx,to,false,true);
  2343. RemoteFilename fromrfn;
  2344. fromrfn.setPath(ep,frompath);
  2345. RemoteFilename torfn;
  2346. torfn.setPath(ep,topath);
  2347. Owned<IFile> fileto = createIFile(torfn);
  2348. if (fileto->exists())
  2349. throw MakeStringException(-1,"fsMoveExternalFile: Destination %s already exists", topath);
  2350. fileto.clear();
  2351. Owned<IFile> file = createIFile(fromrfn);
  2352. file->move(topath);
  2353. StringBuffer s("MoveExternalFile ('");
  2354. s.append(location).append(',').append(frompath).append(',').append(topath).append(") done");
  2355. WUmessage(ctx,SeverityInformation,NULL,s.str());
  2356. AuditMessage(ctx,"MoveExternalFile",frompath,topath);
  2357. }
  2358. FILESERVICES_API void FILESERVICES_CALL fsDeleteExternalFile(ICodeContext * ctx,const char *location,const char *path)
  2359. {
  2360. SocketEndpoint ep(location);
  2361. if (ep.isNull())
  2362. throw MakeStringException(-1,"fsDeleteExternalFile: Cannot resolve location %s",location);
  2363. CDfsLogicalFileName lfn;
  2364. lfn.setExternal(location,path);
  2365. checkExternalFileRights(ctx,lfn,false,true);
  2366. RemoteFilename rfn;
  2367. rfn.setPath(ep,path);
  2368. Owned<IFile> file = createIFile(rfn);
  2369. file->remove();
  2370. StringBuffer s("DeleteExternalFile ('");
  2371. s.append(location).append(',').append(path).append(") done");
  2372. WUmessage(ctx,SeverityInformation,NULL,s.str());
  2373. AuditMessage(ctx,"DeleteExternalFile",path);
  2374. }
  2375. FILESERVICES_API void FILESERVICES_CALL fsCreateExternalDirectory(ICodeContext * ctx,const char *location,const char *_path)
  2376. {
  2377. SocketEndpoint ep(location);
  2378. if (ep.isNull())
  2379. throw MakeStringException(-1, "fsCreateExternalDirectory: Cannot resolve location %s",location);
  2380. CDfsLogicalFileName lfn;
  2381. StringBuffer path(_path);
  2382. if (0 == path.length())
  2383. throw MakeStringException(-1, "fsCreateExternalDirectory: empty directory");
  2384. // remove trailing path separator if present to make it look like a regular LFN after lfn.setExternal
  2385. if (isPathSepChar(path.charAt(path.length()-1)))
  2386. path.remove(path.length()-1, 1);
  2387. lfn.setExternal(location,path);
  2388. checkExternalFileRights(ctx,lfn,false,true);
  2389. RemoteFilename rfn;
  2390. rfn.setPath(ep,path);
  2391. Owned<IFile> file = createIFile(rfn);
  2392. file->createDirectory();
  2393. StringBuffer s("CreateExternalDirectory ('");
  2394. s.append(location).append(',').append(path).append(") done");
  2395. WUmessage(ctx,SeverityInformation,NULL,s.str());
  2396. AuditMessage(ctx,"CreateExternalDirectory",path);
  2397. }
  2398. FILESERVICES_API char * FILESERVICES_CALL fsfGetLogicalFileAttribute(ICodeContext * ctx,const char *_lfn,const char *attrname)
  2399. {
  2400. StringBuffer lfn;
  2401. constructLogicalName(ctx, _lfn, lfn);
  2402. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2403. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false,false, false, nullptr, defaultPrivilegedUser);
  2404. StringBuffer ret;
  2405. if (df) {
  2406. if (strcmp(attrname,"ECL")==0)
  2407. df->getECL(ret);
  2408. else if (strcmp(attrname,"clusterName")==0)
  2409. df->getClusterName(0,ret);
  2410. else if (strcmp(attrname,"partmask")==0)
  2411. ret.append(df->queryPartMask());
  2412. else if (strcmp(attrname,"directory")==0)
  2413. ret.append(df->queryDefaultDir());
  2414. else if (strcmp(attrname,"numparts")==0)
  2415. ret.append(df->numParts());
  2416. else if (strcmp(attrname,"name")==0)
  2417. ret.append(df->queryLogicalName());
  2418. else if (strcmp(attrname,"modified")==0) {
  2419. CDateTime dt;
  2420. df->getModificationTime(dt);
  2421. dt.getString(ret);
  2422. }
  2423. else if (strcmp(attrname,"protected")==0) {
  2424. IPropertyTree &attr = df->queryAttributes();
  2425. Owned<IPropertyTreeIterator> piter = attr.getElements("Protect");
  2426. ForEach(*piter) {
  2427. const char *name = piter->query().queryProp("@name");
  2428. if (name&&*name) {
  2429. if (ret.length())
  2430. ret.append(',');
  2431. ret.append(name);
  2432. }
  2433. }
  2434. }
  2435. else {
  2436. StringBuffer xpath("@");
  2437. xpath.append(attrname);
  2438. IPropertyTree &attr = df->queryAttributes();
  2439. attr.getProp(xpath.str(),ret);
  2440. }
  2441. }
  2442. else
  2443. throw MakeStringException(0, "GetLogicalFileAttribute: Could not find logical file %s", lfn.str());
  2444. return ret.detach();
  2445. }
  2446. FILESERVICES_API void FILESERVICES_CALL fsProtectLogicalFile(ICodeContext * ctx, const char *_lfn, bool set)
  2447. {
  2448. StringBuffer lfn;
  2449. constructLogicalName(ctx, _lfn, lfn);
  2450. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2451. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(), udesc, false, false, false, nullptr, defaultPrivilegedUser);
  2452. if (df)
  2453. {
  2454. StringBuffer uname;
  2455. udesc->getUserName(uname);
  2456. df->setProtect(uname, set);
  2457. if (!set)
  2458. {
  2459. // for backward compatibility only (see HPCC-23190)
  2460. uname.clear().append("user:");
  2461. udesc->getUserName(uname);
  2462. df->setProtect(uname, false);
  2463. }
  2464. }
  2465. else if (set)
  2466. throw MakeStringException(0, "ProtectLogicalFile: Could not find logical file %s", lfn.str());
  2467. }
  2468. static bool build_dfuplus_globals(int argc, const char *argv[], IProperties * globals)
  2469. {
  2470. for (int i = 1; i < argc; i++)
  2471. if (strchr(argv[i],'='))
  2472. globals->loadProp(argv[i]);
  2473. StringBuffer tmp;
  2474. if (globals->hasProp("encrypt")) {
  2475. encrypt(tmp.clear(),globals->queryProp("encrypt") ); // basic encryption at this stage
  2476. globals->setProp("encrypt",tmp.str());
  2477. }
  2478. if (globals->hasProp("decrypt")) {
  2479. encrypt(tmp.clear(),globals->queryProp("decrypt") ); // basic encryption at this stage
  2480. globals->setProp("decrypt",tmp.str());
  2481. }
  2482. return true;
  2483. }
  2484. FILESERVICES_API void FILESERVICES_CALL fsDfuPlusExec(ICodeContext * ctx,const char *_cmd)
  2485. {
  2486. if (!_cmd||!*_cmd)
  2487. return;
  2488. MemoryBuffer mb;
  2489. const char **argv;
  2490. StringBuffer cmdline;
  2491. if (strcmp(_cmd,"dfuplus ")!=0)
  2492. cmdline.append("dfuplus ");
  2493. cmdline.append(_cmd);
  2494. int argc = parseCommandLine(cmdline.str(),mb,argv);
  2495. Owned<IProperties> globals = createProperties(true);
  2496. if (!build_dfuplus_globals(argc, argv, globals))
  2497. throw MakeStringException(-1,"DfuPlusExec: invalid command line");
  2498. const char* server = globals->queryProp("server");
  2499. if (!server || !*server)
  2500. throw MakeStringException(-1,"DfuPlusExec: server url not specified");
  2501. const char* action = globals->queryProp("action");
  2502. if (!action || !*action)
  2503. throw MakeStringException(-1,"DfuPlusExec: no action specified");
  2504. if (ctx) {
  2505. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2506. StringBuffer tmp;
  2507. const char* username = globals->queryProp("username");
  2508. if (!username || !*username)
  2509. globals->setProp("username",udesc->getUserName(tmp.clear()).str());;
  2510. const char* passwd = globals->queryProp("password");
  2511. if (!passwd || !*passwd)
  2512. globals->setProp("password",udesc->getPassword(tmp.clear()).str());;
  2513. }
  2514. class cMsg: implements CDfuPlusMessagerIntercept
  2515. {
  2516. ICodeContext * ctx;
  2517. unsigned limit;
  2518. public:
  2519. cMsg(ICodeContext *_ctx)
  2520. {
  2521. limit = 0;
  2522. ctx = _ctx;
  2523. }
  2524. void info(const char *msg)
  2525. {
  2526. if (ctx&&(++limit<100))
  2527. WUmessage(ctx,SeverityInformation,NULL,msg);
  2528. }
  2529. void err(const char *msg)
  2530. {
  2531. throw MakeStringException(-1,"DfuPlusExec: %s",msg);
  2532. }
  2533. } cmsg(ctx);
  2534. try {
  2535. Owned<CDfuPlusHelper> helper = new CDfuPlusHelper(LINK(globals.get()));
  2536. helper->msgintercept = &cmsg;
  2537. helper->doit();
  2538. }
  2539. catch(IException* e) {
  2540. EXCLOG(e,"fsDfuPlusExec");
  2541. throw;
  2542. }
  2543. }
  2544. FILESERVICES_API char * FILESERVICES_CALL fsGetEspURL(const char *username, const char *userPW)
  2545. {
  2546. #ifdef _CONTAINERIZED
  2547. const IPropertyTree *match = nullptr;
  2548. const char *espService = getComponentConfigSP()->queryProp("@defaultEsp");
  2549. Owned<IPropertyTree> globalConfig = getGlobalConfig();
  2550. if (isEmptyString(espService))
  2551. espService = globalConfig->queryProp("@defaultEsp");
  2552. if (!isEmptyString(espService))
  2553. {
  2554. VStringBuffer service("services[@name='%s']", espService);
  2555. match = globalConfig->queryPropTree(service.str());
  2556. }
  2557. if (!match)
  2558. {
  2559. // Look for 'eclservices' esp service, fallback to 'eclwatch' service.
  2560. Owned<IPropertyTreeIterator> iter = globalConfig->getElements("services");
  2561. ForEach(*iter)
  2562. {
  2563. const char *type = iter->query().queryProp("@type");
  2564. if (streq("eclservices", type))
  2565. {
  2566. match = &iter->query();
  2567. break;
  2568. }
  2569. else if (streq("eclwatch", type))
  2570. match = &iter->query();
  2571. }
  2572. }
  2573. if (match) // MORE - if not found, we could generate a warning - it implies something misconfigured!
  2574. {
  2575. if (!espService)
  2576. espService = match->queryProp("@name");
  2577. StringBuffer credentials;
  2578. if (username && username[0] && userPW && userPW[0])
  2579. credentials.setf("%s:%s@", username, userPW);
  2580. else if (username && username[0])
  2581. credentials.setf("%s@", username);
  2582. const char *protocol = match->getPropBool("@tls") ? "https" : "http";
  2583. unsigned port = match->getPropInt("@port", 8010);
  2584. VStringBuffer espURL("mtls:%s://%s%s:%u", protocol, credentials.str(), espService, port);
  2585. return espURL.detach();
  2586. }
  2587. #else
  2588. Owned<IConstEnvironment> daliEnv = openDaliEnvironment();
  2589. Owned<IPropertyTree> env = getEnvironmentTree(daliEnv);
  2590. if (env.get())
  2591. {
  2592. StringBuffer espURL;
  2593. StringBuffer espInstanceComputerName;
  2594. StringBuffer bindingProtocol;
  2595. StringBuffer xpath;
  2596. StringBuffer instanceAddress;
  2597. StringBuffer espServiceType;
  2598. StringBuffer credentials;
  2599. Owned<IPropertyTreeIterator> espProcessIter = env->getElements("Software/EspProcess");
  2600. ForEach(*espProcessIter)
  2601. {
  2602. Owned<IPropertyTreeIterator> espBindingIter = espProcessIter->query().getElements("EspBinding");
  2603. ForEach(*espBindingIter)
  2604. {
  2605. espBindingIter->query().getProp("@service",espURL.clear());
  2606. xpath.setf("Software/EspService[@name=\"%s\"]/Properties/@type", espURL.str());
  2607. if(env->getProp(xpath.str(), espServiceType.clear()))
  2608. {
  2609. if (strieq(espServiceType.str(),"WsSMC"))
  2610. {
  2611. if (espBindingIter->query().getProp("@protocol",bindingProtocol.clear()))
  2612. {
  2613. Owned<IPropertyTreeIterator> espInstanceIter = espProcessIter->query().getElements("Instance");
  2614. ForEach(*espInstanceIter)
  2615. {
  2616. if (espInstanceIter->query().getProp("@computer",espInstanceComputerName.clear()))
  2617. {
  2618. xpath.setf("Hardware/Computer[@name=\"%s\"]/@netAddress",espInstanceComputerName.str());
  2619. if (env->getProp(xpath.str(),instanceAddress.clear()))
  2620. {
  2621. if (username && username[0] && userPW && userPW[0])
  2622. credentials.setf("%s:%s@", username, userPW);
  2623. else if (username && username[0])
  2624. credentials.setf("%s@", username);
  2625. if (streq(instanceAddress.str(),"."))
  2626. {
  2627. SocketEndpoint ep(instanceAddress.str());
  2628. ep.getIpText(instanceAddress.clear());
  2629. }
  2630. espURL.setf("%s://%s%s:%d", bindingProtocol.str(), credentials.str(), instanceAddress.str(), espBindingIter->query().getPropInt("@port",8010));
  2631. return espURL.detach();
  2632. }
  2633. }
  2634. }
  2635. }
  2636. }
  2637. }
  2638. }
  2639. }
  2640. }
  2641. #endif
  2642. return strdup("");
  2643. }
  2644. FILESERVICES_API char * FILESERVICES_CALL fsGetDefaultDropZone()
  2645. {
  2646. StringBuffer dropZonePath;
  2647. Owned<IPropertyTreeIterator> dropZones = getGlobalConfigSP()->getElements("storage/planes[@category='lz']");
  2648. if (dropZones->first())
  2649. dropZones->query().getProp("@prefix", dropZonePath); // Why the directory? seems a very stange choice
  2650. return strdup(dropZonePath.str());
  2651. }
  2652. FILESERVICES_API void FILESERVICES_CALL fsGetDropZones(ICodeContext *ctx, size32_t & __lenResult, void * & __result)
  2653. {
  2654. MemoryBuffer mb;
  2655. Owned<IPropertyTreeIterator> dropZones = getGlobalConfigSP()->getElements("storage/planes[@category='lz']");
  2656. ForEach(*dropZones)
  2657. {
  2658. const char * directory = dropZones->query().queryProp("@prefix");
  2659. size32_t sz = strlen(directory);
  2660. mb.append(sz).append(sz,directory);
  2661. }
  2662. __lenResult = mb.length();
  2663. __result = mb.detach();
  2664. }
  2665. FILESERVICES_API int FILESERVICES_CALL fsGetExpireDays(ICodeContext * ctx, const char *_lfn)
  2666. {
  2667. StringBuffer lfn;
  2668. constructLogicalName(ctx, _lfn, lfn);
  2669. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2670. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false,false, false, nullptr, defaultPrivilegedUser);
  2671. if (df)
  2672. return df->getExpire();
  2673. else
  2674. throw makeStringExceptionV(0, "GetExpireDays: Could not find logical file %s", lfn.str());
  2675. }
  2676. FILESERVICES_API void FILESERVICES_CALL fsSetExpireDays(ICodeContext * ctx, const char *_lfn, int expireDays)
  2677. {
  2678. if (expireDays < 0)
  2679. throw makeStringExceptionV(0, "SetExpireDays: expireDays parameter value should be >= 0 (%d)", expireDays);
  2680. StringBuffer lfn;
  2681. constructLogicalName(ctx, _lfn, lfn);
  2682. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2683. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false,false, false, nullptr, defaultPrivilegedUser);
  2684. if (df)
  2685. df->setExpire(expireDays);
  2686. else
  2687. throw makeStringExceptionV(0, "SetExpireDays: Could not find logical file %s", lfn.str());
  2688. }
  2689. FILESERVICES_API void FILESERVICES_CALL fsClearExpireDays(ICodeContext * ctx, const char *_lfn)
  2690. {
  2691. StringBuffer lfn;
  2692. constructLogicalName(ctx, _lfn, lfn);
  2693. Linked<IUserDescriptor> udesc = ctx->queryUserDescriptor();
  2694. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn.str(),udesc, false,false, false, nullptr, defaultPrivilegedUser);
  2695. if (df)
  2696. df->setExpire(-1);
  2697. else
  2698. throw makeStringExceptionV(0, "ClearExpireDays: Could not find logical file %s", lfn.str());
  2699. }