ws_packageprocessService.cpp 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  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_packageprocessService.hpp"
  15. #include "daclient.hpp"
  16. #include "dalienv.hpp"
  17. #include "dadfs.hpp"
  18. #include "dfuutil.hpp"
  19. #include "ws_fs.hpp"
  20. #include "ws_workunits.hpp"
  21. #include "packageprocess_errors.h"
  22. #include "referencedfilelist.hpp"
  23. #include "package.h"
  24. #include "eclwatch_errorlist.hpp"
  25. #define SDS_LOCK_TIMEOUT (5*60*1000) // 5mins, 30s a bit short
  26. void CWsPackageProcessEx::init(IPropertyTree *cfg, const char *process, const char *service)
  27. {
  28. packageMapAndSet.subscribe();
  29. }
  30. bool CWsPackageProcessEx::onEcho(IEspContext &context, IEspEchoRequest &req, IEspEchoResponse &resp)
  31. {
  32. StringBuffer respMsg;
  33. ISecUser* user = context.queryUser();
  34. if(user != NULL)
  35. {
  36. const char* name = user->getName();
  37. if (name && *name)
  38. respMsg.appendf("%s: ", name);
  39. }
  40. const char* reqMsg = req.getRequest();
  41. if (reqMsg && *reqMsg)
  42. respMsg.append(reqMsg);
  43. else
  44. respMsg.append("??");
  45. resp.setResponse(respMsg.str());
  46. return true;
  47. }
  48. inline StringBuffer &buildPkgSetId(StringBuffer &id, const char *process)
  49. {
  50. if (!process || !*process)
  51. process = "*";
  52. return id.append("default_").append(process).replace('*', '#').replace('?', '~');
  53. }
  54. IPropertyTree *getPkgSetRegistry(const char *process, bool readonly)
  55. {
  56. Owned<IRemoteConnection> globalLock = querySDS().connect("/PackageSets/", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  57. if (!globalLock)
  58. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to connect to PackageSet information in dali /PackageSets");
  59. IPropertyTree *pkgSets = globalLock->queryRoot();
  60. if (!pkgSets)
  61. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to open PackageSet information in dali /PackageSets");
  62. if (!process || !*process)
  63. process = "*";
  64. StringBuffer id;
  65. buildPkgSetId(id, process);
  66. //Only lock the branch for the target we're interested in.
  67. VStringBuffer xpath("/PackageSets/PackageSet[@id='%s']", id.str());
  68. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), readonly ? RTM_LOCK_READ : RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  69. if (!conn)
  70. {
  71. if (readonly)
  72. return NULL;
  73. Owned<IPropertyTree> pkgSet = createPTree();
  74. pkgSet->setProp("@id", id.str());
  75. pkgSet->setProp("@process", process);
  76. pkgSets->addPropTree("PackageSet", pkgSet.getClear());
  77. globalLock->commit();
  78. conn.setown(querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT));
  79. }
  80. return (conn) ? conn->getRoot() : NULL;
  81. }
  82. ////////////////////////////////////////////////////////////////////////////////////////
  83. const unsigned roxieQueryRoxieTimeOut = 60000;
  84. #define SDS_LOCK_TIMEOUT (5*60*1000) // 5mins, 30s a bit short
  85. bool isFileKnownOnCluster(const char *logicalname, IConstWUClusterInfo *clusterInfo, IUserDescriptor* userdesc)
  86. {
  87. Owned<IDistributedFile> dst = queryDistributedFileDirectory().lookup(logicalname, userdesc, true);
  88. if (dst)
  89. {
  90. SCMStringBuffer processName;
  91. clusterInfo->getRoxieProcess(processName);
  92. if (dst->findCluster(processName.str()) != NotFound)
  93. return true; // file already known for this cluster
  94. }
  95. return false;
  96. }
  97. bool isFileKnownOnCluster(const char *logicalname, const char *target, IUserDescriptor* userdesc)
  98. {
  99. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(target);
  100. if (!clusterInfo)
  101. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Could not find information about target cluster %s ", target);
  102. return isFileKnownOnCluster(logicalname, clusterInfo, userdesc);
  103. }
  104. void cloneFileInfoToDali(unsigned updateFlags, StringArray &notFound, IPropertyTree *packageMap, const char *lookupDaliIp, IConstWUClusterInfo *dstInfo, const char *srcCluster, const char *remotePrefix, IUserDescriptor* userdesc, bool allowForeignFiles)
  105. {
  106. StringBuffer user;
  107. StringBuffer password;
  108. if (userdesc)
  109. {
  110. userdesc->getUserName(user);
  111. userdesc->getPassword(password);
  112. }
  113. Owned<IReferencedFileList> wufiles = createReferencedFileList(user, password, allowForeignFiles, false);
  114. wufiles->addFilesFromPackageMap(packageMap);
  115. SCMStringBuffer processName;
  116. dstInfo->getRoxieProcess(processName);
  117. wufiles->resolveFiles(processName.str(), lookupDaliIp, remotePrefix, srcCluster, !(updateFlags & (DALI_UPDATEF_REPLACE_FILE | DALI_UPDATEF_CLONE_FROM)), false, false);
  118. StringBuffer defReplicateFolder;
  119. getConfigurationDirectory(NULL, "data2", "roxie", processName.str(), defReplicateFolder);
  120. Owned<IDFUhelper> helper = createIDFUhelper();
  121. wufiles->cloneAllInfo(updateFlags, helper, true, false, dstInfo->getRoxieRedundancy(), dstInfo->getChannelsPerNode(), dstInfo->getRoxieReplicateOffset(), defReplicateFolder);
  122. Owned<IReferencedFileIterator> iter = wufiles->getFiles();
  123. ForEach(*iter)
  124. {
  125. IReferencedFile &item = iter->query();
  126. if (item.getFlags() & (RefFileNotFound | RefFileNotOnSource))
  127. notFound.append(item.getLogicalName());
  128. }
  129. }
  130. void cloneFileInfoToDali(unsigned updateFlags, StringArray &notFound, IPropertyTree *packageMap, const char *lookupDaliIp, const char *dstCluster, const char *srcCluster, const char *prefix, IUserDescriptor* userdesc, bool allowForeignFiles)
  131. {
  132. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(dstCluster);
  133. if (!clusterInfo)
  134. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Could not find information about target cluster %s ", dstCluster);
  135. cloneFileInfoToDali(updateFlags, notFound, packageMap, lookupDaliIp, clusterInfo, srcCluster, prefix, userdesc, allowForeignFiles);
  136. }
  137. void makePackageActive(IPropertyTree *pkgSet, IPropertyTree *psEntryNew, const char *target, bool activate)
  138. {
  139. if (activate)
  140. {
  141. VStringBuffer xpath("PackageMap[@querySet='%s'][@active='1']", target);
  142. Owned<IPropertyTreeIterator> psEntries = pkgSet->getElements(xpath.str());
  143. ForEach(*psEntries)
  144. {
  145. IPropertyTree &entry = psEntries->query();
  146. if (psEntryNew != &entry)
  147. entry.setPropBool("@active", false);
  148. }
  149. }
  150. if (psEntryNew->getPropBool("@active") != activate)
  151. psEntryNew->setPropBool("@active", activate);
  152. }
  153. void fixPackageMapFileIds(IPropertyTreeIterator *iter, bool preloadAll)
  154. {
  155. if (!iter)
  156. return;
  157. ForEach(*iter)
  158. {
  159. IPropertyTree &item = iter->query();
  160. if (preloadAll)
  161. item.setPropBool("@preload", true);
  162. Owned<IPropertyTreeIterator> superFiles = item.getElements("SuperFile");
  163. ForEach(*superFiles)
  164. {
  165. IPropertyTree &superFile = superFiles->query();
  166. StringBuffer lc(superFile.queryProp("@id"));
  167. const char *id = lc.toLowerCase().str();
  168. if (*id == '~')
  169. id++;
  170. superFile.setProp("@id", id);
  171. Owned<IPropertyTreeIterator> subFiles = superFile.getElements("SubFile");
  172. ForEach(*subFiles)
  173. {
  174. IPropertyTree &subFile = subFiles->query();
  175. id = subFile.queryProp("@value");
  176. if (id && *id == '~')
  177. {
  178. StringAttr value(id+1);
  179. subFile.setProp("@value", value.get());
  180. }
  181. }
  182. }
  183. }
  184. }
  185. void fixPackageMapFileIds(IPropertyTree *pm, bool preloadAll)
  186. {
  187. if (!pm)
  188. return;
  189. Owned<IPropertyTreeIterator> iter = pm->getElements("Package");
  190. fixPackageMapFileIds(iter, preloadAll);
  191. iter.setown(pm->getElements("Part/Package"));
  192. fixPackageMapFileIds(iter, preloadAll);
  193. }
  194. //////////////////////////////////////////////////////////
  195. #define PKGADD_DFS_OVERWRITE 0x0001
  196. #define PKGADD_ALLOW_FOREIGN 0x0002
  197. #define PKGADD_PRELOAD_ALL 0x0004
  198. #define PKGADD_MAP_ACTIVATE 0x0100
  199. #define PKGADD_MAP_CREATE 0x0200
  200. #define PKGADD_MAP_REPLACE 0x0400
  201. #define PKGADD_SEG_ADD 0x1000
  202. #define PKGADD_SEG_REPLACE 0x2000
  203. class PackageMapUpdater
  204. {
  205. public:
  206. Owned<IRemoteConnection> globalLock;
  207. Owned<IUserDescriptor> userdesc;
  208. Owned<IConstWUClusterInfo> clusterInfo;
  209. Owned<IPropertyTree> pmPart;
  210. IPropertyTree *packageMaps;
  211. IPropertyTree *pmExisting;
  212. StringBuffer daliIP;
  213. StringBuffer srcCluster;
  214. StringBuffer prefix;
  215. StringBuffer pmid;
  216. StringBuffer pkgSetId;
  217. StringAttr process;
  218. StringAttr target;
  219. unsigned flags;
  220. PackageMapUpdater() : flags(0), packageMaps(NULL), pmExisting(NULL){}
  221. inline bool checkFlag(unsigned check)
  222. {
  223. return (flags & check) != 0;
  224. }
  225. inline void setFlag(unsigned flag, bool on=true)
  226. {
  227. if (on)
  228. flags |= flag;
  229. }
  230. IConstWUClusterInfo *ensureClusterInfo()
  231. {
  232. clusterInfo.setown(getTargetClusterInfo(target));
  233. if (!clusterInfo)
  234. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Could not find information about target cluster %s ", target.str());
  235. return clusterInfo;
  236. }
  237. void setPMID(const char *_target, const char *name, bool globalScope)
  238. {
  239. if (!name || !*name)
  240. throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "PackageMap name parameter required");
  241. if (!globalScope)
  242. {
  243. target.set(_target);
  244. if (target.isEmpty())
  245. throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "Target cluster parameter required");
  246. ensureClusterInfo();
  247. pmid.append(target).append("::");
  248. }
  249. pmid.append(name);
  250. pmid.toLowerCase();
  251. }
  252. void setProcess(const char *name)
  253. {
  254. process.set(name);
  255. buildPkgSetId(pkgSetId, process);
  256. }
  257. void setUser(const char *user, const char *password, IEspContext *context)
  258. {
  259. if (user && *user && password && *password)
  260. {
  261. userdesc.setown(createUserDescriptor());
  262. userdesc->set(user, password);
  263. return;
  264. }
  265. if (!context)
  266. return;
  267. setUser(context->queryUserId(), context->queryPassword(), nullptr);
  268. }
  269. void setDerivedDfsLocation(const char *dfsLocation, const char *srcProcess)
  270. {
  271. splitDerivedDfsLocation(dfsLocation, srcCluster, daliIP, prefix, srcProcess, srcProcess, NULL, NULL);
  272. if (srcCluster.length())
  273. {
  274. if (!isProcessCluster(daliIP, srcCluster))
  275. throw MakeStringException(PKG_INVALID_CLUSTER_TYPE, "Process cluster %s not found on %s DALI", srcCluster.str(), daliIP.length() ? daliIP.str() : "local");
  276. }
  277. }
  278. void convertExisting()
  279. {
  280. Linked<IPropertyTree> pmPart = pmExisting;
  281. const char *s = strstr(pmid.str(), "::");
  282. if (s)
  283. pmPart->addProp("@id", s+2);
  284. packageMaps->removeTree(pmExisting);
  285. Owned<IPropertyTree> pmTree = createPTree("PackageMap", ipt_ordered);
  286. pmTree->setProp("@id", pmid);
  287. pmTree->setPropBool("@multipart", true);
  288. pmTree->addPropTree("Part", pmPart.getClear());
  289. pmExisting = packageMaps->addPropTree("PackageMap", pmTree.getClear());
  290. }
  291. void init()
  292. {
  293. VStringBuffer xpath("PackageMap[@id='%s']", pmid.str());
  294. globalLock.setown(querySDS().connect("/PackageMaps", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT));
  295. packageMaps = globalLock->queryRoot();
  296. pmExisting = packageMaps->queryPropTree(xpath);
  297. if (pmExisting && !pmExisting->getPropBool("@multipart", false))
  298. convertExisting();
  299. }
  300. void createPart(const char *partname, IPropertyTree *pTree)
  301. {
  302. if (!partname || !*partname)
  303. throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "No PackageMap Part name provided");
  304. if (!pTree)
  305. throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "No PackageMap content provided");
  306. pmPart.set(pTree);
  307. if (!pmPart)
  308. throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "Invalid PackageMap content");
  309. pmPart->addProp("@id", partname);
  310. StringBuffer lcPmid(pmid);
  311. pmid = lcPmid.toLowerCase().str();
  312. fixPackageMapFileIds(pmPart, checkFlag(PKGADD_PRELOAD_ALL));
  313. }
  314. void cloneDfsInfo(unsigned updateFlags, StringArray &filesNotFound, IPropertyTree *pt)
  315. {
  316. cloneFileInfoToDali(updateFlags, filesNotFound, pt, daliIP, ensureClusterInfo(), srcCluster, prefix, userdesc, checkFlag(PKGADD_ALLOW_FOREIGN));
  317. }
  318. void cloneDfsInfo(unsigned updateFlags, StringArray &filesNotFound)
  319. {
  320. cloneDfsInfo(updateFlags, filesNotFound, pmPart);
  321. }
  322. void doCreate(const char *partname, IPropertyTree *pTree, unsigned updateFlags, StringArray &filesNotFound)
  323. {
  324. if (!pTree)
  325. throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "No PackageMap content provided");
  326. Linked<IPropertyTree> pmTree = pTree;
  327. if (pmExisting)
  328. {
  329. if (!checkFlag(PKGADD_MAP_REPLACE))
  330. throw MakeStringException(PKG_NAME_EXISTS, "PackageMap %s already exists, either delete it or specify overwrite", pmid.str());
  331. }
  332. if (pmTree->hasProp("Part"))
  333. {
  334. fixPackageMapFileIds(pmTree, checkFlag(PKGADD_PRELOAD_ALL));
  335. cloneDfsInfo(updateFlags, filesNotFound, pmTree);
  336. }
  337. else
  338. {
  339. createPart(partname, pmTree.getClear()); //this is a part, not a whole packagemap
  340. cloneDfsInfo(updateFlags, filesNotFound, pmPart);
  341. }
  342. if (pmExisting)
  343. packageMaps->removeTree(pmExisting);
  344. if (!pmTree)
  345. {
  346. //wrap part in full PackageMap
  347. pmTree.setown(createPTree("PackageMap", ipt_ordered));
  348. pmTree->setPropBool("@multipart", true);
  349. pmTree->addPropTree("Part", pmPart.getClear());
  350. }
  351. pmTree->setProp("@id", pmid);
  352. packageMaps->addPropTree("PackageMap", pmTree.getClear());
  353. VStringBuffer xpath("PackageMap[@id='%s'][@querySet='%s']", pmid.str(), target.get());
  354. Owned<IPropertyTree> pkgSet = getPkgSetRegistry(process, false);
  355. IPropertyTree *psEntry = pkgSet->queryPropTree(xpath);
  356. if (!psEntry)
  357. {
  358. psEntry = pkgSet->addPropTree("PackageMap", createPTree("PackageMap"));
  359. psEntry->setProp("@id", pmid);
  360. psEntry->setProp("@querySet", target);
  361. }
  362. makePackageActive(pkgSet, psEntry, target, checkFlag(PKGADD_MAP_ACTIVATE));
  363. }
  364. void doCreate(const char *partname, const char *xml, unsigned updateFlags, StringArray &filesNotFound)
  365. {
  366. Owned<IPropertyTree> pTree = createPTreeFromXMLString(xml, ipt_ordered);
  367. doCreate(partname, pTree, updateFlags, filesNotFound);
  368. }
  369. void create(const char *partname, const char *xml, unsigned updateFlags, StringArray &filesNotFound)
  370. {
  371. init();
  372. doCreate(partname, xml, updateFlags, filesNotFound);
  373. }
  374. void copy(IPropertyTree *pm, const char *name, unsigned updateFlags, StringArray &filesNotFound)
  375. {
  376. init();
  377. doCreate(name, pm, updateFlags, filesNotFound);
  378. }
  379. void copy(const char *srcAddress, const char *srcTarget, const char *name, unsigned updateFlags, StringArray &filesNotFound)
  380. {
  381. VStringBuffer url("http://%s/WsPackageProcess", (srcAddress && *srcAddress) ? srcAddress : ".:8010");
  382. Owned<IClientWsPackageProcess> client = createWsPackageProcessClient();
  383. StringBuffer user, pw;
  384. if (userdesc)
  385. client->setUsernameToken(userdesc->getUserName(user), userdesc->getPassword(pw), nullptr);
  386. client->addServiceUrl(url);
  387. StringBuffer scopedPMID;
  388. if (srcTarget && *srcTarget)
  389. scopedPMID.append(srcTarget).append("::");
  390. scopedPMID.append(name);
  391. Owned<IClientGetPackageMapByIdRequest> req = client->createGetPackageMapByIdRequest();
  392. req->rpc().setConnectTimeOutMs(HTTP_CLIENT_DEFAULT_CONNECT_TIMEOUT); //could make configurable, and consider changing read timeout,
  393. //but do so across all copy type methods under a stand alone JIRA
  394. req->setPackageMapId(scopedPMID);
  395. Owned<IClientGetPackageMapByIdResponse> resp = client->GetPackageMapById(req);
  396. if (resp->getExceptions().ordinality())
  397. {
  398. Owned<IMultiException> mE = makeMultiException("ESP");
  399. mE->append(const_cast<IMultiException&>(resp->getExceptions()));
  400. throw mE.getClear();
  401. }
  402. init();
  403. doCreate(name, resp->getInfo(), updateFlags, filesNotFound);
  404. }
  405. void addPart(const char *partname, const char *xml, unsigned updateFlags, StringArray &filesNotFound)
  406. {
  407. init();
  408. if (!pmExisting)
  409. {
  410. doCreate(partname, xml, updateFlags, filesNotFound);
  411. return;
  412. }
  413. Owned<IPropertyTree> pTree = createPTreeFromXMLString(xml, ipt_ordered);
  414. createPart(partname, pTree.getClear());
  415. VStringBuffer xpath("Part[@id='%s']", partname);
  416. IPropertyTree *existingPart = pmExisting->queryPropTree(xpath);
  417. if (existingPart && !checkFlag(PKGADD_SEG_REPLACE))
  418. throw MakeStringException(PKG_NAME_EXISTS, "Package Part %s already exists, remove, or specify 'delete previous'", partname);
  419. cloneDfsInfo(updateFlags, filesNotFound);
  420. if (existingPart)
  421. pmExisting->removeTree(existingPart);
  422. pmExisting->addPropTree("Part", pmPart.getClear());
  423. }
  424. IPropertyTree *ensurePart(const char *partname)
  425. {
  426. if (!pmExisting)
  427. throw MakeStringException(PKG_NAME_EXISTS, "PackageMap %s not found", pmid.str());
  428. VStringBuffer xpath("Part[@id='%s']", partname);
  429. IPropertyTree *existingPart = pmExisting->queryPropTree(xpath);
  430. if (!existingPart)
  431. throw MakeStringException(PKG_NAME_EXISTS, "PackageMap %s Part %s not found", pmid.str(), partname);
  432. return existingPart;
  433. }
  434. void removePart(const char *partname)
  435. {
  436. init();
  437. pmExisting->removeTree(ensurePart(partname));
  438. }
  439. StringBuffer &getPartContent(const char *partname, StringBuffer &content)
  440. {
  441. init();
  442. return toXML(ensurePart(partname), content);
  443. }
  444. };
  445. void getPackageListInfo(IPropertyTree *mapTree, IEspPackageListMapData *pkgList)
  446. {
  447. pkgList->setId(mapTree->queryProp("@id"));
  448. pkgList->setTarget(mapTree->queryProp("@querySet"));
  449. Owned<IPropertyTreeIterator> iter = mapTree->getElements("Package");
  450. IArrayOf<IConstPackageListData> results;
  451. ForEach(*iter)
  452. {
  453. IPropertyTree &item = iter->query();
  454. Owned<IEspPackageListData> res = createPackageListData("", "");
  455. res->setId(item.queryProp("@id"));
  456. if (item.hasProp("@queries"))
  457. res->setQueries(item.queryProp("@queries"));
  458. results.append(*res.getClear());
  459. }
  460. pkgList->setPkgListData(results);
  461. }
  462. void getAllPackageListInfo(IPropertyTree *mapTree, StringBuffer &info)
  463. {
  464. info.append("<PackageMap id='").append(mapTree->queryProp("@id")).append("'");
  465. Owned<IPropertyTreeIterator> iter = mapTree->getElements("Package");
  466. ForEach(*iter)
  467. {
  468. IPropertyTree &item = iter->query();
  469. info.append("<Package id='").append(item.queryProp("@id")).append("'");
  470. if (item.hasProp("@queries"))
  471. info.append(" queries='").append(item.queryProp("@queries")).append("'");
  472. info.append("></Package>");
  473. }
  474. info.append("</PackageMap>");
  475. }
  476. void listPkgInfo(double version, const char *target, const char *process, const IPropertyTree* packageMaps, IPropertyTree* pkgSetRegistry, IArrayOf<IConstPackageListMapData>* results)
  477. {
  478. StringBuffer xpath("PackageMap");
  479. if (target && *target)
  480. xpath.appendf("[@querySet='%s']", target);
  481. Owned<IPropertyTreeIterator> iter = pkgSetRegistry->getElements(xpath.str());
  482. ForEach(*iter)
  483. {
  484. IPropertyTree &item = iter->query();
  485. const char *id = item.queryProp("@id");
  486. if (!id || !*id)
  487. continue;
  488. StringBuffer xpath;
  489. xpath.append("PackageMap[@id='").append(id).append("']");
  490. IPropertyTree *mapTree = packageMaps->queryPropTree(xpath);
  491. if (!mapTree)
  492. continue;
  493. Owned<IEspPackageListMapData> res = createPackageListMapData("", "");
  494. res->setActive(item.getPropBool("@active"));
  495. if (process && *process && (version >= 1.01))
  496. res->setProcess(process);
  497. getPackageListInfo(mapTree, res);
  498. if (target && *target)
  499. res->setTarget(target);
  500. else
  501. res->setTarget(item.queryProp("@querySet"));
  502. results->append(*res.getClear());
  503. }
  504. }
  505. void listPkgInfo(double version, const char *target, const char *process, const IPropertyTree* packageMaps, IArrayOf<IConstPackageListMapData>* results)
  506. {
  507. Owned<IPropertyTree> pkgSetRegistry = getPkgSetRegistry((process && *process) ? process : "*", true);
  508. if (pkgSetRegistry) //will be NULL if no package map
  509. {
  510. listPkgInfo(version, target, process, packageMaps, pkgSetRegistry, results);
  511. }
  512. }
  513. void getPkgInfo(const IPropertyTree *packageMaps, const char *target, const char *process, StringBuffer &info)
  514. {
  515. Owned<IPropertyTree> tree = createPTree("PackageMaps");
  516. Owned<IPropertyTree> pkgSetRegistry = getPkgSetRegistry(process, true);
  517. if (!pkgSetRegistry)
  518. {
  519. toXML(tree, info);
  520. return;
  521. }
  522. StringBuffer xpath("PackageMap[@active='1']");
  523. if (target && *target)
  524. xpath.appendf("[@querySet='%s']", target);
  525. Owned<IPropertyTreeIterator> iter = pkgSetRegistry->getElements(xpath.str());
  526. ForEach(*iter)
  527. {
  528. IPropertyTree &item = iter->query();
  529. const char *id = item.queryProp("@id");
  530. if (id)
  531. {
  532. StringBuffer xpath;
  533. xpath.append("PackageMap[@id='").append(id).append("']");
  534. IPropertyTree *mapTree = packageMaps->queryPropTree(xpath);
  535. if (mapTree)
  536. mergePTree(tree, mapTree);
  537. }
  538. }
  539. toXML(tree, info);
  540. }
  541. bool deletePkgInfo(const char *name, const char *target, const char *process, bool globalScope)
  542. {
  543. Owned<IRemoteConnection> pkgSetsConn = querySDS().connect("/PackageSets/", myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  544. if (!pkgSetsConn)
  545. throw MakeStringException(PKG_NONE_DEFINED, "No package sets defined");
  546. IPropertyTree* packageSets = pkgSetsConn->queryRoot();
  547. StringBuffer pkgSetId;
  548. buildPkgSetId(pkgSetId, process);
  549. VStringBuffer pkgSet_xpath("PackageSet[@id='%s']", pkgSetId.str());
  550. IPropertyTree *pkgSetRegistry = packageSets->queryPropTree(pkgSet_xpath.str());
  551. if (!pkgSetRegistry)
  552. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "No package sets defined for %s", process);
  553. StringBuffer lcTarget(target);
  554. target = lcTarget.toLowerCase().str();
  555. StringBuffer lcName(name);
  556. name = lcName.toLowerCase().str();
  557. Owned<IPropertyTree> mapEntry;
  558. StringBuffer xpath;
  559. if (!globalScope)
  560. {
  561. xpath.appendf("PackageMap[@id='%s::%s'][@querySet='%s']", target, name, target);
  562. mapEntry.setown(pkgSetRegistry->getPropTree(xpath.str()));
  563. }
  564. if (!mapEntry)
  565. {
  566. xpath.clear().appendf("PackageMap[@id='%s'][@querySet='%s']", name, target);
  567. mapEntry.setown(pkgSetRegistry->getPropTree(xpath.str()));
  568. if (!mapEntry)
  569. throw MakeStringException(PKG_DELETE_NOT_FOUND, "Unable to delete %s - information not found", lcName.str());
  570. }
  571. StringAttr pmid(mapEntry->queryProp("@id"));
  572. pkgSetRegistry->removeTree(mapEntry);
  573. xpath.clear().appendf("PackageSet/PackageMap[@id='%s']", pmid.get());
  574. if (!packageSets->hasProp(xpath))
  575. {
  576. Owned<IRemoteConnection> pkgMapsConn = querySDS().connect("/PackageMaps/", myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  577. if (!pkgMapsConn)
  578. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve PackageMaps information from dali [/PackageMaps]");
  579. IPropertyTree *pkgMaps = pkgMapsConn->queryRoot();
  580. if (!pkgMaps)
  581. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve PackageMaps information from dali [/PackageMaps]");
  582. IPropertyTree *mapTree = pkgMaps->queryPropTree(xpath.clear().appendf("PackageMap[@id='%s']", pmid.get()).str());
  583. if (mapTree)
  584. pkgMaps->removeTree(mapTree);
  585. }
  586. return true;
  587. }
  588. void activatePackageMapInfo(const char *target, const char *name, const char *process, bool globalScope, bool activate)
  589. {
  590. if (!target || !*target)
  591. throw MakeStringExceptionDirect(PKG_TARGET_NOT_DEFINED, "No target defined");
  592. if (!name || !*name)
  593. throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "No pmid specified");
  594. Owned<IRemoteConnection> globalLock = querySDS().connect("PackageSets", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  595. if (!globalLock)
  596. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve PackageSets information from dali /PackageSets");
  597. StringBuffer lcTarget(target);
  598. target = lcTarget.toLowerCase().str();
  599. StringBuffer lcName(name);
  600. name = lcName.toLowerCase().str();
  601. IPropertyTree *root = globalLock->queryRoot();
  602. if (!root)
  603. throw MakeStringException(PKG_ACTIVATE_NOT_FOUND, "Unable to retrieve PackageSet information");
  604. StringBuffer pkgSetId;
  605. buildPkgSetId(pkgSetId, process);
  606. VStringBuffer xpath("PackageSet[@id='%s']", pkgSetId.str());
  607. IPropertyTree *pkgSetTree = root->queryPropTree(xpath);
  608. if (pkgSetTree)
  609. {
  610. IPropertyTree *mapTree = NULL;
  611. if (!globalScope)
  612. {
  613. xpath.clear().appendf("PackageMap[@querySet='%s'][@id='%s::%s']", target, target, name);
  614. mapTree = pkgSetTree->queryPropTree(xpath);
  615. }
  616. if (!mapTree)
  617. {
  618. xpath.clear().appendf("PackageMap[@querySet='%s'][@id='%s']", target, name);
  619. mapTree = pkgSetTree->queryPropTree(xpath);
  620. }
  621. if (!mapTree)
  622. throw MakeStringException(PKG_ACTIVATE_NOT_FOUND, "PackageMap %s not found on target %s", name, target);
  623. makePackageActive(pkgSetTree, mapTree, target, activate);
  624. }
  625. }
  626. void PackageMapAndSet::load(const char* path, IPropertyTree* t)
  627. {
  628. Owned<IRemoteConnection> globalLock = querySDS().connect(path, myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  629. if (!globalLock)
  630. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve %s information from dali /%s", path, path);
  631. t->removeProp(path);
  632. IPropertyTree *root = globalLock->queryRoot();
  633. if (root)
  634. t->addPropTree(path, createPTreeFromIPT(root));
  635. }
  636. void PackageMapAndSet::load(unsigned flags)
  637. {
  638. Owned<IPropertyTree> t = createPTreeFromIPT(tree);
  639. if (flags & PMAS_RELOAD_PACKAGE_SET)
  640. load("PackageSets", t);
  641. if (flags & PMAS_RELOAD_PACKAGE_MAP)
  642. load("PackageMaps", t);
  643. tree.setown(t.getClear());
  644. }
  645. bool CWsPackageProcessEx::readPackageMapString(const char *packageMapString, StringBuffer &target, StringBuffer &process, StringBuffer &packageMap)
  646. {
  647. if (!packageMapString || !*packageMapString)
  648. return false;
  649. StringArray plist;
  650. plist.appendListUniq(packageMapString, ",");
  651. if (plist.length() < 3)
  652. return false;
  653. target.set(plist.item(0));
  654. process.set(plist.item(1));
  655. packageMap.set(plist.item(2));
  656. if (!target.length() || !packageMap.length())
  657. return false;
  658. return true;
  659. }
  660. void CWsPackageProcessEx::getPkgInfoById(const char *target, const char *packageMapId, IPropertyTree* tree)
  661. {
  662. if (!packageMapId || !*packageMapId)
  663. return;
  664. StringBuffer scopedPMID;
  665. if (target && *target)
  666. packageMapId = scopedPMID.append(target).append("::").append(packageMapId).str();
  667. Owned<IPropertyTree> packageMaps = packageMapAndSet.getPackageMaps();
  668. if (!packageMaps)
  669. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve information about package maps from dali server");
  670. StringBuffer lcPMID(packageMapId);
  671. packageMapId = lcPMID.toLowerCase().str();
  672. StringBuffer xpath;
  673. xpath.append("PackageMap[@id='").append(packageMapId).append("']");
  674. IPropertyTree *mapTree = packageMaps->queryPropTree(xpath);
  675. if (mapTree)
  676. mergePTree(tree, mapTree);
  677. }
  678. void CWsPackageProcessEx::getPkgInfoById(const char *packageMapId, IPropertyTree* tree)
  679. {
  680. getPkgInfoById(nullptr, packageMapId, tree);
  681. }
  682. bool CWsPackageProcessEx::onAddPackage(IEspContext &context, IEspAddPackageRequest &req, IEspAddPackageResponse &resp)
  683. {
  684. PackageMapUpdater updater;
  685. updater.setFlag(PKGADD_MAP_CREATE);
  686. updater.setFlag(PKGADD_MAP_ACTIVATE, req.getActivate());
  687. updater.setFlag(PKGADD_MAP_REPLACE, req.getOverWrite());
  688. updater.setFlag(PKGADD_ALLOW_FOREIGN, req.getAllowForeignFiles());
  689. updater.setFlag(PKGADD_PRELOAD_ALL, req.getPreloadAllPackages());
  690. updater.setPMID(req.getTarget(), req.getPackageMap(), req.getGlobalScope());
  691. updater.setProcess(req.getProcess());
  692. updater.setUser(context.queryUserId(), context.queryPassword(), nullptr);
  693. updater.setDerivedDfsLocation(req.getDaliIp(), req.getSourceProcess());
  694. unsigned updateFlags = 0;
  695. if (req.getOverWrite())
  696. updateFlags |= (DALI_UPDATEF_PACKAGEMAP | DALI_UPDATEF_REPLACE_FILE | DALI_UPDATEF_CLONE_FROM | DALI_UPDATEF_SUPERFILES);
  697. if (req.getReplacePackageMap())
  698. updateFlags |= DALI_UPDATEF_PACKAGEMAP;
  699. if (req.getUpdateCloneFrom())
  700. updateFlags |= DALI_UPDATEF_CLONE_FROM;
  701. if (req.getUpdateSuperFiles())
  702. updateFlags |= DALI_UPDATEF_SUPERFILES;
  703. if (req.getAppendCluster())
  704. updateFlags |= DALI_UPDATEF_APPEND_CLUSTER;
  705. StringArray filesNotFound;
  706. updater.create(req.getPackageMap(), req.getInfo(), updateFlags, filesNotFound);
  707. resp.setFilesNotFound(filesNotFound);
  708. resp.updateStatus().setCode(0);
  709. resp.updateStatus().setDescription(StringBuffer("Successfully loaded ").append(req.getPackageMap()));
  710. return true;
  711. }
  712. #define PACKAGEMAP_PATH_SEP_CHAR '/'
  713. bool nextPmPathNode(const char *&path, StringBuffer &node)
  714. {
  715. if (*path==PACKAGEMAP_PATH_SEP_CHAR)
  716. path++;
  717. while (*path && *path!=PACKAGEMAP_PATH_SEP_CHAR)
  718. node.append(*path++);
  719. return (*path && *++path);
  720. }
  721. bool splitPMPath(const char *path, StringBuffer &netAddress, StringBuffer &target, StringBuffer *pmid)
  722. {
  723. if (!path || !*path)
  724. return false;
  725. if (*path==PACKAGEMAP_PATH_SEP_CHAR && path[1]==PACKAGEMAP_PATH_SEP_CHAR)
  726. {
  727. path+=2;
  728. if (!nextPmPathNode(path, netAddress))
  729. return false;
  730. }
  731. if (!nextPmPathNode(path, target))
  732. return (pmid==NULL);
  733. if (!pmid)
  734. return false;
  735. if (nextPmPathNode(path, *pmid))
  736. return false; //query path too deep
  737. return true;
  738. }
  739. bool CWsPackageProcessEx::onCopyPackageMap(IEspContext &context, IEspCopyPackageMapRequest &req, IEspCopyPackageMapResponse &resp)
  740. {
  741. PackageMapUpdater updater;
  742. updater.setFlag(PKGADD_MAP_CREATE);
  743. updater.setFlag(PKGADD_MAP_ACTIVATE, req.getActivate());
  744. updater.setFlag(PKGADD_MAP_REPLACE, req.getReplacePackageMap());
  745. updater.setFlag(PKGADD_PRELOAD_ALL, req.getPreloadAllPackages());
  746. updater.setFlag(PKGADD_ALLOW_FOREIGN, true);
  747. updater.setProcess(req.getProcess());
  748. updater.setUser(context.queryUserId(), context.queryPassword(), &context);
  749. updater.setDerivedDfsLocation(req.getDaliIp(), req.getSourceProcess());
  750. unsigned updateFlags = 0;
  751. if (req.getReplacePackageMap())
  752. updateFlags |= DALI_UPDATEF_PACKAGEMAP;
  753. if (req.getUpdateCloneFrom())
  754. updateFlags |= DALI_UPDATEF_CLONE_FROM;
  755. if (req.getUpdateSuperFiles())
  756. updateFlags |= DALI_UPDATEF_SUPERFILES;
  757. if (req.getAppendCluster())
  758. updateFlags |= DALI_UPDATEF_APPEND_CLUSTER;
  759. StringBuffer srcAddress, srcTarget, srcPMID;
  760. if (!splitPMPath(req.getSourcePath(), srcAddress, srcTarget, &srcPMID))
  761. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid source PackageMap path");
  762. const char *requestedPMID = req.getPMID();
  763. if (requestedPMID && *requestedPMID)
  764. updater.setPMID(req.getTarget(), requestedPMID, false);
  765. else
  766. updater.setPMID(req.getTarget(), srcPMID, false);
  767. StringArray filesNotFound;
  768. if (srcAddress && *srcAddress)
  769. updater.copy(srcAddress, srcTarget, srcPMID, updateFlags, filesNotFound);
  770. else
  771. {
  772. Owned<IPropertyTree> tree = createPTree("PackageMaps");
  773. getPkgInfoById(srcTarget, srcPMID, tree);
  774. if (!tree->hasChildren())
  775. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Source PackageMap not found");
  776. updater.copy(tree, srcPMID, updateFlags, filesNotFound);
  777. }
  778. resp.setFilesNotFound(filesNotFound);
  779. resp.updateStatus().setCode(0);
  780. resp.updateStatus().setDescription(StringBuffer("Successfully loaded ").append(srcPMID.str()));
  781. return true;
  782. }
  783. void CWsPackageProcessEx::deletePackage(const char *packageMap, const char *target, const char *process, bool globalScope, StringBuffer &returnMsg, int &returnCode)
  784. {
  785. bool ret = deletePkgInfo(packageMap, target, process, globalScope);
  786. (ret) ? returnMsg.append("Successfully ") : returnMsg.append("Unsuccessfully ");
  787. returnMsg.append("deleted ").append(packageMap).append(" from ").append(target).append(";");
  788. if (!ret)
  789. returnCode = -1;
  790. return;
  791. }
  792. bool CWsPackageProcessEx::onDeletePackage(IEspContext &context, IEspDeletePackageRequest &req, IEspDeletePackageResponse &resp)
  793. {
  794. int returnCode = 0;
  795. StringBuffer returnMsg;
  796. IArrayOf<IConstPackageMapEntry>& packageMaps = req.getPackageMaps();
  797. ForEachItemIn(p, packageMaps)
  798. {
  799. IConstPackageMapEntry& item=packageMaps.item(p);
  800. if (!item.getId() || !*item.getId())
  801. {
  802. returnMsg.appendf("PackageMap[%d]: Package map Id not specified; ", p);
  803. continue;
  804. }
  805. if (!item.getTarget() || !*item.getTarget())
  806. {
  807. returnMsg.appendf("PackageMap[%d]: Target not specified;", p);
  808. continue;
  809. }
  810. StringBuffer target, processName, packageMap;
  811. packageMap.set(item.getId());
  812. target.set(item.getTarget());
  813. if (!item.getProcess() || !*item.getProcess())
  814. processName.set("*");
  815. else
  816. processName.set(item.getProcess());
  817. deletePackage(packageMap.str(), target.str(), processName.str(), req.getGlobalScope(), returnMsg, returnCode);
  818. }
  819. if (!packageMaps.length())
  820. {
  821. StringAttr pkgMap(req.getPackageMap());
  822. StringAttr processName(req.getProcess());
  823. if (!processName.length())
  824. processName.set("*");
  825. deletePackage(pkgMap.get(), req.getTarget(), processName.get(), req.getGlobalScope(), returnMsg, returnCode);
  826. }
  827. resp.updateStatus().setDescription(returnMsg.str());
  828. resp.updateStatus().setCode(returnCode);
  829. return true;
  830. }
  831. bool CWsPackageProcessEx::onActivatePackage(IEspContext &context, IEspActivatePackageRequest &req, IEspActivatePackageResponse &resp)
  832. {
  833. resp.updateStatus().setCode(0);
  834. activatePackageMapInfo(req.getTarget(), req.getPackageMap(), req.getProcess(), req.getGlobalScope(), true);
  835. return true;
  836. }
  837. bool CWsPackageProcessEx::onDeActivatePackage(IEspContext &context, IEspDeActivatePackageRequest &req, IEspDeActivatePackageResponse &resp)
  838. {
  839. resp.updateStatus().setCode(0);
  840. activatePackageMapInfo(req.getTarget(), req.getPackageMap(), req.getProcess(), req.getGlobalScope(), false);
  841. return true;
  842. }
  843. bool CWsPackageProcessEx::onListPackage(IEspContext &context, IEspListPackageRequest &req, IEspListPackageResponse &resp)
  844. {
  845. Owned<IPropertyTree> packageMaps = packageMapAndSet.getPackageMaps();
  846. if (!packageMaps)
  847. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve information about package maps from dali server");
  848. resp.updateStatus().setCode(0);
  849. IArrayOf<IConstPackageListMapData> results;
  850. StringAttr process(req.getProcess());
  851. listPkgInfo(context.getClientVersion(), req.getTarget(), process.length() ? process.get() : "*", packageMaps, &results);
  852. resp.setPkgListMapData(results);
  853. return true;
  854. }
  855. bool CWsPackageProcessEx::onListPackages(IEspContext &context, IEspListPackagesRequest &req, IEspListPackagesResponse &resp)
  856. {
  857. Owned<IPropertyTree> packageMaps = packageMapAndSet.getPackageMaps();
  858. if (!packageMaps)
  859. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve information about package maps from dali server");
  860. double version = context.getClientVersion();
  861. const char* targetReq = req.getTarget();
  862. const char* processReq = req.getProcess();
  863. const char* processFilterReq = req.getProcessFilter();
  864. IArrayOf<IConstPackageListMapData> results;
  865. if ((!processReq || !*processReq) && (processFilterReq && *processFilterReq))
  866. listPkgInfo(version, targetReq, processFilterReq, packageMaps, &results);
  867. else
  868. {
  869. Owned<IPropertyTree> pkgSetRegistryRoot = packageMapAndSet.getPackageSets();
  870. if (!pkgSetRegistryRoot)
  871. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve information about package sets from dali server");
  872. Owned<IPropertyTreeIterator> iter = pkgSetRegistryRoot->getElements("PackageSet");
  873. ForEach(*iter)
  874. {
  875. try
  876. {
  877. Owned<IPropertyTree> pkgSetRegistry= &iter->get();
  878. StringBuffer process;
  879. pkgSetRegistry->getProp("@process", process);
  880. if (process.length() && (streq(process.str(), "*") || WildMatch(process.str(), processReq, true)))
  881. listPkgInfo(version, targetReq, process.str(), packageMaps, pkgSetRegistry, &results);
  882. }
  883. catch(IException* e)
  884. {
  885. int err = e->errorCode();
  886. //Dali throws an exception if packagemap is not available for a process.
  887. if (err == PKG_DALI_LOOKUP_ERROR)
  888. e->Release();
  889. else
  890. throw e;
  891. }
  892. }
  893. if ((version >=1.01) && processReq && *processReq)
  894. {//Show warning if multiple packages are active for the same target.
  895. ForEachItemIn(i, results)
  896. {
  897. IEspPackageListMapData& r1 = (IEspPackageListMapData&) results.item(i);
  898. if (!r1.getActive())
  899. continue;
  900. const char* target1 = r1.getTarget();
  901. for (unsigned ii = i+1; ii<results.length(); ++ii)
  902. {
  903. IEspPackageListMapData& r2 = (IEspPackageListMapData&) results.item(ii);
  904. if (!r2.getActive())
  905. continue;
  906. if (!streq(target1, r2.getTarget()))
  907. continue;
  908. StringBuffer warning;
  909. warning.appendf("Error: package %s is also active.", r1.getId());
  910. r2.setDescription(warning.str());
  911. }
  912. }
  913. }
  914. }
  915. resp.setPackageMapList(results);
  916. resp.updateStatus().setCode(0);
  917. return true;
  918. }
  919. bool CWsPackageProcessEx::onGetPackage(IEspContext &context, IEspGetPackageRequest &req, IEspGetPackageResponse &resp)
  920. {
  921. Owned<IPropertyTree> packageMaps = packageMapAndSet.getPackageMaps();
  922. if (!packageMaps)
  923. throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve information about package maps from dali server");
  924. resp.updateStatus().setCode(0);
  925. StringAttr process(req.getProcess());
  926. StringBuffer info;
  927. getPkgInfo(packageMaps, req.getTarget(), process.length() ? process.get() : "*", info);
  928. resp.setInfo(info);
  929. return true;
  930. }
  931. bool CWsPackageProcessEx::onGetPackageMapById(IEspContext &context, IEspGetPackageMapByIdRequest &req, IEspGetPackageMapByIdResponse &resp)
  932. {
  933. try
  934. {
  935. const char* pkgMapId = req.getPackageMapId();
  936. if (!pkgMapId && !*pkgMapId)
  937. throw MakeStringException(PKG_MISSING_PARAM, "PackageMap Id not specified");
  938. StringBuffer info;
  939. Owned<IPropertyTree> tree = createPTree("PackageMaps");
  940. getPkgInfoById(pkgMapId, tree);
  941. toXML(tree, info);
  942. resp.setInfo(info.str());
  943. resp.updateStatus().setCode(0);
  944. }
  945. catch (IException *e)
  946. {
  947. StringBuffer retMsg;
  948. resp.updateStatus().setDescription(e->errorMessage(retMsg).str());
  949. resp.updateStatus().setCode(-1);
  950. }
  951. return true;
  952. }
  953. bool CWsPackageProcessEx::onValidatePackage(IEspContext &context, IEspValidatePackageRequest &req, IEspValidatePackageResponse &resp)
  954. {
  955. StringArray warnings;
  956. StringArray errors;
  957. StringArray unmatchedQueries;
  958. StringArray unusedPackages;
  959. StringArray unmatchedFiles;
  960. Owned<IHpccPackageSet> set;
  961. Owned<IPropertyTree> mapTree;
  962. const char *target = req.getTarget();
  963. if (!target || !*target)
  964. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Target cluster required");
  965. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(target);
  966. if (!clusterInfo)
  967. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Target cluster not found");
  968. SCMStringBuffer process;
  969. clusterInfo->getRoxieProcess(process);
  970. if (!process.length())
  971. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Roxie process not found");
  972. const char* pmID = req.getPMID();
  973. const char* info = req.getInfo();
  974. if (req.getActive()) //validate active map
  975. {
  976. mapTree.setown(resolveActivePackageMap(process.str(), target, true));
  977. if (!mapTree)
  978. throw MakeStringException(PKG_PACKAGEMAP_NOT_FOUND, "Active package map not found");
  979. }
  980. else if (pmID && *pmID)
  981. {
  982. mapTree.setown(getPackageMapById(req.getGlobalScope() ? NULL : target, pmID, true));
  983. if (!mapTree)
  984. throw MakeStringException(PKG_PACKAGEMAP_NOT_FOUND, "Package map %s not found", pmID);
  985. }
  986. else if (info && *info)
  987. {
  988. mapTree.setown(createPTreeFromXMLString(info));
  989. if (!mapTree)
  990. throw MakeStringException(PKG_LOAD_PACKAGEMAP_FAILED, "Error processing package file content");
  991. fixPackageMapFileIds(mapTree, false);
  992. }
  993. else
  994. {
  995. throw MakeStringException(PKG_PACKAGEMAP_NOT_FOUND, "package map not specified");
  996. }
  997. if (req.getCheckDFS())
  998. {
  999. Owned<IReferencedFileList> pmfiles = createReferencedFileList(context.queryUserId(), context.queryPassword(), true, false);
  1000. pmfiles->addFilesFromPackageMap(mapTree);
  1001. pmfiles->resolveFiles(process.str(), NULL, NULL, NULL, true, false, false);
  1002. Owned<IReferencedFileIterator> files = pmfiles->getFiles();
  1003. StringArray notInDFS;
  1004. ForEach(*files)
  1005. {
  1006. IReferencedFile &file = files->query();
  1007. if (file.getFlags() & RefFileNotFound)
  1008. notInDFS.append(file.getLogicalName());
  1009. }
  1010. resp.updateFiles().setNotInDFS(notInDFS);
  1011. }
  1012. const char *id = mapTree->queryProp("@id");
  1013. Owned<IHpccPackageMap> map = createPackageMapFromPtree(mapTree, target, id);
  1014. if (!map)
  1015. throw MakeStringException(PKG_LOAD_PACKAGEMAP_FAILED, "Error loading package map %s", id);
  1016. StringArray queriesToVerify;
  1017. const char *queryid = req.getQueryIdToVerify();
  1018. if (queryid && *queryid)
  1019. queriesToVerify.append(queryid);
  1020. ForEachItemIn(i, req.getQueriesToVerify())
  1021. {
  1022. queryid = req.getQueriesToVerify().item(i);
  1023. if (queryid && *queryid)
  1024. queriesToVerify.appendUniq(queryid);
  1025. }
  1026. map->validate(queriesToVerify, warnings, errors, unmatchedQueries, unusedPackages, unmatchedFiles);
  1027. resp.setPMID(map->queryPackageId());
  1028. resp.setWarnings(warnings);
  1029. resp.setErrors(errors);
  1030. resp.updateQueries().setUnmatched(unmatchedQueries);
  1031. resp.updatePackages().setUnmatched(unusedPackages);
  1032. resp.updateFiles().setUnmatched(unmatchedFiles);
  1033. resp.updateStatus().setCode(0);
  1034. return true;
  1035. }
  1036. bool CWsPackageProcessEx::onGetPackageMapSelectOptions(IEspContext &context, IEspGetPackageMapSelectOptionsRequest &req, IEspGetPackageMapSelectOptionsResponse &resp)
  1037. {
  1038. try
  1039. {
  1040. bool includeTargets = req.getIncludeTargets();
  1041. bool includeProcesses = req.getIncludeProcesses();
  1042. if (includeTargets || includeProcesses)
  1043. {
  1044. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1045. Owned<IConstEnvironment> env = factory->openEnvironment();
  1046. if (!env)
  1047. throw MakeStringException(PKG_DALI_LOOKUP_ERROR,"Failed to get environment information.");
  1048. Owned<IPropertyTree> root = &env->getPTree();
  1049. IArrayOf<IConstTargetData> targets;
  1050. CConstWUClusterInfoArray clusters;
  1051. getEnvironmentClusterInfo(root, clusters);
  1052. ForEachItemIn(c, clusters)
  1053. {
  1054. SCMStringBuffer str;
  1055. IConstWUClusterInfo &cluster = clusters.item(c);
  1056. Owned<IEspTargetData> target = createTargetData("", "");
  1057. target->setName(cluster.getName(str).str());
  1058. ClusterType clusterType = cluster.getPlatform();
  1059. if (clusterType == ThorLCRCluster)
  1060. target->setType(THORCLUSTER);
  1061. else if (clusterType == RoxieCluster)
  1062. target->setType(ROXIECLUSTER);
  1063. else
  1064. target->setType(HTHORCLUSTER);
  1065. if (!includeProcesses)
  1066. {
  1067. targets.append(*target.getClear());
  1068. continue;
  1069. }
  1070. StringArray processes;
  1071. if (clusterType == ThorLCRCluster)
  1072. {
  1073. const StringArray &thors = cluster.getThorProcesses();
  1074. ForEachItemIn(i, thors)
  1075. {
  1076. const char* process = thors.item(i);
  1077. if (process && *process)
  1078. processes.append(process);
  1079. }
  1080. }
  1081. else if (clusterType == RoxieCluster)
  1082. {
  1083. SCMStringBuffer process;
  1084. cluster.getRoxieProcess(process);
  1085. if (process.length())
  1086. processes.append(process.str());
  1087. }
  1088. else if (clusterType == HThorCluster)
  1089. {
  1090. SCMStringBuffer process;
  1091. cluster.getAgentQueue(process);
  1092. if (process.length())
  1093. processes.append(process.str());
  1094. }
  1095. if (processes.length())
  1096. target->setProcesses(processes);
  1097. targets.append(*target.getClear());
  1098. }
  1099. resp.setTargets(targets);
  1100. }
  1101. if (req.getIncludeProcessFilters())
  1102. {
  1103. StringArray processFilters;
  1104. processFilters.append("*");
  1105. Owned<IPropertyTree> pkgSets = packageMapAndSet.getPackageSets();
  1106. if (pkgSets)
  1107. {
  1108. Owned<IPropertyTreeIterator> iter = pkgSets->getElements("PackageSet");
  1109. ForEach(*iter)
  1110. {
  1111. StringBuffer process;
  1112. iter->query().getProp("@process", process);
  1113. if (process.length() && !processFilters.contains(process.str()))
  1114. processFilters.append(process.str());
  1115. }
  1116. }
  1117. resp.setProcessFilters(processFilters);
  1118. }
  1119. resp.updateStatus().setCode(0);
  1120. }
  1121. catch (IException *e)
  1122. {
  1123. StringBuffer retMsg;
  1124. resp.updateStatus().setDescription(e->errorMessage(retMsg).str());
  1125. resp.updateStatus().setCode(-1);
  1126. }
  1127. return true;
  1128. }
  1129. bool CWsPackageProcessEx::onGetQueryFileMapping(IEspContext &context, IEspGetQueryFileMappingRequest &req, IEspGetQueryFileMappingResponse &resp)
  1130. {
  1131. const char *queryname = req.getQueryName();
  1132. if (!queryname || !*queryname)
  1133. throw MakeStringException(PKG_INVALID_QUERY_NAME, "Query name required");
  1134. const char *target = req.getTarget();
  1135. if (!target || !*target)
  1136. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Target cluster required");
  1137. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(target);
  1138. if (!clusterInfo)
  1139. throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Unable to find target cluster");
  1140. if (clusterInfo->getPlatform()!=RoxieCluster)
  1141. throw MakeStringException(PKG_INVALID_CLUSTER_TYPE, "Roxie target required");
  1142. Owned<IHpccPackageSet> set;
  1143. Owned<IHpccPackageMap> ownedmap;
  1144. const IHpccPackageMap *map = NULL;
  1145. const char *pmid = req.getPMID();
  1146. if (pmid && *pmid)
  1147. {
  1148. Owned<IPropertyTree> pm = getPackageMapById(req.getGlobalScope() ? NULL : target, pmid, true);
  1149. ownedmap.setown(createPackageMapFromPtree(pm, target, pmid));
  1150. if (!ownedmap)
  1151. throw MakeStringException(PKG_LOAD_PACKAGEMAP_FAILED, "Error loading package map %s", req.getPMID());
  1152. map = ownedmap;
  1153. }
  1154. else
  1155. {
  1156. SCMStringBuffer process;
  1157. clusterInfo->getRoxieProcess(process);
  1158. set.setown(createPackageSet(process.str()));
  1159. if (!set)
  1160. throw MakeStringException(PKG_CREATE_PACKAGESET_FAILED, "Unable to create PackageSet");
  1161. map = set->queryActiveMap(target);
  1162. if (!map)
  1163. throw MakeStringException(PKG_PACKAGEMAP_NOT_FOUND, "Active package map not found");
  1164. }
  1165. Owned<IPropertyTree> fileInfo = createPTree();
  1166. map->gatherFileMappingForQuery(queryname, fileInfo);
  1167. StringArray unmappedFiles;
  1168. Owned<IPropertyTreeIterator> it = fileInfo->getElements("File");
  1169. ForEach(*it)
  1170. unmappedFiles.append(it->query().queryProp(NULL));
  1171. resp.setUnmappedFiles(unmappedFiles);
  1172. IArrayOf<IEspSuperFile> superArray;
  1173. it.setown(fileInfo->getElements("SuperFile"));
  1174. ForEach(*it)
  1175. {
  1176. IPropertyTree &superTree = it->query();
  1177. Owned<IEspSuperFile> superItem = createSuperFile();
  1178. superItem->setName(superTree.queryProp("@name"));
  1179. StringArray subArray;
  1180. Owned<IPropertyTreeIterator> subfiles = superTree.getElements("SubFile");
  1181. ForEach(*subfiles)
  1182. subArray.append(subfiles->query().queryProp(NULL));
  1183. superItem->setSubFiles(subArray);
  1184. superArray.append(*superItem.getClear());
  1185. }
  1186. resp.setSuperFiles(superArray);
  1187. return true;
  1188. }
  1189. bool CWsPackageProcessEx::onAddPartToPackageMap(IEspContext &context, IEspAddPartToPackageMapRequest &req, IEspAddPartToPackageMapResponse &resp)
  1190. {
  1191. PackageMapUpdater updater;
  1192. updater.setFlag(PKGADD_SEG_ADD);
  1193. updater.setFlag(PKGADD_SEG_REPLACE, req.getDeletePrevious());
  1194. updater.setFlag(PKGADD_ALLOW_FOREIGN, req.getAllowForeignFiles());
  1195. updater.setFlag(PKGADD_PRELOAD_ALL, req.getPreloadAllPackages());
  1196. updater.setPMID(req.getTarget(), req.getPackageMap(), req.getGlobalScope());
  1197. updater.setProcess(req.getProcess());
  1198. updater.setUser(context.queryUserId(), context.queryPassword(), nullptr);
  1199. updater.setDerivedDfsLocation(req.getDaliIp(), req.getSourceProcess());
  1200. unsigned updateFlags = 0;
  1201. if (req.getDeletePrevious())
  1202. updateFlags |= DALI_UPDATEF_PACKAGEMAP;
  1203. if (req.getUpdateCloneFrom())
  1204. updateFlags |= DALI_UPDATEF_CLONE_FROM;
  1205. if (req.getUpdateSuperFiles())
  1206. updateFlags |= DALI_UPDATEF_SUPERFILES;
  1207. if (req.getAppendCluster())
  1208. updateFlags |= DALI_UPDATEF_APPEND_CLUSTER;
  1209. StringArray filesNotFound;
  1210. updater.addPart(req.getPartName(), req.getContent(), updateFlags, filesNotFound);
  1211. resp.setFilesNotFound(filesNotFound);
  1212. resp.updateStatus().setCode(0);
  1213. resp.updateStatus().setDescription(VStringBuffer("Successfully loaded Part %s to PackageMap %s", req.getPartName(), updater.pmid.str()));
  1214. return true;
  1215. }
  1216. bool CWsPackageProcessEx::onGetPartFromPackageMap(IEspContext &context, IEspGetPartFromPackageMapRequest &req, IEspGetPartFromPackageMapResponse &resp)
  1217. {
  1218. PackageMapUpdater updater;
  1219. updater.setPMID(req.getTarget(), req.getPackageMap(), req.getGlobalScope());
  1220. StringBuffer content;
  1221. resp.setContent(updater.getPartContent(req.getPartName(), content));
  1222. return true;
  1223. }
  1224. bool CWsPackageProcessEx::onRemovePartFromPackageMap(IEspContext &context, IEspRemovePartFromPackageMapRequest &req, IEspRemovePartFromPackageMapResponse &resp)
  1225. {
  1226. PackageMapUpdater updater;
  1227. updater.setPMID(req.getTarget(), req.getPackageMap(), req.getGlobalScope());
  1228. updater.removePart(req.getPartName());
  1229. resp.updateStatus().setCode(0);
  1230. resp.updateStatus().setDescription(VStringBuffer("Successfully removed Part %s from PackageMap %s", req.getPartName(), updater.pmid.str()));
  1231. return true;
  1232. }
  1233. int CWsPackageProcessSoapBindingEx::onFinishUpload(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response,
  1234. const char *service, const char *method, StringArray& fileNames, StringArray& files, IMultiException *meIn)
  1235. {
  1236. if (meIn && (meIn->ordinality() > 0))
  1237. {
  1238. StringBuffer msg;
  1239. WARNLOG("Exception(s) in EspHttpBinding::onFinishUpload - %s", meIn->errorMessage(msg).append('\n').str());
  1240. if ((ctx.getResponseFormat() == ESPSerializationXML) || (ctx.getResponseFormat() == ESPSerializationJSON))
  1241. {
  1242. response->handleExceptions(NULL, meIn, "FileSpray", "UploadFile", NULL);
  1243. return 0;
  1244. }
  1245. else
  1246. return EspHttpBinding::onFinishUpload(ctx, request, response, service, method, fileNames, files, meIn);
  1247. }
  1248. StringBuffer respStr;
  1249. Owned<IEspWsPackageProcess> iserv = (IEspWsPackageProcess*)getService();
  1250. if(iserv == NULL)
  1251. {
  1252. WARNLOG("Exception(s) in %s::%s - Service not available", service, method);
  1253. respStr.append("{\"Code\":-1,\"Exception\":\"Service not available\"}");
  1254. }
  1255. else
  1256. {
  1257. checkRequest(ctx);
  1258. Owned<CAddPackageRequest> esp_request = new CAddPackageRequest(&ctx, "WsPackageProcess", request->queryParameters(), request->queryAttachments());
  1259. Owned<CAddPackageResponse> esp_response = new CAddPackageResponse("WsPackageProcess");
  1260. StringBuffer source;
  1261. source.setf("WsPackageProcess::%s()", method);
  1262. Owned<IMultiException> me = MakeMultiException(source.str());
  1263. try
  1264. {
  1265. if (!files.length())
  1266. throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "Package content not found");
  1267. esp_request->setInfo(files.item(0));
  1268. iserv->onAddPackage(ctx, *esp_request.get(), *esp_response.get());
  1269. }
  1270. catch (IMultiException* mex)
  1271. {
  1272. me->append(*mex);
  1273. mex->Release();
  1274. }
  1275. catch (IException* e)
  1276. {
  1277. me->append(*e);
  1278. }
  1279. catch (...)
  1280. {
  1281. me->append(*MakeStringExceptionDirect(-1, "Unknown Exception"));
  1282. }
  1283. if (!me->ordinality())
  1284. {
  1285. respStr.append("{\"Code\":0,\"Description\":\"Package Map added\"}");
  1286. }
  1287. else
  1288. {
  1289. StringBuffer msg;
  1290. WARNLOG("Exception(s) in %s::%s - %s", service, method, me->errorMessage(msg).str());
  1291. respStr.appendf("{\"Code\":-1,\"Exception\":\"%s\"}", msg.str());
  1292. }
  1293. }
  1294. response->setContent(respStr.str());
  1295. response->setContentType(HTTP_TYPE_APPLICATION_JSON_UTF8);
  1296. response->send();
  1297. return 0;
  1298. }