daliadmin.cpp 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834
  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. #include "platform.h"
  14. #include "portlist.h"
  15. #include "jlib.hpp"
  16. #include "jmisc.hpp"
  17. #include "jptree.hpp"
  18. #include "jarray.hpp"
  19. #include "jencrypt.hpp"
  20. #include "jregexp.hpp"
  21. #include "jptree.hpp"
  22. #include "jlzw.hpp"
  23. #include "jexcept.hpp"
  24. #include "jset.hpp"
  25. #include "jprop.hpp"
  26. #include "mpbase.hpp"
  27. #include "mpcomm.hpp"
  28. #include "daclient.hpp"
  29. #include "dadiags.hpp"
  30. #include "danqs.hpp"
  31. #include "dadfs.hpp"
  32. #include "dasds.hpp"
  33. #include "dautils.hpp"
  34. #include "daaudit.hpp"
  35. #include "daft.hpp"
  36. #include "rmtfile.hpp"
  37. #include "workunit.hpp"
  38. #include "dllserver.hpp"
  39. #ifdef _WIN32
  40. #include <conio.h>
  41. #else
  42. #define _getch getchar
  43. #define _putch putchar
  44. #endif
  45. #define DEFAULT_DALICONNECT_TIMEOUT 5 // seconds
  46. static unsigned daliConnectTimeoutMs = 5000;
  47. static bool noninteractive=false;
  48. void usage(const char *exe)
  49. {
  50. printf("Usage:\n");
  51. printf(" %s [<daliserver-ip>] <command> { <option> }\n", exe);
  52. printf("\n");
  53. printf("Data store commands:\n");
  54. printf(" export <branchxpath> <destfile>\n");
  55. printf(" import <branchxpath> <srcfile>\n");
  56. printf(" importadd <branchxpath> <srcfile>\n");
  57. printf(" delete <branchxpath>\n");
  58. printf(" set <xpath> <value> -- set single value\n");
  59. printf(" get <xpath> -- get single value\n");
  60. printf(" bget <xpath> <dest-file> -- binary property\n");
  61. printf(" xget <xpath> -- (multi-value tail can have commas)\n");
  62. printf(" wget <xpath> -- (gets all matching xpath)\n");
  63. printf(" add <xpath> <value> -- adds new value\n");
  64. printf(" delv <xpath> -- deletes value\n");
  65. printf(" count <xpath> -- counts xpath matches\n");
  66. printf("\n");
  67. printf("Logical File meta information commands:\n");
  68. printf(" dfsfile <logicalname> -- get meta information for file\n");
  69. printf(" dfspart <logicalname> <part> -- get meta information for part num\n");
  70. printf(" dfscsv <logicalnamemask> -- get csv info. for files matching mask\n");
  71. printf(" dfsgroup <logicalgroupname> [filename] -- get IPs for logical group (aka cluster). Written to optional filename if provided\n");
  72. printf(" dfsmap <logicalname> -- get part files (primary and replicates)\n");
  73. printf(" dfsexists <logicalname> -- sets return value to 0 if file exists\n");
  74. printf(" dfsparents <logicalname> -- list superfiles containing file\n");
  75. printf(" dfsunlink <logicalname> -- unlinks file from all super parents\n");
  76. printf(" dfsverify <logicalname> -- verifies parts exist, returns 0 if ok\n");
  77. printf(" setprotect <logicalname> <id> -- overwrite protects logical file\n");
  78. printf(" unprotect <logicalname> <id> -- unprotect (if id=* then clear all)\n");
  79. printf(" listprotect <logicalnamemask> <id-mask> -- list protected files\n");
  80. printf(" checksuperfile <superfilename> [fix=true|false] -- check superfile links consistent and optionally fix\n");
  81. printf(" checksubfile <subfilename> -- check subfile links to parent consistent\n");
  82. printf(" listexpires <logicalnamemask> -- lists logical files with expiry value\n");
  83. printf(" listrelationships <primary> <secondary>\n");
  84. printf(" dfsperm <logicalname> -- returns LDAP permission for file\n");
  85. printf(" dfscompratio <logicalname> -- returns compression ratio of file\n");
  86. printf(" dfsscopes <mask> -- lists logical scopes (mask = * for all)\n");
  87. printf(" cleanscopes -- remove empty scopes\n");
  88. printf("\n");
  89. printf("Workunit commands:\n");
  90. printf(" listworkunits [<prop>=<val> [<lower> [<upper>]]] -- list workunits that match prop=val in workunit name range lower to upper\n");
  91. printf(" listmatches <connection xpath> [<match xpath>=<val> [<property xpath>]]\n");
  92. printf(" workunittimings <WUID>\n");
  93. printf("\n");
  94. printf("Other dali server and misc commands:\n");
  95. printf(" serverlist <mask> -- list server IPs (mask optional)\n");
  96. printf(" clusterlist <mask> -- list clusters (mask optional)\n");
  97. printf(" auditlog <fromdate> <todate> <match>\n");
  98. printf(" coalesce -- force transaction coalesce\n");
  99. printf(" mpping <server-ip> -- time MP connect\n");
  100. printf(" daliping [ <num> ] -- time dali server connect\n");
  101. printf(" getxref <destxmlfile> -- get all XREF information\n");
  102. printf(" dalilocks [ <ip-pattern> ] [ files ] -- get all locked files/xpaths\n");
  103. printf(" unlock <xpath or logicalfile> -- unlocks either matching xpath(s) or matching logical file(s), can contain wildcards\n");
  104. printf(" validatestore [fix=<true|false>]\n"
  105. " [verbose=<true|false>]\n"
  106. " [deletefiles=<true|false>]-- perform some checks on dali meta data an optionally fix or remove redundant info \n");
  107. printf(" wuidcompress <wildcard> <type> -- scan workunits that match <wildcard> and compress resources of <type>\n");
  108. printf(" wuiddecompress <wildcard> <type> -- scan workunits that match <wildcard> and decompress resources of <type>\n");
  109. printf(" xmlsize <filename> [<percentage>] -- analyse size usage in xml file, display individual items above 'percentage' \n");
  110. printf("\n");
  111. printf("Common options\n");
  112. printf(" server=<dali-server-ip> -- server ip\n");
  113. printf(" -- can be 1st param if numeric ip (or '.')\n");
  114. printf(" user=<username> -- for file operations\n");
  115. printf(" password=<password> -- for file operations\n");
  116. printf(" logfile=<filename> -- filename blank for no log\n");
  117. printf(" rawlog=0|1 -- if raw omits timestamps etc\n");
  118. printf(" timeout=<seconds> -- set dali connect timeout\n");
  119. }
  120. #define SDS_LOCK_TIMEOUT 60000
  121. static void outln(const char *ln)
  122. {
  123. PROGLOG("%s",ln);
  124. }
  125. #define OUTLOG PROGLOG
  126. static const char *remLeading(const char *s)
  127. {
  128. if (*s=='/')
  129. s++;
  130. return s;
  131. }
  132. static bool isWild(const char *path)
  133. {
  134. if (strchr(path,'?')||strchr(path,'*'))
  135. return true;
  136. return false;
  137. }
  138. static const char *splitpath(const char *path,StringBuffer &head,StringBuffer &tmp)
  139. {
  140. if (path[0]!='/')
  141. path = tmp.append('/').append(path).str();
  142. return splitXPath(path, head);
  143. }
  144. // NB: there's strtoll under Linux
  145. static unsigned __int64 hextoll(const char *str, bool &error)
  146. {
  147. unsigned len = strlen(str);
  148. if (!len)
  149. {
  150. error = true;
  151. return 0;
  152. }
  153. unsigned __int64 factor = 1;
  154. unsigned __int64 rolling = 0;
  155. char *ptr = (char *)str+len-1;
  156. loop {
  157. char c = *ptr;
  158. unsigned v;
  159. if (isdigit(c))
  160. v = c-'0';
  161. else if (c>='A' && c<='F')
  162. v = 10+(c-'A');
  163. else if (c>='a' && c<='f')
  164. v = 10+(c-'a');
  165. else {
  166. error = true;
  167. return 0;
  168. }
  169. rolling += v * factor;
  170. factor <<= 4;
  171. if (ptr == str)
  172. break;
  173. --ptr;
  174. }
  175. error = false;
  176. return rolling;
  177. }
  178. static IRemoteConnection *connectXPathOrFile(const char *path,bool safe,StringBuffer &xpath)
  179. {
  180. CDfsLogicalFileName lfn;
  181. StringBuffer lfnpath;
  182. if ((strstr(path,"::")!=NULL)&&!strchr(path,'/')) {
  183. lfn.set(path);
  184. lfn.makeFullnameQuery(lfnpath,DXB_File);
  185. path = lfnpath.str();
  186. }
  187. else if (strchr(path+((*path=='/')?1:0),'/')==NULL)
  188. safe = true; // all root trees safe
  189. Owned<IRemoteConnection> conn = querySDS().connect(remLeading(path),myProcessSession(),safe?0:RTM_LOCK_READ, daliConnectTimeoutMs);
  190. if (!conn&&lfnpath.length()) {
  191. lfn.makeFullnameQuery(lfnpath.clear(),DXB_SuperFile);
  192. path = lfnpath.str();
  193. conn.setown(querySDS().connect(remLeading(path),myProcessSession(),safe?0:RTM_LOCK_READ, daliConnectTimeoutMs));
  194. }
  195. if (conn.get())
  196. xpath.append(path);
  197. return conn.getClear();
  198. }
  199. //=============================================================================
  200. static void _export_(const char *path,const char *dst,bool safe=false)
  201. {
  202. StringBuffer xpath;
  203. Owned<IRemoteConnection> conn = connectXPathOrFile(path,safe,xpath);
  204. if (!conn) {
  205. ERRLOG("Could not connect to %s",path);
  206. return;
  207. }
  208. Owned<IPropertyTree> root = conn->getRoot();
  209. Owned<IFile> f = createIFile(dst);
  210. Owned<IFileIO> io = f->open(IFOcreate);
  211. Owned<IFileIOStream> fstream = createBufferedIOStream(io);
  212. toXML(root, *fstream); // formatted (default)
  213. OUTLOG("Branch %s saved in '%s'",xpath.str(),dst);
  214. conn->close();
  215. }
  216. //==========================================================================================================
  217. static void import(const char *path,const char *src,bool add)
  218. {
  219. Owned<IFile> iFile = createIFile(src);
  220. Owned<IFileIO> iFileIO = iFile->open(IFOread);
  221. if (!iFileIO)
  222. {
  223. ERRLOG("Could not open to %s",src);
  224. return;
  225. }
  226. size32_t sz = (size32_t)iFile->size();
  227. StringBuffer xml;
  228. iFileIO->read(0, sz, xml.reserve(sz));
  229. Owned<IPropertyTree> branch = createPTreeFromXMLString(xml.str());
  230. StringBuffer head;
  231. StringBuffer tmp;
  232. const char *tail=splitpath(path,head,tmp);
  233. if (!tail)
  234. return;
  235. if (!add) {
  236. Owned<IRemoteConnection> bconn = querySDS().connect(remLeading(path),myProcessSession(),RTM_LOCK_READ|RTM_SUB, daliConnectTimeoutMs);
  237. if (bconn) {
  238. Owned<IPropertyTree> broot = bconn->getRoot();
  239. StringBuffer bakname;
  240. Owned<IFileIO> io = createUniqueFile(NULL, tail, "bak", bakname);
  241. OUTLOG("Saving backup of %s to %s",path,bakname.str());
  242. Owned<IFileIOStream> fstream = createBufferedIOStream(io);
  243. toXML(broot, *fstream); // formatted (default)
  244. }
  245. }
  246. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),0, daliConnectTimeoutMs);
  247. if (!conn) {
  248. ERRLOG("Could not connect to %s",path);
  249. return;
  250. }
  251. StringAttr newtail; // must be declared outside the following if
  252. Owned<IPropertyTree> root = conn->getRoot();
  253. if (!add) {
  254. Owned<IPropertyTree> child = root->getPropTree(tail);
  255. root->removeTree(child);
  256. //If replacing a qualified branch then remove the qualifiers before calling addProp
  257. const char * qualifier = strchr(tail, '[');
  258. if (qualifier)
  259. {
  260. newtail.set(tail, qualifier-tail);
  261. tail = newtail;
  262. }
  263. }
  264. Owned<IPropertyTree> oldEnvironment;
  265. if (streq(path,"Environment"))
  266. oldEnvironment.setown(createPTreeFromIPT(conn->queryRoot()));
  267. root->addPropTree(tail,LINK(branch));
  268. conn->commit();
  269. OUTLOG("Branch %s loaded from '%s'",path,src);
  270. conn->close();
  271. if (*path=='/')
  272. path++;
  273. if (strcmp(path,"Environment")==0) {
  274. OUTLOG("Refreshing cluster groups from Environment");
  275. StringBuffer response;
  276. initClusterGroups(false, response, oldEnvironment);
  277. if (response.length())
  278. PROGLOG("updating Environment via import path=%s : %s", path, response.str());
  279. }
  280. }
  281. //=============================================================================
  282. static void _delete_(const char *path,bool backup)
  283. {
  284. StringBuffer head;
  285. StringBuffer tmp;
  286. const char *tail=splitpath(path,head,tmp);
  287. if (!tail)
  288. return;
  289. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_WRITE, daliConnectTimeoutMs);
  290. if (!conn) {
  291. ERRLOG("Could not connect to %s",path);
  292. return;
  293. }
  294. Owned<IPropertyTree> root = conn->getRoot();
  295. Owned<IPropertyTree> child = root->getPropTree(tail);
  296. if (!child) {
  297. ERRLOG("Couldn't find %s/%s",head.str(),tail);
  298. return;
  299. }
  300. if (backup) {
  301. StringBuffer bakname;
  302. Owned<IFileIO> io = createUniqueFile(NULL,"daliadmin", "bak", bakname);
  303. OUTLOG("Saving backup of %s/%s to %s",head.str(),tail,bakname.str());
  304. Owned<IFileIOStream> fstream = createBufferedIOStream(io);
  305. toXML(child, *fstream); // formatted (default)
  306. }
  307. root->removeTree(child);
  308. child.clear();
  309. root.clear();
  310. conn->commit();
  311. conn->close();
  312. }
  313. //=============================================================================
  314. static void set(const char *path,const char *val)
  315. {
  316. StringBuffer head;
  317. StringBuffer tmp;
  318. const char *tail=splitpath(path,head,tmp);
  319. if (!tail)
  320. return;
  321. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_WRITE, daliConnectTimeoutMs);
  322. if (!conn) {
  323. ERRLOG("Could not connect to %s",path);
  324. return;
  325. }
  326. Owned<IPropertyTree> root = conn->getRoot();
  327. StringBuffer oldv;
  328. StringBuffer newv;
  329. root->getProp(tail,oldv);
  330. root->setProp(tail,val);
  331. conn->commit();
  332. root->getProp(tail,newv);
  333. OUTLOG("Changed %s from '%s' to '%s'",path,oldv.str(),newv.str());
  334. conn->close();
  335. }
  336. //=============================================================================
  337. static void get(const char *path)
  338. {
  339. StringBuffer head;
  340. StringBuffer tmp;
  341. const char *tail=splitpath(path,head,tmp);
  342. if (!tail)
  343. return;
  344. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  345. if (!conn) {
  346. ERRLOG("Could not connect to %s",path);
  347. return;
  348. }
  349. Owned<IPropertyTree> root = conn->getRoot();
  350. StringBuffer val;
  351. root->getProp(tail,val);
  352. OUTLOG("Value of %s is: '%s'",path,val.str());
  353. conn->close();
  354. }
  355. //=============================================================================
  356. static void bget(const char *path,const char *outfn)
  357. {
  358. StringBuffer head;
  359. StringBuffer tmp;
  360. const char *tail=splitpath(path,head,tmp);
  361. if (!tail)
  362. return;
  363. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  364. if (!conn) {
  365. ERRLOG("Could not connect to %s",path);
  366. return;
  367. }
  368. Owned<IPropertyTree> root = conn->getRoot();
  369. MemoryBuffer val;
  370. root->getPropBin(tail,val);
  371. Owned<IFile> f = createIFile(outfn);
  372. Owned<IFileIO> io = f->open(IFOcreate);
  373. io->write(0,val.length(),val.toByteArray());
  374. conn->close();
  375. }
  376. //=============================================================================
  377. static void xget(const char *path)
  378. {
  379. if (!path||!*path)
  380. return;
  381. Owned<IRemoteConnection> conn = querySDS().connect("/",myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  382. if (!conn) {
  383. ERRLOG("Could not connect to /");
  384. return;
  385. }
  386. Owned<IPropertyTree> root = conn->getRoot();
  387. StringBuffer head;
  388. StringBuffer tmp;
  389. const char *props=splitpath(path,head,tmp);
  390. const char *s = head.str();
  391. if (*s=='/')
  392. s++;
  393. Owned<IPropertyTreeIterator> it = root->getElements(s);
  394. if (it->first()) {
  395. unsigned idx = 0;
  396. do {
  397. idx++;
  398. StringBuffer res;
  399. res.append(idx).append(',');
  400. s = props;
  401. loop {
  402. const char *e = strchr(s,',');
  403. if (e&&e[1]) {
  404. StringBuffer prop(e-s,s);
  405. it->query().getProp(prop.str(),res);
  406. s = e+1;
  407. res.append(',');
  408. }
  409. else {
  410. it->query().getProp(s,res);
  411. break;
  412. }
  413. }
  414. outln(res.str());
  415. } while (it->next());
  416. }
  417. conn->close();
  418. }
  419. //=============================================================================
  420. static void wget(const char *path)
  421. {
  422. StringBuffer head;
  423. StringBuffer tmp;
  424. const char *tail=splitpath(path,head,tmp);
  425. if (!tail)
  426. return;
  427. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  428. if (!conn) {
  429. ERRLOG("Could not connect to %s",path);
  430. return;
  431. }
  432. Owned<IPropertyTreeIterator> iter = conn->queryRoot()->getElements(tail);
  433. unsigned n = 0;
  434. ForEach(*iter) {
  435. n++;
  436. const char *s = iter->query().queryName();
  437. OUTLOG("%d,%s",n,s);
  438. }
  439. conn->close();
  440. }
  441. //=============================================================================
  442. static void add(const char *path,const char *val)
  443. {
  444. StringBuffer head;
  445. StringBuffer tmp;
  446. const char *tail=splitpath(path,head,tmp);
  447. if (!tail)
  448. return;
  449. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_WRITE, daliConnectTimeoutMs);
  450. if (!conn) {
  451. ERRLOG("Could not connect to %s",path);
  452. return;
  453. }
  454. Owned<IPropertyTree> root = conn->getRoot();
  455. StringBuffer oldv;
  456. StringBuffer newv;
  457. root->addProp(tail,val);
  458. conn->commit();
  459. OUTLOG("Added %s value '%s'",path,val);
  460. conn->close();
  461. }
  462. //=============================================================================
  463. static void delv(const char *path)
  464. {
  465. StringBuffer head;
  466. StringBuffer tmp;
  467. const char *tail=splitpath(path,head,tmp);
  468. if (!tail)
  469. return;
  470. Owned<IRemoteConnection> conn = querySDS().connect(head.str(),myProcessSession(),RTM_LOCK_WRITE, daliConnectTimeoutMs);
  471. if (!conn) {
  472. ERRLOG("Could not connect to %s",path);
  473. return;
  474. }
  475. Owned<IPropertyTree> root = conn->getRoot();
  476. StringBuffer val;
  477. root->getProp(tail,val);
  478. root->removeProp(tail);
  479. OUTLOG("Value of %s was: '%s'",path,val.str());
  480. conn->close();
  481. }
  482. //=============================================================================
  483. static void count(const char *path)
  484. {
  485. unsigned result = querySDS().queryCount(path);
  486. OUTLOG("Count of %s is: %d", path, result);
  487. }
  488. //=============================================================================
  489. static void dfsfile(const char *lname,IUserDescriptor *userDesc, UnsignedArray *partslist=NULL)
  490. {
  491. StringBuffer str;
  492. CDfsLogicalFileName lfn;
  493. lfn.set(lname);
  494. if (!lfn.isExternal()) {
  495. Owned<IPropertyTree> tree = queryDistributedFileDirectory().getFileTree(lname,userDesc,NULL,daliConnectTimeoutMs,true); //,userDesc);
  496. if (partslist)
  497. filterParts(tree,*partslist);
  498. if (!tree) {
  499. ERRLOG("%s not found",lname);
  500. return;
  501. }
  502. toXML(tree, str);
  503. outln(str.str());
  504. }
  505. else {
  506. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(lname,userDesc);
  507. if (file) {
  508. Owned<IFileDescriptor> fdesc = file->getFileDescriptor();
  509. Owned<IPropertyTree> t = createPTree("File");
  510. fdesc->serializeTree(*t);
  511. filterParts(t,*partslist);
  512. toXML(t, str.clear());
  513. outln(str.str());
  514. }
  515. }
  516. }
  517. //=============================================================================
  518. static void dfspart(const char *lname,IUserDescriptor *userDesc, unsigned partnum)
  519. {
  520. UnsignedArray partslist;
  521. partslist.append(partnum);
  522. dfsfile(lname,userDesc,&partslist);
  523. }
  524. //=============================================================================
  525. void dfscsv(const char *dali,IUserDescriptor *udesc)
  526. {
  527. const char *fields[] = {
  528. "name","group","directory","partmask","modified","job","owner","workunit","numparts","size","recordCount","recordSize","compressedSize",NULL
  529. };
  530. Owned<INode> foreigndali;
  531. if (dali&&*dali&&(*dali!='*')) {
  532. SocketEndpoint ep(dali,DALI_SERVER_PORT);
  533. foreigndali.setown(createINode(ep));
  534. }
  535. unsigned start = msTick();
  536. IDFAttributesIterator *iter = queryDistributedFileDirectory().getDFAttributesIterator("*",udesc,true,false,foreigndali);
  537. StringBuffer ln;
  538. unsigned i;
  539. for (i=0;fields[i];i++) {
  540. if (i>0)
  541. ln.append(',');
  542. ln.append('"').append(fields[i]).append('"');
  543. }
  544. outln(ln.str());
  545. if (iter) {
  546. StringBuffer aname;
  547. StringBuffer vals;
  548. ForEach(*iter) {
  549. IPropertyTree &attr=iter->query();
  550. ln.clear();
  551. for (i=0;fields[i];i++) {
  552. aname.clear().append('@').append(fields[i]);
  553. const char *val = attr.queryProp(aname.str());
  554. if (i>0)
  555. ln.append(',');
  556. if (val)
  557. while (*val) {
  558. if (*val!=',')
  559. ln.append(*val);
  560. val++;
  561. }
  562. }
  563. outln(ln.str());
  564. }
  565. }
  566. }
  567. //=============================================================================
  568. static void dfsgroup(const char *name, const char *outputFilename)
  569. {
  570. Owned<IFileIOStream> io;
  571. if (outputFilename)
  572. {
  573. OwnedIFile iFile = createIFile(outputFilename);
  574. OwnedIFileIO iFileIO = iFile->open(IFOcreate);
  575. io.setown(createIOStream(iFileIO));
  576. }
  577. Owned<IGroup> group = queryNamedGroupStore().lookup(name);
  578. if (!group)
  579. {
  580. ERRLOG("cannot find group %s",name);
  581. return;
  582. }
  583. StringBuffer eps;
  584. for (unsigned i=0;i<group->ordinality();i++)
  585. {
  586. group->queryNode(i).endpoint().getUrlStr(eps.clear());
  587. if (io)
  588. {
  589. eps.newline();
  590. io->write(eps.length(), eps.str());
  591. }
  592. else
  593. OUTLOG("%s",eps.str());
  594. }
  595. }
  596. //=============================================================================
  597. static void dfsmap(const char *lname, IUserDescriptor *user)
  598. {
  599. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(lname,user);
  600. if (!file) {
  601. ERRLOG("File %s not found",lname);
  602. return;
  603. }
  604. Owned<IDistributedFilePartIterator> pi = file->getIterator();
  605. unsigned pn=1;
  606. StringBuffer ln;
  607. ForEach(*pi) {
  608. ln.clear().appendf("%d: ",pn);
  609. Owned<IDistributedFilePart> part = &pi->get();
  610. for (unsigned int i=0; i<part->numCopies(); i++) {
  611. RemoteFilename rfn;
  612. part->getFilename(rfn,i);
  613. if (i)
  614. ln.append(", ");
  615. rfn.getRemotePath(ln);
  616. }
  617. outln(ln.str());
  618. pn++;
  619. }
  620. }
  621. //=============================================================================
  622. static int dfsexists(const char *lname,IUserDescriptor *user)
  623. {
  624. return queryDistributedFileDirectory().exists(lname,user)?0:1;
  625. }
  626. //=============================================================================
  627. static void dfsparents(const char *lname, IUserDescriptor *user)
  628. {
  629. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(lname,user);
  630. if (file) {
  631. Owned<IDistributedSuperFileIterator> iter = file->getOwningSuperFiles();
  632. ForEach(*iter)
  633. OUTLOG("%s,%s",iter->query().queryLogicalName(),lname);
  634. }
  635. }
  636. //=============================================================================
  637. static void dfsunlink(const char *lname, IUserDescriptor *user)
  638. {
  639. loop {
  640. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(lname,user);
  641. if (file) {
  642. Owned<IDistributedSuperFileIterator> iter = file->getOwningSuperFiles();
  643. if (!iter->first())
  644. break;
  645. file.clear();
  646. Owned<IDistributedSuperFile> sf = &iter->get();
  647. iter.clear();
  648. if (sf->removeSubFile(lname,false))
  649. OUTLOG("removed %s from %s",lname,sf->queryLogicalName());
  650. else
  651. ERRLOG("FAILED to remove %s from %s",lname,sf->queryLogicalName());
  652. }
  653. }
  654. }
  655. //=============================================================================
  656. class CIpItem: public CInterface
  657. {
  658. public:
  659. IMPLEMENT_IINTERFACE;
  660. IpAddress ip;
  661. bool ok;
  662. };
  663. class CIpTable: public SuperHashTableOf<CIpItem,IpAddress>
  664. {
  665. public:
  666. ~CIpTable()
  667. {
  668. releaseAll();
  669. }
  670. void onAdd(void *)
  671. {
  672. // not used
  673. }
  674. void onRemove(void *e)
  675. {
  676. CIpItem &elem=*(CIpItem *)e;
  677. elem.Release();
  678. }
  679. unsigned getHashFromElement(const void *e) const
  680. {
  681. const CIpItem &elem=*(const CIpItem *)e;
  682. return elem.ip.iphash();
  683. }
  684. unsigned getHashFromFindParam(const void *fp) const
  685. {
  686. return ((const IpAddress *)fp)->iphash();
  687. }
  688. const void * getFindParam(const void *p) const
  689. {
  690. const CIpItem &elem=*(const CIpItem *)p;
  691. return &elem.ip;
  692. }
  693. bool matchesFindParam(const void * et, const void *fp, unsigned fphash) const
  694. {
  695. return ((CIpItem *)et)->ip.ipequals(*(IpAddress *)fp);
  696. }
  697. IMPLEMENT_SUPERHASHTABLEOF_REF_FIND(CIpItem,IpAddress);
  698. bool verifyDaliFileServer(IpAddress &ip)
  699. {
  700. CIpItem *item=find(ip);
  701. if (!item) {
  702. item = new CIpItem;
  703. item->ip.ipset(ip);
  704. item->ok = testDaliServixPresent(ip);
  705. add(*item);
  706. }
  707. return item->ok;
  708. }
  709. };
  710. class CFileCrcItem: public CInterface
  711. {
  712. public:
  713. RemoteFilename filename;
  714. unsigned requiredcrc;
  715. unsigned crc;
  716. unsigned partno;
  717. unsigned copy;
  718. IMPLEMENT_IINTERFACE;
  719. bool ok;
  720. byte flags;
  721. CDateTime dt;
  722. };
  723. #define FLAG_ROW_COMPRESSED 1
  724. #define FLAG_NO_CRC 2
  725. class CFileList: public CIArrayOf<CFileCrcItem>
  726. {
  727. public:
  728. void add(RemoteFilename &filename,unsigned partno,unsigned copy,unsigned crc,byte flags)
  729. {
  730. CFileCrcItem *item = new CFileCrcItem();
  731. item->filename.set(filename);
  732. item->partno = partno;
  733. item->copy = copy;
  734. item->crc = crc;
  735. item->requiredcrc = crc;
  736. item->flags = flags;
  737. append(*item);
  738. }
  739. };
  740. static int dfsverify(const char *name,CDateTime *cutoff, IUserDescriptor *user)
  741. {
  742. static CIpTable dafilesrvips;
  743. Owned<IDistributedFile> file=queryDistributedFileDirectory().lookup(name,user);
  744. if (!file) {
  745. ERRLOG("VERIFY: cannot find %s",name);
  746. return 1;
  747. }
  748. CDateTime filetime;
  749. if (file->getModificationTime(filetime)) {
  750. if (cutoff&&(filetime.compare(*cutoff)<=0))
  751. return 0;
  752. }
  753. IPropertyTree &fileprops = file->queryAttributes();
  754. bool blocked;
  755. bool rowcompressed = file->isCompressed(&blocked)&&!blocked;
  756. CFileList list;
  757. unsigned width = file->numParts();
  758. unsigned short port = getDaliServixPort();
  759. try {
  760. for (unsigned i=0;i<width;i++) {
  761. Owned<IDistributedFilePart> part = file->getPart(i);
  762. for (unsigned copy = 0; copy < part->numCopies(); copy++) {
  763. unsigned reqcrc;
  764. bool noreq = !part->getCrc(reqcrc);
  765. // if (reqcrc==(unsigned)-1)
  766. // continue;
  767. SocketEndpoint ep(part->queryNode()->endpoint());
  768. if (!dafilesrvips.verifyDaliFileServer(ep)) {
  769. StringBuffer ips;
  770. ep.getIpText(ips);
  771. ERRLOG("VERIFY: file %s, cannot run DAFILESRV on %s",name,ips.str());
  772. return 4;
  773. }
  774. RemoteFilename rfn;
  775. part->getFilename(rfn,copy);
  776. rfn.setPort(port);
  777. list.add(rfn,i,copy,reqcrc,rowcompressed?FLAG_ROW_COMPRESSED:(noreq?FLAG_NO_CRC:0));
  778. }
  779. }
  780. }
  781. catch (IException *e)
  782. {
  783. StringBuffer s;
  784. s.appendf("VERIFY: file %s",name);
  785. EXCLOG(e, s.str());
  786. e->Release();
  787. return 2;
  788. }
  789. if (list.ordinality()==0)
  790. return 0;
  791. OUTLOG("VERIFY: start file %s",name);
  792. file.clear();
  793. CriticalSection crit;
  794. class casyncfor: public CAsyncFor
  795. {
  796. CFileList &list;
  797. CriticalSection &crit;
  798. public:
  799. bool ok;
  800. casyncfor(CFileList &_list, CriticalSection &_crit)
  801. : list(_list), crit(_crit)
  802. {
  803. ok = true;
  804. }
  805. void Do(unsigned i)
  806. {
  807. CriticalBlock block(crit);
  808. CFileCrcItem &item = list.item(i);
  809. RemoteFilename &rfn = item.filename;
  810. Owned<IFile> partfile;
  811. StringBuffer eps;
  812. try
  813. {
  814. partfile.setown(createIFile(rfn));
  815. // OUTLOG("VERIFY: part %s on %s",partfile->queryFilename(),rfn.queryEndpoint().getUrlStr(eps).str());
  816. if (partfile) {
  817. CriticalUnblock unblock(crit);
  818. item.crc = partfile->getCRC();
  819. partfile->getTime(NULL,&item.dt,NULL);
  820. if ((item.crc==0)&&!partfile->exists()) {
  821. ERRLOG("VERIFY: does not exist part %s on %s",partfile->queryFilename(),rfn.queryEndpoint().getUrlStr(eps).str());
  822. ok = false;
  823. }
  824. }
  825. else
  826. ok = false;
  827. }
  828. catch (IException *e)
  829. {
  830. StringBuffer s;
  831. s.appendf("VERIFY: part %s on %s",partfile->queryFilename(),rfn.queryEndpoint().getUrlStr(eps).str());
  832. EXCLOG(e, s.str());
  833. e->Release();
  834. ok = false;
  835. }
  836. }
  837. } afor(list,crit);
  838. afor.For(list.ordinality(),400,false,true);
  839. StringBuffer outs;
  840. ForEachItemIn(j,list) {
  841. CFileCrcItem &item = list.item(j);
  842. item.filename.setPort(0);
  843. if (item.crc!=item.requiredcrc) {
  844. StringBuffer rfs;
  845. ERRLOG("VERIFY: FAILED %s (%x,%x) file %s",name,item.crc,item.requiredcrc,item.filename.getRemotePath(rfs).str());
  846. afor.ok = false;
  847. }
  848. }
  849. if (afor.ok) {
  850. OUTLOG("VERIFY: OK file %s",name);
  851. return 0;
  852. }
  853. return 3;
  854. }
  855. //=============================================================================
  856. static void setprotect(const char *filename, const char *callerid, IUserDescriptor *user)
  857. {
  858. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(filename,user);
  859. file->setProtect(callerid,true);
  860. }
  861. //=============================================================================
  862. static void unprotect(const char *filename, const char *callerid, IUserDescriptor *user)
  863. {
  864. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(filename,user);
  865. file->setProtect((strcmp(callerid,"*")==0)?NULL:callerid,false);
  866. }
  867. //=============================================================================
  868. static void listprotect(const char *filename, const char *callerid)
  869. {
  870. Owned<IDFProtectedIterator> piter = queryDistributedFileDirectory().lookupProtectedFiles((strcmp(callerid,"*")==0)?NULL:callerid);
  871. ForEach(*piter) {
  872. if (WildMatch(piter->queryFilename(),filename))
  873. OUTLOG("%s,%s,%s,%u",piter->isSuper()?"SuperFile":"File",piter->queryFilename(),piter->queryOwner(),piter->getCount());
  874. }
  875. }
  876. //=============================================================================
  877. static bool allyes = false;
  878. static bool getResponse()
  879. {
  880. if (allyes)
  881. return true;
  882. int ch;
  883. do
  884. {
  885. ch = toupper(ch = _getch());
  886. } while (ch != 'Y' && ch != 'N' && ch != '*');
  887. _putch(ch);
  888. _putch('\n');
  889. if (ch=='*') {
  890. allyes = true;
  891. return true;
  892. }
  893. return ch=='Y' ? true : false;
  894. }
  895. static bool doFix()
  896. {
  897. if (allyes)
  898. return true;
  899. printf("Fix? (Y/N/*):");
  900. return getResponse();
  901. }
  902. static void checksuperfile(const char *lfn,bool fix=false)
  903. {
  904. if (strcmp(lfn,"*")==0) {
  905. class csuperfilescan: public CSDSFileScanner
  906. {
  907. virtual bool checkScopeOk(const char *scopename)
  908. {
  909. OUTLOG("Processing scope %s",scopename);
  910. return true;
  911. }
  912. void processSuperFile(IPropertyTree &superfile,StringBuffer &name)
  913. {
  914. try {
  915. checksuperfile(name.str(),fix);
  916. }
  917. catch (IException *e) {
  918. EXCLOG(e,"processSuperFiles");
  919. e->Release();
  920. }
  921. }
  922. public:
  923. bool fix;
  924. } superfilescan;
  925. superfilescan.fix = fix;
  926. Owned<IRemoteConnection> conn = querySDS().connect("/Files", myProcessSession(), 0, 100000);
  927. superfilescan.scan(conn,false,true);
  928. return;
  929. }
  930. bool fixed = false;
  931. CDfsLogicalFileName lname;
  932. lname.set(lfn);
  933. StringBuffer query;
  934. lname.makeFullnameQuery(query, DXB_SuperFile, true);
  935. Owned<IRemoteConnection> conn = querySDS().connect(query.str(),myProcessSession(),fix?RTM_LOCK_WRITE:0, daliConnectTimeoutMs);
  936. if (!conn) {
  937. ERRLOG("Could not connect to %s",lfn);
  938. ERRLOG("Superfile %s FAILED",lname.get());
  939. return;
  940. }
  941. Owned<IPropertyTree> root = conn->getRoot();
  942. unsigned n=root->getPropInt("@numsubfiles");
  943. StringBuffer path;
  944. StringBuffer subname;
  945. unsigned subnum = 0;
  946. unsigned i;
  947. for (i=0;i<n;i++) {
  948. loop {
  949. IPropertyTree *sub2 = root->queryPropTree(path.clear().appendf("SubFile[@num=\"%d\"][2]",i+1).str());
  950. if (!sub2)
  951. break;
  952. StringBuffer s;
  953. s.appendf("SuperFile %s: corrupt, subfile file part %d is duplicated",lname.get(),i+1);
  954. ERRLOG("%s",s.str());
  955. if (!fix||!doFix()) {
  956. ERRLOG("Superfile %s FAILED",lname.get());
  957. return;
  958. }
  959. root->removeProp(path.str());
  960. }
  961. IPropertyTree *sub = root->queryPropTree(path.clear().appendf("SubFile[@num=\"%d\"]",i+1).str());
  962. if (!sub) {
  963. StringBuffer s;
  964. s.appendf("SuperFile %s: corrupt, subfile file part %d cannot be found",lname.get(),i+1);
  965. ERRLOG("%s",s.str());
  966. if (!fix||!doFix()) {
  967. ERRLOG("Superfile %s FAILED",lname.get());
  968. return;
  969. }
  970. fixed = true;
  971. break;
  972. }
  973. sub->getProp("@name",subname.clear());
  974. CDfsLogicalFileName sublname;
  975. sublname.set(subname.str());
  976. if (!sublname.isExternal()&&!sublname.isForeign()) {
  977. StringBuffer subquery;
  978. sublname.makeFullnameQuery(subquery, DXB_File, true);
  979. Owned<IRemoteConnection> subconn = querySDS().connect(subquery.str(),myProcessSession(),fix?RTM_LOCK_WRITE:0, daliConnectTimeoutMs);
  980. if (!subconn) {
  981. sublname.makeFullnameQuery(subquery.clear(), DXB_SuperFile, true);
  982. subconn.setown(querySDS().connect(subquery.str(),myProcessSession(),0, daliConnectTimeoutMs));
  983. }
  984. if (!subconn) {
  985. ERRLOG("SuperFile %s is missing sub-file file %s",lname.get(),subname.str());
  986. if (!fix||!doFix()) {
  987. ERRLOG("Superfile %s FAILED",lname.get());
  988. return;
  989. }
  990. root->removeTree(sub);
  991. for (unsigned j=i+1;j<n; j++) {
  992. sub = root->queryPropTree(path.clear().appendf("SubFile[@num=\"%d\"]",j+1).str());
  993. if (sub)
  994. sub->setPropInt("@num",j);
  995. }
  996. i--;
  997. n--;
  998. fixed = true;
  999. continue;
  1000. }
  1001. subnum++;
  1002. Owned<IPropertyTree> subroot = subconn->getRoot();
  1003. Owned<IPropertyTreeIterator> iter = subroot->getElements("SuperOwner");
  1004. StringBuffer pname;
  1005. bool parentok=false;
  1006. ForEach(*iter) {
  1007. iter->query().getProp("@name",pname.clear());
  1008. if (strcmp(pname.str(),lname.get())==0)
  1009. parentok = true;
  1010. else {
  1011. CDfsLogicalFileName sdlname;
  1012. sdlname.set(pname.str());
  1013. StringBuffer sdquery;
  1014. sdlname.makeFullnameQuery(sdquery, DXB_SuperFile, true);
  1015. Owned<IRemoteConnection> sdconn = querySDS().connect(sdquery.str(),myProcessSession(),0, daliConnectTimeoutMs);
  1016. if (!conn) {
  1017. WARNLOG("SubFile %s has missing owner superfile %s",sublname.get(),sdlname.get());
  1018. }
  1019. // make sure superfile exists
  1020. }
  1021. }
  1022. if (!parentok) {
  1023. WARNLOG("SubFile %s is missing link to Superfile %s",sublname.get(),lname.get());
  1024. ForEach(*iter) {
  1025. iter->query().getProp("@name",pname.clear());
  1026. OUTLOG("Candidate %s",pname.str());
  1027. }
  1028. if (fix&&doFix()) {
  1029. Owned<IPropertyTree> t = createPTree("SuperOwner");
  1030. t->setProp("@name",lname.get());
  1031. subroot->addPropTree("SuperOwner",t.getClear());
  1032. }
  1033. }
  1034. }
  1035. else
  1036. subnum++;
  1037. }
  1038. if (fixed)
  1039. root->setPropInt("@numsubfiles",subnum);
  1040. i = 0;
  1041. byte fixstate = 0;
  1042. loop {
  1043. bool err = false;
  1044. IPropertyTree *sub = root->queryPropTree(path.clear().appendf("SubFile[%d]",i+1).str());
  1045. if (sub) {
  1046. unsigned pn = sub->getPropInt("@num");
  1047. if (pn>subnum) {
  1048. ERRLOG("SuperFile %s: corrupt, subfile file part %d spurious",lname.get(),pn);
  1049. if (fixstate==0)
  1050. if (fix&&doFix())
  1051. fixstate = 1;
  1052. else
  1053. fixstate = 2;
  1054. if (fixstate==1) {
  1055. root->removeTree(sub);
  1056. fixed = true;
  1057. i--;
  1058. }
  1059. }
  1060. }
  1061. else
  1062. break;
  1063. i++;
  1064. }
  1065. if (n==0) {
  1066. IPropertyTree *sub = root->queryPropTree("Attr");
  1067. if (!isEmptyPTree(sub)&&!sub->queryProp("description")) {
  1068. if (fix) {
  1069. if (!fixed)
  1070. ERRLOG("FIX Empty Superfile %s contains non-empty Attr",lname.get());
  1071. root->removeTree(sub);
  1072. }
  1073. else if (sub->getPropInt64("@recordCount")||sub->getPropInt64("@size"))
  1074. ERRLOG("FAIL Empty Superfile %s contains non-empty Attr sz=%"I64F"d rc=%"I64F"d",lname.get(),sub->getPropInt64("@recordCount"),sub->getPropInt64("@size"));
  1075. }
  1076. }
  1077. if (fixed)
  1078. OUTLOG("Superfile %s FIXED - from %d to %d subfiles",lname.get(),n,subnum);
  1079. else
  1080. OUTLOG("Superfile %s OK - contains %d subfiles",lname.get(),n);
  1081. }
  1082. //=============================================================================
  1083. static void checksubfile(const char *lfn)
  1084. {
  1085. if (strcmp(lfn,"*")==0) {
  1086. class csubfilescan: public CSDSFileScanner
  1087. {
  1088. virtual bool checkFileOk(IPropertyTree &file,const char *filename)
  1089. {
  1090. return (file.hasProp("SuperOwner[1]"));
  1091. }
  1092. virtual bool checkSuperFileOk(IPropertyTree &file,const char *filename)
  1093. {
  1094. return (file.hasProp("SuperOwner[1]"));
  1095. }
  1096. virtual bool checkScopeOk(const char *scopename)
  1097. {
  1098. OUTLOG("Processing scope %s",scopename);
  1099. return true;
  1100. }
  1101. void processFile(IPropertyTree &root,StringBuffer &name)
  1102. {
  1103. try {
  1104. checksubfile(name.str());
  1105. }
  1106. catch (IException *e) {
  1107. EXCLOG(e,"processSuperFiles");
  1108. e->Release();
  1109. }
  1110. }
  1111. void processSuperFile(IPropertyTree &root,StringBuffer &name)
  1112. {
  1113. try {
  1114. checksubfile(name.str());
  1115. }
  1116. catch (IException *e) {
  1117. EXCLOG(e,"processSuperFiles");
  1118. e->Release();
  1119. }
  1120. }
  1121. public:
  1122. } subfilescan;
  1123. Owned<IRemoteConnection> conn = querySDS().connect("/Files", myProcessSession(), 0, 100000);
  1124. subfilescan.scan(conn,true,true);
  1125. return;
  1126. }
  1127. CDfsLogicalFileName lname;
  1128. lname.set(lfn);
  1129. StringBuffer query;
  1130. lname.makeFullnameQuery(query, DXB_File, true);
  1131. Owned<IRemoteConnection> conn = querySDS().connect(query.str(),myProcessSession(),0, daliConnectTimeoutMs);
  1132. if (!conn) {
  1133. lname.makeFullnameQuery(query.clear(), DXB_SuperFile, true);
  1134. conn.setown(querySDS().connect(query.str(),myProcessSession(),0, daliConnectTimeoutMs));
  1135. }
  1136. if (!conn) {
  1137. ERRLOG("Could not connect to %s",lfn);
  1138. ERRLOG("Subfile %s FAILED",lname.get());
  1139. return;
  1140. }
  1141. Owned<IPropertyTree> root = conn->getRoot();
  1142. Owned<IPropertyTreeIterator> iter = root->getElements("SuperOwner");
  1143. StringBuffer pname;
  1144. bool ok=true;
  1145. ForEach(*iter) {
  1146. iter->query().getProp("@name",pname.clear());
  1147. CDfsLogicalFileName sdlname;
  1148. sdlname.set(pname.str());
  1149. StringBuffer sdquery;
  1150. sdlname.makeFullnameQuery(sdquery, DXB_SuperFile, true);
  1151. Owned<IRemoteConnection> sdconn = querySDS().connect(sdquery.str(),myProcessSession(),0, daliConnectTimeoutMs);
  1152. if (!conn) {
  1153. ERRLOG("SubFile %s has missing owner superfile %s",lname.get(),sdlname.get());
  1154. ok = false;
  1155. }
  1156. else {
  1157. StringBuffer path;
  1158. IPropertyTree *sub = sdconn->queryRoot()->queryPropTree(path.clear().appendf("SubFile[@name=\"%s\"]",lname.get()).str());
  1159. if (!sub) {
  1160. ERRLOG("Superfile %s is not linked to %s",sdlname.get(),lname.get());
  1161. ok = false;
  1162. }
  1163. }
  1164. }
  1165. if (ok)
  1166. OUTLOG("SubFile %s OK",lname.get());
  1167. }
  1168. //=============================================================================
  1169. static void listexpires(const char * lfnmask, IUserDescriptor *user)
  1170. {
  1171. IDFAttributesIterator *iter = queryDistributedFileDirectory().getDFAttributesIterator(lfnmask,user,true,false);
  1172. ForEach(*iter) {
  1173. IPropertyTree &attr=iter->query();
  1174. if (attr.hasProp("@expireDays"))
  1175. {
  1176. unsigned expireDays = attr.getPropInt("@expireDays");
  1177. const char *name = attr.queryProp("@name");
  1178. const char *lastAccessed = attr.queryProp("@accessed");
  1179. if (lastAccessed && name&&*name) // NB: all files that have expireDays should have lastAccessed also
  1180. {
  1181. StringBuffer days;
  1182. if (0 == expireDays)
  1183. days.append("the sasha default number of days");
  1184. else
  1185. {
  1186. days.append(expireDays);
  1187. if (expireDays>1)
  1188. days.append(" days");
  1189. else
  1190. days.append(" day");
  1191. }
  1192. OUTLOG("%s, last accessed = %s, set to expire %s after last accessed", name, lastAccessed, days.str());
  1193. }
  1194. }
  1195. }
  1196. }
  1197. //=============================================================================
  1198. static void listrelationships(const char *primary,const char *secondary)
  1199. {
  1200. Owned<IFileRelationshipIterator> iter = queryDistributedFileDirectory().lookupFileRelationships(primary,secondary,NULL,NULL,S_LINK_RELATIONSHIP_KIND,NULL,NULL,NULL);
  1201. ForEach(*iter) {
  1202. OUTLOG("%s,%s,%s,%s,%s,%s,%s,%s",
  1203. iter->query().queryKind(),
  1204. iter->query().queryPrimaryFilename(),
  1205. iter->query().querySecondaryFilename(),
  1206. iter->query().queryPrimaryFields(),
  1207. iter->query().querySecondaryFields(),
  1208. iter->query().queryCardinality(),
  1209. iter->query().isPayload()?"payload":"",
  1210. iter->query().queryDescription());
  1211. }
  1212. }
  1213. //=============================================================================
  1214. int dfsperm(const char *obj,IUserDescriptor *user)
  1215. {
  1216. int perm =0;
  1217. if (strchr(obj,'\\')||strchr(obj,'/')) {
  1218. Owned<IFileDescriptor> fd = createFileDescriptor();
  1219. RemoteFilename rfn;
  1220. rfn.setRemotePath(obj);
  1221. fd->setPart(0, rfn);
  1222. perm = queryDistributedFileDirectory().getFDescPermissions(fd,user,0);
  1223. }
  1224. else {
  1225. perm = queryDistributedFileDirectory().getFilePermissions(obj,user,0);
  1226. }
  1227. OUTLOG("perm %s = %d",obj,perm);
  1228. return perm;
  1229. }
  1230. //=============================================================================
  1231. static offset_t getCompressedSize(IDistributedFile *file)
  1232. { // this should be parallel! TBD
  1233. if (!file)
  1234. return (offset_t)-1;
  1235. offset_t ret = (offset_t)file->queryAttributes().getPropInt64("@compressedSize",-1);
  1236. if (ret==(offset_t)-1) {
  1237. try {
  1238. ret = 0;
  1239. Owned<IDistributedFilePartIterator> piter = file->getIterator();
  1240. ForEach(*piter) {
  1241. IDistributedFilePart &part = piter->query();
  1242. offset_t sz = (offset_t)-1;
  1243. for (unsigned c=0;c<part.numCopies();c++) {
  1244. RemoteFilename rfn;
  1245. part.getFilename(rfn,c);
  1246. try {
  1247. Owned<IFile> file = createIFile(rfn);
  1248. sz = file->size();
  1249. }
  1250. catch (IException *e) {
  1251. StringBuffer tmp("getCompressedSize(1): ");
  1252. rfn.getPath(tmp);
  1253. EXCLOG(e,tmp.str());
  1254. sz = (offset_t)-1;
  1255. e->Release();
  1256. }
  1257. if (sz!=(offset_t)-1)
  1258. break;
  1259. }
  1260. if (sz==(offset_t)-1) {
  1261. ret = (offset_t)-1;
  1262. break;
  1263. }
  1264. ret += sz;
  1265. }
  1266. }
  1267. catch (IException *e) {
  1268. EXCLOG(e,"getCompressedSize");
  1269. ret = (offset_t)-1;
  1270. e->Release();
  1271. }
  1272. }
  1273. return ret;
  1274. }
  1275. static void dfscompratio (const char *lname, IUserDescriptor *user)
  1276. {
  1277. Owned<IDistributedFile> file = queryDistributedFileDirectory().lookup(lname,user);
  1278. StringBuffer out;
  1279. out.appendf("File %s ",lname);
  1280. if (file) {
  1281. bool compressed = file->isCompressed();
  1282. if (!compressed)
  1283. out.append("not ");
  1284. out.append("compressed, ");
  1285. offset_t size = file->getFileSize(true,false);
  1286. if (size==(offset_t)-1)
  1287. out.appendf("size not known");
  1288. else if (compressed) {
  1289. out.appendf("expanded size %"I64F"d, ",size);
  1290. offset_t csize = getCompressedSize(file);
  1291. if (csize==(offset_t)-1)
  1292. out.append("compressed size unknown");
  1293. else {
  1294. out.appendf("compressed size %"I64F"d",csize);
  1295. if (csize)
  1296. out.appendf(", Ratio %.2f:1 (%%%d)",(float)size/csize,(unsigned)(csize*100/size));
  1297. }
  1298. }
  1299. else
  1300. out.appendf("not compressed, size %"I64F"d",size);
  1301. }
  1302. else
  1303. out.appendf("File %s not found",lname);
  1304. outln(out.str());
  1305. }
  1306. //=============================================================================
  1307. static bool onlyNamePtree(IPropertyTree *t)
  1308. {
  1309. if (!t)
  1310. return true;
  1311. if (t->numUniq())
  1312. return false;
  1313. Owned<IAttributeIterator> ai = t->getAttributes();
  1314. if (ai->first()) {
  1315. if (strcmp(ai->queryName(),"@name")!=0)
  1316. return false;
  1317. if (ai->next())
  1318. return false;
  1319. }
  1320. const char *s = t->queryProp(NULL);
  1321. if (s&&*s)
  1322. return false;
  1323. return true;
  1324. }
  1325. static bool countScopeChildren(IPropertyTree *t,unsigned &files, unsigned &sfiles, unsigned &scopes, unsigned &other)
  1326. {
  1327. scopes = 0;
  1328. files = 0;
  1329. sfiles = 0;
  1330. other = 0;
  1331. if (!t)
  1332. return false;
  1333. Owned<IPropertyTreeIterator> it = t->getElements("*");
  1334. ForEach(*it) {
  1335. IPropertyTree *st = &it->query();
  1336. const char *s = st?st->queryName():NULL;
  1337. if (!s)
  1338. other++;
  1339. else if (stricmp(s,queryDfsXmlBranchName(DXB_File))==0)
  1340. files++;
  1341. else if (stricmp(s,queryDfsXmlBranchName(DXB_SuperFile))==0)
  1342. sfiles++;
  1343. else if (stricmp(s,queryDfsXmlBranchName(DXB_Scope))==0)
  1344. scopes++;
  1345. else
  1346. other++;
  1347. }
  1348. return (other!=0)||(files!=0)||(sfiles!=0)||(scopes!=0)||(!onlyNamePtree(t));
  1349. }
  1350. static void dfsscopes(const char *name, IUserDescriptor *user)
  1351. {
  1352. bool wild = isWild(name);
  1353. Owned<IDFScopeIterator> iter = queryDistributedFileDirectory().getScopeIterator(user,wild?NULL:name,true,true);
  1354. StringBuffer ln;
  1355. ForEach(*iter) {
  1356. CDfsLogicalFileName dlfn;
  1357. StringBuffer scope;
  1358. if (!wild&&name&&*name&&(strcmp(name,".")!=0))
  1359. scope.append(name).append("::");
  1360. scope.append(iter->query());
  1361. if (wild&&!WildMatch(scope.str(),name))
  1362. continue;
  1363. dlfn.set(scope.str(),"x");
  1364. StringBuffer s;
  1365. dlfn.makeScopeQuery(s,true);
  1366. ln.clear().append("SCOPE '").append(iter->query()).append('\'');
  1367. Owned<IRemoteConnection> conn = querySDS().connect(s.str(),myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  1368. if (!conn)
  1369. ERRLOG("%s - Could not connect using %s",ln.str(),s.str());
  1370. else {
  1371. unsigned files;
  1372. unsigned sfiles;
  1373. unsigned scopes;
  1374. unsigned other;
  1375. if (countScopeChildren(conn->queryRoot(),files,sfiles,scopes,other)) {
  1376. ln.appendf(" Files=%d SuperFiles=%d Scopes=%d",files,sfiles,scopes);
  1377. if (other)
  1378. ln.appendf(" others=%d",other);
  1379. OUTLOG("%s",ln.str());
  1380. }
  1381. else
  1382. OUTLOG("%s EMPTY",ln.str());
  1383. }
  1384. }
  1385. }
  1386. //=============================================================================
  1387. static bool recursiveCheckEmptyScope(IPropertyTree &ct)
  1388. {
  1389. Owned<IPropertyTreeIterator> iter = ct.getElements("*");
  1390. ForEach(*iter) {
  1391. IPropertyTree &item = iter->query();
  1392. const char *n = item.queryName();
  1393. if (!n||(strcmp(n,queryDfsXmlBranchName(DXB_Scope))!=0))
  1394. return false;
  1395. if (!recursiveCheckEmptyScope(item))
  1396. return false;
  1397. }
  1398. return true;
  1399. }
  1400. static void cleanscopes(IUserDescriptor *user)
  1401. {
  1402. Owned<IDFScopeIterator> iter = queryDistributedFileDirectory().getScopeIterator(user, NULL,true,true);
  1403. CDfsLogicalFileName dlfn;
  1404. StringBuffer s;
  1405. StringArray toremove;
  1406. ForEach(*iter) {
  1407. CDfsLogicalFileName dlfn;
  1408. StringBuffer scope;
  1409. scope.append(iter->query());
  1410. dlfn.set(scope.str(),"x");
  1411. dlfn.makeScopeQuery(s.clear(),true);
  1412. Owned<IRemoteConnection> conn = querySDS().connect(s.str(),myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  1413. if (!conn)
  1414. DBGLOG("Could not connect to '%s' using %s",iter->query(),s.str());
  1415. else {
  1416. if (recursiveCheckEmptyScope(*conn->queryRoot())) {
  1417. toremove.append(iter->query());
  1418. PROGLOG("EMPTY %s, %s",iter->query(),s.str());
  1419. }
  1420. }
  1421. }
  1422. iter.clear();
  1423. ForEachItemIn(i,toremove) {
  1424. PROGLOG("REMOVE %s",toremove.item(i));
  1425. try {
  1426. queryDistributedFileDirectory().removeEmptyScope(toremove.item(i));
  1427. }
  1428. catch (IException *e) {
  1429. EXCLOG(e,"checkScopes");
  1430. e->Release();
  1431. }
  1432. }
  1433. }
  1434. //=============================================================================
  1435. static void listworkunits(const char *test, const char *min, const char *max)
  1436. {
  1437. Owned<IRemoteConnection> conn = querySDS().connect("/", myProcessSession(), 0, daliConnectTimeoutMs);
  1438. Owned<IPropertyTreeIterator> iter = conn->queryRoot()->getElements("WorkUnits/*");
  1439. ForEach(*iter)
  1440. {
  1441. IPropertyTree &e=iter->query();
  1442. if (test&&*test) {
  1443. const char *tval = strchr(test,'=');
  1444. if (!tval)
  1445. {
  1446. ERRLOG("missing '=' in %s",test);
  1447. return;
  1448. }
  1449. StringBuffer prop;
  1450. if (*test!='@')
  1451. prop.append('@');
  1452. prop.append(tval-test,test);
  1453. tval++;
  1454. const char *val = e.queryProp(prop.str());
  1455. if (!val||(strcmp(val,tval)!=0))
  1456. continue;
  1457. if (min &&(strcmp(e.queryName(),min)<0))
  1458. continue;
  1459. if (max &&(strcmp(e.queryName(),max)>0))
  1460. continue;
  1461. }
  1462. outln(e.queryName());
  1463. }
  1464. }
  1465. //=============================================================================
  1466. static void listmatches(const char *path, const char *match, const char *pval)
  1467. {
  1468. Owned<IRemoteConnection> conn = querySDS().connect(path, myProcessSession(), 0, daliConnectTimeoutMs);
  1469. if (!conn)
  1470. {
  1471. PROGLOG("Failed to connect to %s", path);
  1472. return;
  1473. }
  1474. StringBuffer output("Listing matches for path=");
  1475. output.append(path);
  1476. if (match)
  1477. {
  1478. output.append(", match=").append(match);
  1479. if (pval)
  1480. output.append(", property value = ").append(pval);
  1481. }
  1482. Owned<IPropertyTreeIterator> iter = conn->queryRoot()->getElements(match?match:"*", iptiter_remote);
  1483. ForEach(*iter)
  1484. {
  1485. IPropertyTree &e=iter->query();
  1486. output.clear().append(e.queryName());
  1487. const char *val = e.queryProp(pval?pval:NULL);
  1488. if (val)
  1489. output.append(" = ").append(val);
  1490. outln(output.str());
  1491. }
  1492. }
  1493. //=============================================================================
  1494. static const char *getNum(const char *s,unsigned &num)
  1495. {
  1496. while (*s&&!isdigit(*s))
  1497. s++;
  1498. num = 0;
  1499. while (isdigit(*s)) {
  1500. num = num*10+*s-'0';
  1501. s++;
  1502. }
  1503. return s;
  1504. }
  1505. static void workunittimings(const char *wuid)
  1506. {
  1507. StringBuffer path;
  1508. path.append("/WorkUnits/").append(wuid);
  1509. Owned<IRemoteConnection> conn = querySDS().connect(path, myProcessSession(), 0, daliConnectTimeoutMs);
  1510. if (!conn) {
  1511. ERRLOG("WU %s not found",wuid);
  1512. return;
  1513. }
  1514. IPropertyTree *wu = conn->queryRoot();
  1515. Owned<IPropertyTreeIterator> iter = wu->getElements("Timings/Timing");
  1516. StringBuffer name;
  1517. outln("Name,graph,sub,gid,time ms,time min");
  1518. ForEach(*iter) {
  1519. if (iter->query().getProp("@name",name.clear())) {
  1520. if ((name.length()>11)&&(memcmp("Graph graph",name.str(),11)==0)) {
  1521. unsigned gn;
  1522. const char *s = getNum(name.str(),gn);
  1523. unsigned sn;
  1524. s = getNum(s,sn);
  1525. if (gn&&sn) {
  1526. const char *gs = strchr(name.str(),'(');
  1527. unsigned gid = 0;
  1528. if (gs)
  1529. getNum(gs+1,gid);
  1530. unsigned time = iter->query().getPropInt("@duration");
  1531. OUTLOG("\"%s\",%d,%d,%d,%d,%d",name.str(),gn,sn,gid,time,(time/60000));
  1532. }
  1533. }
  1534. }
  1535. }
  1536. }
  1537. //=============================================================================
  1538. static void serverlist(const char *mask)
  1539. {
  1540. Owned<IRemoteConnection> conn = querySDS().connect( "/Environment/Software", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  1541. if (!conn)
  1542. throw MakeStringException(0,"Failed to connect to Environment/Software");
  1543. IPropertyTree* root = conn->queryRoot();
  1544. Owned<IPropertyTreeIterator> services= root->getElements("*");
  1545. ForEach(*services) {
  1546. IPropertyTree& t = services->query();
  1547. const char *name = t.queryName();
  1548. if (name) {
  1549. if (!mask||!*mask||WildMatch(name,mask)) {
  1550. Owned<IPropertyTreeIterator> insts = t.getElements("Instance");
  1551. ForEach(*insts) {
  1552. StringBuffer ips;
  1553. insts->query().getProp("@netAddress",ips);
  1554. StringBuffer dir;
  1555. insts->query().getProp("@directory",dir);
  1556. OUTLOG("%s,%s,%s",name,ips.str(),dir.str());
  1557. }
  1558. }
  1559. }
  1560. }
  1561. }
  1562. //=============================================================================
  1563. static void clusterlist(const char *mask)
  1564. {
  1565. Owned<IRemoteConnection> conn = querySDS().connect("/Environment/Software", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  1566. if (!conn)
  1567. throw MakeStringException(0,"Failed to connect to Environment/Software");
  1568. IPropertyTree* root = conn->queryRoot();
  1569. Owned<IPropertyTreeIterator> clusters;
  1570. clusters.setown(root->getElements("ThorCluster"));
  1571. ForEach(*clusters) {
  1572. }
  1573. clusters.setown(root->getElements("RoxieCluster"));
  1574. ForEach(*clusters) {
  1575. }
  1576. clusters.setown(root->getElements("EclAgentProcess"));
  1577. ForEach(*clusters) {
  1578. }
  1579. }
  1580. static unsigned clustersToGroups(IPropertyTree *envroot,const StringArray &cmplst,StringArray &cnames,StringArray &groups,bool *done)
  1581. {
  1582. if (!envroot)
  1583. return 0;
  1584. for (int roxie=0;roxie<2;roxie++) {
  1585. Owned<IPropertyTreeIterator> clusters= envroot->getElements(roxie?"RoxieCluster":"ThorCluster");
  1586. unsigned ret = 0;
  1587. ForEach(*clusters) {
  1588. IPropertyTree &cluster = clusters->query();
  1589. const char *name = cluster.queryProp("@name");
  1590. if (name&&*name) {
  1591. ForEachItemIn(i,cmplst) {
  1592. const char *s = cmplst.item(i);
  1593. assertex(s);
  1594. if ((strcmp(s,"*")==0)||WildMatch(name,s,true)) {
  1595. const char *group = cluster.queryProp("@nodeGroup");
  1596. if (!group||!*group)
  1597. group = name;
  1598. bool found = false;
  1599. ForEachItemIn(j,groups)
  1600. if (strcmp(groups.item(j),group)==0)
  1601. found = true;
  1602. if (!found) {
  1603. cnames.append(name);
  1604. groups.append(group);
  1605. if (done)
  1606. done[i] =true;
  1607. break;
  1608. }
  1609. }
  1610. }
  1611. }
  1612. }
  1613. }
  1614. return groups.ordinality();
  1615. }
  1616. static void clusterlist()
  1617. {
  1618. Owned<IRemoteConnection> conn = querySDS().connect("/Environment/Software", myProcessSession(), RTM_LOCK_READ, daliConnectTimeoutMs);
  1619. if (!conn) {
  1620. ERRLOG("Could not connect to /Environment/Software");
  1621. return;
  1622. }
  1623. StringArray list;
  1624. list.append("*");
  1625. StringArray groups;
  1626. StringArray cnames;
  1627. bool *done = (bool *)calloc(list.ordinality(),sizeof(bool));
  1628. clustersToGroups(conn->queryRoot(),list,cnames,groups,done);
  1629. free(done);
  1630. ForEachItemIn(i,cnames)
  1631. OUTLOG("%s,%s",cnames.item(i),groups.item(i));
  1632. }
  1633. //=============================================================================
  1634. static void auditlog(const char *froms, const char *tos, const char *matchs)
  1635. {
  1636. CDateTime from;
  1637. try {
  1638. from.setDateString(froms);
  1639. }
  1640. catch (IException *) {
  1641. ERRLOG("%s: invalid date (format YYYY-MM-DD)",froms);
  1642. throw;
  1643. }
  1644. CDateTime to;
  1645. try {
  1646. to.setDateString(tos);
  1647. }
  1648. catch (IException *) {
  1649. ERRLOG("%s: invalid date (format YYYY-MM-DD)",tos);
  1650. throw;
  1651. }
  1652. StringAttrArray res;
  1653. queryAuditLogs(from,to,matchs,res);
  1654. ForEachItemIn(i,res)
  1655. outln(res.item(i).text.get());
  1656. }
  1657. //=============================================================================
  1658. static void coalesce()
  1659. {
  1660. const char *daliDataPath = NULL;
  1661. const char *remoteBackupLocation = NULL;
  1662. Owned<IStoreHelper> iStoreHelper = createStoreHelper(NULL, daliDataPath, remoteBackupLocation, SH_External|SH_RecoverFromIncErrors);
  1663. unsigned baseEdition = iStoreHelper->queryCurrentEdition();
  1664. StringBuffer storeFilename(daliDataPath);
  1665. iStoreHelper->getCurrentStoreFilename(storeFilename);
  1666. OUTLOG("Loading store: %s", storeFilename.str());
  1667. Owned<IPropertyTree> root = createPTreeFromXMLFile(storeFilename.str());
  1668. OUTLOG("Loaded: %s", storeFilename.str());
  1669. if (baseEdition != iStoreHelper->queryCurrentEdition())
  1670. OUTLOG("Store was changed by another process prior to coalesce. Exiting.");
  1671. else
  1672. {
  1673. if (!iStoreHelper->loadDeltas(root))
  1674. OUTLOG("Nothing to coalesce");
  1675. else
  1676. iStoreHelper->saveStore(root, &baseEdition);
  1677. }
  1678. }
  1679. //=============================================================================
  1680. static void mpping(const char *eps)
  1681. {
  1682. SocketEndpoint ep(eps);
  1683. Owned<INode> node = createINode(ep);
  1684. Owned<IGroup> grp = createIGroup(1,&ep);
  1685. Owned<ICommunicator> comm = createCommunicator(grp,true);
  1686. unsigned start = msTick();
  1687. if (!comm->verifyConnection(0,60*1000))
  1688. ERRLOG("MPping %s failed",eps);
  1689. else
  1690. OUTLOG("MPping %s succeeded in %d",eps,msTick()-start);
  1691. }
  1692. //=============================================================================
  1693. static void daliping(const char *dalis,unsigned connecttime,unsigned n)
  1694. {
  1695. OUTLOG("Dali(%s) connect time: %d ms",dalis,connecttime);
  1696. if (!n)
  1697. return;
  1698. StringBuffer qname("TESTINGQ_");
  1699. SocketEndpoint ep;
  1700. ep.setLocalHost(0);
  1701. ep.getUrlStr(qname);
  1702. Owned<INamedQueueConnection> qconn;
  1703. qconn.setown(createNamedQueueConnection(0));
  1704. Owned<IQueueChannel> channel;
  1705. channel.setown(qconn->open(qname.str()));
  1706. MemoryBuffer mb;
  1707. while (channel->probe()) {
  1708. mb.clear();
  1709. channel->get(mb);
  1710. }
  1711. unsigned max = 0;
  1712. unsigned tot = 0;
  1713. for (unsigned i=0;i<=n;i++) {
  1714. mb.clear().append("Hello").append(i);
  1715. ep.serialize(mb);
  1716. unsigned start = msTick();
  1717. channel->put(mb);
  1718. channel->get(mb);
  1719. if (i) { // ignore first
  1720. unsigned t = msTick()-start;
  1721. if (t>max)
  1722. max = t;
  1723. tot += t;
  1724. OUTLOG("Dali(%s) ping %d ms",dalis,t);
  1725. if (i+1<n)
  1726. Sleep(1000);
  1727. }
  1728. }
  1729. OUTLOG("Dali(%s) ping avg = %d max = %d ms",dalis,tot/n,max);
  1730. }
  1731. //=============================================================================
  1732. static void convertBinBranch(IPropertyTree &cluster,const char *branch)
  1733. {
  1734. StringBuffer query(branch);
  1735. query.append("/data");
  1736. IPropertyTree *t;
  1737. MemoryBuffer buf;
  1738. cluster.getPropBin(query.str(),buf);
  1739. if (buf.length()) {
  1740. StringBuffer xml;
  1741. xml.append(buf.length(),buf.toByteArray());
  1742. t = createPTreeFromXMLString(xml.str());
  1743. cluster.removeProp(query.str());
  1744. cluster.addPropTree(query.str(),t);
  1745. }
  1746. }
  1747. static void getxref(const char *dst)
  1748. {
  1749. Owned<IRemoteConnection> conn = querySDS().connect("DFU/XREF",myProcessSession(),RTM_LOCK_READ, daliConnectTimeoutMs);
  1750. Owned<IPropertyTree> root = createPTreeFromIPT(conn->getRoot());
  1751. Owned<IPropertyTreeIterator> iter = root->getElements("Cluster");
  1752. ForEach(*iter) {
  1753. IPropertyTree &cluster = iter->query();
  1754. convertBinBranch(cluster,"Directories");
  1755. convertBinBranch(cluster,"Lost");
  1756. convertBinBranch(cluster,"Found");
  1757. convertBinBranch(cluster,"Orphans");
  1758. convertBinBranch(cluster,"Messages");
  1759. }
  1760. Owned<IFile> f = createIFile(dst);
  1761. Owned<IFileIO> io = f->open(IFOcreate);
  1762. Owned<IFileIOStream> fstream = createBufferedIOStream(io);
  1763. toXML(root, *fstream); // formatted (default)
  1764. OUTLOG("DFU/XREF saved in '%s'",dst);
  1765. conn->close();
  1766. }
  1767. struct CTreeItem : public CInterface
  1768. {
  1769. String *tail;
  1770. CTreeItem *parent;
  1771. unsigned index;
  1772. unsigned startOffset;
  1773. unsigned endOffset;
  1774. unsigned adjust;
  1775. bool supressidx;
  1776. CTreeItem(CTreeItem *_parent, String *_tail, unsigned _index, unsigned _startOffset)
  1777. {
  1778. parent = LINK(_parent);
  1779. startOffset = _startOffset;
  1780. endOffset = 0;
  1781. adjust = 0;
  1782. index = _index;
  1783. supressidx = true;
  1784. tail = _tail;
  1785. }
  1786. ~CTreeItem()
  1787. {
  1788. if (parent)
  1789. parent->Release();
  1790. ::Release(tail);
  1791. }
  1792. void getXPath(StringBuffer &xpath)
  1793. {
  1794. if (parent)
  1795. parent->getXPath(xpath);
  1796. xpath.append('/').append(tail->toCharArray());
  1797. if ((index!=0)||tail->IsShared())
  1798. xpath.append('[').append(index+1).append(']');
  1799. }
  1800. unsigned size() { return endOffset?(endOffset-startOffset):0; }
  1801. unsigned adjustedSize(bool &adjusted) { adjusted = (adjust!=0); return size()-adjust; }
  1802. };
  1803. class CXMLSizesParser : public CInterface
  1804. {
  1805. Owned<IPullPTreeReader> xmlReader;
  1806. PTreeReaderOptions xmlOptions;
  1807. double pc;
  1808. class CParse : public CInterface, implements IPTreeNotifyEvent
  1809. {
  1810. CIArrayOf<CTreeItem> stack;
  1811. String * levtail;
  1812. CIArrayOf<CTreeItem> arr;
  1813. unsigned limit;
  1814. __int64 totalSize;
  1815. static int _sortF(CInterface **_left, CInterface **_right)
  1816. {
  1817. CTreeItem **left = (CTreeItem **)_left;
  1818. CTreeItem **right = (CTreeItem **)_right;
  1819. return ((*right)->size() - (*left)->size());
  1820. }
  1821. public:
  1822. IMPLEMENT_IINTERFACE;
  1823. CParse(unsigned __int64 _totalSize, double limitpc) : totalSize(_totalSize)
  1824. {
  1825. levtail = NULL;
  1826. limit = (unsigned)((double)totalSize*limitpc/100.0);
  1827. }
  1828. void reset()
  1829. {
  1830. stack.kill();
  1831. }
  1832. // IPTreeNotifyEvent
  1833. virtual void beginNode(const char *tag, offset_t startOffset)
  1834. {
  1835. String *tail = levtail;
  1836. if (levtail&&(0 == strcmp(tag, levtail->toCharArray())))
  1837. tail->Link();
  1838. else
  1839. tail = new String(tag);
  1840. levtail = NULL; // opening new child
  1841. CTreeItem *parent = stack.empty()?NULL:&stack.tos();
  1842. CTreeItem *item = new CTreeItem(parent, tail, tail->getLinkCount(), startOffset);
  1843. stack.append(*item);
  1844. }
  1845. virtual void newAttribute(const char *tag, const char *value)
  1846. {
  1847. }
  1848. virtual void beginNodeContent(const char *tag)
  1849. {
  1850. }
  1851. virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset)
  1852. {
  1853. CTreeItem *tos = &stack.tos();
  1854. assertex(tos);
  1855. tos->endOffset = endOffset;
  1856. bool adjusted;
  1857. unsigned sz = tos->adjustedSize(adjusted);
  1858. if (sz>=limit)
  1859. {
  1860. CTreeItem *parent = tos->parent;
  1861. while (parent) {
  1862. parent->adjust += sz;
  1863. parent = parent->parent;
  1864. }
  1865. tos->Link();
  1866. arr.append(*tos);
  1867. levtail = tos->tail;
  1868. }
  1869. else
  1870. levtail = NULL;
  1871. stack.pop();
  1872. }
  1873. void printFullResults()
  1874. {
  1875. arr.sort(_sortF);
  1876. ForEachItemIn(m, arr)
  1877. {
  1878. CTreeItem &match = arr.item(m);
  1879. StringBuffer xpath;
  1880. match.getXPath(xpath);
  1881. printf("xpath=%s, size=%d\n", xpath.str(), match.size());
  1882. }
  1883. }
  1884. void printResultTree()
  1885. {
  1886. if (!totalSize)
  1887. return;
  1888. StringBuffer res;
  1889. ForEachItemIn(i, arr) {
  1890. CTreeItem &item = arr.item(i);
  1891. bool adjusted;
  1892. unsigned sz = item.adjustedSize(adjusted);
  1893. if (sz>=limit) {
  1894. res.clear();
  1895. item.getXPath(res);
  1896. if (adjusted)
  1897. res.append(" (rest)");
  1898. res.padTo(40);
  1899. res.appendf(" %10d(%5.2f%%)",sz,((float)sz*100.0)/(float)totalSize);
  1900. printf("%s\n",res.str());
  1901. }
  1902. }
  1903. }
  1904. } *parser;
  1905. public:
  1906. IMPLEMENT_IINTERFACE;
  1907. CXMLSizesParser(const char *fName, PTreeReaderOptions _xmlOptions=ptr_none, double _pc=1.0) : xmlOptions(_xmlOptions), pc(_pc) { go(fName); }
  1908. ~CXMLSizesParser() { ::Release(parser); }
  1909. void go(const char *fName)
  1910. {
  1911. OwnedIFile ifile = createIFile(fName);
  1912. OwnedIFileIO ifileio = ifile->open(IFOread);
  1913. if (!ifileio)
  1914. throw MakeStringException(0, "Failed to open: %s", ifile->queryFilename());
  1915. parser = new CParse(ifileio->size(), pc);
  1916. Owned<IIOStream> stream = createIOStream(ifileio);
  1917. xmlReader.setown(createPullXMLStreamReader(*stream, *parser, xmlOptions));
  1918. }
  1919. void printResultTree()
  1920. {
  1921. parser->printResultTree();
  1922. }
  1923. virtual bool next()
  1924. {
  1925. return xmlReader->next();
  1926. }
  1927. virtual void reset()
  1928. {
  1929. parser->reset();
  1930. xmlReader->reset();
  1931. }
  1932. };
  1933. static void xmlSize(const char *filename, double pc)
  1934. {
  1935. try
  1936. {
  1937. OwnedIFile iFile = createIFile(filename);
  1938. if (!iFile->exists())
  1939. OUTLOG("File '%s' not found", filename);
  1940. else
  1941. {
  1942. Owned<CXMLSizesParser> parser = new CXMLSizesParser((filename&&*filename)?filename:"dalisds.xml", ptr_none, pc);
  1943. while (parser->next())
  1944. ;
  1945. parser->printResultTree();
  1946. }
  1947. }
  1948. catch (IException *e)
  1949. {
  1950. pexception("xmlSize", e);
  1951. e->Release();
  1952. }
  1953. }
  1954. //=============================================================================
  1955. static bool begins(const char *&ln,const char *pat)
  1956. {
  1957. size32_t sz = strlen(pat);
  1958. if (memicmp(ln,pat,sz)==0) {
  1959. ln += sz;
  1960. return true;
  1961. }
  1962. return false;
  1963. }
  1964. static void dodalilocks(const char *pattern,const char *obj,Int64Array *conn,bool filesonly)
  1965. {
  1966. StringBuffer buf;
  1967. getDaliDiagnosticValue("locks",buf);
  1968. for (int pass=(filesonly?1:0);pass<2;pass++) {
  1969. bool headerdone = false;
  1970. StringBuffer line;
  1971. StringBuffer curfile;
  1972. StringBuffer curxpath;
  1973. StringBuffer ips;
  1974. StringBuffer times;
  1975. StringBuffer sessid;
  1976. StringBuffer connid;
  1977. const char *s = buf.str();
  1978. loop {
  1979. line.clear();
  1980. while (*s&&(*s!='\n'))
  1981. line.append(*(s++));
  1982. if (line.length()) {
  1983. const char *ln = line.str();
  1984. if (begins(ln,"Locks on path: ")) {
  1985. curfile.clear();
  1986. curxpath.clear();
  1987. const char *x = ln;
  1988. while (*x)
  1989. curxpath.append(*(x++));
  1990. if (begins(ln,"/Files")) {
  1991. while (*ln&&(begins(ln,"/Scope[@name=\"")||begins(ln,"/File[@name=\"")||begins(ln,"/SuperFile[@name=\""))) {
  1992. if (curfile.length())
  1993. curfile.append("::");
  1994. while (*ln&&(*ln!='"'))
  1995. curfile.append(*(ln++));
  1996. if (*ln=='"')
  1997. ln++;
  1998. if (*ln==']')
  1999. ln++;
  2000. }
  2001. }
  2002. }
  2003. else if (isdigit(*ln)) {
  2004. if (obj)
  2005. if (!curxpath.length()||!WildMatch(curxpath.str(),obj))
  2006. if (!curfile.length()||!WildMatch(curfile.str(),obj))
  2007. continue;
  2008. if ((curfile.length()!=0)==(pass==1)) {
  2009. ips.clear();
  2010. while (*ln&&(*ln!=':'))
  2011. ips.append(*(ln++));
  2012. if (!pattern||WildMatch(ips.str(),pattern)) {
  2013. ips.append(*ln++);
  2014. while (isdigit(*ln))
  2015. ips.append(*ln++);
  2016. while (*ln!='|')
  2017. ln++;
  2018. ln++; // sessid start
  2019. sessid.clear();
  2020. while (*ln!='|') {
  2021. sessid.append(*ln);
  2022. ln++;
  2023. }
  2024. sessid.clip();
  2025. ln++; // connectid start
  2026. connid.clear();
  2027. while (*ln!='|') {
  2028. connid.append(*ln);
  2029. ln++;
  2030. }
  2031. connid.clip();
  2032. ln++; // mode start
  2033. unsigned mode = 0;
  2034. while (isdigit(*ln))
  2035. mode = mode*10+(*(ln++)-'0');
  2036. while (*ln!='|')
  2037. ln++;
  2038. ln++; // duration start
  2039. times.clear();
  2040. while (*ln&&(*ln!='('))
  2041. times.append(*(ln++));
  2042. ln++;
  2043. unsigned duration = 0;
  2044. while (isdigit(*ln))
  2045. duration = duration*10+(*(ln++)-'0');
  2046. if (conn) {
  2047. bool err;
  2048. __int64 c = (__int64)hextoll(connid.str(),err);
  2049. if (!err) {
  2050. bool found = false;
  2051. ForEachItemIn(i,*conn)
  2052. if (c==conn->item(i))
  2053. found = true;
  2054. if (!found)
  2055. conn->append(c);
  2056. }
  2057. }
  2058. else {
  2059. if (!headerdone) {
  2060. OUTLOG( "\nServer IP , session ,mode, time ,duration ,%s",pass?"File":"XPath");
  2061. OUTLOG( "==================,===========,===,====================,=========,=====");
  2062. headerdone = true;
  2063. }
  2064. OUTLOG("%s, %s, %d, %s, %d, %s",ips.str(),sessid.str(),mode,times.str(),duration,pass?curfile.str():curxpath.str());
  2065. }
  2066. }
  2067. }
  2068. }
  2069. }
  2070. if (!*s)
  2071. break;
  2072. s++;
  2073. }
  2074. }
  2075. }
  2076. static void dalilocks(const char *pattern,bool fileonly)
  2077. {
  2078. dodalilocks(pattern,NULL,NULL,fileonly);
  2079. }
  2080. //=============================================================================
  2081. static void unlock(const char *pattern)
  2082. {
  2083. Int64Array conn;
  2084. dodalilocks(NULL,pattern,&conn,false);
  2085. ForEachItemIn(i,conn) {
  2086. MemoryBuffer mb;
  2087. __int64 connectionId = conn.item(i);
  2088. bool success;
  2089. bool disconnect = false; // TBD?
  2090. mb.append("unlock").append(connectionId).append(disconnect);
  2091. getDaliDiagnosticValue(mb);
  2092. mb.read(success);
  2093. StringBuffer connectionInfo;
  2094. if (!success)
  2095. PROGLOG("Lock %"I64F"x not found",connectionId);
  2096. else {
  2097. mb.read(connectionInfo);
  2098. PROGLOG("Lock %"I64F"x successfully removed: %s", connectionId, connectionInfo.str());
  2099. }
  2100. }
  2101. }
  2102. static void wuidCompress(const char *match, const char *type, bool compress)
  2103. {
  2104. if (0 != stricmp("graph", type))
  2105. {
  2106. WARNLOG("Currently, only type=='graph' supported.");
  2107. return;
  2108. }
  2109. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  2110. Owned<IConstWorkUnitIterator> iter = factory->getWorkUnitsByXPath(match);
  2111. ForEach(*iter)
  2112. {
  2113. IConstWorkUnit &wuid = iter->query();
  2114. StringArray graphNames;
  2115. Owned<IConstWUGraphIterator> graphIter = &wuid.getGraphs(GraphTypeAny);
  2116. ForEach(*graphIter)
  2117. {
  2118. SCMStringBuffer graphName;
  2119. IConstWUGraph &graph = graphIter->query();
  2120. Owned<IPropertyTree> xgmml = graph.getXGMMLTreeRaw();
  2121. if (compress != xgmml->hasProp("graphBin"))
  2122. {
  2123. graph.getName(graphName);
  2124. graphNames.append(graphName.s.str());
  2125. }
  2126. }
  2127. if (graphNames.ordinality())
  2128. {
  2129. SCMStringBuffer wuidName;
  2130. wuid.getWuid(wuidName);
  2131. StringAttr msg;
  2132. msg.set(compress?"Compressing":"Uncompressing");
  2133. PROGLOG("%s graphs for workunit: %s", msg.get(), wuidName.s.str());
  2134. Owned<IWorkUnit> wWuid = &wuid.lock();
  2135. ForEachItemIn(n, graphNames)
  2136. {
  2137. Owned<IWUGraph> wGraph = wWuid->updateGraph(graphNames.item(n));
  2138. PROGLOG("%s graph: %s", msg.get(), graphNames.item(n));
  2139. // get/set - will convert to/from new format (binary compress blob)
  2140. Owned<IPropertyTree> xgmml = wGraph->getXGMMLTree(false);
  2141. wGraph->setXGMMLTree(xgmml.getClear(), compress);
  2142. }
  2143. }
  2144. }
  2145. }
  2146. static void validateStore(bool fix, bool deleteFiles, bool verbose)
  2147. {
  2148. /*
  2149. * Place holder for client-side dali store verification/validation. Currently performs:
  2150. * 1) validates GeneratedDll entries correspond to current workunits (see HPCC-9146)
  2151. */
  2152. CTimeMon totalTime, ts;
  2153. PROGLOG("Gathering list of workunits");
  2154. Owned<IRemoteConnection> conn = querySDS().connect("/WorkUnits", myProcessSession(), RTM_LOCK_READ, 10000);
  2155. if (!conn)
  2156. throw MakeStringException(0, "Failed to connect to /WorkUnits");
  2157. AtomRefTable wuids;
  2158. Owned<IPropertyTreeIterator> wuidIter = conn->queryRoot()->getElements("*");
  2159. ForEach(*wuidIter)
  2160. {
  2161. IPropertyTree &wuid = wuidIter->query();
  2162. wuids.queryCreate(wuid.queryName());
  2163. }
  2164. PROGLOG("%d workunits gathered. Took %d ms", wuids.count(), ts.elapsed());
  2165. ts.reset(0);
  2166. StringArray uidsToDelete;
  2167. UnsignedArray indexToDelete;
  2168. PROGLOG("Gathering associated files");
  2169. conn.setown(querySDS().connect("/GeneratedDlls", myProcessSession(), fix?RTM_LOCK_WRITE:RTM_LOCK_READ, 10000));
  2170. IPropertyTree *root = conn->queryRoot()->queryBranch(NULL); // force all to download
  2171. Owned<IPropertyTreeIterator> gdIter = root->getElements("*");
  2172. RegExpr RE("^.*{W2[0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]{-[0-9]+}?}{[^0-9].*|}$");
  2173. unsigned index=1;
  2174. ForEach(*gdIter)
  2175. {
  2176. IPropertyTree &gd = gdIter->query();
  2177. const char *name = gd.queryProp("@name");
  2178. if (name && *name)
  2179. {
  2180. if (RE.find(name))
  2181. {
  2182. StringBuffer wuid;
  2183. RE.substitute(wuid,"#1");
  2184. const char *w = wuid.str();
  2185. bool found = NULL != wuids.find(*w);
  2186. const char *uid = gd.queryProp("@uid");
  2187. if (!found)
  2188. {
  2189. uidsToDelete.append(uid);
  2190. indexToDelete.append(index);
  2191. }
  2192. }
  2193. }
  2194. ++index;
  2195. }
  2196. PROGLOG("%d out of %d workunit files not associated with any workunit. Took %d ms", indexToDelete.ordinality(), index, ts.elapsed());
  2197. ts.reset(0);
  2198. IArrayOf<IDllEntry> removedEntries;
  2199. unsigned numDeleted = 0;
  2200. ForEachItemInRev(d, indexToDelete)
  2201. {
  2202. const char *uid = uidsToDelete.item(d);
  2203. unsigned index = indexToDelete.item(d);
  2204. StringBuffer path("GeneratedDll[");
  2205. path.append(index).append("]");
  2206. IPropertyTree *gd = root->queryPropTree(path.str());
  2207. if (NULL == gd)
  2208. throwUnexpected();
  2209. const char *uidQuery = gd->queryProp("@uid");
  2210. if (0 != strcmp(uid, uidQuery))
  2211. throw MakeStringException(0, "Expecting uid=%s @ GeneratedDll[%d], but found uid=%s", uid, index, uidQuery);
  2212. if (verbose)
  2213. PROGLOG("Removing: %s, uid=%s", path.str(), uid);
  2214. if (fix)
  2215. {
  2216. Owned<IDllEntry> entry = queryDllServer().createEntry(root, gd);
  2217. entry->remove(false, false); // NB: This will remove child 'gd' element from root (GeneratedDlls)
  2218. if (deleteFiles) // delay until after meta info removed and /GeneratedDlls unlocked
  2219. removedEntries.append(*entry.getClear());
  2220. }
  2221. ++numDeleted;
  2222. }
  2223. if (fix)
  2224. {
  2225. conn->commit();
  2226. PROGLOG("Removed %d unassociated file entries. Took %d ms", numDeleted, ts.elapsed());
  2227. ts.reset(0);
  2228. if (deleteFiles)
  2229. {
  2230. PROGLOG("Deleting physical files..");
  2231. ForEachItemIn(r, removedEntries)
  2232. {
  2233. IDllEntry &entry = removedEntries.item(r);
  2234. PROGLOG("Removing files for: %s", entry.queryName());
  2235. entry.remove(true, false);
  2236. }
  2237. PROGLOG("Removed physical files. Took %d ms", ts.elapsed());
  2238. }
  2239. }
  2240. else
  2241. PROGLOG("%d unassociated file entries to remove - use 'fix=true'", numDeleted);
  2242. PROGLOG("Done time = %d secs", totalTime.elapsed()/1000);
  2243. }
  2244. //=============================================================================
  2245. void testThorRunningWUs()
  2246. {
  2247. Owned<IRemoteConnection> conn = querySDS().connect("/Status/Servers",myProcessSession(),RTM_LOCK_READ,30000);
  2248. if (conn.get())
  2249. {
  2250. Owned<IPropertyTreeIterator> it(conn->queryRoot()->getElements("Server"));
  2251. ForEach(*it) {
  2252. StringBuffer instance;
  2253. if(it->query().hasProp("@queue"))
  2254. {
  2255. const char* queue=it->query().queryProp("@queue");
  2256. if(strstr(queue,".thor")) {
  2257. Owned<IPropertyTreeIterator> wuids(it->query().getElements("WorkUnit"));
  2258. ForEach(*wuids) {
  2259. IPropertyTree &wu = wuids->query();
  2260. const char* wuid=wu.queryProp(NULL);
  2261. if (wuid&&*wuid) {
  2262. const char *prioclass = wu.queryProp("@priorityClass");
  2263. bool high = false;
  2264. if (prioclass&&(stricmp(prioclass,"high")==0))
  2265. high = true;
  2266. OUTLOG("%s running on queue %s",wuid,queue);
  2267. }
  2268. }
  2269. }
  2270. }
  2271. }
  2272. }
  2273. }
  2274. #define CHECKPARAMS(mn,mx) { if ((np<mn)||(np>mx)) throw MakeStringException(-1,"%s: incorrect number of parameters",cmd); }
  2275. int main(int argc, char* argv[])
  2276. {
  2277. int ret = 0;
  2278. InitModuleObjects();
  2279. EnableSEHtoExceptionMapping();
  2280. setDaliServixSocketCaching(true);
  2281. if (argc<2) {
  2282. usage(argv[0]);
  2283. return -1;
  2284. }
  2285. Owned<IProperties> props = createProperties("daliadmin.ini");
  2286. StringArray params;
  2287. SocketEndpoint ep;
  2288. StringBuffer tmps;
  2289. for (int i=1;i<argc;i++) {
  2290. const char *param = argv[i];
  2291. if ((memcmp(param,"server=",7)==0)||
  2292. (memcmp(param,"logfile=",8)==0)||
  2293. (memcmp(param,"rawlog=",8)==0)||
  2294. (memcmp(param,"user=",5)==0)||
  2295. (memcmp(param,"password=",9)==0) ||
  2296. (memcmp(param,"fix=",4)==0) ||
  2297. (memcmp(param,"verbose=",8)==0) ||
  2298. (memcmp(param,"deletefiles=",12)==0) ||
  2299. (memcmp(param,"timeout=",4)==0))
  2300. props->loadProp(param);
  2301. else if ((i==1)&&(isdigit(*param)||(*param=='.'))&&ep.set(((*param=='.')&&param[1])?(param+1):param,DALI_SERVER_PORT))
  2302. props->setProp("server",ep.getUrlStr(tmps.clear()).str());
  2303. else {
  2304. if ((0==stricmp(param,"help")) || (0 ==stricmp(param,"-help")) || (0 ==stricmp(param,"--help"))) {
  2305. usage(argv[0]);
  2306. return -1;
  2307. }
  2308. params.append(param);
  2309. }
  2310. }
  2311. if (!params.ordinality()) {
  2312. usage(argv[0]);
  2313. return -1;
  2314. }
  2315. try {
  2316. StringBuffer logname;
  2317. StringBuffer aliasname;
  2318. bool rawlog = props->getPropBool("rawlog");
  2319. Owned<ILogMsgHandler> fileMsgHandler;
  2320. if (props->getProp("logfile",logname)) {
  2321. if (logname.length()) {
  2322. fileMsgHandler.setown(getFileLogMsgHandler(logname.str(), NULL, rawlog?MSGFIELD_prefix:MSGFIELD_STANDARD, false, false, true));
  2323. queryLogMsgManager()->addMonitorOwn(fileMsgHandler.getClear(), getCategoryLogMsgFilter(MSGAUD_all, MSGCLS_all, TopDetail));
  2324. }
  2325. }
  2326. // set stdout
  2327. attachStandardHandleLogMsgMonitor(stdout,0,MSGAUD_all,MSGCLS_all&~(MSGCLS_disaster|MSGCLS_error|MSGCLS_warning));
  2328. Owned<ILogMsgFilter> filter = getCategoryLogMsgFilter(MSGAUD_user, MSGCLS_error|MSGCLS_warning);
  2329. queryLogMsgManager()->changeMonitorFilter(queryStderrLogMsgHandler(), filter);
  2330. queryStderrLogMsgHandler()->setMessageFields(MSGFIELD_prefix);
  2331. }
  2332. catch (IException *e) {
  2333. pexception("daliadmin",e);
  2334. e->Release();
  2335. ret = 255;
  2336. }
  2337. unsigned daliconnectelapsed;
  2338. StringBuffer daliserv;
  2339. if (!ret) {
  2340. const char *cmd = params.item(0);
  2341. unsigned np = params.ordinality()-1;
  2342. if (!props->getProp("server",daliserv.clear()))
  2343. {
  2344. // external commands
  2345. if (stricmp(cmd,"xmlsize")==0)
  2346. {
  2347. CHECKPARAMS(1,2);
  2348. xmlSize(params.item(1), np>1?atof(params.item(2)):1.0);
  2349. }
  2350. else
  2351. ERRLOG("Unknown command %s",cmd);
  2352. return 0;
  2353. }
  2354. else
  2355. {
  2356. try {
  2357. SocketEndpoint ep(daliserv.str(),DALI_SERVER_PORT);
  2358. SocketEndpointArray epa;
  2359. epa.append(ep);
  2360. Owned<IGroup> group = createIGroup(epa);
  2361. unsigned start = msTick();
  2362. initClientProcess(group, DCR_Util);
  2363. daliconnectelapsed = msTick()-start;
  2364. }
  2365. catch (IException *e) {
  2366. EXCLOG(e,"daliadmin initClientProcess");
  2367. e->Release();
  2368. ret = 254;
  2369. }
  2370. if (!ret) {
  2371. try {
  2372. Owned<IUserDescriptor> userDesc;
  2373. if (props->getProp("user",tmps.clear())) {
  2374. userDesc.setown(createUserDescriptor());
  2375. StringBuffer ps;
  2376. props->getProp("password",ps);
  2377. userDesc->set(tmps.str(),ps.str());
  2378. queryDistributedFileDirectory().setDefaultUser(userDesc);
  2379. }
  2380. daliConnectTimeoutMs = 1000 * props->getPropInt("timeout", DEFAULT_DALICONNECT_TIMEOUT);
  2381. if (stricmp(cmd,"export")==0) {
  2382. CHECKPARAMS(2,2);
  2383. _export_(params.item(1),params.item(2));
  2384. }
  2385. else if (stricmp(cmd,"import")==0) {
  2386. CHECKPARAMS(2,2);
  2387. import(params.item(1),params.item(2),false);
  2388. }
  2389. else if (stricmp(cmd,"importadd")==0) {
  2390. CHECKPARAMS(2,2);
  2391. import(params.item(1),params.item(2),true);
  2392. }
  2393. else if (stricmp(cmd,"delete")==0) {
  2394. CHECKPARAMS(1,1);
  2395. _delete_(params.item(1),true);
  2396. }
  2397. else if (stricmp(cmd,"set")==0) {
  2398. CHECKPARAMS(2,2);
  2399. set(params.item(1),params.item(2));
  2400. }
  2401. else if (stricmp(cmd,"get")==0) {
  2402. CHECKPARAMS(1,1);
  2403. get(params.item(1));
  2404. }
  2405. else if (stricmp(cmd,"bget")==0) {
  2406. CHECKPARAMS(2,2);
  2407. bget(params.item(1),params.item(2));
  2408. }
  2409. else if (stricmp(cmd,"wget")==0) {
  2410. CHECKPARAMS(1,1);
  2411. wget(params.item(1));
  2412. }
  2413. else if (stricmp(cmd,"xget")==0) {
  2414. CHECKPARAMS(1,1);
  2415. wget(params.item(1));
  2416. }
  2417. else if (stricmp(cmd,"add")==0) {
  2418. CHECKPARAMS(2,2);
  2419. add(params.item(1),params.item(2));
  2420. }
  2421. else if (stricmp(cmd,"delv")==0) {
  2422. CHECKPARAMS(1,1);
  2423. delv(params.item(1));
  2424. }
  2425. else if (stricmp(cmd,"count")==0) {
  2426. CHECKPARAMS(1,1);
  2427. count(params.item(1));
  2428. }
  2429. else if (stricmp(cmd,"dfsfile")==0) {
  2430. CHECKPARAMS(1,1);
  2431. dfsfile(params.item(1),userDesc);
  2432. }
  2433. else if (stricmp(cmd,"dfspart")==0) {
  2434. CHECKPARAMS(2,2);
  2435. dfspart(params.item(1),userDesc,atoi(params.item(2)));
  2436. }
  2437. else if (stricmp(cmd,"dfscsv")==0) {
  2438. CHECKPARAMS(1,1);
  2439. dfscsv(params.item(1),userDesc);
  2440. }
  2441. else if (stricmp(cmd,"dfsgroup")==0) {
  2442. CHECKPARAMS(1,2);
  2443. dfsgroup(params.item(1),(np>1)?params.item(2):NULL);
  2444. }
  2445. else if (stricmp(cmd,"dfsmap")==0) {
  2446. CHECKPARAMS(1,1);
  2447. dfsmap(params.item(1), userDesc);
  2448. }
  2449. else if (stricmp(cmd,"dfsexist")==0) {
  2450. CHECKPARAMS(1,1);
  2451. ret = dfsexists(params.item(1),userDesc);
  2452. }
  2453. else if (stricmp(cmd,"dfsparents")==0) {
  2454. CHECKPARAMS(1,1);
  2455. dfsparents(params.item(1),userDesc);
  2456. }
  2457. else if (stricmp(cmd,"dfsunlink")==0) {
  2458. CHECKPARAMS(1,1);
  2459. dfsunlink(params.item(1),userDesc);
  2460. }
  2461. else if (stricmp(cmd,"dfsverify")==0) {
  2462. CHECKPARAMS(1,1);
  2463. ret = dfsverify(params.item(1),NULL,userDesc);
  2464. }
  2465. else if (stricmp(cmd,"setprotect")==0) {
  2466. CHECKPARAMS(2,2);
  2467. setprotect(params.item(1),params.item(2),userDesc);
  2468. }
  2469. else if (stricmp(cmd,"unprotect")==0) {
  2470. CHECKPARAMS(2,2);
  2471. unprotect(params.item(1),params.item(2),userDesc);
  2472. }
  2473. else if (stricmp(cmd,"listprotect")==0) {
  2474. CHECKPARAMS(0,2);
  2475. listprotect((np>1)?params.item(1):"*",(np>2)?params.item(2):"*");
  2476. }
  2477. else if (stricmp(cmd,"checksuperfile")==0) {
  2478. CHECKPARAMS(1,1);
  2479. bool fix = props->getPropBool("fix");
  2480. checksuperfile(params.item(1),fix);
  2481. }
  2482. else if (stricmp(cmd,"checksubfile")==0) {
  2483. CHECKPARAMS(1,1);
  2484. checksubfile(params.item(1));
  2485. }
  2486. else if (stricmp(cmd,"listexpires")==0) {
  2487. CHECKPARAMS(0,1);
  2488. listexpires((np>1)?params.item(1):"*",userDesc);
  2489. }
  2490. else if (stricmp(cmd,"listrelationships")==0) {
  2491. CHECKPARAMS(2,2);
  2492. listrelationships(params.item(1),params.item(2));
  2493. }
  2494. else if (stricmp(cmd,"dfsperm")==0) {
  2495. if (!userDesc.get())
  2496. throw MakeStringException(-1,"dfsperm requires username to be set (user=)");
  2497. CHECKPARAMS(1,1);
  2498. ret = dfsperm(params.item(1),userDesc);
  2499. }
  2500. else if (stricmp(cmd,"dfscompratio")==0) {
  2501. CHECKPARAMS(1,1);
  2502. dfscompratio(params.item(1),userDesc);
  2503. }
  2504. else if (stricmp(cmd,"dfsscopes")==0) {
  2505. CHECKPARAMS(0,1);
  2506. dfsscopes((np>1)?params.item(1):"*",userDesc);
  2507. }
  2508. else if (stricmp(cmd,"cleanscopes")==0) {
  2509. CHECKPARAMS(0,0);
  2510. cleanscopes(userDesc);
  2511. }
  2512. else if (stricmp(cmd,"listworkunits")==0) {
  2513. CHECKPARAMS(0,3);
  2514. listworkunits((np>0)?params.item(1):NULL,(np>1)?params.item(2):NULL,(np>2)?params.item(3):NULL);
  2515. }
  2516. else if (stricmp(cmd,"listmatches")==0) {
  2517. CHECKPARAMS(0,3);
  2518. listmatches((np>0)?params.item(1):NULL,(np>1)?params.item(2):NULL,(np>2)?params.item(3):NULL);
  2519. }
  2520. else if (stricmp(cmd,"workunittimings")==0) {
  2521. CHECKPARAMS(1,1);
  2522. workunittimings(params.item(1));
  2523. }
  2524. else if (stricmp(cmd,"serverlist")==0) {
  2525. CHECKPARAMS(1,1);
  2526. serverlist(params.item(1));
  2527. }
  2528. else if (stricmp(cmd,"clusterlist")==0) {
  2529. CHECKPARAMS(1,1);
  2530. clusterlist(params.item(1));
  2531. }
  2532. else if (stricmp(cmd,"auditlog")==0) {
  2533. CHECKPARAMS(2,3);
  2534. auditlog(params.item(1),params.item(2),(np>2)?params.item(3):NULL);
  2535. }
  2536. else if (stricmp(cmd,"coalesce")==0) {
  2537. CHECKPARAMS(0,0);
  2538. coalesce();
  2539. }
  2540. else if (stricmp(cmd,"mpping")==0) {
  2541. CHECKPARAMS(1,1);
  2542. mpping(params.item(1));
  2543. }
  2544. else if (stricmp(cmd,"daliping")==0) {
  2545. CHECKPARAMS(0,1);
  2546. daliping(daliserv.str(),daliconnectelapsed,(np>0)?atoi(params.item(1)):1);
  2547. }
  2548. else if (stricmp(cmd,"getxref")==0) {
  2549. CHECKPARAMS(1,1);
  2550. getxref(params.item(1));
  2551. }
  2552. else if (stricmp(cmd,"dalilocks")==0) {
  2553. CHECKPARAMS(0,2);
  2554. bool filesonly = false;
  2555. if (np&&(stricmp(params.item(np),"files")==0)) {
  2556. filesonly = true;
  2557. np--;
  2558. }
  2559. dalilocks(np>0?params.item(1):NULL,filesonly);
  2560. }
  2561. else if (stricmp(cmd,"unlock")==0) {
  2562. CHECKPARAMS(1,1);
  2563. unlock(params.item(1));
  2564. }
  2565. else if (stricmp(cmd,"validateStore")==0) {
  2566. CHECKPARAMS(0,2);
  2567. bool fix = props->getPropBool("fix");
  2568. bool verbose = props->getPropBool("verbose");
  2569. bool deleteFiles = props->getPropBool("deletefiles");
  2570. validateStore(fix, deleteFiles, verbose);
  2571. }
  2572. else if (stricmp(cmd,"wuidCompress")==0) {
  2573. CHECKPARAMS(2,2);
  2574. wuidCompress(params.item(1), params.item(2), true);
  2575. }
  2576. else if (stricmp(cmd,"wuidDecompress")==0) {
  2577. CHECKPARAMS(2,2);
  2578. wuidCompress(params.item(1), params.item(2), false);
  2579. }
  2580. else
  2581. ERRLOG("Unknown command %s",cmd);
  2582. }
  2583. catch (IException *e) {
  2584. EXCLOG(e,"daliadmin");
  2585. e->Release();
  2586. }
  2587. closedownClientProcess();
  2588. }
  2589. }
  2590. }
  2591. setDaliServixSocketCaching(false);
  2592. setNodeCaching(false);
  2593. releaseAtoms();
  2594. fflush(stdout);
  2595. fflush(stderr);
  2596. return ret;
  2597. }