dafilesrv.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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 "platform.h"
  14. #include "portlist.h"
  15. #include "build-config.h"
  16. #include "jlib.hpp"
  17. #include "jiface.hpp"
  18. #include "jutil.hpp"
  19. #include "jfile.hpp"
  20. #include "jlog.hpp"
  21. #include "jmisc.hpp"
  22. #include "dalienv.hpp"
  23. #include "dafdesc.hpp"
  24. #ifdef _MSC_VER
  25. #pragma warning (disable : 4355)
  26. #endif
  27. static const bool defaultRowServiceOnStdPort = true;
  28. static const bool defaultDedicatedRowServiceSSL = false;
  29. static const char* defaultRowSericeConfiguration = "RowSvc";
  30. #include "remoteerr.hpp"
  31. #include "dafscommon.hpp"
  32. #include "rmtclient.hpp"
  33. #include "dafsserver.hpp"
  34. void usage()
  35. {
  36. printf("dafilesrv usage:\n");
  37. printf(" dafilesrv [-T<n>] [...] [<port>] [<send-buff-size-kb> <recv-buff-size-kb>]\n");
  38. printf(" -- run test local\n");
  39. printf(" dafilesrv -D [ -L <log-dir> ] [ -LOCAL ] -- run as linux daemon\n");
  40. printf(" dafilesrv -R -- run remote (linux daemon, windows standalone)\n");
  41. printf(" dafilesrv -install -- install windows service\n");
  42. printf(" dafilesrv -remove -- remove windows service\n\n");
  43. printf(" add -I <instance name> to specify an instance name\n");
  44. printf(" add -NOSSL to disable SSL sockets, even when specified in configuration\n\n");
  45. printf(" additional optional args:\n");
  46. printf(" [-p <port>] [-sslp <ssl-port>] [-sbsize <send-buff-size-kb>] [-rbsize <recv-buff-size-kb>]\n");
  47. printf(" [-addr <ip>:<port>]\n\n");
  48. printf(" Standard port is %d\n",DAFILESRV_PORT);
  49. printf(" Standard SSL port is %d (certificate and key required in environment.conf)\n",SECURE_DAFILESRV_PORT);
  50. printf(" Version: %s\n\n",remoteServerVersionString());
  51. }
  52. static Owned<IRemoteFileServer> server;
  53. #ifdef _WIN32
  54. // Service code
  55. #define DAFS_SERVICE_NAME "DaFileSrv"
  56. #define DAFS_SERVICE_DISPLAY_NAME "Dali File Server"
  57. void LogError( const char *s,DWORD dwError )
  58. {
  59. LPTSTR lpBuffer = NULL;
  60. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
  61. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  62. (LPTSTR) &lpBuffer, 0, NULL );
  63. OERRLOG( "%s(%d): %s", s, dwError, lpBuffer );
  64. LocalFree( lpBuffer );
  65. }
  66. // Service initialization
  67. static class CService *THIS; // singleton instance
  68. class CService
  69. {
  70. SERVICE_STATUS ServiceStatus;
  71. SERVICE_STATUS_HANDLE hStatus;
  72. // Control handler function
  73. void doControlHandler(DWORD request)
  74. {
  75. switch(request) {
  76. case SERVICE_CONTROL_STOP:
  77. PROGLOG(DAFS_SERVICE_NAME " Control: stopped");
  78. ServiceStatus.dwWin32ExitCode = 0;
  79. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  80. break;
  81. case SERVICE_CONTROL_SHUTDOWN:
  82. PROGLOG(DAFS_SERVICE_NAME "Control: shutdown");
  83. ServiceStatus.dwWin32ExitCode = 0;
  84. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  85. break;
  86. case SERVICE_CONTROL_INTERROGATE:
  87. break;
  88. default:
  89. PROGLOG(DAFS_SERVICE_NAME " Control: %d",request);
  90. break;
  91. }
  92. // Report current status
  93. SetServiceStatus (hStatus, &ServiceStatus);
  94. return;
  95. }
  96. void doServiceMain(int argc, char** argv)
  97. {
  98. ServiceStatus.dwServiceType = SERVICE_WIN32;
  99. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  100. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  101. ServiceStatus.dwWin32ExitCode = 0;
  102. ServiceStatus.dwServiceSpecificExitCode = 0;
  103. ServiceStatus.dwCheckPoint = 0;
  104. ServiceStatus.dwWaitHint = 0;
  105. hStatus = RegisterServiceCtrlHandler(DAFS_SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);
  106. if (hStatus == (SERVICE_STATUS_HANDLE)0) {
  107. // Registering Control Handler failed
  108. LogError("RegisterServiceCtrlHandler",GetLastError());
  109. return;
  110. }
  111. // Initialize Service
  112. if (!init()) {
  113. // Initialization failed
  114. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  115. ServiceStatus.dwWin32ExitCode = -1;
  116. SetServiceStatus(hStatus, &ServiceStatus);
  117. return;
  118. }
  119. // We report the running status to SCM.
  120. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  121. SetServiceStatus (hStatus, &ServiceStatus);
  122. // The worker loop of a service
  123. run();
  124. return;
  125. }
  126. public:
  127. CService()
  128. {
  129. THIS = this;
  130. }
  131. void start()
  132. {
  133. SERVICE_TABLE_ENTRY ServiceTable[2];
  134. ServiceTable[0].lpServiceName = DAFS_SERVICE_NAME;
  135. ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
  136. ServiceTable[1].lpServiceName = NULL;
  137. ServiceTable[1].lpServiceProc = NULL;
  138. // Start the control dispatcher thread for our service
  139. if (!StartServiceCtrlDispatcher(ServiceTable)) {
  140. LogError("StartServiceCtrlDispatcher",GetLastError());
  141. }
  142. }
  143. void stop()
  144. {
  145. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  146. ServiceStatus.dwCheckPoint = 0;
  147. ServiceStatus.dwWaitHint = 0;
  148. ServiceStatus.dwWin32ExitCode = 0;
  149. ServiceStatus.dwServiceSpecificExitCode = 0;
  150. SetServiceStatus(hStatus, &ServiceStatus);
  151. }
  152. // Control handler function
  153. static void ControlHandler(DWORD request)
  154. {
  155. THIS->doControlHandler(request) ;
  156. }
  157. static void ServiceMain(int argc, char** argv)
  158. {
  159. THIS->doServiceMain(argc, argv);
  160. }
  161. bool running() { return ServiceStatus.dwCurrentState == SERVICE_RUNNING; }
  162. virtual bool init() = 0;
  163. virtual void run() = 0;
  164. };
  165. bool installService(const char *servicename,const char *servicedisplayname,const char *dependancies)
  166. {
  167. DWORD err = ERROR_SUCCESS;
  168. char path[512];
  169. if (GetModuleFileName( NULL, path, sizeof(path) )) {
  170. SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); // full access rights
  171. if (hSCM) {
  172. SC_HANDLE hService = CreateService(
  173. hSCM, // SCManager database
  174. servicename, // name of service
  175. servicedisplayname, // name to display
  176. SERVICE_ALL_ACCESS, // desired access
  177. SERVICE_WIN32_OWN_PROCESS,//|SERVICE_INTERACTIVE_PROCESS , // service type
  178. SERVICE_AUTO_START, // start type
  179. SERVICE_ERROR_NORMAL, // error control type
  180. path, // service's binary
  181. NULL, // no load ordering group
  182. NULL, // no tag identifier
  183. dependancies, // dependencies
  184. NULL, // LocalSystem account
  185. NULL); // no password
  186. if (hService) {
  187. Sleep(1000);
  188. StartService(hService,0,0);
  189. CloseServiceHandle(hService);
  190. }
  191. else
  192. err = GetLastError();
  193. }
  194. else
  195. err = GetLastError();
  196. CloseServiceHandle(hSCM);
  197. }
  198. else
  199. err = GetLastError();
  200. if (err!=ERROR_SUCCESS) {
  201. LogError("Install failed",err);
  202. return false;
  203. }
  204. return true;
  205. }
  206. bool uninstallService(const char *servicename,const char *servicedisplayname)
  207. {
  208. DWORD err = ERROR_SUCCESS;
  209. SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); // full access rights
  210. if (hSCM) {
  211. SC_HANDLE hService = OpenService(hSCM, servicename, SERVICE_STOP|SERVICE_QUERY_STATUS);
  212. if (hService) {
  213. // try to stop the service
  214. SERVICE_STATUS ss;
  215. if ( ControlService( hService, SERVICE_CONTROL_STOP, &ss ) ) {
  216. PROGLOG("Stopping %s", servicedisplayname);
  217. Sleep( 1000 );
  218. while( QueryServiceStatus( hService, &ss ) ) {
  219. if ( ss.dwCurrentState != SERVICE_STOP_PENDING )
  220. break;
  221. Sleep( 1000 );
  222. }
  223. if ( ss.dwCurrentState == SERVICE_STOPPED )
  224. PROGLOG("%s Service stopped",servicedisplayname);
  225. else
  226. OERRLOG("%s failed to stop",servicedisplayname);
  227. }
  228. CloseServiceHandle(hService);
  229. }
  230. hService = OpenService(hSCM, servicename, DELETE);
  231. if (hService) {
  232. // now remove the service
  233. if (!DeleteService(hService))
  234. err = GetLastError();
  235. CloseServiceHandle(hService);
  236. }
  237. else
  238. err = GetLastError();
  239. CloseServiceHandle(hSCM);
  240. }
  241. else
  242. err = GetLastError();
  243. if (err!=ERROR_SUCCESS) {
  244. LogError("Uninstall failed",err);
  245. return false;
  246. }
  247. return true;
  248. }
  249. #else
  250. void sighandler(int signum, siginfo_t *info, void *extra)
  251. {
  252. PROGLOG("Caught signal %d, %p", signum, info?info->si_addr:0);
  253. if (server)
  254. server->stop();
  255. }
  256. int initDaemon()
  257. {
  258. int ret = daemon(1,0);
  259. if (ret)
  260. return ret;
  261. struct sigaction act;
  262. sigset_t blockset;
  263. sigemptyset(&blockset);
  264. act.sa_mask = blockset;
  265. act.sa_handler = SIG_IGN;
  266. act.sa_flags = 0;
  267. sigaction(SIGHUP, &act, NULL);
  268. act.sa_flags = SA_SIGINFO;
  269. act.sa_sigaction = &sighandler;
  270. sigaction(SIGTERM, &act, NULL);
  271. sigaction(SIGINT, &act, NULL);
  272. return 0;
  273. }
  274. #endif
  275. int main(int argc,char **argv)
  276. {
  277. InitModuleObjects();
  278. EnableSEHtoExceptionMapping();
  279. #ifndef __64BIT__
  280. // Restrict stack sizes on 32-bit systems
  281. Thread::setDefaultStackSize(0x10000); // 64K stack (also set in windows DSP)
  282. #endif
  283. Owned<IFile> sentinelFile = createSentinelTarget();
  284. removeSentinelFile(sentinelFile);
  285. SocketEndpoint listenep;
  286. unsigned sendbufsize = 0;
  287. unsigned recvbufsize = 0;
  288. int i = 1;
  289. bool isdaemon = (memicmp(argv[0]+strlen(argv[0])-4,".exe",4)==0);
  290. // bit of a kludge for windows - if .exe not specified then not daemon
  291. bool locallisten = false;
  292. const char *logdir=NULL;
  293. StringBuffer logDir;
  294. StringBuffer componentName;
  295. // Get SSL Settings
  296. DAFSConnectCfg connectMethod;
  297. unsigned short port;
  298. unsigned short sslport;
  299. const char * sslCertFile;
  300. const char * sslKeyFile;
  301. queryDafsSecSettings(&connectMethod, &port, &sslport, &sslCertFile, &sslKeyFile, nullptr);
  302. unsigned maxThreads = DEFAULT_THREADLIMIT;
  303. unsigned maxThreadsDelayMs = DEFAULT_THREADLIMITDELAYMS;
  304. unsigned maxAsyncCopy = DEFAULT_ASYNCCOPYMAX;
  305. unsigned parallelRequestLimit = DEFAULT_STDCMD_PARALLELREQUESTLIMIT;
  306. unsigned throttleDelayMs = DEFAULT_STDCMD_THROTTLEDELAYMS;
  307. unsigned throttleCPULimit = DEFAULT_STDCMD_THROTTLECPULIMIT;
  308. unsigned throttleQueueLimit = DEFAULT_STDCMD_THROTTLEQUEUELIMIT;
  309. unsigned parallelSlowRequestLimit = DEFAULT_SLOWCMD_PARALLELREQUESTLIMIT;
  310. unsigned throttleSlowDelayMs = DEFAULT_SLOWCMD_THROTTLEDELAYMS;
  311. unsigned throttleSlowCPULimit = DEFAULT_SLOWCMD_THROTTLECPULIMIT;
  312. unsigned throttleSlowQueueLimit = DEFAULT_SLOWCMD_THROTTLEQUEUELIMIT;
  313. unsigned dedicatedRowServicePort = DEFAULT_ROWSERVICE_PORT;
  314. StringAttr rowServiceConfiguration = defaultRowSericeConfiguration;
  315. bool dedicatedRowServiceSSL = defaultDedicatedRowServiceSSL;
  316. bool rowServiceOnStdPort = defaultRowServiceOnStdPort;
  317. // these should really be in env, but currently they are not ...
  318. listenep.port = port;
  319. // get command line arguements, including dafilesrv name
  320. while (argc>i) {
  321. if (stricmp(argv[i],"-D")==0) {
  322. i++;
  323. isdaemon = true;
  324. }
  325. else if (stricmp(argv[i],"-R")==0) { // for remote run
  326. i++;
  327. #ifdef _WIN32
  328. isdaemon = false;
  329. #else
  330. isdaemon = true;
  331. #endif
  332. }
  333. else if ((argv[i][0]=='-')&&(toupper(argv[i][1])=='T')&&(!argv[i][2]||isdigit(argv[i][2]))) {
  334. if (argv[i][2])
  335. setDaliServerTrace((byte)atoi(argv[i]+2));
  336. i++;
  337. isdaemon = false;
  338. }
  339. else if ((argc>i+1)&&(stricmp(argv[i],"-L")==0)) {
  340. i++;
  341. logDir.clear().append(argv[i++]);
  342. }
  343. else if ((argc>i+1)&&(stricmp(argv[i],"-I")==0)) {
  344. i++;
  345. componentName.clear().append(argv[i++]);
  346. }
  347. else if ((argc>i+1)&&(stricmp(argv[i],"-p")==0)) {
  348. i++;
  349. listenep.port = atoi(argv[i++]);
  350. }
  351. else if ((argc>i+1)&&(stricmp(argv[i],"-addr")==0)) {
  352. i++;
  353. if (strchr(argv[i],'.')||!isdigit(argv[i][0]))
  354. listenep.set(argv[i], listenep.port);
  355. else
  356. listenep.port = atoi(argv[i]);
  357. i++;
  358. }
  359. else if ((argc>i+1)&&(stricmp(argv[i],"-sslp")==0)) {
  360. i++;
  361. sslport = atoi(argv[i++]);
  362. }
  363. else if ((argc>i+1)&&(stricmp(argv[i],"-sbsize")==0)) {
  364. i++;
  365. sendbufsize = atoi(argv[i++]);
  366. }
  367. else if ((argc>i+1)&&(stricmp(argv[i],"-rbsize")==0)) {
  368. i++;
  369. recvbufsize = atoi(argv[i++]);
  370. }
  371. else if (stricmp(argv[i],"-h")==0) {
  372. usage();
  373. exit(0);
  374. }
  375. else if (stricmp(argv[i],"-LOCAL")==0) {
  376. i++;
  377. locallisten = true;
  378. }
  379. else if (stricmp(argv[i],"-NOSSL")==0) { // overrides config setting
  380. i++;
  381. if (connectMethod == SSLOnly || connectMethod == SSLFirst || connectMethod == UnsecureFirst)
  382. {
  383. PROGLOG("DaFileSrv SSL specified in config but overridden by -NOSSL in command line");
  384. connectMethod = SSLNone;
  385. }
  386. }
  387. else
  388. break;
  389. }
  390. #ifdef _WIN32
  391. if ((argc>i)&&(stricmp(argv[i],"-install")==0)) {
  392. if (installService(DAFS_SERVICE_NAME,DAFS_SERVICE_DISPLAY_NAME,NULL)) {
  393. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Installed");
  394. return 0;
  395. }
  396. return 1;
  397. }
  398. if ((argc>i)&&(stricmp(argv[i],"-remove")==0)) {
  399. if (uninstallService(DAFS_SERVICE_NAME,DAFS_SERVICE_DISPLAY_NAME)) {
  400. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Uninstalled");
  401. return 0;
  402. }
  403. return 1;
  404. }
  405. #endif
  406. if (argc > i) {
  407. if (strchr(argv[i],'.')||!isdigit(argv[i][0]))
  408. listenep.set(argv[i], listenep.port);
  409. else
  410. listenep.port = atoi(argv[i]);
  411. sendbufsize = (argc>i+1)?(atoi(argv[i+1])*1024):0;
  412. recvbufsize = (argc>i+2)?(atoi(argv[i+2])*1024):0;
  413. }
  414. Owned<IPropertyTree> env = getHPCCEnvironment();
  415. IPropertyTree *keyPairInfo = nullptr;
  416. if (env)
  417. {
  418. StringBuffer dafilesrvPath("Software/DafilesrvProcess");
  419. if (componentName.length())
  420. dafilesrvPath.appendf("[@name=\"%s\"]", componentName.str());
  421. else
  422. dafilesrvPath.append("[1]"); // in absence of name, use 1st
  423. IPropertyTree *daFileSrv = env->queryPropTree(dafilesrvPath);
  424. Owned<IPropertyTree> _dafileSrv;
  425. if (daFileSrv)
  426. {
  427. const char *componentGroupName = daFileSrv->queryProp("@group");
  428. if (!isEmptyString(componentGroupName))
  429. {
  430. VStringBuffer dafilesrvGroupPath("Software/DafilesrvGroup[@name=\"%s\"]", componentGroupName);
  431. IPropertyTree *daFileSrvGroup = env->queryPropTree(dafilesrvGroupPath);
  432. if (daFileSrvGroup)
  433. {
  434. // create a copy of the group settings and merge in (overwrite) with the component settings, i.e. any group settings become defaults
  435. _dafileSrv.setown(createPTreeFromIPT(daFileSrvGroup));
  436. synchronizePTree(_dafileSrv, daFileSrv, false, false);
  437. daFileSrv = _dafileSrv;
  438. }
  439. }
  440. // Component level DaFileSrv settings:
  441. maxThreads = daFileSrv->getPropInt("@maxThreads", DEFAULT_THREADLIMIT);
  442. maxThreadsDelayMs = daFileSrv->getPropInt("@maxThreadsDelayMs", DEFAULT_THREADLIMITDELAYMS);
  443. maxAsyncCopy = daFileSrv->getPropInt("@maxAsyncCopy", DEFAULT_ASYNCCOPYMAX);
  444. parallelRequestLimit = daFileSrv->getPropInt("@parallelRequestLimit", DEFAULT_STDCMD_PARALLELREQUESTLIMIT);
  445. throttleDelayMs = daFileSrv->getPropInt("@throttleDelayMs", DEFAULT_STDCMD_THROTTLEDELAYMS);
  446. throttleCPULimit = daFileSrv->getPropInt("@throttleCPULimit", DEFAULT_STDCMD_THROTTLECPULIMIT);
  447. throttleQueueLimit = daFileSrv->getPropInt("@throttleQueueLimit", DEFAULT_STDCMD_THROTTLEQUEUELIMIT);
  448. parallelSlowRequestLimit = daFileSrv->getPropInt("@parallelSlowRequestLimit", DEFAULT_SLOWCMD_PARALLELREQUESTLIMIT);
  449. throttleSlowDelayMs = daFileSrv->getPropInt("@throttleSlowDelayMs", DEFAULT_SLOWCMD_THROTTLEDELAYMS);
  450. throttleSlowCPULimit = daFileSrv->getPropInt("@throttleSlowCPULimit", DEFAULT_SLOWCMD_THROTTLECPULIMIT);
  451. throttleSlowQueueLimit = daFileSrv->getPropInt("@throttleSlowQueueLimit", DEFAULT_SLOWCMD_THROTTLEQUEUELIMIT);
  452. dedicatedRowServicePort = daFileSrv->getPropInt("@rowServicePort", DEFAULT_ROWSERVICE_PORT);
  453. dedicatedRowServiceSSL = daFileSrv->getPropBool("@rowServiceSSL", defaultDedicatedRowServiceSSL);
  454. rowServiceOnStdPort = daFileSrv->getPropBool("@rowServiceOnStdPort", defaultRowServiceOnStdPort);
  455. if (daFileSrv->queryProp("@rowServiceConfiguration"))
  456. rowServiceConfiguration = daFileSrv->queryProp("@rowServiceConfiguration");
  457. // any overrides by Instance definitions?
  458. IPropertyTree *dafileSrvInstance = nullptr;
  459. Owned<IPropertyTreeIterator> iter = daFileSrv->getElements("Instance");
  460. ForEach(*iter)
  461. {
  462. IpAddress instanceIP(iter->query().queryProp("@netAddress"));
  463. if (instanceIP.ipequals(queryHostIP()))
  464. dafileSrvInstance = &iter->query();
  465. }
  466. if (dafileSrvInstance)
  467. {
  468. Owned<IPropertyTree> _dafileSrvInstance;
  469. // check if there's a DaFileSrvGroup
  470. const char *instanceGroupName = dafileSrvInstance->queryProp("@group");
  471. if (!isEmptyString(instanceGroupName) && (isEmptyString(componentGroupName) || !strsame(instanceGroupName, componentGroupName))) // i.e. only if different
  472. {
  473. VStringBuffer dafilesrvGroupPath("Software/DafilesrvGroup[@name=\"%s\"]", instanceGroupName);
  474. IPropertyTree *daFileSrvGroup = env->queryPropTree(dafilesrvGroupPath);
  475. if (daFileSrvGroup)
  476. {
  477. // create a copy of the group settings and merge in (overwrite) with the instance settings, i.e. any group settings become defaults
  478. _dafileSrvInstance.setown(createPTreeFromIPT(daFileSrvGroup));
  479. synchronizePTree(_dafileSrvInstance, dafileSrvInstance, false, false);
  480. dafileSrvInstance = _dafileSrvInstance;
  481. }
  482. }
  483. maxThreads = dafileSrvInstance->getPropInt("@maxThreads", maxThreads);
  484. maxThreadsDelayMs = dafileSrvInstance->getPropInt("@maxThreadsDelayMs", maxThreadsDelayMs);
  485. maxAsyncCopy = dafileSrvInstance->getPropInt("@maxAsyncCopy", maxAsyncCopy);
  486. parallelRequestLimit = dafileSrvInstance->getPropInt("@parallelRequestLimit", parallelRequestLimit);
  487. throttleDelayMs = dafileSrvInstance->getPropInt("@throttleDelayMs", throttleDelayMs);
  488. throttleCPULimit = dafileSrvInstance->getPropInt("@throttleCPULimit", throttleCPULimit);
  489. throttleQueueLimit = dafileSrvInstance->getPropInt("@throttleQueueLimit", throttleQueueLimit);
  490. parallelSlowRequestLimit = dafileSrvInstance->getPropInt("@parallelSlowRequestLimit", parallelSlowRequestLimit);
  491. throttleSlowDelayMs = dafileSrvInstance->getPropInt("@throttleSlowDelayMs", throttleSlowDelayMs);
  492. throttleSlowCPULimit = dafileSrvInstance->getPropInt("@throttleSlowCPULimit", throttleSlowCPULimit);
  493. throttleSlowQueueLimit = dafileSrvInstance->getPropInt("@throttleSlowQueueLimit", throttleSlowQueueLimit);
  494. dedicatedRowServicePort = dafileSrvInstance->getPropInt("@rowServicePort", dedicatedRowServicePort);
  495. dedicatedRowServiceSSL = dafileSrvInstance->getPropBool("@rowServiceSSL", dedicatedRowServiceSSL);
  496. rowServiceOnStdPort = dafileSrvInstance->getPropBool("@rowServiceOnStdPort", rowServiceOnStdPort);
  497. }
  498. }
  499. keyPairInfo = env->queryPropTree("EnvSettings/Keys");
  500. }
  501. #ifndef _USE_OPENSSL
  502. if (dedicatedRowServicePort)
  503. {
  504. dedicatedRowServiceSSL = false;
  505. }
  506. #endif
  507. if (0 == logDir.length())
  508. {
  509. getConfigurationDirectory(NULL,"log","dafilesrv",componentName.str(),logDir);
  510. if (0 == logDir.length())
  511. logDir.append(".");
  512. }
  513. if (componentName.length())
  514. {
  515. addPathSepChar(logDir);
  516. logDir.append(componentName.str());
  517. }
  518. if ( (connectMethod == SSLNone) && (listenep.port == 0) )
  519. {
  520. printf("\nError, port must not be 0\n");
  521. usage();
  522. exit(-1);
  523. }
  524. else if ( (connectMethod == SSLOnly) && (sslport == 0) )
  525. {
  526. printf("\nError, secure port must not be 0\n");
  527. usage();
  528. exit(-1);
  529. }
  530. else if ( ((connectMethod == SSLFirst) || (connectMethod == UnsecureFirst)) && ((listenep.port == 0) || (sslport == 0)) )
  531. {
  532. printf("\nError, both port and secure port must not be 0\n");
  533. usage();
  534. exit(-1);
  535. }
  536. StringBuffer secMethod;
  537. if (connectMethod == SSLNone)
  538. secMethod.append("SSLNone");
  539. else if (connectMethod == SSLOnly)
  540. secMethod.append("SSLOnly");
  541. else if (connectMethod == SSLFirst)
  542. secMethod.append("SSLFirst");
  543. else if (connectMethod == UnsecureFirst)
  544. secMethod.append("UnsecureFirst");
  545. if (isdaemon) {
  546. #ifdef _WIN32
  547. class cserv: public CService
  548. {
  549. bool stopped;
  550. bool started;
  551. DAFSConnectCfg connectMethod;
  552. SocketEndpoint listenep;
  553. unsigned maxThreads;
  554. unsigned maxThreadsDelayMs;
  555. unsigned maxAsyncCopy;
  556. unsigned parallelRequestLimit;
  557. unsigned throttleDelayMs;
  558. unsigned throttleCPULimit;
  559. unsigned parallelSlowRequestLimit;
  560. unsigned throttleSlowDelayMs;
  561. unsigned throttleSlowCPULimit;
  562. unsigned sslport;
  563. StringBuffer secMethod;
  564. Linked<IPropertyTree> keyPairInfo;
  565. StringAttr rowServiceConfiguration;
  566. unsigned dedicatedRowServicePort;
  567. bool dedicatedRowServiceSSL;
  568. bool rowServiceOnStdPort;
  569. class cpollthread: public Thread
  570. {
  571. cserv *parent;
  572. public:
  573. cpollthread( cserv *_parent )
  574. : Thread("CService::cpollthread"), parent(_parent)
  575. {
  576. }
  577. int run()
  578. {
  579. while (parent->poll())
  580. Sleep(1000);
  581. return 1;
  582. }
  583. } pollthread;
  584. Owned<IRemoteFileServer> server;
  585. public:
  586. cserv(DAFSConnectCfg _connectMethod, SocketEndpoint _listenep,
  587. unsigned _maxThreads, unsigned _maxThreadsDelayMs, unsigned _maxAsyncCopy,
  588. unsigned _parallelRequestLimit, unsigned _throttleDelayMs, unsigned _throttleCPULimit,
  589. unsigned _parallelSlowRequestLimit, unsigned _throttleSlowDelayMs, unsigned _throttleSlowCPULimit,
  590. unsigned _sslport, const char * _secMethod,
  591. IPropertyTree *_keyPairInfo,
  592. const char *_rowServiceConfiguration,
  593. unsigned _dedicatedRowServicePort, bool _dedicatedRowServiceSSL, bool _rowServiceOnStdPort)
  594. : connectMethod(_connectMethod), listenep(_listenep), pollthread(this),
  595. maxThreads(_maxThreads), maxThreadsDelayMs(_maxThreadsDelayMs), maxAsyncCopy(_maxAsyncCopy),
  596. parallelRequestLimit(_parallelRequestLimit), throttleDelayMs(_throttleDelayMs), throttleCPULimit(_throttleCPULimit),
  597. parallelSlowRequestLimit(_parallelSlowRequestLimit), throttleSlowDelayMs(_throttleSlowDelayMs), throttleSlowCPULimit(_throttleSlowCPULimit),
  598. sslport(_sslport), secMethod(_secMethod),
  599. keyPairInfo(_keyPairInfo),
  600. rowServiceConfiguration(_rowServiceConfiguration), dedicatedRowServicePort(_dedicatedRowServicePort), dedicatedRowServiceSSL(_dedicatedRowServiceSSL), rowServiceOnStdPort(_rowServiceOnStdPort)
  601. {
  602. stopped = false;
  603. started = false;
  604. }
  605. virtual ~cserv()
  606. {
  607. stopped = true;
  608. if (started)
  609. pollthread.join();
  610. }
  611. bool init()
  612. {
  613. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Initialized");
  614. started = true;
  615. pollthread.start();
  616. return true;
  617. }
  618. bool poll()
  619. {
  620. if (stopped||!running()) {
  621. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Stopping");
  622. if (server) {
  623. server->stop();
  624. server.clear();
  625. }
  626. return false;
  627. }
  628. return true;
  629. }
  630. void run()
  631. {
  632. // Get params from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DaFileSrv\Parameters
  633. StringBuffer eps;
  634. if (listenep.isNull())
  635. eps.append(listenep.port);
  636. else
  637. listenep.getUrlStr(eps);
  638. if (connectMethod != SSLOnly)
  639. PROGLOG("Opening " DAFS_SERVICE_DISPLAY_NAME " on %s", eps.str());
  640. if (connectMethod == SSLOnly || connectMethod == SSLFirst || connectMethod == UnsecureFirst)
  641. {
  642. SocketEndpoint sslep(listenep);
  643. sslep.port = sslport;
  644. eps.kill();
  645. if (sslep.isNull())
  646. eps.append(sslep.port);
  647. else
  648. sslep.getUrlStr(eps);
  649. PROGLOG("Opening " DAFS_SERVICE_DISPLAY_NAME " on SECURE %s", eps.str());
  650. }
  651. PROGLOG("Dali File Server socket security model: %s", secMethod.str());
  652. const char * verstring = remoteServerVersionString();
  653. PROGLOG("Version: %s", verstring);
  654. if (dedicatedRowServicePort)
  655. PROGLOG("Row service(%s) port = %u", rowServiceConfiguration, dedicatedRowServicePort);
  656. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Running");
  657. server.setown(createRemoteFileServer(maxThreads, maxThreadsDelayMs, maxAsyncCopy, keyPairInfo));
  658. server->setThrottle(ThrottleStd, parallelRequestLimit, throttleDelayMs, throttleCPULimit);
  659. server->setThrottle(ThrottleSlow, parallelSlowRequestLimit, throttleSlowDelayMs, throttleSlowCPULimit);
  660. try
  661. {
  662. if (dedicatedRowServicePort)
  663. {
  664. SocketEndpoint rowServiceEp(listenep); // copy listenep, incase bound by -addr
  665. rowServiceEp.port = dedicatedRowServicePort;
  666. server->run(connectMethod, listenep, sslport, &rowServiceEp, dedicatedRowServiceSSL, rowServiceOnStdPort);
  667. }
  668. else
  669. server->run(connectMethod, listenep, sslport);
  670. }
  671. catch (IException *e) {
  672. EXCLOG(e,DAFS_SERVICE_NAME);
  673. e->Release();
  674. }
  675. PROGLOG(DAFS_SERVICE_DISPLAY_NAME " Stopped");
  676. stopped = true;
  677. }
  678. } service(connectMethod, listenep,
  679. maxThreads, maxThreadsDelayMs, maxAsyncCopy,
  680. parallelRequestLimit, throttleDelayMs, throttleCPULimit,
  681. parallelSlowRequestLimit, throttleSlowDelayMs, throttleSlowCPULimit, sslport, secMethod,
  682. keyPairInfo, rowServiceConfiguration, dedicatedRowServicePort, dedicatedRowServiceSSL, rowServiceOnStdPort);
  683. service.start();
  684. return 0;
  685. #else
  686. int ret = initDaemon();
  687. if (ret)
  688. return ret;
  689. #endif
  690. }
  691. #ifndef _CONTAINERIZED
  692. {
  693. Owned<IComponentLogFileCreator> lf = createComponentLogFileCreator(logDir.str(), "DAFILESRV");
  694. lf->setCreateAliasFile(false);
  695. lf->setMaxDetail(TopDetail);
  696. lf->beginLogging();
  697. }
  698. #else
  699. setupContainerizedLogMsgHandler();
  700. #endif
  701. write_pidfile(componentName.str());
  702. PROGLOG("Dafilesrv starting - Build %s", BUILD_TAG);
  703. PROGLOG("Parallel request limit = %d, throttleDelayMs = %d, throttleCPULimit = %d", parallelRequestLimit, throttleDelayMs, throttleCPULimit);
  704. const char * verstring = remoteServerVersionString();
  705. StringBuffer eps;
  706. if (listenep.isNull())
  707. eps.append(listenep.port);
  708. else
  709. listenep.getUrlStr(eps);
  710. if (connectMethod != SSLOnly)
  711. PROGLOG("Opening Dali File Server on %s", eps.str());
  712. if (connectMethod == SSLOnly || connectMethod == SSLFirst || connectMethod == UnsecureFirst)
  713. {
  714. SocketEndpoint sslep(listenep);
  715. sslep.port = sslport;
  716. eps.kill();
  717. if (sslep.isNull())
  718. eps.append(sslep.port);
  719. else
  720. sslep.getUrlStr(eps);
  721. PROGLOG("Opening Dali File Server on SECURE %s", eps.str());
  722. }
  723. PROGLOG("Dali File Server socket security model: %s", secMethod.str());
  724. PROGLOG("Version: %s", verstring);
  725. if (dedicatedRowServicePort)
  726. PROGLOG("Row service port = %u%s", dedicatedRowServicePort, dedicatedRowServiceSSL ? " SECURE" : "");
  727. server.setown(createRemoteFileServer(maxThreads, maxThreadsDelayMs, maxAsyncCopy, keyPairInfo));
  728. server->setThrottle(ThrottleStd, parallelRequestLimit, throttleDelayMs, throttleCPULimit);
  729. server->setThrottle(ThrottleSlow, parallelSlowRequestLimit, throttleSlowDelayMs, throttleSlowCPULimit);
  730. class CPerfHook : public CSimpleInterfaceOf<IPerfMonHook>
  731. {
  732. public:
  733. virtual void processPerfStats(unsigned processorUsage, unsigned memoryUsage, unsigned memoryTotal, unsigned __int64 fistDiskUsage, unsigned __int64 firstDiskTotal, unsigned __int64 secondDiskUsage, unsigned __int64 secondDiskTotal, unsigned threadCount)
  734. {
  735. }
  736. virtual StringBuffer &extraLogging(StringBuffer &extra)
  737. {
  738. return server->getStats(extra.newline(), true);
  739. }
  740. virtual void log(int level, const char *msg)
  741. {
  742. PROGLOG("%s", msg);
  743. }
  744. } perfHook;
  745. startPerformanceMonitor(10*60*1000, PerfMonStandard, &perfHook);
  746. writeSentinelFile(sentinelFile);
  747. try
  748. {
  749. if (dedicatedRowServicePort)
  750. {
  751. SocketEndpoint rowServiceEp(listenep); // copy listenep, incase bound by -addr
  752. rowServiceEp.port = dedicatedRowServicePort;
  753. server->run(connectMethod, listenep, sslport, &rowServiceEp, dedicatedRowServiceSSL, rowServiceOnStdPort);
  754. }
  755. else
  756. server->run(connectMethod, listenep, sslport);
  757. }
  758. catch (IException *e)
  759. {
  760. EXCLOG(e,"DAFILESRV");
  761. if (e->errorCode() == DAFSERR_serverinit_failed)
  762. removeSentinelFile(sentinelFile); // so init does not keep trying to start it ...
  763. e->Release();
  764. }
  765. stopPerformanceMonitor();
  766. if (server)
  767. server->stop();
  768. server.clear();
  769. PROGLOG("Stopped Dali File Server");
  770. return 0;
  771. }