dllserver.cpp 24 KB

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