environment.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376
  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. static int environmentTraceLevel = 1;
  28. static Owned <IConstEnvironment> cache;
  29. class CConstInstanceInfo;
  30. class CLocalEnvironment : public CInterface, implements IConstEnvironment
  31. {
  32. private:
  33. // NOTE - order is important - we need to construct before p and (especially) destruct after p
  34. Owned<IRemoteConnection> conn;
  35. Owned<IPropertyTree> p;
  36. mutable MapStringToMyClass<IConstEnvBase> cache;
  37. mutable Mutex safeCache;
  38. mutable bool dropZoneCacheBuilt;
  39. mutable bool machineCacheBuilt;
  40. StringBuffer xPath;
  41. IConstEnvBase * getCache(const char *path) const;
  42. void setCache(const char *path, IConstEnvBase *value) const;
  43. void buildMachineCache() const;
  44. void buildDropZoneCache() const;
  45. public:
  46. IMPLEMENT_IINTERFACE;
  47. CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree *x=NULL, const char* path="Environment");
  48. CLocalEnvironment(const char* path="config.xml");
  49. virtual ~CLocalEnvironment();
  50. virtual IStringVal & getName(IStringVal & str) const;
  51. virtual IStringVal & getXML(IStringVal & str) const;
  52. virtual IPropertyTree & getPTree() const;
  53. virtual IEnvironment& lock() const;
  54. virtual IConstDomainInfo * getDomain(const char * name) const;
  55. virtual IConstMachineInfo * getMachine(const char * name) const;
  56. virtual IConstMachineInfo * getMachineByAddress(const char * name) const;
  57. virtual IConstMachineInfo * getMachineForLocalHost() const;
  58. virtual IConstDropZoneInfo * getDropZone(const char * name) const;
  59. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const;
  60. virtual IConstInstanceInfo * getInstance(const char * type, const char * version, const char *domain) const;
  61. virtual CConstInstanceInfo * getInstanceByIP(const char *type, const char *version, IpAddress &ip) const;
  62. virtual IConstComputerTypeInfo * getComputerType(const char * name) const;
  63. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr, const char *defprogname) const;
  64. virtual void preload();
  65. virtual IRemoteConnection* getConnection() const { return conn.getLink(); }
  66. void setXML(const char * logicalName);
  67. const char* getPath() const { return xPath.str(); }
  68. void unlockRemote();
  69. virtual bool isConstEnvironment() const { return true; }
  70. virtual void clearCache();
  71. };
  72. class CLockedEnvironment : public CInterface, implements IEnvironment
  73. {
  74. public:
  75. //note that order of construction/destruction is important
  76. Owned<CLocalEnvironment> c;
  77. Owned<CLocalEnvironment> env;
  78. Owned<CLocalEnvironment> constEnv;
  79. IMPLEMENT_IINTERFACE;
  80. CLockedEnvironment(CLocalEnvironment *_c)
  81. {
  82. Owned<IRemoteConnection> connection = _c->getConnection();
  83. if (connection)
  84. {
  85. constEnv.set(_c); //save original constant environment
  86. //we only wish to allow one party to allow updating the environment.
  87. //
  88. //create a new /NewEnvironment subtree, locked for read/write access for self and entire subtree; delete on disconnect
  89. //
  90. StringBuffer newName("/New");
  91. newName.append(constEnv->getPath());
  92. const unsigned int mode = RTM_CREATE | RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE |
  93. RTM_LOCK_SUB | RTM_DELETE_ON_DISCONNECT;
  94. Owned<IRemoteConnection> conn = querySDS().connect(newName.str(), myProcessSession(), mode, SDS_LOCK_TIMEOUT);
  95. if (conn == NULL)
  96. {
  97. if (environmentTraceLevel > 0)
  98. PrintLog("Failed to create locked environment %s", newName.str());
  99. throw MakeStringException(-1, "Failed to get a lock on environment /%s", newName.str());
  100. }
  101. //save the locked environment
  102. env.setown(new CLocalEnvironment(conn, NULL, newName.str()));
  103. //get a lock on the const environment
  104. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  105. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  106. if (conn2 == NULL)
  107. {
  108. if (environmentTraceLevel > 0)
  109. PrintLog("Failed to lock environment %s", constEnv->getPath());
  110. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  111. }
  112. //copy const environment to our member environment
  113. Owned<IPropertyTree> pSrc = conn2->getRoot();
  114. c.setown( new CLocalEnvironment(NULL, createPTreeFromIPT(pSrc)));
  115. conn2->rollback();
  116. }
  117. else
  118. {
  119. c.set(_c);
  120. }
  121. }
  122. virtual ~CLockedEnvironment()
  123. {
  124. }
  125. virtual IStringVal & getName(IStringVal & str) const
  126. { return c->getName(str); }
  127. virtual IStringVal & getXML(IStringVal & str) const
  128. { return c->getXML(str); }
  129. virtual IPropertyTree & getPTree() const
  130. {
  131. return c->getPTree();
  132. }
  133. virtual IConstDomainInfo * getDomain(const char * name) const
  134. { return c->getDomain(name); }
  135. virtual IConstMachineInfo * getMachine(const char * name) const
  136. { return c->getMachine(name); }
  137. virtual IConstMachineInfo * getMachineByAddress(const char * name) const
  138. { return c->getMachineByAddress(name); }
  139. virtual IConstMachineInfo * getMachineForLocalHost() const
  140. { return c->getMachineForLocalHost(); }
  141. virtual IConstDropZoneInfo * getDropZone(const char * name) const
  142. { return c->getDropZone(name); }
  143. virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const
  144. { return c->getDropZoneByComputer(computer); }
  145. virtual IConstInstanceInfo * getInstance(const char *type, const char *version, const char *domain) const
  146. { return c->getInstance(type, version, domain); }
  147. virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr,const char *defprogname) const
  148. { return c->getRunInfo(path, dir, type, version, machineaddr, defprogname); }
  149. virtual IConstComputerTypeInfo * getComputerType(const char * name) const
  150. { return c->getComputerType(name); }
  151. virtual IEnvironment & lock() const
  152. { ((CInterface*)this)->Link(); return *(IEnvironment*)this; }
  153. virtual void commit();
  154. virtual void rollback();
  155. virtual void setXML(const char * pstr)
  156. { c->setXML(pstr); }
  157. virtual void preload()
  158. { c->preload(); }
  159. virtual bool isConstEnvironment() const { return false; }
  160. virtual void clearCache() { c->clearCache(); }
  161. };
  162. void CLockedEnvironment::commit()
  163. {
  164. if (constEnv)
  165. {
  166. //get a lock on const environment momentarily
  167. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  168. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  169. if (conn2 == NULL)
  170. {
  171. if (environmentTraceLevel > 0)
  172. PrintLog("Failed to lock environment %s", constEnv->getPath());
  173. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  174. }
  175. //copy locked environment to const environment
  176. Owned<IPropertyTree> pSrc = &getPTree();
  177. Owned<IPropertyTree> pDst = conn2->queryRoot()->getBranch(NULL);
  178. // JCS - I think it could (and would be more efficient if it had kept the original read lock connection to Env
  179. // - instead of using NewEnv as lock point, still work on copy, then changeMode of original connect
  180. // - as opposed to current scheme, where it recoonects in write mode and has to lazy fetch original env to update.
  181. // ensures pDst is equal to pSrc, whilst minimizing changes to pDst
  182. try { synchronizePTree(pDst, pSrc); }
  183. catch (IException *) { conn2->rollback(); throw; }
  184. conn2->commit();
  185. }
  186. else
  187. {
  188. Owned<IRemoteConnection> conn = c->getConnection();
  189. conn->commit();
  190. }
  191. }
  192. void CLockedEnvironment::rollback()
  193. {
  194. if (constEnv)
  195. {
  196. //get a lock on const environment momentarily
  197. const unsigned int mode2 = RTM_CREATE_QUERY | RTM_LOCK_READ | RTM_LOCK_WRITE | RTM_LOCK_SUB;
  198. Owned<IRemoteConnection> conn2 = querySDS().connect(constEnv->getPath(), myProcessSession(), mode2, SDS_LOCK_TIMEOUT);
  199. if (conn2 == NULL)
  200. {
  201. if (environmentTraceLevel > 0)
  202. PrintLog("Failed to lock environment %s", constEnv->getPath());
  203. throw MakeStringException(-1, "Failed to get a lock on environment /%s", constEnv->getPath());
  204. }
  205. //copy const environment to locked environment (as it stands now) again losing any changes we made
  206. Owned<IPropertyTree> pSrc = conn2->getRoot();
  207. Owned<IPropertyTree> pDst = &getPTree();
  208. pDst->removeTree( pDst->queryPropTree("Hardware") );
  209. pDst->removeTree( pDst->queryPropTree("Software") );
  210. pDst->removeTree( pDst->queryPropTree("Programs") );
  211. pDst->removeTree( pDst->queryPropTree("Data") );
  212. mergePTree(pDst, pSrc);
  213. conn2->rollback();
  214. }
  215. else
  216. {
  217. Owned<IRemoteConnection> conn = c->getConnection();
  218. conn->rollback();
  219. }
  220. }
  221. //==========================================================================================
  222. // the following class implements notification handler for subscription to dali for environment
  223. // updates by other clients and is used by environment factory below. This also serves as
  224. // a sample self-contained implementation that can be easily tailored for other purposes.
  225. //==========================================================================================
  226. class CSdsSubscription : public CInterface, implements ISDSSubscription
  227. {
  228. public:
  229. CSdsSubscription()
  230. {
  231. m_constEnvUpdated = false;
  232. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  233. sub_id = envFactory->subscribe(this);
  234. }
  235. virtual ~CSdsSubscription()
  236. {
  237. /* note that ideally, we would make this class automatically
  238. unsubscribe in this destructor. However, underlying dali client
  239. layer (CDaliSubscriptionManagerStub) links to this object and so
  240. object would not get destroyed just by an application releasing it.
  241. The application either needs to explicitly unsubscribe or close
  242. the environment which unsubscribes during close down. */
  243. }
  244. void unsubscribe()
  245. {
  246. synchronized block(m_mutexEnv);
  247. if (sub_id)
  248. {
  249. Owned<IEnvironmentFactory> m_envFactory = getEnvironmentFactory();
  250. m_envFactory->unsubscribe(sub_id);
  251. sub_id = 0;
  252. }
  253. }
  254. IMPLEMENT_IINTERFACE;
  255. //another client (like configenv) may have updated the environment and we got notified
  256. //(thanks to our subscription) but don't just reload it yet since this notification is sent on
  257. //another thread asynchronously and we may be actively working with the old environment. Just
  258. //invoke handleEnvironmentChange() when we are ready to invalidate cache in environment factory.
  259. //
  260. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=NULL)
  261. {
  262. DBGLOG("Environment was updated by another client of Dali server. Invalidating cache.\n");
  263. synchronized block(m_mutexEnv);
  264. m_constEnvUpdated = true;
  265. }
  266. void handleEnvironmentChange()
  267. {
  268. synchronized block(m_mutexEnv);
  269. if (m_constEnvUpdated)
  270. {
  271. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  272. Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
  273. constEnv->clearCache();
  274. m_constEnvUpdated = false;
  275. }
  276. }
  277. private:
  278. SubscriptionId sub_id;
  279. Mutex m_mutexEnv;
  280. bool m_constEnvUpdated;
  281. };
  282. //==========================================================================================
  283. class CEnvironmentFactory : public CInterface,
  284. implements IEnvironmentFactory, implements IDaliClientShutdown
  285. {
  286. public:
  287. IMPLEMENT_IINTERFACE;
  288. typedef ArrayOf<SubscriptionId> SubscriptionIDs;
  289. SubscriptionIDs subIDs;
  290. Mutex mutex;
  291. Owned<CSdsSubscription> subscription;
  292. CEnvironmentFactory()
  293. {
  294. }
  295. virtual void clientShutdown();
  296. virtual ~CEnvironmentFactory()
  297. {
  298. close(); //just in case it was not explicitly closed
  299. }
  300. virtual IConstEnvironment* openEnvironment()
  301. {
  302. synchronized procedure(mutex);
  303. if (!cache)
  304. {
  305. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  306. if (conn)
  307. cache.setown(new CLocalEnvironment(conn));
  308. }
  309. return cache.getLink();
  310. }
  311. virtual IEnvironment* updateEnvironment()
  312. {
  313. Owned<IConstEnvironment> pConstEnv = openEnvironment();
  314. synchronized procedure(mutex);
  315. return &pConstEnv->lock();
  316. }
  317. virtual IEnvironment * loadLocalEnvironmentFile(const char * filename)
  318. {
  319. Owned<IPropertyTree> ptree = createPTreeFromXMLFile(filename);
  320. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(NULL, ptree);
  321. return new CLockedEnvironment(pLocalEnv);
  322. }
  323. virtual IEnvironment * loadLocalEnvironment(const char * xml)
  324. {
  325. Owned<IPropertyTree> ptree = createPTreeFromXMLString(xml);
  326. Owned<CLocalEnvironment> pLocalEnv = new CLocalEnvironment(NULL, ptree);
  327. return new CLockedEnvironment(pLocalEnv);
  328. }
  329. void close()
  330. {
  331. SubscriptionIDs copySubIDs;
  332. {
  333. synchronized procedure(mutex);
  334. cache.clear();
  335. //save the active subscriptions in another array
  336. //so they can be unsubscribed without causing deadlock
  337. // since ~CSdsSubscription() would ask us to unsubscribe the
  338. //same requiring a mutex lock (copy is a little price for this
  339. //normally small/empty array).
  340. //
  341. ForEachItemIn(i, subIDs)
  342. copySubIDs.append(subIDs.item(i));
  343. subIDs.kill();
  344. }
  345. //now unsubscribe all outstanding subscriptions
  346. //
  347. subscription.clear();
  348. ForEachItemIn(i, copySubIDs)
  349. querySDS().unsubscribe( copySubIDs.item(i) );
  350. }
  351. virtual SubscriptionId subscribe(ISDSSubscription* pSubHandler)
  352. {
  353. SubscriptionId sub_id = querySDS().subscribe("/Environment", *pSubHandler);
  354. synchronized procedure(mutex);
  355. subIDs.append(sub_id);
  356. return sub_id;
  357. }
  358. virtual void unsubscribe(SubscriptionId sub_id)
  359. {
  360. synchronized procedure(mutex);
  361. aindex_t i = subIDs.find(sub_id);
  362. if (i != NotFound)
  363. {
  364. querySDS().unsubscribe(sub_id);
  365. subIDs.remove(i);
  366. }
  367. }
  368. virtual void validateCache()
  369. {
  370. if (!subscription)
  371. subscription.setown( new CSdsSubscription() );
  372. subscription->handleEnvironmentChange();
  373. }
  374. private:
  375. IRemoteConnection* connect(const char *xpath, unsigned flags)
  376. {
  377. return querySDS().connect(xpath, myProcessSession(), flags, SDS_LOCK_TIMEOUT);
  378. }
  379. };
  380. static CEnvironmentFactory *factory=NULL;
  381. void CEnvironmentFactory::clientShutdown()
  382. {
  383. closeEnvironment();
  384. }
  385. MODULE_INIT(INIT_PRIORITY_ENV_ENVIRONMENT)
  386. {
  387. return true;
  388. }
  389. MODULE_EXIT()
  390. {
  391. ::Release(factory);
  392. }
  393. //==========================================================================================
  394. class CConstEnvBase : public CInterface
  395. {
  396. protected:
  397. const CLocalEnvironment* env; // Not linked - would be circular....
  398. // That could cause problems
  399. Linked<IPropertyTree> root;
  400. public:
  401. CConstEnvBase(const CLocalEnvironment* _env, IPropertyTree *_root)
  402. : env(_env), root(_root)
  403. {
  404. }
  405. IStringVal& getXML(IStringVal &str) const
  406. {
  407. StringBuffer x;
  408. toXML(root->queryBranch("."), x);
  409. str.set(x.str());
  410. return str;
  411. };
  412. IStringVal& getName(IStringVal &str) const
  413. {
  414. str.set(root->queryProp("@name"));
  415. return str;
  416. }
  417. IPropertyTree& getPTree() const
  418. {
  419. return *LINK(root);
  420. }
  421. };
  422. #define IMPLEMENT_ICONSTENVBASE \
  423. virtual IStringVal& getXML(IStringVal &str) const { return CConstEnvBase::getXML(str); } \
  424. virtual IStringVal& getName(IStringVal &str) const { return CConstEnvBase::getName(str); } \
  425. virtual IPropertyTree& getPTree() const { return CConstEnvBase::getPTree(); }
  426. //==========================================================================================
  427. class CConstDomainInfo : public CConstEnvBase, implements IConstDomainInfo
  428. {
  429. public:
  430. IMPLEMENT_IINTERFACE;
  431. IMPLEMENT_ICONSTENVBASE;
  432. CConstDomainInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  433. virtual void getAccountInfo(IStringVal &name, IStringVal &pw) const
  434. {
  435. if (root->hasProp("@username"))
  436. name.set(root->queryProp("@username"));
  437. else
  438. name.clear();
  439. if (root->hasProp("@password"))
  440. {
  441. StringBuffer pwd;
  442. decrypt(pwd, root->queryProp("@password"));
  443. pw.set(pwd.str());
  444. }
  445. else
  446. pw.clear();
  447. }
  448. virtual void getSnmpSecurityString(IStringVal & securityString) const
  449. {
  450. if (root->hasProp("@snmpSecurityString"))
  451. {
  452. StringBuffer sec_string;
  453. decrypt(sec_string, root->queryProp("@snmpSecurityString"));
  454. securityString.set(sec_string.str());
  455. }
  456. else
  457. securityString.set("");
  458. }
  459. virtual void getSSHAccountInfo(IStringVal &name, IStringVal &sshKeyFile, IStringVal& sshKeyPassphrase) const
  460. {
  461. if (root->hasProp("@username"))
  462. name.set(root->queryProp("@username"));
  463. else
  464. name.clear();
  465. if (root->hasProp("@sshKeyFile"))
  466. sshKeyFile.set(root->queryProp("@sshKeyFile"));
  467. else
  468. sshKeyFile.clear();
  469. if (root->hasProp("@sshKeyPassphrase"))
  470. sshKeyPassphrase.set(root->queryProp("@sshKeyPassphrase"));
  471. else
  472. sshKeyPassphrase.clear();
  473. }
  474. };
  475. //==========================================================================================
  476. struct mapOsEnums { EnvMachineOS val; const char *str; };
  477. static EnvMachineOS getEnum(IPropertyTree *p, const char *propname, mapOsEnums *map)
  478. {
  479. const char *v = p->queryProp(propname);
  480. if (v && *v)
  481. {
  482. while (map->str)
  483. {
  484. if (stricmp(v, map->str)==0)
  485. return map->val;
  486. map++;
  487. }
  488. throw MakeStringException(0, "Unknown operating system: \"%s\"", v);
  489. }
  490. return MachineOsUnknown;
  491. }
  492. struct mapStateEnums { EnvMachineState val; const char *str; };
  493. static EnvMachineState getEnum(IPropertyTree *p, const char *propname, mapStateEnums *map)
  494. {
  495. const char *v = p->queryProp(propname);
  496. if (v && *v)
  497. {
  498. while (map->str)
  499. {
  500. if (stricmp(v, map->str)==0)
  501. return map->val;
  502. map++;
  503. }
  504. assertex(!"Unexpected value in getEnum");
  505. }
  506. return MachineStateUnknown;
  507. }
  508. mapOsEnums OperatingSystems[] = {
  509. { MachineOsW2K, "W2K" },
  510. { MachineOsSolaris, "solaris" },
  511. { MachineOsLinux, "linux" },
  512. { MachineOsSize, NULL }
  513. };
  514. mapStateEnums MachineStates[] = {
  515. { MachineStateAvailable, "Available" },
  516. { MachineStateUnavailable, "Unavailable" },
  517. { MachineStateUnknown, "Unknown" }
  518. };
  519. //==========================================================================================
  520. class CConstMachineInfo : public CConstEnvBase, implements IConstMachineInfo
  521. {
  522. public:
  523. IMPLEMENT_IINTERFACE;
  524. IMPLEMENT_ICONSTENVBASE;
  525. CConstMachineInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  526. virtual IConstDomainInfo* getDomain() const
  527. {
  528. return env->getDomain(root->queryProp("@domain"));
  529. }
  530. virtual IStringVal& getNetAddress(IStringVal &str) const
  531. {
  532. str.set(root->queryProp("@netAddress"));
  533. return str;
  534. }
  535. virtual IStringVal& getDescription(IStringVal &str) const
  536. {
  537. UNIMPLEMENTED;
  538. }
  539. virtual unsigned getNicSpeedMbitSec() const
  540. {
  541. const char * v = root->queryProp("@nicSpeed");
  542. if (v && *v)
  543. return atoi(v);
  544. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  545. if (type)
  546. return type->getNicSpeedMbitSec();
  547. return 0;
  548. }
  549. virtual EnvMachineOS getOS() const
  550. {
  551. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  552. if (os != MachineOsUnknown)
  553. return os;
  554. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  555. if (type)
  556. return type->getOS();
  557. return MachineOsUnknown;
  558. }
  559. virtual EnvMachineState getState() const
  560. {
  561. return getEnum(root, "@state", MachineStates);
  562. }
  563. };
  564. //==========================================================================================
  565. class CConstComputerTypeInfo : public CConstEnvBase, implements IConstComputerTypeInfo
  566. {
  567. public:
  568. IMPLEMENT_IINTERFACE;
  569. IMPLEMENT_ICONSTENVBASE;
  570. CConstComputerTypeInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  571. virtual EnvMachineOS getOS() const
  572. {
  573. EnvMachineOS os = getEnum(root, "@opSys", OperatingSystems);
  574. if (os != MachineOsUnknown)
  575. return os;
  576. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  577. if (type && (type.get() != this))
  578. return type->getOS();
  579. return MachineOsUnknown;
  580. }
  581. virtual unsigned getNicSpeedMbitSec() const
  582. {
  583. const char * v = root->queryProp("@nicSpeed");
  584. if (v && *v)
  585. return atoi(v);
  586. Owned<IConstComputerTypeInfo> type = env->getComputerType(root->queryProp("@computerType"));
  587. if (type && (type.get() != this))
  588. return type->getNicSpeedMbitSec();
  589. return 0;
  590. }
  591. };
  592. //==========================================================================================
  593. class CConstInstanceInfo : public CConstEnvBase, implements IConstInstanceInfo
  594. {
  595. public:
  596. IMPLEMENT_IINTERFACE;
  597. IMPLEMENT_ICONSTENVBASE;
  598. CConstInstanceInfo(const CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root)
  599. {
  600. }
  601. virtual IConstMachineInfo * getMachine() const
  602. {
  603. return env->getMachine(root->queryProp("@computer"));
  604. }
  605. virtual IStringVal & getEndPoint(IStringVal & str) const
  606. {
  607. SCMStringBuffer ep;
  608. Owned<IConstMachineInfo> machine = getMachine();
  609. if (machine)
  610. {
  611. machine->getNetAddress(ep);
  612. const char *port = root->queryProp("@port");
  613. if (port)
  614. ep.s.append(':').append(port);
  615. }
  616. str.set(ep.str());
  617. return str;
  618. }
  619. virtual IStringVal & getExecutableDirectory(IStringVal & str) const
  620. {
  621. // this is the deploy directory so uses local path separators (I suspect this call is LEGACY now)
  622. SCMStringBuffer ep;
  623. Owned<IConstMachineInfo> machine = getMachine();
  624. if (machine)
  625. {
  626. machine->getNetAddress(ep);
  627. ep.s.insert(0, PATHSEPSTR PATHSEPSTR);
  628. }
  629. ep.s.append(PATHSEPCHAR).append(root->queryProp("@directory"));
  630. str.set(ep.str());
  631. return str;
  632. }
  633. virtual bool doGetRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname, bool useprog) const
  634. {
  635. // this is remote path i.e. path should match *target* nodes format
  636. Owned<IConstMachineInfo> machine = getMachine();
  637. if (!machine)
  638. return false;
  639. char psep;
  640. bool appendexe;
  641. switch (machine->getOS()) {
  642. case MachineOsSolaris:
  643. case MachineOsLinux:
  644. psep = '/';
  645. appendexe = false;
  646. break;
  647. default:
  648. psep = '\\';
  649. appendexe = true;
  650. }
  651. StringBuffer tmp;
  652. const char *program = useprog?root->queryProp("@program"):NULL; // if program specified assume absolute
  653. if (!program||!*program) {
  654. SCMStringBuffer ep;
  655. machine->getNetAddress(ep);
  656. const char *dir = root->queryProp("@directory");
  657. if (dir) {
  658. if (isPathSepChar(*dir))
  659. dir++;
  660. if (!*dir)
  661. return false;
  662. tmp.append(psep).append(psep).append(ep.s).append(psep);
  663. do {
  664. if (isPathSepChar(*dir))
  665. tmp.append(psep);
  666. else
  667. tmp.append(*dir);
  668. dir++;
  669. } while (*dir);
  670. if (!isPathSepChar(tmp.charAt(tmp.length()-1)))
  671. tmp.append(psep);
  672. tmp.append(defprogname);
  673. size32_t l = strlen(defprogname);
  674. if (appendexe&&((l<5)||(stricmp(defprogname+l-4,".exe")!=0)))
  675. tmp.append(".exe");
  676. }
  677. program = tmp.str();
  678. }
  679. progpath.set(program);
  680. const char *workd = root->queryProp("@workdir"); // if program specified assume absolute
  681. workdir.set(workd?workd:"");
  682. return true;
  683. }
  684. virtual bool getRunInfo(IStringVal & progpath, IStringVal & workdir, const char *defprogname) const
  685. {
  686. return doGetRunInfo(progpath,workdir,defprogname,true);
  687. }
  688. virtual unsigned getPort() const
  689. {
  690. return root->getPropInt("@port", 0);
  691. }
  692. };
  693. class CConstDropZoneInfo : public CConstEnvBase, implements IConstDropZoneInfo
  694. {
  695. public:
  696. IMPLEMENT_IINTERFACE;
  697. IMPLEMENT_ICONSTENVBASE;
  698. CConstDropZoneInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root) {}
  699. virtual IStringVal& getComputerName(IStringVal &str) const
  700. {
  701. str.set(root->queryProp("@computer"));
  702. return str;
  703. }
  704. virtual IStringVal& getDescription(IStringVal &str) const
  705. {
  706. str.set(root->queryProp("@description"));
  707. return str;
  708. }
  709. virtual IStringVal& getDirectory(IStringVal &str) const
  710. {
  711. str.set(root->queryProp("@directory"));
  712. return str;
  713. }
  714. };
  715. #if 0
  716. //==========================================================================================
  717. class CConstProcessInfo : public CConstEnvBase, implements IConstProcessInfo
  718. {
  719. IArrayOf<IConstInstanceInfo> w;
  720. CArrayIteratorOf<IInterface, IIterator> it;
  721. public:
  722. IMPLEMENT_IINTERFACE;
  723. IMPLEMENT_ICONSTENVBASE;
  724. CConstProcessInfo(CLocalEnvironment *env, IPropertyTree *root) : CConstEnvBase(env, root), it(w)
  725. {
  726. Owned<IPropertyTreeIterator> _it = root->getElements("*"); // MORE - should be instance
  727. for (_it->first(); _it->isValid(); _it->next())
  728. {
  729. IPropertyTree *rp = &_it->query();
  730. w.append(*new CConstInstanceInfo(env, rp)); // CConstInstanceInfo will link rp
  731. }
  732. }
  733. bool first() { return it.first(); }
  734. bool isValid() { return it.isValid(); }
  735. bool next() { return it.next(); }
  736. IConstInstanceInfo & query() { return (IConstInstanceInfo &) it.query();}
  737. virtual IConstInstanceInfo * getInstance(const char *domain)
  738. {
  739. for (int pass=0; pass<2; pass++)
  740. {
  741. ForEachItemIn(idx, w)
  742. {
  743. Owned<IConstMachineInfo> m = w.item(idx).getMachine();
  744. if (m)
  745. {
  746. Owned<IConstDomainInfo> dm = m->getDomain();
  747. if (dm)
  748. {
  749. StringBuffer thisdomain;
  750. //dm->getName(StringBufferAdaptor(thisdomain)); // confuses g++
  751. StringBufferAdaptor strval(thisdomain);
  752. dm->getName(strval);
  753. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  754. return LINK(&w.item(idx));
  755. }
  756. }
  757. }
  758. }
  759. return NULL;
  760. }
  761. };
  762. #endif
  763. //==========================================================================================
  764. CLocalEnvironment::CLocalEnvironment(const char* environmentFile)
  765. {
  766. if (environmentFile && *environmentFile)
  767. {
  768. IPropertyTree* root = createPTreeFromXMLFile(environmentFile);
  769. if (root)
  770. p.set(root);
  771. }
  772. machineCacheBuilt = false;
  773. }
  774. CLocalEnvironment::CLocalEnvironment(IRemoteConnection *_conn, IPropertyTree* root/*=NULL*/,
  775. const char* path/*="/Environment"*/)
  776. : xPath(path)
  777. {
  778. conn.set(_conn);
  779. if (root)
  780. p.set(root);
  781. else
  782. p.setown(conn->getRoot());
  783. machineCacheBuilt = false;
  784. }
  785. CLocalEnvironment::~CLocalEnvironment()
  786. {
  787. if (conn)
  788. conn->rollback();
  789. }
  790. IEnvironment& CLocalEnvironment::lock() const
  791. {
  792. return *new CLockedEnvironment((CLocalEnvironment*)this);
  793. }
  794. IStringVal & CLocalEnvironment::getName(IStringVal & str) const
  795. {
  796. synchronized procedure(safeCache);
  797. str.set(p->queryProp("@name"));
  798. return str;
  799. }
  800. IStringVal & CLocalEnvironment::getXML(IStringVal & str) const
  801. {
  802. StringBuffer xml;
  803. {
  804. synchronized procedure(safeCache);
  805. toXML(p->queryBranch("."), xml);
  806. }
  807. str.set(xml.str());
  808. return str;
  809. }
  810. IPropertyTree & CLocalEnvironment::getPTree() const
  811. {
  812. synchronized procedure(safeCache);
  813. return *LINK(p);
  814. }
  815. IConstEnvBase * CLocalEnvironment::getCache(const char *path) const
  816. {
  817. IConstEnvBase * ret = cache.getValue(path);
  818. ::Link(ret);
  819. return ret;
  820. }
  821. void CLocalEnvironment::setCache(const char *path, IConstEnvBase *value) const
  822. {
  823. cache.setValue(path, value);
  824. }
  825. IConstDomainInfo * CLocalEnvironment::getDomain(const char * name) const
  826. {
  827. if (!name)
  828. return NULL;
  829. StringBuffer xpath;
  830. xpath.appendf("Hardware/Domain[@name=\"%s\"]", name);
  831. synchronized procedure(safeCache);
  832. IConstEnvBase *cached = getCache(xpath.str());
  833. if (!cached)
  834. {
  835. IPropertyTree *d = p->queryPropTree(xpath.str());
  836. if (!d)
  837. return NULL;
  838. cached = new CConstDomainInfo((CLocalEnvironment *) this, d);
  839. setCache(xpath.str(), cached);
  840. }
  841. return (IConstDomainInfo *) cached;
  842. }
  843. void CLocalEnvironment::buildMachineCache() const
  844. {
  845. synchronized procedure(safeCache);
  846. if (!machineCacheBuilt)
  847. {
  848. Owned<IPropertyTreeIterator> it = p->getElements("Hardware/Computer");
  849. ForEach(*it)
  850. {
  851. const char *name = it->query().queryProp("@name");
  852. if (name)
  853. {
  854. StringBuffer x("Hardware/Computer[@name=\"");
  855. x.append(name).append("\"]");
  856. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  857. cache.setValue(x.str(), cached);
  858. }
  859. name = it->query().queryProp("@netAddress");
  860. if (name)
  861. {
  862. StringBuffer x("Hardware/Computer[@netAddress=\"");
  863. x.append(name).append("\"]");
  864. Owned<IConstEnvBase> cached = new CConstMachineInfo((CLocalEnvironment *) this, &it->query());
  865. cache.setValue(x.str(), cached);
  866. IpAddress ip;
  867. ip.ipset(name);
  868. if (ip.isLocal())
  869. cache.setValue("Hardware/Computer[@netAddress=\".\"]", cached);
  870. }
  871. }
  872. machineCacheBuilt = true;
  873. }
  874. }
  875. void CLocalEnvironment::buildDropZoneCache() const
  876. {
  877. synchronized procedure(safeCache);
  878. if (!dropZoneCacheBuilt)
  879. {
  880. Owned<IPropertyTreeIterator> it = p->getElements("Software/DropZone");
  881. ForEach(*it)
  882. {
  883. const char *name = it->query().queryProp("@name");
  884. if (name)
  885. {
  886. StringBuffer x("Software/DropZone[@name=\"");
  887. x.append(name).append("\"]");
  888. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  889. cache.setValue(x.str(), cached);
  890. }
  891. name = it->query().queryProp("@computer");
  892. if (name)
  893. {
  894. StringBuffer x("Software/DropZone[@computer=\"");
  895. x.append(name).append("\"]");
  896. Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
  897. cache.setValue(x.str(), cached);
  898. }
  899. }
  900. dropZoneCacheBuilt = true;
  901. }
  902. }
  903. IConstComputerTypeInfo * CLocalEnvironment::getComputerType(const char * name) const
  904. {
  905. if (!name)
  906. return NULL;
  907. StringBuffer xpath;
  908. xpath.appendf("Hardware/ComputerType[@name=\"%s\"]", name);
  909. synchronized procedure(safeCache);
  910. IConstEnvBase *cached = getCache(xpath.str());
  911. if (!cached)
  912. {
  913. IPropertyTree *d = p->queryPropTree(xpath.str());
  914. if (!d)
  915. return NULL;
  916. cached = new CConstComputerTypeInfo((CLocalEnvironment *) this, d);
  917. setCache(xpath.str(), cached);
  918. }
  919. return (CConstComputerTypeInfo *) cached;
  920. }
  921. IConstMachineInfo * CLocalEnvironment::getMachine(const char * name) const
  922. {
  923. if (!name)
  924. return NULL;
  925. buildMachineCache();
  926. StringBuffer xpath;
  927. xpath.appendf("Hardware/Computer[@name=\"%s\"]", name);
  928. synchronized procedure(safeCache);
  929. IConstEnvBase *cached = getCache(xpath.str());
  930. if (!cached)
  931. {
  932. IPropertyTree *d = p->queryPropTree(xpath.str());
  933. if (!d)
  934. return NULL;
  935. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  936. setCache(xpath.str(), cached);
  937. }
  938. return (CConstMachineInfo *) cached;
  939. }
  940. IConstMachineInfo * CLocalEnvironment::getMachineByAddress(const char * name) const
  941. {
  942. if (!name)
  943. return NULL;
  944. buildMachineCache();
  945. Owned<IPropertyTreeIterator> iter;
  946. StringBuffer xpath;
  947. xpath.appendf("Hardware/Computer[@netAddress=\"%s\"]", name);
  948. synchronized procedure(safeCache);
  949. IConstEnvBase *cached = getCache(xpath.str());
  950. if (!cached)
  951. {
  952. IPropertyTree *d = p->queryPropTree(xpath.str());
  953. if (!d) {
  954. // I suspect not in the original spirit of this but look for resolved IP
  955. Owned<IPropertyTreeIterator> iter = p->getElements("Hardware/Computer");
  956. IpAddress ip;
  957. ip.ipset(name);
  958. ForEach(*iter) {
  959. IPropertyTree &computer = iter->query();
  960. IpAddress ip2;
  961. const char *ips = computer.queryProp("@netAddress");
  962. if (ips&&*ips) {
  963. ip2.ipset(ips);
  964. if (ip.ipequals(ip2)) {
  965. d = &computer;
  966. break;
  967. }
  968. }
  969. }
  970. }
  971. if (!d)
  972. return NULL;
  973. StringBuffer xpath1;
  974. xpath1.appendf("Hardware/Computer[@name=\"%s\"]", d->queryProp("@name"));
  975. cached = getCache(xpath1.str());
  976. if (!cached)
  977. {
  978. cached = new CConstMachineInfo((CLocalEnvironment *) this, d);
  979. setCache(xpath1.str(), cached);
  980. setCache(xpath.str(), cached);
  981. }
  982. }
  983. return (CConstMachineInfo *) cached;
  984. }
  985. IConstMachineInfo * CLocalEnvironment::getMachineForLocalHost() const
  986. {
  987. buildMachineCache();
  988. synchronized procedure(safeCache);
  989. return (CConstMachineInfo *) getCache("Hardware/Computer[@netAddress=\".\"]");
  990. }
  991. IConstDropZoneInfo * CLocalEnvironment::getDropZone(const char * name) const
  992. {
  993. if (!name)
  994. return NULL;
  995. buildDropZoneCache();
  996. VStringBuffer xpath("Software/DropZone[@name=\"%s\"]", name);
  997. synchronized procedure(safeCache);
  998. return (CConstDropZoneInfo *) getCache(xpath.str());
  999. }
  1000. IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputer(const char * computer) const
  1001. {
  1002. if (!computer)
  1003. return NULL;
  1004. buildDropZoneCache();
  1005. VStringBuffer xpath("Software/DropZone[@computer=\"%s\"]", computer);
  1006. synchronized procedure(safeCache);
  1007. return (CConstDropZoneInfo *) getCache(xpath.str());
  1008. }
  1009. IConstInstanceInfo * CLocalEnvironment::getInstance(const char *type, const char *version, const char *domain) const
  1010. {
  1011. StringBuffer xpath("Software/");
  1012. xpath.append(type);
  1013. if (version)
  1014. xpath.append("[@version='").append(version).append("']");
  1015. xpath.append("/Instance");
  1016. synchronized procedure(safeCache);
  1017. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1018. for (_it->first(); _it->isValid(); _it->next())
  1019. {
  1020. IPropertyTree *rp = &_it->query();
  1021. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1022. Owned<IConstMachineInfo> m = inst->getMachine();
  1023. if (m)
  1024. {
  1025. Owned<IConstDomainInfo> dm = m->getDomain();
  1026. if (dm)
  1027. {
  1028. SCMStringBuffer thisdomain;
  1029. dm->getName(thisdomain);
  1030. if (thisdomain.length() && strcmp(domain, thisdomain.str())==0)
  1031. return inst.getClear();
  1032. }
  1033. }
  1034. }
  1035. return NULL;
  1036. }
  1037. CConstInstanceInfo * CLocalEnvironment::getInstanceByIP(const char *type, const char *version, IpAddress &ip) const
  1038. {
  1039. StringBuffer xpath("Software/");
  1040. xpath.append(type);
  1041. if (version)
  1042. xpath.append("[@version='").append(version).append("']");
  1043. xpath.append("/Instance");
  1044. synchronized procedure(safeCache);
  1045. assertex(p);
  1046. Owned<IPropertyTreeIterator> _it = p->getElements(xpath);
  1047. assertex(_it);
  1048. for (_it->first(); _it->isValid(); _it->next())
  1049. {
  1050. IPropertyTree *rp = &_it->query();
  1051. assertex(rp);
  1052. Owned<CConstInstanceInfo> inst = new CConstInstanceInfo(this, rp); // CConstInstanceInfo will link rp
  1053. Owned<IConstMachineInfo> m = inst->getMachine();
  1054. if (m)
  1055. {
  1056. SCMStringBuffer eps;
  1057. m->getNetAddress(eps);
  1058. SocketEndpoint ep(eps.str());
  1059. if (ep.ipequals(ip))
  1060. return inst.getClear();
  1061. }
  1062. }
  1063. return NULL;
  1064. }
  1065. void CLocalEnvironment::unlockRemote()
  1066. {
  1067. #if 0
  1068. conn->commit(true);
  1069. conn->changeMode(0, SDS_LOCK_TIMEOUT);
  1070. #else
  1071. if (conn)
  1072. {
  1073. synchronized procedure(safeCache);
  1074. p.clear();
  1075. conn.setown(querySDS().connect(xPath.str(), myProcessSession(), 0, SDS_LOCK_TIMEOUT));
  1076. p.setown(conn->getRoot());
  1077. }
  1078. #endif
  1079. }
  1080. void CLocalEnvironment::preload()
  1081. {
  1082. synchronized procedure(safeCache);
  1083. p->queryBranch(".");
  1084. }
  1085. void CLocalEnvironment::setXML(const char *xml)
  1086. {
  1087. Owned<IPropertyTree> newRoot = createPTreeFromXMLString(xml);
  1088. synchronized procedure(safeCache);
  1089. Owned<IPropertyTreeIterator> it = p->getElements("*");
  1090. ForEach(*it)
  1091. {
  1092. p->removeTree(&it->query());
  1093. }
  1094. it.setown(newRoot->getElements("*"));
  1095. ForEach(*it)
  1096. {
  1097. IPropertyTree *sub = &it->get();
  1098. p->addPropTree(sub->queryName(), sub);
  1099. }
  1100. }
  1101. bool CLocalEnvironment::getRunInfo(IStringVal & path, IStringVal & dir, const char * tag, const char * version, const char *machineaddr, const char *defprogname) const
  1102. {
  1103. try
  1104. {
  1105. // PrintLog("getExecutablePath %s %s %s", tag, version, machineaddr);
  1106. // first see if local machine with deployed on
  1107. SocketEndpoint ep(machineaddr);
  1108. Owned<CConstInstanceInfo> ipinstance = getInstanceByIP(tag, version, ep);
  1109. if (ipinstance)
  1110. {
  1111. StringAttr testpath;
  1112. StringAttrAdaptor teststrval(testpath);
  1113. if (ipinstance->doGetRunInfo(teststrval,dir,defprogname,false)) { // this returns full string
  1114. RemoteFilename rfn;
  1115. rfn.setRemotePath(testpath.get());
  1116. Owned<IFile> file = createIFile(rfn);
  1117. if (file->exists()) {
  1118. StringBuffer tmp;
  1119. rfn.getLocalPath(tmp);
  1120. path.set(tmp.str());
  1121. return true;
  1122. }
  1123. }
  1124. }
  1125. Owned<IConstMachineInfo> machine = getMachineByAddress(machineaddr);
  1126. if (!machine)
  1127. {
  1128. LOG(MCdebugInfo, unknownJob, "Unable to find machine for %s", machineaddr);
  1129. return false;
  1130. }
  1131. StringAttr targetdomain;
  1132. Owned<IConstDomainInfo> domain = machine->getDomain();
  1133. if (!domain)
  1134. {
  1135. LOG(MCdebugInfo, unknownJob, "Unable to find domain for %s", machineaddr);
  1136. return false;
  1137. }
  1138. //domain->getName(StringAttrAdaptor(targetdomain)); // confuses g++
  1139. StringAttrAdaptor strval(targetdomain);
  1140. domain->getName(strval);
  1141. Owned<IConstInstanceInfo> instance = getInstance(tag, version, targetdomain);
  1142. if (!instance)
  1143. {
  1144. LOG(MCdebugInfo, unknownJob, "Unable to find process %s for domain %s", tag, targetdomain.get());
  1145. return false;
  1146. }
  1147. return instance->getRunInfo(path,dir,defprogname);
  1148. }
  1149. catch (IException * e)
  1150. {
  1151. EXCLOG(e, "Extracting slave version");
  1152. e->Release();
  1153. return false;
  1154. }
  1155. }
  1156. void CLocalEnvironment::clearCache()
  1157. {
  1158. synchronized procedure(safeCache);
  1159. if (conn) {
  1160. p.clear();
  1161. conn->reload();
  1162. p.setown(conn->getRoot());
  1163. }
  1164. cache.kill();
  1165. machineCacheBuilt = false;
  1166. resetPasswordsFromSDS();
  1167. }
  1168. //==========================================================================================
  1169. static CriticalSection getEnvSect;
  1170. extern ENVIRONMENT_API IEnvironmentFactory * getEnvironmentFactory()
  1171. {
  1172. CriticalBlock block(getEnvSect);
  1173. if (!factory)
  1174. {
  1175. factory = new CEnvironmentFactory();
  1176. addShutdownHook(*factory);
  1177. }
  1178. return LINK(factory);
  1179. }
  1180. extern ENVIRONMENT_API void closeEnvironment()
  1181. {
  1182. try
  1183. {
  1184. CEnvironmentFactory* pFactory;
  1185. {
  1186. //this method is not meant to be invoked by multiple
  1187. //threads concurrently but just in case...
  1188. CriticalBlock block(getEnvSect);
  1189. pFactory = factory;
  1190. factory = NULL;
  1191. }
  1192. clearPasswordsFromSDS();
  1193. if (pFactory)
  1194. {
  1195. removeShutdownHook(*pFactory);
  1196. pFactory->close();
  1197. pFactory->Release();
  1198. }
  1199. }
  1200. catch (IException *e)
  1201. {
  1202. EXCLOG(e);
  1203. }
  1204. }