Leaked source code of windows server 2003
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.

753 lines
22 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. ServStat.cpp
  7. The server statistics dialog
  8. FILE HISTORY:
  9. */
  10. #include <afx.h>
  11. #include "dbgutil.h"
  12. #include "stdafx.h"
  13. #include "winssnap.h"
  14. #include "server.h"
  15. #include "resource.h"
  16. #include "svrstats.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. #define INTLTIMESTR(time) (((CIntlTime)(time)).CIntlTime::operator const CString())
  23. #define TMST1(x) INTLTIMESTR((m_wrResults).WinsStat.TimeStamps.x)
  24. #define INTLNUMSTR(num) (((CIntlNumber)(num)).CIntlNumber::operator const CString())
  25. #define TCTR(x) INTLNUMSTR((m_wrResults).WinsStat.Counters.x)
  26. #define STATMUTEXNAME _T("WINSADMNGETSTATISTICS")
  27. #define WM_UPDATE_STATS WM_USER + 1099
  28. enum
  29. {
  30. SERVER_STAT_START_TIME = 0,
  31. SERVER_STAT_DB_INIT_TIME,
  32. SERVER_STAT_STAT_CLEAR_TIME,
  33. SERVER_STAT_BLANK0,
  34. SERVER_STAT_LAST_PERIODIC_REP,
  35. SERVER_STAT_LAST_ADMIN_REP,
  36. SERVER_STAT_LAST_NET_UPDATE_REP,
  37. SERVER_STAT_LAST_ADDRESS_CHANGE_REP,
  38. SERVER_STAT_BLANK1,
  39. SERVER_STAT_TOTAL_QUERIES,
  40. SERVER_STAT_SUCCESSFUL_QUERRIES,
  41. SERVER_STAT_FAILED_QUERRIES,
  42. SERVER_STAT_BLANK2,
  43. SERVER_STAT_TOTAL_RELEASES,
  44. SERVER_STAT_SUCCESSFUL_RELEASES,
  45. SERVER_STAT_FAILED_RELEASES,
  46. SERVER_STAT_BLANK3,
  47. SERVER_STAT_UNIQUE_REGISTRATIONS,
  48. SERVER_STAT_UNIQUE_CONFLICTS,
  49. SERVER_STAT_UNIQUE_RENEWALS,
  50. SERVER_STAT_BLANK4,
  51. SERVER_STAT_GROUP_REGISTRATIONS,
  52. SERVER_STAT_GROUP_CONFLICTS,
  53. SERVER_STAT_GROUP_RENEWALS,
  54. SERVER_STAT_BLANK5,
  55. SERVER_STAT_TOTAL_REG,
  56. SERVER_STAT_BLANK6,
  57. SERVER_STAT_LAST_PERIODIC_SCAV,
  58. SERVER_STAT_LAST_ADMIN_SCAV,
  59. SERVER_STAT_LAST_EXTINCTION_SCAV,
  60. SERVER_STAT_LAST_VERIFICATION_SCAV,
  61. SERVER_STAT_BLANK7,
  62. SERVER_STAT_PARTNERS_HEADER,
  63. SERVER_STAT_MAX
  64. };
  65. /*---------------------------------------------------------------------------
  66. CServerStatsFrame implementation
  67. ---------------------------------------------------------------------------*/
  68. const ContainerColumnInfo s_rgServerStatsColumnInfo[] =
  69. {
  70. { IDS_SERVER_STATS_START_TIME, 0, TRUE },
  71. { IDS_SERVER_STATS_DB_INIT_TIME, 0, TRUE },
  72. { IDS_SERVER_STATS_LAST_CLEAR_TIME, 0, TRUE },
  73. { IDS_BLANK, 0, TRUE },
  74. { IDS_SERVER_STATS_LAST_PREP, 0, TRUE },
  75. { IDS_SERVER_STATS_LAST_AREP, 0, TRUE },
  76. { IDS_SERVER_STATS_LAST_NREP, 0, TRUE },
  77. { IDS_SERVER_STATS_LAST_ACREP, 0, TRUE },
  78. { IDS_BLANK, 0, TRUE },
  79. { IDS_SERVER_STATS_TOTAL_QUERRIES, 0, TRUE },
  80. { IDS_SERVER_STATS_SUCCESSFUL, 0, TRUE },
  81. { IDS_SERVER_STATS_FAILED, 0, TRUE },
  82. { IDS_BLANK, 0, TRUE },
  83. { IDS_SERVER_STATS_TOTAL_RELEASES, 0, TRUE },
  84. { IDS_SERVER_STATS_SUCCESSFUL, 0, TRUE },
  85. { IDS_SERVER_STATS_FAILED, 0, TRUE },
  86. { IDS_BLANK, 0, TRUE },
  87. { IDS_SERVER_STATS_UNIQUE_REGISTRATIONS, 0, TRUE },
  88. { IDS_SERVER_STATS_CONFLICTS, 0, TRUE },
  89. { IDS_SERVER_STATS_RENEWALS, 0, TRUE },
  90. { IDS_BLANK, 0, TRUE },
  91. { IDS_SERVER_STATS_GROUP_REGISTRATIONS, 0, TRUE },
  92. { IDS_SERVER_STATS_CONFLICTS, 0, TRUE },
  93. { IDS_SERVER_STATS_RENEWALS, 0, TRUE },
  94. { IDS_BLANK, 0, TRUE },
  95. { IDS_SERVER_STATS_TOTAL_REGISTRATIONS, 0, TRUE },
  96. { IDS_BLANK, 0, TRUE },
  97. { IDS_SERVER_STATS_LAST_PSCAV, 0, TRUE },
  98. { IDS_SERVER_STATS_LAST_ASCAV, 0, TRUE },
  99. { IDS_SERVER_STATS_LAST_ESCAV, 0, TRUE },
  100. { IDS_SERVER_STATS_LAST_VSCAV, 0, TRUE },
  101. { IDS_BLANK, 0, TRUE },
  102. { IDS_SERVER_STATS_PARTNERS_HEADER, 0, TRUE },
  103. };
  104. UINT _cdecl
  105. RefreshStatsThread(LPVOID pParam)
  106. {
  107. DWORD dw;
  108. ThreadInfo * pInfo = (ThreadInfo *)(pParam);
  109. HANDLE hmutStatistics = NULL;
  110. HRESULT hr = hrOK;
  111. COM_PROTECT_TRY
  112. {
  113. // Open the existing mutex
  114. while (hmutStatistics == NULL)
  115. {
  116. if ((hmutStatistics = ::OpenMutex(SYNCHRONIZE, FALSE, STATMUTEXNAME)) == NULL)
  117. {
  118. ::Sleep(2000L);
  119. }
  120. }
  121. // This is where the work gets done
  122. for (;;)
  123. {
  124. pInfo->dwInterval = pInfo->pDlg->GetRefreshInterval();
  125. //::Sleep((pInfo->dwInterval)*1000);
  126. if (::WaitForSingleObject(pInfo->pDlg->m_hAbortEvent, (pInfo->dwInterval) * 1000) == WAIT_OBJECT_0)
  127. {
  128. // we're going away, lets get outta here
  129. break;
  130. }
  131. // Wait until we get the go ahead
  132. dw = ::WaitForSingleObject(hmutStatistics, INFINITE);
  133. if (dw == WAIT_OBJECT_0)
  134. {
  135. dw = pInfo->pDlg->GetStats();
  136. if (dw == ERROR_SUCCESS)
  137. {
  138. PostMessage(pInfo->pDlg->GetSafeHwnd(), WM_UPDATE_STATS, 0, 0);
  139. }
  140. ::ReleaseMutex(hmutStatistics);
  141. }
  142. }
  143. if (hmutStatistics != NULL)
  144. CloseHandle(hmutStatistics);
  145. delete pInfo;
  146. }
  147. COM_PROTECT_CATCH
  148. return 0;
  149. }
  150. /*---------------------------------------------------------------------------
  151. CServerStatsFrame::CServerStatsFrame()
  152. Constructor
  153. ---------------------------------------------------------------------------*/
  154. CServerStatsFrame::CServerStatsFrame()
  155. : StatsDialog(STATSDLG_VERTICAL|STATSDLG_CLEAR)
  156. {
  157. SetColumnInfo(s_rgServerStatsColumnInfo,
  158. DimensionOf(s_rgServerStatsColumnInfo));
  159. m_hmutStatistics = NULL;
  160. m_hAbortEvent = NULL;
  161. m_pRefreshThread = NULL;
  162. ZeroMemory(&m_wrResults, sizeof(m_wrResults));
  163. }
  164. /*---------------------------------------------------------------------------
  165. CServerStatsFrame::CServerStatsFrame()
  166. Destructor
  167. ---------------------------------------------------------------------------*/
  168. CServerStatsFrame::~CServerStatsFrame()
  169. {
  170. }
  171. BEGIN_MESSAGE_MAP(CServerStatsFrame, StatsDialog)
  172. //{{AFX_MSG_MAP(CServerStatistics)
  173. //}}AFX_MSG_MAP
  174. ON_MESSAGE(WM_NEW_STATS_AVAILABLE, OnNewStatsAvailable)
  175. ON_MESSAGE(WM_UPDATE_STATS, OnUpdateStats)
  176. ON_BN_CLICKED(IDC_STATSDLG_BTN_CLEAR, OnClear)
  177. ON_WM_DESTROY()
  178. END_MESSAGE_MAP()
  179. /*---------------------------------------------------------------------------
  180. CServerStatsFrame::CServerStatsFrame()
  181. Gets the statistics from the server handler and updates the
  182. internal variable m_wrResults
  183. ---------------------------------------------------------------------------*/
  184. HRESULT CServerStatsFrame::RefreshData(BOOL fGrabNewData)
  185. {
  186. if (fGrabNewData)
  187. {
  188. DWORD dwError = 0;
  189. BEGIN_WAIT_CURSOR;
  190. dwError = GetStats();
  191. END_WAIT_CURSOR;
  192. if (dwError != ERROR_SUCCESS)
  193. {
  194. WinsMessageBox(dwError);
  195. }
  196. else
  197. {
  198. UpdateWindow(&m_wrResults);
  199. }
  200. }
  201. return hrOK;
  202. }
  203. DWORD CServerStatsFrame::GetStats()
  204. {
  205. DWORD dwError = 0;
  206. SPITFSNode spNode;
  207. PWINSINTF_RESULTS_T pResults = NULL;
  208. CWinsServerHandler * pServer;
  209. pServer = GETHANDLER(CWinsServerHandler, m_spNode);
  210. dwError = pServer->GetStatistics(m_spNode, &pResults);
  211. if (dwError == ERROR_SUCCESS)
  212. {
  213. m_wrResults = *(pResults);
  214. }
  215. return dwError;
  216. }
  217. BOOL CServerStatsFrame::OnInitDialog()
  218. {
  219. CString st;
  220. BOOL bRet;
  221. AfxFormatString1(st, IDS_SERVER_STATS_TITLE, m_strServerAddress);
  222. SetWindowText((LPCTSTR) st);
  223. bRet = StatsDialog::OnInitDialog();
  224. // add the blank column because the replication partner stats need them
  225. m_listCtrl.InsertColumn(2, _T(" "), LVCFMT_LEFT, 100);
  226. // Set the default column widths to the width of the widest column
  227. SetColumnWidths(2 /* Number of Columns */);
  228. UpdateWindow(&m_wrResults);
  229. // set the default window size
  230. RECT rect;
  231. GetWindowRect(&rect);
  232. int nWidth = 0;
  233. for (int i = 0; i < 3; i++)
  234. {
  235. nWidth += m_listCtrl.GetColumnWidth(i);
  236. }
  237. SetWindowPos(NULL, rect.left, rect.top, nWidth + 20, SERVER_STATS_DEFAULT_HEIGHT, SWP_SHOWWINDOW);
  238. if ((m_hmutStatistics = ::CreateMutex(NULL, FALSE, STATMUTEXNAME)) == NULL)
  239. {
  240. Trace1("CServerStatsFrame::OnInitDialog() - CreateMutex failed! %lx\n", GetLastError());
  241. return FALSE;
  242. }
  243. if ((m_hAbortEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
  244. {
  245. Trace1("CServerStatsFrame::OnInitDialog() - CreateEvent failed! %lx\n", GetLastError());
  246. return FALSE;
  247. }
  248. StartRefresherThread();
  249. return bRet;
  250. }
  251. void CServerStatsFrame::Sort(UINT nColumnId)
  252. {
  253. // we don't sort any of our stats
  254. }
  255. /*---------------------------------------------------------------------------
  256. CServerStatsFrame::OnNewStatsAvailable(UINT wParam, LONG lParam)
  257. called in response to the message ON_NEW_STATS_AVAILABLE
  258. Author: EricDav
  259. ---------------------------------------------------------------------------*/
  260. afx_msg long
  261. CServerStatsFrame::OnNewStatsAvailable(UINT wParam, LONG lParam)
  262. {
  263. DWORD dwErr = GetStats();
  264. if (dwErr == ERROR_SUCCESS)
  265. {
  266. UpdateWindow(&m_wrResults);
  267. }
  268. else
  269. {
  270. WinsMessageBox(dwErr);
  271. }
  272. return 0;
  273. }
  274. /*---------------------------------------------------------------------------
  275. CServerStatsFrame::OnNewStatsAvailable(UINT wParam, LONG lParam)
  276. called in response to the message WM_UPDATE_STATS
  277. The background thread updates the stats, now we need to update
  278. the UI on the correct thread.
  279. Author: EricDav
  280. ---------------------------------------------------------------------------*/
  281. afx_msg long
  282. CServerStatsFrame::OnUpdateStats(UINT wParam, LONG lParam)
  283. {
  284. UpdateWindow(&m_wrResults);
  285. return 0;
  286. }
  287. /*---------------------------------------------------------------------------
  288. CServerStatsFrame::UpdateWindow(PWINSINTF_RESULTS_T pwrResults)
  289. Updates the contents of the dialog
  290. ---------------------------------------------------------------------------*/
  291. void
  292. CServerStatsFrame::UpdateWindow(PWINSINTF_RESULTS_T pwrResults)
  293. {
  294. SPITFSNode spNode;
  295. CWinsServerHandler * pServer;
  296. CString str;
  297. UINT i;
  298. int nTotalAddresses = 0, nTotalInUse = 0, nTotalAvailable = 0;
  299. // now fill in the data
  300. for (i = 0; i < SERVER_STAT_MAX; i++)
  301. {
  302. if (!pwrResults)
  303. str = _T("---");
  304. else
  305. {
  306. switch (i)
  307. {
  308. // server stsrt time
  309. case SERVER_STAT_START_TIME:
  310. {
  311. CTime timeStart(m_wrResults.WinsStat.TimeStamps.WinsStartTime);
  312. if(timeStart != 0)
  313. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.WinsStartTime);
  314. else
  315. str.LoadString(IDS_INVALID_TIME);
  316. }
  317. break;
  318. // database initialized time
  319. case SERVER_STAT_DB_INIT_TIME:
  320. {
  321. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastInitDbTime);
  322. if(timeStart != 0)
  323. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastInitDbTime);
  324. else
  325. str.LoadString(IDS_INVALID_TIME);
  326. }
  327. break;
  328. // statistics last cleared time
  329. case SERVER_STAT_STAT_CLEAR_TIME:
  330. {
  331. CTime timeStart(m_wrResults.WinsStat.TimeStamps.CounterResetTime);
  332. if(timeStart != 0)
  333. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.CounterResetTime);
  334. else
  335. str.LoadString(IDS_INVALID_TIME);
  336. }
  337. break;
  338. // some blank lines in between
  339. case SERVER_STAT_BLANK0:
  340. case SERVER_STAT_BLANK1:
  341. case SERVER_STAT_BLANK2:
  342. case SERVER_STAT_BLANK3:
  343. case SERVER_STAT_BLANK4:
  344. case SERVER_STAT_BLANK5:
  345. case SERVER_STAT_BLANK6:
  346. case SERVER_STAT_BLANK7:
  347. str = _T("");
  348. break;
  349. case SERVER_STAT_LAST_PERIODIC_REP:
  350. {
  351. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastPRplTime);
  352. if(timeStart != 0)
  353. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastPRplTime);
  354. else
  355. str.LoadString(IDS_INVALID_TIME);
  356. }
  357. break;
  358. case SERVER_STAT_LAST_ADMIN_REP:
  359. {
  360. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastATRplTime);
  361. if(timeStart != 0)
  362. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastATRplTime);
  363. else
  364. str.LoadString(IDS_INVALID_TIME);
  365. }
  366. break;
  367. case SERVER_STAT_LAST_NET_UPDATE_REP:
  368. {
  369. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastNTRplTime);
  370. if(timeStart != 0)
  371. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastNTRplTime);
  372. else
  373. str.LoadString(IDS_INVALID_TIME);
  374. }
  375. break;
  376. // last address changed time
  377. case SERVER_STAT_LAST_ADDRESS_CHANGE_REP:
  378. {
  379. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastACTRplTime);
  380. if(timeStart != 0)
  381. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastACTRplTime);
  382. else
  383. str.LoadString(IDS_INVALID_TIME);
  384. }
  385. break;
  386. // total queries received
  387. case SERVER_STAT_TOTAL_QUERIES:
  388. str = TCTR(NoOfQueries);
  389. break;
  390. // successful queries
  391. case SERVER_STAT_SUCCESSFUL_QUERRIES:
  392. str = TCTR(NoOfSuccQueries);
  393. break;
  394. // Queries that failed
  395. case SERVER_STAT_FAILED_QUERRIES:
  396. str = TCTR(NoOfFailQueries);
  397. break;
  398. case SERVER_STAT_TOTAL_RELEASES:
  399. str = TCTR(NoOfRel);
  400. break;
  401. case SERVER_STAT_SUCCESSFUL_RELEASES:
  402. str = TCTR(NoOfSuccRel);
  403. break;
  404. case SERVER_STAT_FAILED_RELEASES:
  405. str = TCTR(NoOfFailRel);
  406. break;
  407. // unique registrations
  408. case SERVER_STAT_UNIQUE_REGISTRATIONS:
  409. str = TCTR(NoOfUniqueReg);
  410. break;
  411. case SERVER_STAT_UNIQUE_CONFLICTS:
  412. str = TCTR(NoOfUniqueCnf);
  413. break;
  414. case SERVER_STAT_UNIQUE_RENEWALS:
  415. str = TCTR(NoOfUniqueRef);
  416. break;
  417. // group registrations
  418. case SERVER_STAT_GROUP_REGISTRATIONS:
  419. str = TCTR(NoOfGroupReg);
  420. break;
  421. case SERVER_STAT_GROUP_CONFLICTS:
  422. str = TCTR(NoOfGroupCnf);
  423. break;
  424. case SERVER_STAT_GROUP_RENEWALS:
  425. str = TCTR(NoOfGroupRef);
  426. break;
  427. // total registrations
  428. case SERVER_STAT_TOTAL_REG:
  429. str = INTLNUMSTR(m_wrResults.WinsStat.Counters.NoOfGroupReg +
  430. m_wrResults.WinsStat.Counters.NoOfUniqueReg);
  431. break;
  432. case SERVER_STAT_LAST_PERIODIC_SCAV:
  433. {
  434. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastPScvTime);
  435. if(timeStart != 0)
  436. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastPScvTime);
  437. else
  438. str.LoadString(IDS_INVALID_TIME);
  439. }
  440. break;
  441. case SERVER_STAT_LAST_ADMIN_SCAV:
  442. {
  443. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastATScvTime);
  444. if(timeStart != 0)
  445. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastATScvTime);
  446. else
  447. str.LoadString(IDS_INVALID_TIME);
  448. }
  449. break;
  450. case SERVER_STAT_LAST_EXTINCTION_SCAV:
  451. {
  452. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastTombScvTime);
  453. if(timeStart != 0)
  454. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastTombScvTime);
  455. else
  456. str.LoadString(IDS_INVALID_TIME);
  457. }
  458. break;
  459. case SERVER_STAT_LAST_VERIFICATION_SCAV:
  460. {
  461. CTime timeStart(m_wrResults.WinsStat.TimeStamps.LastVerifyScvTime);
  462. if(timeStart != 0)
  463. FormatDateTime(str, &m_wrResults.WinsStat.TimeStamps.LastVerifyScvTime);
  464. else
  465. str.LoadString(IDS_INVALID_TIME);
  466. }
  467. break;
  468. case SERVER_STAT_PARTNERS_HEADER:
  469. {
  470. str.LoadString(IDS_SERVER_STATS_NO_OF_FAILED);
  471. m_listCtrl.SetItemText(i, 2, (LPCTSTR) str);
  472. str.LoadString(IDS_SERVER_STATS_NO_OF_REPLS);
  473. }
  474. break;
  475. default:
  476. Assert("Invalid server statistic type!");
  477. break;
  478. }
  479. }
  480. // now the string is set, display in the dlg
  481. m_listCtrl.SetItemText(i, 1, (LPCTSTR) str);
  482. }
  483. UpdatePartnerStats();
  484. }
  485. /*---------------------------------------------------------------------------
  486. CServerStatsFrame::StartRefresherThread()
  487. Starts the refresher thread, called as soon as the dilog is
  488. brought up
  489. ---------------------------------------------------------------------------*/
  490. void
  491. CServerStatsFrame::StartRefresherThread()
  492. {
  493. ThreadInfo *info = new ThreadInfo;
  494. CWinsServerHandler * pServer;
  495. pServer = GETHANDLER(CWinsServerHandler, m_spNode);
  496. info->dwInterval = pServer->m_dwRefreshInterval;
  497. info->pDlg = this;
  498. m_pRefreshThread = ::AfxBeginThread(RefreshStatsThread, info);
  499. if (m_pRefreshThread == NULL)
  500. {
  501. Trace0("Failed to create thread\n");
  502. m_pRefreshThread = NULL;
  503. return;
  504. }
  505. Trace0("Auto refresh thread succesfully started\n");
  506. }
  507. /*---------------------------------------------------------------------------
  508. CServerStatsFrame::ReInitRefresherThread()
  509. If the refresher thread was running, re-start it. It is needed
  510. in order to pick on the fly the new refresh intervals
  511. ---------------------------------------------------------------------------*/
  512. void
  513. CServerStatsFrame::ReInitRefresherThread()
  514. {
  515. // if there is a refresher thread, just restart it
  516. if (m_pRefreshThread != NULL)
  517. {
  518. KillRefresherThread();
  519. StartRefresherThread();
  520. }
  521. }
  522. /*---------------------------------------------------------------------------
  523. CServerStatsFrame::KillRefresherThread()
  524. Kills the refresh data thread, caled when the dlg is destroyed
  525. ---------------------------------------------------------------------------*/
  526. void
  527. CServerStatsFrame::KillRefresherThread()
  528. {
  529. //
  530. // Kill refresher thread if necessary.
  531. //
  532. if (m_pRefreshThread == NULL)
  533. {
  534. //
  535. // No thread running
  536. //
  537. return;
  538. }
  539. //::TerminateThread(m_pRefreshThread->m_hThread, 0);
  540. //::CloseHandle(m_pRefreshThread->m_hThread);
  541. ::SetEvent(m_hAbortEvent);
  542. ::WaitForSingleObject(m_pRefreshThread->m_hThread, 5000);
  543. m_pRefreshThread = NULL;
  544. }
  545. /*---------------------------------------------------------------------------
  546. CServerStatsFrame::OnDestroy( )
  547. Message Handler
  548. ---------------------------------------------------------------------------*/
  549. void
  550. CServerStatsFrame::OnDestroy( )
  551. {
  552. KillRefresherThread();
  553. if (m_hmutStatistics)
  554. {
  555. ::CloseHandle(m_hmutStatistics);
  556. m_hmutStatistics = NULL;
  557. }
  558. if (m_hAbortEvent)
  559. {
  560. ::CloseHandle(m_hAbortEvent);
  561. m_hAbortEvent = NULL;
  562. }
  563. }
  564. /*---------------------------------------------------------------------------
  565. CServerStatsFrame::GetRefreshInterval()
  566. Returns the refresh interval, stored in the server handler
  567. ---------------------------------------------------------------------------*/
  568. DWORD
  569. CServerStatsFrame::GetRefreshInterval()
  570. {
  571. CWinsServerHandler * pServer;
  572. pServer = GETHANDLER(CWinsServerHandler, m_spNode);
  573. return pServer->m_dwRefreshInterval;
  574. }
  575. /*---------------------------------------------------------------------------
  576. CServerStatsFrame::OnClear()
  577. Calls the wins api to reset counters and updates data, in response to
  578. click of the clear button
  579. ---------------------------------------------------------------------------*/
  580. void
  581. CServerStatsFrame::OnClear()
  582. {
  583. DWORD dwErr = ERROR_SUCCESS;
  584. CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, m_spNode);
  585. // clear the ststistics
  586. BEGIN_WAIT_CURSOR
  587. dwErr = pServer->ClearStatistics(m_spNode);
  588. END_WAIT_CURSOR
  589. if (dwErr == ERROR_SUCCESS)
  590. {
  591. // refresh the data now
  592. RefreshData(TRUE);
  593. UpdateWindow(&m_wrResults);
  594. }
  595. else
  596. {
  597. WinsMessageBox(dwErr);
  598. }
  599. }
  600. /*---------------------------------------------------------------------------
  601. CServerStatsFrame::UpdatePartnerStats()
  602. ---------------------------------------------------------------------------*/
  603. void
  604. CServerStatsFrame::UpdatePartnerStats()
  605. {
  606. UINT i, uCount;
  607. CString strText;
  608. // first remove all old partner info
  609. uCount = m_listCtrl.GetItemCount();
  610. for (i = 0; i < (uCount - SERVER_STAT_MAX); i++)
  611. {
  612. m_listCtrl.DeleteItem(SERVER_STAT_MAX);
  613. }
  614. int nPartner = 0;
  615. // now add all of the partner information in
  616. for (i = SERVER_STAT_MAX; i < SERVER_STAT_MAX + m_wrResults.WinsStat.NoOfPnrs; i++)
  617. {
  618. m_listCtrl.InsertItem(i, _T(""));
  619. // ip address
  620. ::MakeIPAddress(m_wrResults.WinsStat.pRplPnrs[nPartner].Add.IPAdd, strText);
  621. m_listCtrl.SetItemText(i, 0, strText);
  622. // replication count
  623. strText.Format(_T("%d"), m_wrResults.WinsStat.pRplPnrs[nPartner].NoOfRpls);
  624. m_listCtrl.SetItemText(i, 1, strText);
  625. // failed count
  626. strText.Format(_T("%d"), m_wrResults.WinsStat.pRplPnrs[nPartner].NoOfCommFails);
  627. m_listCtrl.SetItemText(i, 2, strText);
  628. nPartner++;
  629. }
  630. }