dllserver.cpp 25 KB

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