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.

3314 lines
108 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. nmsscv.c
  5. Abstract:
  6. This module contains functions that implement the functionality
  7. associated with scavenging
  8. Functions:
  9. NmsScvInit,
  10. ScvThdInitFn,
  11. DoScavenging
  12. ReconfigScv
  13. Portability:
  14. This module is portable
  15. Author:
  16. Pradeep Bahl (PradeepB) Apr-1993
  17. Revision History:
  18. Modification date Person Description of modification
  19. ----------------- ------- ----------------------------
  20. --*/
  21. /*
  22. * Includes
  23. */
  24. #include <time.h>
  25. #include "wins.h"
  26. #include "winsevt.h"
  27. #include "nms.h"
  28. #include "nmsnmh.h"
  29. #include "winsmsc.h"
  30. #include "winsdbg.h"
  31. #include "winsthd.h"
  32. #include "winscnf.h"
  33. #include "nmsdb.h"
  34. #include "winsque.h"
  35. #include "nmsscv.h"
  36. #include "rpl.h"
  37. #include "rplpull.h"
  38. #include "rplmsgf.h"
  39. #include "comm.h"
  40. #include "winsintf.h"
  41. #include "winstmm.h"
  42. #ifdef WINSDBG
  43. #define SCV_EVT_NM TEXT("ScvEvtNm")
  44. #else
  45. #define SCV_EVT_NM NULL
  46. #endif
  47. //
  48. // The no. of retries and the time interval (in secs) between each retry
  49. // when trying to establish comm. with a WINS for the purpose of verifying
  50. // old active replicas in the local db
  51. //
  52. #define VERIFY_NO_OF_RETRIES 0 //0 retries
  53. #define VERIFY_RETRY_TIME_INTERVAL 30 //30 secs
  54. //
  55. // We get rid of extraneous log files every 3 hours.
  56. //
  57. FUTURES("Use symbols for times - defined in winscnf.h")
  58. #define ONE_HOUR 3600
  59. #define THREE_HOURS 10800
  60. #define TWENTY_FOUR_HOURS (3600 * 24)
  61. #define THREE_DAYS (TWENTY_FOUR_HOURS * 3)
  62. #define PERIOD_OF_LOG_DEL THREE_HOURS
  63. #define PERIOD_OF_BACKUP TWENTY_FOUR_HOURS
  64. #define LOG_SCV_MUL_OF_REF_INTVL 6
  65. /*
  66. * Local Macro Declarations
  67. */
  68. //
  69. // macro to set the state of a record in an in-memory data structure to
  70. // that specified as an arg. if it has timed out. We check whether
  71. // CurrTime is greater than pRec Timestamp before doing the other if test
  72. // because these numbers otherwise the subtraction will produce a positive
  73. // number even if current time is older than the timestamp (say the date
  74. // on the pc was changed)
  75. //
  76. #define SET_STATE_IF_REQD_M(pRec, CurrentTime, TimeInterval, State, Cntr) \
  77. { \
  78. pRec->fScv = FALSE; \
  79. if (CurrentTime >= (time_t)(pRec)->TimeStamp) \
  80. { \
  81. NMSDB_SET_STATE_M( \
  82. (pRec)->Flag, \
  83. (State) \
  84. ); \
  85. (pRec)->NewTimeStamp = (pRec)->TimeStamp + \
  86. TimeInterval; \
  87. (pRec)->fScv = TRUE; \
  88. NoOfRecsScv++; \
  89. (Cntr)++; \
  90. } \
  91. }
  92. #define DO_SCV_EVT_NM TEXT("WinsDoScvEvt")
  93. /*
  94. * Local Typedef Declarations
  95. */
  96. /*
  97. * Global Variable Definitions
  98. */
  99. HANDLE NmsScvDoScvEvtHdl;//event signaled to initiate scavenging
  100. //
  101. // The min. version number to start scavenging from (for local records)
  102. //
  103. VERS_NO_T NmsScvMinScvVersNo;
  104. volatile BOOL fNmsScvThdOutOfReck;
  105. DWORD sMcastIntvl;
  106. /*
  107. * Local Variable Definitions
  108. */
  109. FUTURES("Put all these in a structure and allocate it. Initialize sBootTime")
  110. FUTURES("in nms.c")
  111. STATIC time_t sBootTime; //Boot Time
  112. STATIC time_t sLastRefTime; //Last time we looked for active
  113. // entries
  114. STATIC time_t sLastVerifyTime; //Last time we looked for replicais
  115. STATIC time_t sLastFullVerifyTime; //Last time we did full validation
  116. STATIC time_t sLastAdminScvTime; //Last time admin. did scavenging
  117. STATIC time_t sLastTombTime; //Last time we looked for replica
  118. // tombstones
  119. STATIC BOOL sfAdminForcedScv; //set to TRUE if the administrator
  120. //forces scavenging
  121. STATIC time_t sLastDbNullBackupTime;//Last time we deleted extraneous
  122. //log files
  123. STATIC time_t sLastDbBackupTime; //Last time we last did full backup
  124. #if MCAST > 0
  125. STATIC time_t sLastMcastTime; //Last time we last did full backup
  126. #endif
  127. /*
  128. * Local Function Prototype Declarations
  129. */
  130. STATIC
  131. STATUS
  132. DoScavenging(
  133. PNMSSCV_PARAM_T pScvParam,
  134. BOOL fSignaled,
  135. LPBOOL pfResetTimer,
  136. LPBOOL pfSpTimeOver
  137. );
  138. STATIC
  139. DWORD
  140. ScvThdInitFn(
  141. IN LPVOID pThdParam
  142. );
  143. STATIC
  144. VOID
  145. ReconfigScv(
  146. PNMSSCV_PARAM_T pScvParam
  147. );
  148. STATIC
  149. VOID
  150. UpdDb(
  151. IN PNMSSCV_PARAM_T pScvParam,
  152. IN PRPL_REC_ENTRY_T pStartBuff,
  153. IN DWORD NoOfRecs,
  154. IN DWORD NoOfRecsToUpd
  155. );
  156. STATIC
  157. STATUS
  158. VerifyDbData(
  159. PNMSSCV_PARAM_T pScvParam,
  160. time_t CurrentTime,
  161. DWORD Age,
  162. BOOL fForce,
  163. BOOL fPeriodicCC
  164. );
  165. STATIC
  166. STATUS
  167. PickWinsToUse(
  168. IN PCOMM_ADD_T pVerifyWinsAdd,
  169. IN PCOMM_ADD_T pOwnerWinsAdd,
  170. IN BOOL fUseRplPnr,
  171. OUT LPBOOL pfNonOwnerPnr,
  172. OUT LPBOOL pRplType
  173. );
  174. STATIC
  175. STATUS
  176. EstablishCommForVerify(
  177. PCOMM_ADD_T pWinsAdd,
  178. PCOMM_HDL_T pDlgHdl
  179. );
  180. STATIC
  181. VOID
  182. PullAndUpdateDb(
  183. PCOMM_HDL_T pDlgHdl,
  184. PCOMM_ADD_T pWinsAdd,
  185. PRPL_REC_ENTRY_T pRspBuff,
  186. DWORD WinsIndex,
  187. VERS_NO_T MinVersNo,
  188. VERS_NO_T MaxVersNo,
  189. DWORD RplType,
  190. DWORD NoOfLocalRecs,
  191. time_t CurrentTime,
  192. PNMSSCV_PARAM_T pScvParam,
  193. BOOL fNonOwnerPnr,
  194. LPDWORD pTotNoOfPulledRecs
  195. );
  196. STATIC
  197. __inline
  198. VOID
  199. FreeDbMemory(
  200. LPVOID pStartBuff,
  201. DWORD NoOfLocalDbRecs,
  202. PWINSTHD_TLS_T pTls
  203. );
  204. STATIC
  205. VOID
  206. ChkConfNUpd(
  207. #if SUPPORT612WINS > 0
  208. IN PCOMM_HDL_T pDlgHdl,
  209. #endif
  210. IN PCOMM_ADD_T pOwnerWinsAdd,
  211. IN DWORD RplType,
  212. IN DWORD OwnerId,
  213. IN PRPL_REC_ENTRY_T *ppLocalDbRecs,
  214. IN LPBYTE pPulledRecs,
  215. IN DWORD *pNoOfLocalDbRecs,
  216. IN time_t CurrentTime,
  217. IN DWORD VerifyTimeIntvl,
  218. IN BOOL fNonOwnerPnr,
  219. OUT LPDWORD pNoOfPulledRecs,
  220. OUT PVERS_NO_T pMaxVersNo
  221. );
  222. STATIC
  223. VOID
  224. CompareWithLocalRecs(
  225. IN VERS_NO_T VersNo,
  226. IN LPBYTE pName,
  227. IN NMSDB_ENTRY_STATE_E RecState_e,
  228. IN OUT PRPL_REC_ENTRY_T *ppLocalDbRecs,
  229. IN OUT DWORD *pNoOfLocalRecs,
  230. IN time_t CurrentTime,
  231. IN BOOL fNonOwnerPnr,
  232. IN OUT DWORD *pNoOfRecsDel,
  233. OUT PNMSSCV_REC_ACTION_E pRecAction_e
  234. );
  235. STATIC
  236. VOID
  237. DoBackup(
  238. PNMSSCV_PARAM_T pScvParam,
  239. LPBOOL pfThdPrNormal
  240. );
  241. #if MCAST > 0
  242. VOID
  243. DoMcastSend(
  244. DWORD_PTR CurrentTime,
  245. DWORD Code,
  246. DWORD fNow
  247. );
  248. #endif
  249. //
  250. // function definitions start here
  251. //
  252. VOID
  253. NmsScvInit(
  254. VOID
  255. )
  256. /*++
  257. Routine Description:
  258. This function is called to initialize the scavenger thread
  259. Arguments:
  260. None
  261. Externals Used:
  262. None
  263. Return Value:
  264. None
  265. Error Handling:
  266. Called by:
  267. Side Effects:
  268. Comments:
  269. None
  270. --*/
  271. {
  272. //
  273. // Create the event handle signaled when scavenging has to be
  274. // initiated. This event is signaled by an RPC thread
  275. // to start scavenging
  276. //
  277. WinsMscCreateEvt(
  278. DO_SCV_EVT_NM,
  279. FALSE, //auto-reset
  280. &NmsScvDoScvEvtHdl
  281. );
  282. //
  283. // initialize sLastTombTime (used for determining if we need to look for
  284. // tombstones of replicas) and sLastVerifyTime to current time.
  285. // Don't forget RefreshTime
  286. //
  287. (void)time(&sBootTime);
  288. sLastVerifyTime = //fall through
  289. sLastTombTime = //fall through
  290. sLastFullVerifyTime = //fall through
  291. sLastAdminScvTime = //fall through
  292. sLastRefTime = sBootTime;
  293. //
  294. // Initialize the queue used by the scavenger thread
  295. //
  296. WinsQueInit(TEXT("NmsScvEvt"), &QueWinsScvQueHd);
  297. //
  298. // Create the Scavenger thread
  299. //
  300. WinsThdPool.ScvThds[0].ThdHdl = WinsMscCreateThd(
  301. ScvThdInitFn,
  302. NULL,
  303. &WinsThdPool.ScvThds[0].ThdId
  304. );
  305. //
  306. // Init WinsThdPool properly
  307. //
  308. WinsThdPool.ScvThds[0].fTaken = TRUE;
  309. WinsThdPool.ThdCount++;
  310. return;
  311. }
  312. VOID
  313. GetIntervalToDefSpTime(
  314. LPDWORD pTimeInt
  315. )
  316. /*++
  317. Routine Description:
  318. This function finds the time interval in seconds upto the Default Specific
  319. time.
  320. Arguments:
  321. OUT pTimeInt - Time Interval in seconds
  322. Externals Used:
  323. None
  324. Return Value:
  325. Success status codes --
  326. Error status codes --
  327. Error Handling:
  328. Called by:
  329. Side Effects:
  330. Comments:
  331. None
  332. --*/
  333. {
  334. SYSTEMTIME CurrTime;
  335. GetSystemTime(&CurrTime);
  336. //
  337. // If default time hour is greater then current hour, add 3600
  338. // for the number of hours it is ahead. Then subtract the the
  339. // number of minutes and seconds in the current time
  340. //
  341. if (WINSCNF_DEF_CC_SP_HR > CurrTime.wHour)
  342. {
  343. *pTimeInt = (WINSCNF_DEF_CC_SP_HR - CurrTime.wHour) * 3600;
  344. *pTimeInt -= ((CurrTime.wMinute * 60) + (CurrTime.wSecond));
  345. }
  346. else //default hour is same or less than current hour
  347. {
  348. *pTimeInt = (CurrTime.wHour - WINSCNF_DEF_CC_SP_HR) * 3600;
  349. *pTimeInt += (CurrTime.wMinute * 60) + (CurrTime.wSecond);
  350. }
  351. return;
  352. }
  353. DWORD
  354. ScvThdInitFn(
  355. IN LPVOID pThdParam
  356. )
  357. /*++
  358. Routine Description:
  359. This function is the initialization function for the scavenger
  360. thread
  361. Arguments:
  362. pThdParam - Not used
  363. Externals Used:
  364. None
  365. Return Value:
  366. Success status codes -- should never return
  367. Error status codes -- WINS_FAILURE
  368. Error Handling:
  369. Called by:
  370. Side Effects:
  371. Comments:
  372. None
  373. --*/
  374. {
  375. BOOL fSignaled = FALSE;
  376. HANDLE ThdEvtArr[3];
  377. DWORD IndexOfHdlSignaled;
  378. NMSSCV_PARAM_T ScvParam;
  379. DWORD SleepTime;
  380. time_t CurrentTime;
  381. BOOL fThdPrNormal;
  382. DWORD TimeInt;
  383. QUE_SCV_REQ_WRK_ITM_T WrkItm;
  384. BOOL fResetTimer = TRUE;
  385. time_t AbsTime;
  386. time_t LastCC;
  387. BOOL fTimerRunning = FALSE;
  388. BOOL fSpTimeOver = FALSE;
  389. UNREFERENCED_PARAMETER(pThdParam);
  390. ThdEvtArr[0] = NmsTermEvt;
  391. ThdEvtArr[1] = WinsCnf.CnfChgEvtHdl;
  392. ThdEvtArr[2] = QueWinsScvQueHd.EvtHdl;
  393. try {
  394. /*
  395. Initialize the thread with the database
  396. */
  397. NmsDbThdInit(WINS_E_NMSSCV);
  398. DBGMYNAME("Scavenger Thread");
  399. //
  400. // get the scavenging parameters from the configuration structure.
  401. // Note; There is no need for any synchronization here since
  402. // we are executing in the main thread (process is initalizing
  403. // at invocation).
  404. //
  405. ScvParam.ScvChunk = WinsCnf.ScvChunk;
  406. ScvParam.RefreshInterval = WinsCnf.RefreshInterval;
  407. ScvParam.TombstoneInterval = WinsCnf.TombstoneInterval;
  408. ScvParam.TombstoneTimeout = WinsCnf.TombstoneTimeout;
  409. ScvParam.VerifyInterval = WinsCnf.VerifyInterval;
  410. ScvParam.PrLvl = WinsCnf.ScvThdPriorityLvl;
  411. //
  412. // Load up the CC parameters
  413. //
  414. ScvParam.CC.TimeInt = WinsCnf.CC.TimeInt;
  415. ScvParam.CC.fSpTime = WinsCnf.CC.fSpTime;
  416. ScvParam.CC.SpTimeInt = WinsCnf.CC.SpTimeInt;
  417. ScvParam.CC.MaxRecsAAT = WinsCnf.CC.MaxRecsAAT;
  418. ScvParam.CC.fUseRplPnrs = WinsCnf.CC.fUseRplPnrs;
  419. sMcastIntvl = WinsCnf.McastIntvl;
  420. //
  421. // if backup path is not NULL, copy it into ScvParam structure
  422. //
  423. if (WinsCnf.pBackupDirPath != NULL)
  424. {
  425. (VOID)strcpy(ScvParam.BackupDirPath, WinsCnf.pBackupDirPath);
  426. }
  427. else
  428. {
  429. ScvParam.BackupDirPath[0] = EOS;
  430. }
  431. //
  432. // Use a stack variable WrkItm. Schedule it with the timer thread
  433. // if required (will happen only if the CC key is present).
  434. //
  435. FUTURES("Set two work items - for two timer requests. One to fire off at a")
  436. FUTURES("specific time. The other one for the time interval")
  437. WrkItm.Opcode_e = WINSINTF_E_VERIFY_SCV; //verify replicas
  438. WrkItm.Age = 0; //no matter how recent
  439. WrkItm.fForce = TRUE; //force verification even if
  440. //we did it recently
  441. LOOP:
  442. try {
  443. while (TRUE)
  444. {
  445. sfAdminForcedScv = FALSE;
  446. SleepTime = min(min(sMcastIntvl, ScvParam.RefreshInterval),
  447. PERIOD_OF_LOG_DEL);
  448. if (fResetTimer)
  449. {
  450. if (fTimerRunning)
  451. {
  452. //
  453. // Delete the old timer request. This should
  454. // deallocate it
  455. //
  456. DBGPRINT0(SCV, "ScvThdInit: Deleting Timer requests\n");
  457. WinsTmmDeleteReqs(WINS_E_NMSSCV);
  458. fTimerRunning = FALSE;
  459. }
  460. //
  461. // If the time interval for CC is not MAXULONG, it means
  462. // user wants CC to be done. TimeInt will be MAXULONG if
  463. // there is no Wins\Paramaters\CC key in the registry
  464. //
  465. if (ScvParam.CC.TimeInt != MAXULONG)
  466. {
  467. //
  468. // if no specific time was indicated, use default (2 am).
  469. //
  470. if (!fSpTimeOver)
  471. {
  472. if (!ScvParam.CC.fSpTime)
  473. {
  474. //
  475. // Get the current hour. Schedule a wakeup at exact
  476. // 2 am.
  477. //
  478. GetIntervalToDefSpTime(&TimeInt);
  479. }
  480. else
  481. {
  482. TimeInt = ScvParam.CC.SpTimeInt;
  483. }
  484. }
  485. else
  486. {
  487. TimeInt = ScvParam.CC.TimeInt;
  488. }
  489. DBGPRINT1(SCV, "ScvThdInit: TimeInt is (%d)\n", TimeInt);
  490. // Insert a timer request. Let the Timer thread create
  491. // a work item for it.
  492. //
  493. (VOID)time(&AbsTime);
  494. if( !fSpTimeOver )
  495. {
  496. AbsTime += (time_t)TimeInt;
  497. LastCC = AbsTime;
  498. }
  499. else
  500. {
  501. do
  502. {
  503. LastCC += (time_t)TimeInt;
  504. }
  505. while( LastCC <= (AbsTime + WINSCNF_MIN_VALID_INTER_CC_INTVL));
  506. AbsTime = LastCC;
  507. }
  508. WinsTmmInsertEntry(
  509. NULL,
  510. WINS_E_NMSSCV,
  511. QUE_E_CMD_SET_TIMER,
  512. FALSE, //not used presently
  513. AbsTime,
  514. TimeInt,
  515. &QueWinsScvQueHd,
  516. &WrkItm,
  517. 0,
  518. NULL
  519. );
  520. fTimerRunning = TRUE;
  521. fResetTimer = FALSE;
  522. }
  523. }
  524. //
  525. // Do a timed wait until signaled for termination
  526. //
  527. // Multiply the sleep time by 1000 since WinsMscWaitTimed
  528. // function expects the time interval in msecs.
  529. //
  530. #ifdef WINSDBG
  531. {
  532. time_t ltime;
  533. (VOID)time(&ltime);
  534. DBGPRINT2(SCV, "ScvThdInitFn: Sleeping for (%d) secs. Last scavenging took = (%d secs)\n", SleepTime, ltime - CurrentTime);
  535. }
  536. #endif
  537. WinsMscWaitTimedUntilSignaled(
  538. ThdEvtArr,
  539. sizeof(ThdEvtArr)/sizeof(HANDLE),
  540. &IndexOfHdlSignaled,
  541. SleepTime * 1000,
  542. &fSignaled
  543. );
  544. //
  545. // We can be signaled for termination, configuration change,
  546. // by the admin to do general or specific scavenging or by
  547. // the timer thread
  548. //
  549. if (fSignaled)
  550. {
  551. if (IndexOfHdlSignaled == 0)
  552. {
  553. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  554. }
  555. else
  556. {
  557. if (IndexOfHdlSignaled == 1)
  558. {
  559. ReconfigScv(&ScvParam);
  560. //
  561. // Reset the timer
  562. //
  563. fResetTimer = TRUE;
  564. continue;
  565. }
  566. //
  567. // else, this must be the signal to initiate scavenging
  568. // (by the admin. or the timer thread)
  569. //
  570. sfAdminForcedScv = TRUE;
  571. }
  572. }
  573. //
  574. // Get the current time and check if we need to do scavenging
  575. //
  576. (void)time(&CurrentTime);
  577. if (
  578. ( (CurrentTime > sLastRefTime)
  579. &&
  580. ((CurrentTime - sLastRefTime) >= (time_t)ScvParam.RefreshInterval))
  581. ||
  582. sfAdminForcedScv
  583. )
  584. {
  585. //
  586. // Do scavenging
  587. //
  588. NmsDbOpenTables(WINS_E_NMSSCV);
  589. //DBGPRINT0(ERR, "SCVTHDINITFN: OPENED tables\n");
  590. (VOID)DoScavenging(&ScvParam, fSignaled, &fResetTimer, &fSpTimeOver);
  591. NmsDbCloseTables();
  592. //DBGPRINT0(ERR, "SCVTHDINITFN: CLOSED tables\n");
  593. fTimerRunning = !fResetTimer;
  594. }
  595. //
  596. // If enough time has expired to warrant a purging of old log
  597. // files, do it (check done in DoBackup). We don't do this
  598. // on an admin. trigger since it may take long.
  599. //
  600. if (!sfAdminForcedScv)
  601. {
  602. #if MCAST > 0
  603. DoMcastSend(CurrentTime, COMM_MCAST_WINS_UP, FALSE);
  604. #endif
  605. fThdPrNormal = TRUE;
  606. DoBackup(&ScvParam, &fThdPrNormal);
  607. }
  608. } // end of while (TRUE)
  609. } //end of inner try {..}
  610. except(EXCEPTION_EXECUTE_HANDLER) {
  611. DBGPRINTEXC("ScvThdInit");
  612. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_SCV_EXC);
  613. }
  614. goto LOOP;
  615. } //end of outer try {..}
  616. except(EXCEPTION_EXECUTE_HANDLER) {
  617. DBGPRINTEXC("ScvThdInit");
  618. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_SCV_EXC);
  619. //
  620. // Let us terminate the thread gracefully
  621. //
  622. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  623. }
  624. //
  625. // We should never get here
  626. //
  627. return(WINS_FAILURE);
  628. }
  629. STATUS
  630. DoScavenging(
  631. PNMSSCV_PARAM_T pScvParam,
  632. BOOL fSignaled,
  633. LPBOOL pfResetTimer,
  634. LPBOOL pfSpTimeOver
  635. )
  636. /*++
  637. Routine Description:
  638. This function is responsible for doing all scavenging
  639. Arguments:
  640. None
  641. Externals Used:
  642. None
  643. Return Value:
  644. None
  645. Error Handling:
  646. Called by:
  647. ScvThdInitFn()
  648. Side Effects:
  649. Comments:
  650. None
  651. --*/
  652. {
  653. PRPL_REC_ENTRY_T pStartBuff;
  654. PRPL_REC_ENTRY_T pRec;
  655. DWORD BuffLen;
  656. DWORD NoOfRecs = 0;
  657. time_t CurrentTime;
  658. DWORD NoOfRecsScv; //no of records whose state has
  659. //been affected
  660. DWORD TotNoOfRecsScv = 0; //Total no of records
  661. //whose state has
  662. //been affected
  663. VERS_NO_T MyMaxVersNo;
  664. DWORD i; //for loop counter
  665. DWORD RecCnt;
  666. LARGE_INTEGER n; //for loop counter
  667. LARGE_INTEGER Tmp;
  668. DWORD State; //stores state of a record
  669. VERS_NO_T VersNoLimit;
  670. DWORD NoOfRecChgToRelSt = 0;
  671. DWORD NoOfRecChgToTombSt = 0;
  672. DWORD NoOfRecToDel = 0;
  673. DWORD MaxNoOfRecsReqd = 0;
  674. BOOL fLastEntryDel = FALSE;
  675. PWINSTHD_TLS_T pTls;
  676. PRPL_REC_ENTRY_T pTmp;
  677. BOOL fRecsExistent = FALSE;
  678. VERS_NO_T MinScvVersNo;
  679. #ifdef WINSDBG
  680. DWORD SectionCount = 0;
  681. #endif
  682. PQUE_SCV_REQ_WRK_ITM_T pScvWrkItm;
  683. PQUE_SCV_REQ_WRK_ITM_T pClientWrkItm;
  684. PQUE_TMM_REQ_WRK_ITM_T pTmmWrkItm;
  685. QUE_SCV_OPC_E Opcode_e;
  686. DWORD Age;
  687. STATUS RetStat;
  688. BOOL fForce;
  689. BOOL fPeriodicCC = FALSE;
  690. DBGENTER("DoScavenging\n");
  691. *pfResetTimer = FALSE;
  692. while (TRUE)
  693. {
  694. try {
  695. if (fSignaled)
  696. {
  697. RetStat = QueRemoveScvWrkItm((LPVOID *)&pScvWrkItm);
  698. if (RetStat == WINS_NO_REQ)
  699. {
  700. break;
  701. }
  702. else
  703. {
  704. //
  705. // If we got signaled by the timer thread, get the pointer
  706. // to the local WrkItm of ScvThdInitFn()
  707. //
  708. if (pScvWrkItm->CmdTyp_e == QUE_E_CMD_TIMER_EXPIRED)
  709. {
  710. DBGPRINT0(SCV, "DoScavenging: Timer Thd. triggered scavenging\n");
  711. pClientWrkItm = ((PQUE_TMM_REQ_WRK_ITM_T)(pScvWrkItm))->pClientCtx;
  712. fPeriodicCC = TRUE;
  713. if (!*pfResetTimer)
  714. {
  715. *pfResetTimer = TRUE;
  716. }
  717. //
  718. // If *pfSpTimeOver is false, it means that the timer
  719. // thread wokr us up at SpTime specified in registry
  720. // (or at 2am if SpTime) was not specifid in registry.
  721. // Set *pfSpTimeOver to TRUE so that from hereon we
  722. // use TimeInterval specified in the registry as
  723. // the time interval
  724. //
  725. if (!*pfSpTimeOver)
  726. {
  727. *pfSpTimeOver = TRUE;
  728. }
  729. }
  730. else
  731. {
  732. pClientWrkItm = pScvWrkItm;
  733. }
  734. Opcode_e = pClientWrkItm->Opcode_e;
  735. Age = pClientWrkItm->Age;
  736. fForce = (BOOL)pClientWrkItm->fForce;
  737. if (*pfResetTimer)
  738. {
  739. WinsTmmDeallocReq((PQUE_TMM_REQ_WRK_ITM_T)pScvWrkItm);
  740. }
  741. else
  742. {
  743. //
  744. // Free the admin. initiated rpc work item
  745. //
  746. WinsMscHeapFree(NmsRpcHeapHdl, pScvWrkItm);
  747. }
  748. }
  749. }
  750. else
  751. {
  752. //
  753. // timer expiry of the wait call
  754. //
  755. Opcode_e = WINSINTF_E_SCV_GENERAL;
  756. Age = pScvParam->VerifyInterval;
  757. fForce = FALSE; // no forceful scavenging
  758. }
  759. if (sfAdminForcedScv && !fPeriodicCC)
  760. {
  761. WinsIntfSetTime( NULL, WINSINTF_E_ADMIN_TRIG_SCV );
  762. DBGPRINTTIME(SCV, "STARTING AN ADMIN. TRIGGERED SCAVENGING CYCLE ", LastATScvTime);
  763. DBGPRINTTIME(DET, "STARTING AN ADMIN. TRIGGERED SCAVENGING CYCLE ", LastATScvTime);
  764. }
  765. else
  766. {
  767. WinsIntfSetTime( NULL, WINSINTF_E_PLANNED_SCV);
  768. DBGPRINTTIME(SCV, "STARTING A SCAVENGING CYCLE ", LastPScvTime);
  769. DBGPRINTTIME(DET, "STARTING A SCAVENGING CYCLE ", LastPScvTime);
  770. }
  771. //
  772. // get the current time
  773. //
  774. (void)time(&CurrentTime);
  775. if (Opcode_e == WINSINTF_E_SCV_GENERAL)
  776. {
  777. WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_SCVENGING_STARTED);
  778. //
  779. // record current time in sLastRefTime
  780. //
  781. sLastRefTime = CurrentTime;
  782. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  783. //
  784. // Store the max. version number in a local since the max. version
  785. // number is incremented by several threads
  786. //
  787. NMSNMH_DEC_VERS_NO_M(
  788. NmsNmhMyMaxVersNo,
  789. MyMaxVersNo
  790. );
  791. //
  792. // synchronize with RplPullPullSpecifiedRange
  793. //
  794. MinScvVersNo = NmsScvMinScvVersNo;
  795. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  796. //
  797. // Set thread priority to the level indicated in the WinsCnf
  798. // structure
  799. //
  800. WinsMscSetThreadPriority(
  801. WinsThdPool.ScvThds[0].ThdHdl,
  802. pScvParam->PrLvl
  803. );
  804. // log a detailed event showing the range of version_numbers that
  805. // are being scavenged. This helps finding out why some particuler
  806. // record is stalled in the database. (If it doesn't fall in this
  807. // range it means the scavenger is not even looking at it).
  808. WinsEvtLogDetEvt(
  809. TRUE, // Informational event
  810. WINS_EVT_SCV_RANGE, // event ID
  811. NULL, // NULL filename
  812. __LINE__, // line number where this event is logged
  813. "dddd", // data section format
  814. MinScvVersNo.LowPart, MinScvVersNo.HighPart, // data: 2nd, 3rd words
  815. MyMaxVersNo.LowPart, MyMaxVersNo.HighPart); // data: 4th, 5th words
  816. Tmp.QuadPart = pScvParam->ScvChunk;
  817. for (
  818. n.QuadPart = MinScvVersNo.QuadPart; // min. version no. to
  819. //start from
  820. LiLeq(n, MyMaxVersNo); // until we reach the max. vers. no
  821. // no third expression here
  822. )
  823. {
  824. BOOL fGotSome = FALSE;
  825. //
  826. // The max. version number to ask for in one shot.
  827. //
  828. VersNoLimit.QuadPart = LiAdd(n, Tmp);
  829. //
  830. // If my max. version number is less than the version number
  831. // computed above, we do not specify a number for the max.
  832. // records. If however, my max. vers. no is more, we specify
  833. // the number equal to the chunk specified in Tmp
  834. //
  835. if (LiLeq(MyMaxVersNo, VersNoLimit))
  836. {
  837. MaxNoOfRecsReqd = 0;
  838. }
  839. else
  840. {
  841. MaxNoOfRecsReqd = Tmp.LowPart;
  842. }
  843. // log a detailed event saying what are the exact records that are retrieved
  844. // from the database for scavenging. This helps finding out whether the loop is
  845. // not broken earlier that expected leaving records not scavenged.
  846. WinsEvtLogDetEvt(
  847. TRUE, // Informational event
  848. WINS_EVT_SCV_CHUNK, // event ID
  849. NULL, // NULL filename
  850. __LINE__, // line number where this event is logged
  851. "ddddd", // data section format
  852. MaxNoOfRecsReqd, // data: 2nd word
  853. n.LowPart, n.HighPart, // data: 3rd, 4th words
  854. MyMaxVersNo.LowPart, MyMaxVersNo.HighPart); // data: 5th, 6th words
  855. /*
  856. * Call database manager function to get all the records. owned
  857. * by us. No need to check the return status here
  858. */
  859. NmsDbGetDataRecs(
  860. WINS_E_NMSSCV,
  861. pScvParam->PrLvl,
  862. n,
  863. MyMaxVersNo, //Max vers. no
  864. MaxNoOfRecsReqd,
  865. FALSE, //we want data recs upto MaxVers
  866. FALSE, //not interested in replica tombstones
  867. NULL, //must be NULL since we are not
  868. //doing scavenging of clutter
  869. &NmsLocalAdd,
  870. FALSE, //both dynamic & static records should be considered
  871. WINSCNF_RPL_DEFAULT_TYPE, //no use here
  872. (LPVOID *)&pStartBuff,
  873. &BuffLen,
  874. &NoOfRecs
  875. );
  876. //
  877. // If no of records retrieved is 0, we should break out of
  878. // the loop
  879. //
  880. if (NoOfRecs == 0)
  881. {
  882. //
  883. // deallocate the heap that was created
  884. //
  885. // NmsDbGetDataRecs always allocates a buffer (even if
  886. // the number of records is 0). Let us deallocate it
  887. //
  888. GET_TLS_M(pTls);
  889. ASSERT(pTls->HeapHdl != NULL);
  890. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  891. WinsMscHeapDestroy(pTls->HeapHdl);
  892. break;
  893. }
  894. fGotSome = TRUE;
  895. if (!fRecsExistent)
  896. {
  897. fRecsExistent = TRUE;
  898. }
  899. NoOfRecsScv = 0; // init the counter to 0
  900. (void)time(&CurrentTime);
  901. for (
  902. i = 0, pRec = pStartBuff;
  903. i < NoOfRecs;
  904. i++
  905. )
  906. {
  907. State = NMSDB_ENTRY_STATE_M(pRec->Flag);
  908. switch (State)
  909. {
  910. case(NMSDB_E_ACTIVE):
  911. // don't touch active static records
  912. if (!NMSDB_IS_ENTRY_STATIC_M(pRec->Flag))
  913. {
  914. SET_STATE_IF_REQD_M(
  915. pRec,
  916. CurrentTime,
  917. pScvParam->TombstoneInterval,
  918. NMSDB_E_RELEASED,
  919. NoOfRecChgToRelSt
  920. );
  921. }
  922. break;
  923. case(NMSDB_E_RELEASED):
  924. // a static record can't become released, but who knows...
  925. // just making sure we don't touch statics in this case
  926. if (!NMSDB_IS_ENTRY_STATIC_M(pRec->Flag))
  927. {
  928. SET_STATE_IF_REQD_M(
  929. pRec,
  930. CurrentTime,
  931. pScvParam->TombstoneTimeout,
  932. NMSDB_E_TOMBSTONE,
  933. NoOfRecChgToTombSt
  934. );
  935. }
  936. break;
  937. case(NMSDB_E_TOMBSTONE):
  938. FUTURES("Redesign, so that the if condition is not executed multiple times");
  939. //
  940. //If there are records to delete and we have
  941. //been up and running for at least 3 days, go
  942. //ahead and delete them. The records should
  943. //have replicated to atleast one partner by
  944. //now.
  945. if ((CurrentTime - sBootTime) >= THREE_DAYS ||
  946. sfNoLimitChk)
  947. {
  948. SET_STATE_IF_REQD_M(
  949. pRec,
  950. CurrentTime,
  951. pScvParam->TombstoneTimeout, //no use
  952. NMSDB_E_DELETED,
  953. NoOfRecToDel
  954. );
  955. }
  956. break;
  957. default:
  958. DBGPRINT1(EXC, "DoScavenging: Weird State of Record (%d)\n", State);
  959. WINSEVT_LOG_M(WINS_EXC_FAILURE, WINS_EVT_SFT_ERR);
  960. // Just change the state of the record to tombstone and continue
  961. // with scavenging.
  962. NMSDB_SET_STATE_M(pRec->Flag, NMSDB_E_TOMBSTONE);
  963. break;
  964. }
  965. pRec = (PRPL_REC_ENTRY_T)(
  966. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  967. );
  968. }
  969. //
  970. // Make pTmp point to the last record in the
  971. // buffer.
  972. //
  973. pTmp = (PRPL_REC_ENTRY_T)(
  974. (LPBYTE)pRec - RPL_REC_ENTRY_SIZE);
  975. //
  976. // If one or more records need to be scavenged
  977. //
  978. if (NoOfRecsScv > 0)
  979. {
  980. if (NoOfRecToDel > 0)
  981. {
  982. //
  983. // If the most recent record in this chunk has
  984. // to be deleted, let us record that fact in a
  985. // boolean.
  986. // If in the scavenging of the next chunk, the
  987. // most recent record is not deleted, the boolean
  988. // will be reset. At this point we don't know
  989. // whether or not there is even another record
  990. // more recent than this one (the next time, we
  991. // retrieve records, we may not get any)
  992. //
  993. CHECK("This if test is most probably not required. Get rid of it")
  994. if (LiLeq(pTmp->VersNo, MyMaxVersNo))
  995. {
  996. //
  997. // If entry is marked for deletion
  998. //
  999. if (NMSDB_ENTRY_DEL_M(pTmp->Flag))
  1000. {
  1001. fLastEntryDel = TRUE;
  1002. }
  1003. else
  1004. {
  1005. fLastEntryDel = FALSE;
  1006. }
  1007. }
  1008. }
  1009. else
  1010. {
  1011. fLastEntryDel = FALSE;
  1012. }
  1013. UpdDb(
  1014. pScvParam,
  1015. pStartBuff,
  1016. NoOfRecs,
  1017. NoOfRecsScv
  1018. );
  1019. TotNoOfRecsScv += NoOfRecsScv;
  1020. }
  1021. #ifdef WINSDBG
  1022. else
  1023. {
  1024. DBGPRINT0(DET,"DoScavenging: NO RECORDS NEED TO BE SCAVENGED AT THIS TIME\n");
  1025. }
  1026. #endif
  1027. //
  1028. // get pointer to TLS for accessing the heap hdl later on
  1029. //
  1030. GET_TLS_M(pTls);
  1031. //
  1032. // if we specified a max. no. and the no. of recs retrieved
  1033. // is less than that, clearly there are no more records to
  1034. // retrieve. Get rid of the buffer and break out of the loop
  1035. //
  1036. if ((MaxNoOfRecsReqd > 0) && (NoOfRecs < MaxNoOfRecsReqd))
  1037. {
  1038. //
  1039. // Since the number of records we retrieved were
  1040. // less than the max. we had specified, it means that
  1041. // there are no more records to retrieve. Break out of
  1042. // the for loop
  1043. //
  1044. //
  1045. // destroy the heap that was allocated
  1046. //
  1047. for (RecCnt=0, pRec = pStartBuff; RecCnt<NoOfRecs; RecCnt++)
  1048. {
  1049. WinsMscHeapFree(pTls->HeapHdl, pRec->pName);
  1050. pRec = (PRPL_REC_ENTRY_T)(
  1051. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  1052. );
  1053. }
  1054. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  1055. WinsMscHeapDestroy(pTls->HeapHdl);
  1056. break;
  1057. }
  1058. //
  1059. // Set n to the highest version number retrieved if it is
  1060. // more than what n would be set to prior to the next
  1061. // iteration.
  1062. //
  1063. // At the next iteration, n will be compared with the highest
  1064. // version number we have. If equal, then we don't have to
  1065. // iterate anymore (useful when the highest version number
  1066. // is very high but there are one or more records with low
  1067. // version numbers
  1068. //
  1069. if (LiGtr(pTmp->VersNo, VersNoLimit))
  1070. {
  1071. n = pTmp->VersNo;
  1072. }
  1073. else
  1074. {
  1075. n = VersNoLimit;
  1076. }
  1077. //
  1078. // destroy the heap that was allocated
  1079. //
  1080. for (RecCnt=0, pRec = pStartBuff; RecCnt<NoOfRecs; RecCnt++)
  1081. {
  1082. WinsMscHeapFree(pTls->HeapHdl, pRec->pName);
  1083. pRec = (PRPL_REC_ENTRY_T)(
  1084. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  1085. );
  1086. }
  1087. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  1088. WinsMscHeapDestroy(pTls->HeapHdl);
  1089. } // end of for loop for looping over records
  1090. WINSEVT_LOG_INFO_D_M(TotNoOfRecsScv, WINS_EVT_SCV_RECS);
  1091. WINSDBG_INC_SEC_COUNT_M(SectionCount);
  1092. //
  1093. // If the last scavenging action was a deletion, it means that
  1094. // we deleted the highest version numbered record owned by
  1095. // us. Let us therefore update the Special record that records
  1096. // this version number.
  1097. //
  1098. if (fLastEntryDel)
  1099. {
  1100. WinsMscSetThreadPriority(
  1101. WinsThdPool.ScvThds[0].ThdHdl,
  1102. THREAD_PRIORITY_NORMAL
  1103. );
  1104. (VOID)NmsDbUpdHighestVersNoRec(
  1105. NULL, //no pTls
  1106. MyMaxVersNo,
  1107. TRUE //enter critical section
  1108. );
  1109. WinsMscSetThreadPriority(
  1110. WinsThdPool.ScvThds[0].ThdHdl,
  1111. pScvParam->PrLvl
  1112. );
  1113. }
  1114. (void)time(&CurrentTime);
  1115. //
  1116. // Let us get rid of the replica tombstones if sufficient time has
  1117. // elapsed since the last time we did this. Exception: If the
  1118. // administrator has requested scavenging, let us do it now.
  1119. // Even if admin. requests it we don't do it unless we have been
  1120. // up and running for atleast 3 days. This is in line with our
  1121. // philosophy of being absolutely robust even when admin. makes
  1122. // mistakes.
  1123. // sfNoLimitChk allows testers to override this 3 day limitations.
  1124. if (
  1125. ( ((CurrentTime > sLastTombTime)
  1126. &&
  1127. (CurrentTime - sLastTombTime) > (time_t)min(
  1128. pScvParam->TombstoneTimeout,
  1129. pScvParam->TombstoneInterval
  1130. ) )
  1131. ||
  1132. sfAdminForcedScv
  1133. )
  1134. &&
  1135. ((CurrentTime - sBootTime >= THREE_DAYS) || fForce || sfNoLimitChk)
  1136. )
  1137. {
  1138. NMSSCV_CLUT_T ClutterInfo;
  1139. WinsIntfSetTime(
  1140. NULL,
  1141. WINSINTF_E_TOMBSTONES_SCV
  1142. );
  1143. NoOfRecsScv = 0;
  1144. NoOfRecToDel = 0;
  1145. ClutterInfo.Interval = pScvParam->TombstoneTimeout;
  1146. ClutterInfo.CurrentTime = CurrentTime;
  1147. ClutterInfo.fAll = FALSE; //not used but
  1148. //let us set it
  1149. /*
  1150. * Call database manager function to get all the
  1151. * replicas that are tombstones
  1152. */
  1153. DBGPRINT0(DET, "DoScavenging: GETTING REPLICA TOMBSTONES\n");
  1154. NmsDbGetDataRecs(
  1155. WINS_E_NMSSCV,
  1156. pScvParam->PrLvl,
  1157. n, //no use in this call
  1158. MyMaxVersNo, //no use in this call
  1159. 0, //no use in this call
  1160. TRUE, //no use in this call
  1161. TRUE, //Get only replica tombstones
  1162. &ClutterInfo,
  1163. &NmsLocalAdd, //no use in this call
  1164. FALSE, //both dyn & static should be taken
  1165. WINSCNF_RPL_DEFAULT_TYPE, //no use here
  1166. (LPVOID *)&pStartBuff,
  1167. &BuffLen,
  1168. &NoOfRecs
  1169. );
  1170. if(NoOfRecs > 0)
  1171. {
  1172. for (
  1173. i = 0, pRec = pStartBuff;
  1174. i < NoOfRecs;
  1175. i++
  1176. )
  1177. {
  1178. NMSDB_SET_STATE_M(pRec->Flag, NMSDB_E_DELETED);
  1179. pRec->fScv = TRUE;
  1180. NoOfRecToDel = NoOfRecs;
  1181. pRec = (PRPL_REC_ENTRY_T)(
  1182. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  1183. );
  1184. }
  1185. //
  1186. // If one or more replicas needs to be deleted
  1187. // call UpdDb
  1188. //
  1189. DBGPRINT1(DET, "DoScavenging: %d REPLICAS WILL BE DELETED\n", NoOfRecs);
  1190. UpdDb(
  1191. pScvParam,
  1192. pStartBuff,
  1193. NoOfRecs,
  1194. NoOfRecs //NoOfRecsScv
  1195. );
  1196. if (fForce)
  1197. {
  1198. DBGPRINT0(SCV, "DoScavenging: FORCEFUL SCAVENGING OF REPLICA TOMBSTONES\n");
  1199. WINSEVT_LOG_M(WINS_SUCCESS, WINS_EVT_FORCE_SCV_R_T);
  1200. }
  1201. WINSEVT_LOG_INFO_D_M(NoOfRecsScv, WINS_EVT_SCV_RPLTOMB);
  1202. }
  1203. #ifdef WINSDBG
  1204. else
  1205. {
  1206. DBGPRINT0(DET, "DoScavenging: NO REPLICA TOMBSTONES DELETED\n");
  1207. }
  1208. #endif
  1209. //
  1210. // destroy the heap that was allocated
  1211. //
  1212. GET_TLS_M(pTls);
  1213. //
  1214. // destroy the heap that was allocated
  1215. //
  1216. for (RecCnt=0, pRec = pStartBuff; RecCnt<NoOfRecs; RecCnt++)
  1217. {
  1218. WinsMscHeapFree(pTls->HeapHdl, pRec->pName);
  1219. pRec = (PRPL_REC_ENTRY_T)(
  1220. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  1221. );
  1222. }
  1223. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  1224. WinsMscHeapDestroy(pTls->HeapHdl);
  1225. //
  1226. // record current time in sLastTombTime
  1227. //
  1228. sLastTombTime = CurrentTime;
  1229. } // end of if (test if replica tombstones need to be processed)
  1230. WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_SCVENGING_COMPLETED);
  1231. }
  1232. WINSDBG_INC_SEC_COUNT_M(SectionCount);
  1233. if (Opcode_e != WINSINTF_E_SCV_GENERAL)
  1234. {
  1235. WinsMscSetThreadPriority(
  1236. WinsThdPool.ScvThds[0].ThdHdl,
  1237. pScvParam->PrLvl
  1238. );
  1239. }
  1240. //
  1241. // If we are due for a verification or if we are being forced to do
  1242. // it by the admin., do it. Note: Timer Thread initiated verification
  1243. // is always forced. An admin. initiated one may or may not be forced.
  1244. // We force the admin. to specify the kind of verification he wants.
  1245. // If he chooses to do a forceful one, then we give him a warning.
  1246. // about the overhead of this (specially if a number of admins. are
  1247. // doing forceful verification around the same time or one after
  1248. // another
  1249. //
  1250. if (
  1251. ((CurrentTime > sLastVerifyTime)
  1252. &&
  1253. ((CurrentTime - sLastVerifyTime) > (time_t)pScvParam->VerifyInterval))
  1254. ||
  1255. fForce
  1256. ||
  1257. (sfAdminForcedScv && (CurrentTime - sLastAdminScvTime) >= ONE_HOUR )
  1258. )
  1259. {
  1260. // we might want to always log normal events for consistency checking
  1261. // since this operation happens normally only when initiated by the
  1262. // administrator or at about 24hrs, if configured
  1263. // (or reg param ..Parameters\ConsistencyCheck:TimeInterval)
  1264. // --ft: #384489: if this is an administrator initiated action...
  1265. //if (sfAdminForcedScv)
  1266. //..log the event as a normal one
  1267. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_CCCHECK_STARTED);
  1268. //else
  1269. //..log it as a detailed event only.
  1270. // WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_CCCHECK_STARTED);
  1271. WinsIntfSetTime(
  1272. NULL,
  1273. WINSINTF_E_VERIFY_SCV
  1274. );
  1275. //
  1276. // get all active replicas that are older than the
  1277. // verify interval. Contact the owner WINS to verify their
  1278. // validity
  1279. //
  1280. //DBGPRINT1(ERR, "DoScavenging: pScvParam is (%x)\n", pScvParam);
  1281. (VOID)VerifyDbData(pScvParam, CurrentTime, Age, fForce, fPeriodicCC);
  1282. //WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_SCV_CLUTTER);
  1283. // --ft: #384489: see comment above.
  1284. //if (sfAdminForcedScv)
  1285. //..log the event as a normal one
  1286. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_CCCHECK_COMPLETED);
  1287. //else
  1288. //..log it as a detailed event only.
  1289. // WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_CCCHECK_COMPLETED);
  1290. sLastVerifyTime = CurrentTime;
  1291. }
  1292. WINSDBG_INC_SEC_COUNT_M(SectionCount);
  1293. } // end of try ..
  1294. except (EXCEPTION_EXECUTE_HANDLER) {
  1295. DBGPRINTEXC("DoScavenging");
  1296. DBGPRINT1(EXC, "DoScavenging: Section Count (%d)\n", SectionCount);
  1297. DBGPRINT5(EXC, "DoScavenging: Variables - i (%d), NoOfRecs (%d), \
  1298. NoOfRecsScv (%d), pStartBuff (%p), pRec (%p)\n",
  1299. i, NoOfRecs, NoOfRecsScv, pStartBuff, pRec
  1300. );
  1301. if (GetExceptionCode() != WINS_EXC_COMM_FAIL)
  1302. {
  1303. //
  1304. // Set thd. priority back to normal
  1305. //
  1306. WinsMscSetThreadPriority(
  1307. WinsThdPool.ScvThds[0].ThdHdl,
  1308. THREAD_PRIORITY_NORMAL
  1309. );
  1310. //
  1311. // This is serious. Let us reraise the exception so that
  1312. // WINS comes down
  1313. //
  1314. //WINS_RERAISE_EXC_M();
  1315. //
  1316. // just return so that we close tables in the caller function
  1317. //
  1318. return(WINS_FAILURE);
  1319. }
  1320. }
  1321. //
  1322. // Set thd. priority back to normal
  1323. //
  1324. WinsMscSetThreadPriority(
  1325. WinsThdPool.ScvThds[0].ThdHdl,
  1326. THREAD_PRIORITY_NORMAL
  1327. );
  1328. if (Opcode_e == WINSINTF_E_SCV_GENERAL)
  1329. {
  1330. //
  1331. //If we were not able to retrieve any owned records in this scavenging
  1332. // cycle, adjust the min. scv vers. no. Synchronize with
  1333. // RplPullPullSpecifiedRange
  1334. //
  1335. if (!fRecsExistent)
  1336. {
  1337. //
  1338. // NmsScvMinScvVersNo may be greater than MyMaxVersNo
  1339. // (This may happen if we did not find any local records
  1340. // last time around and no registrations have taken
  1341. // place since then).
  1342. //
  1343. if (LiGtr(MyMaxVersNo, NmsScvMinScvVersNo))
  1344. {
  1345. //
  1346. //
  1347. // Change the Low end of the range that
  1348. // we will use it at the next Scavenging cycle
  1349. //
  1350. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1351. //
  1352. // Set the Min. Scv. Vers. no to 1 more than the max. vers.
  1353. // no. we used when searching for records to scavenge.
  1354. //
  1355. NMSNMH_INC_VERS_NO_M(MyMaxVersNo, MyMaxVersNo);
  1356. NmsScvMinScvVersNo = MyMaxVersNo;
  1357. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1358. }
  1359. }
  1360. //
  1361. // If we are not executing a work item from the queue, break out
  1362. // of the while loop, else continue (to get the next work item)
  1363. // if there
  1364. //
  1365. if (!fSignaled)
  1366. {
  1367. break;
  1368. }
  1369. }
  1370. } // end of while
  1371. DBGPRINT0(SCV, "SCAVENGING CYCLE ENDED\n");
  1372. DBGLEAVE("DoScavenging\n");
  1373. return(WINS_SUCCESS);
  1374. }
  1375. VOID
  1376. ReconfigScv(
  1377. PNMSSCV_PARAM_T pScvParam
  1378. )
  1379. /*++
  1380. Routine Description:
  1381. This function is called to reinit the scavenging params
  1382. Arguments:
  1383. pScvParam - Structure storing the scavenging params
  1384. Externals Used:
  1385. None
  1386. Return Value:
  1387. None
  1388. Error Handling:
  1389. Called by:
  1390. ScvThdInitFn
  1391. Side Effects:
  1392. Comments:
  1393. None
  1394. --*/
  1395. {
  1396. DBGENTER("ReconfigScv\n");
  1397. //
  1398. // Extract the parameters that are related
  1399. // to scavenging and go back to doing the timed
  1400. // wait. Since WinsCnf can change any time, we
  1401. // operate with copies. Also, the priority of this
  1402. // thread is changed outside of this critical section
  1403. // See DoScavenging().
  1404. //
  1405. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1406. try {
  1407. pScvParam->ScvChunk = WinsCnf.ScvChunk;
  1408. pScvParam->RefreshInterval = WinsCnf.RefreshInterval;
  1409. pScvParam->TombstoneInterval = WinsCnf.TombstoneInterval;
  1410. pScvParam->TombstoneTimeout = WinsCnf.TombstoneTimeout;
  1411. pScvParam->PrLvl = WinsCnf.ScvThdPriorityLvl;
  1412. //
  1413. // Load up the CC parameters
  1414. //
  1415. pScvParam->CC.TimeInt = WinsCnf.CC.TimeInt;
  1416. pScvParam->CC.fSpTime = WinsCnf.CC.fSpTime;
  1417. pScvParam->CC.SpTimeInt = WinsCnf.CC.SpTimeInt;
  1418. pScvParam->CC.MaxRecsAAT = WinsCnf.CC.MaxRecsAAT;
  1419. pScvParam->CC.fUseRplPnrs = WinsCnf.CC.fUseRplPnrs;
  1420. //
  1421. // If the backup path has changed, start using it.
  1422. //
  1423. if (WinsCnf.pBackupDirPath != NULL)
  1424. {
  1425. if (strcmp(WinsCnf.pBackupDirPath, pScvParam->BackupDirPath))
  1426. {
  1427. strcpy(pScvParam->BackupDirPath, WinsCnf.pBackupDirPath);
  1428. }
  1429. }
  1430. else
  1431. {
  1432. pScvParam->BackupDirPath[0] = EOS;
  1433. }
  1434. }
  1435. finally {
  1436. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1437. }
  1438. DBGLEAVE("ReconfigScv\n");
  1439. return;
  1440. }
  1441. #ifdef WINSDBG
  1442. #pragma optimize ("", off)
  1443. #endif
  1444. VOID
  1445. UpdDb(
  1446. IN PNMSSCV_PARAM_T pScvParam,
  1447. IN PRPL_REC_ENTRY_T pStartBuff,
  1448. IN DWORD NoOfRecs,
  1449. IN DWORD NoOfRecsToUpd
  1450. )
  1451. /*++
  1452. Routine Description:
  1453. This function is called to update the DB
  1454. Arguments:
  1455. pScvParam - Scavenging params
  1456. pStartBuff - Buffer containing records processed by DoScavenging()
  1457. NoOfRecs - No of records in the above buffer
  1458. NoofRecsToUpd - No of records that need to be modified in the db
  1459. Externals Used:
  1460. None
  1461. Return Value:
  1462. None
  1463. Error Handling:
  1464. Called by:
  1465. DoScavenging
  1466. Side Effects:
  1467. Comments:
  1468. None
  1469. --*/
  1470. {
  1471. DWORD i;
  1472. DWORD NoUpdated = 0; //No of records that have been
  1473. //updated
  1474. PRPL_REC_ENTRY_T pRec = pStartBuff;
  1475. DBGENTER("UpdDb\n");
  1476. //
  1477. // Set the current index to be the clustered index
  1478. //
  1479. NmsDbSetCurrentIndex(
  1480. NMSDB_E_NAM_ADD_TBL_NM,
  1481. NMSDB_NAM_ADD_CLUST_INDEX_NAME
  1482. );
  1483. //
  1484. // Update the database now
  1485. //
  1486. for (
  1487. i = 0;
  1488. i < NoOfRecs;
  1489. i++
  1490. )
  1491. {
  1492. //
  1493. // if the record was updated, update the db
  1494. //
  1495. if (pRec->fScv)
  1496. {
  1497. if (NmsDbQueryNUpdIfMatch(
  1498. pRec,
  1499. pScvParam->PrLvl,
  1500. TRUE, //chg pr. lvl
  1501. WINS_E_NMSSCV
  1502. ) == WINS_SUCCESS
  1503. )
  1504. {
  1505. NoUpdated++; // no of records that we
  1506. //have updated in the db
  1507. }
  1508. else
  1509. {
  1510. DBGPRINT0(ERR, "DoScavenging: Could not scavenge a record\n");
  1511. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SCV_ERR);
  1512. }
  1513. }
  1514. //
  1515. // see if we are done
  1516. //
  1517. if (NoUpdated == NoOfRecsToUpd)
  1518. {
  1519. break;
  1520. }
  1521. pRec = (PRPL_REC_ENTRY_T)(
  1522. (LPBYTE)pRec + RPL_REC_ENTRY_SIZE
  1523. );
  1524. } // end of for loop
  1525. DBGPRINT1(FLOW, "LEAVE: SCAVENGING: UpdDb. Records Updated = (%d)\n", NoUpdated);
  1526. return;
  1527. } // UpdDb()
  1528. #ifdef WINSDBG
  1529. #pragma optimize ("", on)
  1530. #endif
  1531. STATUS
  1532. VerifyDbData(
  1533. PNMSSCV_PARAM_T pScvParam,
  1534. time_t CurrentTime,
  1535. DWORD Age,
  1536. BOOL fForce,
  1537. BOOL fPeriodicCC
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. This function is called to remove any clutter that might have
  1542. accumulated in the db. For each owner, excepting self, in the
  1543. db, it gets the version numbers of the active records that are
  1544. older than the verify time interval. It then contacts the owner
  1545. WINS to verify their validity
  1546. Arguments:
  1547. pScvParam - pointer to the scavenging parameters
  1548. Externals Used:
  1549. None
  1550. Return Value:
  1551. None
  1552. Error Handling:
  1553. Called by:
  1554. DoScavenging
  1555. Side Effects:
  1556. Comments:
  1557. None
  1558. --*/
  1559. {
  1560. DWORD MaxOwnerIdFound;
  1561. volatile DWORD i;
  1562. NMSSCV_CLUT_T ClutterInfo;
  1563. PRPL_REC_ENTRY_T pStartBuff;
  1564. DWORD BuffLen;
  1565. DWORD NoOfLocalDbRecs;
  1566. COMM_ADD_T OwnerWinsAdd;
  1567. COMM_ADD_T VerifyWinsAdd;
  1568. PCOMM_ADD_T pWinsAdd;
  1569. VERS_NO_T MinVersNo, MaxVersNo;
  1570. PNMSDB_WINS_STATE_E pWinsState_e;
  1571. PVERS_NO_T pStartVersNo;
  1572. NMSDB_WINS_STATE_E WinsState_e;
  1573. COMM_HDL_T DlgHdl;
  1574. PWINSTHD_TLS_T pTls;
  1575. static DWORD sFirstOwnerId = 1;
  1576. DWORD FirstOwnerId;
  1577. DWORD NoOfPulledRecs;
  1578. DWORD TotNoOfPulledRecs = 0;
  1579. DWORD LastOwnerId;
  1580. BOOL fNonOwnerPnr;
  1581. DWORD TotPulledRecsFromOneWins;
  1582. BOOL fDlgStarted = FALSE;
  1583. BOOL fFirstTime;
  1584. PRPL_REC_ENTRY_T pLastEntry;
  1585. STATUS RetStat;
  1586. DWORD RplType;
  1587. BOOL fPulledAtLeastOnce;
  1588. VERS_NO_T MaxVersNoSave;
  1589. DBGENTER("VerifyDbData\n");
  1590. //
  1591. // Init the structure used by NmsDbGetDataRecs()
  1592. //
  1593. ClutterInfo.Interval = pScvParam->VerifyInterval;
  1594. ClutterInfo.CurrentTime = CurrentTime;
  1595. ClutterInfo.Age = Age;
  1596. ClutterInfo.fAll = TRUE;
  1597. //
  1598. // Set thread priority to NORMAL
  1599. //
  1600. WinsMscSetThreadPriority(
  1601. WinsThdPool.ScvThds[0].ThdHdl,
  1602. THREAD_PRIORITY_NORMAL
  1603. );
  1604. //
  1605. // Cleanup the owner-address table if it requires cleaning
  1606. //
  1607. NmsDbCleanupOwnAddTbl(&MaxOwnerIdFound);
  1608. try {
  1609. //
  1610. // If it is an admin. forced verification or the one that happens
  1611. // due to the verify interval being over, do a full validation
  1612. //
  1613. if (!fPeriodicCC)
  1614. {
  1615. FirstOwnerId = 1;
  1616. sLastFullVerifyTime = CurrentTime;
  1617. }
  1618. else
  1619. {
  1620. //
  1621. // Periodic verification. Skip the owners we verified earlier
  1622. //
  1623. if (sFirstOwnerId >= MaxOwnerIdFound)
  1624. {
  1625. sFirstOwnerId = 1;
  1626. }
  1627. FirstOwnerId = sFirstOwnerId;
  1628. }
  1629. LastOwnerId = MaxOwnerIdFound;
  1630. //
  1631. // for each owner in the db, excluding self, do the following.
  1632. //
  1633. for (i = FirstOwnerId; i <= LastOwnerId; i++)
  1634. {
  1635. //
  1636. // If it is periodic verification and we have pulled more than
  1637. // the max. threshold specified for one particular cycle,
  1638. // break out of the loop
  1639. //
  1640. if (fPeriodicCC && (TotNoOfPulledRecs >= pScvParam->CC.MaxRecsAAT))
  1641. {
  1642. break;
  1643. }
  1644. //
  1645. // Get all ACTIVE replicas that are older than verify interval.
  1646. //
  1647. ClutterInfo.OwnerId = i;
  1648. //
  1649. // We need to synchronize with the Pull thread which can
  1650. // change the NmsDbOwnAddTbl table. The entry may have
  1651. // been deleted by the Pull thread (DeleteWins), so we
  1652. // should be ready for access violation
  1653. //
  1654. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  1655. RPL_FIND_ADD_BY_OWNER_ID_M(
  1656. i, pWinsAdd, pWinsState_e, pStartVersNo);
  1657. //
  1658. // The Wins entry should be there.
  1659. //
  1660. ASSERT(pWinsAdd);
  1661. OwnerWinsAdd = *pWinsAdd;
  1662. WinsState_e = *pWinsState_e;
  1663. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  1664. //
  1665. // If WINS is not active, log a record and continue to
  1666. // the next WINS. It is possible for WINS to get deleted
  1667. // to between the time we get its records and the time
  1668. // we check the own-add table for its entry.
  1669. //
  1670. if (
  1671. (WinsState_e == NMSDB_E_WINS_DOWN) ||
  1672. (WinsState_e == NMSDB_E_WINS_DELETED)
  1673. )
  1674. {
  1675. //
  1676. // if there are records in the db, then the
  1677. // state of WINS in the in-memory table can not
  1678. // be deleted
  1679. //
  1680. DBGPRINT2(SCV, "VerifyDbData: WINS with index = (%d) and IP Address = (%x) is either down or deleted \n", i, OwnerWinsAdd.Add.IPAdd);
  1681. continue;
  1682. }
  1683. WINS_ASSIGN_INT_TO_LI_M(MinVersNo, 0);
  1684. fFirstTime = TRUE;
  1685. TotPulledRecsFromOneWins = 0;
  1686. fPulledAtLeastOnce = FALSE;
  1687. //
  1688. // Save the max. vers. no. that we have in the
  1689. // pRplPullOwnerVersNo table in a local.
  1690. //
  1691. EnterCriticalSection(&RplVersNoStoreCrtSec);
  1692. #ifdef WINSDBG
  1693. try {
  1694. #endif
  1695. MaxVersNoSave = (pRplPullOwnerVersNo + i)->VersNo;
  1696. #ifdef WINSDBG
  1697. } //end of try { .. }
  1698. finally {
  1699. #endif
  1700. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  1701. #ifdef WINSDBG
  1702. }
  1703. #endif
  1704. do
  1705. {
  1706. NoOfLocalDbRecs = 0;
  1707. // DBGPRINT1(ERR, "VerifyDbData:1 pScvParam is (%x)\n", pScvParam);
  1708. MaxVersNo.QuadPart = 0;
  1709. NmsDbGetDataRecs(
  1710. WINS_E_NMSSCV,
  1711. pScvParam->PrLvl,
  1712. MinVersNo,
  1713. MaxVersNo, //not used in this call
  1714. 0,
  1715. TRUE, //fUpToLimit set to TRUE
  1716. FALSE, //not interested in replica tombstones
  1717. &ClutterInfo,
  1718. &OwnerWinsAdd, //Wins Address - not used
  1719. FALSE, //dyn + static recs required
  1720. WINSCNF_RPL_DEFAULT_TYPE, //no use here
  1721. (LPVOID *)&pStartBuff,
  1722. &BuffLen,
  1723. &NoOfLocalDbRecs
  1724. );
  1725. GET_TLS_M(pTls);
  1726. ASSERT(pTls->HeapHdl != NULL);
  1727. WinsMscChkTermEvt(
  1728. #ifdef WINSDBG
  1729. WINS_E_NMSSCV,
  1730. #endif
  1731. FALSE
  1732. );
  1733. PERF("Optimize so that we reuse a dlg session if we need to go to the same")
  1734. PERF("pnr in a subsequent iteration")
  1735. //
  1736. // If this is the first time, we pick a WINS and establish
  1737. // communications with it. Note: If the max. vers. no
  1738. // in pRplOwnerVersNo for this WINS is 0, we continue on
  1739. // to the next WINS in our list.
  1740. //
  1741. // We don't care whether or not we were able to retrieve
  1742. // any records from the db. If we retrieved 0 but the Wins's
  1743. // pRplPullOwnerVersNo entry has a positive entry, it means
  1744. // we are out of synch
  1745. //
  1746. if (fFirstTime)
  1747. {
  1748. if (MaxVersNoSave.QuadPart == 0)
  1749. {
  1750. ASSERT(NoOfLocalDbRecs == 0);
  1751. DBGPRINT2(SCV, "VerifyDbData: WINS with index = (%d) and address = (%x) has pRplPullOwnerVersNo value of 0. SKIPPING IT\n", i, OwnerWinsAdd.Add.IPAdd);
  1752. FreeDbMemory(pStartBuff, NoOfLocalDbRecs, pTls);
  1753. break;
  1754. }
  1755. //
  1756. // Pick the pnr to use for verification
  1757. //
  1758. if (PickWinsToUse(
  1759. &VerifyWinsAdd,
  1760. &OwnerWinsAdd,
  1761. pScvParam->CC.fUseRplPnrs,
  1762. &fNonOwnerPnr,
  1763. &RplType) != WINS_SUCCESS)
  1764. {
  1765. //
  1766. // Any error that needed to be logged has already
  1767. // been logged. Just return success.
  1768. //
  1769. FreeDbMemory(pStartBuff, NoOfLocalDbRecs, pTls);
  1770. return (WINS_SUCCESS);
  1771. }
  1772. //
  1773. // Establish communication with it. If we can not
  1774. // establish comm. with it, break out of the loop
  1775. //
  1776. RetStat = EstablishCommForVerify(&VerifyWinsAdd, &DlgHdl);
  1777. if (RetStat == WINS_FAILURE)
  1778. {
  1779. FreeDbMemory(pStartBuff, NoOfLocalDbRecs, pTls);
  1780. break; //go on to the next WINS in the list of owners
  1781. }
  1782. fDlgStarted = TRUE;
  1783. //
  1784. // get the min and max version numbers of the active
  1785. // replicas
  1786. //
  1787. MinVersNo.QuadPart = 1; //pStartBuff->VersNo;
  1788. fFirstTime = FALSE;
  1789. } // if first time
  1790. {
  1791. //
  1792. //Must not pull a version number that is > what we
  1793. //have in our table to avoid conflicting with the
  1794. //pull thread.
  1795. //
  1796. MaxVersNo = MaxVersNoSave;
  1797. }
  1798. ASSERT(MaxVersNo.QuadPart <= MaxVersNoSave.QuadPart);
  1799. DBGPRINT5(DET, "VerifyDbData: Going to pull records in the range (%d %d) to (%d %d) from Wins with owner id = (%d)\n",
  1800. MinVersNo.HighPart, MinVersNo.LowPart,
  1801. MaxVersNo.HighPart, MaxVersNo.LowPart,
  1802. i
  1803. );
  1804. try
  1805. {
  1806. //
  1807. // Pull the records in the range from the WINS
  1808. //
  1809. PullAndUpdateDb(
  1810. &DlgHdl,
  1811. &OwnerWinsAdd,
  1812. pStartBuff,
  1813. i,
  1814. MinVersNo,
  1815. MaxVersNo,
  1816. RplType,
  1817. NoOfLocalDbRecs,
  1818. CurrentTime,
  1819. pScvParam,
  1820. fNonOwnerPnr,
  1821. &TotPulledRecsFromOneWins
  1822. );
  1823. }
  1824. except (EXCEPTION_EXECUTE_HANDLER)
  1825. {
  1826. // just in case some exception is raised while pulling the records,
  1827. // bail this owner only, not the entire scavenge process
  1828. FreeDbMemory(pStartBuff, NoOfLocalDbRecs, pTls);
  1829. break;
  1830. }
  1831. if (!fPulledAtLeastOnce)
  1832. {
  1833. fPulledAtLeastOnce = TRUE;
  1834. }
  1835. //
  1836. // deallocate the memory block that was allocated
  1837. //
  1838. // NmsDbGetDataRecs always allocates a buffer (even if
  1839. // the number of records is 0). Let us deallocate it
  1840. //
  1841. FreeDbMemory(pStartBuff, NoOfLocalDbRecs, pTls);
  1842. //
  1843. // Make the min. version number 1 more than the the
  1844. // max. vers. no. we used last time
  1845. //
  1846. NMSNMH_INC_VERS_NO_M(MaxVersNo, MinVersNo);
  1847. } while (LiLtr(MaxVersNo,MaxVersNoSave));
  1848. if (fDlgStarted)
  1849. {
  1850. ECommEndDlg(&DlgHdl);
  1851. fDlgStarted = FALSE;
  1852. }
  1853. if ((WinsCnf.LogDetailedEvts > 0) &&
  1854. fPulledAtLeastOnce)
  1855. {
  1856. WinsEvtLogDetEvt(TRUE, WINS_EVT_CC_NO_RECS, NULL,
  1857. __LINE__, "ddd", TotPulledRecsFromOneWins,
  1858. OwnerWinsAdd.Add.IPAdd, VerifyWinsAdd.Add.IPAdd);
  1859. DBGPRINT3(SCV, "VerifyDbData: WINS pulled (%d) records owned by WINS= (%x) from WINS = (%x) for doing CC\n",
  1860. TotPulledRecsFromOneWins, OwnerWinsAdd.Add.IPAdd, VerifyWinsAdd.Add.IPAdd);
  1861. }
  1862. //
  1863. // Total no. of records pulled so far
  1864. //
  1865. TotNoOfPulledRecs += TotPulledRecsFromOneWins;
  1866. } //end of for loop for looping over owners
  1867. //
  1868. // We are done for this cycle. If this was a CC verify, set
  1869. // sFirstOwnerId to the index of the WINS to start from in the next
  1870. // periodic CC cycle
  1871. //
  1872. if (fPeriodicCC)
  1873. {
  1874. sFirstOwnerId = i;
  1875. }
  1876. } // end of try
  1877. except(EXCEPTION_EXECUTE_HANDLER) {
  1878. DBGPRINTEXC("VerifyDbData");
  1879. DBGPRINT2(EXC, "VerifyDbData: i is (%d), MaxOwnerIdFound is (%d)\n",i, MaxOwnerIdFound);
  1880. //--ft: bug #422659--
  1881. // if an exception happens between EstablishCommForVerify and ECommEndDlg
  1882. // we need to make sure we close the connection - otherwise the connection
  1883. // remains active and the sender WINS eventually get stucked in send().
  1884. if (fDlgStarted)
  1885. ECommEndDlg(&DlgHdl);
  1886. WINS_RERAISE_EXC_M();
  1887. }
  1888. //
  1889. // Set the priority back the old level
  1890. //
  1891. WinsMscSetThreadPriority(
  1892. WinsThdPool.ScvThds[0].ThdHdl,
  1893. pScvParam->PrLvl
  1894. );
  1895. DBGLEAVE("VerifyDbData\n");
  1896. return(WINS_SUCCESS);
  1897. } // VerifyDbData()
  1898. STATUS
  1899. PickWinsToUse(
  1900. IN PCOMM_ADD_T pVerifyWinsAdd,
  1901. IN PCOMM_ADD_T pOwnerWinsAdd,
  1902. IN BOOL fUseRplPnrs,
  1903. OUT LPBOOL pfNonOwnerPnr,
  1904. OUT LPBOOL pfRplType
  1905. )
  1906. /*++
  1907. Routine Description:
  1908. This function picks a WINS to verify the active replicas with
  1909. Arguments:
  1910. Externals Used:
  1911. None
  1912. Return Value:
  1913. Success status codes --
  1914. Error status codes --
  1915. Error Handling:
  1916. Called by:
  1917. Side Effects:
  1918. Comments:
  1919. None
  1920. --*/
  1921. {
  1922. PRPL_CONFIG_REC_T pRplPnr;
  1923. DWORD IndexOfPnrToUse;
  1924. STATUS RetStat = WINS_SUCCESS;
  1925. *pfNonOwnerPnr = FALSE;
  1926. DBGENTER("PickWinsToUse\n");
  1927. //
  1928. // If the admin. specified that we should just use
  1929. // our replication partners for consistency checking,
  1930. // pick a replication partner for this.
  1931. //
  1932. *pfNonOwnerPnr = FALSE;
  1933. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1934. try {
  1935. pRplPnr = RplGetConfigRec(RPL_E_PULL, NULL, pOwnerWinsAdd);
  1936. if (fUseRplPnrs)
  1937. {
  1938. //
  1939. // If this guy is not a partner but there are other partners that
  1940. // we can pick from, pick one
  1941. //
  1942. if (pRplPnr == NULL)
  1943. {
  1944. if (WinsCnf.PullInfo.NoOfPushPnrs > 0)
  1945. {
  1946. //
  1947. // Just use one of the pnrs. Pick one at
  1948. // random
  1949. //
  1950. *pfRplType = WinsCnf.PullInfo.RplType;
  1951. srand((unsigned)time(NULL));
  1952. IndexOfPnrToUse = rand() % WinsCnf.PullInfo.NoOfPushPnrs;
  1953. *pVerifyWinsAdd = ((PRPL_CONFIG_REC_T)((LPBYTE)WinsCnf.PullInfo.pPullCnfRecs + (IndexOfPnrToUse * RPL_CONFIG_REC_SIZE)))->WinsAdd;
  1954. *pfNonOwnerPnr = TRUE;
  1955. }
  1956. else
  1957. {
  1958. DBGPRINT0(ERR, "PickWinsToUse: CC checking NOT DONE since no partners are there\n");
  1959. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_CC_FAILED);
  1960. RetStat = WINS_FAILURE;
  1961. }
  1962. }
  1963. else
  1964. {
  1965. *pfRplType = pRplPnr->RplType;
  1966. }
  1967. } // if (fUseRplPnr)
  1968. else
  1969. {
  1970. *pfRplType = (pRplPnr != NULL) ? pRplPnr->RplType : WinsCnf.PullInfo.RplType;
  1971. }
  1972. } // end if try {..}
  1973. finally {
  1974. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1975. if (RetStat == WINS_SUCCESS)
  1976. {
  1977. //
  1978. // If we are to communicate with the owner WINS, set *pVerifyWinsAdd
  1979. // since it was not set above.
  1980. //
  1981. if (!*pfNonOwnerPnr)
  1982. {
  1983. *pVerifyWinsAdd = *pOwnerWinsAdd;
  1984. }
  1985. DBGPRINT3(DET, "VerifyDbData: Using pnr no = (%d) with address = (%x) for verification of records owned by WINS (%x)\n", IndexOfPnrToUse, pVerifyWinsAdd->Add.IPAdd, pOwnerWinsAdd->Add.IPAdd)
  1986. }
  1987. }
  1988. DBGLEAVE("PickWinsToUse\n");
  1989. return (RetStat);
  1990. } //PickWinsToUse()
  1991. STATUS
  1992. EstablishCommForVerify(
  1993. PCOMM_ADD_T pWinsAdd,
  1994. PCOMM_HDL_T pDlgHdl
  1995. )
  1996. /*++
  1997. Routine Description:
  1998. This function is called to setup communication with a WINS
  1999. Arguments:
  2000. Externals Used:
  2001. None
  2002. Return Value:
  2003. Success status codes --
  2004. Error status codes --
  2005. Error Handling:
  2006. Called by:
  2007. Side Effects:
  2008. Comments:
  2009. None
  2010. --*/
  2011. {
  2012. //DWORD NoOfRetries = 0;
  2013. BOOL fAbort = FALSE;
  2014. STATUS RetStat = WINS_SUCCESS;
  2015. DBGENTER("EstablishCommForVerify\n");
  2016. //
  2017. // We try a certain number of times to establish a
  2018. // a dialogue. Currently, it is 1.
  2019. //
  2020. do
  2021. {
  2022. try {
  2023. ECommStartDlg( pWinsAdd, WINS_E_NMSSCV, pDlgHdl );
  2024. }
  2025. except(EXCEPTION_EXECUTE_HANDLER) {
  2026. DBGPRINTEXC("VerifyDbData");
  2027. if (GetExceptionCode() == WINS_EXC_COMM_FAIL)
  2028. {
  2029. DBGPRINT1(EXC, "VerifyDbData: Could not start a dlg with WINS at address (%x)\n", pWinsAdd->Add.IPAdd);
  2030. //--ft: 07/10/00 commented out since VERIFY_NO_OF_RETRIES is 0 anyhow so the test is always false.
  2031. //if (NoOfRetries++ < VERIFY_NO_OF_RETRIES)
  2032. //{
  2033. // Sleep(VERIFY_RETRY_TIME_INTERVAL);
  2034. // continue;
  2035. //}
  2036. RetStat = WINS_FAILURE;
  2037. }
  2038. else
  2039. {
  2040. //
  2041. // This is a serious error. Log and abort the verify cycle
  2042. //
  2043. WINSEVT_LOG_M(WINS_FATAL_ERR, WINS_EVT_SFT_ERR);
  2044. RetStat = WINS_FAILURE;
  2045. }
  2046. } // end of exception handler
  2047. break;
  2048. } while (TRUE);
  2049. if (RetStat == WINS_FAILURE)
  2050. {
  2051. DBGPRINT1(ERR, "EstablishCommForVerify: Could not start dlg with WINS at address (%x)\n", pWinsAdd->Add.IPAdd);
  2052. }
  2053. DBGLEAVE("EstablishCommForVerify\n");
  2054. return(RetStat);
  2055. } // EstablishCommForVerify()
  2056. VOID
  2057. PullAndUpdateDb(
  2058. PCOMM_HDL_T pDlgHdl,
  2059. PCOMM_ADD_T pOwnerWinsAdd,
  2060. PRPL_REC_ENTRY_T pRspBuff,
  2061. DWORD WinsIndex,
  2062. VERS_NO_T MinVersNo,
  2063. VERS_NO_T MaxVersNo,
  2064. DWORD RplType,
  2065. DWORD NoOfLocalDbRecs,
  2066. time_t CurrentTime,
  2067. PNMSSCV_PARAM_T pScvParam,
  2068. BOOL fNonOwnerPnr,
  2069. LPDWORD pTotNoPulledFromOneWins
  2070. )
  2071. /*++
  2072. Routine Description:
  2073. This pulls the records in the range specified and then updates the db
  2074. accordingly
  2075. Arguments:
  2076. Externals Used:
  2077. None
  2078. Return Value:
  2079. NONE
  2080. Error Handling:
  2081. Called by:
  2082. VerifyDbData()
  2083. Side Effects:
  2084. Comments:
  2085. None
  2086. --*/
  2087. {
  2088. LPBYTE pBuffOfPulledRecs;
  2089. VERS_NO_T VersNo;
  2090. DWORD NoOfPulledRecs;
  2091. DBGENTER("PullAndUpdateDb\n");
  2092. while (TRUE)
  2093. {
  2094. //
  2095. //Pull the records in the range min-max determined
  2096. //above
  2097. //
  2098. RplPullPullEntries(
  2099. pDlgHdl,
  2100. WinsIndex,
  2101. MaxVersNo,
  2102. MinVersNo,
  2103. WINS_E_NMSSCV,
  2104. &pBuffOfPulledRecs,
  2105. FALSE, //do not want to update counters
  2106. RplType
  2107. );
  2108. //
  2109. // Update the DB. All valid records are updated.
  2110. // The invalid records are deleted from the db
  2111. //
  2112. ChkConfNUpd(
  2113. #if SUPPORT612WINS > 0
  2114. pDlgHdl,
  2115. #endif
  2116. pOwnerWinsAdd,
  2117. RplType,
  2118. WinsIndex,
  2119. &pRspBuff,
  2120. pBuffOfPulledRecs,
  2121. &NoOfLocalDbRecs,
  2122. CurrentTime,
  2123. pScvParam->VerifyInterval,
  2124. fNonOwnerPnr,
  2125. &NoOfPulledRecs,
  2126. &VersNo
  2127. );
  2128. *pTotNoPulledFromOneWins += NoOfPulledRecs;
  2129. //
  2130. // Free the response buffer
  2131. //
  2132. ECommFreeBuff(pBuffOfPulledRecs - COMM_HEADER_SIZE);
  2133. //
  2134. //If vers. no. pulled is smaller than the Max. Vers
  2135. //no, specified, check if it is because of the limit
  2136. //we have set for the max. number or records that
  2137. //can be replicated at a time. If yes, pull again.
  2138. //
  2139. if (
  2140. LiLtr(VersNo, MaxVersNo)
  2141. &&
  2142. (NoOfPulledRecs == RPL_MAX_LIMIT_FOR_RPL)
  2143. )
  2144. {
  2145. MinVersNo = VersNo;
  2146. NMSNMH_INC_VERS_NO_M(MinVersNo, MinVersNo);
  2147. continue;
  2148. }
  2149. break; //break out of the loop
  2150. } //end of while (pulled all records in the range from pnr)_
  2151. DBGLEAVE("PullAndUpdateDb\n");
  2152. return;
  2153. } // PullAndUpdateDb()
  2154. __inline
  2155. VOID
  2156. FreeDbMemory(
  2157. LPVOID pStartBuff,
  2158. DWORD NoOfLocalDbRecs,
  2159. PWINSTHD_TLS_T pTls
  2160. )
  2161. /*++
  2162. Routine Description:
  2163. Frees the memory allocated by NmsDbGetDataRecs()
  2164. Arguments:
  2165. Externals Used:
  2166. None
  2167. Return Value:
  2168. NONE
  2169. Error Handling:
  2170. Called by:
  2171. VerifyDbData()
  2172. Side Effects:
  2173. Comments:
  2174. None
  2175. --*/
  2176. {
  2177. PRPL_REC_ENTRY_T pRec;
  2178. DWORD RecCnt;
  2179. for (
  2180. RecCnt=0, pRec = pStartBuff;
  2181. RecCnt < NoOfLocalDbRecs;
  2182. RecCnt++
  2183. )
  2184. {
  2185. WinsMscHeapFree(pTls->HeapHdl, pRec->pName);
  2186. pRec = (PRPL_REC_ENTRY_T)( (LPBYTE)pRec + RPL_REC_ENTRY_SIZE );
  2187. }
  2188. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  2189. WinsMscHeapDestroy(pTls->HeapHdl);
  2190. return;
  2191. } // FreeDbMemory ()
  2192. VOID
  2193. ChkConfNUpd(
  2194. #if SUPPORT612WINS > 0
  2195. IN PCOMM_HDL_T pDlgHdl,
  2196. #endif
  2197. IN PCOMM_ADD_T pOwnerWinsAdd,
  2198. IN DWORD RplType,
  2199. IN DWORD OwnerId,
  2200. IN PRPL_REC_ENTRY_T *ppLocalDbRecs,
  2201. IN LPBYTE pRspBuff,
  2202. IN DWORD *pNoOfLocalDbRecs,
  2203. IN time_t CurrentTime,
  2204. IN DWORD VerifyTimeIntvl,
  2205. IN BOOL fNonOwnerPnr,
  2206. OUT LPDWORD pNoOfPulledRecs,
  2207. OUT PVERS_NO_T pMaxVersNo
  2208. )
  2209. /*++
  2210. Routine Description:
  2211. This function compares the records that have been pulled from
  2212. a WINS with those in its local db. If the comparison is successful,
  2213. the record's timestamp in the local db is updated. If the
  2214. comparison is unsuccessful (i.e. the record in the local db has
  2215. no match in the list of records pulled from the remote WINS, the
  2216. record is deleted in the local db
  2217. Arguments:
  2218. pLocalDbRecs - Address of buffer holding the local active replicas
  2219. pRspBuff - Buffer containing records pulled from the remote WINS
  2220. NoOfLocalDbRecs - No of local replicas in the above buffer
  2221. Externals Used:
  2222. None
  2223. Return Value:
  2224. NONE
  2225. Error Handling:
  2226. Called by:
  2227. VerifyDbData()
  2228. Side Effects:
  2229. Comments:
  2230. None
  2231. --*/
  2232. {
  2233. DWORD NoOfPulledRecs;
  2234. BYTE Name[NMSDB_MAX_NAM_LEN];
  2235. DWORD NameLen;
  2236. BOOL fGrp;
  2237. DWORD NoOfAdds;
  2238. COMM_ADD_T NodeAdd[NMSDB_MAX_MEMS_IN_GRP * 2]; //twice the # of
  2239. VERS_NO_T VersNo;
  2240. LPBYTE pTmp = pRspBuff + 4; //past the opcode
  2241. DWORD i, j;
  2242. PRPL_REC_ENTRY_T pRecLcl;
  2243. DWORD NoOfRecsDel = 0;
  2244. PRPL_REC_ENTRY_T pStartOfLocalRecs = *ppLocalDbRecs;
  2245. DWORD MvNoOfLocalDbRecs = *pNoOfLocalDbRecs;
  2246. DWORD Flag;
  2247. DWORD NoOfRecsUpd = 0;
  2248. DWORD NoOfRecsIns = 0;
  2249. struct in_addr InAddr;
  2250. #if SUPPORT612WINS > 0
  2251. BOOL fIsPnrBeta1Wins;
  2252. #endif
  2253. DBGENTER("ChkConfNUpd\n");
  2254. //
  2255. // Set the current index to be the clustered index
  2256. //
  2257. NmsDbSetCurrentIndex(
  2258. NMSDB_E_NAM_ADD_TBL_NM,
  2259. NMSDB_NAM_ADD_CLUST_INDEX_NAME
  2260. );
  2261. #if SUPPORT612WINS > 0
  2262. COMM_IS_PNR_BETA1_WINS_M(pDlgHdl, fIsPnrBeta1Wins);
  2263. #endif
  2264. /*
  2265. * Get the no of records from the response and also the first record
  2266. * if there is at least one record in the buffer
  2267. */
  2268. RplMsgfUfmSndEntriesRsp(
  2269. #if SUPPORT612WINS > 0
  2270. fIsPnrBeta1Wins,
  2271. #endif
  2272. &pTmp,
  2273. &NoOfPulledRecs,
  2274. Name,
  2275. &NameLen,
  2276. &fGrp,
  2277. &NoOfAdds,
  2278. NodeAdd,
  2279. &Flag,
  2280. &VersNo,
  2281. TRUE /*Is it first time*/
  2282. );
  2283. if (WinsCnf.LogDetailedEvts > 0)
  2284. {
  2285. PCOMMASSOC_DLG_CTX_T pDlgCtx = pDlgHdl->pEnt;
  2286. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = pDlgCtx->AssocHdl.pEnt;
  2287. DWORD IpPartner = pAssocCtx->RemoteAdd.sin_addr.s_addr;
  2288. WinsEvtLogDetEvt(TRUE, WINS_EVT_REC_PULLED, TEXT("Verification"), __LINE__, "ddd", IpPartner, pOwnerWinsAdd->Add.IPAdd, NoOfPulledRecs);
  2289. }
  2290. DBGPRINT3(SCV, "ChkConfNUpd: pulled Records - (%d), local records - (%d), local records Buf (%p)\n",
  2291. NoOfPulledRecs, *pNoOfLocalDbRecs, pStartOfLocalRecs);
  2292. *pNoOfPulledRecs = NoOfPulledRecs;
  2293. if (NoOfPulledRecs > 0)
  2294. {
  2295. NMSSCV_REC_ACTION_E RecAction_e;
  2296. //
  2297. // After this function returns, all local records that have
  2298. // a version number < the version record of the pulled record
  2299. // will be marked deleted. Also, if there is a local record
  2300. // with the same version number as the pulled record but a
  2301. // different name it will be marked for deletion and fAddDiff
  2302. // will be set to TRUE so that we register the pulled record
  2303. // A local record with the same name and version number as
  2304. // the pulled one will be updated (timestamp only) in the db.
  2305. //
  2306. CompareWithLocalRecs(
  2307. VersNo,
  2308. Name,
  2309. NMSDB_ENTRY_STATE_M(Flag),
  2310. &pStartOfLocalRecs,
  2311. &MvNoOfLocalDbRecs,
  2312. CurrentTime,
  2313. fNonOwnerPnr,
  2314. &NoOfRecsDel,
  2315. &RecAction_e
  2316. );
  2317. //
  2318. // If RecAction_e is NMSSCV_E_INSERT and the record is
  2319. // marked as DELETED, it means that the pulled record
  2320. // has the same version number but a different name.
  2321. // This should never happen in a consistent system of
  2322. // WINS servers. The fact that it happened means that
  2323. // the administrator has goofed up. The remote WINS server
  2324. // has started afresh (new database) or its database got
  2325. // corrupted. If any of the above did happen, the
  2326. // administrator should have made sure that at startup,
  2327. // the WINS server was starting from a version counter
  2328. // value that was not less than what any of the other WINS
  2329. // servers thought it to be in.
  2330. //
  2331. // To bring the database upto snuff, this WINS server will
  2332. // register this replica. If there is a clash, it will
  2333. // be handled appropriately. One can think of this as
  2334. // a pulling in of replicas at replication time.
  2335. //
  2336. for (
  2337. i = 0, pRecLcl = *ppLocalDbRecs;
  2338. pRecLcl < pStartOfLocalRecs;
  2339. i++
  2340. )
  2341. {
  2342. //
  2343. //
  2344. // We update/delete the record depending upon the
  2345. // Flag value set by Compare
  2346. // not interested in the return code
  2347. //
  2348. pRecLcl->NewTimeStamp = (DWORD)CurrentTime + VerifyTimeIntvl;
  2349. NmsDbQueryNUpdIfMatch(
  2350. pRecLcl,
  2351. THREAD_PRIORITY_NORMAL,
  2352. FALSE, //don't change pr. lvl
  2353. WINS_E_NMSSCV
  2354. );
  2355. NoOfRecsUpd++;
  2356. pRecLcl = (PRPL_REC_ENTRY_T)((LPBYTE)pRecLcl +
  2357. RPL_REC_ENTRY_SIZE);
  2358. }
  2359. //
  2360. // register the replica if it needs to be inserted
  2361. //
  2362. if (RecAction_e == NMSSCV_E_INSERT)
  2363. {
  2364. RplPullRegRepl(
  2365. Name,
  2366. NameLen,
  2367. Flag,
  2368. OwnerId,
  2369. VersNo,
  2370. NoOfAdds,
  2371. NodeAdd,
  2372. pOwnerWinsAdd,
  2373. RplType
  2374. );
  2375. NoOfRecsIns++;
  2376. }
  2377. //
  2378. // Do until we have covered all the local records.
  2379. //
  2380. for (i=1; MvNoOfLocalDbRecs > 0; i++)
  2381. {
  2382. //
  2383. // if we have retrieved all the pull records, use a
  2384. // version number that is > the highest in the local
  2385. // db recs cache so that all the records more than
  2386. // the highest version # pulled get deleted -
  2387. // Check out CompareWithLocalRecs()
  2388. //
  2389. if (i < NoOfPulledRecs)
  2390. {
  2391. RplMsgfUfmSndEntriesRsp(
  2392. #if SUPPORT612WINS > 0
  2393. fIsPnrBeta1Wins,
  2394. #endif
  2395. &pTmp,
  2396. &NoOfPulledRecs,
  2397. Name,
  2398. &NameLen,
  2399. &fGrp,
  2400. &NoOfAdds,
  2401. NodeAdd,
  2402. &Flag,
  2403. &VersNo,
  2404. FALSE /*Is it first time*/
  2405. );
  2406. }
  2407. else
  2408. {
  2409. //
  2410. // Find out if this is the end of replica records.
  2411. // if we pulled exactly RPL_MAX_LIMIT_FOR_RPL, then that
  2412. // may mean that there is more to come. In that case we just
  2413. // get out of the loop and pull next lot.
  2414. //
  2415. // otherwise, this is the last record from the replica.
  2416. // we set VerNo to highest value so that all the local records
  2417. // more than the highest vers no of the pulled records get
  2418. // deleted.
  2419. //
  2420. if ( RPL_MAX_LIMIT_FOR_RPL == NoOfPulledRecs )
  2421. {
  2422. break;
  2423. } else {
  2424. if (VersNo.HighPart != MAXLONG)
  2425. {
  2426. VersNo.LowPart = MAXULONG;
  2427. VersNo.HighPart = MAXLONG;
  2428. }
  2429. }
  2430. }
  2431. //
  2432. //See if there is a hit with a local record. If there
  2433. //is a hit, we update the time stamp of the hit
  2434. //record, else we delete it
  2435. //
  2436. // First set, pRecLcl to the address of the first
  2437. // local record since pStartOfLocalRecs can be changed
  2438. // by this function. Actually, there is no need to
  2439. // do this. pRecLcl will be set already
  2440. //
  2441. pRecLcl = pStartOfLocalRecs;
  2442. CompareWithLocalRecs(
  2443. VersNo,
  2444. Name,
  2445. NMSDB_ENTRY_STATE_M(Flag),
  2446. &pStartOfLocalRecs,
  2447. &MvNoOfLocalDbRecs,
  2448. CurrentTime,
  2449. fNonOwnerPnr,
  2450. &NoOfRecsDel,
  2451. &RecAction_e
  2452. );
  2453. //
  2454. // All records upto the new first local record should
  2455. // be updated/deleted
  2456. //
  2457. for (
  2458. j = 0;
  2459. pRecLcl < pStartOfLocalRecs;
  2460. j++
  2461. )
  2462. {
  2463. //
  2464. //We update/delete the record depending
  2465. //upon the Flag value set by Compare
  2466. // not interested in the return code
  2467. //
  2468. pRecLcl->NewTimeStamp = (DWORD)CurrentTime + VerifyTimeIntvl;
  2469. NmsDbQueryNUpdIfMatch(
  2470. pRecLcl,
  2471. THREAD_PRIORITY_NORMAL,
  2472. FALSE, //don't change pr. lvl
  2473. WINS_E_NMSSCV
  2474. );
  2475. NoOfRecsUpd++;
  2476. pRecLcl = (PRPL_REC_ENTRY_T)((LPBYTE)pRecLcl +
  2477. RPL_REC_ENTRY_SIZE);
  2478. }
  2479. //
  2480. // register the replica if it needs to be inserted
  2481. //
  2482. if (RecAction_e == NMSSCV_E_INSERT)
  2483. {
  2484. RplPullRegRepl(
  2485. Name,
  2486. NameLen,
  2487. Flag,
  2488. OwnerId,
  2489. VersNo,
  2490. NoOfAdds,
  2491. NodeAdd,
  2492. pOwnerWinsAdd,
  2493. RplType
  2494. );
  2495. NoOfRecsIns++;
  2496. }
  2497. }
  2498. //
  2499. // Whatever records were not retrieved must be retrieved
  2500. // now and then inserted
  2501. //
  2502. for (j=i; j < NoOfPulledRecs; j++)
  2503. {
  2504. RplMsgfUfmSndEntriesRsp(
  2505. #if SUPPORT612WINS > 0
  2506. fIsPnrBeta1Wins,
  2507. #endif
  2508. &pTmp,
  2509. &NoOfPulledRecs,
  2510. Name,
  2511. &NameLen,
  2512. &fGrp,
  2513. &NoOfAdds,
  2514. NodeAdd,
  2515. &Flag,
  2516. &VersNo,
  2517. FALSE /*Is it first time*/
  2518. );
  2519. RplPullRegRepl(
  2520. Name,
  2521. NameLen,
  2522. Flag,
  2523. OwnerId,
  2524. VersNo,
  2525. NoOfAdds,
  2526. NodeAdd,
  2527. pOwnerWinsAdd,
  2528. RplType
  2529. );
  2530. NoOfRecsIns++;
  2531. }
  2532. }
  2533. else // we got 0 records from the remote WINS server. It means that
  2534. // all the active replicas for this WINS need to be deleted
  2535. {
  2536. //
  2537. // We delete records only if the pnr with which we are doing
  2538. // verification is the owner of the records
  2539. //
  2540. VersNo.QuadPart = 0;
  2541. if (!fNonOwnerPnr)
  2542. {
  2543. pRecLcl = *ppLocalDbRecs;
  2544. //
  2545. // Change state of all replicas that we retrieved to deleted
  2546. //
  2547. for (i = 0; i < *pNoOfLocalDbRecs; i++)
  2548. {
  2549. NMSDB_SET_STATE_M(pRecLcl->Flag, NMSDB_E_DELETED);
  2550. //
  2551. //
  2552. // We update/delete the record depending upon the
  2553. // Flag value set by Compare
  2554. // not interested in the return code
  2555. //
  2556. NmsDbQueryNUpdIfMatch(
  2557. pRecLcl,
  2558. THREAD_PRIORITY_NORMAL,
  2559. FALSE, //don't change pr. lvl
  2560. WINS_E_NMSSCV
  2561. );
  2562. pRecLcl = (PRPL_REC_ENTRY_T)((LPBYTE)pRecLcl +
  2563. RPL_REC_ENTRY_SIZE);
  2564. NoOfRecsDel++;
  2565. }
  2566. }
  2567. }
  2568. //
  2569. // Update our couters/pointers for the next iterations.
  2570. // see PullAndUpdateDb routine.
  2571. //
  2572. *pMaxVersNo = VersNo;
  2573. *ppLocalDbRecs = pStartOfLocalRecs;
  2574. *pNoOfLocalDbRecs = MvNoOfLocalDbRecs;
  2575. if (WinsCnf.LogDetailedEvts > 0)
  2576. {
  2577. InAddr.s_addr = htonl(pOwnerWinsAdd->Add.IPAdd);
  2578. WinsEvtLogDetEvt(TRUE, WINS_EVT_CC_STATS, NULL, __LINE__, "sddd", inet_ntoa(InAddr), NoOfRecsIns, NoOfRecsUpd, NoOfRecsDel);
  2579. }
  2580. DBGPRINT4(DET, "ChkConfNUpd: Wins = (%s). NO OF RECS INSERTED = (%d); NO OF RECORDS UPDATED = (%d); NO OF RECS DELETED = (%d)\n", inet_ntoa(InAddr), NoOfRecsIns, NoOfRecsUpd, NoOfRecsDel);
  2581. DBGLEAVE("ChkConfNUpd\n");
  2582. return;
  2583. } // ChkConfNUpd()
  2584. VOID
  2585. CompareWithLocalRecs(
  2586. IN VERS_NO_T VersNo,
  2587. IN LPBYTE pName,
  2588. IN NMSDB_ENTRY_STATE_E RecState_e,
  2589. IN OUT PRPL_REC_ENTRY_T *ppLocalDbRecs,
  2590. IN OUT DWORD *pNoOfLocalRecs,
  2591. IN time_t CurrentTime,
  2592. IN BOOL fNonOwnerPnr,
  2593. IN OUT DWORD *pNoOfRecsDel,
  2594. OUT PNMSSCV_REC_ACTION_E pRecAction_e
  2595. )
  2596. /*++
  2597. Routine Description:
  2598. This function checks if the pulled record is in the buffer containing
  2599. local active replicas. If it is, it is marked for update (timestamp)
  2600. If it is not, then all replicas in the buffer that have a version
  2601. stamp < the pulled record are marked for deletion
  2602. Arguments:
  2603. VersNo - Version no. of the pulled record
  2604. pName - Name in the pulled record
  2605. ppLocalDbRecs - ptr to address of buffer containing one or more
  2606. local active replicas
  2607. pNoOfLocalRecs - count of records in the above buffer
  2608. pNoOfRecsDel - count of records to be deleted
  2609. Externals Used:
  2610. None
  2611. Return Value:
  2612. None
  2613. Error Handling:
  2614. Called by:
  2615. ChkConfNUpd()
  2616. Side Effects:
  2617. Comments:
  2618. None
  2619. --*/
  2620. {
  2621. DWORD i;
  2622. PRPL_REC_ENTRY_T pRecLcl = *ppLocalDbRecs;
  2623. #ifdef UNICODE
  2624. WCHAR NameLcl[WINS_MAX_FILENAME_SZ];
  2625. WCHAR NameRem[WINS_MAX_FILENAME_SZ];
  2626. #endif
  2627. //
  2628. // default is don't insert.
  2629. //
  2630. *pRecAction_e = NMSSCV_E_DONT_INSERT;
  2631. //
  2632. // Loop over all local replicas
  2633. //
  2634. for(i=0; i < *pNoOfLocalRecs; i++)
  2635. {
  2636. //
  2637. // if version number of pulled record is less, we should get the
  2638. // next pulled record from the response buffer. We should
  2639. // insert this one into our db
  2640. //
  2641. if (LiLtr(VersNo, pRecLcl->VersNo))
  2642. {
  2643. #if 0
  2644. //
  2645. // We don't insert tombstones
  2646. //
  2647. if (RecState_e == NMSDB_E_ACTIVE)
  2648. #endif
  2649. //
  2650. // Even tombstones are inserted because we may
  2651. // have just got rid of the active record (lower
  2652. // version number than this tombstone). The above
  2653. // is TRUE only when pulling from an owner WINS
  2654. //
  2655. if ((RecState_e == NMSDB_E_ACTIVE) || !fNonOwnerPnr)
  2656. {
  2657. *pRecAction_e = NMSSCV_E_INSERT;
  2658. }
  2659. break;
  2660. }
  2661. else
  2662. {
  2663. //
  2664. // if version number is same, we need to update this record
  2665. // in our local db. We mark it for update. Caveat:
  2666. // if we are verifying with a non-owner, we don't mark
  2667. // record for deletion. We just keep it since we don't
  2668. // know who is more current (we or our replication partner)
  2669. //
  2670. if (LiEql(VersNo, pRecLcl->VersNo))
  2671. {
  2672. if (
  2673. !(RtlCompareMemory(pRecLcl->pName, pName,
  2674. pRecLcl->NameLen) == pRecLcl->NameLen)
  2675. &&
  2676. !fNonOwnerPnr
  2677. )
  2678. {
  2679. DBGPRINT2(DET, "CompareWithLocalRecs: Names are DIFFERENT. Name to Verify (%s), Name pulled (%s).\nThis could mean that the remote WINS server restarted with a vers. counter value < the value in the previous invocation.\n",
  2680. pRecLcl->pName/*pRecLcl->Name*/, pName);
  2681. FUTURES("Replace the local record with the pulled record")
  2682. NMSDB_SET_STATE_M(pRecLcl->Flag, NMSDB_E_DELETED);
  2683. (*pNoOfRecsDel)++;
  2684. //
  2685. // Insert record regardless of its state
  2686. // (ACTIVE or TOMBSTONE)
  2687. //
  2688. *pRecAction_e = NMSSCV_E_INSERT;
  2689. }
  2690. i++; //increment i so that we don't compare the
  2691. //the next pulled record with all local records
  2692. //upto the one we just compared this pulled
  2693. //record with
  2694. break;
  2695. }
  2696. else
  2697. {
  2698. //
  2699. // For the non-owner case, since we don't know whether
  2700. // our pnr is more/less current than us, we don't delete
  2701. // the local record
  2702. //
  2703. if (!fNonOwnerPnr)
  2704. {
  2705. //
  2706. // version number is greater than record in
  2707. // our local db. We delete our local db record
  2708. //
  2709. NMSDB_SET_STATE_M(pRecLcl->Flag, NMSDB_E_DELETED);
  2710. (*pNoOfRecsDel)++;
  2711. }
  2712. }
  2713. }
  2714. pRecLcl = (PRPL_REC_ENTRY_T)((LPBYTE)pRecLcl + RPL_REC_ENTRY_SIZE);
  2715. }
  2716. //
  2717. // Adjust the pointer in the buffer of local replicas so that next
  2718. // time we are called in this verify cycle, we don't look at
  2719. // the replicas we have already seen. Also, adjust the count.
  2720. //
  2721. *ppLocalDbRecs = (PRPL_REC_ENTRY_T)(
  2722. (LPBYTE)(*ppLocalDbRecs) + (i * RPL_REC_ENTRY_SIZE)
  2723. );
  2724. *pNoOfLocalRecs = *pNoOfLocalRecs - i;
  2725. return;
  2726. } //CompareWithLocalRecs
  2727. VOID
  2728. DoBackup(
  2729. PNMSSCV_PARAM_T pScvParam,
  2730. LPBOOL pfThdPrNormal
  2731. )
  2732. /*++
  2733. Routine Description:
  2734. Arguments:
  2735. Externals Used:
  2736. None
  2737. Return Value:
  2738. Success status codes --
  2739. Error status codes --
  2740. Error Handling:
  2741. Called by:
  2742. Side Effects:
  2743. Comments:
  2744. None
  2745. --*/
  2746. {
  2747. time_t CurrentTime;
  2748. (void)time(&CurrentTime);
  2749. //
  2750. // if logging is on and sufficient time has elapsed to warrant a
  2751. // another backup.
  2752. //
  2753. if (WinsCnf.fLoggingOn &&
  2754. (CurrentTime - sLastDbNullBackupTime) >= PERIOD_OF_LOG_DEL)
  2755. {
  2756. #ifdef WINSDBG
  2757. IF_DBG(HEAP_CNTRS)
  2758. {
  2759. WinsSetFlags(WINSINTF_MEMORY_INFO_DUMP | WINSINTF_HEAP_INFO_DUMP | WINSINTF_QUE_ITEMS_DUMP);
  2760. }
  2761. #endif
  2762. DBGPRINT0(DET, "DoBackup: Will do backup now\n");
  2763. if (!*pfThdPrNormal)
  2764. {
  2765. //
  2766. // Set thread priority back to normal
  2767. //
  2768. WinsMscSetThreadPriority(
  2769. WinsThdPool.ScvThds[0].ThdHdl,
  2770. THREAD_PRIORITY_NORMAL
  2771. );
  2772. *pfThdPrNormal = TRUE;
  2773. }
  2774. if (pScvParam->BackupDirPath[0] != EOS)
  2775. {
  2776. if (
  2777. (CurrentTime - sLastDbBackupTime) > PERIOD_OF_BACKUP)
  2778. {
  2779. if (NmsDbBackup(pScvParam->BackupDirPath,
  2780. NMSDB_FULL_BACKUP)
  2781. != WINS_SUCCESS)
  2782. {
  2783. //
  2784. // Failed to do full backup, just get rid of the
  2785. // log files.
  2786. //
  2787. DBGPRINT0(ERR, "DOING BACKUP to NULL\n");
  2788. NmsDbBackup(NULL, 0);
  2789. }
  2790. else
  2791. {
  2792. sLastDbBackupTime = CurrentTime;
  2793. }
  2794. }
  2795. else
  2796. {
  2797. DBGPRINT0(ERR, "DOING BACKUP to NULL\n");
  2798. NmsDbBackup(NULL, 0);
  2799. }
  2800. }
  2801. else
  2802. {
  2803. //
  2804. // Can not do full backup, just get rid of the
  2805. // log files.
  2806. //
  2807. DBGPRINT0(ERR, "DOING BACKUP to NULL\n");
  2808. NmsDbBackup(NULL, 0);
  2809. }
  2810. sLastDbNullBackupTime = CurrentTime;
  2811. }
  2812. return;
  2813. }
  2814. #if MCAST > 0
  2815. VOID
  2816. DoMcastSend(
  2817. DWORD_PTR CurrentTime,
  2818. DWORD Code,
  2819. DWORD fNow
  2820. )
  2821. {
  2822. if (fNow || (CurrentTime - sLastMcastTime) >= sMcastIntvl)
  2823. {
  2824. CommSendMcastMsg(Code);
  2825. if (!fNow)
  2826. {
  2827. sLastMcastTime = CurrentTime;
  2828. }
  2829. }
  2830. return;
  2831. }
  2832. #endif