environment.cpp 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972
  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 "mpbase.hpp"
  21. #include "daclient.hpp"
  22. #include "dadfs.hpp"
  23. #include "dafdesc.hpp"
  24. #include "dasds.hpp"
  25. #include "dalienv.hpp"
  26. #define SDS_LOCK_TIMEOUT 30000
  27. #define DEFAULT_DROPZONE_INDEX 1
  28. #define DROPZONE_BY_MACHINE_SUFFIX "-dropzoneByMachine-"
  29. #define DROPZONE_SUFFIX "dropzone-"
  30. #define MACHINE_PREFIX "machine-"
  31. static int environmentTraceLevel = 1;
  32. static Owned <IConstEnvironment> cache;
  33. class CLocalEnvironment;
  34. class CConstMachineInfoIterator : public CSimpleInterfaceOf<IConstMachineInfoIterator>
  35. {
  36. public:
  37. CConstMachineInfoIterator();
  38. virtual bool first() override;
  39. virtual bool next() override;
  40. virtual bool isValid() override;
  41. virtual IConstMachineInfo & query() override;
  42. virtual unsigned count() const override;
  43. protected:
  44. Owned<IConstMachineInfo> curr;
  45. Owned<CLocalEnvironment> constEnv;
  46. unsigned index = 1;
  47. unsigned maxIndex = 0;
  48. };
  49. class CConstDropZoneServerInfoIterator : public CSimpleInterfaceOf<IConstDropZoneServerInfoIterator>
  50. {
  51. public:
  52. CConstDropZoneServerInfoIterator(const IConstDropZoneInfo * dropZone);
  53. virtual bool first() override;
  54. virtual bool next() override;
  55. virtual bool isValid() override;
  56. virtual IConstDropZoneServerInfo & query() override;
  57. virtual unsigned count() const override;
  58. protected:
  59. Owned<IConstDropZoneServerInfo> curr;
  60. Owned<CLocalEnvironment> constEnv;
  61. Owned<IPropertyTreeIterator> serverListIt;
  62. unsigned maxIndex = 0;
  63. };
  64. class CConstDropZoneInfoIterator : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
  65. {
  66. public:
  67. CConstDropZoneInfoIterator();
  68. virtual bool first() override;
  69. virtual bool next() override;
  70. virtual bool isValid() override;
  71. virtual IConstDropZoneInfo & query() override;
  72. virtual unsigned count() const override;
  73. protected:
  74. Owned<IConstDropZoneInfo> curr;
  75. Owned<CLocalEnvironment> constEnv;
  76. unsigned index = 1;
  77. unsigned maxIndex = 0;
  78. };
  79. class CConstDropZoneIteratorByComputer : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
  80. {
  81. public:
  82. CConstDropZoneIteratorByComputer(const char * computer);
  83. virtual bool first() override;
  84. virtual bool next() override;
  85. virtual bool isValid() override;
  86. virtual IConstDropZoneInfo & query() override;
  87. virtual unsigned count() const override;
  88. protected:
  89. StringBuffer computerName;
  90. Owned<IConstDropZoneInfo> curr;
  91. Owned<CLocalEnvironment> constEnv;
  92. unsigned index = 1;
  93. unsigned maxIndex = 0;
  94. };
  95. //==========================================================================================
  96. class CConstInstanceInfo;
  97. class CLocalEnvironment : implements IConstEnvironment, public CInterface
  98. {
  99. private:
  100. // NOTE - order is important - we need to construct before p and (especially) destruct after p
  101. Owned<IRemoteConnection> conn;
  102. Owned<IPropertyTree> p;
  103. mutable MapStringToMyClass<IConstEnvBase> cache;
  104. mutable Mutex safeCache;
  105. mutable bool dropZoneCacheBuilt;
  106. mutable bool machineCacheBuilt;
  107. StringBuffer xPath;
  108. Owned<IPropertyTree> numOfDropzonesByComputer;
  109. mutable unsigned numOfMachines;
  110. mutable unsigned numOfDropZones;
  111. IConstEnvBase * getCache(const char *path) const;
  112. void setCache(const char *path, IConstEnvBase *value) const;
  113. void buildMachineCache() const;
  114. void buildDropZoneCache() const;
  115. void init();
  116. StringBuffer & createComputerNameXpath(const char * computer, StringBuffer &xpath) const
  117. {
  118. xpath.append("numberOfDropZones[@name=\"");
  119. xpath.append(computer).append("\"]/number");
  120. return xpath;
  121. }
  122. mutable bool isDropZoneRestrictionLoaded = false;
  123. mutable bool dropZoneRestrictionEnabled = true;
  124. public:
  125. IMPLEMENT_IINTERFACE;
  126. CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree *x=nullptr, const char* path="Environment");
  127. CLocalEnvironment(const char* path="config.xml");
  128. virtual ~CLocalEnvironment();
  129. virtual IStringVal & getName(IStringVal & str) const;
  130. virtual IStringVal & getXML(IStringVal & str) const;
  131. virtual IPropertyTree & getPTree() const;
  132. virtual IEnvironment& lock() const;
  133. virtual IConstDomainInfo * getDomain(const char * name) const;
  134. virtual IConstMachineInfo * getMachine(const char * name) const;
  135. virtual IConstMachineInfo * getMachineByAddress(const char * machineIp) const;
  136. virtual IConstMachineInfo * getMachineForLocalHost() const;
  137. virtual IConstDropZoneInfo * getDropZone(const char * name) const;
  138. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const;
  139. virtual IConstInstanceInfo * getInstance(const char * type, const char * version, const char *domain) const;
  140. virtual CConstInstanceInfo * getInstanceByIP(const char *type, const char *version, IpAddress &ip) const;
  141. virtual IConstComputerTypeInfo * getComputerType(const char * name) const;
  142. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr, const char *defprogname) const;
  143. virtual void preload();
  144. virtual IRemoteConnection* getConnection() const { return conn.getLink(); }
  145. void setXML(const char * logicalName);
  146. const char* getPath() const { return xPath.str(); }
  147. void unlockRemote();
  148. virtual bool isConstEnvironment() const { return true; }
  149. virtual void clearCache();
  150. virtual IConstMachineInfoIterator * getMachineIterator() const;
  151. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer, const char * dzname) const;
  152. virtual IConstDropZoneInfoIterator * getDropZoneIteratorByComputer(const char * computer) const;
  153. virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const;
  154. virtual IConstDropZoneInfoIterator * getDropZoneIterator() const;
  155. unsigned getNumberOfMachines() const { buildMachineCache(); return numOfMachines; }
  156. IConstMachineInfo * getMachineByIndex(unsigned index) const;
  157. unsigned getNumberOfDropZonesByComputer(const char * computer) const
  158. {
  159. buildDropZoneCache();
  160. StringBuffer xpath;
  161. createComputerNameXpath(computer, xpath);
  162. return numOfDropzonesByComputer->getPropInt(xpath);
  163. }
  164. IConstDropZoneInfo * getDropZoneByComputerByIndex(const char * computer, unsigned index) const;
  165. unsigned getNumberOfDropZones() const { buildDropZoneCache(); return numOfDropZones; }
  166. IConstDropZoneInfo * getDropZoneByIndex(unsigned index) const;
  167. bool isDropZoneRestrictionEnabled() const;
  168. };
  169. class CLockedEnvironment : implements IEnvironment, public CInterface
  170. {
  171. public:
  172. //note that order of construction/destruction is important
  173. Owned<CLocalEnvironment> c;
  174. Owned<CLocalEnvironment> env;
  175. Owned<CLocalEnvironment> constEnv;
  176. IMPLEMENT_IINTERFACE;
  177. CLockedEnvironment(CLocalEnvironment *_c)
  178. {
  179. Owned<IRemoteConnection> connection = _c->getConnection();
  180. if (connection)
  181. {
  182. constEnv.set(_c); //save original constant environment
  183. //we only wish to allow one party to allow updating the environment.
  184. //
  185. //create a new /NewEnvironment subtree, locked for read/write access for self and entire subtree; delete on disconnect
  186. //
  187. StringBuffer newName("/New");
  188. newName.append(constEnv->getPath());
  189. const unsigned int mode = RTM_CREATE | RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE |
  190. RTM_LOCK_SUB | RTM_DELETE_ON_DISCONNECT;
  191. Owned<IRemoteConnection> conn = querySDS().connect(newName.str(), myProcessSession(), mode, SDS_LOCK_TIMEOUT);
  192. if (conn == nullptr)
  193. {
  194. if (environmentTraceLevel > 0)
  195. PrintLog("Failed to create locked environment %s", newName.str());
  196. throw MakeStringException(-1, "Failed to get a lock on environment /%s", newName.str());
  197. }
  198. //save the locked environment
  199. env.setown(new CLocalEnvironment(conn, nullptr, newName.str()));
  200. //get a lock on the const environment
  201. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  202. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  203. if (conn2 == nullptr)
  204. {
  205. if (environmentTraceLevel > 0)
  206. PrintLog("Failed to lock environment %s", constEnv->getPath());
  207. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  208. }
  209. //copy const environment to our member environment
  210. Owned<IPropertyTree> pSrc = conn2->getRoot();
  211. c.setown( new CLocalEnvironment(nullptr, createPTreeFromIPT(pSrc)));
  212. conn2->rollback();
  213. }
  214. else
  215. {
  216. c.set(_c);
  217. }
  218. }
  219. virtual ~CLockedEnvironment()
  220. {
  221. }
  222. virtual IStringVal & getName(IStringVal & str) const
  223. { return c->getName(str); }
  224. virtual IStringVal & getXML(IStringVal & str) const
  225. { return c->getXML(str); }
  226. virtual IPropertyTree & getPTree() const
  227. { return c->getPTree(); }
  228. virtual IConstDomainInfo * getDomain(const char * name) const
  229. { return c->getDomain(name); }
  230. virtual IConstMachineInfo * getMachine(const char * name) const
  231. { return c->getMachine(name); }
  232. virtual IConstMachineInfo * getMachineByAddress(const char * machineIp) const
  233. { return c->getMachineByAddress(machineIp); }
  234. virtual IConstMachineInfo * getMachineForLocalHost() const
  235. { return c->getMachineForLocalHost(); }
  236. virtual IConstDropZoneInfo * getDropZone(const char * name) const
  237. { return c->getDropZone(name); }
  238. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const
  239. { return c->getDropZoneByComputer(computer); }
  240. virtual IConstInstanceInfo * getInstance(const char *type, const char *version, const char *domain) const
  241. { return c->getInstance(type, version, domain); }
  242. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr,const char *defprogname) const
  243. { return c->getRunInfo(path, dir, type, version, machineaddr, defprogname); }
  244. virtual IConstComputerTypeInfo * getComputerType(const char * name) const
  245. { return c->getComputerType(name); }
  246. virtual IEnvironment & lock() const
  247. { ((CInterface*)this)->Link(); return *(IEnvironment*)this; }
  248. virtual void commit();
  249. virtual void rollback();
  250. virtual void setXML(const char * pstr)
  251. { c->setXML(pstr); }
  252. virtual void preload()
  253. { c->preload(); }
  254. virtual bool isConstEnvironment() const { return false; }
  255. virtual void clearCache() { c->clearCache(); }
  256. virtual IConstMachineInfoIterator * getMachineIterator() const
  257. { return c->getMachineIterator(); }
  258. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer, const char * dzname) const
  259. { return c->getDropZoneByComputer(computer, dzname); }
  260. virtual IConstDropZoneInfoIterator * getDropZoneIteratorByComputer(const char * computer) const
  261. { return c->getDropZoneIteratorByComputer(computer); }
  262. virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const
  263. { return c->getDropZoneByAddressPath(netaddress, targetPath); }
  264. virtual IConstDropZoneInfoIterator * getDropZoneIterator() const
  265. { return c->getDropZoneIterator(); }
  266. virtual bool isDropZoneRestrictionEnabled() const
  267. { return c->isDropZoneRestrictionEnabled(); }
  268. };
  269. void CLockedEnvironment::commit()
  270. {
  271. if (constEnv)
  272. {
  273. //get a lock on const environment momentarily
  274. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  275. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  276. if (conn2 == nullptr)
  277. {
  278. if (environmentTraceLevel > 0)
  279. PrintLog("Failed to lock environment %s", constEnv->getPath());
  280. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  281. }
  282. //copy locked environment to const environment
  283. Owned<IPropertyTree> pSrc = &getPTree();
  284. Owned<IPropertyTree> pDst = conn2->queryRoot()->getBranch(nullptr);
  285. // JCS - I think it could (and would be more efficient if it had kept the original read lock connection to Env
  286. // - instead of using NewEnv as lock point, still work on copy, then changeMode of original connect
  287. // - as opposed to current scheme, where it recoonects in write mode and has to lazy fetch original env to update.
  288. // ensures pDst is equal to pSrc, whilst minimizing changes to pDst
  289. try { synchronizePTree(pDst, pSrc); }
  290. catch (IException *) { conn2->rollback(); throw; }
  291. conn2->commit();
  292. }
  293. else
  294. {
  295. Owned<IRemoteConnection> conn = c->getConnection();
  296. conn->commit();
  297. }
  298. }
  299. void CLockedEnvironment::rollback()
  300. {
  301. if (constEnv)
  302. {
  303. //get a lock on const environment momentarily
  304. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  305. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  306. if (conn2 == nullptr)
  307. {
  308. if (environmentTraceLevel > 0)
  309. PrintLog("Failed to lock environment %s", constEnv->getPath());
  310. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  311. }
  312. //copy const environment to locked environment (as it stands now) again losing any changes we made
  313. Owned<IPropertyTree> pSrc = conn2->getRoot();
  314. Owned<IPropertyTree> pDst = &getPTree();
  315. pDst->removeTree( pDst->queryPropTree("Hardware") );
  316. pDst->removeTree( pDst->queryPropTree("Software") );
  317. pDst->removeTree( pDst->queryPropTree("Programs") );
  318. pDst->removeTree( pDst->queryPropTree("Data") );
  319. mergePTree(pDst, pSrc);
  320. conn2->rollback();
  321. }
  322. else
  323. {
  324. Owned<IRemoteConnection> conn = c->getConnection();
  325. conn->rollback();
  326. }
  327. }
  328. //==========================================================================================
  329. // the following class implements notification handler for subscription to dali for environment
  330. // updates by other clients and is used by environment factory below. This also serves as
  331. // a sample self-contained implementation that can be easily tailored for other purposes.
  332. //==========================================================================================
  333. class CSdsSubscription : implements ISDSSubscription, public CInterface
  334. {
  335. public:
  336. CSdsSubscription()
  337. {
  338. m_constEnvUpdated = false;
  339. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  340. sub_id = envFactory->subscribe(this);
  341. }
  342. virtual ~CSdsSubscription()
  343. {
  344. /* note that ideally, we would make this class automatically
  345. unsubscribe in this destructor. However, underlying dali client
  346. layer (CDaliSubscriptionManagerStub) links to this object and so
  347. object would not get destroyed just by an application releasing it.
  348. The application either needs to explicitly unsubscribe or close
  349. the environment which unsubscribes during close down. */
  350. }
  351. void unsubscribe()
  352. {
  353. synchronized block(m_mutexEnv);
  354. if (sub_id)
  355. {
  356. Owned<IEnvironmentFactory> m_envFactory = getEnvironmentFactory();
  357. m_envFactory->unsubscribe(sub_id);
  358. sub_id = 0;
  359. }
  360. }
  361. IMPLEMENT_IINTERFACE;
  362. //another client (like configenv) may have updated the environment and we got notified
  363. //(thanks to our subscription) but don't just reload it yet since this notification is sent on
  364. //another thread asynchronously and we may be actively working with the old environment. Just
  365. //invoke handleEnvironmentChange() when we are ready to invalidate cache in environment factory.
  366. //
  367. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=nullptr)
  368. {
  369. DBGLOG("Environment was updated by another client of Dali server. Invalidating cache.\n");
  370. synchronized block(m_mutexEnv);
  371. m_constEnvUpdated = true;
  372. }
  373. void handleEnvironmentChange()
  374. {
  375. synchronized block(m_mutexEnv);
  376. if (m_constEnvUpdated)
  377. {
  378. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  379. Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
  380. constEnv->clearCache();
  381. m_constEnvUpdated = false;
  382. }
  383. }
  384. private:
  385. SubscriptionId sub_id;
  386. Mutex m_mutexEnv;
  387. bool m_constEnvUpdated;
  388. };
  389. //==========================================================================================
  390. class CEnvironmentFactory : public CInterface,
  391. implements IEnvironmentFactory, implements IDaliClientShutdown
  392. {
  393. public:
  394. IMPLEMENT_IINTERFACE;
  395. typedef ArrayOf<SubscriptionId> SubscriptionIDs;
  396. SubscriptionIDs subIDs;
  397. Mutex mutex;
  398. Owned<CSdsSubscription> subscription;
  399. CEnvironmentFactory()
  400. {
  401. }
  402. virtual void clientShutdown();
  403. virtual ~CEnvironmentFactory()
  404. {
  405. close(); //just in case it was not explicitly closed
  406. }
  407. virtual IConstEnvironment* openEnvironment()
  408. {
  409. synchronized procedure(mutex);
  410. if (!cache)
  411. {
  412. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  413. if (conn)
  414. cache.setown(new CLocalEnvironment(conn));
  415. }
  416. return cache.getLink();
  417. }
  418. virtual IEnvironment* updateEnvironment()
  419. {
  420. Owned<IConstEnvironment> pConstEnv = openEnvironment();
  421. synchronized procedure(mutex);
  422. return &pConstEnv->lock();
  423. }
  424. virtual IEnvironment * loadLocalEnvironmentFile(const char * filename)
  425. {
  426. Owned<IPropertyTree> ptree = createPTreeFromXMLFile(filename);
  427. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(nullptr, ptree);
  428. return new CLockedEnvironment(pLocalEnv);
  429. }
  430. virtual IEnvironment * loadLocalEnvironment(const char * xml)
  431. {
  432. Owned<IPropertyTree> ptree = createPTreeFromXMLString(xml);
  433. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(nullptr, ptree);
  434. return new CLockedEnvironment(pLocalEnv);
  435. }
  436. void close()
  437. {
  438. SubscriptionIDs copySubIDs;
  439. {
  440. synchronized procedure(mutex);
  441. cache.clear();
  442. //save the active subscriptions in another array
  443. //so they can be unsubscribed without causing deadlock
  444. // since ~CSdsSubscription() would ask us to unsubscribe the
  445. //same requiring a mutex lock (copy is a little price for this
  446. //normally small/empty array).
  447. //
  448. ForEachItemIn(i, subIDs)
  449. copySubIDs.append(subIDs.item(i));
  450. subIDs.kill();
  451. }
  452. //now unsubscribe all outstanding subscriptions
  453. //
  454. subscription.clear();
  455. ForEachItemIn(i, copySubIDs)
  456. querySDS().unsubscribe( copySubIDs.item(i) );
  457. }
  458. virtual SubscriptionId subscribe(ISDSSubscription* pSubHandler)
  459. {
  460. SubscriptionId sub_id = querySDS().subscribe("/Environment", *pSubHandler);
  461. synchronized procedure(mutex);
  462. subIDs.append(sub_id);
  463. return sub_id;
  464. }
  465. virtual void unsubscribe(SubscriptionId sub_id)
  466. {
  467. synchronized procedure(mutex);
  468. aindex_t i = subIDs.find(sub_id);
  469. if (i != NotFound)
  470. {
  471. querySDS().unsubscribe(sub_id);
  472. subIDs.remove(i);
  473. }
  474. }
  475. virtual void validateCache()
  476. {
  477. if (!subscription)
  478. subscription.setown( new CSdsSubscription() );
  479. subscription->handleEnvironmentChange();
  480. }
  481. private:
  482. IRemoteConnection* connect(const char *xpath, unsigned flags)
  483. {
  484. return querySDS().connect(xpath, myProcessSession(), flags, SDS_LOCK_TIMEOUT);
  485. }
  486. };
  487. static CEnvironmentFactory *factory=nullptr;
  488. void CEnvironmentFactory::clientShutdown()
  489. {
  490. closeEnvironment();
  491. }
  492. MODULE_INIT(INIT_PRIORITY_ENV_ENVIRONMENT)
  493. {
  494. return true;
  495. }
  496. MODULE_EXIT()
  497. {
  498. ::Release(factory);
  499. }
  500. //==========================================================================================
  501. class CConstEnvBase : public CInterface
  502. {
  503. protected:
  504. const CLocalEnvironment* env; // Not linked - would be circular....
  505. // That could cause problems
  506. Linked<IPropertyTree> root;
  507. public:
  508. CConstEnvBase(const CLocalEnvironment* _env, IPropertyTree *_root)
  509. : env(_env), root(_root)
  510. {
  511. }
  512. IStringVal& getXML(IStringVal &str) const
  513. {
  514. StringBuffer x;
  515. toXML(root->queryBranch("."), x);
  516. str.set(x.str());
  517. return str;
  518. };
  519. IStringVal& getName(IStringVal &str) const
  520. {
  521. str.set(root->queryProp("@name"));
  522. return str;
  523. }
  524. IPropertyTree& getPTree() const
  525. {
  526. return *LINK(root);
  527. }
  528. };
  529. #define IMPLEMENT_ICONSTENVBASE \
  530. virtual IStringVal& getXML(IStringVal &str) const { return CConstEnvBase::getXML(str); } \
  531. virtual IStringVal& getName(IStringVal &str) const { return CConstEnvBase::getName(str); } \
  532. virtual IPropertyTree& getPTree() const { return CConstEnvBase::getPTree(); }
  533. //==========================================================================================
  534. class CConstDomainInfo : public CConstEnvBase, implements IConstDomainInfo
  535. {
  536. public:
  537. IMPLEMENT_IINTERFACE;
  538. IMPLEMENT_ICONSTENVBASE;
  539. CConstDomainInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  540. virtual void getAccountInfo(IStringVal &name, IStringVal &pw) const
  541. {
  542. if (root->hasProp("@username"))
  543. name.set(root->queryProp("@username"));
  544. else
  545. name.clear();
  546. if (root->hasProp("@password"))
  547. {
  548. StringBuffer pwd;
  549. decrypt(pwd, root->queryProp("@password"));
  550. pw.set(pwd.str());
  551. }
  552. else
  553. pw.clear();
  554. }
  555. virtual void getSnmpSecurityString(IStringVal & securityString) const
  556. {
  557. if (root->hasProp("@snmpSecurityString"))
  558. {
  559. StringBuffer sec_string;
  560. decrypt(sec_string, root->queryProp("@snmpSecurityString"));
  561. securityString.set(sec_string.str());
  562. }
  563. else
  564. securityString.set("");
  565. }
  566. virtual void getSSHAccountInfo(IStringVal &name, IStringVal &sshKeyFile, IStringVal& sshKeyPassphrase) const
  567. {
  568. if (root->hasProp("@username"))
  569. name.set(root->queryProp("@username"));
  570. else
  571. name.clear();
  572. if (root->hasProp("@sshKeyFile"))
  573. sshKeyFile.set(root->queryProp("@sshKeyFile"));
  574. else
  575. sshKeyFile.clear();
  576. if (root->hasProp("@sshKeyPassphrase"))
  577. sshKeyPassphrase.set(root->queryProp("@sshKeyPassphrase"));
  578. else
  579. sshKeyPassphrase.clear();
  580. }
  581. };
  582. //==========================================================================================
  583. struct mapOsEnums { EnvMachineOS val; const char *str; };
  584. static EnvMachineOS getEnum(IPropertyTree *p, const char *propname, mapOsEnums *map)
  585. {
  586. const char *v = p->queryProp(propname);
  587. if (v && *v)
  588. {
  589. while (map->str)
  590. {
  591. if (stricmp(v, map->str)==0)
  592. return map->val;
  593. map++;
  594. }
  595. throw MakeStringException(0, "Unknown operating system: \"%s\"", v);
  596. }
  597. return MachineOsUnknown;
  598. }
  599. struct mapStateEnums { EnvMachineState val; const char *str; };
  600. static EnvMachineState getEnum(IPropertyTree *p, const char *propname, mapStateEnums *map)
  601. {
  602. const char *v = p->queryProp(propname);
  603. if (v && *v)
  604. {
  605. while (map->str)
  606. {
  607. if (stricmp(v, map->str)==0)
  608. return map->val;
  609. map++;
  610. }
  611. assertex(!"Unexpected value in getEnum");
  612. }
  613. return MachineStateUnknown;
  614. }
  615. mapOsEnums OperatingSystems[] = {
  616. { MachineOsW2K, "W2K" },
  617. { MachineOsSolaris, "solaris" },
  618. { MachineOsLinux, "linux" },
  619. { MachineOsSize, nullptr }
  620. };
  621. mapStateEnums MachineStates[] = {
  622. { MachineStateAvailable, "Available" },
  623. { MachineStateUnavailable, "Unavailable" },
  624. { MachineStateUnknown, "Unknown" }
  625. };
  626. //==========================================================================================
  627. class CConstMachineInfo : public CConstEnvBase, implements IConstMachineInfo
  628. {
  629. public:
  630. IMPLEMENT_IINTERFACE;
  631. IMPLEMENT_ICONSTENVBASE;
  632. CConstMachineInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  633. virtual IConstDomainInfo* getDomain() const
  634. {
  635. return env->getDomain(root->queryProp("@domain"));
  636. }
  637. virtual IStringVal& getNetAddress(IStringVal &str) const
  638. {
  639. str.set(root->queryProp("@netAddress"));
  640. return str;
  641. }
  642. virtual IStringVal& getDescription(IStringVal &str) const
  643. {
  644. UNIMPLEMENTED;
  645. }
  646. virtual unsigned getNicSpeedMbitSec() const
  647. {
  648. const char * v = root->queryProp("@nicSpeed");
  649. if (v && *v)
  650. return atoi(v);
  651. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  652. if (type)
  653. return type->getNicSpeedMbitSec();
  654. return 0;
  655. }
  656. virtual EnvMachineOS getOS() const
  657. {
  658. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  659. if (os != MachineOsUnknown)
  660. return os;
  661. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  662. if (type)
  663. return type->getOS();
  664. return MachineOsUnknown;
  665. }
  666. virtual EnvMachineState getState() const
  667. {
  668. return getEnum(root, "@state", MachineStates);
  669. }
  670. };
  671. //==========================================================================================
  672. class CConstComputerTypeInfo : public CConstEnvBase, implements IConstComputerTypeInfo
  673. {
  674. public:
  675. IMPLEMENT_IINTERFACE;
  676. IMPLEMENT_ICONSTENVBASE;
  677. CConstComputerTypeInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  678. virtual EnvMachineOS getOS() const
  679. {
  680. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  681. if (os != MachineOsUnknown)
  682. return os;
  683. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  684. if (type && (type.get() != this))
  685. return type->getOS();
  686. return MachineOsUnknown;
  687. }
  688. virtual unsigned getNicSpeedMbitSec() const
  689. {
  690. const char * v = root->queryProp("@nicSpeed");
  691. if (v && *v)
  692. return atoi(v);
  693. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  694. if (type && (type.get() != this))
  695. return type->getNicSpeedMbitSec();
  696. return 0;
  697. }
  698. };
  699. //==========================================================================================
  700. class CConstInstanceInfo : public CConstEnvBase, implements IConstInstanceInfo
  701. {
  702. public:
  703. IMPLEMENT_IINTERFACE;
  704. IMPLEMENT_ICONSTENVBASE;
  705. CConstInstanceInfo(const CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root)
  706. {
  707. }
  708. virtual IConstMachineInfo * getMachine() const
  709. {
  710. return env->getMachine(root->queryProp("@computer"));
  711. }
  712. virtual IStringVal & getEndPoint(IStringVal & str) const
  713. {
  714. SCMStringBuffer ep;
  715. Owned<IConstMachineInfo> machine = getMachine();
  716. if (machine)
  717. {
  718. machine->getNetAddress(ep);
  719. const char *port = root->queryProp("@port");
  720. if (port)
  721. ep.s.append(':').append(port);
  722. }
  723. str.set(ep.str());
  724. return str;
  725. }
  726. virtual IStringVal & getExecutableDirectory(IStringVal & str) const
  727. {
  728. // this is the deploy directory so uses local path separators (I suspect this call is LEGACY now)
  729. SCMStringBuffer ep;
  730. Owned<IConstMachineInfo> machine = getMachine();
  731. if (machine)
  732. {
  733. machine->getNetAddress(ep);
  734. ep.s.insert(0, PATHSEPSTR PATHSEPSTR);
  735. }
  736. ep.s.append(PATHSEPCHAR).append(root->queryProp("@directory"));
  737. str.set(ep.str());
  738. return str;
  739. }
  740. virtual bool doGetRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname, bool useprog) const
  741. {
  742. // this is remote path i.e. path should match *target* nodes format
  743. Owned<IConstMachineInfo> machine = getMachine();
  744. if (!machine)
  745. return false;
  746. char psep;
  747. bool appendexe;
  748. switch (machine->getOS())
  749. {
  750. case MachineOsSolaris:
  751. case MachineOsLinux:
  752. psep = '/';
  753. appendexe = false;
  754. break;
  755. default:
  756. psep = '\\';
  757. appendexe = true;
  758. }
  759. StringBuffer tmp;
  760. const char *program = useprog?root->queryProp("@program"):nullptr; // if program specified assume absolute
  761. if (!program||!*program)
  762. {
  763. SCMStringBuffer ep;
  764. machine->getNetAddress(ep);
  765. const char *dir = root->queryProp("@directory");
  766. if (dir)
  767. {
  768. if (isPathSepChar(*dir))
  769. dir++;
  770. if (!*dir)
  771. return false;
  772. tmp.append(psep).append(psep).append(ep.s).append(psep);
  773. do {
  774. if (isPathSepChar(*dir))
  775. tmp.append(psep);
  776. else
  777. tmp.append(*dir);
  778. dir++;
  779. } while (*dir);
  780. if (!isPathSepChar(tmp.charAt(tmp.length()-1)))
  781. tmp.append(psep);
  782. tmp.append(defprogname);
  783. size32_t l = strlen(defprogname);
  784. if (appendexe&&((l<5)||(stricmp(defprogname+l-4,".exe")!=0)))
  785. tmp.append(".exe");
  786. }
  787. program = tmp.str();
  788. }
  789. progpath.set(program);
  790. const char *workd = root->queryProp("@workdir"); // if program specified assume absolute
  791. workdir.set(workd?workd:"");
  792. return true;
  793. }
  794. virtual bool getRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname) const
  795. {
  796. return doGetRunInfo(progpath,workdir,defprogname,true);
  797. }
  798. virtual unsigned getPort() const
  799. {
  800. return root->getPropInt("@port", 0);
  801. }
  802. };
  803. class CConstDropZoneServerInfo : public CConstEnvBase, implements IConstDropZoneServerInfo
  804. {
  805. public:
  806. IMPLEMENT_IINTERFACE;
  807. IMPLEMENT_ICONSTENVBASE;
  808. CConstDropZoneServerInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root), prop(root) {}
  809. virtual StringBuffer & getName(StringBuffer & name) const
  810. {
  811. name.append(prop->queryProp("@name"));
  812. return name;
  813. }
  814. virtual StringBuffer & getServer(StringBuffer & server) const
  815. {
  816. server.append(prop->queryProp("@server"));
  817. return server;
  818. }
  819. private:
  820. IPropertyTree * prop;
  821. };
  822. class CConstDropZoneInfo : public CConstEnvBase, implements IConstDropZoneInfo
  823. {
  824. public:
  825. IMPLEMENT_IINTERFACE;
  826. IMPLEMENT_ICONSTENVBASE;
  827. CConstDropZoneInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  828. virtual IStringVal& getComputerName(IStringVal &str) const
  829. {
  830. str.set(root->queryProp("@computer"));
  831. return str;
  832. }
  833. virtual IStringVal& getDescription(IStringVal &str) const
  834. {
  835. str.set(root->queryProp("@description"));
  836. return str;
  837. }
  838. virtual IStringVal& getDirectory(IStringVal &str) const
  839. {
  840. str.set(root->queryProp("@directory"));
  841. return str;
  842. }
  843. virtual IStringVal& getUMask(IStringVal &str) const
  844. {
  845. if (root->hasProp("@umask"))
  846. str.set(root->queryProp("@umask"));
  847. return str;
  848. }
  849. virtual bool isECLWatchVisible() const
  850. {
  851. return root->getPropBool("@ECLWatchVisible", true);
  852. }
  853. virtual IConstDropZoneServerInfoIterator * getServers() const
  854. {
  855. return new CConstDropZoneServerInfoIterator(this);
  856. }
  857. };
  858. #if 0
  859. //==========================================================================================
  860. class CConstProcessInfo : public CConstEnvBase, implements IConstProcessInfo
  861. {
  862. IArrayOf<IConstInstanceInfo> w;
  863. CArrayIteratorOf<IInterface, IIterator> it;
  864. public:
  865. IMPLEMENT_IINTERFACE;
  866. IMPLEMENT_ICONSTENVBASE;
  867. CConstProcessInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root), it(w)
  868. {
  869. Owned<IPropertyTreeIterator> _it = root->getElements("*"); // MORE - should be instance
  870. for (_it->first(); _it->isValid(); _it->next())
  871. {
  872. IPropertyTree *rp = &_it->query();
  873. w.append(*new CConstInstanceInfo(env, rp)); // CConstInstanceInfo will link rp
  874. }
  875. }
  876. bool first() { return it.first(); }
  877. bool isValid() { return it.isValid(); }
  878. bool next() { return it.next(); }
  879. IConstInstanceInfo & query() { return (IConstInstanceInfo &) it.query();}
  880. virtual IConstInstanceInfo * getInstance(const char *domain)
  881. {
  882. for (int pass=0; pass<2; pass++)
  883. {
  884. ForEachItemIn(idx, w)
  885. {
  886. Owned<IConstMachineInfo> m = w.item(idx).getMachine();
  887. if (m)
  888. {
  889. Owned<IConstDomainInfo> dm = m->getDomain();
  890. if (dm)
  891. {
  892. StringBuffer thisdomain;
  893. //dm->getName(StringBufferAdaptor(thisdomain)); // confuses g++
  894. StringBufferAdaptor strval(thisdomain);
  895. dm->getName(strval);
  896. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  897. return LINK(&w.item(idx));
  898. }
  899. }
  900. }
  901. }
  902. return nullptr;
  903. }
  904. };
  905. #endif
  906. //==========================================================================================
  907. CLocalEnvironment::CLocalEnvironment(const char* environmentFile)
  908. {
  909. if (environmentFile && *environmentFile)
  910. {
  911. IPropertyTree* root = createPTreeFromXMLFile(environmentFile);
  912. if (root)
  913. p.set(root);
  914. }
  915. init();
  916. }
  917. CLocalEnvironment::CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree* root/*=nullptr*/,
  918. const char* path/*="/Environment"*/)
  919. : xPath(path)
  920. {
  921. conn.set(_conn);
  922. if (root)
  923. p.set(root);
  924. else
  925. p.setown(conn->getRoot());
  926. init();
  927. }
  928. void CLocalEnvironment::init()
  929. {
  930. machineCacheBuilt = false;
  931. dropZoneCacheBuilt = false;
  932. numOfMachines = 0;
  933. numOfDropZones = 0;
  934. numOfDropzonesByComputer.setown(createPTree("computers"));
  935. isDropZoneRestrictionLoaded = false;
  936. }
  937. CLocalEnvironment::~CLocalEnvironment()
  938. {
  939. if (conn)
  940. conn->rollback();
  941. }
  942. IEnvironment& CLocalEnvironment::lock() const
  943. {
  944. return *new CLockedEnvironment((CLocalEnvironment*)this);
  945. }
  946. IStringVal & CLocalEnvironment::getName(IStringVal & str) const
  947. {
  948. synchronized procedure(safeCache);
  949. str.set(p->queryProp("@name"));
  950. return str;
  951. }
  952. IStringVal & CLocalEnvironment::getXML(IStringVal & str) const
  953. {
  954. StringBuffer xml;
  955. {
  956. synchronized procedure(safeCache);
  957. toXML(p->queryBranch("."), xml);
  958. }
  959. str.set(xml.str());
  960. return str;
  961. }
  962. IPropertyTree & CLocalEnvironment::getPTree() const
  963. {
  964. synchronized procedure(safeCache);
  965. return *LINK(p);
  966. }
  967. IConstEnvBase * CLocalEnvironment::getCache(const char *path) const
  968. {
  969. IConstEnvBase * ret = cache.getValue(path);
  970. ::Link(ret);
  971. return ret;
  972. }
  973. void CLocalEnvironment::setCache(const char *path, IConstEnvBase *value) const
  974. {
  975. cache.setValue(path, value);
  976. }
  977. IConstDomainInfo * CLocalEnvironment::getDomain(const char * name) const
  978. {
  979. if (!name)
  980. return nullptr;
  981. StringBuffer xpath;
  982. xpath.appendf("Hardware/Domain[@name=\"%s\"]", name);
  983. synchronized procedure(safeCache);
  984. IConstEnvBase *cached = getCache(xpath.str());
  985. if (!cached)
  986. {
  987. IPropertyTree *d = p->queryPropTree(xpath.str());
  988. if (!d)
  989. return nullptr;
  990. cached = new CConstDomainInfo((CLocalEnvironment *) this, d);
  991. setCache(xpath.str(), cached);
  992. }
  993. return (IConstDomainInfo *) cached;
  994. }
  995. void CLocalEnvironment::buildMachineCache() const
  996. {
  997. synchronized procedure(safeCache);
  998. if (!machineCacheBuilt)
  999. {
  1000. Owned<IPropertyTreeIterator> it = p->getElements("Hardware/Computer");
  1001. ForEach(*it)
  1002. {
  1003. const char *name = it->query().queryProp("@name");
  1004. if (name)
  1005. {
  1006. StringBuffer x("Hardware/Computer[@name=\"");
  1007. x.append(name).append("\"]");
  1008. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1009. cache.setValue(x.str(), cached);
  1010. }
  1011. const char * netAddress = it->query().queryProp("@netAddress");
  1012. if (netAddress)
  1013. {
  1014. StringBuffer x("Hardware/Computer[@netAddress=\"");
  1015. x.append(netAddress).append("\"]");
  1016. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1017. cache.setValue(x.str(), cached);
  1018. IpAddress ip;
  1019. ip.ipset(netAddress);
  1020. if (ip.isLocal())
  1021. cache.setValue("Hardware/Computer[@netAddress=\".\"]", cached);
  1022. }
  1023. numOfMachines++;
  1024. StringBuffer x("Hardware/Computer[@id=\"");
  1025. x.append(MACHINE_PREFIX).append(numOfMachines).append("\"]");
  1026. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  1027. cache.setValue(x.str(), cached);
  1028. }
  1029. machineCacheBuilt = true;
  1030. }
  1031. }
  1032. void CLocalEnvironment::buildDropZoneCache() const
  1033. {
  1034. synchronized procedure(safeCache);
  1035. if (!dropZoneCacheBuilt)
  1036. {
  1037. Owned<IPropertyTreeIterator> it = p->getElements("Software/DropZone");
  1038. ForEach(*it)
  1039. {
  1040. const char *name = it->query().queryProp("@name");
  1041. if (name)
  1042. {
  1043. StringBuffer x("Software/DropZone[@name=\"");
  1044. x.append(name).append("\"]");
  1045. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  1046. cache.setValue(x.str(), cached);
  1047. }
  1048. const char * computer = it->query().queryProp("@computer");
  1049. if (computer)
  1050. {
  1051. StringBuffer xpath;
  1052. createComputerNameXpath(computer, xpath);
  1053. unsigned numOfDropZoneByComputer = numOfDropzonesByComputer->getPropInt(xpath.str(), -1);
  1054. if (numOfDropZoneByComputer == -1)
  1055. {
  1056. numOfDropZoneByComputer = 0;
  1057. IPropertyTree * val = createPTree("numberOfDropZones");
  1058. val->addPropInt("@number",numOfDropZoneByComputer);
  1059. val->addProp("@name", computer);
  1060. numOfDropzonesByComputer->addPropTree("numberOfDropZones",val);
  1061. }
  1062. numOfDropZoneByComputer++;
  1063. numOfDropzonesByComputer->setPropInt(xpath.str(), numOfDropZoneByComputer);
  1064. StringBuffer x("Software/DropZone[@computer=\"");
  1065. x.append(computer);
  1066. x.append(DROPZONE_BY_MACHINE_SUFFIX).append(numOfDropZoneByComputer);
  1067. x.append("\"]");
  1068. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  1069. cache.setValue(x.str(), cached);
  1070. }
  1071. numOfDropZones++;
  1072. StringBuffer x("Software/DropZone[@id=\"");
  1073. x.append(DROPZONE_SUFFIX).append(numOfDropZones).append("\"]");
  1074. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  1075. cache.setValue(x.str(), cached);
  1076. }
  1077. dropZoneCacheBuilt = true;
  1078. }
  1079. }
  1080. IConstComputerTypeInfo * CLocalEnvironment::getComputerType(const char * name) const
  1081. {
  1082. if (!name)
  1083. return nullptr;
  1084. StringBuffer xpath;
  1085. xpath.appendf("Hardware/ComputerType[@name=\"%s\"]", name);
  1086. synchronized procedure(safeCache);
  1087. IConstEnvBase *cached = getCache(xpath.str());
  1088. if (!cached)
  1089. {
  1090. IPropertyTree *d = p->queryPropTree(xpath.str());
  1091. if (!d)
  1092. return nullptr;
  1093. cached = new CConstComputerTypeInfo((CLocalEnvironment *) this, d);
  1094. setCache(xpath.str(), cached);
  1095. }
  1096. return (CConstComputerTypeInfo *) cached;
  1097. }
  1098. IConstMachineInfo * CLocalEnvironment::getMachine(const char * name) const
  1099. {
  1100. if (!name)
  1101. return nullptr;
  1102. buildMachineCache();
  1103. StringBuffer xpath;
  1104. xpath.appendf("Hardware/Computer[@name=\"%s\"]", name);
  1105. synchronized procedure(safeCache);
  1106. IConstEnvBase *cached = getCache(xpath.str());
  1107. if (!cached)
  1108. {
  1109. IPropertyTree *d = p->queryPropTree(xpath.str());
  1110. if (!d)
  1111. return nullptr;
  1112. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  1113. setCache(xpath.str(), cached);
  1114. }
  1115. return (CConstMachineInfo *) cached;
  1116. }
  1117. IConstMachineInfo * CLocalEnvironment::getMachineByAddress(const char * machineIp) const
  1118. {
  1119. if (!machineIp)
  1120. return nullptr;
  1121. buildMachineCache();
  1122. Owned<IPropertyTreeIterator> iter;
  1123. StringBuffer xpath;
  1124. xpath.appendf("Hardware/Computer[@netAddress=\"%s\"]", machineIp);
  1125. synchronized procedure(safeCache);
  1126. IConstEnvBase *cached = getCache(xpath.str());
  1127. if (!cached)
  1128. {
  1129. IPropertyTree *d = p->queryPropTree(xpath.str());
  1130. if (!d)
  1131. {
  1132. // I suspect not in the original spirit of this but look for resolved IP
  1133. Owned<IPropertyTreeIterator> iter = p->getElements("Hardware/Computer");
  1134. IpAddress ip;
  1135. ip.ipset(machineIp);
  1136. ForEach(*iter)
  1137. {
  1138. IPropertyTree &computer = iter->query();
  1139. IpAddress ip2;
  1140. const char *ips = computer.queryProp("@netAddress");
  1141. if (ips&&*ips)
  1142. {
  1143. ip2.ipset(ips);
  1144. if (ip.ipequals(ip2))
  1145. {
  1146. d = &computer;
  1147. break;
  1148. }
  1149. }
  1150. }
  1151. }
  1152. if (!d)
  1153. return nullptr;
  1154. StringBuffer xpath1;
  1155. xpath1.appendf("Hardware/Computer[@name=\"%s\"]", d->queryProp("@name"));
  1156. cached = getCache(xpath1.str());
  1157. if (!cached)
  1158. {
  1159. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  1160. setCache(xpath1.str(), cached);
  1161. setCache(xpath.str(), cached);
  1162. }
  1163. }
  1164. return (CConstMachineInfo *) cached;
  1165. }
  1166. IConstMachineInfo * CLocalEnvironment::getMachineByIndex(unsigned index) const
  1167. {
  1168. if (!numOfMachines || (index == 0))
  1169. return nullptr;
  1170. buildMachineCache();
  1171. if (index > numOfMachines)
  1172. return nullptr;
  1173. StringBuffer xpath("Hardware/Computer[@id=\"");
  1174. xpath.append(MACHINE_PREFIX).append(index).append("\"]");
  1175. synchronized procedure(safeCache);
  1176. return (IConstMachineInfo *) getCache(xpath.str());
  1177. }
  1178. IConstMachineInfo * CLocalEnvironment::getMachineForLocalHost() const
  1179. {
  1180. buildMachineCache();
  1181. synchronized procedure(safeCache);
  1182. return (CConstMachineInfo *) getCache("Hardware/Computer[@netAddress=\".\"]");
  1183. }
  1184. IConstDropZoneInfo * CLocalEnvironment::getDropZone(const char * name) const
  1185. {
  1186. if (!name)
  1187. return nullptr;
  1188. buildDropZoneCache();
  1189. VStringBuffer xpath("Software/DropZone[@name=\"%s\"]", name);
  1190. synchronized procedure(safeCache);
  1191. return (CConstDropZoneInfo *) getCache(xpath.str());
  1192. }
  1193. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputer(const char * computer) const
  1194. {
  1195. if (!computer)
  1196. return nullptr;
  1197. buildDropZoneCache();
  1198. StringBuffer x;
  1199. createComputerNameXpath(computer, x);
  1200. unsigned numOfDropZoneByComputer = numOfDropzonesByComputer->getPropInt(x, -1);
  1201. if (numOfDropZoneByComputer == -1)
  1202. return nullptr;
  1203. StringBuffer xpath("Software/DropZone[@computer=\"");
  1204. xpath.append(computer);
  1205. xpath.append(DROPZONE_BY_MACHINE_SUFFIX).append(DEFAULT_DROPZONE_INDEX);
  1206. xpath.append("\"]");
  1207. synchronized procedure(safeCache);
  1208. return (CConstDropZoneInfo *) getCache(xpath.str());
  1209. }
  1210. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputer(const char * computer, const char * dzname) const
  1211. {
  1212. IConstDropZoneInfo * dzInfo = getDropZone(dzname);
  1213. if (!dzInfo)
  1214. return nullptr;
  1215. SCMStringBuffer cachedComputer;
  1216. dzInfo->getComputerName(cachedComputer);
  1217. if (!streq(computer, cachedComputer.str()))
  1218. return nullptr;
  1219. return dzInfo;
  1220. }
  1221. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputerByIndex(const char * computer, unsigned index) const
  1222. {
  1223. if (!computer || (index == 0))
  1224. return nullptr;
  1225. buildDropZoneCache();
  1226. if (index > getNumberOfDropZonesByComputer(computer))
  1227. return nullptr;
  1228. StringBuffer xpath("Software/DropZone[@computer=\"");
  1229. xpath.append(computer).append(DROPZONE_BY_MACHINE_SUFFIX).append(index).append("\"]");
  1230. synchronized procedure(safeCache);
  1231. return (CConstDropZoneInfo *) getCache(xpath.str());
  1232. }
  1233. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByIndex(unsigned index) const
  1234. {
  1235. if (!numOfDropZones || (index == 0))
  1236. return nullptr;
  1237. buildDropZoneCache();
  1238. if (index > numOfDropZones)
  1239. return nullptr;
  1240. StringBuffer xpath("Software/DropZone[@id=\"");
  1241. xpath.append(DROPZONE_SUFFIX).append(index).append("\"]");
  1242. synchronized procedure(safeCache);
  1243. return (CConstDropZoneInfo *) getCache(xpath.str());
  1244. }
  1245. IConstInstanceInfo * CLocalEnvironment::getInstance(const char *type, const char *version, const char *domain) const
  1246. {
  1247. StringBuffer xpath("Software/");
  1248. xpath.append(type);
  1249. if (version)
  1250. xpath.append("[@version='").append(version).append("']");
  1251. xpath.append("/Instance");
  1252. synchronized procedure(safeCache);
  1253. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1254. for (_it->first(); _it->isValid(); _it->next())
  1255. {
  1256. IPropertyTree *rp = &_it->query();
  1257. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1258. Owned<IConstMachineInfo> m = inst->getMachine();
  1259. if (m)
  1260. {
  1261. Owned<IConstDomainInfo> dm = m->getDomain();
  1262. if (dm)
  1263. {
  1264. SCMStringBuffer thisdomain;
  1265. dm->getName(thisdomain);
  1266. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  1267. return inst.getClear();
  1268. }
  1269. }
  1270. }
  1271. return nullptr;
  1272. }
  1273. CConstInstanceInfo * CLocalEnvironment::getInstanceByIP(const char *type, const char *version, IpAddress &ip) const
  1274. {
  1275. StringBuffer xpath("Software/");
  1276. xpath.append(type);
  1277. if (version)
  1278. xpath.append("[@version='").append(version).append("']");
  1279. xpath.append("/Instance");
  1280. synchronized procedure(safeCache);
  1281. assertex(p);
  1282. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1283. assertex(_it);
  1284. for (_it->first(); _it->isValid(); _it->next())
  1285. {
  1286. IPropertyTree *rp = &_it->query();
  1287. assertex(rp);
  1288. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1289. Owned<IConstMachineInfo> m = inst->getMachine();
  1290. if (m)
  1291. {
  1292. SCMStringBuffer eps;
  1293. m->getNetAddress(eps);
  1294. SocketEndpoint ep(eps.str());
  1295. if (ep.ipequals(ip))
  1296. return inst.getClear();
  1297. }
  1298. }
  1299. return nullptr;
  1300. }
  1301. void CLocalEnvironment::unlockRemote()
  1302. {
  1303. #if 0
  1304. conn->commit(true);
  1305. conn->changeMode(0, SDS_LOCK_TIMEOUT);
  1306. #else
  1307. if (conn)
  1308. {
  1309. synchronized procedure(safeCache);
  1310. p.clear();
  1311. conn.setown(querySDS().connect(xPath.str(), myProcessSession(), 0, SDS_LOCK_TIMEOUT));
  1312. p.setown(conn->getRoot());
  1313. }
  1314. #endif
  1315. }
  1316. void CLocalEnvironment::preload()
  1317. {
  1318. synchronized procedure(safeCache);
  1319. p->queryBranch(".");
  1320. }
  1321. void CLocalEnvironment::setXML(const char *xml)
  1322. {
  1323. Owned<IPropertyTree> newRoot = createPTreeFromXMLString(xml);
  1324. synchronized procedure(safeCache);
  1325. Owned<IPropertyTreeIterator> it = p->getElements("*");
  1326. ForEach(*it)
  1327. {
  1328. p->removeTree(&it->query());
  1329. }
  1330. it.setown(newRoot->getElements("*"));
  1331. ForEach(*it)
  1332. {
  1333. IPropertyTree *sub = &it->get();
  1334. p->addPropTree(sub->queryName(), sub);
  1335. }
  1336. }
  1337. bool CLocalEnvironment::getRunInfo(IStringVal & path, IStringVal & dir, const char * tag, const char * version, const char *machineaddr, const char *defprogname) const
  1338. {
  1339. try
  1340. {
  1341. // PrintLog("getExecutablePath %s %s %s", tag, version, machineaddr);
  1342. // first see if local machine with deployed on
  1343. SocketEndpoint ep(machineaddr);
  1344. Owned<CConstInstanceInfo> ipinstance = getInstanceByIP(tag, version, ep);
  1345. if (ipinstance)
  1346. {
  1347. StringAttr testpath;
  1348. StringAttrAdaptor teststrval(testpath);
  1349. if (ipinstance->doGetRunInfo(teststrval,dir,defprogname,false))
  1350. { // this returns full string
  1351. RemoteFilename rfn;
  1352. rfn.setRemotePath(testpath.get());
  1353. Owned<IFile> file = createIFile(rfn);
  1354. if (file->exists())
  1355. {
  1356. StringBuffer tmp;
  1357. rfn.getLocalPath(tmp);
  1358. path.set(tmp.str());
  1359. return true;
  1360. }
  1361. }
  1362. }
  1363. Owned<IConstMachineInfo> machine = getMachineByAddress(machineaddr);
  1364. if (!machine)
  1365. {
  1366. LOG(MCdebugInfo, unknownJob, "Unable to find machine for %s", machineaddr);
  1367. return false;
  1368. }
  1369. StringAttr targetdomain;
  1370. Owned<IConstDomainInfo> domain = machine->getDomain();
  1371. if (!domain)
  1372. {
  1373. LOG(MCdebugInfo, unknownJob, "Unable to find domain for %s", machineaddr);
  1374. return false;
  1375. }
  1376. //domain->getName(StringAttrAdaptor(targetdomain)); // confuses g++
  1377. StringAttrAdaptor strval(targetdomain);
  1378. domain->getName(strval);
  1379. Owned<IConstInstanceInfo> instance = getInstance(tag, version, targetdomain);
  1380. if (!instance)
  1381. {
  1382. LOG(MCdebugInfo, unknownJob, "Unable to find process %s for domain %s", tag, targetdomain.get());
  1383. return false;
  1384. }
  1385. return instance->getRunInfo(path,dir,defprogname);
  1386. }
  1387. catch (IException * e)
  1388. {
  1389. EXCLOG(e, "Extracting slave version");
  1390. e->Release();
  1391. return false;
  1392. }
  1393. }
  1394. void CLocalEnvironment::clearCache()
  1395. {
  1396. synchronized procedure(safeCache);
  1397. if (conn)
  1398. {
  1399. p.clear();
  1400. unsigned mode = 0;
  1401. try
  1402. {
  1403. conn->reload();
  1404. }
  1405. catch (IException *e)
  1406. {
  1407. EXCLOG(e, "Failed to reload connection");
  1408. e->Release();
  1409. mode = conn->queryMode();
  1410. conn.clear();
  1411. }
  1412. if (!conn)
  1413. conn.setown(querySDS().connect(xPath, myProcessSession(), mode, SDS_LOCK_TIMEOUT));
  1414. p.setown(conn->getRoot());
  1415. }
  1416. cache.kill();
  1417. numOfDropzonesByComputer.clear();
  1418. init();
  1419. resetPasswordsFromSDS();
  1420. }
  1421. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByAddressPath(const char * netaddress, const char *targetFilePath) const
  1422. {
  1423. IConstDropZoneInfo * dropZone = nullptr;
  1424. IpAddress targetIp(netaddress);
  1425. unsigned dropzonePathLen = _MAX_PATH + 1;
  1426. #ifdef _DEBUG
  1427. LOG(MCdebugInfo, unknownJob, "Netaddress: '%s', targetFilePath: '%s'", netaddress, targetFilePath);
  1428. #endif
  1429. // Check the directory path first
  1430. Owned<IConstDropZoneInfoIterator> zoneIt = getDropZoneIterator();
  1431. ForEach(*zoneIt)
  1432. {
  1433. SCMStringBuffer dropZoneDir;
  1434. zoneIt->query().getDirectory(dropZoneDir);
  1435. StringBuffer fullDropZoneDir(dropZoneDir.str());
  1436. addPathSepChar(fullDropZoneDir);
  1437. IConstDropZoneInfo * candidateDropZone = nullptr;
  1438. if (strncmp(fullDropZoneDir, targetFilePath, fullDropZoneDir.length()) == 0)
  1439. {
  1440. candidateDropZone = &zoneIt->query();
  1441. // The backward compatibility built in IConstDropZoneServerInfoIterator
  1442. Owned<IConstDropZoneServerInfoIterator> dropzoneServerListIt = candidateDropZone->getServers();
  1443. ForEach(*dropzoneServerListIt)
  1444. {
  1445. StringBuffer dropzoneServer;
  1446. dropzoneServerListIt->query().getServer(dropzoneServer);
  1447. // It can be a hostname or an IP -> get the IP
  1448. IpAddress serverIP(dropzoneServer.str());
  1449. #ifdef _DEBUG
  1450. StringBuffer serverIpString;
  1451. serverIP.getIpText(serverIpString);
  1452. LOG(MCdebugInfo, unknownJob, "Listed server: '%s', IP: '%s'", dropzoneServer.str(), serverIpString.str());
  1453. #endif
  1454. if (targetIp.ipequals(serverIP))
  1455. {
  1456. // OK the target is a valid machine in the server list we have a right drop zone candidate
  1457. // Keep this candidate drop zone if its directory path is shorter than we already have
  1458. if (dropzonePathLen > fullDropZoneDir.length())
  1459. {
  1460. dropzonePathLen = fullDropZoneDir.length();
  1461. dropZone = candidateDropZone;
  1462. }
  1463. break;
  1464. }
  1465. }
  1466. }
  1467. }
  1468. return LINK(dropZone);
  1469. }
  1470. IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIteratorByComputer(const char * computer) const
  1471. {
  1472. return new CConstDropZoneIteratorByComputer(computer);
  1473. }
  1474. IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIterator() const
  1475. {
  1476. return new CConstDropZoneInfoIterator();
  1477. }
  1478. IConstMachineInfoIterator * CLocalEnvironment::getMachineIterator() const
  1479. {
  1480. return new CConstMachineInfoIterator();
  1481. }
  1482. bool CLocalEnvironment::isDropZoneRestrictionEnabled() const
  1483. {
  1484. if (!isDropZoneRestrictionLoaded)
  1485. {
  1486. dropZoneRestrictionEnabled = queryEnvironmentConf().getPropBool("useDropZoneRestriction", true);
  1487. isDropZoneRestrictionLoaded=true;
  1488. }
  1489. return dropZoneRestrictionEnabled;
  1490. }
  1491. //==========================================================================================
  1492. // Iterators implementation
  1493. CConstMachineInfoIterator::CConstMachineInfoIterator()
  1494. {
  1495. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1496. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1497. maxIndex = constEnv->getNumberOfMachines();
  1498. }
  1499. bool CConstMachineInfoIterator::first()
  1500. {
  1501. index = 1;
  1502. curr.setown(constEnv->getMachineByIndex(index));
  1503. return curr != nullptr;
  1504. }
  1505. bool CConstMachineInfoIterator::next()
  1506. {
  1507. if (index < maxIndex)
  1508. {
  1509. index++;
  1510. curr.setown(constEnv->getMachineByIndex(index));
  1511. }
  1512. else
  1513. curr.clear();
  1514. return curr != nullptr;
  1515. }
  1516. bool CConstMachineInfoIterator::isValid()
  1517. {
  1518. return curr != nullptr;
  1519. }
  1520. IConstMachineInfo & CConstMachineInfoIterator::query()
  1521. {
  1522. return *curr;
  1523. }
  1524. unsigned CConstMachineInfoIterator::count() const
  1525. {
  1526. return maxIndex;
  1527. }
  1528. //--------------------------------------------------
  1529. CConstDropZoneIteratorByComputer::CConstDropZoneIteratorByComputer(const char * computer)
  1530. {
  1531. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1532. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1533. computerName.set(computer);
  1534. maxIndex = constEnv->getNumberOfDropZonesByComputer(computer);
  1535. }
  1536. bool CConstDropZoneIteratorByComputer::first()
  1537. {
  1538. index = 1;
  1539. curr.setown(constEnv->getDropZoneByComputerByIndex(computerName.str(), index));
  1540. return curr != nullptr;
  1541. }
  1542. bool CConstDropZoneIteratorByComputer::next()
  1543. {
  1544. if (index < maxIndex)
  1545. {
  1546. index++;
  1547. curr.setown(constEnv->getDropZoneByComputerByIndex(computerName.str(), index));
  1548. }
  1549. else
  1550. curr.clear();
  1551. return curr != nullptr;
  1552. }
  1553. bool CConstDropZoneIteratorByComputer::isValid()
  1554. {
  1555. return curr != nullptr;
  1556. }
  1557. IConstDropZoneInfo & CConstDropZoneIteratorByComputer::query()
  1558. {
  1559. return *curr;
  1560. }
  1561. unsigned CConstDropZoneIteratorByComputer::count() const
  1562. {
  1563. return maxIndex;
  1564. }
  1565. //--------------------------------------------------
  1566. CConstDropZoneServerInfoIterator::CConstDropZoneServerInfoIterator(const IConstDropZoneInfo * dropZone)
  1567. {
  1568. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1569. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1570. // For backward compatibility
  1571. SCMStringBuffer dropZoneMachineName;
  1572. // Returns dropzone '@computer' value if it is exists
  1573. dropZone->getComputerName(dropZoneMachineName);
  1574. if (0 != dropZoneMachineName.length())
  1575. {
  1576. // Create a ServerList for legacy element.
  1577. Owned<IPropertyTree> legacyServerList = createPTree();
  1578. Owned<IConstMachineInfo> machineInfo = constEnv->getMachine(dropZoneMachineName.str());
  1579. if (machineInfo)
  1580. {
  1581. SCMStringBuffer dropZoneMachineNetAddress;
  1582. machineInfo->getNetAddress(dropZoneMachineNetAddress);
  1583. // Create a single ServerList record related to @computer
  1584. //<ServerList name="ServerList" server="<IP_of_@computer>"/>
  1585. Owned<IPropertyTree> newRecord = createPTree();
  1586. newRecord->setProp("@name", "ServerList");
  1587. newRecord->setProp("@server", dropZoneMachineNetAddress.str());
  1588. legacyServerList->addPropTree("ServerList",newRecord.getClear());
  1589. maxIndex = 1;
  1590. }
  1591. else
  1592. {
  1593. // Something is terrible wrong because there is no matching machine for DropZone @computer
  1594. maxIndex = 0;
  1595. }
  1596. serverListIt.setown(legacyServerList->getElements("ServerList"));
  1597. }
  1598. else
  1599. {
  1600. Owned<IPropertyTree> pSrc = &dropZone->getPTree();
  1601. serverListIt.setown(pSrc->getElements("ServerList"));
  1602. maxIndex = pSrc->getCount("ServerList");
  1603. }
  1604. }
  1605. bool CConstDropZoneServerInfoIterator::first()
  1606. {
  1607. bool hasFirst = serverListIt->first();
  1608. if (hasFirst)
  1609. curr.setown(new CConstDropZoneServerInfo(constEnv, &serverListIt->query()));
  1610. else
  1611. curr.clear();
  1612. return hasFirst;
  1613. }
  1614. bool CConstDropZoneServerInfoIterator::next()
  1615. {
  1616. bool hasNext = serverListIt->next();
  1617. if (hasNext)
  1618. curr.setown(new CConstDropZoneServerInfo(constEnv, &serverListIt->query()));
  1619. else
  1620. curr.clear();
  1621. return hasNext;
  1622. }
  1623. bool CConstDropZoneServerInfoIterator::isValid()
  1624. {
  1625. return nullptr != curr;
  1626. }
  1627. IConstDropZoneServerInfo & CConstDropZoneServerInfoIterator::query()
  1628. {
  1629. return *curr;
  1630. }
  1631. unsigned CConstDropZoneServerInfoIterator::count() const
  1632. {
  1633. return maxIndex;
  1634. }
  1635. //--------------------------------------------------
  1636. CConstDropZoneInfoIterator::CConstDropZoneInfoIterator()
  1637. {
  1638. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  1639. constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
  1640. maxIndex = constEnv->getNumberOfDropZones();
  1641. }
  1642. bool CConstDropZoneInfoIterator::first()
  1643. {
  1644. index = 1;
  1645. curr.setown(constEnv->getDropZoneByIndex(index));
  1646. return curr != nullptr;
  1647. }
  1648. bool CConstDropZoneInfoIterator::next()
  1649. {
  1650. if (index < maxIndex)
  1651. {
  1652. index++;
  1653. curr.setown(constEnv->getDropZoneByIndex(index));
  1654. }
  1655. else
  1656. curr.clear();
  1657. return curr != nullptr;
  1658. }
  1659. bool CConstDropZoneInfoIterator::isValid()
  1660. {
  1661. return curr != nullptr;
  1662. }
  1663. IConstDropZoneInfo & CConstDropZoneInfoIterator::query()
  1664. {
  1665. return *curr;
  1666. }
  1667. unsigned CConstDropZoneInfoIterator::count() const
  1668. {
  1669. return maxIndex;
  1670. }
  1671. //==========================================================================================
  1672. static CriticalSection getEnvSect;
  1673. extern ENVIRONMENT_API IEnvironmentFactory * getEnvironmentFactory()
  1674. {
  1675. CriticalBlock block(getEnvSect);
  1676. if (!factory)
  1677. {
  1678. factory = new CEnvironmentFactory();
  1679. addShutdownHook(*factory);
  1680. }
  1681. return LINK(factory);
  1682. }
  1683. extern ENVIRONMENT_API void closeEnvironment()
  1684. {
  1685. try
  1686. {
  1687. CEnvironmentFactory* pFactory;
  1688. {
  1689. //this method is not meant to be invoked by multiple
  1690. //threads concurrently but just in case...
  1691. CriticalBlock block(getEnvSect);
  1692. pFactory = factory;
  1693. factory = nullptr;
  1694. }
  1695. clearPasswordsFromSDS();
  1696. if (pFactory)
  1697. {
  1698. removeShutdownHook(*pFactory);
  1699. pFactory->close();
  1700. pFactory->Release();
  1701. }
  1702. }
  1703. catch (IException *e)
  1704. {
  1705. EXCLOG(e);
  1706. }
  1707. }