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.

1290 lines
42 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. rpl.c
  5. Abstract:
  6. This module contains functions used by the COMSYS and NMS components
  7. of WINS. It also contains functions used by both the Pull and Push
  8. handler components of the Replicator
  9. Functions:
  10. RplInit
  11. RplInsertQue
  12. RplFindOwnerId
  13. RplPushProc
  14. Portability:
  15. This module is portable
  16. Author:
  17. Pradeep Bahl (PradeepB) Jan-1993
  18. Revision History:
  19. Modification date Person Description of modification
  20. ----------------- ------- ----------------------------
  21. --*/
  22. /*
  23. * Includes
  24. */
  25. #include "wins.h"
  26. #include <winsock2.h>
  27. #include "nms.h"
  28. #include "nmsdb.h"
  29. #include "winsmsc.h"
  30. #include "winsevt.h"
  31. #include "winscnf.h"
  32. #include "winsque.h"
  33. #include "winsthd.h"
  34. #include "comm.h"
  35. #include "nmsnmh.h"
  36. #include "rpl.h"
  37. #include "rplmsgf.h"
  38. #include "rplpull.h"
  39. #include "rplpush.h"
  40. /*
  41. * Local Macro Declarations
  42. */
  43. #define INIT_REC_BUFF_HEAP_SIZE 1000 //1000 bytes
  44. //
  45. // defines for the local message sent by the replicator to the Push/Pull
  46. // thread and for setting the opcode in such a message
  47. //
  48. #define LOCAL_RPL_MSG_SZ (RPL_OPCODE_SIZE + COMM_BUFF_HEADER_SIZE + sizeof(LONG))
  49. #define SET_OPCODE_M(pBuff, Opc) { \
  50. *((pBuff) + LOCAL_RPL_MSG_SZ + 3) = \
  51. (Opc); \
  52. }
  53. #define USER_PORTION_M(pMsg) (pMsg + COMM_BUFF_HEADER_SIZE + sizeof(LONG))
  54. #define USER_LEN_M(TotalLen) (TotalLen - COMM_BUFF_HEADER_SIZE - sizeof(LONG))
  55. /*
  56. * Local Typedef Declarations
  57. */
  58. /*
  59. * Global Variable Definitions
  60. */
  61. HANDLE RplWrkItmHeapHdl;
  62. #if 0
  63. HANDLE RplRecHeapHdl;
  64. #endif
  65. HANDLE RplSyncWTcpThdEvtHdl; //Sync up with the TCP thread
  66. //
  67. // critical section to guard the RplPullOwnerVersNo array
  68. //
  69. CRITICAL_SECTION RplVersNoStoreCrtSec;
  70. /*
  71. * Local Variable Definitions
  72. */
  73. //
  74. // Critical Section that is instantiated only if this WINS server has
  75. // one or more Push Partners
  76. //
  77. CRITICAL_SECTION sPushNtfCrtSec;
  78. /*
  79. * Local Function Prototype Declarations
  80. */
  81. /* prototypes for functions local to this module go here */
  82. STATUS
  83. ERplInit(
  84. VOID
  85. )
  86. /*++
  87. Routine Description:
  88. This function is called to initialize the replicator.
  89. It creates the PULL and PUSH threads
  90. Arguments:
  91. pRplConfigRec - A list of configuration records
  92. Externals Used:
  93. None
  94. Return Value:
  95. Success status codes -- WINS_SUCCESS
  96. Error status codes -- WINS_FAILURE
  97. Error Handling:
  98. Called by:
  99. Init() in nms.c
  100. Side Effects:
  101. Comments:
  102. Replicator connections are dynamic. They are initiated when
  103. needed and terminated when they have served their purpose.
  104. If the connections were to be made STATIC, we would do the
  105. following in the above function:
  106. Start a dialogue with each pull partner. Also
  107. creates a dialogue with each of the WINS servers that we have to
  108. send a notification to.
  109. --*/
  110. {
  111. STATUS RetStat;
  112. //
  113. // Make a copy of the magic number
  114. //
  115. RplPullCnfMagicNo = WinsCnf.MagicNo;
  116. /*
  117. * Create heap for allocating Rpl work items
  118. */
  119. DBGPRINT0(HEAP_CRDL, "ERplInit: Rpl Wrk. Item. Heap\n");
  120. RplWrkItmHeapHdl = WinsMscHeapCreate(
  121. 0, /*to have mutual exclusion */
  122. RPL_WRKITM_BUFF_HEAP_SIZE
  123. );
  124. #if 0
  125. /*
  126. * Create heap for allocating memory for names that are longer
  127. * than 17 characters and for storing group members when the
  128. * number of members are > 5
  129. */
  130. RplRecHeapHdl = WinsMscHeapCreate(
  131. 0, /*to have mutual exclusion */
  132. INIT_REC_BUFF_HEAP_SIZE
  133. );
  134. #endif
  135. /*
  136. We create a PULL thread regardless of whether or not there
  137. was a PULL record in the configuration info (in the registry).
  138. This is because another WINS could send this WINS a push
  139. notification. This push notification will be received by the
  140. PUSH thread which will forward it to the PULL thread.
  141. Considering that a situation where an RQ server in a multi-RQ
  142. configuration not getting Push notifications or not pulling
  143. from another RQ server is rare, we go ahead and create the
  144. PULL thread.
  145. A redundent PULL thread is not much overhead. Creating a PULL thread
  146. on demand is going to be messier.
  147. */
  148. WinsMscCreateEvt(
  149. TEXT("RplPullSynchWTcpThdEvtHd"),
  150. FALSE, //auto-reset
  151. &RplSyncWTcpThdEvtHdl
  152. );
  153. //
  154. // Initialize the critical section that guards the
  155. // RplPullOwnerVersNo Table.
  156. //
  157. InitializeCriticalSection(&RplVersNoStoreCrtSec);
  158. RetStat = WinsMscSetUpThd(
  159. &QueRplPullQueHd,
  160. RplPullInit,
  161. &WinsCnf,
  162. &WinsThdPool.RplThds[WINSTHD_RPL_PULL_INDEX].ThdHdl,
  163. &WinsThdPool.RplThds[WINSTHD_RPL_PULL_INDEX].ThdId
  164. );
  165. if (RetStat == WINS_SUCCESS)
  166. {
  167. WinsThdPool.RplThds[WINSTHD_RPL_PULL_INDEX].fTaken =
  168. TRUE;
  169. WinsThdPool.ThdCount++; //increment the thread count
  170. }
  171. //
  172. // initialize the sPushNtfCrtSec Critical Section. This is
  173. // used by ERplPushProc
  174. //
  175. CHECK("Is this critical section needed. I don't think so")
  176. InitializeCriticalSection(&sPushNtfCrtSec);
  177. /*
  178. We create the PUSH thread regardless of whether or not there was
  179. any PUSH record in the configuration info in the registry. This is
  180. because, other WINS servers could pull from this WINS or send it
  181. a push notification.
  182. Perhaps we should wait until the first connection from a PULL
  183. partner is received. That however will complicate the design
  184. a bit more. Considering that a situation where nobody is pulling
  185. from the RQ server is going to be rare in a multi-RQ server
  186. configuration, we just go ahead and create the PUSH thread now
  187. and keep the design simple and clean.
  188. */
  189. PERF("Don't create the thread here. Let WinsQueInsertRplPushWrkItm create it")
  190. //
  191. // Set it to TRUE here before creating the thread instead of after
  192. // it has been created to escape the window where another thread
  193. // creates it from inside WinsQueInsertRplPushWrkItm (Not the
  194. // case currently)
  195. //
  196. fRplPushThdExists = TRUE;
  197. RetStat = WinsMscSetUpThd(
  198. &QueRplPushQueHd,
  199. RplPushInit,
  200. &WinsCnf,
  201. &WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdHdl,
  202. &WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdId
  203. );
  204. if (RetStat == WINS_SUCCESS)
  205. {
  206. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].fTaken =
  207. TRUE;
  208. WinsThdPool.ThdCount++; //increment the thread count
  209. }
  210. else
  211. {
  212. fRplPushThdExists = FALSE;
  213. }
  214. return(WINS_SUCCESS);
  215. }
  216. STATUS
  217. RplFindOwnerId (
  218. IN PCOMM_ADD_T pWinsAdd,
  219. IN OUT LPBOOL pfAllocNew,
  220. OUT DWORD UNALIGNED *pOwnerId,
  221. IN DWORD InitpAction_e,
  222. IN DWORD MemberPrec
  223. )
  224. /*++
  225. Routine Description:
  226. The function finds the owner id correponding to a WINS server.
  227. It searches the OwnerIdAddTbl for a match. If none is found, it
  228. creates a mapping in the table and returns with the same.
  229. Arguments:
  230. pWinsAdd -- Address of WINS whose owner id is sought
  231. pfAllocNew -- On input, if TRUE, assign an owner id. if this WINS is
  232. not known. On output indicates whether a new entry
  233. was allocated or old one (deleted one) reused
  234. pOwnerId -- Owner Id of WINS
  235. pNewStartVersNo - Start vers. no of this WINS.
  236. pOldStartVersNo - Start vers. no of this WINS that we have.
  237. pNewUid - Uid of the WINS
  238. pOldUid - Old Uid of the WINS
  239. Externals Used:
  240. NmsDbOwnAddTbl
  241. Return Value:
  242. Success status codes -- WINS_SUCCESS
  243. Error status codes -- WINS_FAILURE
  244. Error Handling:
  245. Called by:
  246. NmsDbGetDataRecs, HandleUpdVersNoReq in rplpush.c
  247. Side Effects:
  248. Comments:
  249. This function is always called with either the last 4 arguments being
  250. NULL or non-NULL.
  251. --*/
  252. {
  253. DWORD i;
  254. STATUS RetStat = WINS_SUCCESS;
  255. DWORD NoOfOwners;
  256. PNMSDB_ADD_STATE_T pOwnAddTbl = pNmsDbOwnAddTbl;
  257. BOOL fDelEntryFound = FALSE;
  258. DWORD OwnerIdOfFirstDelEntry;
  259. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  260. NoOfOwners = NmsDbNoOfOwners;
  261. try {
  262. /*
  263. * check OwnerIdAddTbl for a mapping
  264. */
  265. for (i = 0; i < NoOfOwners; i++, pOwnAddTbl++)
  266. {
  267. if (
  268. (ECommCompAdd(
  269. pWinsAdd,
  270. &(pOwnAddTbl->WinsAdd)
  271. ) == COMM_SAME_ADD)
  272. ||
  273. (pOwnAddTbl->WinsState_e ==
  274. NMSDB_E_WINS_DELETED)
  275. )
  276. {
  277. //
  278. // if the state of WINS in the in-memory table is
  279. // deleted, then we check if we are allowed (by the
  280. // client of this function) to allocate a new
  281. // entry (or reuse one that is deleted). If yes,
  282. // we change the state of this WINS to ACTIVE
  283. // and also update the database table
  284. //
  285. if (pOwnAddTbl->WinsState_e == NMSDB_E_WINS_DELETED)
  286. {
  287. if (!fDelEntryFound)
  288. {
  289. fDelEntryFound = TRUE;
  290. OwnerIdOfFirstDelEntry = i;
  291. }
  292. continue;
  293. }
  294. else // state is not deleted (means we found our entry)
  295. {
  296. #if 0
  297. ModifyRec();
  298. #endif
  299. //
  300. // Since we did not reuse an old one, set
  301. // *pfAllocNew to FALSE
  302. //
  303. *pfAllocNew = FALSE;
  304. }
  305. *pOwnerId = i;
  306. break;
  307. }
  308. }
  309. //
  310. // if we did not find any entry in the table ...
  311. //
  312. if (i == NoOfOwners)
  313. {
  314. //
  315. // If we are authorized to create an entry and we have one or
  316. // more vacant slots to do this ..
  317. //
  318. if (*pfAllocNew)
  319. {
  320. //
  321. // If we have a deleted entry, reuse it
  322. //
  323. if (fDelEntryFound)
  324. {
  325. pOwnAddTbl = pNmsDbOwnAddTbl+OwnerIdOfFirstDelEntry;
  326. pOwnAddTbl->WinsState_e = NMSDB_E_WINS_ACTIVE;
  327. pOwnAddTbl->WinsAdd = *pWinsAdd;
  328. #if 0
  329. AssignStartVersNo()
  330. #endif
  331. /*
  332. * Write the record into the database table
  333. */
  334. NmsDbWriteOwnAddTbl(
  335. NMSDB_E_INSERT_REC,
  336. OwnerIdOfFirstDelEntry,
  337. pWinsAdd,
  338. NMSDB_E_WINS_ACTIVE,
  339. &pOwnAddTbl->StartVersNo,
  340. &pOwnAddTbl->Uid
  341. );
  342. //
  343. // The above function has incremented the
  344. // number of owners. Since we reused
  345. // a deleted entry, let us correct the
  346. // count
  347. //
  348. NmsDbNoOfOwners--;
  349. *pOwnerId = OwnerIdOfFirstDelEntry;
  350. }
  351. else // we don't have a deleted entry
  352. {
  353. /*
  354. * If mapping could not be found, create one and store it
  355. *
  356. * Enter the critical section first since an RPC thread
  357. * may be accessing this table (WinsStatus())
  358. */
  359. if (i >= NmsDbTotNoOfSlots)
  360. {
  361. WINSMSC_REALLOC_M(
  362. sizeof(NMSDB_ADD_STATE_T)*(NmsDbTotNoOfSlots * 2),
  363. (LPVOID *)&pNmsDbOwnAddTbl
  364. );
  365. pOwnAddTbl = pNmsDbOwnAddTbl + NmsDbTotNoOfSlots;
  366. NmsDbTotNoOfSlots *= 2;
  367. DBGPRINT1(DET, "RplFindOwnerId: NO OF SLOTS IN NMSDBOWNASSTBL HAS BEEN INCREASED TO %d\n", NmsDbTotNoOfSlots);
  368. RplPullAllocVersNoArray(&pRplPullOwnerVersNo, (RplPullMaxNoOfWins * 2));
  369. RplPullMaxNoOfWins *= 2;
  370. DBGPRINT2(DET, "RplFindOwnerId: NO OF SLOTS IN NMSDBOWNADDTBL and in RPL_OWNER_VERS_NO_ARRAY HAS BEEN INCREASED TO (%d and %d)\n", NmsDbTotNoOfSlots, RplPullMaxNoOfWins);
  371. }
  372. pOwnAddTbl->WinsAdd = *pWinsAdd;
  373. pOwnAddTbl->WinsState_e = NMSDB_E_WINS_ACTIVE;
  374. #if 0
  375. InitStartVersNo()
  376. #endif
  377. *pOwnerId = i;
  378. /*
  379. * Write the record into the database table. The following
  380. * call will increment NmsDbNoOfOwners
  381. */
  382. NmsDbWriteOwnAddTbl(
  383. NMSDB_E_INSERT_REC,
  384. i,
  385. pWinsAdd,
  386. NMSDB_E_WINS_ACTIVE,
  387. &pOwnAddTbl->StartVersNo,
  388. &pOwnAddTbl->Uid
  389. );
  390. }
  391. }
  392. else //can't allocate a new one
  393. {
  394. //
  395. // if we weren't asked to allocate a new one, return a
  396. // failure code. If we were asked to allocate a new one,
  397. // raise an exception (serious error)
  398. //
  399. RetStat = WINS_FAILURE;
  400. *pfAllocNew = FALSE;
  401. }
  402. }
  403. }
  404. except(EXCEPTION_EXECUTE_HANDLER) {
  405. DBGPRINTEXC("RplFindOwnerId");
  406. RetStat = WINS_FAILURE;
  407. //
  408. // log a message
  409. //
  410. }
  411. //
  412. // if we were able to find the member or inserted it
  413. //
  414. if (RetStat != WINS_FAILURE)
  415. {
  416. if (
  417. (InitpAction_e == WINSCNF_E_INITP)
  418. ||
  419. (
  420. (InitpAction_e == WINSCNF_E_INITP_IF_NON_EXISTENT)
  421. &&
  422. (*pfAllocNew)
  423. )
  424. )
  425. {
  426. pOwnAddTbl->MemberPrec = MemberPrec;
  427. }
  428. }
  429. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  430. return(RetStat);
  431. }
  432. STATUS
  433. ERplInsertQue(
  434. WINS_CLIENT_E Client_e,
  435. QUE_CMD_TYP_E CmdType_e,
  436. PCOMM_HDL_T pDlgHdl,
  437. MSG_T pMsg,
  438. MSG_LEN_T MsgLen,
  439. LPVOID pClientCtx,
  440. DWORD MagicNo
  441. )
  442. /*++
  443. Routine Description:
  444. This function is called to queue a replicator request
  445. Arguments:
  446. Client_e - Client that is inserting the work item
  447. CmdType_e - Type of command to be specified in the work item
  448. pDlgHdl - Dlg Hdl if relevant to the work item
  449. pMsg - Message if this function is executing in a comm thread
  450. Msglen - Length of the message
  451. pClientCtx - Context of the client to insert in the work item
  452. Externals Used:
  453. None
  454. Return Value:
  455. Success status codes -- WINS_SUCCESS
  456. Error status codes -- WINS_FAILURE
  457. Error Handling:
  458. Called by:
  459. ParseMsg() in comm.c, HandleUpdNtf() in rplpush.c, etc
  460. Side Effects:
  461. Comments:
  462. None
  463. --*/
  464. {
  465. FUTURES("Move all this to queue.c; Enter and leave critical sections")
  466. PQUE_RPL_REQ_WRK_ITM_T pWrkItm;
  467. PQUE_TMM_REQ_WRK_ITM_T pTmmWrkItm;
  468. QueAllocWrkItm(
  469. RplWrkItmHeapHdl,
  470. sizeof(QUE_RPL_REQ_WRK_ITM_T),
  471. (LPVOID *)&pWrkItm
  472. );
  473. switch(CmdType_e)
  474. {
  475. /*
  476. Wrk item queues by COMSYS (tcp listener thread) -- when a
  477. replicator message has been received
  478. */
  479. case(QUE_E_CMD_REPLICATE_MSG):
  480. pWrkItm->pMsg = pMsg;
  481. pWrkItm->MsgLen = MsgLen;
  482. pWrkItm->DlgHdl = *pDlgHdl;
  483. pWrkItm->CmdTyp_e = CmdType_e;
  484. QueInsertRplPushWrkItm(
  485. (PLIST_ENTRY)pWrkItm,
  486. FALSE //we are not in the crit. sec.
  487. );
  488. break;
  489. //
  490. // Work items are also queued as a result of
  491. // administrative action
  492. //
  493. case(QUE_E_CMD_REPLICATE):
  494. case(QUE_E_CMD_PULL_RANGE):
  495. DBGPRINT0(FLOW,
  496. "RplInsertQue: PULL Trigger command from administrator\n"
  497. );
  498. pWrkItm->CmdTyp_e = CmdType_e;
  499. pWrkItm->pClientCtx = pClientCtx;
  500. pWrkItm->MagicNo = MagicNo;
  501. QueInsertWrkItm(
  502. (PLIST_ENTRY)pWrkItm,
  503. QUE_E_RPLPULL,
  504. NULL
  505. );
  506. break;
  507. /*
  508. * Wrk items queued by the Timer Manager thread -- when a timeout
  509. * has occurred.
  510. */
  511. //
  512. // Currently, not being used by TMM. This if for future extensibility
  513. // Tmm interfaces with different clients and it is better that
  514. // that it be unaware of who the client is (see wintmm.c). When
  515. // in the future, there is a case where TMM acquires knowledge
  516. // of who the client is, it can use the ERplInsertQue function
  517. // for Rpl Client to notify it if the timer expiration.
  518. //
  519. case(QUE_E_CMD_TIMER_EXPIRED):
  520. pTmmWrkItm = pClientCtx;
  521. pWrkItm->pClientCtx = pTmmWrkItm->pClientCtx;
  522. pWrkItm->CmdTyp_e = CmdType_e;
  523. QueInsertWrkItm(
  524. (PLIST_ENTRY)pWrkItm,
  525. QUE_E_UNKNOWN_TYPQ,
  526. pTmmWrkItm->pRspQueHd
  527. );
  528. break;
  529. /*
  530. * Wrk item queues by the main thread -- when configuration
  531. * has changed
  532. */
  533. case(QUE_E_CMD_CONFIG): //fall through
  534. case(QUE_E_CMD_DELETE_WINS):
  535. case(QUE_E_CMD_ADDR_CHANGE):
  536. pWrkItm->pClientCtx = pClientCtx;
  537. pWrkItm->CmdTyp_e = CmdType_e;
  538. QueInsertWrkItm(
  539. (PLIST_ENTRY)pWrkItm,
  540. QUE_E_RPLPULL,
  541. NULL
  542. );
  543. break;
  544. /*
  545. Wrk item queued by an NBT thread -- when a certain number
  546. of updates have been exceeded
  547. It can also be queued by an RPC thread as a result of administrative action.
  548. */
  549. case(QUE_E_CMD_SND_PUSH_NTF):
  550. case(QUE_E_CMD_SND_PUSH_NTF_PROP):
  551. #ifdef WINSDBG
  552. if (Client_e == WINS_E_WINSRPC)
  553. {
  554. DBGPRINT0(FLOW,
  555. "RplInsertQue: PUSH trigger command from administrator\n");
  556. }
  557. #endif
  558. pWrkItm->pClientCtx = pClientCtx;
  559. pWrkItm->pMsg = pMsg;
  560. pWrkItm->CmdTyp_e = CmdType_e;
  561. pWrkItm->MagicNo = MagicNo;
  562. QueInsertSndNtfWrkItm( (PLIST_ENTRY)pWrkItm);
  563. break;
  564. //
  565. // Work item queued by the Push thread on getting an update
  566. // notification message from a remote WINS
  567. //
  568. case(QUE_E_CMD_HDL_PUSH_NTF):
  569. PERF("currently we are not passing any pClientCtx. So we can take off this")
  570. PERF("assignment")
  571. pWrkItm->pClientCtx = pClientCtx;
  572. pWrkItm->CmdTyp_e = CmdType_e;
  573. pWrkItm->DlgHdl = *pDlgHdl;
  574. pWrkItm->pMsg = pMsg;
  575. pWrkItm->MsgLen = MsgLen;
  576. pWrkItm->MagicNo = MagicNo;
  577. QueInsertNetNtfWrkItm( (PLIST_ENTRY)pWrkItm);
  578. break;
  579. default:
  580. DBGPRINT1(ERR,
  581. "ERplInsertQue: Invalid client Id (%d)\n",
  582. Client_e
  583. );
  584. WINSEVT_LOG_M(WINS_FATAL_ERR, WINS_EVT_SFT_ERR);
  585. break;
  586. }
  587. return(WINS_SUCCESS);
  588. }
  589. FUTURES("Optimize so that records with Invalid metric are not looked at")
  590. VOID
  591. ERplPushProc(
  592. BOOL fAddDiff,
  593. LPVOID pCtx,
  594. PCOMM_ADD_T pNoPushWins1,
  595. PCOMM_ADD_T pNoPushWins2
  596. )
  597. /*++
  598. Routine Description:
  599. This function is called in an NBT thread or in the PULL thread
  600. to push notifications to remote WINS servers (Pull pnrs)
  601. Arguments:
  602. fAddDiff - Indicates whether this function got called as a result of
  603. address change
  604. pCtx - ctx to be passed in the work item
  605. pNoPushWins1 - Add of wins to which a trigger should not be sent
  606. pNoPushWins2 - Add of wins to which a trigger should not be sent
  607. Externals Used:
  608. None
  609. Return Value:
  610. None
  611. Error Handling:
  612. Called by:
  613. NmsNmhNamRegInd, NmsNmhNamRegGrp, NmsNmhReplRegInd, NmsNmhReplGrpMems,
  614. NmsNmhUpdVersNo, PullEntries in rplpull.c
  615. Side Effects:
  616. Comments:
  617. This function is called inside of the NmsNmhNamRegCrtSec section.
  618. There is no need for the thread to be within the WinsCnfCnfCrtSec
  619. since the thread (main thread) that changes WinsCnf structure
  620. enters the NmsNmsNamRegCrtSec (besides the WinsCnfCnfCrtSec)
  621. prior to changing WinsCnf.
  622. --*/
  623. {
  624. PRPL_CONFIG_REC_T pCnfRec;
  625. COMM_IP_ADD_T IPAdd1 = 0;
  626. COMM_IP_ADD_T IPAdd2 = 0;
  627. if (fAddDiff)
  628. {
  629. if (pNoPushWins1)
  630. {
  631. IPAdd1 = pNoPushWins1->Add.IPAdd;
  632. }
  633. if (pNoPushWins2)
  634. {
  635. IPAdd2 = pNoPushWins2->Add.IPAdd;
  636. }
  637. }
  638. //
  639. // The trigger needs to be sent to all our Push Pnrs
  640. //
  641. pCnfRec = WinsCnf.PushInfo.pPushCnfRecs;
  642. DBGPRINT2(RPL, "ERplPushProc: CurrVersNo is %d %d \n", NmsNmhMyMaxVersNo.HighPart, NmsNmhMyMaxVersNo.LowPart);
  643. if (!pCnfRec) {
  644. return;
  645. }
  646. //
  647. // Loop over all our Push pnrs
  648. //
  649. for (
  650. ;
  651. pCnfRec->WinsAdd.Add.IPAdd != INADDR_NONE;
  652. pCnfRec = (PRPL_CONFIG_REC_T)(
  653. (LPBYTE) pCnfRec + RPL_CONFIG_REC_SIZE
  654. )
  655. )
  656. {
  657. //
  658. // If the replication is not being done as a result of
  659. // an address change, then compare our current max. version
  660. // number with the last one at which we sent triggers to see
  661. // if the requisite number of updates have been made to
  662. // justify another trigger.
  663. //
  664. if (!fAddDiff)
  665. {
  666. //
  667. // If the Update count field is invalid, go to the next
  668. // record
  669. //
  670. if (pCnfRec->UpdateCount == RPL_INVALID_METRIC)
  671. {
  672. continue;
  673. }
  674. //
  675. // This function is always called from the macro, RPL_PUSH_NTF_M().
  676. // When called, NmsNmhMyMaxVersNo is always the version # to be given
  677. // to the next record. pCnfRec->LastVersNo is the version
  678. // that was given to the first record after the last update
  679. // notification or the first update since WINS invocation if
  680. // no update notification was sent on WINS invocation.
  681. //
  682. if(
  683. (LiSub(NmsNmhMyMaxVersNo, pCnfRec->LastVersNo)/pCnfRec->UpdateCount)
  684. == 0
  685. )
  686. {
  687. DBGPRINT0(RPL, "ERplPushProc: Update Count notification threshold not reached yet\n");
  688. continue;
  689. }
  690. }
  691. else
  692. {
  693. //
  694. // If fAddDiff flag is TRUE, it can either mean that
  695. // this function got invoked as a result of a
  696. // name registration done by an NBT thread that changed
  697. // the address after conflict resolution or it can mean
  698. // that replication trigger was sent by an administrator
  699. // who desires its propagation along a fan out tree
  700. // of WINS servers (we might be at the starting point of
  701. // the tree (root of the tree triggered by the admin) or
  702. // at another level. If we are not at the root, we need
  703. // to check the Push Partners to which we must not
  704. // propagate (we don't want to propagate to the WINS that
  705. // that propagated the trigger to us.
  706. //
  707. if (
  708. (pCnfRec->WinsAdd.Add.IPAdd == IPAdd1)
  709. ||
  710. (pCnfRec->WinsAdd.Add.IPAdd == IPAdd2)
  711. )
  712. {
  713. continue;
  714. }
  715. FUTURES("Check whether we have just done replication with this WINS")
  716. FUTURES("This check can be madei if we store the version numbers of")
  717. FUTURES("all owners - in our db - that we replicated to this WINS in the")
  718. FUTURES("last replication cycle in the configuration record of this WINS")
  719. CHECK("Is storing this information - more memory - more cycles at replication")
  720. CHECK("more cycles at reinitialization - etc worth the saving in cycles")
  721. CHECK("at propagation time")
  722. }
  723. CHECK("Do we need this critical section ??")
  724. EnterCriticalSection(&sPushNtfCrtSec);
  725. try
  726. {
  727. {
  728. pCnfRec->LastVersNo = NmsNmhMyMaxVersNo;
  729. DBGPRINT0(RPL, "ERplPushProc: Update Count notification BEING SENT\n");
  730. ERplInsertQue(
  731. WINS_E_NMSNMH,
  732. fAddDiff ? QUE_E_CMD_SND_PUSH_NTF_PROP :
  733. QUE_E_CMD_SND_PUSH_NTF,
  734. NULL, //no need to pass dlg hdl
  735. pCtx, //ctx
  736. 0, //msg length
  737. pCnfRec,
  738. pCnfRec->MagicNo
  739. );
  740. }
  741. }
  742. except(EXCEPTION_EXECUTE_HANDLER)
  743. {
  744. DWORD ExcCode = GetExceptionCode();
  745. DBGPRINT1(EXC, "ERplPushProc: Got Exception (%x)\n", ExcCode);
  746. //
  747. // log a message
  748. //
  749. WINSEVT_LOG_M(ExcCode, WINS_EVT_PUSH_TRIGGER_EXC);
  750. }
  751. LeaveCriticalSection(&sPushNtfCrtSec);
  752. } // end of for loop
  753. return;
  754. } // ERplPushProc()
  755. PRPL_CONFIG_REC_T
  756. RplGetConfigRec(
  757. RPL_RR_TYPE_E TypeOfRec_e,
  758. PCOMM_HDL_T pDlgHdl,
  759. PCOMM_ADD_T pAdd
  760. )
  761. /*++
  762. Routine Description:
  763. This function is called to search the list of pull/push pnrs and
  764. return with the address of the pnr corresponding to the address passed
  765. in.
  766. Arguments:
  767. RPL_RR_TYPE_E Type of record (pull/push)
  768. PCOMM_HDL_T Dlg Hdl (implicit) of Pnr
  769. Externals Used:
  770. None
  771. Return Value:
  772. Address of Pnr's config structure or NULL
  773. Error Handling:
  774. Called by:
  775. Push thread & CheckIfDel() in Pull thread
  776. Side Effects:
  777. Comments:
  778. None
  779. --*/
  780. {
  781. PRPL_CONFIG_REC_T pPnr;
  782. BOOL fRplPnr = FALSE;
  783. COMM_ADD_T WinsAdd;
  784. PCOMM_ADD_T pWinsAdd = &WinsAdd;
  785. DBGENTER("GetConfigRec\n");
  786. EnterCriticalSection(&WinsCnfCnfCrtSec);
  787. if (TypeOfRec_e == RPL_E_PULL)
  788. {
  789. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  790. }
  791. else
  792. {
  793. pPnr = WinsCnf.PushInfo.pPushCnfRecs;
  794. }
  795. try {
  796. if (pPnr != NULL)
  797. {
  798. if (pAdd == NULL)
  799. {
  800. COMM_INIT_ADD_FR_DLG_HDL_M(pWinsAdd, pDlgHdl);
  801. }
  802. else
  803. {
  804. pWinsAdd = pAdd;
  805. }
  806. //
  807. // Search for the Cnf record for the WINS we want to
  808. // send the PUSH notification to/Replicate with.
  809. //
  810. for (
  811. ;
  812. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  813. &&
  814. !fRplPnr;
  815. // no third expression
  816. )
  817. {
  818. //
  819. // Check if this is the one we want
  820. //
  821. if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->Add.IPAdd)
  822. {
  823. //
  824. // We are done. Set the fRplPnr flag to TRUE so that
  825. // we break out of the loop.
  826. //
  827. // Note: Don't use break since that would cause
  828. // a search for a 'finally' block
  829. //
  830. fRplPnr = TRUE;
  831. continue; //so that we break out of the loop
  832. }
  833. //
  834. // Get the next record that follows this one sequentially
  835. //
  836. pPnr = WinsCnfGetNextRplCnfRec(
  837. pPnr,
  838. RPL_E_IN_SEQ //seq. traversal
  839. );
  840. }
  841. }
  842. }
  843. except(EXCEPTION_EXECUTE_HANDLER) {
  844. DBGPRINTEXC("GetConfigRec");
  845. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PULL_TRIG_PROC);
  846. }
  847. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  848. #ifdef WINSDBG
  849. if (fRplPnr)
  850. {
  851. DBGPRINT1(RPLPUSH, "LEAVING GetConfigRec - Pnr with address %x is in our list\n", pWinsAdd->Add.IPAdd);
  852. }
  853. else
  854. {
  855. if (pDlgHdl)
  856. {
  857. COMM_INIT_ADD_FR_DLG_HDL_M(pWinsAdd, pDlgHdl);
  858. DBGPRINT1(RPLPUSH, "LEAVING GetConfigRec - Pnr with address %x is NOT in our list\n", pWinsAdd->Add.IPAdd);
  859. }
  860. }
  861. #endif
  862. return(fRplPnr ? pPnr : NULL);
  863. }
  864. #if 0
  865. VOID
  866. ERplPushCompl(
  867. PCOMM_ADD_T pNoPushWins
  868. )
  869. /*++
  870. Routine Description:
  871. This function is called by the PULL thread to push notifications
  872. to remote WINS servers that have an INVALID_METRIC in their
  873. UpdateCount field (Pull pnrs)
  874. Arguments:
  875. pNoPushWins - Add of wins to which a trigger should not be sent
  876. Externals Used:
  877. None
  878. Return Value:
  879. None
  880. Error Handling:
  881. Called by:
  882. Side Effects:
  883. Comments:
  884. This function is called inside of the NmsNmhNamRegCrtSec section.
  885. There is no need for the thread to be within the WinsCnfCnfCrtSec
  886. since the thread (main thread) that changes WinsCnf structure
  887. enters the NmsNmsNamRegCrtSec (besides the WinsCnfCnfCrtSec)
  888. prior to changing WinsCnf.
  889. --*/
  890. {
  891. VERS_NO_T CurrVersNo;
  892. PRPL_CONFIG_REC_T pCnfRec;
  893. BOOL fPush;
  894. //
  895. // The trigger needs to be sent to all our Push Pnrs
  896. //
  897. pCnfRec = WinsCnf.PushInfo.pPushCnfRecs;
  898. //
  899. // Let us get the current highest version no. of records owned by us
  900. //
  901. NMSNMH_DEC_VERS_NO_M(
  902. NmsNmhMyMaxVersNo,
  903. CurrVersNo
  904. );
  905. //
  906. // Loop over all our Push pnrs
  907. //
  908. for (
  909. ;
  910. pCnfRec->WinsAdd.Add.IPAdd != INADDR_NONE;
  911. pCnfRec = (PRPL_CONFIG_REC_T)(
  912. (LPBYTE) pCnfRec + RPL_CONFIG_REC_SIZE
  913. )
  914. )
  915. {
  916. //
  917. // If the Update count field is invalid, go to the next
  918. // record
  919. //
  920. if (
  921. (pCnfRec->UpdateCount != RPL_INVALID_METRIC)
  922. ||
  923. (pCnfRec->WinsAdd.Add.IPAdd == pNoPushWins)
  924. )
  925. {
  926. continue;
  927. }
  928. EnterCriticalSection(&sPushNtfCrtSec);
  929. try
  930. {
  931. {
  932. pCnfRec->LastVersNo = CurrVersNo;
  933. ERplInsertQue(
  934. WINS_E_NMSNMH,
  935. QUE_E_CMD_SND_PUSH_NTF,
  936. NULL, //no need to pass dlg hdl
  937. NULL, //no msg is there
  938. 0, //msg length
  939. pCnfRec
  940. );
  941. }
  942. }
  943. except(EXCEPTION_EXECUTE_HANDLER)
  944. {
  945. DBGPRINTEXC("ERplPushCompl:");
  946. //
  947. // log a message
  948. //
  949. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_PUSH_TRIGGER_EXC);
  950. }
  951. LeaveCriticalSection(&sPushNtfCrtSec);
  952. }
  953. return;
  954. } // ERplPushCompl()
  955. //
  956. // Cut and Paste from RplFindOwnerId
  957. //
  958. VOID
  959. ModifyRec()
  960. {
  961. //
  962. // The entry may have been inserted with a
  963. // 0 start version counter value. If we
  964. // have a valid value now, put that in.
  965. //
  966. if (
  967. pNewStartVersNo != NULL
  968. &&
  969. (
  970. (LiNeq(pOwnAddTbl->StartVersNo,
  971. *pNewStartVersNo))
  972. ||
  973. (pOwnAddTbl->Uid != *pNewUid)
  974. )
  975. )
  976. {
  977. /*
  978. * Write the record into the database
  979. * table
  980. */
  981. NmsDbWriteOwnAddTbl(
  982. NMSDB_E_MODIFY_REC,
  983. i,
  984. pWinsAdd,
  985. NMSDB_E_WINS_ACTIVE,
  986. pNewStartVersNo,
  987. pNewUid
  988. );
  989. *pOldStartVersNo =
  990. pOwnAddTbl->StartVersNo;
  991. *pOldUid = pOwnAddTbl->Uid;
  992. //
  993. // Init the in-memory table's field
  994. //
  995. pOwnAddTbl->StartVersNo =
  996. *pNewStartVersNo;
  997. pOwnAddTbl->Uid = *pNewUid;
  998. }
  999. else
  1000. {
  1001. if (pOldStartVersNo != NULL)
  1002. {
  1003. *pOldStartVersNo =
  1004. pOwnAddTbl->StartVersNo;
  1005. }
  1006. if (pOldUid != NULL)
  1007. {
  1008. *pOldUid = pOwnAddTbl->Uid;
  1009. }
  1010. }
  1011. } //ModifyRec()
  1012. //
  1013. // Cut and paste from RplFindOwnerId
  1014. //
  1015. VOID
  1016. AssignStartVersNo()
  1017. {
  1018. //
  1019. // If we have a start version number for this
  1020. // WINS, use it to initialize the in-memory
  1021. // table field, else make the same 0.
  1022. //
  1023. if (pNewStartVersNo != NULL)
  1024. {
  1025. pOwnAddTbl->StartVersNo = *pNewStartVersNo;
  1026. pOwnAddTbl->Uid = *pNewUid;
  1027. //
  1028. // Assign 0, since we didn't have any s.vers.
  1029. // # for this owner
  1030. //
  1031. WINS_ASSIGN_INT_TO_VERS_NO_M(
  1032. *pOldStartVersNo, 0);
  1033. //
  1034. // Assign 0, since we didn't have any Uid
  1035. // for this owner
  1036. //
  1037. *pOldUid = 0;
  1038. }
  1039. else
  1040. {
  1041. //
  1042. // Assign 0, since we don't have any s.vers.
  1043. // # for this owner
  1044. //
  1045. WINS_ASSIGN_INT_TO_VERS_NO_M(
  1046. pOwnAddTbl->StartVersNo, 0
  1047. );
  1048. //
  1049. // Assign 0, since we didn't have any Uid
  1050. // for this owner
  1051. //
  1052. pOwnAddTbl->Uid = 0;
  1053. }
  1054. } //AssignStartVersNo()
  1055. //
  1056. // Cut and paste from RplFindOwnerId()
  1057. //
  1058. InitStartVersNo()
  1059. {
  1060. if (pNewStartVersNo != NULL)
  1061. {
  1062. pOwnAddTbl->StartVersNo = *pNewStartVersNo;
  1063. WINS_ASSIGN_INT_TO_VERS_NO_M(*pOldStartVersNo,0);
  1064. pOwnAddTbl->Uid = *pNewUid;
  1065. *pOldUid = 0;
  1066. }
  1067. else
  1068. {
  1069. WINS_ASSIGN_INT_TO_VERS_NO_M(pOwnAddTbl->StartVersNo,0);
  1070. pOwnAddTbl->Uid = 0;
  1071. }
  1072. } //InitStartVersNo()
  1073. #endif
  1074.