dllserver.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "jliball.hpp"
  15. #include "dllserver.hpp"
  16. #include "jiter.ipp"
  17. #include "jexcept.hpp"
  18. #include "dllservererr.hpp"
  19. #include "daclient.hpp"
  20. #include "dasds.hpp"
  21. #include "rmtfile.hpp"
  22. #include "dalienv.hpp"
  23. #include "thorplugin.hpp"
  24. #ifdef _WIN32
  25. #define DEFAULT_SERVER_ROOTDIR "c:\\dllserver"
  26. #else
  27. #define DEFAULT_SERVER_ROOTDIR "/c$/dllserver"
  28. #endif
  29. static Owned<IConstDomainInfo> hostDomain;
  30. IConstDomainInfo * getDomainFromIp(const char * ip)
  31. {
  32. Owned<IEnvironmentFactory> ef = getEnvironmentFactory();
  33. Owned<IConstEnvironment> env = ef->openEnvironment();
  34. if (!env)
  35. return NULL;
  36. Owned<IConstMachineInfo> curMachine = env->getMachineByAddress(ip);
  37. if (!curMachine)
  38. return NULL;
  39. return curMachine->getDomain();
  40. }
  41. IConstDomainInfo * cachedHostDomain()
  42. {
  43. if (!hostDomain)
  44. {
  45. StringBuffer ipText;
  46. queryHostIP().getIpText(ipText);
  47. hostDomain.setown(getDomainFromIp(ipText.str()));
  48. }
  49. return hostDomain;
  50. }
  51. void getPath(StringBuffer & path, const char * name)
  52. {
  53. path.append("/GeneratedDlls/GeneratedDll[@uid=\"").append(name).append("\"]");
  54. }
  55. //---------------------------------------------------------------------------
  56. class TreeIteratorWrapper : public CInterface, implements IIterator
  57. {
  58. public:
  59. TreeIteratorWrapper(IPropertyTreeIterator * _iter) { iter.setown(_iter); }
  60. IMPLEMENT_IINTERFACE
  61. virtual bool first()
  62. {
  63. cur.clear();
  64. return iter->first();
  65. }
  66. virtual bool next()
  67. {
  68. cur.clear();
  69. return iter->next();
  70. }
  71. virtual bool isValid()
  72. {
  73. return (cur != NULL);
  74. }
  75. virtual IInterface & get()
  76. {
  77. return *cur.getLink();
  78. }
  79. virtual IInterface & query()
  80. {
  81. return *cur;
  82. }
  83. protected:
  84. Owned<IInterface> cur;
  85. Owned<IPropertyTreeIterator> iter;
  86. };
  87. //---------------------------------------------------------------------------
  88. static void deleteLocationFiles(IDllLocation & cur, bool removeDirectory)
  89. {
  90. RemoteFilename filename;
  91. cur.getDllFilename(filename);
  92. Owned<IFile> file = createIFile(filename);
  93. file->remove();
  94. if (cur.getLibFilename(filename))
  95. {
  96. file.setown(createIFile(filename));
  97. file->remove();
  98. }
  99. if (removeDirectory)
  100. {
  101. //Finally try and remove the directory - this will fail if it isn't empty
  102. StringBuffer path, dir;
  103. cur.getDllFilename(filename);
  104. filename.getRemotePath(path);
  105. splitDirTail(path.str(), dir);
  106. filename.setRemotePath(dir.str());
  107. file.setown(createIFile(filename));
  108. file->remove();
  109. }
  110. }
  111. class DllLocation : public CInterface, implements IDllLocation
  112. {
  113. const char *cacheRoot;
  114. public:
  115. DllLocation(IPropertyTree * _entryRoot, IPropertyTree * _locationRoot, const char *_cacheRoot)
  116. : cacheRoot(_cacheRoot)
  117. {
  118. entryRoot.set(_entryRoot);
  119. locationRoot.set(_locationRoot);
  120. }
  121. IMPLEMENT_IINTERFACE
  122. virtual void getDllFilename(RemoteFilename & filename)
  123. {
  124. SocketEndpoint ep(locationRoot->queryProp("@ip"));
  125. filename.setPath(ep, locationRoot->queryProp("@dll"));
  126. }
  127. virtual bool getLibFilename(RemoteFilename & filename)
  128. {
  129. const char * lib = locationRoot->queryProp("@lib");
  130. if (!lib) return false;
  131. #ifndef _WIN32
  132. int namelen = strlen(lib);
  133. StringBuffer libnamebuf(lib);
  134. if(!((namelen >= 3) && (strcmp(lib+namelen-3, ".so") == 0)))
  135. {
  136. libnamebuf.append(".so");
  137. lib = libnamebuf.str();
  138. }
  139. #endif
  140. SocketEndpoint ep(locationRoot->queryProp("@ip"));
  141. filename.setPath(ep, lib);
  142. return true;
  143. }
  144. virtual void getIP(IpAddress & ip)
  145. {
  146. ip.ipset(locationRoot->queryProp("@ip"));
  147. }
  148. virtual DllLocationType queryLocation()
  149. {
  150. SocketEndpoint ep(locationRoot->queryProp("@ip"));
  151. if (ep.isLocal())
  152. {
  153. RemoteFilename filename;
  154. getDllFilename(filename);
  155. StringBuffer lp;
  156. filename.getLocalPath(lp);
  157. if (strncmp(lp, cacheRoot, strlen(cacheRoot))==0)
  158. return DllLocationDirectory;
  159. return DllLocationLocal;
  160. }
  161. #ifdef _WIN32
  162. Owned<IConstDomainInfo> curDomain = getDomainFromIp(locationRoot->queryProp("@ip"));
  163. IConstDomainInfo * hostDomain = cachedHostDomain();
  164. if (curDomain && hostDomain && (curDomain == hostDomain))
  165. return DllLocationDomain;
  166. #endif
  167. return DllLocationAnywhere;
  168. }
  169. virtual void remove(bool removeFiles, bool removeDirectory);
  170. protected:
  171. Owned<IPropertyTree> locationRoot;
  172. Owned<IPropertyTree> entryRoot;
  173. };
  174. static bool propsMatch(IPropertyTree & left, IPropertyTree & right, const char * prop)
  175. {
  176. const char * l = left.queryProp(prop);
  177. const char * r = right.queryProp(prop);
  178. if (!l || !r) return (l == r);
  179. return strcmp(l, r) == 0;
  180. }
  181. void DllLocation::remove(bool removeFiles, bool removeDirectory)
  182. {
  183. if (removeFiles)
  184. {
  185. try
  186. {
  187. deleteLocationFiles(*this, removeDirectory);
  188. }
  189. catch (IException * e)
  190. {
  191. EXCLOG(e, "Removing dll");
  192. e->Release();
  193. }
  194. }
  195. StringBuffer path;
  196. getPath(path, entryRoot->queryProp("@name"));
  197. Owned<IRemoteConnection> conn = querySDS().connect(path.str(), myProcessSession(), RTM_LOCK_WRITE, 5000);
  198. Owned<IPropertyTreeIterator> iter = conn->queryRoot()->getElements("location");
  199. ForEach(*iter)
  200. {
  201. IPropertyTree & cur = iter->query();
  202. if (propsMatch(cur, *locationRoot, "@ip") && propsMatch(cur, *locationRoot, "@dll") && propsMatch(cur, *locationRoot, "@lib"))
  203. {
  204. conn->queryRoot()->removeTree(&cur);
  205. break;
  206. }
  207. }
  208. }
  209. class LocationIterator : public TreeIteratorWrapper
  210. {
  211. const char *cacheRoot;
  212. public:
  213. LocationIterator(IPropertyTree * _dllEntry, IPropertyTreeIterator * _iter, const char *_cacheRoot)
  214. : TreeIteratorWrapper(_iter), cacheRoot(_cacheRoot)
  215. {
  216. dllEntry.set(_dllEntry);
  217. }
  218. virtual bool first()
  219. {
  220. bool ok = TreeIteratorWrapper::first();
  221. if (ok)
  222. cur.setown(new DllLocation(dllEntry, &iter->query(), cacheRoot));
  223. return ok;
  224. }
  225. virtual bool next()
  226. {
  227. bool ok = TreeIteratorWrapper::next();
  228. if (ok)
  229. cur.setown(new DllLocation(dllEntry, &iter->query(), cacheRoot));
  230. return ok;
  231. }
  232. protected:
  233. Owned<IPropertyTree> dllEntry;
  234. };
  235. //---------------------------------------------------------------------------
  236. class DllEntry : public CInterface, implements IDllEntry
  237. {
  238. public:
  239. DllEntry(IPropertyTree * root, const char *cacheRoot);
  240. IMPLEMENT_IINTERFACE
  241. virtual IIterator * createLocationIterator();
  242. virtual IDllLocation * getBestLocation();
  243. virtual IDllLocation * getBestLocationCandidate();
  244. virtual void getCreated(IJlibDateTime & dateTime)
  245. {
  246. dateTime.setString(root->queryProp("@created"));
  247. }
  248. virtual const char * queryKind()
  249. {
  250. return root->queryProp("@kind");
  251. }
  252. virtual const char * queryName()
  253. {
  254. return root->queryProp("@name");
  255. }
  256. virtual void remove(bool removeFiles, bool removeDirectory);
  257. protected:
  258. Owned<IPropertyTree> root;
  259. const char *cacheRoot;
  260. };
  261. DllEntry::DllEntry(IPropertyTree * _root, const char *_cacheRoot)
  262. : cacheRoot(_cacheRoot)
  263. {
  264. root.set(_root);
  265. }
  266. IIterator * DllEntry::createLocationIterator()
  267. {
  268. return new LocationIterator(root, root->getElements("location"), cacheRoot);
  269. }
  270. typedef IArrayOf<IDllLocation> LocationArray;
  271. int orderLocations(IInterface * * pLeft, IInterface * * pRight)
  272. {
  273. IDllLocation * left = (IDllLocation *)*pLeft;
  274. IDllLocation * right = (IDllLocation *)*pRight;
  275. return right->queryLocation() - left->queryLocation();
  276. }
  277. IDllLocation * DllEntry::getBestLocation()
  278. {
  279. LocationArray locations;
  280. Owned<IIterator> iter = createLocationIterator();
  281. ForEach(*iter)
  282. locations.append((IDllLocation &)iter->get());
  283. locations.sort(orderLocations);
  284. ForEachItemIn(idx, locations)
  285. {
  286. IDllLocation & cur = locations.item(idx);
  287. try
  288. {
  289. RemoteFilename filename;
  290. cur.getDllFilename(filename);
  291. Owned<IFile> file = createIFile(filename);
  292. Owned<IFileIO> io = file->open(IFOread);
  293. if (io)
  294. return LINK(&cur);
  295. }
  296. catch (IException * e)
  297. {
  298. StringBuffer s;
  299. EXCLOG(e, s.appendf("GetBestLocation - could not load entry for %s", root->queryProp("@name")).str());
  300. e->Release();
  301. //MORE: Should possibly remove the entry... but we don't know why we couldn't read it - could be a domain issue.
  302. }
  303. }
  304. throwError1(DSVERR_CouldNotFindDll, root->queryProp("@name"));
  305. return NULL;
  306. }
  307. IDllLocation * DllEntry::getBestLocationCandidate()
  308. {
  309. Owned<IIterator> iter = createLocationIterator();
  310. Owned<IDllLocation> best;
  311. DllLocationType bestLocation = DllLocationNowhere;
  312. ForEach(*iter)
  313. {
  314. IDllLocation & cur = (IDllLocation &)iter->query();
  315. DllLocationType location = cur.queryLocation();
  316. if (location == DllLocationDirectory)
  317. return LINK(&cur);
  318. if (location > bestLocation)
  319. {
  320. best.set(&cur);
  321. bestLocation = location;
  322. }
  323. }
  324. if (!best)
  325. throwError1(DSVERR_CouldNotFindDll, root->queryProp("@name"));
  326. return best.getClear();
  327. }
  328. void DllEntry::remove(bool removeFiles, bool removeDirectory)
  329. {
  330. if (removeFiles)
  331. {
  332. Owned<IIterator> iter = createLocationIterator();
  333. // a bit nasty, but don't remove the directory for the first location, since this is where things are created in the first place.
  334. bool isFirst = true;
  335. ForEach(*iter)
  336. {
  337. try
  338. {
  339. IDllLocation & cur = (IDllLocation &)iter->query();
  340. deleteLocationFiles(cur, removeDirectory && !isFirst);
  341. }
  342. catch (IException * e)
  343. {
  344. EXCLOG(e, "Removing dll");
  345. e->Release();
  346. }
  347. isFirst = false;
  348. }
  349. }
  350. StringBuffer path;
  351. getPath(path, root->queryProp("@name"));
  352. Owned<IRemoteConnection> conn = querySDS().connect(path.str(), myProcessSession(), RTM_LOCK_WRITE, 5000);
  353. conn->close(true);
  354. }
  355. class DllIterator : public TreeIteratorWrapper
  356. {
  357. public:
  358. DllIterator(IPropertyTree * _root, IPropertyTreeIterator * _iter, const char *_cacheRoot)
  359. : TreeIteratorWrapper(_iter), cacheRoot(_cacheRoot)
  360. {
  361. root.set(_root);
  362. }
  363. virtual bool first()
  364. {
  365. bool ok = TreeIteratorWrapper::first();
  366. if (ok)
  367. cur.setown(new DllEntry(&iter->query(), cacheRoot));
  368. return ok;
  369. }
  370. virtual bool next()
  371. {
  372. bool ok = TreeIteratorWrapper::next();
  373. if (ok)
  374. cur.setown(new DllEntry(&iter->query(), cacheRoot));
  375. return ok;
  376. }
  377. protected:
  378. Owned<IPropertyTree> root;
  379. const char *cacheRoot;
  380. };
  381. //---------------------------------------------------------------------------
  382. class DllServer : public CInterface, implements IDllServer
  383. {
  384. public:
  385. DllServer(const char * _rootDir);
  386. IMPLEMENT_IINTERFACE
  387. virtual IIterator * createDllIterator();
  388. virtual void ensureAvailable(const char * name, DllLocationType location);
  389. virtual void getDll(const char * name, MemoryBuffer & dllText);
  390. virtual IDllEntry * getEntry(const char * name);
  391. virtual void getLibrary(const char * name, MemoryBuffer & dllText);
  392. virtual void getLocalLibraryName(const char * name, StringBuffer & libraryName);
  393. virtual DllLocationType isAvailable(const char * name);
  394. virtual ILoadedDllEntry * loadDll(const char * name, DllLocationType location);
  395. virtual void removeDll(const char * name, bool removeDlls, bool removeDirectory);
  396. virtual void registerDll(const char * name, const char * kind, const char * dllPath);
  397. protected:
  398. void copyFileLocally(RemoteFilename & targetName, RemoteFilename & sourceName);
  399. DllEntry * doGetEntry(const char * name);
  400. void doRegisterDll(const char * name, const char * kind, const char * dllPath, const char * libPath);
  401. IDllLocation * getBestMatch(const char * name);
  402. IDllLocation * getBestMatchEx(const char * name);
  403. protected:
  404. StringAttr rootDir;
  405. };
  406. DllServer::DllServer(const char * _rootDir)
  407. {
  408. rootDir.set(_rootDir);
  409. }
  410. void DllServer::copyFileLocally(RemoteFilename & targetName, RemoteFilename & sourceName)
  411. {
  412. StringBuffer sourceLocalPath,targetLocalPath;
  413. sourceName.getLocalPath(sourceLocalPath);
  414. targetLocalPath.append(rootDir);
  415. recursiveCreateDirectory(targetLocalPath.str());
  416. targetLocalPath.append(PATHSEPCHAR);
  417. splitFilename(sourceLocalPath.str(),NULL,NULL,&targetLocalPath,&targetLocalPath);
  418. SocketEndpoint hostEndpoint;
  419. hostEndpoint.setLocalHost((unsigned short)0);
  420. targetName.setPath(hostEndpoint, targetLocalPath.str());
  421. OwnedIFile source = createIFile(sourceName);
  422. OwnedIFile target = createIFile(targetName);
  423. copyFile(target, source);
  424. }
  425. IIterator * DllServer::createDllIterator()
  426. {
  427. Owned<IRemoteConnection> conn = querySDS().connect("/GeneratedDlls", myProcessSession(), 0, 5000);
  428. IPropertyTree * root = conn->queryRoot();
  429. return conn ? (IIterator *)new DllIterator(root, root->getElements("GeneratedDll"), rootDir) : (IIterator *)new CNullIterator;
  430. }
  431. DllEntry * DllServer::doGetEntry(const char * name)
  432. {
  433. StringBuffer path;
  434. getPath(path, name);
  435. Owned<IRemoteConnection> conn = querySDS().connect(path.str(), myProcessSession(), 0, 5000);
  436. if (conn)
  437. return new DllEntry(conn->queryRoot(), rootDir);
  438. return NULL;
  439. }
  440. void DllServer::doRegisterDll(const char * name, const char * kind, const char * dllPath, const char * libPath)
  441. {
  442. Owned<IRemoteConnection> lock = querySDS().connect("/GeneratedDlls", myProcessSession(), RTM_LOCK_WRITE, 5000);
  443. RemoteFilename dllRemote;
  444. StringBuffer ipText, dllText;
  445. dllRemote.setRemotePath(dllPath);
  446. dllRemote.queryIP().getIpText(ipText);
  447. dllRemote.getLocalPath(dllText);
  448. StringBuffer path;
  449. getPath(path, name);
  450. Owned<IRemoteConnection> conn = querySDS().connect(path.str(), myProcessSession(), RTM_LOCK_WRITE, 5000);
  451. if (conn)
  452. {
  453. //check the entry doesn't exist already....
  454. Owned<IPropertyTreeIterator> iter = conn->queryRoot()->getElements("location");
  455. ForEach(*iter)
  456. {
  457. IPropertyTree & cur = iter->query();
  458. if ((stricmp(cur.queryProp("@ip"),ipText.str()) == 0) &&
  459. (stricmp(cur.queryProp("@dll"),dllText.str()) == 0))
  460. return;
  461. }
  462. }
  463. else
  464. {
  465. conn.setown(querySDS().connect("/GeneratedDlls/GeneratedDll", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_ADD, 5000));
  466. if (!conn)
  467. {
  468. ::Release(querySDS().connect("/GeneratedDlls", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_ADD, 5000));
  469. conn.setown(querySDS().connect("/GeneratedDlls/GeneratedDll", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_ADD, 5000));
  470. }
  471. IPropertyTree * entry = conn->queryRoot();
  472. entry->setProp("@name", name);
  473. entry->setProp("@kind", kind);
  474. Owned<IJlibDateTime> now = createDateTimeNow();
  475. StringBuffer nowText;
  476. StringBufferAdaptor strval(nowText);
  477. now->getString(strval);
  478. entry->setProp("@created", nowText.str());
  479. conn->queryRoot()->setProp("@uid", name);
  480. }
  481. IPropertyTree * locationTree = createPTree("location", false);
  482. locationTree->setProp("@ip", ipText.str());
  483. locationTree->setProp("@dll", dllText.str());
  484. if (libPath && strlen(libPath))
  485. {
  486. RemoteFilename libRemote;
  487. libRemote.setRemotePath(libPath);
  488. if (!dllRemote.queryIP().ipequals(libRemote.queryIP()))
  489. throwError(DSVERR_DllLibIpMismatch);
  490. StringBuffer libText;
  491. libRemote.getLocalPath(libText);
  492. locationTree->setProp("@lib", libText.str());
  493. }
  494. conn->queryRoot()->addPropTree("location", locationTree);
  495. }
  496. void DllServer::ensureAvailable(const char * name, DllLocationType location)
  497. {
  498. Owned<DllEntry> match = doGetEntry(name);
  499. if (!match)
  500. throwError1(DSVERR_CouldNotFindDll, name);
  501. Owned<IDllLocation> bestLocation = match->getBestLocation();
  502. if (bestLocation->queryLocation() < location)
  503. {
  504. StringBuffer remoteDllPath, remoteLibPath;
  505. RemoteFilename sourceName, dllName, libName;
  506. bestLocation->getDllFilename(sourceName);
  507. copyFileLocally(dllName, sourceName);
  508. dllName.getRemotePath(remoteDllPath);
  509. if (bestLocation->getLibFilename(sourceName))
  510. {
  511. copyFileLocally(libName, sourceName);
  512. libName.getRemotePath(remoteLibPath);
  513. }
  514. doRegisterDll(name, "**Error**", remoteDllPath.str(), remoteLibPath.str());
  515. assertex(isAvailable(name) >= DllLocationLocal);
  516. }
  517. }
  518. IDllLocation * DllServer::getBestMatch(const char * name)
  519. {
  520. Owned<DllEntry> match = doGetEntry(name);
  521. if (!match)
  522. return NULL;
  523. return match->getBestLocation();
  524. }
  525. IDllLocation * DllServer::getBestMatchEx(const char * name)
  526. {
  527. IDllLocation * location = getBestMatch(name);
  528. if (!location)
  529. throwError1(DSVERR_CouldNotFindDll, name);
  530. return location;
  531. }
  532. IDllEntry * DllServer::getEntry(const char * name)
  533. {
  534. return doGetEntry(name);
  535. }
  536. void DllServer::getDll(const char * name, MemoryBuffer & dllText)
  537. {
  538. RemoteFilename filename;
  539. Owned<IDllLocation> match = getBestMatchEx(name);
  540. match->getDllFilename(filename);
  541. Owned<IFile> file = createIFile(filename);
  542. OwnedIFileIO io = file->open(IFOread);
  543. read(io, 0, (size32_t)-1, dllText);
  544. }
  545. void DllServer::getLibrary(const char * name, MemoryBuffer & libText)
  546. {
  547. RemoteFilename filename;
  548. Owned<IDllLocation> match = getBestMatchEx(name);
  549. if (!match->getLibFilename(filename))
  550. throwError1(DSVERR_NoAssociatedLib, name);
  551. Owned<IFile> file = createIFile(filename);
  552. OwnedIFileIO io = file->open(IFOread);
  553. read(io, 0, (size32_t)-1, libText);
  554. }
  555. void DllServer::getLocalLibraryName(const char * name, StringBuffer & libraryName)
  556. {
  557. RemoteFilename filename;
  558. Owned<IDllLocation> match = getBestMatchEx(name);
  559. if (match->queryLocation() < DllLocationLocal)
  560. throwError1(DSVERR_LibNotLocal, name);
  561. if (!match->getLibFilename(filename))
  562. throwError1(DSVERR_NoAssociatedLib, name);
  563. filename.getLocalPath(libraryName);
  564. }
  565. DllLocationType DllServer::isAvailable(const char * name)
  566. {
  567. try
  568. {
  569. Owned<IDllLocation> match = getBestMatch(name);
  570. if (match)
  571. return match->queryLocation();
  572. }
  573. catch (IException *E)
  574. {
  575. E->Release();
  576. }
  577. return DllLocationNowhere;
  578. }
  579. ILoadedDllEntry * DllServer::loadDll(const char * name, DllLocationType type)
  580. {
  581. #ifdef _WIN32
  582. if (type < DllLocationDomain)
  583. type = DllLocationDomain;
  584. #else
  585. if (type < DllLocationLocal)
  586. type = DllLocationLocal;
  587. #endif
  588. ensureAvailable(name, type);
  589. Owned<IDllLocation> location = getBestMatchEx(name);
  590. RemoteFilename rfile;
  591. location->getDllFilename(rfile);
  592. StringBuffer x;
  593. rfile.getPath(x);
  594. LOG(MCdebugInfo, unknownJob, "Loading dll (%s) from location %s", name, x.str());
  595. return createDllEntry(x.str(), false, NULL);
  596. }
  597. void DllServer::removeDll(const char * name, bool removeDlls, bool removeDirectory)
  598. {
  599. Owned<IDllEntry> entry = getEntry(name);
  600. if (entry)
  601. entry->remove(removeDlls, removeDirectory);
  602. }
  603. void DllServer::registerDll(const char * name, const char * kind, const char * dllLocation)
  604. {
  605. doRegisterDll(name, kind, dllLocation, NULL);
  606. }
  607. //---------------------------------------------------------------------------
  608. static DllServer * dllServer;
  609. #if 0
  610. struct __init_dllserver
  611. {
  612. ~__init_dllserver() { ::Release(dllServer); }
  613. } __do_init_dllserver;
  614. #endif
  615. IDllServer & queryDllServer()
  616. {
  617. if (!dllServer)
  618. {
  619. const char* dllserver_root = getenv("DLLSERVER_ROOT");
  620. StringBuffer dir;
  621. if(dllserver_root == NULL)
  622. {
  623. if (envGetConfigurationDirectory("temp","dllserver","dllserver",dir)) // not sure if different instance might be better but never separated in past
  624. dllserver_root = dir.str();
  625. else
  626. dllserver_root = DEFAULT_SERVER_ROOTDIR;
  627. }
  628. initDllServer(dllserver_root);
  629. }
  630. return *dllServer;
  631. }
  632. void closeDllServer()
  633. {
  634. hostDomain.clear();
  635. if (dllServer)
  636. {
  637. dllServer->Release();
  638. dllServer = NULL;
  639. }
  640. }
  641. void initDllServer(const char * localRoot)
  642. {
  643. ::Release(dllServer);
  644. dllServer = new DllServer(localRoot);
  645. }
  646. void cleanUpOldDlls()
  647. {
  648. Owned<IJlibDateTime> cutoff = createDateTimeNow();
  649. unsigned year;
  650. unsigned month;
  651. unsigned day;
  652. cutoff->getGmtDate(year, month, day);
  653. if (false && month-- == 1)
  654. {
  655. month = 12;
  656. year--;
  657. }
  658. cutoff->setGmtDate(year, month, day);
  659. //Remove all but one copy of all workunits more than a month old
  660. Owned<IIterator> dllIter = queryDllServer().createDllIterator();
  661. ForEach(*dllIter)
  662. {
  663. IDllEntry & entry = (IDllEntry &)dllIter->query();
  664. if (strcmp(entry.queryKind(), "workunit")==0)
  665. {
  666. Owned<IJlibDateTime> created = createDateTime();
  667. entry.getCreated(*created);
  668. if (created->compare(*cutoff) < 0)
  669. {
  670. Owned<IIterator> locIter = entry.createLocationIterator();
  671. bool first = true;
  672. ForEach(*locIter)
  673. {
  674. IDllLocation & location = (IDllLocation &)locIter->query();
  675. if (!first)
  676. location.remove(true, true);
  677. first = false;
  678. }
  679. }
  680. }
  681. }
  682. }
  683. void testDllServer()
  684. {
  685. IDllServer & server = queryDllServer();
  686. Owned<IDllEntry> oldentry2 = server.getEntry("WorkUnit1");
  687. if (oldentry2)
  688. oldentry2->remove(false, false);
  689. server.registerDll("WorkUnit1","workunit","\\\\ghalliday\\c$\\edata\\ecl\\regress\\process0.dll");
  690. assertex(server.isAvailable("WorkUnit1") == DllLocationLocal);
  691. server.ensureAvailable("WorkUnit1",DllLocationLocal);
  692. server.registerDll("WorkUnit1","workunit","\\\\1.1.1.1\\c$\\edata\\ecl\\regress\\process0.dll");
  693. const char * abcFilename = "\\\\127.0.0.1\\c$\\temp\\dlltest\abc";
  694. Owned<IFile> temp = createIFile(abcFilename);
  695. recursiveCreateDirectoryForFile(abcFilename);
  696. Owned<IFileIO> io = temp->open(IFOcreate);
  697. io->write(0, 10, "abcdefghij");
  698. io.clear();
  699. server.registerDll("WorkUnitAbc","workunit",abcFilename);
  700. server.removeDll("WorkUnitAbc", true, true);
  701. cleanUpOldDlls();
  702. }