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.

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