daserver.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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 <unordered_map>
  14. #include <string>
  15. #include "build-config.h"
  16. #include "platform.h"
  17. #include "thirdparty.h"
  18. #include "jlib.hpp"
  19. #include "jlog.ipp"
  20. #include "jptree.hpp"
  21. #include "jmisc.hpp"
  22. #include "jutil.hpp"
  23. #include "mpbase.hpp"
  24. #include "mpcomm.hpp"
  25. #include "mplog.hpp" //MORE: deprecated feature, not used by any new clients, remove once all deployed clients that depend on it are upgraded
  26. #include "rmtfile.hpp"
  27. #include "dacoven.hpp"
  28. #include "dadfs.hpp"
  29. #include "dasess.hpp"
  30. #include "daaudit.hpp"
  31. #include "dasds.hpp"
  32. #include "daclient.hpp"
  33. #include "dasubs.ipp"
  34. #include "danqs.hpp"
  35. #include "dadiags.hpp"
  36. #ifdef _DEBUG
  37. //#define DALI_MIN
  38. #endif
  39. #ifdef DALI_MIN
  40. #define _NO_LDAP
  41. #endif
  42. #include "daserver.hpp"
  43. #ifndef _NO_LDAP
  44. #include "daldap.hpp"
  45. #endif
  46. Owned<IPropertyTree> serverConfig;
  47. static IArrayOf<IDaliServer> servers;
  48. static CriticalSection *stopServerCrit;
  49. MODULE_INIT(INIT_PRIORITY_DALI_DASERVER)
  50. {
  51. stopServerCrit = new CriticalSection;
  52. return true;
  53. }
  54. MODULE_EXIT()
  55. {
  56. servers.kill(); // should already be clear when stopped
  57. serverConfig.clear();
  58. delete stopServerCrit;
  59. }
  60. #define DEFAULT_PERF_REPORT_DELAY 60
  61. #define DEFAULT_MOUNT_POINT "/mnt/dalimirror/"
  62. void setMsgLevel(ILogMsgHandler * fileMsgHandler, unsigned level)
  63. {
  64. ILogMsgFilter *filter = getSwitchLogMsgFilterOwn(getComponentLogMsgFilter(3), getCategoryLogMsgFilter(MSGAUD_all, MSGCLS_all, level, true), getDefaultLogMsgFilter());
  65. queryLogMsgManager()->changeMonitorFilter(queryStderrLogMsgHandler(), filter);
  66. queryLogMsgManager()->changeMonitorFilterOwn(fileMsgHandler, filter);
  67. }
  68. void AddServers(const char *auditdir)
  69. {
  70. // order significant
  71. servers.append(*createDaliSessionServer());
  72. servers.append(*createDaliPublisherServer());
  73. servers.append(*createDaliSDSServer(serverConfig));
  74. servers.append(*createDaliNamedQueueServer());
  75. servers.append(*createDaliDFSServer(serverConfig));
  76. servers.append(*createDaliAuditServer(auditdir));
  77. servers.append(*createDaliDiagnosticsServer());
  78. // add new coven servers here
  79. }
  80. static bool serverStopped = false;
  81. static void stopServer()
  82. {
  83. CriticalBlock b(*stopServerCrit); // NB: will not protect against abort handler, which will interrupt thread and be on same TID.
  84. if (serverStopped) return;
  85. serverStopped = true;
  86. ForEachItemInRev(h,servers)
  87. {
  88. IDaliServer &server=servers.item(h);
  89. LOG(MCprogress, unknownJob, "Suspending %d",h);
  90. server.suspend();
  91. }
  92. ForEachItemInRev(i,servers)
  93. {
  94. IDaliServer &server=servers.item(i);
  95. LOG(MCprogress, unknownJob, "Stopping %d",i);
  96. server.stop();
  97. }
  98. closeCoven();
  99. ForEachItemInRev(j,servers)
  100. {
  101. servers.remove(j); // ensure correct order for destruction
  102. }
  103. stopLogMsgReceivers(); //MORE: deprecated feature, not used by any new clients, remove once all deployed clients that depend on it are upgraded
  104. stopMPServer();
  105. }
  106. bool actionOnAbort()
  107. {
  108. stopServer();
  109. return true;
  110. }
  111. USE_JLIB_ALLOC_HOOK;
  112. void usage(void)
  113. {
  114. printf("daserver (option)\n");
  115. printf("--rank|-r <value>\t: dali ranking value\n");
  116. printf("--server|-s <value>\t: server ip if not local host\n");
  117. printf("--port|-p <value>\t: server port only effective if --server set\n");
  118. printf("--daemon|-d <instanceName>\t: run daemon as instance\n");
  119. }
  120. /* NB: Ideally this belongs within common/environment,
  121. * however, that would introduce a circular dependency.
  122. */
  123. static bool populateWhiteListFromEnvironment(IWhiteListWriter &writer)
  124. {
  125. if (isContainerized())
  126. return false;
  127. Owned<IRemoteConnection> conn = querySDS().connect("/Environment", 0, 0, INFINITE);
  128. assertex(conn);
  129. if (!conn->queryRoot()->hasProp("Software/DaliServerProcess"))
  130. return false;
  131. // only ever expecting 1 DaliServerProcess and 1 WhiteList
  132. const IPropertyTree *whiteListTree = conn->queryRoot()->queryPropTree("Software/DaliServerProcess[1]/WhiteList[1]");
  133. bool enabled = true;
  134. if (whiteListTree)
  135. {
  136. enabled = whiteListTree->getPropBool("@enabled", true); // on by default
  137. // Default for now is to allow clients that send no role (legacy) to connect if their IP is whitelisted.
  138. writer.setAllowAnonRoles(whiteListTree->getPropBool("@allowAnonRoles", true));
  139. }
  140. std::unordered_map<std::string, std::string> machineMap;
  141. auto populateMachineMap = [&machineMap](const IPropertyTree &environment)
  142. {
  143. Owned<IPropertyTreeIterator> machineIter = environment.getElements("Hardware/Computer");
  144. ForEach(*machineIter)
  145. {
  146. const IPropertyTree &machine = machineIter->query();
  147. const char *name = machine.queryProp("@name");
  148. const char *host = machine.queryProp("@netAddress");
  149. machineMap.insert({name, host});
  150. }
  151. };
  152. auto resolveComputer = [&machineMap](const char *compName, const char *defaultValue, StringBuffer &result) -> const char *
  153. {
  154. const auto &it = machineMap.find(compName);
  155. if (it == machineMap.end())
  156. return defaultValue;
  157. IpAddress ip(it->second.c_str());
  158. if (ip.isNull())
  159. return defaultValue;
  160. return ip.getIpText(result);
  161. };
  162. auto addRoles = [&writer, &resolveComputer](const IPropertyTree &component, const std::initializer_list<unsigned __int64> &roles)
  163. {
  164. Owned<IPropertyTreeIterator> instanceIter = component.getElements("Instance");
  165. ForEach(*instanceIter)
  166. {
  167. const char *compName = instanceIter->query().queryProp("@computer");
  168. StringBuffer ipSB;
  169. const char *ip = resolveComputer(compName, component.queryProp("@netAddress"), ipSB);
  170. if (ip)
  171. {
  172. for (const auto &role: roles)
  173. writer.add(ip, role);
  174. }
  175. }
  176. };
  177. populateMachineMap(*conn->queryRoot());
  178. enum SoftwareComponentType
  179. {
  180. RoxieCluster,
  181. ThorCluster,
  182. EclAgentProcess,
  183. DfuServerProcess,
  184. EclCCServerProcess,
  185. EspProcess,
  186. SashaServerProcess,
  187. EclSchedulerProcess,
  188. DaliServerProcess,
  189. BackupNodeProcess,
  190. EclServerProcess,
  191. SparkThorProcess,
  192. };
  193. std::unordered_map<std::string, SoftwareComponentType> softwareTypeRoleMap = {
  194. { "RoxieCluster", RoxieCluster },
  195. { "ThorCluster", ThorCluster },
  196. { "EclAgentProcess", EclAgentProcess },
  197. { "DfuServerProcess", DfuServerProcess },
  198. { "EclCCServerProcess", EclCCServerProcess },
  199. { "EspProcess", EspProcess },
  200. { "SashaServerProcess", SashaServerProcess },
  201. { "EclSchedulerProcess", EclSchedulerProcess },
  202. { "DaliServerProcess", DaliServerProcess },
  203. { "BackupNodeProcess", BackupNodeProcess },
  204. { "EclServerProcess", EclServerProcess },
  205. { "SparkThorProcess", SparkThorProcess },
  206. };
  207. Owned<IPropertyTreeIterator> softwareIter = conn->queryRoot()->getElements("Software/*");
  208. ForEach(*softwareIter)
  209. {
  210. const IPropertyTree &component = softwareIter->query();
  211. const char *compProcess = component.queryName();
  212. const auto &it = softwareTypeRoleMap.find(compProcess);
  213. if (it != softwareTypeRoleMap.end())
  214. {
  215. switch (it->second)
  216. {
  217. case RoxieCluster:
  218. {
  219. Owned<IPropertyTreeIterator> serverIter = component.getElements("RoxieServerProcess");
  220. ForEach(*serverIter)
  221. {
  222. const IPropertyTree &server = serverIter->query();
  223. const char *serverCompName = server.queryProp("@computer");
  224. StringBuffer ipSB;
  225. const char *ip = resolveComputer(serverCompName, server.queryProp("@netAddress"), ipSB);
  226. if (ip)
  227. writer.add(ip, DCR_Roxie);
  228. }
  229. break;
  230. }
  231. case ThorCluster:
  232. {
  233. const char *masterCompName = component.queryProp("ThorMasterProcess/@computer");
  234. StringBuffer ipSB;
  235. const char *ip = resolveComputer(masterCompName, nullptr, ipSB);
  236. if (ip)
  237. {
  238. writer.add(ip, DCR_ThorMaster);
  239. writer.add(ip, DCR_DaliAdmin);
  240. }
  241. // NB: slaves are currently seen as foreign clients and are only used by Std.File.GetUniqueInteger (which calls Dali v. occassionally)
  242. Owned<IPropertyTreeIterator> slaveIter = component.getElements("ThorSlaveProcess");
  243. ForEach(*slaveIter)
  244. {
  245. const char *slaveCompName = slaveIter->query().queryProp("@computer");
  246. const char *ip = resolveComputer(slaveCompName, nullptr, ipSB.clear());
  247. if (ip)
  248. writer.add(ip, DCR_ThorSlave);
  249. }
  250. break;
  251. }
  252. case EclAgentProcess:
  253. addRoles(component, { DCR_EclAgent, DCR_AgentExec });
  254. break;
  255. case DfuServerProcess:
  256. addRoles(component, { DCR_DfuServer });
  257. break;
  258. case EclCCServerProcess:
  259. addRoles(component, { DCR_EclCCServer, DCR_EclCC });
  260. break;
  261. case EclServerProcess:
  262. addRoles(component, { DCR_EclServer, DCR_EclCC });
  263. break;
  264. case EspProcess:
  265. addRoles(component, { DCR_EspServer });
  266. break;
  267. case SashaServerProcess:
  268. addRoles(component, { DCR_SashaServer, DCR_XRef });
  269. break;
  270. case EclSchedulerProcess:
  271. addRoles(component, { DCR_EclScheduler });
  272. break;
  273. case BackupNodeProcess:
  274. addRoles(component, { DCR_BackupGen, DCR_DaliAdmin });
  275. break;
  276. case DaliServerProcess:
  277. addRoles(component, { DCR_DaliServer, DCR_DaliDiag, DCR_SwapNode, DCR_UpdateEnv, DCR_DaliAdmin, DCR_TreeView, DCR_Testing, DCR_DaFsControl, DCR_XRef, DCR_Config, DCR_ScheduleAdmin, DCR_Monitoring, DCR_DaliStop });
  278. break;
  279. case SparkThorProcess:
  280. addRoles(component, { DCR_DaliAdmin });
  281. break;
  282. }
  283. }
  284. }
  285. if (whiteListTree)
  286. {
  287. Owned<IPropertyTreeIterator> whiteListIter = whiteListTree->getElements("Entry");
  288. ForEach(*whiteListIter)
  289. {
  290. const IPropertyTree &entry = whiteListIter->query();
  291. StringArray hosts, roles;
  292. hosts.appendListUniq(entry.queryProp("@hosts"), ",");
  293. roles.appendListUniq(entry.queryProp("@roles"), ",");
  294. ForEachItemIn(h, hosts)
  295. {
  296. IpAddress ip(hosts.item(h));
  297. if (!ip.isNull())
  298. {
  299. StringBuffer ipStr;
  300. ip.getIpText(ipStr);
  301. ForEachItemIn(r, roles)
  302. {
  303. const char *roleStr = roles.item(r);
  304. char *endPtr;
  305. long numericRole = strtol(roleStr, &endPtr, 10);
  306. if (endPtr != roleStr && (numericRole>0 && numericRole<DCR_Max)) // in case legacy role needs adding
  307. writer.add(ipStr.str(), numericRole);
  308. else
  309. writer.add(ipStr.str(), queryRole(roleStr));
  310. }
  311. }
  312. }
  313. }
  314. }
  315. return enabled;
  316. }
  317. static StringBuffer &formatDaliRole(StringBuffer &out, unsigned __int64 role)
  318. {
  319. return out.append(queryRoleName((DaliClientRole)role));
  320. }
  321. static constexpr const char * defaultYaml = R"!!(
  322. version: 1.0
  323. dali:
  324. name: dali
  325. dataPath: "/var/lib/HPCCSystems/dalistorage"
  326. logging:
  327. detail: 100
  328. )!!";
  329. int main(int argc, const char* argv[])
  330. {
  331. rank_t myrank = 0;
  332. const char *server = nullptr;
  333. int port = 0;
  334. InitModuleObjects();
  335. NoQuickEditSection x;
  336. try
  337. {
  338. EnableSEHtoExceptionMapping();
  339. #ifndef __64BIT__
  340. // Restrict stack sizes on 32-bit systems
  341. Thread::setDefaultStackSize(0x20000);
  342. #endif
  343. setAllocHook(true);
  344. serverConfig.setown(loadConfiguration(defaultYaml, argv, "dali", "DALI", DALICONF, nullptr));
  345. #ifndef _CONTAINERIZED
  346. Owned<IFile> sentinelFile = createSentinelTarget();
  347. removeSentinelFile(sentinelFile);
  348. for (unsigned i=1;i<(unsigned)argc;i++) {
  349. if (streq(argv[i],"--daemon") || streq(argv[i],"-d")) {
  350. if (daemon(1,0) || write_pidfile(argv[++i])) {
  351. perror("Failed to daemonize");
  352. return EXIT_FAILURE;
  353. }
  354. }
  355. else if (streq(argv[i],"--server") || streq(argv[i],"-s"))
  356. server = argv[++i];
  357. else if (streq(argv[i],"--port") || streq(argv[i],"-p"))
  358. port = atoi(argv[++i]);
  359. else if (streq(argv[i],"--rank") || streq(argv[i],"-r"))
  360. myrank = atoi(argv[++i]);
  361. else {
  362. usage();
  363. return EXIT_FAILURE;
  364. }
  365. }
  366. #endif
  367. #ifndef _CONTAINERIZED
  368. ILogMsgHandler * fileMsgHandler;
  369. {
  370. Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(serverConfig, "dali");
  371. lf->setLogDirSubdir("server");//add to tail of config log dir
  372. lf->setName("DaServer");//override default filename
  373. fileMsgHandler = lf->beginLogging();
  374. }
  375. #else
  376. setupContainerizedLogMsgHandler();
  377. #endif
  378. PROGLOG("Build %s", BUILD_TAG);
  379. StringBuffer dataPath;
  380. StringBuffer mirrorPath;
  381. #ifdef _CONTAINERIZED
  382. serverConfig->getProp("@dataPath", dataPath);
  383. /* NB: mirror settings are unlikely to be used in a container setup
  384. If detected, set in to legacy location under SDS/ for backward compatibility */
  385. serverConfig->getProp("@remoteBackupLocation", mirrorPath);
  386. if (mirrorPath.length())
  387. serverConfig->setProp("SDS/@remoteBackupLocation", mirrorPath);
  388. #else
  389. if (getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"dali","dali",serverConfig->queryProp("@name"),dataPath))
  390. serverConfig->setProp("@dataPath",dataPath.str());
  391. else if (getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"data","dali",serverConfig->queryProp("@name"),dataPath))
  392. serverConfig->setProp("@dataPath",dataPath.str());
  393. else
  394. serverConfig->getProp("@dataPath",dataPath);
  395. if (dataPath.length())
  396. {
  397. RemoteFilename rfn;
  398. rfn.setRemotePath(dataPath);
  399. if (!rfn.isLocal())
  400. {
  401. OERRLOG("if a dataPath is specified, it must be on local machine");
  402. return 0;
  403. }
  404. }
  405. // JCSMORE remoteBackupLocation should not be a property of SDS section really.
  406. if (!getConfigurationDirectory(serverConfig->queryPropTree("Directories"),"mirror","dali",serverConfig->queryProp("@name"),mirrorPath))
  407. serverConfig->getProp("SDS/@remoteBackupLocation",mirrorPath);
  408. #endif
  409. if (dataPath.length())
  410. {
  411. addPathSepChar(dataPath); // ensures trailing path separator
  412. serverConfig->setProp("@dataPath", dataPath.str());
  413. recursiveCreateDirectory(dataPath.str());
  414. }
  415. if (mirrorPath.length())
  416. {
  417. try
  418. {
  419. addPathSepChar(mirrorPath);
  420. try
  421. {
  422. StringBuffer backupURL;
  423. if (mirrorPath.length()<=2 || !isPathSepChar(mirrorPath.charAt(0)) || !isPathSepChar(mirrorPath.charAt(1)))
  424. { // local machine path, convert to url
  425. const char *backupnode = serverConfig->queryProp("SDS/@backupComputer");
  426. RemoteFilename rfn;
  427. if (backupnode&&*backupnode) {
  428. SocketEndpoint ep(backupnode);
  429. rfn.setPath(ep,mirrorPath.str());
  430. }
  431. else {
  432. OWARNLOG("Local path used for backup url: %s", mirrorPath.str());
  433. rfn.setLocalPath(mirrorPath.str());
  434. }
  435. rfn.getRemotePath(backupURL);
  436. mirrorPath.clear().append(backupURL);
  437. }
  438. else
  439. backupURL.append(mirrorPath);
  440. recursiveCreateDirectory(backupURL.str());
  441. addPathSepChar(backupURL);
  442. serverConfig->setProp("SDS/@remoteBackupLocation", backupURL.str());
  443. PROGLOG("Backup URL = %s", backupURL.str());
  444. }
  445. catch (IException *e)
  446. {
  447. EXCLOG(e, "Failed to create remote backup directory, disabling backups", MSGCLS_warning);
  448. serverConfig->removeProp("SDS/@remoteBackupLocation");
  449. mirrorPath.clear();
  450. e->Release();
  451. }
  452. if (mirrorPath.length())
  453. {
  454. PROGLOG("Checking backup location: %s", mirrorPath.str());
  455. #if defined(__linux__)
  456. if (serverConfig->getPropBool("@useNFSBackupMount", false))
  457. {
  458. RemoteFilename rfn;
  459. if (mirrorPath.length()<=2 || !isPathSepChar(mirrorPath.charAt(0)) || !isPathSepChar(mirrorPath.charAt(1)))
  460. rfn.setLocalPath(mirrorPath.str());
  461. else
  462. rfn.setRemotePath(mirrorPath.str());
  463. if (!rfn.getPort() && !rfn.isLocal())
  464. {
  465. StringBuffer mountPoint;
  466. serverConfig->getProp("@mountPoint", mountPoint);
  467. if (!mountPoint.length())
  468. mountPoint.append(DEFAULT_MOUNT_POINT);
  469. addPathSepChar(mountPoint);
  470. recursiveCreateDirectory(mountPoint.str());
  471. PROGLOG("Mounting url \"%s\" on mount point \"%s\"", mirrorPath.str(), mountPoint.str());
  472. bool ub = unmountDrive(mountPoint.str());
  473. if (!mountDrive(mountPoint.str(), rfn))
  474. {
  475. if (!ub)
  476. PROGLOG("Failed to remount mount point \"%s\", possibly in use?", mountPoint.str());
  477. else
  478. PROGLOG("Failed to mount \"%s\"", mountPoint.str());
  479. return 0;
  480. }
  481. else
  482. serverConfig->setProp("SDS/@remoteBackupLocation", mountPoint.str());
  483. mirrorPath.clear().append(mountPoint);
  484. }
  485. }
  486. #endif
  487. StringBuffer backupCheck(dataPath);
  488. backupCheck.append("bakchk.").append((unsigned)GetCurrentProcessId());
  489. OwnedIFile iFileDataDir = createIFile(backupCheck.str());
  490. OwnedIFileIO iFileIO = iFileDataDir->open(IFOcreate);
  491. iFileIO.clear();
  492. try
  493. {
  494. backupCheck.clear().append(mirrorPath).append("bakchk.").append((unsigned)GetCurrentProcessId());
  495. OwnedIFile iFileBackup = createIFile(backupCheck.str());
  496. if (iFileBackup->exists())
  497. {
  498. PROGLOG("remoteBackupLocation and dali data path point to same location! : %s", mirrorPath.str());
  499. iFileDataDir->remove();
  500. return 0;
  501. }
  502. }
  503. catch (IException *)
  504. {
  505. try { iFileDataDir->remove(); } catch (IException *e) { EXCLOG(e, NULL); e->Release(); }
  506. throw;
  507. }
  508. iFileDataDir->remove();
  509. #ifndef _CONTAINERIZED
  510. StringBuffer dest(mirrorPath.str());
  511. dest.append(DALICONF);
  512. copyFile(dest.str(), DALICONF);
  513. StringBuffer covenPath(dataPath);
  514. OwnedIFile ifile = createIFile(covenPath.append(DALICOVEN).str());
  515. if (ifile->exists())
  516. {
  517. dest.clear().append(mirrorPath.str()).append(DALICOVEN);
  518. copyFile(dest.str(), covenPath.str());
  519. }
  520. #endif
  521. }
  522. if (serverConfig->getPropBool("@daliServixCaching", true))
  523. setDaliServixSocketCaching(true);
  524. }
  525. catch (IException *e)
  526. {
  527. StringBuffer s("Failure whilst preparing dali backup location: ");
  528. LOG(MCoperatorError, unknownJob, e, s.append(mirrorPath).append(". Backup disabled").str());
  529. serverConfig->removeProp("SDS/@remoteBackupLocation");
  530. e->Release();
  531. }
  532. }
  533. #ifndef _CONTAINERIZED
  534. write_pidfile(serverConfig->queryProp("@name"));
  535. NamedMutex globalNamedMutex("DASERVER");
  536. if (!serverConfig->getPropBool("allowMultipleDalis"))
  537. {
  538. PROGLOG("Checking for existing daserver instances");
  539. if (!globalNamedMutex.lockWait(0))
  540. {
  541. OWARNLOG("Another DASERVER process is currently running");
  542. return 0;
  543. }
  544. }
  545. #endif
  546. SocketEndpoint ep;
  547. SocketEndpointArray epa;
  548. if (!server)
  549. {
  550. ep.setLocalHost(DALI_SERVER_PORT);
  551. epa.append(ep);
  552. }
  553. else
  554. {
  555. if (!port)
  556. ep.set(server,DALI_SERVER_PORT);
  557. else
  558. ep.set(server,port);
  559. epa.append(ep);
  560. }
  561. unsigned short myport = epa.item(myrank).port;
  562. startMPServer(DCR_DaliServer, myport, true, true);
  563. Owned<IMPServer> mpServer = getMPServer();
  564. Owned<IWhiteListHandler> whiteListHandler = createWhiteListHandler(populateWhiteListFromEnvironment, formatDaliRole);
  565. mpServer->installWhiteListCallback(whiteListHandler);
  566. #ifndef _CONTAINERIZED
  567. setMsgLevel(fileMsgHandler, serverConfig->getPropInt("SDS/@msgLevel", 100));
  568. #endif
  569. startLogMsgChildReceiver();
  570. startLogMsgParentReceiver();
  571. IGroup *group = createIGroup(epa);
  572. initCoven(group,serverConfig);
  573. group->Release();
  574. epa.kill();
  575. // Audit logging
  576. StringBuffer auditDir;
  577. {
  578. Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(serverConfig, "dali");
  579. lf->setLogDirSubdir("audit");//add to tail of config log dir
  580. lf->setName("DaAudit");//override default filename
  581. lf->setCreateAliasFile(false);
  582. lf->setMsgFields(MSGFIELD_timeDate | MSGFIELD_code);
  583. lf->setMsgAudiences(MSGAUD_audit);
  584. lf->setMaxDetail(TopDetail);
  585. lf->beginLogging();
  586. auditDir.set(lf->queryLogDir());
  587. }
  588. // SNMP logging
  589. bool enableSNMP = serverConfig->getPropBool("SDS/@enableSNMP");
  590. if (serverConfig->getPropBool("SDS/@enableSysLog",true))
  591. UseSysLogForOperatorMessages();
  592. AddServers(auditDir.str());
  593. addAbortHandler(actionOnAbort);
  594. startPerformanceMonitor(serverConfig->getPropInt("Coven/@perfReportDelay", DEFAULT_PERF_REPORT_DELAY)*1000);
  595. StringBuffer absPath;
  596. makeAbsolutePath(dataPath.str(), absPath);
  597. setPerformanceMonitorPrimaryFileSystem(absPath.str());
  598. if (mirrorPath.length())
  599. {
  600. absPath.clear();
  601. makeAbsolutePath(mirrorPath.str(), absPath);
  602. setPerformanceMonitorSecondaryFileSystem(absPath.str());
  603. }
  604. try
  605. {
  606. ForEachItemIn(i1,servers)
  607. {
  608. IDaliServer &server=servers.item(i1);
  609. server.start();
  610. }
  611. }
  612. catch (IException *e)
  613. {
  614. EXCLOG(e, "Failed whilst starting servers");
  615. stopServer();
  616. stopPerformanceMonitor();
  617. throw;
  618. }
  619. try {
  620. #ifndef _NO_LDAP
  621. setLDAPconnection(createDaliLdapConnection(serverConfig->getPropTree("Coven/ldapSecurity")));
  622. #endif
  623. }
  624. catch (IException *e) {
  625. EXCLOG(e, "LDAP initialization error");
  626. stopServer();
  627. stopPerformanceMonitor();
  628. throw;
  629. }
  630. PROGLOG("DASERVER[%d] starting - listening to port %d",myrank,queryMyNode()->endpoint().port);
  631. startMPServer(DCR_DaliServer, myport, false, true);
  632. bool ok = true;
  633. ForEachItemIn(i2,servers)
  634. {
  635. IDaliServer &server=servers.item(i2);
  636. try {
  637. server.ready();
  638. }
  639. catch (IException *e) {
  640. EXCLOG(e,"Exception starting Dali Server");
  641. ok = false;
  642. }
  643. }
  644. if (ok) {
  645. #ifndef _CONTAINERIZED
  646. writeSentinelFile(sentinelFile);
  647. #endif
  648. covenMain();
  649. removeAbortHandler(actionOnAbort);
  650. }
  651. stopLogMsgListener();
  652. stopServer();
  653. stopPerformanceMonitor();
  654. }
  655. catch (IException *e) {
  656. EXCLOG(e, "Exception");
  657. }
  658. UseSysLogForOperatorMessages(false);
  659. return 0;
  660. }