fileservices.cpp 96 KB

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