environment.cpp 80 KB

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