fileservices.cpp 110 KB

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