Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1379 lines
54 KiB

  1. //
  2. // MODULE: STATUSPAGES.CPP
  3. //
  4. //
  5. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  6. //
  7. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  8. //
  9. // AUTHOR: Oleg Kalosha
  10. //
  11. // ORIGINAL DATE: 10-23-98
  12. //
  13. // NOTES:
  14. //
  15. // Version Date By Comments
  16. //--------------------------------------------------------------------
  17. // V3.0 10-23-98 OK Created by division of apgtsctx.cpp
  18. //
  19. #pragma warning(disable:4786)
  20. #include "stdafx.h"
  21. #include "time.h"
  22. #include "apgtscls.h"
  23. #include "apgtscfg.h"
  24. #include "CounterMgr.h"
  25. #include "SafeTime.h"
  26. #include "apgtsmfc.h"
  27. //Global Declaration.
  28. const CString k_strTableBorderColor = _T("\"#000000\"");
  29. const CString k_strBGColorOfTitle = _T( "\"#333366\"");
  30. const CString k_strTextColorOfTitleOrSubTitle = _T("\"#FFFFFF\"");
  31. const CString k_strTextColorOfName = _T("\"#CCCCC99\"");
  32. const CString k_strTextColorOfValue = _T("\"#FFFFCC\"");
  33. const CString k_strBGColorOfSubTitle = _T("\"#3333CC\"");
  34. void AppendNameAndValueAsRow(CString &strAppend, CString strText, CString strVal)
  35. {
  36. strAppend += _T("<TR>\n");
  37. if(strText != _T(""))
  38. {
  39. strAppend += _T("<TD BGCOLOR=");
  40. strAppend += k_strTextColorOfName;
  41. strAppend += _T(">");
  42. strAppend += _T("<B>");
  43. strAppend += strText;
  44. strAppend += _T("</B>\n");
  45. strAppend += _T("</TD>\n");
  46. }
  47. strAppend += _T("<TD ALIGN=\"CENTER\" BGCOLOR=");
  48. strAppend += k_strTextColorOfValue;
  49. strAppend += _T(">");
  50. strAppend += strVal;
  51. strAppend += _T("</TD>\n");
  52. strAppend += _T("</TR>\n");
  53. }
  54. // If bSubTitle is TRUE, the subtitle inside the table will be displayed in a
  55. // lighter background to differentiate between the title(darker background)
  56. // and the subtitle.
  57. void DisplayTextAsTable(CString &strDisplay, CString strText, bool bSubTitle)
  58. {
  59. strDisplay += _T("<TABLE BORDER= \"1\" BORDERCOLOR=");
  60. strDisplay += k_strTableBorderColor;
  61. strDisplay += _T("CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  62. strDisplay += _T("<TR>\n");
  63. strDisplay += _T("<TD COLSPAN =2 ALIGN=\"CENTER\" BGCOLOR=");
  64. if(bSubTitle)
  65. strDisplay += k_strBGColorOfTitle;
  66. else
  67. strDisplay += k_strBGColorOfSubTitle;
  68. strDisplay += _T(">\n");
  69. strDisplay += _T("<FONT SIZE=\"+1\" COLOR=");
  70. strDisplay += k_strTextColorOfTitleOrSubTitle;
  71. strDisplay += _T("<B>\n");
  72. strDisplay += strText;
  73. strDisplay += _T("</B>\n");
  74. strDisplay += _T("</TD>\n");
  75. strDisplay += _T("</TR>\n");
  76. }
  77. void AppendTwoNamesAndValueAsRow(CString &strAppend, CString strText1, CString strText2, CString strVal)
  78. {
  79. strAppend += _T("<TR>\n");
  80. strAppend += _T("<TD ALIGN=\"LEFT\" BGCOLOR=");
  81. strAppend += k_strTextColorOfName;
  82. strAppend += _T(" >");
  83. strAppend += _T("<B>\n");
  84. strAppend += strText1;
  85. strAppend += _T("</B>\n");
  86. strAppend += _T("</TD>");
  87. strAppend += _T("<TD ALIGN=\"CENTER\" BGCOLOR=");
  88. strAppend += k_strTextColorOfValue;
  89. strAppend += _T(">\n");
  90. strAppend += strText2;
  91. strAppend += _T("</TD>\n");
  92. strAppend += _T("<TD ALIGN=\"CENTER\" BGCOLOR=");
  93. strAppend += k_strTextColorOfValue;
  94. strAppend += _T(">\n");
  95. strAppend += strVal;
  96. strAppend += _T("</TD>\n");
  97. strAppend += _T("</TR>\n");
  98. }
  99. // Returns true if we should show the full (rather than partial) first page.
  100. bool APGTSContext::ShowFullFirstPage(bool bHasPwd)
  101. {
  102. // You can compile with the NOPWD option to suppress all password checking.
  103. // This is intended mainly for creating test versions with this feature suppressed.
  104. #ifdef NOPWD
  105. return true;
  106. #else
  107. return bHasPwd;
  108. #endif // ifndef NOPWD
  109. }
  110. void APGTSContext::InsertPasswordInForm()
  111. {
  112. // You can compile with the NOPWD option to suppress all password checking.
  113. // This is intended mainly for creating test versions with this feature suppressed.
  114. #ifndef NOPWD
  115. m_strText += _T("<INPUT TYPE=hidden NAME=\"PWD\" VALUE=\"");
  116. m_strText += m_strTempPwd;
  117. m_strText += _T("\">\n");
  118. #endif // ifndef NOPWD
  119. }
  120. void APGTSContext::BeginSelfAddressingForm()
  121. {
  122. m_strText += _T("<FORM ACTION=\"");
  123. m_strText += _T("http://");
  124. m_strText += m_strLocalIPAddress;
  125. m_strText += m_strVRoot;
  126. m_strText += _T("\" METHOD=POST>\n");
  127. }
  128. // Append to m_strText: contents of an HTML page giving:
  129. // - usage statistics
  130. // - list of available troubleshooter topics
  131. // Not available to the end user.
  132. // INPUT bHasPwd - if this is false, limit the info shown on this page.
  133. void APGTSContext::DisplayFirstPage(bool bHasPwd)
  134. {
  135. CHourlyDailyCounter tmp_counter;
  136. DWORD dwRegistryItem =0;
  137. CString strRegistryItem;
  138. const CString strRegistryItemNotFound = _T("not found");
  139. CRegistryMonitor& registryMonitor = m_pConf->GetRegistryMonitor();
  140. CThreadPool& threadPool = m_pConf->GetThreadPool();
  141. CPoolQueue& poolQueue = m_pConf->GetPoolQueue();
  142. m_strText += _T("<html>\n");
  143. m_strText += _T("<B><head><title>Welcome</title></head>\n");
  144. m_strText += _T("<body bgcolor=");
  145. m_strText += k_strTextColorOfTitleOrSubTitle;
  146. m_strText += _T(">\n");
  147. m_strText += _T("<TABLE BORDER= \"1\" BORDERCOLOR=");
  148. m_strText += k_strTableBorderColor;
  149. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  150. m_strText += _T("<TR>\n");
  151. m_strText += _T("<TD COLSPAN=\"4\" ALIGN=CENTER BGCOLOR=");
  152. m_strText += k_strBGColorOfTitle;
  153. m_strText += _T(">\n");
  154. m_strText += _T("<FONT SIZE=\"+3\" COLOR=");
  155. m_strText += k_strTextColorOfTitleOrSubTitle;
  156. m_strText += _T(">\n");
  157. m_strText += _T("<B>Welcome To The Generic Troubleshooter v");
  158. m_strText += gstrProductVersion;
  159. m_strText += _T("</B></FONT> ");
  160. m_strText += _T("</TD>\n");
  161. m_strText += _T("</TR>\n");
  162. m_strText += _T("</h1></center>\n");
  163. m_strText += _T("</TABLE>\n");
  164. ////////////////////////////////////////////////////////////////////////////////////
  165. // Display global counters
  166. CString strTmp;
  167. CHourlyDailyCounter* curr_counter = NULL;
  168. m_strText += _T("<TABLE BORDER= \"1\" BORDERCOLOR=");
  169. m_strText += k_strTableBorderColor;
  170. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  171. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdProgramContemporary));
  172. if (curr_counter)
  173. {
  174. strTmp= CDisplayCounterCurrentDateTime(curr_counter).Display();
  175. AppendNameAndValueAsRow(m_strText, _T("Current Date/Time:"), strTmp);
  176. strTmp = CDisplayCounterCreateDateTime(curr_counter).Display();
  177. AppendNameAndValueAsRow(m_strText, _T("Date/Time program started:"), strTmp);
  178. }
  179. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdStatusAccess));
  180. if (curr_counter)
  181. {
  182. strTmp = CDisplayCounterTotal(curr_counter).Display();
  183. AppendNameAndValueAsRow(m_strText, _T("Number of status accesses to system since program was started:"), strTmp);
  184. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  185. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent status access:"), strTmp);
  186. }
  187. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdActionAccess));
  188. if (curr_counter)
  189. {
  190. strTmp = CDisplayCounterTotal(curr_counter).Display();
  191. AppendNameAndValueAsRow(m_strText, _T("Number of operator action accesses to system since program was started:"), strTmp);
  192. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  193. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent operator action access:"), strTmp);
  194. }
  195. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTotalAccessStart));
  196. if (curr_counter)
  197. {
  198. strTmp = CDisplayCounterTotal(curr_counter).Display();
  199. AppendNameAndValueAsRow(m_strText, _T("Number of total accesses to system since program was started:"), strTmp);
  200. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  201. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent access:"), strTmp);
  202. }
  203. if (ShowFullFirstPage(bHasPwd))
  204. {
  205. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdRequestUnknown));
  206. if (curr_counter)
  207. {
  208. strTmp = CDisplayCounterTotal(curr_counter).Display();
  209. AppendNameAndValueAsRow(m_strText, _T("Number of requests to system for unknown troubleshooters topics since program was started:"), strTmp);
  210. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  211. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent request to system for unknown troubleshooter topic:"), strTmp);
  212. }
  213. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdRequestRejected));
  214. if (curr_counter)
  215. {
  216. strTmp = CDisplayCounterTotal(curr_counter).Display();
  217. AppendNameAndValueAsRow(m_strText, _T("Number of requests system has rejected because of backlog in queue since program was started:"), strTmp);
  218. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  219. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent request system has rejected because of backlog in queue:"), strTmp);
  220. }
  221. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdErrorLogged));
  222. if (curr_counter)
  223. {
  224. strTmp = CDisplayCounterTotal(curr_counter).Display();
  225. AppendNameAndValueAsRow(m_strText, _T("Number of errors logged to event log since program was started:"), strTmp);
  226. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  227. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent logged error:"), strTmp);
  228. }
  229. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eMaxWQItems, dwRegistryItem))
  230. {
  231. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  232. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItem);
  233. }
  234. else
  235. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItemNotFound);
  236. ////////////////////////////////////////////////////////////////////////////////////
  237. // Extract and display information about threads and queue
  238. tmp_counter.Init(threadPool.GetWorkingThreadCount());
  239. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  240. AppendNameAndValueAsRow(m_strText, _T("Current number of working threads:"), strTmp);
  241. tmp_counter.Init(poolQueue.GetTotalQueueItems());
  242. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  243. AppendNameAndValueAsRow(m_strText, _T("Current number of work items in queue:"), strTmp);
  244. tmp_counter.Init(poolQueue.GetTotalWorkItems());
  245. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  246. AppendNameAndValueAsRow(m_strText, _T("Current number of work items either in queue or in progress:"), strTmp);
  247. }
  248. ////////////////////////////////////////////////////////////////////////////////////
  249. // Extract and display snapshot information about topic
  250. DWORD dwTotal=0, dwNoInit=0, dwFail=0;
  251. vector<CString> vector_placeholder;
  252. m_pConf->GetTopicShop().GetTopicsStatus(dwTotal, dwNoInit, dwFail, &vector_placeholder);
  253. tmp_counter.Init(dwTotal);
  254. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  255. AppendNameAndValueAsRow(m_strText, _T("Total number of known troubleshooter topics:"), strTmp);
  256. if (ShowFullFirstPage(bHasPwd))
  257. {
  258. tmp_counter.Init(dwFail);
  259. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  260. AppendNameAndValueAsRow(m_strText, _T("Number of troubleshooter topics that we have tried and failed to load:"), strTmp);
  261. }
  262. m_strText += _T("</TABLE>\n");
  263. ////////////////////////////////////////////////////////////////////////////////////
  264. m_strText += _T("</ul><center>\n");
  265. ////////////////////////////////////////////////////////////////////////////////////
  266. ////////////////////////////////////////////////////////////////////////////////////
  267. // Display buttons to get to sibling status pages
  268. if (ShowFullFirstPage(bHasPwd))
  269. {
  270. BeginSelfAddressingForm();
  271. InsertPasswordInForm();
  272. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  273. m_strText += C_FURTHER_GLOBAL;
  274. // Value here is not actually relevant; effectively used as a comment.
  275. m_strText += _T("\" VALUE=\"Further Global Status Page\">\n");
  276. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Further Global Status Page\">\n");
  277. m_strText += _T("</FORM>\n");
  278. BeginSelfAddressingForm();
  279. InsertPasswordInForm();
  280. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  281. m_strText += C_THREAD_OVERVIEW;
  282. // Value here is not actually relevant; effectively used as a comment.
  283. m_strText += _T("\" VALUE=\"Thread Status Overview Page\">\n");
  284. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Thread Status Overview Page\">\n");
  285. m_strText += _T("</FORM>\n");
  286. }
  287. ////////////////////////////////////////////////////////////////////////////////////
  288. // Display topics & links to status information for those topics
  289. vector<CString>arrstrTopic;
  290. m_pConf->GetListOfTopicNames(arrstrTopic);
  291. DWORD nTopics = arrstrTopic.size();
  292. for (DWORD i=0; i<nTopics; i++)
  293. {
  294. m_strText += _T("<TABLE>");
  295. m_strText += _T("<TR>");
  296. m_strText += _T("<TD>");
  297. BeginSelfAddressingForm();
  298. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  299. m_strText += C_TOPIC;
  300. m_strText += _T("\" VALUE=\"");
  301. m_strText += arrstrTopic[i];
  302. m_strText += _T("\">\n");
  303. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"");
  304. m_strText += _T("Problem Page for ");
  305. m_strText += arrstrTopic[i];
  306. m_strText += _T("\">\n");
  307. m_strText += _T("</FORM>\n");
  308. m_strText += _T("</TD>");
  309. if (ShowFullFirstPage(bHasPwd))
  310. {
  311. m_strText += _T("<TD>");
  312. BeginSelfAddressingForm();
  313. InsertPasswordInForm();
  314. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  315. m_strText += C_TOPIC_STATUS;
  316. m_strText += _T("\" VALUE=\"");
  317. m_strText += arrstrTopic[i];
  318. m_strText += _T("\">\n");
  319. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"");
  320. m_strText += _T("Status Page for ");
  321. m_strText += arrstrTopic[i];
  322. m_strText += _T("\">\n");
  323. m_strText += _T("</FORM>\n");
  324. m_strText += _T("</TD>");
  325. }
  326. m_strText += _T("</TR>");
  327. m_strText += _T("</TABLE>");
  328. }
  329. if(nTopics == 0)
  330. {
  331. m_strText += _T("<P>There are currently no troubleshooters available");
  332. }
  333. ////////////////////////////////////////////////////////////////////////////////////
  334. m_strText += _T("</center>\n");
  335. ////////////////////////////////////////////////////////////////////////////////////
  336. if (ShowFullFirstPage(bHasPwd))
  337. {
  338. m_strText += _T("<TABLE BORDER= \"1\" BORDERCOLOR=\"#000000\" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  339. ////////////////////////////////////////////////////////////////////////////////////
  340. // Display registry info
  341. if (registryMonitor.GetStringInfo(CAPGTSRegConnector::eResourcePath, strRegistryItem))
  342. AppendNameAndValueAsRow(m_strText, _T("Full path to resource:"), strRegistryItem);
  343. else
  344. AppendNameAndValueAsRow(m_strText, _T("Full path to resource:"), strRegistryItemNotFound);
  345. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eCookieLife, dwRegistryItem))
  346. {
  347. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  348. AppendNameAndValueAsRow(m_strText, _T("HTTP cookie expiration in minutes:"), strRegistryItem);
  349. }
  350. else
  351. AppendNameAndValueAsRow(m_strText, _T("HTTP cookie expiration in minutes:"), strRegistryItemNotFound);
  352. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eMaxThreads, dwRegistryItem))
  353. {
  354. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  355. AppendNameAndValueAsRow(m_strText, _T("Maximum threads:"), strRegistryItem);
  356. }
  357. else
  358. AppendNameAndValueAsRow(m_strText, _T("Maximum threads:"), strRegistryItemNotFound);
  359. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eMaxWQItems, dwRegistryItem))
  360. {
  361. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  362. AppendNameAndValueAsRow(m_strText, _T("Maximum work queue items:"), strRegistryItem);
  363. }
  364. else
  365. AppendNameAndValueAsRow(m_strText, _T("Maximum work queue items :"), strRegistryItemNotFound);
  366. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eReloadDelay, dwRegistryItem))
  367. {
  368. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  369. AppendNameAndValueAsRow(m_strText, _T("Refresh delay:"), strRegistryItem);
  370. }
  371. else
  372. AppendNameAndValueAsRow(m_strText, _T("Refresh delay:"), strRegistryItemNotFound);
  373. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eThreadsPP, dwRegistryItem))
  374. {
  375. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  376. AppendNameAndValueAsRow(m_strText, _T("Threads per processor:"), strRegistryItem);
  377. }
  378. else
  379. AppendNameAndValueAsRow(m_strText, _T("Threads per processor:"), strRegistryItemNotFound);
  380. if (registryMonitor.GetStringInfo(CAPGTSRegConnector::eVrootPath, strRegistryItem))
  381. AppendNameAndValueAsRow(m_strText, _T("VRoot path to DLL:"), strRegistryItem);
  382. else
  383. AppendNameAndValueAsRow(m_strText, _T("VRoot path to DLL:"), strRegistryItemNotFound);
  384. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eDetailedEventLogging, dwRegistryItem))
  385. {
  386. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  387. AppendNameAndValueAsRow(m_strText, _T("Detailed event logging:"), strRegistryItem);
  388. }
  389. else
  390. AppendNameAndValueAsRow(m_strText, _T("Detailed event logging:"), strRegistryItemNotFound);
  391. if (registryMonitor.GetStringInfo(CAPGTSRegConnector::eLogFilePath, strRegistryItem))
  392. AppendNameAndValueAsRow(m_strText, _T("Log file directory:"), strRegistryItem);
  393. else
  394. AppendNameAndValueAsRow(m_strText, _T("Log file directory:"), strRegistryItemNotFound);
  395. }
  396. m_strText += _T("</TABLE>\n");
  397. ////////////////////////////////////////////////////////////////////////////////////
  398. m_strText += _T("</body></html>\n");
  399. ////////////////////////////////////////////////////////////////////////////////////
  400. }
  401. void APGTSContext::DisplayFurtherGlobalStatusPage()
  402. {
  403. CHourlyDailyCounter tmp_counter;
  404. DWORD dwRegistryItem =0;
  405. CString strRegistryItem;
  406. CString strTmp;
  407. const CString strRegistryItemNotFound = _T("not found");
  408. CRegistryMonitor& registryMonitor = m_pConf->GetRegistryMonitor();
  409. CThreadPool& threadPool = m_pConf->GetThreadPool();
  410. CPoolQueue& poolQueue = m_pConf->GetPoolQueue();
  411. CHourlyDailyCounter* curr_counter = NULL;
  412. CDailyTotals daily;
  413. CHourlyTotals hourly;
  414. m_strText += _T("<html>\n");
  415. m_strText += _T("<B><head><title>Status</title></head>\n");
  416. m_strText += _T("<body bgcolor=");
  417. m_strText += k_strTextColorOfTitleOrSubTitle;
  418. m_strText += _T(">\n");
  419. m_strText += _T("<TABLE BORDER= \"1\" BORDERCOLOR=");
  420. m_strText += k_strTableBorderColor;
  421. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  422. m_strText += _T("<TR>\n");
  423. m_strText += _T("<TD COLSPAN=\"4\" ALIGN=CENTER BGCOLOR=");
  424. m_strText += k_strBGColorOfTitle;
  425. m_strText += _T(">\n");
  426. m_strText += _T("<FONT SIZE=\"+3\" COLOR=");
  427. m_strText += k_strTextColorOfTitleOrSubTitle;
  428. m_strText += _T(">\n");
  429. m_strText += _T("<B>Further Global Status Page ");
  430. m_strText += _T("</B></FONT> ");
  431. m_strText += _T("</TD>\n");
  432. m_strText += _T("</TR>\n");
  433. m_strText += _T("</TABLE>\n");
  434. ////////////////////////////////////////////////////////////////////////////////////
  435. // Display global counters
  436. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  437. m_strText += k_strTableBorderColor;
  438. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  439. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdProgramContemporary));
  440. if (curr_counter)
  441. {
  442. strTmp = CDisplayCounterCurrentDateTime(curr_counter).Display();
  443. AppendNameAndValueAsRow(m_strText, _T("Current Date/Time:"), strTmp);
  444. }
  445. m_strText += _T("</TABLE>\n");
  446. m_strText += _T("<br>\n");
  447. DisplayTextAsTable(m_strText, _T("Status Access To The System"), 1);
  448. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdStatusAccess));
  449. if (curr_counter)
  450. {
  451. strTmp = CDisplayCounterTotal(curr_counter).Display();
  452. AppendNameAndValueAsRow(m_strText, _T("Number of status accesses to system since program was started:"), strTmp);
  453. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  454. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent status access:"), strTmp);
  455. m_strText += _T("</TABLE>\n");
  456. DisplayTextAsTable(m_strText, _T("Daily/hourly count of status accesses to system since program was started"), 0);
  457. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  458. }
  459. m_strText += _T("</TABLE>\n");
  460. m_strText += _T("<br>\n");
  461. DisplayTextAsTable(m_strText, _T("Operator Access To The System"), 1);
  462. m_strText += _T("</TABLE>\n");
  463. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  464. m_strText += k_strTableBorderColor;
  465. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  466. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdActionAccess));
  467. if (curr_counter)
  468. {
  469. strTmp = CDisplayCounterTotal(curr_counter).Display();
  470. AppendNameAndValueAsRow(m_strText, _T("Number of operator action accesses to system since program was started:"), strTmp);
  471. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  472. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent operator action access:"), strTmp);
  473. m_strText += _T("</TABLE>\n");
  474. DisplayTextAsTable(m_strText, _T("Daily/hourly count of operator action accesses to system since program was started"), 0);
  475. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  476. }
  477. m_strText += _T("</TABLE>\n");
  478. m_strText += _T("<br>\n");
  479. DisplayTextAsTable(m_strText, _T("Total Access To The System"), 1);
  480. m_strText += _T("</TABLE>\n");
  481. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  482. m_strText += k_strTableBorderColor;
  483. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  484. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTotalAccessStart));
  485. if (curr_counter)
  486. {
  487. strTmp = CDisplayCounterTotal(curr_counter).Display();
  488. AppendNameAndValueAsRow(m_strText, _T("Number of total accesses to system since program was started:"), strTmp);
  489. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  490. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent access:"), strTmp);
  491. m_strText += _T("</TABLE>\n");
  492. DisplayTextAsTable(m_strText, _T("Daily/hourly count of total accesses to system since program was started"), 0);
  493. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  494. }
  495. m_strText += _T("</TABLE>\n");
  496. m_strText += _T("<br>\n");
  497. DisplayTextAsTable(m_strText, _T("Request To System For UnKnown TroubleShooter Topics"), 1);
  498. m_strText += _T("</TABLE>\n");
  499. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  500. m_strText += k_strTableBorderColor;
  501. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  502. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdRequestUnknown));
  503. if (curr_counter)
  504. {
  505. strTmp = CDisplayCounterTotal(curr_counter).Display();
  506. AppendNameAndValueAsRow(m_strText, _T("Number of requests to system for unknown troubleshooters topics since program was started:"), strTmp);
  507. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  508. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent request to system for unknown troubleshooter topic:"), strTmp);
  509. m_strText += _T("</TABLE>\n");
  510. DisplayTextAsTable(m_strText, _T("Daily/hourly count of requests to system for unknown troubleshooter topics since program was started"), 0);
  511. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  512. }
  513. m_strText += _T("</TABLE>\n");
  514. m_strText += _T("<br>\n");
  515. DisplayTextAsTable(m_strText, _T("Requests System Has Rejected"), 1);
  516. m_strText += _T("</TABLE>\n");
  517. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  518. m_strText += k_strTableBorderColor;
  519. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  520. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdRequestRejected));
  521. if (curr_counter)
  522. {
  523. strTmp = CDisplayCounterTotal(curr_counter).Display();
  524. AppendNameAndValueAsRow(m_strText, _T("Number of requests system has rejected because of backlog in queue since program was started:"), strTmp);
  525. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  526. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent request system has rejected because of backlog in queue:"), strTmp);
  527. m_strText += _T("</TABLE>\n");
  528. DisplayTextAsTable(m_strText, _T("Daily/hourly count of requests system has rejected because of backlog in queue since program was started"), 0);
  529. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  530. }
  531. m_strText += _T("</TABLE>\n");
  532. m_strText += _T("<br>\n");
  533. DisplayTextAsTable(m_strText, _T("Errors Logged To Event Log"), 1);
  534. m_strText += _T("</TABLE>\n");
  535. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  536. m_strText += k_strTableBorderColor;
  537. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  538. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdErrorLogged));
  539. if (curr_counter)
  540. {
  541. strTmp = CDisplayCounterTotal(curr_counter).Display();
  542. AppendNameAndValueAsRow(m_strText, _T("Number of errors logged to event log since program was started:"), strTmp);
  543. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  544. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent logged error:"), strTmp);
  545. m_strText += _T("</TABLE>\n");
  546. DisplayTextAsTable(m_strText, _T("Daily/hourly count of logged errors"), 0);
  547. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  548. }
  549. m_strText += _T("</TABLE>\n");
  550. m_strText += _T("<br>\n");
  551. DisplayTextAsTable(m_strText, _T("Statistics About Queue, Thread and Successful/Unsuccessful Load Of Topics"), 1);
  552. m_strText += _T("</TABLE>\n");
  553. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  554. m_strText += k_strTableBorderColor;
  555. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  556. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eMaxWQItems, dwRegistryItem))
  557. {
  558. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  559. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItem);
  560. }
  561. else
  562. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItemNotFound);
  563. m_strText += _T("\n");
  564. ////////////////////////////////////////////////////////////////////////////////////
  565. // Extract and display information about threads and queue
  566. tmp_counter.Init(threadPool.GetWorkingThreadCount());
  567. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  568. AppendNameAndValueAsRow(m_strText, _T("Current number of working threads:"), strTmp);
  569. tmp_counter.Init(poolQueue.GetTotalQueueItems());
  570. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  571. AppendNameAndValueAsRow(m_strText, _T("Current number of work items in queue :"), strTmp);
  572. tmp_counter.Init(poolQueue.GetTotalWorkItems());
  573. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  574. AppendNameAndValueAsRow(m_strText, _T("Current number of work items either in queue or in progress :"), strTmp);
  575. //////////////////////////////////////////////////////////////////////////////////
  576. strTmp = CSafeTime(poolQueue.GetTimeLastAdd()).StrLocalTime();
  577. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent addition to queue :"), strTmp);
  578. strTmp = CSafeTime(poolQueue.GetTimeLastRemove()).StrLocalTime();
  579. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent removal from queue :"), strTmp);
  580. ////////////////////////////////////////////////////////////////////////////////////
  581. // Extract and display snapshot information about topic
  582. DWORD dwTotal=0, dwNoInit=0, dwFail=0;
  583. vector<CString> vector_topics_failed;
  584. m_pConf->GetTopicShop().GetTopicsStatus(dwTotal, dwNoInit, dwFail, &vector_topics_failed);
  585. tmp_counter.Init(dwTotal);
  586. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  587. AppendNameAndValueAsRow(m_strText, _T("Total number of known troubleshooter topics:"), strTmp);
  588. tmp_counter.Init(dwNoInit);
  589. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  590. AppendNameAndValueAsRow(m_strText, _T("Number of troubleshooter topics that we have not yet tried to load:"), strTmp);
  591. tmp_counter.Init(dwFail);
  592. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  593. AppendNameAndValueAsRow(m_strText, _T("Number of troubleshooter topics that we have tried and failed to load:"), strTmp);
  594. if (vector_topics_failed.size())
  595. for (vector<CString>::iterator i = vector_topics_failed.begin(); i != vector_topics_failed.end(); i++)
  596. {
  597. strTmp = *i;
  598. AppendNameAndValueAsRow(m_strText, _T("List of troubleshooter topics that we have tried and failed to load:"), strTmp);
  599. }
  600. else
  601. {
  602. strTmp = _T("No topics");
  603. AppendNameAndValueAsRow(m_strText, _T("List of troubleshooter topics that we have tried and failed to load:"), strTmp);
  604. }
  605. ////////////////////////////////////////////////////////////////////////////////////
  606. // Extract and display snapshot information about alternate templates
  607. vector<CString> vector_templates_failed;
  608. vector<DWORD> vector_templatescnt_failed;
  609. DWORD dwTemplateCnt;
  610. m_pConf->GetTopicShop().GetTemplatesStatus( &vector_templates_failed, &vector_templatescnt_failed );
  611. dwTemplateCnt= vector_templates_failed.size();
  612. if (dwTemplateCnt)
  613. {
  614. // Only output if there are failed loads.
  615. tmp_counter.Init( dwTemplateCnt );
  616. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  617. AppendNameAndValueAsRow(m_strText, _T("Total number of templates not found:"), strTmp);
  618. vector<DWORD>::iterator j = vector_templatescnt_failed.begin();
  619. for (vector<CString>::iterator i = vector_templates_failed.begin();
  620. i != vector_templates_failed.end(); i++)
  621. {
  622. strTmp = *i;
  623. AppendNameAndValueAsRow(m_strText, _T(""), strTmp);
  624. if (j != vector_templatescnt_failed.end())
  625. {
  626. // Output the counts.
  627. tmp_counter.Init( *j );
  628. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  629. AppendNameAndValueAsRow(m_strText, _T(": "), strTmp);
  630. j++;
  631. }
  632. }
  633. }
  634. m_strText += _T("</TABLE>\n");
  635. //////////////////////////////////////////////////////////////////////////////////
  636. // Link buttons
  637. BeginSelfAddressingForm();
  638. InsertPasswordInForm();
  639. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  640. m_strText += C_FIRST;
  641. // Value here is not actually relevant; effectively used as a comment.
  642. m_strText += _T("\" VALUE=\"Front Page\">\n");
  643. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Front Page\">\n");
  644. m_strText += _T("</FORM>\n");
  645. BeginSelfAddressingForm();
  646. InsertPasswordInForm();
  647. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  648. m_strText += C_THREAD_OVERVIEW;
  649. // Value here is not actually relevant; effectively used as a comment.
  650. m_strText += _T("\" VALUE=\"Thread Status Overview Page\">\n");
  651. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Thread Status Overview Page\">\n");
  652. m_strText += _T("</FORM>\n");
  653. //////////////////////////////////////////////////////////////////////////////////
  654. m_strText += _T("</body></html>\n");
  655. //////////////////////////////////////////////////////////////////////////////////
  656. }
  657. void APGTSContext::DisplayThreadStatusOverviewPage()
  658. {
  659. CString strTmp;
  660. CString strTmp2;
  661. CString strTmp3;
  662. CString strTmp4;
  663. CHourlyDailyCounter tmp_counter;
  664. DWORD dwRegistryItem =0;
  665. CString strRegistryItem;
  666. const CString strRegistryItemNotFound = _T("not found");
  667. CRegistryMonitor& registryMonitor = m_pConf->GetRegistryMonitor();
  668. CDirectoryMonitor& directoryMonitor = m_pConf->GetDirectoryMonitor();
  669. CTopicShop& topicShop = m_pConf->GetTopicShop();
  670. CThreadPool& threadPool = m_pConf->GetThreadPool();
  671. CPoolQueue& poolQueue = m_pConf->GetPoolQueue();
  672. CHourlyDailyCounter* curr_counter = NULL;
  673. CDailyTotals daily;
  674. CHourlyTotals hourly;
  675. ////////////////////////////////////////////////////////////////////////////////////
  676. // Collect status information for pool threads
  677. vector<CPoolThreadStatus> arrPoolThreadStatus;
  678. for (long i = 0; i < threadPool.GetWorkingThreadCount(); i++)
  679. {
  680. CPoolThreadStatus status;
  681. threadPool.ThreadStatus(i, status);
  682. arrPoolThreadStatus.push_back(status);
  683. }
  684. m_strText += _T("<html>\n");
  685. m_strText += _T("<B><head><title>Status</title></head>\n");
  686. m_strText += _T("<body bgcolor=");
  687. m_strText += k_strTextColorOfTitleOrSubTitle;
  688. m_strText += _T(">\n");
  689. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  690. m_strText += k_strTableBorderColor;
  691. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  692. m_strText += _T("<TR>\n");
  693. m_strText += _T("<TD COLSPAN=\"4\" ALIGN=CENTER BGCOLOR=");
  694. m_strText += k_strBGColorOfTitle;
  695. m_strText += _T(">\n");
  696. m_strText += _T("<FONT SIZE=\"+3\" COLOR=");
  697. m_strText += k_strTextColorOfTitleOrSubTitle;
  698. m_strText += _T(">\n");
  699. m_strText += _T("<B>Thread Status Overview Page ");
  700. m_strText += _T("</B></FONT> ");
  701. m_strText += _T("</TD>\n");
  702. m_strText += _T("</TR>\n");
  703. m_strText += _T("</h1></center>\n");
  704. m_strText += _T("</TABLE>\n");
  705. ////////////////////////////////////////////////////////////////////////////////////
  706. // Display global counters
  707. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=\"#000000\" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  708. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdProgramContemporary));
  709. if (curr_counter)
  710. {
  711. strTmp = CDisplayCounterCurrentDateTime(curr_counter).Display();
  712. AppendNameAndValueAsRow(m_strText, _T("Current Date/Time:"), strTmp);
  713. }
  714. if (registryMonitor.GetNumericInfo(CAPGTSRegConnector::eMaxWQItems, dwRegistryItem))
  715. {
  716. strRegistryItem.Format(_T("%d"), dwRegistryItem);
  717. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItem);
  718. }
  719. else
  720. AppendNameAndValueAsRow(m_strText, _T("Current maximum size of queue:"), strRegistryItemNotFound);
  721. ////////////////////////////////////////////////////////////////////////////////////
  722. // Extract and display information about threads and queue
  723. tmp_counter.Init(threadPool.GetWorkingThreadCount());
  724. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  725. AppendNameAndValueAsRow(m_strText, _T("Current number of working threads:"), strTmp);
  726. tmp_counter.Init(poolQueue.GetTotalQueueItems());
  727. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  728. AppendNameAndValueAsRow(m_strText, _T("Current number of work items in queue:"), strTmp);
  729. tmp_counter.Init(poolQueue.GetTotalWorkItems());
  730. strTmp = CDisplayCounterTotal(&tmp_counter).Display();
  731. AppendNameAndValueAsRow(m_strText, _T("Current number of work items either in queue or in progress:"), strTmp);
  732. strTmp = CSafeTime(poolQueue.GetTimeLastAdd()).StrLocalTime();
  733. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent addition to queue:"), strTmp);
  734. strTmp = CSafeTime(poolQueue.GetTimeLastRemove()).StrLocalTime();
  735. AppendNameAndValueAsRow(m_strText, _T("Date/Time of most recent removal from queue:"), strTmp);
  736. //////////////////////////////////////////////////////////////////////////////////
  737. // thread pool status information
  738. long more5 = 0, more10 = 0;
  739. vector<CPoolThreadStatus> arrPoolThreadStatusOlder5;
  740. // This next is slightly klugy. Ideally, we'd get this info into arrPoolThreadStatusOlder5
  741. vector<DWORD> Older5ThreadNumber;
  742. for (i = 0; i < arrPoolThreadStatus.size(); i++)
  743. {
  744. if (arrPoolThreadStatus[i].m_bWorking)
  745. {
  746. if (arrPoolThreadStatus[i].m_seconds > 5)
  747. {
  748. arrPoolThreadStatusOlder5.push_back(arrPoolThreadStatus[i]);
  749. Older5ThreadNumber.push_back(i);
  750. more5++;
  751. }
  752. if (arrPoolThreadStatus[i].m_seconds > 10)
  753. more10++;
  754. }
  755. }
  756. strTmp.Format(_T("%ld"), more5);
  757. AppendNameAndValueAsRow(m_strText, _T("Number of pool threads that have been working on a task for more than 5 seconds:"), strTmp);
  758. strTmp.Format(_T("%ld"), more10);
  759. AppendNameAndValueAsRow(m_strText, _T("Number of pool threads that have been working on a task for more than 10 seconds:"), strTmp);
  760. m_strText += _T("</TABLE>\n");
  761. m_strText += _T("<br>\n");
  762. DisplayTextAsTable(m_strText, _T("Detailed information on each of the pool threads that has been working on a task for more than 5 seconds"), 1);
  763. for (i = 0; i < arrPoolThreadStatusOlder5.size(); i++)
  764. {
  765. strTmp.Format(_T("<B>Thread %d </B>"), Older5ThreadNumber[i]);
  766. strTmp2 = _T(" has been in \"working\" state for ");
  767. strTmp += strTmp2;
  768. strTmp3.Format(_T("%ld"), (long)arrPoolThreadStatusOlder5[i].m_seconds);
  769. strTmp3 += _T(" seconds");
  770. AppendNameAndValueAsRow(m_strText, strTmp, strTmp3);
  771. strTmp.Format( _T("Date/Time thread %d started:"), Older5ThreadNumber[i]);
  772. strTmp2 = CSafeTime(arrPoolThreadStatusOlder5[i].m_timeCreated).StrLocalTime();
  773. AppendNameAndValueAsRow(m_strText, strTmp, strTmp2);
  774. strTmp.Format( _T("Thread %d is working on topic:"), Older5ThreadNumber[i]);
  775. strTmp2 = arrPoolThreadStatusOlder5[i].m_strTopic.GetLength()
  776. ? arrPoolThreadStatusOlder5[i].m_strTopic
  777. : _T("no topic");
  778. AppendNameAndValueAsRow(m_strText, strTmp, strTmp2);
  779. strTmp.Format (_T("Client IP address for Thread %d:"),Older5ThreadNumber[i] );
  780. strTmp2 = arrPoolThreadStatusOlder5[i].m_strClientIP.GetLength()
  781. ? arrPoolThreadStatusOlder5[i].m_strClientIP : _T("no address");
  782. AppendNameAndValueAsRow(m_strText, strTmp, strTmp2);
  783. strTmp.Format( _T(" Client browser for Thread %d:"), Older5ThreadNumber[i] );
  784. strTmp2 = arrPoolThreadStatusOlder5[i].m_strBrowser.GetLength()
  785. ? arrPoolThreadStatusOlder5[i].m_strBrowser : _T("no browser");
  786. AppendNameAndValueAsRow(m_strText, strTmp, strTmp2);
  787. }
  788. if (!i)
  789. AppendNameAndValueAsRow(m_strText, _T(""), _T("No threads"));
  790. //////////////////////////////////////////////////////////////////////////////////
  791. // registry monitor thread status information
  792. CRegistryMonitor::ThreadStatus registryStatus;
  793. DWORD registrySeconds = 0;
  794. CString strRegistryStatus;
  795. registryMonitor.GetStatus(registryStatus, registrySeconds);
  796. switch(registryStatus)
  797. {
  798. case CRegistryMonitor::eBeforeInit: strRegistryStatus = _T("Before Init");
  799. break;
  800. case CRegistryMonitor::eInit: strRegistryStatus = _T("Init");
  801. break;
  802. case CRegistryMonitor::eFail: strRegistryStatus = _T("Fail");
  803. break;
  804. case CRegistryMonitor::eDefaulting: strRegistryStatus = _T("Defaulting");
  805. break;
  806. case CRegistryMonitor::eWait: strRegistryStatus = _T("Wait");
  807. break;
  808. case CRegistryMonitor::eRun: strRegistryStatus = _T("Run");
  809. break;
  810. case CRegistryMonitor::eExiting: strRegistryStatus = _T("Exiting");
  811. break;
  812. }
  813. m_strText += _T("</TABLE>\n");
  814. m_strText += _T("<br>\n");
  815. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  816. m_strText += k_strTableBorderColor;
  817. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  818. strTmp = strRegistryStatus;
  819. AppendNameAndValueAsRow(m_strText, _T("Current status of Registry Monitor thread:"), strTmp);
  820. strTmp.Format(_T("%ld"), (long)registrySeconds);
  821. strTmp += _T(" seconds\n");
  822. AppendNameAndValueAsRow(m_strText, _T("The thread has been in this status for "), strTmp);
  823. //////////////////////////////////////////////////////////////////////////////////
  824. // directory monitor thread status information
  825. CDirectoryMonitor::ThreadStatus directoryStatus;
  826. DWORD directorySeconds = 0;
  827. CString strDirectoryStatus;
  828. directoryMonitor.GetStatus(directoryStatus, directorySeconds);
  829. switch(directoryStatus)
  830. {
  831. case CDirectoryMonitor::eBeforeInit: strDirectoryStatus = _T("Before Init");
  832. break;
  833. case CDirectoryMonitor::eFail: strDirectoryStatus = _T("Fail");
  834. break;
  835. case CDirectoryMonitor::eWaitDirPath: strDirectoryStatus = _T("Wait For Dir Path");
  836. break;
  837. case CDirectoryMonitor::eWaitChange: strDirectoryStatus = _T("Wait For Change");
  838. break;
  839. case CDirectoryMonitor::eWaitSettle: strDirectoryStatus = _T("Wait To Settle");
  840. break;
  841. case CDirectoryMonitor::eRun: strDirectoryStatus = _T("Run");
  842. break;
  843. case CDirectoryMonitor::eBeforeWaitChange: strDirectoryStatus = _T("Before Wait Change");
  844. break;
  845. case CDirectoryMonitor::eExiting: strDirectoryStatus = _T("Exiting");
  846. break;
  847. }
  848. strTmp = strDirectoryStatus;
  849. AppendNameAndValueAsRow(m_strText, _T("Current status of Directory Monitor thread:"), strTmp);
  850. strTmp.Format(_T("%ld"), (long)directorySeconds);
  851. strTmp += _T(" seconds\n");
  852. AppendNameAndValueAsRow(m_strText, _T("The thread has been in this status for "), strTmp);
  853. //////////////////////////////////////////////////////////////////////////////////
  854. // topic builder thread status information
  855. CTopicShop::ThreadStatus topicshopStatus;
  856. DWORD topicshopSeconds = 0;
  857. CString strTopicshopStatus;
  858. topicShop.GetThreadStatus(topicshopStatus, topicshopSeconds);
  859. switch(topicshopStatus)
  860. {
  861. case CTopicShop::eBeforeInit: strTopicshopStatus = _T("Before Init");
  862. break;
  863. case CTopicShop::eFail: strTopicshopStatus = _T("Fail");
  864. break;
  865. case CTopicShop::eWait: strTopicshopStatus = _T("Wait");
  866. break;
  867. case CTopicShop::eRun: strTopicshopStatus = _T("Run");
  868. break;
  869. case CTopicShop::eExiting: strTopicshopStatus = _T("Exiting");
  870. break;
  871. }
  872. strTmp = strTopicshopStatus;
  873. AppendNameAndValueAsRow(m_strText, _T("Current status of TopicShop Monitor thread:"), strTmp);
  874. strTmp.Format(_T("%ld"), (long)topicshopSeconds);
  875. strTmp += _T(" seconds\n");
  876. AppendNameAndValueAsRow(m_strText, _T("The thread has been in this status for "), strTmp);
  877. //////////////////////////////////////////////////////////////////////////////////
  878. m_strText += _T("</TABLE>\n");
  879. m_strText += _T("<br>\n");
  880. DisplayTextAsTable(m_strText, _T("State of each pool thread"), 1);
  881. for (i = 0; i < arrPoolThreadStatus.size(); i++)
  882. {
  883. strTmp.Format(_T("<B>Thread %d has been in "), i);
  884. strTmp2 = arrPoolThreadStatus[i].m_bWorking ? _T("\"working\"") : _T("\"waiting\"");
  885. strTmp3 = _T(" state for </B>");
  886. strTmp2 += strTmp3;
  887. strTmp += strTmp2;
  888. strTmp4.Format(_T("%ld"), (long)arrPoolThreadStatus[i].m_seconds);
  889. strTmp4 += _T(" seconds.");
  890. AppendNameAndValueAsRow(m_strText, strTmp, strTmp4);
  891. }
  892. if (!i)
  893. AppendNameAndValueAsRow(m_strText, _T(""),_T("No threads") );
  894. m_strText += _T("</TABLE>\n");
  895. //////////////////////////////////////////////////////////////////////////////////
  896. // Link buttons
  897. BeginSelfAddressingForm();
  898. InsertPasswordInForm();
  899. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  900. m_strText += C_FURTHER_GLOBAL;
  901. // Value here is not actually relevant; effectively used as a comment.
  902. m_strText += _T("\" VALUE=\"Further Global Status Page\">\n");
  903. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Further Global Status Page\">\n");
  904. m_strText += _T("</FORM>\n");
  905. BeginSelfAddressingForm();
  906. InsertPasswordInForm();
  907. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  908. m_strText += C_FIRST;
  909. // Value here is not actually relevant; effectively used as a comment.
  910. m_strText += _T("\" VALUE=\"Front Page\">\n");
  911. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Front Page\">\n");
  912. m_strText += _T("</FORM>\n");
  913. m_strText += _T("</body></html>\n");
  914. }
  915. ///////////////////////////
  916. void APGTSContext::DisplayTopicStatusPage(LPCTSTR topic_name)
  917. {
  918. CHourlyDailyCounter tmp_counter, *curr_counter;
  919. CTopicShop& topicShop = m_pConf->GetTopicShop();
  920. CTopicInCatalog* pTopicInCatalog = topicShop.GetCatalogEntry(topic_name);
  921. CHourlyTotals hourly;
  922. CDailyTotals daily;
  923. CString strTmp;
  924. CString strTmp2;
  925. m_strText += _T("<html>\n");
  926. m_strText += _T("<B><head><title>Status</title></head>\n");
  927. m_strText += _T("<body bgcolor=");
  928. m_strText += k_strTextColorOfTitleOrSubTitle;
  929. m_strText += _T(">\n");
  930. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  931. m_strText += k_strTableBorderColor;
  932. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  933. m_strText += _T("<TR>\n");
  934. m_strText += _T("<TD COLSPAN=\"4\" ALIGN=CENTER BGCOLOR=");
  935. m_strText += k_strBGColorOfTitle;
  936. m_strText += _T("> \n");
  937. m_strText += _T("<FONT SIZE=\"+3\" COLOR=");
  938. m_strText += k_strTextColorOfTitleOrSubTitle;
  939. m_strText += _T("> \n");
  940. m_strText += _T("<B>Topic Status Page for ");
  941. m_strText += topic_name;
  942. m_strText += _T("</B></FONT> ");
  943. m_strText += _T("</TD>\n");
  944. m_strText += _T("</TR>\n");
  945. if (pTopicInCatalog)
  946. m_strText += _T("</h1></center>\n");
  947. else
  948. {
  949. m_strText += _T("No data available");
  950. m_strText += _T("</h1></center>\n");
  951. return;
  952. }
  953. CTopicInfo topicInfo = pTopicInCatalog->GetTopicInfo();
  954. CString strDsc = CAbstractFileReader::GetJustName(topicInfo.GetDscFilePath());
  955. CString strHti = CAbstractFileReader::GetJustName(topicInfo.GetHtiFilePath());
  956. CString strBes = CAbstractFileReader::GetJustName(topicInfo.GetBesFilePath());
  957. m_strText += _T("</TABLE>\n");
  958. m_strText += _T("<TABLE BORDER= \"1\" BORDERCOLOR=\"#000000\" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  959. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdProgramContemporary));
  960. if (curr_counter)
  961. {
  962. strTmp = CDisplayCounterCurrentDateTime(curr_counter).Display();
  963. AppendNameAndValueAsRow(m_strText, _T("Current Date/Time:"), strTmp);
  964. }
  965. m_strText += _T("</TABLE>\n");
  966. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  967. m_strText += k_strTableBorderColor;
  968. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  969. strTmp = CString(_T("<BR>")) + (strDsc.GetLength() ? strDsc : _T("Unknown"));
  970. strTmp2 = CString(_T("<BR>")) + topicInfo.GetStrDscFileCreated();
  971. AppendTwoNamesAndValueAsRow(m_strText, _T("DSC file:"), strTmp, strTmp2);
  972. m_strText += _T("</TABLE>\n");
  973. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  974. m_strText += k_strTableBorderColor;
  975. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  976. bool bHTIinsideOfDSC= false, bBESinsideOfDSC= false;
  977. {
  978. CP_TOPIC ptrTopic;
  979. pTopicInCatalog->GetTopicNoWait(ptrTopic);
  980. CString strTmp;
  981. if (!ptrTopic.IsNull())
  982. {
  983. strTmp = ptrTopic->GetNetPropItemStr( H_NET_DATE_TIME );
  984. // Check for HTI and BES files inside the DSC.
  985. CString strTmpHTI= ptrTopic->GetMultilineNetProp( H_NET_HTI_ONLINE, _T("%s\r\n") );
  986. if (strTmpHTI.GetLength())
  987. bHTIinsideOfDSC= true;
  988. CString strTmpBES= ptrTopic->GetNetPropItemStr( H_NET_BES );
  989. if (strTmpBES.GetLength())
  990. bBESinsideOfDSC= true;
  991. }
  992. strTmp2 = strTmp.GetLength() ? strTmp : _T("Unavailable");
  993. AppendNameAndValueAsRow(m_strText, _T("Last revision date/time of DSC:"), strTmp2);
  994. }
  995. m_strText += _T("</TABLE>\n");
  996. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  997. m_strText += k_strTableBorderColor;
  998. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  999. strTmp2 = CString(_T("<BR>")) + topicInfo.GetStrHtiFileCreated();
  1000. if (strHti.GetLength())
  1001. strTmp= _T("<BR>") + strHti;
  1002. else if (bHTIinsideOfDSC)
  1003. {
  1004. // Use DSC file settings.
  1005. strTmp = CString(_T("<BR>")) + (strDsc.GetLength() ? strDsc : _T("Unknown"));
  1006. strTmp2 = CString(_T("<BR>")) + topicInfo.GetStrDscFileCreated();
  1007. }
  1008. else
  1009. strTmp= _T("<BR>Unknown");
  1010. AppendTwoNamesAndValueAsRow(m_strText, _T("HTI file:"), strTmp, strTmp2);
  1011. strTmp2 = CString(_T("<BR>")) + topicInfo.GetStrBesFileCreated();
  1012. if (strBes.GetLength())
  1013. strTmp= _T("<BR>") + strBes;
  1014. else if (bBESinsideOfDSC)
  1015. {
  1016. // Use DSC file settings.
  1017. strTmp = CString(_T("<BR>")) + (strDsc.GetLength() ? strDsc : _T("Unknown"));
  1018. strTmp2 = CString(_T("<BR>")) + topicInfo.GetStrDscFileCreated();
  1019. }
  1020. else
  1021. strTmp= _T("<BR>Unknown");
  1022. AppendTwoNamesAndValueAsRow(m_strText, _T("BES file:"), strTmp, strTmp2);
  1023. if (pTopicInCatalog->GetTopicInfoMayNotBeCurrent())
  1024. {
  1025. m_strText += _T("<TR>\n");
  1026. m_strText += _T("<TD COLSPAN=3 ALIGN=\"CENTER\" BGCOLOR=\"#CCCC99\" >\n");
  1027. m_strText += _T("<BR>***BES or HTI may recently have changed, and data may not yet be updated.***");
  1028. m_strText += _T("</TD>\n");
  1029. m_strText += _T("</TR>\n");
  1030. }
  1031. m_strText += _T("</TABLE>\n");
  1032. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=");
  1033. m_strText += k_strTableBorderColor;
  1034. m_strText += _T(" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  1035. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicEvent, topicInfo.GetNetworkName()));
  1036. if (curr_counter)
  1037. {
  1038. strTmp = CDisplayCounterFirstDateTime(curr_counter).Display();
  1039. AppendNameAndValueAsRow(m_strText, _T("Date/time of first becoming aware of this topic:"), strTmp);
  1040. }
  1041. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoad, topicInfo.GetNetworkName()));
  1042. if (curr_counter)
  1043. {
  1044. strTmp = CDisplayCounterFirstDateTime(curr_counter).Display();
  1045. AppendNameAndValueAsRow(m_strText, _T("Date/time of first attempted load of this topic:"), strTmp);
  1046. }
  1047. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoadOK, topicInfo.GetNetworkName()));
  1048. if (curr_counter)
  1049. {
  1050. strTmp = CDisplayCounterFirstDateTime(curr_counter).Display();
  1051. AppendNameAndValueAsRow(m_strText, _T("Date/time of first successful load of this topic:"), strTmp);
  1052. }
  1053. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicEvent, topicInfo.GetNetworkName()));
  1054. if (curr_counter)
  1055. {
  1056. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  1057. AppendNameAndValueAsRow(m_strText, _T("Date/time of most recent change (detected by directory monitor) or reload request (from an operator) to this topic:"), strTmp);
  1058. }
  1059. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoad, topicInfo.GetNetworkName()));
  1060. if (curr_counter)
  1061. {
  1062. strTmp = CDisplayCounterTotal(curr_counter).Display();
  1063. AppendNameAndValueAsRow(m_strText, _T("Count of attempted loads of this topic:"), strTmp);
  1064. }
  1065. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoad, topicInfo.GetNetworkName()));
  1066. if (curr_counter)
  1067. {
  1068. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  1069. AppendNameAndValueAsRow(m_strText, _T("Date/time of most recent attempted load of this topic:"), strTmp);
  1070. }
  1071. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoadOK, topicInfo.GetNetworkName()));
  1072. if (curr_counter)
  1073. {
  1074. strTmp = CDisplayCounterTotal(curr_counter).Display();
  1075. AppendNameAndValueAsRow(m_strText, _T("Count of successful loads of this topic:"), strTmp);
  1076. }
  1077. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicLoadOK, topicInfo.GetNetworkName()));
  1078. if (curr_counter)
  1079. {
  1080. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  1081. AppendNameAndValueAsRow(m_strText, _T("Date/time of most recent successful load of this topic:"), strTmp);
  1082. }
  1083. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHit, topicInfo.GetNetworkName()));
  1084. if (curr_counter)
  1085. {
  1086. strTmp = CDisplayCounterFirstDateTime(curr_counter).Display();
  1087. AppendNameAndValueAsRow(m_strText, _T("Date/time of first user hit on this topic:"), strTmp);
  1088. }
  1089. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHit, topicInfo.GetNetworkName()));
  1090. if (curr_counter)
  1091. {
  1092. strTmp = CDisplayCounterLastDateTime(curr_counter).Display();
  1093. AppendNameAndValueAsRow(m_strText, _T("Date/time of most recent hit:"), strTmp);
  1094. }
  1095. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHit, topicInfo.GetNetworkName()));
  1096. if (curr_counter)
  1097. {
  1098. strTmp = CDisplayCounterTotal(curr_counter).Display();
  1099. AppendNameAndValueAsRow(m_strText, _T("Total count of hits since system startup:"), strTmp);
  1100. }
  1101. m_strText += _T("</TABLE>\n");
  1102. m_strText += _T("<br>\n");
  1103. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHit, topicInfo.GetNetworkName()));
  1104. if (curr_counter)
  1105. {
  1106. DisplayTextAsTable(m_strText, _T("Daily/hourly count of hits"), 1);
  1107. m_strText += CDisplayCounterDailyHourly(curr_counter, &daily, &hourly).Display();
  1108. }
  1109. m_strText += _T("</TABLE>\n");
  1110. m_strText += _T("<br>\n");
  1111. m_strText += _T("<TABLE BORDER=\"1\" BORDERCOLOR=\"#000000\" CELLPADDING=\"2\" CELLSPACING=\"0\" WIDTH=100%>\n");
  1112. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHitNewCookie, topicInfo.GetNetworkName()));
  1113. if (curr_counter)
  1114. {
  1115. strTmp = CDisplayCounterTotal(curr_counter).Display();
  1116. AppendNameAndValueAsRow(m_strText, _T("Hits without cookie (presumably first hit by this user):"), strTmp);
  1117. }
  1118. curr_counter = (CHourlyDailyCounter*)Get_g_CounterMgr()->Get(CCounterLocation(CCounterLocation::eIdTopicHitOldCookie, topicInfo.GetNetworkName()));
  1119. if (curr_counter)
  1120. {
  1121. strTmp = CDisplayCounterTotal(curr_counter).Display();
  1122. AppendNameAndValueAsRow(m_strText, _T("Hits with cookie (presumably not first hit by this user):"), strTmp);
  1123. }
  1124. m_strText += _T("</TABLE>\n");
  1125. if (CTopicInCatalog::eFail != pTopicInCatalog->GetTopicStatus())
  1126. {
  1127. BeginSelfAddressingForm();
  1128. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  1129. m_strText += C_TOPIC;
  1130. m_strText += _T("\" VALUE=\"");
  1131. m_strText += topic_name;
  1132. m_strText += _T("\">\n");
  1133. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"");
  1134. m_strText += _T("Problem Page for ");
  1135. m_strText += topic_name;
  1136. m_strText += _T("\">\n");
  1137. m_strText += _T("</FORM>\n");
  1138. }
  1139. BeginSelfAddressingForm();
  1140. InsertPasswordInForm();
  1141. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  1142. m_strText += C_FURTHER_GLOBAL;
  1143. // Value here is not actually relevant; effectively used as a comment.
  1144. m_strText += _T("\" VALUE=\"Further Global Status Page\">\n");
  1145. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Further Global Status Page\">\n");
  1146. m_strText += _T("</FORM>\n");
  1147. BeginSelfAddressingForm();
  1148. InsertPasswordInForm();
  1149. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  1150. m_strText += C_THREAD_OVERVIEW;
  1151. // Value here is not actually relevant; effectively used as a comment.
  1152. m_strText += _T("\" VALUE=\"Thread Status Overview Page\">\n");
  1153. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Thread Status Overview Page\">\n");
  1154. m_strText += _T("</FORM>\n");
  1155. BeginSelfAddressingForm();
  1156. InsertPasswordInForm();
  1157. m_strText += _T("<INPUT TYPE=hidden NAME=\"");
  1158. m_strText += C_FIRST;
  1159. // Value here is not actually relevant; effectively used as a comment.
  1160. m_strText += _T("\" VALUE=\"Front Page\">\n");
  1161. m_strText += _T("<INPUT TYPE=SUBMIT VALUE=\"Front Page\">\n");
  1162. m_strText += _T("</FORM>\n");
  1163. //m_strText += _T("</TABLE>\n");
  1164. ///////////////////////////////////////////////////////////////////////////////////
  1165. m_strText += _T("</body></html>\n");
  1166. }