ws_dfuXRefService.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #pragma warning (disable : 4786)
  14. #include "ws_dfuXRefService.hpp"
  15. #include "dadfs.hpp"
  16. #include "daft.hpp"
  17. #include "wshelpers.hpp"
  18. #include "exception_util.hpp"
  19. #include "package.h"
  20. #include "roxiecontrol.hpp"
  21. static const char* FEATURE_URL = "DfuXrefAccess";
  22. static void appendReplyMessage(bool json, StringBuffer &reply, const char *href,const char *format,...) __attribute__((format(printf, 4, 5)));
  23. static void appendReplyMessage(bool json, StringBuffer &reply, const char *href,const char *format,...)
  24. {
  25. va_list args;
  26. va_start(args, format);
  27. StringBuffer msg;
  28. msg.valist_appendf(format, args);
  29. va_end(args);
  30. StringBuffer fmsg;
  31. const char *s=msg.str();
  32. loop {
  33. char c=*(s++);
  34. if (!c||(c=='\n')) {
  35. Owned<IPropertyTree> tree = createPTree("Message");
  36. tree->addProp("Value",fmsg.str());
  37. if (href) {
  38. tree->addProp("href",href);
  39. href = NULL;
  40. }
  41. if (json)
  42. toJSON(tree,reply);
  43. else
  44. toXML(tree,reply);
  45. if (!c)
  46. break;
  47. fmsg.clear();
  48. }
  49. else
  50. fmsg.append(c);
  51. }
  52. }
  53. static void dfuXrefXMLToJSON(StringBuffer& buf)
  54. {
  55. try
  56. {
  57. Owned<IPropertyTree> result = createPTreeFromXMLString(buf.str());
  58. if (result)
  59. toJSON(result, buf.clear());
  60. else
  61. PROGLOG("dfuXrefXMLToJSON() failed in creating PTree.");
  62. }
  63. catch (IException *e)
  64. {
  65. EXCLOG(e,"dfuXrefXMLToJSON() failed");
  66. e->Release();
  67. }
  68. }
  69. void CWsDfuXRefEx::init(IPropertyTree *cfg, const char *process, const char *service)
  70. {
  71. StringBuffer xpath;
  72. DBGLOG("Initializing %s service [process = %s]", service, process);
  73. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/User", process, service);
  74. cfg->getProp(xpath.str(), user_);
  75. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/Password", process, service);
  76. cfg->getProp(xpath.str(), password_);
  77. if (!daliClientActive())
  78. {
  79. ERRLOG("No Dali Connection Active.");
  80. throw MakeStringException(-1, "No Dali Connection Active. Please Specify a Dali to connect to in you configuration file");
  81. }
  82. XRefNodeManager.setown(CreateXRefNodeFactory());
  83. //Start out builder thread......
  84. m_XRefbuilder.setown(new CXRefExBuilderThread());
  85. m_XRefbuilder->start();
  86. }
  87. bool CWsDfuXRefEx::onDFUXRefArrayAction(IEspContext &context, IEspDFUXRefArrayActionRequest &req, IEspDFUXRefArrayActionResponse &resp)
  88. {
  89. try
  90. {
  91. StringBuffer username;
  92. context.getUserID(username);
  93. Owned<IUserDescriptor> userdesc;
  94. if(username.length() > 0)
  95. {
  96. const char* passwd = context.queryPassword();
  97. userdesc.setown(createUserDescriptor());
  98. userdesc->set(username.str(), passwd);
  99. }
  100. if(*req.getAction() == 0 || *req.getType() == 0 || *req.getCluster() == 0)
  101. {
  102. ERRLOG("Invalid Parameters into CWsDfuXRefEx::onDFUXRefArrayAction");
  103. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Action, cluster, or type not defined.");
  104. }
  105. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  106. if (xRefNode.get() == 0)
  107. {
  108. ERRLOG("Unable to resolve XRef cluster name %s",req.getCluster());
  109. throw MakeStringException(ECLWATCH_CANNOT_RESOLVE_CLUSTER_NAME, "Unable to resolve cluster name %s",req.getCluster());
  110. }
  111. Owned<IXRefFilesNode> _fileNode = getFileNodeInterface(*xRefNode.get(),req.getType());
  112. if (_fileNode.get() == 0)
  113. {
  114. ERRLOG("Unable to find a suitable IXRefFilesNode interface for %s",req.getType());
  115. throw MakeStringException(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "Unable to find a suitable IXRefFilesNode interface for %s",req.getType());
  116. }
  117. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Full, false))
  118. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to run Xref command. Permission denied.");
  119. StringBuffer returnStr,UserName;
  120. const char* ActionType = req.getAction();
  121. ESPSerializationFormat fmt = context.getResponseFormat();
  122. for(unsigned i = 0; i < req.getXRefFiles().length();i++)
  123. {
  124. StringBuffer errstr;
  125. if (strcmp("Delete" ,ActionType) == 0)
  126. {
  127. if (_fileNode->RemovePhysical(req.getXRefFiles().item(i),userdesc,req.getCluster(),errstr))
  128. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Removed Physical part %s",req.getXRefFiles().item(i));
  129. else
  130. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Error(s) removing physical part %s\n%s",req.getXRefFiles().item(i),errstr.str());
  131. }
  132. else if (strcmp("Attach" ,ActionType) == 0)
  133. {
  134. if(_fileNode->AttachPhysical(req.getXRefFiles().item(i),userdesc,req.getCluster(),errstr) )
  135. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Reattached Physical part %s",req.getXRefFiles().item(i));
  136. else
  137. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Error(s) attaching physical part %s\n%s",req.getXRefFiles().item(i),errstr.str());
  138. }
  139. if (strcmp("DeleteLogical" ,ActionType) == 0)
  140. {
  141. // Note we don't want to physically delete 'lost' files - this will end up with orphans on next time round but that is safer
  142. if (_fileNode->RemoveLogical(req.getXRefFiles().item(i),userdesc,req.getCluster(),errstr)) {
  143. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Removed Logical File %s",req.getXRefFiles().item(i));
  144. }
  145. else
  146. appendReplyMessage(fmt==ESPSerializationJSON, returnStr,NULL,"Error(s) removing File %s\n%s",req.getXRefFiles().item(i),errstr.str());
  147. }
  148. }
  149. xRefNode->commit();
  150. resp.setDFUXRefArrayActionResult(returnStr.str());
  151. }
  152. catch(IException* e)
  153. {
  154. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  155. }
  156. return true;
  157. }
  158. IXRefFilesNode* CWsDfuXRefEx::getFileNodeInterface(IXRefNode& XRefNode,const char* nodeType)
  159. {
  160. if (strcmp("Found" ,nodeType) == 0)
  161. return XRefNode.getFoundFiles();
  162. else if (strcmp("Lost" ,nodeType) == 0)
  163. return XRefNode.getLostFiles();
  164. else if (strcmp("Orphan" ,nodeType) == 0)
  165. return XRefNode.getOrphanFiles();
  166. else
  167. WARNLOG("Unrecognized file node type %s",nodeType);
  168. return 0;
  169. }
  170. void CWsDfuXRefEx::readLostFileQueryResult(IEspContext &context, StringBuffer& buf)
  171. {
  172. Owned<IPropertyTree> lostFilesQueryResult = createPTreeFromXMLString(buf.str());
  173. if (!lostFilesQueryResult)
  174. {
  175. PROGLOG("readLostFileQueryResult() failed in creating PTree.");
  176. return;
  177. }
  178. StringBuffer username;
  179. Owned<IUserDescriptor> userdesc;
  180. context.getUserID(username);
  181. if(username.length() > 0)
  182. {
  183. const char* passwd = context.queryPassword();
  184. userdesc.setown(createUserDescriptor());
  185. userdesc->set(username.str(), passwd);
  186. }
  187. Owned<IPropertyTreeIterator> iter = lostFilesQueryResult->getElements("File");
  188. ForEach(*iter)
  189. {
  190. IPropertyTree& item = iter->query();
  191. const char* fileName = item.queryProp("Name");
  192. if (!fileName || !*fileName)
  193. continue;
  194. try
  195. {
  196. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(fileName, userdesc, false, false, false, NULL, 0);
  197. if(df)
  198. item.addPropInt64("Size", queryDistributedFileSystem().getSize(df));
  199. }
  200. catch(IException* e)
  201. {
  202. item.addProp("Status", "Warning: this file may be locked now. It can't be recovered as locked.");
  203. StringBuffer eMsg;
  204. PROGLOG("Exception in readLostFileQueryResult(): %s", e->errorMessage(eMsg).str());
  205. e->Release();
  206. }
  207. }
  208. if (context.getResponseFormat() == ESPSerializationJSON)
  209. toJSON(lostFilesQueryResult, buf.clear());
  210. else
  211. toXML(lostFilesQueryResult, buf.clear());
  212. }
  213. bool CWsDfuXRefEx::onDFUXRefLostFiles(IEspContext &context, IEspDFUXRefLostFilesQueryRequest &req, IEspDFUXRefLostFilesQueryResponse &resp)
  214. {
  215. try
  216. {
  217. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  218. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to read Xref Lost Files. Permission denied.");
  219. if (!req.getCluster() || !*req.getCluster())
  220. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  221. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  222. if (xRefNode.get() == 0)
  223. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  224. StringBuffer buf;
  225. Owned<IXRefFilesNode> _lost = xRefNode->getLostFiles();
  226. if (_lost)
  227. {
  228. _lost->Serialize(buf);
  229. if (!buf.isEmpty())
  230. readLostFileQueryResult(context, buf);
  231. }
  232. resp.setDFUXRefLostFilesQueryResult(buf.str());
  233. }
  234. catch(IException* e)
  235. {
  236. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  237. }
  238. return true;
  239. }
  240. bool CWsDfuXRefEx::onDFUXRefFoundFiles(IEspContext &context, IEspDFUXRefFoundFilesQueryRequest &req, IEspDFUXRefFoundFilesQueryResponse &resp)
  241. {
  242. try
  243. {
  244. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  245. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to read Xref Found Files. Permission denied.");
  246. StringBuffer username;
  247. context.getUserID(username);
  248. if (!req.getCluster() || !*req.getCluster())
  249. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  250. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  251. if (xRefNode.get() == 0)
  252. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  253. StringBuffer buf;
  254. Owned<IXRefFilesNode> _found = xRefNode->getFoundFiles();
  255. if (_found)
  256. {
  257. _found->Serialize(buf);
  258. if (!buf.isEmpty())
  259. {
  260. ESPSerializationFormat fmt = context.getResponseFormat();
  261. if (fmt == ESPSerializationJSON)
  262. dfuXrefXMLToJSON(buf);
  263. }
  264. }
  265. resp.setDFUXRefFoundFilesQueryResult(buf.str());
  266. }
  267. catch(IException* e)
  268. {
  269. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  270. }
  271. return true;
  272. }
  273. bool CWsDfuXRefEx::onDFUXRefOrphanFiles(IEspContext &context, IEspDFUXRefOrphanFilesQueryRequest &req, IEspDFUXRefOrphanFilesQueryResponse &resp)
  274. {
  275. try
  276. {
  277. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  278. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to read Xref Orphan Files. Permission denied.");
  279. StringBuffer username;
  280. context.getUserID(username);
  281. if (!req.getCluster() || !*req.getCluster())
  282. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  283. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  284. if (xRefNode.get() == 0)
  285. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  286. StringBuffer buf;
  287. Owned<IXRefFilesNode> _orphan = xRefNode->getOrphanFiles();
  288. if (_orphan)
  289. {
  290. _orphan->Serialize(buf);
  291. if (!buf.isEmpty())
  292. {
  293. ESPSerializationFormat fmt = context.getResponseFormat();
  294. if (fmt == ESPSerializationJSON)
  295. dfuXrefXMLToJSON(buf);
  296. }
  297. }
  298. resp.setDFUXRefOrphanFilesQueryResult(buf.str());
  299. }
  300. catch(IException* e)
  301. {
  302. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  303. }
  304. return true;
  305. }
  306. bool CWsDfuXRefEx::onDFUXRefMessages(IEspContext &context, IEspDFUXRefMessagesQueryRequest &req, IEspDFUXRefMessagesQueryResponse &resp)
  307. {
  308. try
  309. {
  310. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  311. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to get Xref Messages. Permission denied.");
  312. StringBuffer username;
  313. context.getUserID(username);
  314. if (!req.getCluster() || !*req.getCluster())
  315. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  316. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  317. if (xRefNode.get() == 0)
  318. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  319. StringBuffer buf;
  320. xRefNode->serializeMessages(buf);
  321. if (!buf.isEmpty())
  322. {
  323. ESPSerializationFormat fmt = context.getResponseFormat();
  324. if (fmt == ESPSerializationJSON)
  325. dfuXrefXMLToJSON(buf);
  326. }
  327. resp.setDFUXRefMessagesQueryResult(buf.str());
  328. }
  329. catch(IException* e)
  330. {
  331. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  332. }
  333. return true;
  334. }
  335. bool CWsDfuXRefEx::onDFUXRefCleanDirectories(IEspContext &context, IEspDFUXRefCleanDirectoriesRequest &req, IEspDFUXRefCleanDirectoriesResponse &resp)
  336. {
  337. try
  338. {
  339. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Write, false))
  340. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to clean Xref Directories. Permission denied.");
  341. StringBuffer username;
  342. context.getUserID(username);
  343. if (!req.getCluster() || !*req.getCluster())
  344. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  345. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  346. if (xRefNode.get() == 0)
  347. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  348. StringBuffer buf;
  349. xRefNode->removeEmptyDirectories(buf);
  350. resp.setRedirectUrl(StringBuffer("/WsDFUXRef/DFUXRefDirectories?Cluster=").append(req.getCluster()));
  351. }
  352. catch(IException* e)
  353. {
  354. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  355. }
  356. return true;
  357. }
  358. bool CWsDfuXRefEx::onDFUXRefDirectories(IEspContext &context, IEspDFUXRefDirectoriesQueryRequest &req, IEspDFUXRefDirectoriesQueryResponse &resp)
  359. {
  360. try
  361. {
  362. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  363. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to get Xref Directories. Permission denied.");
  364. StringBuffer username;
  365. context.getUserID(username);
  366. if (!req.getCluster() || !*req.getCluster())
  367. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  368. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  369. if (xRefNode.get() == 0)
  370. throw MakeStringExceptionDirect(ECLWATCH_CANNOT_FIND_IXREFFILESNODE, "XRefNode not found.");
  371. StringBuffer buf, buf0;
  372. xRefNode->serializeDirectories(buf0);
  373. if (!buf0.isEmpty())
  374. {
  375. Owned <IPropertyTree> dirs = createPTreeFromXMLString(buf0.str()); // Why are we doing this?
  376. if (!dirs)
  377. throw MakeStringExceptionDirect(ECLWATCH_INVALID_COMPONENT_INFO, "Failed in creating PTree for XRefNode Directories.");
  378. Owned<IPropertyTreeIterator> iter = dirs->getElements("Directory");
  379. ForEach(*iter)
  380. {
  381. IPropertyTree &node = iter->query();
  382. StringBuffer positive, negative;
  383. char* skew = (char*) node.queryProp("Skew");
  384. if (!skew || !*skew)
  385. continue;
  386. char* skewPtr = strchr(skew, '/');
  387. if (skewPtr)
  388. {
  389. if (skew[0] == '+' && (strlen(skew) > 1))
  390. positive.append(skewPtr - skew - 1, skew+1);
  391. else
  392. positive.append(skewPtr - skew, skew);
  393. skewPtr++;
  394. if (skewPtr)
  395. {
  396. if (skewPtr[0] == '-')
  397. negative.append(skewPtr+1);
  398. else
  399. negative.append(skewPtr);
  400. }
  401. }
  402. else
  403. {
  404. if (skew[0] == '+' && (strlen(skew) > 1))
  405. positive.append(skew+1);
  406. else
  407. positive.append(skew);
  408. }
  409. node.removeProp("Skew");
  410. node.addProp("PositiveSkew", positive);
  411. node.addProp("NegativeSkew", negative);
  412. }
  413. ESPSerializationFormat fmt = context.getResponseFormat();
  414. if (fmt == ESPSerializationJSON)
  415. toJSON(dirs, buf);
  416. else
  417. toXML(dirs, buf);
  418. }
  419. resp.setDFUXRefDirectoriesQueryResult(buf.str());
  420. }
  421. catch(IException* e)
  422. {
  423. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  424. }
  425. return true;
  426. }
  427. bool CWsDfuXRefEx::onDFUXRefBuild(IEspContext &context, IEspDFUXRefBuildRequest &req, IEspDFUXRefBuildResponse &resp)
  428. {
  429. try
  430. {
  431. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Full, false))
  432. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to build Xref. Permission denied.");
  433. StringBuffer username;
  434. context.getUserID(username);
  435. if (!req.getCluster() || !*req.getCluster())
  436. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "Cluster not defined.");
  437. //create the node if it doesn;t exist
  438. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(req.getCluster());
  439. if (xRefNode.get() == 0)
  440. {
  441. xRefNode.setown( XRefNodeManager->CreateXRefNode(req.getCluster()));
  442. }
  443. StringBuffer returnStr;
  444. ESPSerializationFormat fmt = context.getResponseFormat();
  445. if (m_XRefbuilder->IsQueued(req.getCluster()) )
  446. appendReplyMessage(fmt == ESPSerializationJSON, returnStr,"/WsDFUXRef/DFUXRefList","An XRef build for cluster %s is in process. Click here to return to the main XRef List.",req.getCluster());
  447. else if (!m_XRefbuilder->IsRunning())
  448. appendReplyMessage(fmt == ESPSerializationJSON, returnStr,"/WsDFUXRef/DFUXRefList","Running XRef Process. Click here to return to the main XRef List.");
  449. else
  450. appendReplyMessage(fmt == ESPSerializationJSON, returnStr,"/WsDFUXRef/DFUXRefList","someone is currently running a Xref build. Your request will be added to the queue. Please click here to return to the main page.");
  451. m_XRefbuilder->QueueRequest(xRefNode,req.getCluster());
  452. resp.setDFUXRefActionResult(returnStr.str());
  453. }
  454. catch(IException* e)
  455. {
  456. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  457. }
  458. return true;
  459. }
  460. bool CWsDfuXRefEx::onDFUXRefBuildCancel(IEspContext &context, IEspDFUXRefBuildCancelRequest &req, IEspDFUXRefBuildCancelResponse &resp)
  461. {
  462. try
  463. {
  464. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Full, false))
  465. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to cancel Xref Build. Permission denied.");
  466. StringBuffer username;
  467. context.getUserID(username);
  468. m_XRefbuilder->Cancel();
  469. StringBuffer returnStr;
  470. ESPSerializationFormat fmt = context.getResponseFormat();
  471. if (fmt == ESPSerializationJSON)
  472. {
  473. returnStr.append("{ \"Message\": { \"Value\": ");
  474. returnStr.append("\"All Queued items have been cleared. The current running job will continue to execute.\",");
  475. returnStr.append("\"href\": \"/WsDFUXRef/DFUXRefList\" } }");
  476. }
  477. else
  478. returnStr.appendf("<Message><Value>All Queued items have been cleared. The current running job will continue to execute.</Value><href>/WsDFUXRef/DFUXRefList</href></Message>");
  479. resp.setDFUXRefBuildCancelResult(returnStr.str());
  480. }
  481. catch(IException* e)
  482. {
  483. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  484. }
  485. return true;
  486. }
  487. void CWsDfuXRefEx::addXRefNode(const char* name, IPropertyTree* pXRefNodeTree)
  488. {
  489. IPropertyTree* XRefTreeNode = pXRefNodeTree->addPropTree("XRefNode", createPTree(ipt_caseInsensitive));
  490. XRefTreeNode->setProp("Name",name);
  491. Owned<IXRefNode> xRefNode = XRefNodeManager->getXRefNode(name);
  492. if (!xRefNode)
  493. {
  494. XRefTreeNode->setProp("Modified","");
  495. XRefTreeNode->setProp("Status","Not Run");
  496. }
  497. else
  498. {
  499. StringBuffer modified, status;
  500. XRefTreeNode->setProp("Modified",xRefNode->getLastModified(modified).str());
  501. XRefTreeNode->setProp("Status",xRefNode->getStatus(status).str());
  502. }
  503. }
  504. bool CWsDfuXRefEx::onDFUXRefList(IEspContext &context, IEspDFUXRefListRequest &req, IEspDFUXRefListResponse &resp)
  505. {
  506. try
  507. {
  508. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  509. throw MakeStringException(ECLWATCH_DFU_XREF_ACCESS_DENIED, "Failed to access Xref. Permission denied.");
  510. StringBuffer username;
  511. context.getUserID(username);
  512. CConstWUClusterInfoArray clusters;
  513. getEnvironmentClusterInfo(clusters);
  514. BoolHash uniqueProcesses;
  515. Owned<IPropertyTree> pXRefNodeTree = createPTree("XRefNodes");
  516. ForEachItemIn(c, clusters)
  517. {
  518. IConstWUClusterInfo &cluster = clusters.item(c);
  519. const StringArray &primaryThorProcesses = cluster.getPrimaryThorProcesses();
  520. ForEachItemIn(i,primaryThorProcesses)
  521. {
  522. const char *thorProcess = primaryThorProcesses.item(i);
  523. if (!thorProcess || !*thorProcess)
  524. continue;
  525. bool* found = uniqueProcesses.getValue(thorProcess);
  526. if (found && *found)
  527. continue;
  528. uniqueProcesses.setValue(thorProcess, true);
  529. addXRefNode(thorProcess, pXRefNodeTree);
  530. }
  531. }
  532. addXRefNode("SuperFiles", pXRefNodeTree);
  533. StringBuffer buf;
  534. ESPSerializationFormat fmt = context.getResponseFormat();
  535. if (fmt == ESPSerializationJSON)
  536. resp.setDFUXRefListResult(toJSON(pXRefNodeTree, buf).str());
  537. else
  538. resp.setDFUXRefListResult(toXML(pXRefNodeTree, buf).str());
  539. }
  540. catch(IException* e)
  541. {
  542. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  543. }
  544. return true;
  545. }
  546. inline const char *skipTilda(const char *lfn) //just in case
  547. {
  548. if (lfn)
  549. while (*lfn == '~' || *lfn == ' ')
  550. lfn++;
  551. return lfn;
  552. }
  553. inline void addLfnToUsedFileMap(MapStringTo<bool> &usedFileMap, const char *lfn)
  554. {
  555. lfn = skipTilda(lfn);
  556. if (lfn)
  557. usedFileMap.setValue(lfn, true);
  558. }
  559. void addUsedFilesFromPackageMaps(MapStringTo<bool> &usedFileMap, const char *process)
  560. {
  561. Owned<IPropertyTree> packageSet = resolvePackageSetRegistry(process, true);
  562. if (!packageSet)
  563. throw MakeStringException(ECLWATCH_PACKAGEMAP_NOTRESOLVED, "Unable to retrieve package information from dali /PackageMaps");
  564. StringArray pmids;
  565. Owned<IStringIterator> targets = getTargetClusters("RoxieCluster", process);
  566. ForEach(*targets)
  567. {
  568. SCMStringBuffer target;
  569. VStringBuffer xpath("PackageMap[@querySet='%s']", targets->str(target).str());
  570. Owned<IPropertyTreeIterator> activeMaps = packageSet->getElements(xpath);
  571. //Add files referenced in all active maps, for all targets configured for this process cluster
  572. ForEach(*activeMaps)
  573. {
  574. const char *pmid = activeMaps->query().queryProp("@id");
  575. if (!pmids.appendUniq(pmid))
  576. continue;
  577. Owned<IPropertyTree> packageMap = getPackageMapById(pmid, true);
  578. if (packageMap)
  579. {
  580. Owned<IPropertyTreeIterator> subFiles = packageMap->getElements("//SubFile");
  581. ForEach(*subFiles)
  582. addLfnToUsedFileMap(usedFileMap, subFiles->query().queryProp("@value"));
  583. }
  584. }
  585. }
  586. }
  587. void findUnusedFilesInDFS(StringArray &unusedFiles, const char *process, const MapStringTo<bool> &usedFileMap)
  588. {
  589. Owned<IRemoteConnection> globalLock = querySDS().connect("/Files/", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  590. Owned<IPropertyTree> root = globalLock->getRoot();
  591. VStringBuffer xpath("//File[Cluster/@name='%s']/OrigName", process);
  592. Owned<IPropertyTreeIterator> files = root->getElements(xpath);
  593. ForEach(*files)
  594. {
  595. const char *lfn = skipTilda(files->query().queryProp(NULL));
  596. if (lfn && !usedFileMap.getValue(lfn))
  597. unusedFiles.append(lfn);
  598. }
  599. }
  600. bool CWsDfuXRefEx::onDFUXRefUnusedFiles(IEspContext &context, IEspDFUXRefUnusedFilesRequest &req, IEspDFUXRefUnusedFilesResponse &resp)
  601. {
  602. const char *process = req.getProcessCluster();
  603. if (!process || !*process)
  604. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "process cluster, not specified.");
  605. SocketEndpointArray servers;
  606. getRoxieProcessServers(process, servers);
  607. if (!servers.length())
  608. throw MakeStringExceptionDirect(ECLWATCH_INVALID_CLUSTER_INFO, "process cluster, not found.");
  609. Owned<ISocket> sock = ISocket::connect_timeout(servers.item(0), 5000);
  610. Owned<IPropertyTree> controlXrefInfo = sendRoxieControlQuery(sock, "<control:getQueryXrefInfo/>", 5000);
  611. if (!controlXrefInfo)
  612. throw MakeStringExceptionDirect(ECLWATCH_INTERNAL_ERROR, "roxie cluster, not responding.");
  613. MapStringTo<bool> usedFileMap;
  614. Owned<IPropertyTreeIterator> roxieFiles = controlXrefInfo->getElements("//File");
  615. ForEach(*roxieFiles)
  616. addLfnToUsedFileMap(usedFileMap, roxieFiles->query().queryProp("@name"));
  617. if (req.getCheckPackageMaps())
  618. addUsedFilesFromPackageMaps(usedFileMap, process);
  619. StringArray unusedFiles;
  620. findUnusedFilesInDFS(unusedFiles, process, usedFileMap);
  621. resp.setUnusedFileCount(unusedFiles.length());
  622. resp.setUnusedFiles(unusedFiles);
  623. return true;
  624. }