environment.cpp 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416
  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 "jlib.hpp"
  14. #include "environment.hpp"
  15. #include "jptree.hpp"
  16. #include "jexcept.hpp"
  17. #include "jiter.ipp"
  18. #include "jmisc.hpp"
  19. #include "jencrypt.hpp"
  20. #include "jutil.hpp"
  21. #include "mpbase.hpp"
  22. #include "daclient.hpp"
  23. #include "dadfs.hpp"
  24. #include "dafdesc.hpp"
  25. #include "dasds.hpp"
  26. #include "dalienv.hpp"
  27. #include <string>
  28. #include <unordered_map>
  29. #include <tuple>
  30. #define SDS_LOCK_TIMEOUT 30000
  31. #define DEFAULT_DROPZONE_INDEX 1
  32. #define DROPZONE_BY_MACHINE_SUFFIX "-dropzoneByMachine-"
  33. #define DROPZONE_SUFFIX "dropzone-"
  34. #define MACHINE_PREFIX "machine-"
  35. #define SPARKTHOR_SUFFIX "sparkthor-"
  36. static int environmentTraceLevel = 1;
  37. static Owned <IConstEnvironment> cache;
  38. class CLocalEnvironment;
  39. class CConstMachineInfoIterator : public CSimpleInterfaceOf<IConstMachineInfoIterator>
  40. {
  41. public:
  42. CConstMachineInfoIterator();
  43. virtual bool first() override;
  44. virtual bool next() override;
  45. virtual bool isValid() override;
  46. virtual IConstMachineInfo & query() override;
  47. virtual unsigned count() const override;
  48. protected:
  49. Owned<IConstMachineInfo> curr;
  50. Owned<CLocalEnvironment> constEnv;
  51. unsigned index = 1;
  52. unsigned maxIndex = 0;
  53. };
  54. class CConstDropZoneServerInfoIterator : public CSimpleInterfaceOf<IConstDropZoneServerInfoIterator>
  55. {
  56. public:
  57. CConstDropZoneServerInfoIterator(const IConstDropZoneInfo * dropZone);
  58. virtual bool first() override;
  59. virtual bool next() override;
  60. virtual bool isValid() override;
  61. virtual IConstDropZoneServerInfo & query() override;
  62. virtual unsigned count() const override;
  63. protected:
  64. Owned<IConstDropZoneServerInfo> curr;
  65. Owned<CLocalEnvironment> constEnv;
  66. Owned<IPropertyTreeIterator> serverListIt;
  67. unsigned maxIndex = 0;
  68. };
  69. class CConstDropZoneInfoIterator : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
  70. {
  71. public:
  72. CConstDropZoneInfoIterator();
  73. virtual bool first() override;
  74. virtual bool next() override;
  75. virtual bool isValid() override;
  76. virtual IConstDropZoneInfo & query() override;
  77. virtual unsigned count() const override;
  78. protected:
  79. Owned<IConstDropZoneInfo> curr;
  80. Owned<CLocalEnvironment> constEnv;
  81. unsigned index = 1;
  82. unsigned maxIndex = 0;
  83. };
  84. class CConstSparkThorInfoIterator : public CSimpleInterfaceOf<IConstSparkThorInfoIterator>
  85. {
  86. public:
  87. CConstSparkThorInfoIterator();
  88. virtual bool first() override;
  89. virtual bool next() override;
  90. virtual bool isValid() override;
  91. virtual IConstSparkThorInfo & query() override;
  92. virtual unsigned count() const override;
  93. protected:
  94. Owned<IConstSparkThorInfo> curr;
  95. Owned<CLocalEnvironment> constEnv;
  96. unsigned index = 1;
  97. unsigned maxIndex = 0;
  98. };
  99. class CConstInstanceInfoIterator : public CSimpleInterfaceOf<IConstInstanceInfoIterator>
  100. {
  101. public:
  102. CConstInstanceInfoIterator(const CLocalEnvironment * env, IPropertyTreeIterator * itr);
  103. virtual bool first() override;
  104. virtual bool next() override;
  105. virtual bool isValid() override;
  106. virtual IConstInstanceInfo & query() override;
  107. virtual unsigned count() const override;
  108. protected:
  109. Owned<IPropertyTreeIterator> instanceItr;
  110. Owned<IConstInstanceInfo> curr;
  111. const CLocalEnvironment* constEnv;
  112. unsigned index = 1;
  113. unsigned maxIndex = 0;
  114. };
  115. //==========================================================================================
  116. class CConstInstanceInfo;
  117. class CLocalEnvironment : implements IConstEnvironment, public CInterface
  118. {
  119. private:
  120. // NOTE - order is important - we need to construct before p and (especially) destruct after p
  121. Owned<IRemoteConnection> conn;
  122. Owned<IPropertyTree> p;
  123. mutable MapStringToMyClass<IConstEnvBase> cache;
  124. mutable Mutex safeCache;
  125. mutable bool dropZoneCacheBuilt;
  126. mutable bool machineCacheBuilt;
  127. mutable bool sparkThorCacheBuilt;
  128. mutable bool clusterGroupKeyNameCache;
  129. StringBuffer fileAccessUrl;
  130. struct KeyPairMapEntity
  131. {
  132. std::string publicKey, privateKey;
  133. };
  134. mutable std::unordered_map<std::string, KeyPairMapEntity> keyPairMap;
  135. mutable std::unordered_map<std::string, std::string> keyGroupMap;
  136. StringBuffer xPath;
  137. mutable unsigned numOfMachines;
  138. mutable unsigned numOfDropZones;
  139. mutable unsigned numOfSparkThors;
  140. IConstEnvBase * getCache(const char *path) const;
  141. void setCache(const char *path, IConstEnvBase *value) const;
  142. void buildMachineCache() const;
  143. void buildDropZoneCache() const;
  144. void buildSparkThorCache() const;
  145. void init();
  146. mutable bool isDropZoneRestrictionLoaded = false;
  147. mutable bool dropZoneRestrictionEnabled = true;
  148. void ensureClusterGroupKeyMap() const // keyPairMap and keyGroupMap it alters is mutable
  149. {
  150. if (!clusterGroupKeyNameCache)
  151. {
  152. StringBuffer keysDir;
  153. envGetConfigurationDirectory("keys",nullptr, nullptr, keysDir);
  154. Owned<IPropertyTreeIterator> keyPairIt = p->getElements("EnvSettings/Keys/KeyPair");
  155. ForEach(*keyPairIt)
  156. {
  157. IPropertyTree &keyPair = keyPairIt->query();
  158. const char *name = keyPair.queryProp("@name");
  159. const char *publicKeyPath = keyPair.queryProp("@publicKey");
  160. const char *privateKeyPath = keyPair.queryProp("@privateKey");
  161. if (isEmptyString(name))
  162. {
  163. WARNLOG("skipping invalid EnvSettings/Key/KeyPair entry, name not defined");
  164. continue;
  165. }
  166. if (isEmptyString(publicKeyPath) || isEmptyString(privateKeyPath))
  167. {
  168. WARNLOG("skipping invalid EnvSettings/Key/KeyPair entry, name=%s", name);
  169. continue;
  170. }
  171. StringBuffer absPublicKeyPath, absPrivateKeyPath;
  172. if (!isAbsolutePath(publicKeyPath))
  173. {
  174. absPublicKeyPath.append(keysDir);
  175. addPathSepChar(absPublicKeyPath);
  176. absPublicKeyPath.append(publicKeyPath);
  177. }
  178. else
  179. absPublicKeyPath.append(publicKeyPath);
  180. if (!isAbsolutePath(privateKeyPath))
  181. {
  182. absPrivateKeyPath.append(keysDir);
  183. addPathSepChar(absPrivateKeyPath);
  184. absPrivateKeyPath.append(privateKeyPath);
  185. }
  186. else
  187. absPrivateKeyPath.append(privateKeyPath);
  188. keyPairMap[name] = { absPublicKeyPath.str(), absPrivateKeyPath.str() };
  189. }
  190. /* From 7.0.0 until 7.0.6, the <Keys> section of the environment required
  191. * the mappings to be defined as "Cluster" instead of "ClusterGroup" - See: HPCC-21192
  192. */
  193. #define BKWRDCOMPAT_CLUSTER_VS_CLUSTERGROUP
  194. const char *groupKeysPath = "EnvSettings/Keys/ClusterGroup";
  195. #ifdef BKWRDCOMPAT_CLUSTER_VS_CLUSTERGROUP
  196. for (unsigned i=0; i<2; i++) // once for std. "ClusterGroup", 2nd time for legacy "Cluster"
  197. {
  198. #endif
  199. Owned<IPropertyTreeIterator> clusterGroupIter = p->getElements(groupKeysPath);
  200. #ifdef BKWRDCOMPAT_CLUSTER_VS_CLUSTERGROUP
  201. if (clusterGroupIter->first() && keyGroupMap.size()) // NB: always 0 1st time around.
  202. {
  203. WARNLOG("Invalid configuration: mixed 'Keys/ClusterGroup' definitions and legacy 'Keys/Cluster' definitions found, legacy 'Keys/Cluster' definition will be ignored.");
  204. break;
  205. }
  206. #endif
  207. ForEach(*clusterGroupIter)
  208. {
  209. IPropertyTree &clusterGroup = clusterGroupIter->query();
  210. const char *groupName = clusterGroup.queryProp("@name");
  211. if (isEmptyString(groupName))
  212. {
  213. WARNLOG("skipping %s entry with no name", groupKeysPath);
  214. continue;
  215. }
  216. if (clusterGroup.hasProp("@keyPairName"))
  217. {
  218. const char *keyPairName = clusterGroup.queryProp("@keyPairName");
  219. if (isEmptyString(keyPairName))
  220. {
  221. WARNLOG("skipping invalid %s entry, name=%s", groupKeysPath, groupName);
  222. continue;
  223. }
  224. keyGroupMap[groupName] = keyPairName;
  225. }
  226. }
  227. #ifdef BKWRDCOMPAT_CLUSTER_VS_CLUSTERGROUP
  228. groupKeysPath = "EnvSettings/Keys/Cluster";
  229. }
  230. #endif
  231. clusterGroupKeyNameCache = true;
  232. }
  233. }
  234. public:
  235. IMPLEMENT_IINTERFACE;
  236. CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree *x=nullptr, const char* path="Environment");
  237. CLocalEnvironment(const char* path="config.xml");
  238. virtual ~CLocalEnvironment();
  239. virtual IStringVal & getName(IStringVal & str) const;
  240. virtual IStringVal & getXML(IStringVal & str) const;
  241. virtual IPropertyTree & getPTree() const;
  242. virtual IEnvironment& lock() const;
  243. virtual IConstDomainInfo * getDomain(const char * name) const;
  244. virtual IConstMachineInfo * getMachine(const char * name) const;
  245. virtual IConstMachineInfo * getMachineByAddress(const char * machineIp) const;
  246. virtual IConstMachineInfo * getMachineForLocalHost() const;
  247. virtual IConstDropZoneInfo * getDropZone(const char * name) const;
  248. virtual IConstInstanceInfo * getInstance(const char * type, const char * version, const char *domain) const;
  249. virtual CConstInstanceInfo * getInstanceByIP(const char *type, const char *version, IpAddress &ip) const;
  250. virtual IConstComputerTypeInfo * getComputerType(const char * name) const;
  251. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr, const char *defprogname) const;
  252. virtual void preload();
  253. virtual IRemoteConnection* getConnection() const { return conn.getLink(); }
  254. void setXML(const char * logicalName);
  255. const char* getPath() const { return xPath.str(); }
  256. void unlockRemote();
  257. virtual bool isConstEnvironment() const { return true; }
  258. virtual void clearCache();
  259. virtual IConstMachineInfoIterator * getMachineIterator() const;
  260. virtual IConstDropZoneInfoIterator * getDropZoneIteratorByAddress(const char * address) const;
  261. virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const;
  262. virtual IConstDropZoneInfoIterator * getDropZoneIterator() const;
  263. unsigned getNumberOfMachines() const { buildMachineCache(); return numOfMachines; }
  264. IConstMachineInfo * getMachineByIndex(unsigned index) const;
  265. unsigned getNumberOfDropZones() const { buildDropZoneCache(); return numOfDropZones; }
  266. IConstDropZoneInfo * getDropZoneByIndex(unsigned index) const;
  267. bool isDropZoneRestrictionEnabled() const;
  268. virtual const char *getClusterGroupKeyPairName(const char *group) const override
  269. {
  270. synchronized procedure(safeCache);
  271. ensureClusterGroupKeyMap();
  272. return keyGroupMap[group].c_str();
  273. }
  274. virtual const char *getPublicKeyPath(const char *keyPairName) const override
  275. {
  276. synchronized procedure(safeCache);
  277. ensureClusterGroupKeyMap();
  278. return keyPairMap[keyPairName].publicKey.c_str();
  279. }
  280. virtual const char *getPrivateKeyPath(const char *keyPairName) const override
  281. {
  282. synchronized procedure(safeCache);
  283. ensureClusterGroupKeyMap();
  284. return keyPairMap[keyPairName].privateKey.c_str();
  285. }
  286. virtual const char *getFileAccessUrl() const
  287. {
  288. synchronized procedure(safeCache);
  289. return fileAccessUrl.length() ? fileAccessUrl.str() : nullptr;
  290. }
  291. virtual IConstDaFileSrvInfo *getDaFileSrvGroupInfo(const char *name) const override;
  292. virtual IConstSparkThorInfo *getSparkThor(const char *name) const;
  293. virtual IConstSparkThorInfoIterator *getSparkThorIterator() const;
  294. unsigned getNumberOfSparkThors() const { buildSparkThorCache(); return numOfSparkThors; }
  295. IConstSparkThorInfo *getSparkThorByIndex(unsigned index) const;
  296. };
  297. class CLockedEnvironment : implements IEnvironment, public CInterface
  298. {
  299. public:
  300. //note that order of construction/destruction is important
  301. Owned<CLocalEnvironment> c;
  302. Owned<CLocalEnvironment> env;
  303. Owned<CLocalEnvironment> constEnv;
  304. IMPLEMENT_IINTERFACE;
  305. CLockedEnvironment(CLocalEnvironment *_c)
  306. {
  307. Owned<IRemoteConnection> connection = _c->getConnection();
  308. if (connection)
  309. {
  310. constEnv.set(_c); //save original constant environment
  311. //we only wish to allow one party to allow updating the environment.
  312. //
  313. //create a new /NewEnvironment subtree, locked for read/write access for self and entire subtree; delete on disconnect
  314. //
  315. StringBuffer newName("/New");
  316. newName.append(constEnv->getPath());
  317. const unsigned int mode = RTM_CREATE | RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE |
  318. RTM_LOCK_SUB | RTM_DELETE_ON_DISCONNECT;
  319. Owned<IRemoteConnection> conn = querySDS().connect(newName.str(), myProcessSession(), mode, SDS_LOCK_TIMEOUT);
  320. if (conn == nullptr)
  321. {
  322. if (environmentTraceLevel > 0)
  323. PrintLog("Failed to create locked environment %s", newName.str());
  324. throw MakeStringException(-1, "Failed to get a lock on environment /%s", newName.str());
  325. }
  326. //save the locked environment
  327. env.setown(new CLocalEnvironment(conn, nullptr, newName.str()));
  328. //get a lock on the const environment
  329. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  330. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  331. if (conn2 == nullptr)
  332. {
  333. if (environmentTraceLevel > 0)
  334. PrintLog("Failed to lock environment %s", constEnv->getPath());
  335. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  336. }
  337. //copy const environment to our member environment
  338. Owned<IPropertyTree> pSrc = conn2->getRoot();
  339. c.setown( new CLocalEnvironment(nullptr, createPTreeFromIPT(pSrc)));
  340. conn2->rollback();
  341. }
  342. else
  343. {
  344. c.set(_c);
  345. }
  346. }
  347. virtual ~CLockedEnvironment()
  348. {
  349. }
  350. virtual IStringVal & getName(IStringVal & str) const
  351. { return c->getName(str); }
  352. virtual IStringVal & getXML(IStringVal & str) const
  353. { return c->getXML(str); }
  354. virtual IPropertyTree & getPTree() const
  355. { return c->getPTree(); }
  356. virtual IConstDomainInfo * getDomain(const char * name) const
  357. { return c->getDomain(name); }
  358. virtual IConstMachineInfo * getMachine(const char * name) const
  359. { return c->getMachine(name); }
  360. virtual IConstMachineInfo * getMachineByAddress(const char * machineIp) const
  361. { return c->getMachineByAddress(machineIp); }
  362. virtual IConstMachineInfo * getMachineForLocalHost() const
  363. { return c->getMachineForLocalHost(); }
  364. virtual IConstDropZoneInfo * getDropZone(const char * name) const
  365. { return c->getDropZone(name); }
  366. virtual IConstInstanceInfo * getInstance(const char *type, const char *version, const char *domain) const
  367. { return c->getInstance(type, version, domain); }
  368. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr,const char *defprogname) const
  369. { return c->getRunInfo(path, dir, type, version, machineaddr, defprogname); }
  370. virtual IConstComputerTypeInfo * getComputerType(const char * name) const
  371. { return c->getComputerType(name); }
  372. virtual IEnvironment & lock() const
  373. { ((CInterface*)this)->Link(); return *(IEnvironment*)this; }
  374. virtual void commit();
  375. virtual void rollback();
  376. virtual void setXML(const char * pstr)
  377. { c->setXML(pstr); }
  378. virtual void preload()
  379. { c->preload(); }
  380. virtual bool isConstEnvironment() const { return false; }
  381. virtual void clearCache() { c->clearCache(); }
  382. virtual IConstMachineInfoIterator * getMachineIterator() const
  383. { return c->getMachineIterator(); }
  384. virtual IConstDropZoneInfoIterator * getDropZoneIteratorByAddress(const char * address) const
  385. { return c->getDropZoneIteratorByAddress(address); }
  386. virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const
  387. { return c->getDropZoneByAddressPath(netaddress, targetPath); }
  388. virtual IConstDropZoneInfoIterator * getDropZoneIterator() const
  389. { return c->getDropZoneIterator(); }
  390. virtual bool isDropZoneRestrictionEnabled() const
  391. { return c->isDropZoneRestrictionEnabled(); }
  392. virtual const char *getClusterGroupKeyPairName(const char *cluster) const override
  393. { return c->getClusterGroupKeyPairName(cluster); }
  394. virtual const char *getPublicKeyPath(const char *keyPairName) const override
  395. { return c->getPublicKeyPath(keyPairName); }
  396. virtual const char *getPrivateKeyPath(const char *keyPairName) const override
  397. { return c->getPrivateKeyPath(keyPairName); }
  398. virtual const char *getFileAccessUrl() const
  399. { return c->getFileAccessUrl(); }
  400. virtual IConstDaFileSrvInfo *getDaFileSrvGroupInfo(const char *name) const override
  401. { return c->getDaFileSrvGroupInfo(name); }
  402. virtual IConstSparkThorInfo *getSparkThor(const char *name) const
  403. { return c->getSparkThor(name); }
  404. virtual IConstSparkThorInfoIterator *getSparkThorIterator() const
  405. { return c->getSparkThorIterator(); }
  406. };
  407. void CLockedEnvironment::commit()
  408. {
  409. if (constEnv)
  410. {
  411. //get a lock on const environment momentarily
  412. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  413. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  414. if (conn2 == nullptr)
  415. {
  416. if (environmentTraceLevel > 0)
  417. PrintLog("Failed to lock environment %s", constEnv->getPath());
  418. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  419. }
  420. //copy locked environment to const environment
  421. Owned<IPropertyTree> pSrc = &getPTree();
  422. Owned<IPropertyTree> pDst = conn2->queryRoot()->getBranch(nullptr);
  423. // JCS - I think it could (and would be more efficient if it had kept the original read lock connection to Env
  424. // - instead of using NewEnv as lock point, still work on copy, then changeMode of original connect
  425. // - as opposed to current scheme, where it recoonects in write mode and has to lazy fetch original env to update.
  426. // ensures pDst is equal to pSrc, whilst minimizing changes to pDst
  427. try { synchronizePTree(pDst, pSrc); }
  428. catch (IException *) { conn2->rollback(); throw; }
  429. conn2->commit();
  430. }
  431. else
  432. {
  433. Owned<IRemoteConnection> conn = c->getConnection();
  434. conn->commit();
  435. }
  436. }
  437. void CLockedEnvironment::rollback()
  438. {
  439. if (constEnv)
  440. {
  441. //get a lock on const environment momentarily
  442. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  443. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  444. if (conn2 == nullptr)
  445. {
  446. if (environmentTraceLevel > 0)
  447. PrintLog("Failed to lock environment %s", constEnv->getPath());
  448. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  449. }
  450. //copy const environment to locked environment (as it stands now) again losing any changes we made
  451. Owned<IPropertyTree> pSrc = conn2->getRoot();
  452. Owned<IPropertyTree> pDst = &getPTree();
  453. pDst->removeTree( pDst->queryPropTree("Hardware") );
  454. pDst->removeTree( pDst->queryPropTree("Software") );
  455. pDst->removeTree( pDst->queryPropTree("Programs") );
  456. pDst->removeTree( pDst->queryPropTree("Data") );
  457. mergePTree(pDst, pSrc);
  458. conn2->rollback();
  459. }
  460. else
  461. {
  462. Owned<IRemoteConnection> conn = c->getConnection();
  463. conn->rollback();
  464. }
  465. }
  466. //==========================================================================================
  467. // the following class implements notification handler for subscription to dali for environment
  468. // updates by other clients and is used by environment factory below. This also serves as
  469. // a sample self-contained implementation that can be easily tailored for other purposes.
  470. //==========================================================================================
  471. class CSdsSubscription : implements ISDSSubscription, public CInterface
  472. {
  473. public:
  474. CSdsSubscription(IEnvironmentFactory &_factory) : factory(_factory)
  475. {
  476. m_constEnvUpdated = false;
  477. sub_id = factory.subscribe(this);
  478. }
  479. virtual ~CSdsSubscription()
  480. {
  481. /* note that ideally, we would make this class automatically
  482. unsubscribe in this destructor. However, underlying dali client
  483. layer (CDaliSubscriptionManagerStub) links to this object and so
  484. object would not get destroyed just by an application releasing it.
  485. The application either needs to explicitly unsubscribe or close
  486. the environment which unsubscribes during close down. */
  487. }
  488. void unsubscribe()
  489. {
  490. synchronized block(m_mutexEnv);
  491. if (sub_id)
  492. {
  493. factory.unsubscribe(sub_id);
  494. sub_id = 0;
  495. }
  496. }
  497. IMPLEMENT_IINTERFACE;
  498. //another client (like configenv) may have updated the environment and we got notified
  499. //(thanks to our subscription) but don't just reload it yet since this notification is sent on
  500. //another thread asynchronously and we may be actively working with the old environment. Just
  501. //invoke handleEnvironmentChange() when we are ready to invalidate cache in environment factory.
  502. //
  503. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=nullptr)
  504. {
  505. DBGLOG("Environment was updated by another client of Dali server. Invalidating cache.\n");
  506. synchronized block(m_mutexEnv);
  507. m_constEnvUpdated = true;
  508. }
  509. void handleEnvironmentChange()
  510. {
  511. synchronized block(m_mutexEnv);
  512. if (m_constEnvUpdated)
  513. {
  514. Owned<IConstEnvironment> constEnv = factory.openEnvironment();
  515. constEnv->clearCache();
  516. m_constEnvUpdated = false;
  517. }
  518. }
  519. private:
  520. SubscriptionId sub_id;
  521. Mutex m_mutexEnv;
  522. bool m_constEnvUpdated;
  523. IEnvironmentFactory &factory;
  524. };
  525. //==========================================================================================
  526. class CEnvironmentFactory : public CInterface,
  527. implements IEnvironmentFactory, implements IDaliClientShutdown
  528. {
  529. public:
  530. IMPLEMENT_IINTERFACE;
  531. typedef ArrayOf<SubscriptionId> SubscriptionIDs;
  532. SubscriptionIDs subIDs;
  533. Mutex mutex;
  534. Owned<CSdsSubscription> subscription;
  535. CEnvironmentFactory()
  536. {
  537. }
  538. virtual void clientShutdown();
  539. virtual ~CEnvironmentFactory()
  540. {
  541. close(); //just in case it was not explicitly closed
  542. }
  543. virtual IConstEnvironment* openEnvironment()
  544. {
  545. synchronized procedure(mutex);
  546. if (!cache)
  547. {
  548. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  549. if (conn)
  550. cache.setown(new CLocalEnvironment(conn));
  551. }
  552. if (!cache)
  553. throw MakeStringException(0, "Failed to get environment information");
  554. return cache.getLink();
  555. }
  556. virtual IEnvironment* updateEnvironment()
  557. {
  558. Owned<IConstEnvironment> pConstEnv = openEnvironment();
  559. synchronized procedure(mutex);
  560. return &pConstEnv->lock();
  561. }
  562. virtual IEnvironment * loadLocalEnvironmentFile(const char * filename)
  563. {
  564. Owned<IPropertyTree> ptree = createPTreeFromXMLFile(filename, ipt_lowmem);
  565. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(nullptr, ptree);
  566. return new CLockedEnvironment(pLocalEnv);
  567. }
  568. virtual IEnvironment * loadLocalEnvironment(const char * xml)
  569. {
  570. Owned<IPropertyTree> ptree = createPTreeFromXMLString(xml, ipt_lowmem);
  571. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(nullptr, ptree);
  572. return new CLockedEnvironment(pLocalEnv);
  573. }
  574. void close()
  575. {
  576. SubscriptionIDs copySubIDs;
  577. {
  578. synchronized procedure(mutex);
  579. cache.clear();
  580. //save the active subscriptions in another array
  581. //so they can be unsubscribed without causing deadlock
  582. // since ~CSdsSubscription() would ask us to unsubscribe the
  583. //same requiring a mutex lock (copy is a little price for this
  584. //normally small/empty array).
  585. //
  586. ForEachItemIn(i, subIDs)
  587. copySubIDs.append(subIDs.item(i));
  588. subIDs.kill();
  589. }
  590. //now unsubscribe all outstanding subscriptions
  591. //
  592. subscription.clear();
  593. ForEachItemIn(i, copySubIDs)
  594. querySDS().unsubscribe( copySubIDs.item(i) );
  595. }
  596. virtual SubscriptionId subscribe(ISDSSubscription* pSubHandler)
  597. {
  598. SubscriptionId sub_id = querySDS().subscribe("/Environment", *pSubHandler);
  599. synchronized procedure(mutex);
  600. subIDs.append(sub_id);
  601. return sub_id;
  602. }
  603. virtual void unsubscribe(SubscriptionId sub_id)
  604. {
  605. synchronized procedure(mutex);
  606. aindex_t i = subIDs.find(sub_id);
  607. if (i != NotFound)
  608. {
  609. querySDS().unsubscribe(sub_id);
  610. subIDs.remove(i);
  611. }
  612. }
  613. virtual void validateCache()
  614. {
  615. if (!subscription)
  616. subscription.setown( new CSdsSubscription(*this) );
  617. subscription->handleEnvironmentChange();
  618. }
  619. private:
  620. IRemoteConnection* connect(const char *xpath, unsigned flags)
  621. {
  622. return querySDS().connect(xpath, myProcessSession(), flags, SDS_LOCK_TIMEOUT);
  623. }
  624. };
  625. static CEnvironmentFactory *factory=nullptr;
  626. void CEnvironmentFactory::clientShutdown()
  627. {
  628. closeEnvironment();
  629. }
  630. MODULE_INIT(INIT_PRIORITY_ENV_ENVIRONMENT)
  631. {
  632. return true;
  633. }
  634. MODULE_EXIT()
  635. {
  636. ::Release(factory);
  637. }
  638. //==========================================================================================
  639. class CConstEnvBase : public CInterface
  640. {
  641. protected:
  642. const CLocalEnvironment* env; // Not linked - would be circular....
  643. // That could cause problems
  644. Linked<IPropertyTree> root;
  645. public:
  646. CConstEnvBase(const CLocalEnvironment* _env, IPropertyTree *_root)
  647. : env(_env), root(_root)
  648. {
  649. }
  650. IStringVal& getXML(IStringVal &str) const
  651. {
  652. StringBuffer x;
  653. toXML(root->queryBranch("."), x);
  654. str.set(x.str());
  655. return str;
  656. };
  657. IStringVal& getName(IStringVal &str) const
  658. {
  659. str.set(root->queryProp("@name"));
  660. return str;
  661. }
  662. IPropertyTree& getPTree() const
  663. {
  664. return *LINK(root);
  665. }
  666. };
  667. #define IMPLEMENT_ICONSTENVBASE \
  668. virtual IStringVal& getXML(IStringVal &str) const { return CConstEnvBase::getXML(str); } \
  669. virtual IStringVal& getName(IStringVal &str) const { return CConstEnvBase::getName(str); } \
  670. virtual IPropertyTree& getPTree() const { return CConstEnvBase::getPTree(); }
  671. //==========================================================================================
  672. class CConstDomainInfo : public CConstEnvBase, implements IConstDomainInfo
  673. {
  674. public:
  675. IMPLEMENT_IINTERFACE;
  676. IMPLEMENT_ICONSTENVBASE;
  677. CConstDomainInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  678. virtual void getAccountInfo(IStringVal &name, IStringVal &pw) const
  679. {
  680. if (root->hasProp("@username"))
  681. name.set(root->queryProp("@username"));
  682. else
  683. name.clear();
  684. if (root->hasProp("@password"))
  685. {
  686. StringBuffer pwd;
  687. decrypt(pwd, root->queryProp("@password"));
  688. pw.set(pwd.str());
  689. }
  690. else
  691. pw.clear();
  692. }
  693. virtual void getSnmpSecurityString(IStringVal & securityString) const
  694. {
  695. if (root->hasProp("@snmpSecurityString"))
  696. {
  697. StringBuffer sec_string;
  698. decrypt(sec_string, root->queryProp("@snmpSecurityString"));
  699. securityString.set(sec_string.str());
  700. }
  701. else
  702. securityString.set("");
  703. }
  704. virtual void getSSHAccountInfo(IStringVal &name, IStringVal &sshKeyFile, IStringVal& sshKeyPassphrase) const
  705. {
  706. if (root->hasProp("@username"))
  707. name.set(root->queryProp("@username"));
  708. else
  709. name.clear();
  710. if (root->hasProp("@sshKeyFile"))
  711. sshKeyFile.set(root->queryProp("@sshKeyFile"));
  712. else
  713. sshKeyFile.clear();
  714. if (root->hasProp("@sshKeyPassphrase"))
  715. sshKeyPassphrase.set(root->queryProp("@sshKeyPassphrase"));
  716. else
  717. sshKeyPassphrase.clear();
  718. }
  719. };
  720. //==========================================================================================
  721. struct mapOsEnums { EnvMachineOS val; const char *str; };
  722. static EnvMachineOS getEnum(IPropertyTree *p, const char *propname, mapOsEnums *map)
  723. {
  724. const char *v = p->queryProp(propname);
  725. if (v && *v)
  726. {
  727. while (map->str)
  728. {
  729. if (stricmp(v, map->str)==0)
  730. return map->val;
  731. map++;
  732. }
  733. throw MakeStringException(0, "Unknown operating system: \"%s\"", v);
  734. }
  735. return MachineOsUnknown;
  736. }
  737. struct mapStateEnums { EnvMachineState val; const char *str; };
  738. static EnvMachineState getEnum(IPropertyTree *p, const char *propname, mapStateEnums *map)
  739. {
  740. const char *v = p->queryProp(propname);
  741. if (v && *v)
  742. {
  743. while (map->str)
  744. {
  745. if (stricmp(v, map->str)==0)
  746. return map->val;
  747. map++;
  748. }
  749. assertex(!"Unexpected value in getEnum");
  750. }
  751. return MachineStateUnknown;
  752. }
  753. mapOsEnums OperatingSystems[] = {
  754. { MachineOsW2K, "W2K" },
  755. { MachineOsSolaris, "solaris" },
  756. { MachineOsLinux, "linux" },
  757. { MachineOsSize, nullptr }
  758. };
  759. mapStateEnums MachineStates[] = {
  760. { MachineStateAvailable, "Available" },
  761. { MachineStateUnavailable, "Unavailable" },
  762. { MachineStateUnknown, "Unknown" }
  763. };
  764. //==========================================================================================
  765. class CConstMachineInfo : public CConstEnvBase, implements IConstMachineInfo
  766. {
  767. public:
  768. IMPLEMENT_IINTERFACE;
  769. IMPLEMENT_ICONSTENVBASE;
  770. CConstMachineInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  771. virtual IConstDomainInfo* getDomain() const
  772. {
  773. return env->getDomain(root->queryProp("@domain"));
  774. }
  775. virtual IStringVal& getNetAddress(IStringVal &str) const
  776. {
  777. str.set(root->queryProp("@netAddress"));
  778. return str;
  779. }
  780. virtual IStringVal& getDescription(IStringVal &str) const
  781. {
  782. UNIMPLEMENTED;
  783. }
  784. virtual unsigned getNicSpeedMbitSec() const
  785. {
  786. const char * v = root->queryProp("@nicSpeed");
  787. if (v && *v)
  788. return atoi(v);
  789. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  790. if (type)
  791. return type->getNicSpeedMbitSec();
  792. return 0;
  793. }
  794. virtual EnvMachineOS getOS() const
  795. {
  796. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  797. if (os != MachineOsUnknown)
  798. return os;
  799. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  800. if (type)
  801. return type->getOS();
  802. return MachineOsUnknown;
  803. }
  804. virtual EnvMachineState getState() const
  805. {
  806. return getEnum(root, "@state", MachineStates);
  807. }
  808. };
  809. //==========================================================================================
  810. class CConstComputerTypeInfo : public CConstEnvBase, implements IConstComputerTypeInfo
  811. {
  812. public:
  813. IMPLEMENT_IINTERFACE;
  814. IMPLEMENT_ICONSTENVBASE;
  815. CConstComputerTypeInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  816. virtual EnvMachineOS getOS() const
  817. {
  818. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  819. if (os != MachineOsUnknown)
  820. return os;
  821. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  822. if (type && (type.get() != this))
  823. return type->getOS();
  824. return MachineOsUnknown;
  825. }
  826. virtual unsigned getNicSpeedMbitSec() const
  827. {
  828. const char * v = root->queryProp("@nicSpeed");
  829. if (v && *v)
  830. return atoi(v);
  831. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  832. if (type && (type.get() != this))
  833. return type->getNicSpeedMbitSec();
  834. return 0;
  835. }
  836. };
  837. //==========================================================================================
  838. class CConstInstanceInfo : public CConstEnvBase, implements IConstInstanceInfo
  839. {
  840. public:
  841. IMPLEMENT_IINTERFACE;
  842. IMPLEMENT_ICONSTENVBASE;
  843. CConstInstanceInfo(const CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root)
  844. {
  845. }
  846. virtual IConstMachineInfo * getMachine() const
  847. {
  848. return env->getMachine(root->queryProp("@computer"));
  849. }
  850. virtual IStringVal & getEndPoint(IStringVal & str) const
  851. {
  852. SCMStringBuffer ep;
  853. Owned<IConstMachineInfo> machine = getMachine();
  854. if (machine)
  855. {
  856. machine->getNetAddress(ep);
  857. const char *port = root->queryProp("@port");
  858. if (port)
  859. ep.s.append(':').append(port);
  860. }
  861. str.set(ep.str());
  862. return str;
  863. }
  864. virtual IStringVal & getExecutableDirectory(IStringVal & str) const
  865. {
  866. // this is the deploy directory so uses local path separators (I suspect this call is LEGACY now)
  867. SCMStringBuffer ep;
  868. Owned<IConstMachineInfo> machine = getMachine();
  869. if (machine)
  870. {
  871. machine->getNetAddress(ep);
  872. ep.s.insert(0, PATHSEPSTR PATHSEPSTR);
  873. }
  874. ep.s.append(PATHSEPCHAR).append(root->queryProp("@directory"));
  875. str.set(ep.str());
  876. return str;
  877. }
  878. virtual IStringVal & getDirectory(IStringVal & str) const
  879. {
  880. str.set(root->queryProp("@directory"));
  881. return str;
  882. }
  883. virtual bool doGetRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname, bool useprog) const
  884. {
  885. // this is remote path i.e. path should match *target* nodes format
  886. Owned<IConstMachineInfo> machine = getMachine();
  887. if (!machine)
  888. return false;
  889. char psep;
  890. bool appendexe;
  891. switch (machine->getOS())
  892. {
  893. case MachineOsSolaris:
  894. case MachineOsLinux:
  895. psep = '/';
  896. appendexe = false;
  897. break;
  898. default:
  899. psep = '\\';
  900. appendexe = true;
  901. }
  902. StringBuffer tmp;
  903. const char *program = useprog?root->queryProp("@program"):nullptr; // if program specified assume absolute
  904. if (!program||!*program)
  905. {
  906. SCMStringBuffer ep;
  907. machine->getNetAddress(ep);
  908. const char *dir = root->queryProp("@directory");
  909. if (dir)
  910. {
  911. if (isPathSepChar(*dir))
  912. dir++;
  913. if (!*dir)
  914. return false;
  915. tmp.append(psep).append(psep).append(ep.s).append(psep);
  916. do {
  917. if (isPathSepChar(*dir))
  918. tmp.append(psep);
  919. else
  920. tmp.append(*dir);
  921. dir++;
  922. } while (*dir);
  923. if (!isPathSepChar(tmp.charAt(tmp.length()-1)))
  924. tmp.append(psep);
  925. tmp.append(defprogname);
  926. size32_t l = strlen(defprogname);
  927. if (appendexe&&((l<5)||(stricmp(defprogname+l-4,".exe")!=0)))
  928. tmp.append(".exe");
  929. }
  930. program = tmp.str();
  931. }
  932. progpath.set(program);
  933. const char *workd = root->queryProp("@workdir"); // if program specified assume absolute
  934. workdir.set(workd?workd:"");
  935. return true;
  936. }
  937. virtual bool getRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname) const
  938. {
  939. return doGetRunInfo(progpath,workdir,defprogname,true);
  940. }
  941. virtual unsigned getPort() const
  942. {
  943. return root->getPropInt("@port", 0);
  944. }
  945. };
  946. class CConstDropZoneServerInfo : public CConstEnvBase, implements IConstDropZoneServerInfo
  947. {
  948. public:
  949. IMPLEMENT_IINTERFACE;
  950. IMPLEMENT_ICONSTENVBASE;
  951. CConstDropZoneServerInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root), prop(root) {}
  952. virtual StringBuffer & getName(StringBuffer & name) const
  953. {
  954. name.append(prop->queryProp("@name"));
  955. return name;
  956. }
  957. virtual StringBuffer & getServer(StringBuffer & server) const
  958. {
  959. server.append(prop->queryProp("@server"));
  960. return server;
  961. }
  962. private:
  963. IPropertyTree * prop;
  964. };
  965. class CConstDropZoneInfo : public CConstEnvBase, implements IConstDropZoneInfo
  966. {
  967. public:
  968. IMPLEMENT_IINTERFACE;
  969. IMPLEMENT_ICONSTENVBASE;
  970. CConstDropZoneInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root)
  971. {
  972. getStandardPosixPath(posixPath, root->queryProp("@directory"));
  973. }
  974. virtual IStringVal& getComputerName(IStringVal &str) const
  975. {
  976. str.set(root->queryProp("@computer"));
  977. return str;
  978. }
  979. virtual IStringVal& getDescription(IStringVal &str) const
  980. {
  981. str.set(root->queryProp("@description"));
  982. return str;
  983. }
  984. virtual IStringVal& getDirectory(IStringVal &str) const
  985. {
  986. str.set(posixPath.str());
  987. return str;
  988. }
  989. virtual IStringVal& getUMask(IStringVal &str) const
  990. {
  991. if (root->hasProp("@umask"))
  992. str.set(root->queryProp("@umask"));
  993. return str;
  994. }
  995. virtual bool isECLWatchVisible() const
  996. {
  997. return root->getPropBool("@ECLWatchVisible", true);
  998. }
  999. virtual IConstDropZoneServerInfoIterator * getServers() const
  1000. {
  1001. return new CConstDropZoneServerInfoIterator(this);
  1002. }
  1003. private:
  1004. StringBuffer posixPath;
  1005. };
  1006. class CConstSparkThorInfo : public CConstEnvBase, implements IConstSparkThorInfo
  1007. {
  1008. public:
  1009. IMPLEMENT_IINTERFACE;
  1010. IMPLEMENT_ICONSTENVBASE;
  1011. CConstSparkThorInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  1012. virtual IStringVal &getBuild(IStringVal &str) const
  1013. {
  1014. str.set(root->queryProp("@build"));
  1015. return str;
  1016. }
  1017. virtual IStringVal &getThorClusterName(IStringVal &str) const
  1018. {
  1019. str.set(root->queryProp("@ThorClusterName"));
  1020. return str;
  1021. }
  1022. virtual unsigned getSparkExecutorCores() const
  1023. {
  1024. return root->getPropInt("@SPARK_EXECUTOR_CORES", 0);
  1025. }
  1026. virtual unsigned long getSparkExecutorMemory() const
  1027. {
  1028. return readSizeSetting(root->queryProp("@SPARK_EXECUTOR_MEMORY"), 0);
  1029. }
  1030. virtual unsigned getSparkMasterPort() const
  1031. {
  1032. return root->getPropInt("@SPARK_MASTER_PORT", 0);
  1033. }
  1034. virtual unsigned getSparkMasterWebUIPort() const
  1035. {
  1036. return root->getPropInt("@SPARK_MASTER_WEBUI_PORT", 0);
  1037. }
  1038. virtual unsigned getSparkWorkerCores() const
  1039. {
  1040. return root->getPropInt("@SPARK_WORKER_CORES", 0);
  1041. }
  1042. virtual unsigned long getSparkWorkerMemory() const
  1043. {
  1044. return readSizeSetting(root->queryProp("@SPARK_WORKER_MEMORY"), 0);
  1045. }
  1046. virtual unsigned getSparkWorkerPort() const
  1047. {
  1048. return root->getPropInt("@SPARK_WORKER_PORT", 0);
  1049. }
  1050. virtual IConstInstanceInfoIterator *getInstanceIterator() const
  1051. {
  1052. return new CConstInstanceInfoIterator(env, root->getElements("Instance"));
  1053. }
  1054. };
  1055. #if 0
  1056. //==========================================================================================
  1057. class CConstProcessInfo : public CConstEnvBase, implements IConstProcessInfo
  1058. {
  1059. IArrayOf<IConstInstanceInfo> w;
  1060. CArrayIteratorOf<IInterface, IIterator> it;
  1061. public:
  1062. IMPLEMENT_IINTERFACE;
  1063. IMPLEMENT_ICONSTENVBASE;
  1064. CConstProcessInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root), it(w)
  1065. {
  1066. Owned<IPropertyTreeIterator> _it = root->getElements("*"); // MORE - should be instance
  1067. for (_it->first(); _it->isValid(); _it->next())
  1068. {
  1069. IPropertyTree *rp = &_it->query();
  1070. w.append(*new CConstInstanceInfo(env, rp)); // CConstInstanceInfo will link rp
  1071. }
  1072. }
  1073. bool first() { return it.first(); }
  1074. bool isValid() { return it.isValid(); }
  1075. bool next() { return it.next(); }
  1076. IConstInstanceInfo & query() { return (IConstInstanceInfo &) it.query();}
  1077. virtual IConstInstanceInfo * getInstance(const char *domain)
  1078. {
  1079. for (int pass=0; pass<2; pass++)
  1080. {
  1081. ForEachItemIn(idx, w)
  1082. {
  1083. Owned<IConstMachineInfo> m = w.item(idx).getMachine();
  1084. if (m)
  1085. {
  1086. Owned<IConstDomainInfo> dm = m->getDomain();
  1087. if (dm)
  1088. {
  1089. StringBuffer thisdomain;
  1090. //dm->getName(StringBufferAdaptor(thisdomain)); // confuses g++
  1091. StringBufferAdaptor strval(thisdomain);
  1092. dm->getName(strval);
  1093. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  1094. return LINK(&w.item(idx));
  1095. }
  1096. }
  1097. }
  1098. }
  1099. return nullptr;
  1100. }
  1101. };
  1102. #endif
  1103. class CConstDaFileSrvInfo : public CConstEnvBase, implements IConstDaFileSrvInfo
  1104. {
  1105. public:
  1106. IMPLEMENT_IINTERFACE;
  1107. IMPLEMENT_ICONSTENVBASE;
  1108. CConstDaFileSrvInfo(const CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root)
  1109. {
  1110. }
  1111. virtual const char *getName() const override
  1112. {
  1113. return root->queryProp("@name");
  1114. }
  1115. virtual unsigned getPort() const override
  1116. {
  1117. return root->getPropInt("@rowServicePort");
  1118. }
  1119. virtual bool getSecure() const override
  1120. {
  1121. return root->getPropBool("@rowServiceSSL");
  1122. }
  1123. };
  1124. //==========================================================================================
  1125. CLocalEnvironment::CLocalEnvironment(const char* environmentFile)
  1126. {
  1127. if (environmentFile && *environmentFile)
  1128. {
  1129. IPropertyTree* root = createPTreeFromXMLFile(environmentFile);
  1130. if (root)
  1131. p.set(root);
  1132. }
  1133. init();
  1134. }
  1135. CLocalEnvironment::CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree* root/*=nullptr*/,
  1136. const char* path/*="/Environment"*/)
  1137. : xPath(path)
  1138. {
  1139. conn.set(_conn);
  1140. if (root)
  1141. p.set(root);
  1142. else
  1143. p.setown(conn->getRoot());
  1144. init();
  1145. }
  1146. void CLocalEnvironment::init()
  1147. {
  1148. machineCacheBuilt = false;
  1149. dropZoneCacheBuilt = false;
  1150. sparkThorCacheBuilt = false;
  1151. numOfMachines = 0;
  1152. numOfDropZones = 0;
  1153. numOfSparkThors = 0;
  1154. isDropZoneRestrictionLoaded = false;
  1155. clusterGroupKeyNameCache = false;
  1156. ::getFileAccessUrl(fileAccessUrl);
  1157. }
  1158. CLocalEnvironment::~CLocalEnvironment()
  1159. {
  1160. if (conn)
  1161. conn->rollback();
  1162. }
  1163. IEnvironment& CLocalEnvironment::lock() const
  1164. {
  1165. return *new CLockedEnvironment((CLocalEnvironment*)this);
  1166. }
  1167. IStringVal & CLocalEnvironment::getName(IStringVal & str) const
  1168. {
  1169. synchronized procedure(safeCache);
  1170. str.set(p->queryProp("@name"));
  1171. return str;
  1172. }
  1173. IStringVal & CLocalEnvironment::getXML(IStringVal & str) const
  1174. {
  1175. StringBuffer xml;
  1176. {
  1177. synchronized procedure(safeCache);
  1178. toXML(p->queryBranch("."), xml);
  1179. }
  1180. str.set(xml.str());
  1181. return str;
  1182. }
  1183. IPropertyTree & CLocalEnvironment::getPTree() const
  1184. {
  1185. synchronized procedure(safeCache);
  1186. return *LINK(p);
  1187. }
  1188. IConstEnvBase * CLocalEnvironment::getCache(const char *path) const
  1189. {
  1190. IConstEnvBase * ret = cache.getValue(path);
  1191. ::Link(ret);
  1192. return ret;
  1193. }
  1194. void CLocalEnvironment::setCache(const char *path, IConstEnvBase *value) const
  1195. {
  1196. cache.setValue(path, value);
  1197. }
  1198. IConstDomainInfo * CLocalEnvironment::getDomain(const char * name) const
  1199. {
  1200. if (!name)
  1201. return nullptr;
  1202. StringBuffer xpath;
  1203. xpath.appendf("Hardware/Domain[@name=\"%s\"]", name);
  1204. synchronized procedure(safeCache);
  1205. IConstEnvBase *cached = getCache(xpath.str());
  1206. if (!cached)
  1207. {
  1208. IPropertyTree *d = p->queryPropTree(xpath.str());
  1209. if (!d)
  1210. return nullptr;
  1211. cached = new CConstDomainInfo((CLocalEnvironment *) this, d);
  1212. setCache(xpath.str(), cached);
  1213. }
  1214. return (IConstDomainInfo *) cached;
  1215. }
  1216. void CLocalEnvironment::buildMachineCache() const
  1217. {
  1218. synchronized procedure(safeCache);
  1219. if (!machineCacheBuilt)
  1220. {
  1221. Owned<IPropertyTreeIterator> it = p->getElements("Hardware/Computer");
  1222. ForEach(*it)
  1223. {
  1224. const char *name = it->query().queryProp("@name");
  1225. if (name)
  1226. {
  1227. StringBuffer x("Hardware/Computer[@name=\"");
  1228. x.append(name).append("\"]");
  1229. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1230. cache.setValue(x.str(), cached);
  1231. }
  1232. const char * netAddress = it->query().queryProp("@netAddress");
  1233. if (netAddress)
  1234. {
  1235. StringBuffer x("Hardware/Computer[@netAddress=\"");
  1236. x.append(netAddress).append("\"]");
  1237. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1238. cache.setValue(x.str(), cached);
  1239. IpAddress ip;
  1240. ip.ipset(netAddress);
  1241. if (ip.isLocal())
  1242. cache.setValue("Hardware/Computer[@netAddress=\".\"]", cached);
  1243. }
  1244. numOfMachines++;
  1245. StringBuffer x("Hardware/Computer[@id=\"");
  1246. x.append(MACHINE_PREFIX).append(numOfMachines).append("\"]");
  1247. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1248. cache.setValue(x.str(), cached);
  1249. }
  1250. machineCacheBuilt = true;
  1251. }
  1252. }
  1253. void CLocalEnvironment::buildDropZoneCache() const
  1254. {
  1255. synchronized procedure(safeCache);
  1256. if (!dropZoneCacheBuilt)
  1257. {
  1258. Owned<IPropertyTreeIterator> it = p->getElements("Software/DropZone");
  1259. ForEach(*it)
  1260. {
  1261. const char *name = it->query().queryProp("@name");
  1262. if (name)
  1263. {
  1264. StringBuffer x("Software/DropZone[@name=\"");
  1265. x.append(name).append("\"]");
  1266. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  1267. cache.setValue(x.str(), cached);
  1268. }
  1269. numOfDropZones++;
  1270. StringBuffer x("Software/DropZone[@id=\"");
  1271. x.append(DROPZONE_SUFFIX).append(numOfDropZones).append("\"]");
  1272. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  1273. cache.setValue(x.str(), cached);
  1274. }
  1275. dropZoneCacheBuilt = true;
  1276. }
  1277. }
  1278. IConstComputerTypeInfo * CLocalEnvironment::getComputerType(const char * name) const
  1279. {
  1280. if (!name)
  1281. return nullptr;
  1282. StringBuffer xpath;
  1283. xpath.appendf("Hardware/ComputerType[@name=\"%s\"]", name);
  1284. synchronized procedure(safeCache);
  1285. IConstEnvBase *cached = getCache(xpath.str());
  1286. if (!cached)
  1287. {
  1288. IPropertyTree *d = p->queryPropTree(xpath.str());
  1289. if (!d)
  1290. return nullptr;
  1291. cached = new CConstComputerTypeInfo((CLocalEnvironment *) this, d);
  1292. setCache(xpath.str(), cached);
  1293. }
  1294. return (CConstComputerTypeInfo *) cached;
  1295. }
  1296. IConstMachineInfo * CLocalEnvironment::getMachine(const char * name) const
  1297. {
  1298. if (!name)
  1299. return nullptr;
  1300. buildMachineCache();
  1301. StringBuffer xpath;
  1302. xpath.appendf("Hardware/Computer[@name=\"%s\"]", name);
  1303. synchronized procedure(safeCache);
  1304. IConstEnvBase *cached = getCache(xpath.str());
  1305. if (!cached)
  1306. {
  1307. IPropertyTree *d = p->queryPropTree(xpath.str());
  1308. if (!d)
  1309. return nullptr;
  1310. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  1311. setCache(xpath.str(), cached);
  1312. }
  1313. return (CConstMachineInfo *) cached;
  1314. }
  1315. IConstMachineInfo * CLocalEnvironment::getMachineByAddress(const char * machineIp) const
  1316. {
  1317. if (!machineIp)
  1318. return nullptr;
  1319. buildMachineCache();
  1320. Owned<IPropertyTreeIterator> iter;
  1321. StringBuffer xpath;
  1322. xpath.appendf("Hardware/Computer[@netAddress=\"%s\"]", machineIp);
  1323. synchronized procedure(safeCache);
  1324. IConstEnvBase *cached = getCache(xpath.str());
  1325. if (!cached)
  1326. {
  1327. IPropertyTree *d = p->queryPropTree(xpath.str());
  1328. if (!d)
  1329. {
  1330. // I suspect not in the original spirit of this but look for resolved IP
  1331. Owned<IPropertyTreeIterator> iter = p->getElements("Hardware/Computer");
  1332. IpAddress ip;
  1333. ip.ipset(machineIp);
  1334. ForEach(*iter)
  1335. {
  1336. IPropertyTree &computer = iter->query();
  1337. IpAddress ip2;
  1338. const char *ips = computer.queryProp("@netAddress");
  1339. if (ips&&*ips)
  1340. {
  1341. ip2.ipset(ips);
  1342. if (ip.ipequals(ip2))
  1343. {
  1344. d = &computer;
  1345. break;
  1346. }
  1347. }
  1348. }
  1349. }
  1350. if (!d)
  1351. return nullptr;
  1352. StringBuffer xpath1;
  1353. xpath1.appendf("Hardware/Computer[@name=\"%s\"]", d->queryProp("@name"));
  1354. cached = getCache(xpath1.str());
  1355. if (!cached)
  1356. {
  1357. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  1358. setCache(xpath1.str(), cached);
  1359. setCache(xpath.str(), cached);
  1360. }
  1361. }
  1362. return (CConstMachineInfo *) cached;
  1363. }
  1364. IConstMachineInfo * CLocalEnvironment::getMachineByIndex(unsigned index) const
  1365. {
  1366. if (!numOfMachines || (index == 0))
  1367. return nullptr;
  1368. buildMachineCache();
  1369. if (index > numOfMachines)
  1370. return nullptr;
  1371. StringBuffer xpath("Hardware/Computer[@id=\"");
  1372. xpath.append(MACHINE_PREFIX).append(index).append("\"]");
  1373. synchronized procedure(safeCache);
  1374. return (IConstMachineInfo *) getCache(xpath.str());
  1375. }
  1376. IConstMachineInfo * CLocalEnvironment::getMachineForLocalHost() const
  1377. {
  1378. buildMachineCache();
  1379. synchronized procedure(safeCache);
  1380. return (CConstMachineInfo *) getCache("Hardware/Computer[@netAddress=\".\"]");
  1381. }
  1382. IConstDropZoneInfo * CLocalEnvironment::getDropZone(const char * name) const
  1383. {
  1384. if (!name)
  1385. return nullptr;
  1386. buildDropZoneCache();
  1387. VStringBuffer xpath("Software/DropZone[@name=\"%s\"]", name);
  1388. synchronized procedure(safeCache);
  1389. return (CConstDropZoneInfo *) getCache(xpath.str());
  1390. }
  1391. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByIndex(unsigned index) const
  1392. {
  1393. if (!numOfDropZones || (index == 0))
  1394. return nullptr;
  1395. buildDropZoneCache();
  1396. if (index > numOfDropZones)
  1397. return nullptr;
  1398. StringBuffer xpath("Software/DropZone[@id=\"");
  1399. xpath.append(DROPZONE_SUFFIX).append(index).append("\"]");
  1400. synchronized procedure(safeCache);
  1401. return (CConstDropZoneInfo *) getCache(xpath.str());
  1402. }
  1403. IConstInstanceInfo * CLocalEnvironment::getInstance(const char *type, const char *version, const char *domain) const
  1404. {
  1405. StringBuffer xpath("Software/");
  1406. xpath.append(type);
  1407. if (version)
  1408. xpath.append("[@version='").append(version).append("']");
  1409. xpath.append("/Instance");
  1410. synchronized procedure(safeCache);
  1411. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1412. for (_it->first(); _it->isValid(); _it->next())
  1413. {
  1414. IPropertyTree *rp = &_it->query();
  1415. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1416. Owned<IConstMachineInfo> m = inst->getMachine();
  1417. if (m)
  1418. {
  1419. Owned<IConstDomainInfo> dm = m->getDomain();
  1420. if (dm)
  1421. {
  1422. SCMStringBuffer thisdomain;
  1423. dm->getName(thisdomain);
  1424. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  1425. return inst.getClear();
  1426. }
  1427. }
  1428. }
  1429. return nullptr;
  1430. }
  1431. CConstInstanceInfo * CLocalEnvironment::getInstanceByIP(const char *type, const char *version, IpAddress &ip) const
  1432. {
  1433. StringBuffer xpath("Software/");
  1434. xpath.append(type);
  1435. if (version)
  1436. xpath.append("[@version='").append(version).append("']");
  1437. xpath.append("/Instance");
  1438. synchronized procedure(safeCache);
  1439. assertex(p);
  1440. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1441. assertex(_it);
  1442. for (_it->first(); _it->isValid(); _it->next())
  1443. {
  1444. IPropertyTree *rp = &_it->query();
  1445. assertex(rp);
  1446. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1447. Owned<IConstMachineInfo> m = inst->getMachine();
  1448. if (m)
  1449. {
  1450. SCMStringBuffer eps;
  1451. m->getNetAddress(eps);
  1452. SocketEndpoint ep(eps.str());
  1453. if (ep.ipequals(ip))
  1454. return inst.getClear();
  1455. }
  1456. }
  1457. return nullptr;
  1458. }
  1459. void CLocalEnvironment::unlockRemote()
  1460. {
  1461. #if 0
  1462. conn->commit(true);
  1463. conn->changeMode(0, SDS_LOCK_TIMEOUT);
  1464. #else
  1465. if (conn)
  1466. {
  1467. synchronized procedure(safeCache);
  1468. p.clear();
  1469. conn.setown(querySDS().connect(xPath.str(), myProcessSession(), 0, SDS_LOCK_TIMEOUT));
  1470. p.setown(conn->getRoot());
  1471. }
  1472. #endif
  1473. }
  1474. void CLocalEnvironment::preload()
  1475. {
  1476. synchronized procedure(safeCache);
  1477. p->queryBranch(".");
  1478. }
  1479. void CLocalEnvironment::setXML(const char *xml)
  1480. {
  1481. Owned<IPropertyTree> newRoot = createPTreeFromXMLString(xml, ipt_lowmem);
  1482. synchronized procedure(safeCache);
  1483. Owned<IPropertyTreeIterator> it = p->getElements("*");
  1484. ForEach(*it)
  1485. {
  1486. p->removeTree(&it->query());
  1487. }
  1488. it.setown(newRoot->getElements("*"));
  1489. ForEach(*it)
  1490. {
  1491. IPropertyTree *sub = &it->get();
  1492. p->addPropTree(sub->queryName(), sub);
  1493. }
  1494. }
  1495. bool CLocalEnvironment::getRunInfo(IStringVal & path, IStringVal & dir, const char * tag, const char * version, const char *machineaddr, const char *defprogname) const
  1496. {
  1497. try
  1498. {
  1499. // PrintLog("getExecutablePath %s %s %s", tag, version, machineaddr);
  1500. // first see if local machine with deployed on
  1501. SocketEndpoint ep(machineaddr);
  1502. Owned<CConstInstanceInfo> ipinstance = getInstanceByIP(tag, version, ep);
  1503. if (ipinstance)
  1504. {
  1505. StringAttr testpath;
  1506. StringAttrAdaptor teststrval(testpath);
  1507. if (ipinstance->doGetRunInfo(teststrval,dir,defprogname,false))
  1508. { // this returns full string
  1509. RemoteFilename rfn;
  1510. rfn.setRemotePath(testpath.get());
  1511. Owned<IFile> file = createIFile(rfn);
  1512. if (file->exists())
  1513. {
  1514. StringBuffer tmp;
  1515. rfn.getLocalPath(tmp);
  1516. path.set(tmp.str());
  1517. return true;
  1518. }
  1519. }
  1520. }
  1521. Owned<IConstMachineInfo> machine = getMachineByAddress(machineaddr);
  1522. if (!machine)
  1523. {
  1524. LOG(MCdebugInfo, unknownJob, "Unable to find machine for %s", machineaddr);
  1525. return false;
  1526. }
  1527. StringAttr targetdomain;
  1528. Owned<IConstDomainInfo> domain = machine->getDomain();
  1529. if (!domain)
  1530. {
  1531. LOG(MCdebugInfo, unknownJob, "Unable to find domain for %s", machineaddr);
  1532. return false;
  1533. }
  1534. //domain->getName(StringAttrAdaptor(targetdomain)); // confuses g++
  1535. StringAttrAdaptor strval(targetdomain);
  1536. domain->getName(strval);
  1537. Owned<IConstInstanceInfo> instance = getInstance(tag, version, targetdomain);
  1538. if (!instance)
  1539. {
  1540. LOG(MCdebugInfo, unknownJob, "Unable to find process %s for domain %s", tag, targetdomain.get());
  1541. return false;
  1542. }
  1543. return instance->getRunInfo(path,dir,defprogname);
  1544. }
  1545. catch (IException * e)
  1546. {
  1547. EXCLOG(e, "Extracting slave version");
  1548. e->Release();
  1549. return false;
  1550. }
  1551. }
  1552. void CLocalEnvironment::clearCache()
  1553. {
  1554. synchronized procedure(safeCache);
  1555. if (conn)
  1556. {
  1557. p.clear();
  1558. unsigned mode = 0;
  1559. try
  1560. {
  1561. conn->reload();
  1562. }
  1563. catch (IException *e)
  1564. {
  1565. EXCLOG(e, "Failed to reload connection");
  1566. e->Release();
  1567. mode = conn->queryMode();
  1568. conn.clear();
  1569. }
  1570. if (!conn)
  1571. conn.setown(querySDS().connect(xPath, myProcessSession(), mode, SDS_LOCK_TIMEOUT));
  1572. p.setown(conn->getRoot());
  1573. }
  1574. cache.kill();
  1575. keyGroupMap.clear();
  1576. keyPairMap.clear();
  1577. init();
  1578. resetPasswordsFromSDS();
  1579. }
  1580. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByAddressPath(const char * netaddress, const char *targetFilePath) const
  1581. {
  1582. IConstDropZoneInfo * dropZone = nullptr;
  1583. IpAddress targetIp(netaddress);
  1584. unsigned dropzonePathLen = _MAX_PATH + 1;
  1585. #ifdef _DEBUG
  1586. LOG(MCdebugInfo, unknownJob, "Netaddress: '%s', targetFilePath: '%s'", netaddress, targetFilePath);
  1587. #endif
  1588. // Check the directory path first
  1589. Owned<IConstDropZoneInfoIterator> zoneIt = getDropZoneIterator();
  1590. ForEach(*zoneIt)
  1591. {
  1592. SCMStringBuffer dropZoneDir;
  1593. zoneIt->query().getDirectory(dropZoneDir);
  1594. StringBuffer fullDropZoneDir(dropZoneDir.str());
  1595. addPathSepChar(fullDropZoneDir);
  1596. IConstDropZoneInfo * candidateDropZone = nullptr;
  1597. if (strncmp(fullDropZoneDir, targetFilePath, fullDropZoneDir.length()) == 0)
  1598. {
  1599. candidateDropZone = &zoneIt->query();
  1600. // The backward compatibility built in IConstDropZoneServerInfoIterator
  1601. Owned<IConstDropZoneServerInfoIterator> dropzoneServerListIt = candidateDropZone->getServers();
  1602. ForEach(*dropzoneServerListIt)
  1603. {
  1604. StringBuffer dropzoneServer;
  1605. dropzoneServerListIt->query().getServer(dropzoneServer);
  1606. // It can be a hostname or an IP -> get the IP
  1607. IpAddress serverIP(dropzoneServer.str());
  1608. #ifdef _DEBUG
  1609. StringBuffer serverIpString;
  1610. serverIP.getIpText(serverIpString);
  1611. LOG(MCdebugInfo, unknownJob, "Listed server: '%s', IP: '%s'", dropzoneServer.str(), serverIpString.str());
  1612. #endif
  1613. if (targetIp.ipequals(serverIP))
  1614. {
  1615. // OK the target is a valid machine in the server list we have a right drop zone candidate
  1616. // Keep this candidate drop zone if its directory path is shorter than we already have
  1617. if (dropzonePathLen > fullDropZoneDir.length())
  1618. {
  1619. dropzonePathLen = fullDropZoneDir.length();
  1620. dropZone = candidateDropZone;
  1621. }
  1622. break;
  1623. }
  1624. }
  1625. }
  1626. }
  1627. return LINK(dropZone);
  1628. }
  1629. IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIteratorByAddress(const char *addr) const
  1630. {
  1631. class CByAddrIter : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
  1632. {
  1633. IArrayOf<IConstDropZoneInfo> matches;
  1634. unsigned cur = NotFound;
  1635. public:
  1636. CByAddrIter(IConstDropZoneInfoIterator *baseIter, const char *addr)
  1637. {
  1638. IpAddress toMatch(addr);
  1639. ForEach(*baseIter)
  1640. {
  1641. IConstDropZoneInfo &dz = baseIter->query();
  1642. Owned<IConstDropZoneServerInfoIterator> serverIter = dz.getServers();
  1643. ForEach(*serverIter)
  1644. {
  1645. IConstDropZoneServerInfo &serverElem = serverIter->query();
  1646. StringBuffer serverName;
  1647. IpAddress serverIp(serverElem.getServer(serverName).str());
  1648. if (serverIp.ipequals(toMatch))
  1649. {
  1650. matches.append(*LINK(&dz));
  1651. break;
  1652. }
  1653. }
  1654. }
  1655. }
  1656. virtual bool first() override
  1657. {
  1658. if (0 == matches.ordinality())
  1659. {
  1660. cur = NotFound;
  1661. return false;
  1662. }
  1663. cur = 0;
  1664. return true;
  1665. }
  1666. virtual bool next() override
  1667. {
  1668. if (cur+1==matches.ordinality())
  1669. {
  1670. cur = NotFound;
  1671. return false;
  1672. }
  1673. ++cur;
  1674. return true;
  1675. }
  1676. virtual bool isValid() override
  1677. {
  1678. return NotFound != cur;
  1679. }
  1680. virtual IConstDropZoneInfo &query() override
  1681. {
  1682. assertex(NotFound != cur);
  1683. return matches.item(cur);
  1684. }
  1685. virtual unsigned count() const override
  1686. {
  1687. return matches.ordinality();
  1688. }
  1689. };
  1690. Owned<IConstDropZoneInfoIterator> baseIter = new CConstDropZoneInfoIterator();
  1691. return new CByAddrIter(baseIter, addr);
  1692. }
  1693. IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIterator() const
  1694. {
  1695. return new CConstDropZoneInfoIterator();
  1696. }
  1697. IConstMachineInfoIterator * CLocalEnvironment::getMachineIterator() const
  1698. {
  1699. return new CConstMachineInfoIterator();
  1700. }
  1701. bool CLocalEnvironment::isDropZoneRestrictionEnabled() const
  1702. {
  1703. if (!isDropZoneRestrictionLoaded)
  1704. {
  1705. dropZoneRestrictionEnabled = queryEnvironmentConf().getPropBool("useDropZoneRestriction", true);
  1706. isDropZoneRestrictionLoaded=true;
  1707. }
  1708. return dropZoneRestrictionEnabled;
  1709. }
  1710. IConstDaFileSrvInfo *CLocalEnvironment::getDaFileSrvGroupInfo(const char *name) const
  1711. {
  1712. if (!name)
  1713. return nullptr;
  1714. VStringBuffer xpath("Software/DafilesrvGroup[@name=\"%s\"]", name);
  1715. synchronized procedure(safeCache);
  1716. IConstEnvBase *cached = getCache(xpath.str());
  1717. if (!cached)
  1718. {
  1719. IPropertyTree *d = p->queryPropTree(xpath.str());
  1720. if (!d)
  1721. return nullptr;
  1722. cached = new CConstDaFileSrvInfo(this, d);
  1723. setCache(xpath.str(), cached);
  1724. }
  1725. return (IConstDaFileSrvInfo *) cached;
  1726. }
  1727. IConstSparkThorInfo *CLocalEnvironment::getSparkThor(const char *name) const
  1728. {
  1729. if (isEmptyString(name))
  1730. return nullptr;
  1731. buildSparkThorCache();
  1732. VStringBuffer xpath("Software/SparkThor[@name=\"%s\"]", name);
  1733. synchronized procedure(safeCache);
  1734. return (CConstSparkThorInfo *) getCache(xpath);
  1735. }
  1736. IConstSparkThorInfo *CLocalEnvironment::getSparkThorByIndex(unsigned index) const
  1737. {
  1738. if (index == 0)
  1739. return nullptr;
  1740. buildSparkThorCache();
  1741. if (index > numOfSparkThors)
  1742. return nullptr;
  1743. StringBuffer xpath("Software/SparkThor[@id=\"");
  1744. xpath.append(SPARKTHOR_SUFFIX).append(index).append("\"]");
  1745. synchronized procedure(safeCache);
  1746. return (CConstSparkThorInfo *) getCache(xpath);
  1747. }
  1748. IConstSparkThorInfoIterator *CLocalEnvironment::getSparkThorIterator() const
  1749. {
  1750. return new CConstSparkThorInfoIterator();
  1751. }
  1752. void CLocalEnvironment::buildSparkThorCache() const
  1753. {
  1754. synchronized procedure(safeCache);
  1755. if (sparkThorCacheBuilt)
  1756. return;
  1757. Owned<IPropertyTreeIterator> it = p->getElements("Software/SparkThorProcess");
  1758. ForEach(*it)
  1759. {
  1760. const char *name = it->query().queryProp("@name");
  1761. if (!isEmptyString(name))
  1762. {
  1763. StringBuffer x("Software/SparkThor[@name=\"");
  1764. x.append(name).append("\"]");
  1765. Owned<IConstEnvBase> cached = new CConstSparkThorInfo((CLocalEnvironment *) this, &it->query());
  1766. cache.setValue(x, cached);
  1767. }
  1768. numOfSparkThors++;
  1769. StringBuffer x("Software/SparkThor[@id=\"");
  1770. x.append(SPARKTHOR_SUFFIX).append(numOfSparkThors).append("\"]");
  1771. Owned<IConstEnvBase> cached = new CConstSparkThorInfo((CLocalEnvironment *) this, &it->query());
  1772. cache.setValue(x, cached);
  1773. }
  1774. sparkThorCacheBuilt = true;
  1775. }
  1776. //==========================================================================================
  1777. // Iterators implementation
  1778. CConstMachineInfoIterator::CConstMachineInfoIterator()
  1779. {
  1780. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  1781. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1782. maxIndex = constEnv->getNumberOfMachines();
  1783. }
  1784. bool CConstMachineInfoIterator::first()
  1785. {
  1786. index = 1;
  1787. curr.setown(constEnv->getMachineByIndex(index));
  1788. return curr != nullptr;
  1789. }
  1790. bool CConstMachineInfoIterator::next()
  1791. {
  1792. if (index < maxIndex)
  1793. {
  1794. index++;
  1795. curr.setown(constEnv->getMachineByIndex(index));
  1796. }
  1797. else
  1798. curr.clear();
  1799. return curr != nullptr;
  1800. }
  1801. bool CConstMachineInfoIterator::isValid()
  1802. {
  1803. return curr != nullptr;
  1804. }
  1805. IConstMachineInfo & CConstMachineInfoIterator::query()
  1806. {
  1807. return *curr;
  1808. }
  1809. unsigned CConstMachineInfoIterator::count() const
  1810. {
  1811. return maxIndex;
  1812. }
  1813. CConstDropZoneServerInfoIterator::CConstDropZoneServerInfoIterator(const IConstDropZoneInfo * dropZone)
  1814. {
  1815. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  1816. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1817. // For backward compatibility
  1818. SCMStringBuffer dropZoneMachineName;
  1819. // Returns dropzone '@computer' value if it is exists
  1820. dropZone->getComputerName(dropZoneMachineName);
  1821. if (0 != dropZoneMachineName.length())
  1822. {
  1823. // Create a ServerList for legacy element.
  1824. Owned<IPropertyTree> legacyServerList = createPTree(ipt_lowmem);
  1825. Owned<IConstMachineInfo> machineInfo = constEnv->getMachine(dropZoneMachineName.str());
  1826. if (machineInfo)
  1827. {
  1828. SCMStringBuffer dropZoneMachineNetAddress;
  1829. machineInfo->getNetAddress(dropZoneMachineNetAddress);
  1830. // Create a single ServerList record related to @computer
  1831. //<ServerList name="ServerList" server="<IP_of_@computer>"/>
  1832. IPropertyTree *newRecord = legacyServerList->addPropTree("ServerList");
  1833. newRecord->setProp("@name", "ServerList");
  1834. newRecord->setProp("@server", dropZoneMachineNetAddress.str());
  1835. maxIndex = 1;
  1836. }
  1837. else
  1838. {
  1839. // Something is terrible wrong because there is no matching machine for DropZone @computer
  1840. maxIndex = 0;
  1841. }
  1842. serverListIt.setown(legacyServerList->getElements("ServerList"));
  1843. }
  1844. else
  1845. {
  1846. Owned<IPropertyTree> pSrc = &dropZone->getPTree();
  1847. serverListIt.setown(pSrc->getElements("ServerList"));
  1848. maxIndex = pSrc->getCount("ServerList");
  1849. }
  1850. }
  1851. bool CConstDropZoneServerInfoIterator::first()
  1852. {
  1853. bool hasFirst = serverListIt->first();
  1854. if (hasFirst)
  1855. curr.setown(new CConstDropZoneServerInfo(constEnv, &serverListIt->query()));
  1856. else
  1857. curr.clear();
  1858. return hasFirst;
  1859. }
  1860. bool CConstDropZoneServerInfoIterator::next()
  1861. {
  1862. bool hasNext = serverListIt->next();
  1863. if (hasNext)
  1864. curr.setown(new CConstDropZoneServerInfo(constEnv, &serverListIt->query()));
  1865. else
  1866. curr.clear();
  1867. return hasNext;
  1868. }
  1869. bool CConstDropZoneServerInfoIterator::isValid()
  1870. {
  1871. return nullptr != curr;
  1872. }
  1873. IConstDropZoneServerInfo & CConstDropZoneServerInfoIterator::query()
  1874. {
  1875. return *curr;
  1876. }
  1877. unsigned CConstDropZoneServerInfoIterator::count() const
  1878. {
  1879. return maxIndex;
  1880. }
  1881. //--------------------------------------------------
  1882. CConstDropZoneInfoIterator::CConstDropZoneInfoIterator()
  1883. {
  1884. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  1885. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1886. maxIndex = constEnv->getNumberOfDropZones();
  1887. }
  1888. bool CConstDropZoneInfoIterator::first()
  1889. {
  1890. index = 1;
  1891. curr.setown(constEnv->getDropZoneByIndex(index));
  1892. return curr != nullptr;
  1893. }
  1894. bool CConstDropZoneInfoIterator::next()
  1895. {
  1896. if (index < maxIndex)
  1897. {
  1898. index++;
  1899. curr.setown(constEnv->getDropZoneByIndex(index));
  1900. }
  1901. else
  1902. curr.clear();
  1903. return curr != nullptr;
  1904. }
  1905. bool CConstDropZoneInfoIterator::isValid()
  1906. {
  1907. return curr != nullptr;
  1908. }
  1909. IConstDropZoneInfo & CConstDropZoneInfoIterator::query()
  1910. {
  1911. return *curr;
  1912. }
  1913. unsigned CConstDropZoneInfoIterator::count() const
  1914. {
  1915. return maxIndex;
  1916. }
  1917. //--------------------------------------------------
  1918. CConstSparkThorInfoIterator::CConstSparkThorInfoIterator()
  1919. {
  1920. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  1921. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1922. maxIndex = constEnv->getNumberOfSparkThors();
  1923. }
  1924. bool CConstSparkThorInfoIterator::first()
  1925. {
  1926. index = 1;
  1927. curr.setown(constEnv->getSparkThorByIndex(index));
  1928. return curr != nullptr;
  1929. }
  1930. bool CConstSparkThorInfoIterator::next()
  1931. {
  1932. if (index < maxIndex)
  1933. {
  1934. index++;
  1935. curr.setown(constEnv->getSparkThorByIndex(index));
  1936. }
  1937. else
  1938. curr.clear();
  1939. return curr != nullptr;
  1940. }
  1941. bool CConstSparkThorInfoIterator::isValid()
  1942. {
  1943. return curr != nullptr;
  1944. }
  1945. IConstSparkThorInfo &CConstSparkThorInfoIterator::query()
  1946. {
  1947. return *curr;
  1948. }
  1949. unsigned CConstSparkThorInfoIterator::count() const
  1950. {
  1951. return maxIndex;
  1952. }
  1953. //--------------------------------------------------
  1954. CConstInstanceInfoIterator::CConstInstanceInfoIterator(const CLocalEnvironment *env, IPropertyTreeIterator *itr)
  1955. : constEnv(env)
  1956. {
  1957. instanceItr.setown(itr);
  1958. maxIndex = 0;
  1959. ForEach(*instanceItr)
  1960. maxIndex++;
  1961. }
  1962. bool CConstInstanceInfoIterator::first()
  1963. {
  1964. index = 1;
  1965. instanceItr->first();
  1966. curr.setown(new CConstInstanceInfo(constEnv, &instanceItr->query()));
  1967. return curr != nullptr;
  1968. }
  1969. bool CConstInstanceInfoIterator::next()
  1970. {
  1971. if (index < maxIndex)
  1972. {
  1973. index++;
  1974. instanceItr->next();
  1975. curr.setown(new CConstInstanceInfo(constEnv, &instanceItr->query()));
  1976. }
  1977. else
  1978. curr.clear();
  1979. return curr != nullptr;
  1980. }
  1981. bool CConstInstanceInfoIterator::isValid()
  1982. {
  1983. return curr != nullptr;
  1984. }
  1985. IConstInstanceInfo &CConstInstanceInfoIterator::query()
  1986. {
  1987. return *curr;
  1988. }
  1989. unsigned CConstInstanceInfoIterator::count() const
  1990. {
  1991. return maxIndex;
  1992. }
  1993. //==========================================================================================
  1994. static CriticalSection getEnvSect;
  1995. extern ENVIRONMENT_API IEnvironmentFactory * getEnvironmentFactory(bool update)
  1996. {
  1997. CriticalBlock block(getEnvSect);
  1998. if (!factory)
  1999. {
  2000. factory = new CEnvironmentFactory();
  2001. addShutdownHook(*factory);
  2002. }
  2003. if (update)
  2004. factory->validateCache();
  2005. return LINK(factory);
  2006. }
  2007. extern ENVIRONMENT_API void closeEnvironment()
  2008. {
  2009. try
  2010. {
  2011. CEnvironmentFactory* pFactory;
  2012. {
  2013. //this method is not meant to be invoked by multiple
  2014. //threads concurrently but just in case...
  2015. CriticalBlock block(getEnvSect);
  2016. pFactory = factory;
  2017. factory = nullptr;
  2018. }
  2019. clearPasswordsFromSDS();
  2020. if (pFactory)
  2021. {
  2022. removeShutdownHook(*pFactory);
  2023. pFactory->close();
  2024. pFactory->Release();
  2025. }
  2026. }
  2027. catch (IException *e)
  2028. {
  2029. EXCLOG(e);
  2030. }
  2031. }
  2032. extern ENVIRONMENT_API unsigned long readSizeSetting(const char * sizeStr, const unsigned long defaultSize)
  2033. {
  2034. StringBuffer buf = sizeStr;
  2035. buf.trim();
  2036. if (buf.isEmpty())
  2037. return defaultSize;
  2038. const char* ptrStart = buf;
  2039. const char* ptrAfterDigit = ptrStart;
  2040. while (*ptrAfterDigit && isdigit(*ptrAfterDigit))
  2041. ptrAfterDigit++;
  2042. if (!*ptrAfterDigit)
  2043. return atol(buf);
  2044. const char* ptr = ptrAfterDigit;
  2045. while (*ptr && (ptr[0] == ' '))
  2046. ptr++;
  2047. char c = ptr[0];
  2048. buf.setLength(ptrAfterDigit - ptrStart);
  2049. unsigned long size = atol(buf);
  2050. switch (c)
  2051. {
  2052. case 'k':
  2053. case 'K':
  2054. size *= 1000;
  2055. break;
  2056. case 'm':
  2057. case 'M':
  2058. size *= 1000000;
  2059. break;
  2060. case 'g':
  2061. case 'G':
  2062. size *= 1000000000;
  2063. break;
  2064. case 't':
  2065. case 'T':
  2066. size *= 1000000000000;
  2067. break;
  2068. default:
  2069. break;
  2070. }
  2071. return size;
  2072. }
  2073. unsigned getAccessibleServiceURLList(const char *serviceType, std::vector<std::string> &list)
  2074. {
  2075. unsigned added = 0;
  2076. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  2077. Owned<IConstEnvironment> daliEnv = factory->openEnvironment();
  2078. Owned<IPropertyTree> env = &daliEnv->getPTree();
  2079. if (env.get())
  2080. {
  2081. StringBuffer fileMetaServiceUrl;
  2082. StringBuffer espInstanceComputerName;
  2083. StringBuffer bindingProtocol;
  2084. StringBuffer xpath;
  2085. StringBuffer instanceAddress;
  2086. StringBuffer espServiceType;
  2087. Owned<IPropertyTreeIterator> espProcessIter = env->getElements("Software/EspProcess");
  2088. ForEach(*espProcessIter)
  2089. {
  2090. Owned<IPropertyTreeIterator> espBindingIter = espProcessIter->query().getElements("EspBinding");
  2091. ForEach(*espBindingIter)
  2092. {
  2093. xpath.setf("Software/EspService[@name=\"%s\"]/Properties/@type", espBindingIter->query().queryProp("@service"));
  2094. if (strisame(env->queryProp(xpath), serviceType))
  2095. {
  2096. if (espBindingIter->query().getProp("@protocol", bindingProtocol.clear()))
  2097. {
  2098. Owned<IPropertyTreeIterator> espInstanceIter = espProcessIter->query().getElements("Instance");
  2099. ForEach(*espInstanceIter)
  2100. {
  2101. if (espInstanceIter->query().getProp("@computer", espInstanceComputerName.clear()))
  2102. {
  2103. xpath.setf("Hardware/Computer[@name=\"%s\"]/@netAddress", espInstanceComputerName.str());
  2104. if (env->getProp(xpath.str(), instanceAddress.clear()))
  2105. {
  2106. fileMetaServiceUrl.setf("%s://%s:%d", bindingProtocol.str(), instanceAddress.str(), espBindingIter->query().getPropInt("@port",8010));
  2107. list.push_back(fileMetaServiceUrl.str());
  2108. ++added;
  2109. }
  2110. }
  2111. }
  2112. }
  2113. }
  2114. }//ESPBinding
  2115. }//ESPProcess
  2116. }
  2117. return added;
  2118. }