#ifndef _RPL_
#define _RPL_
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:



Abstract:





Functions:



Portability:


        This header is portable.

Author:

        Pradeep Bahl        (PradeepB)        Jan-1993



Revision History:

        Modification Date        Person                Description of Modification
        ------------------        -------                ---------------------------

--*/

/*
  includes
*/
#include "wins.h"
#include "comm.h"
#include "nmsdb.h"
#include "winsque.h"

/*
  defines
*/
/*
  RPL_OPCODE_SIZE -- size of opcode in message sent between two replicators.
        This define is used by rplmsgf
*/
#define RPL_OPCODE_SIZE                4        //sizeof the Opcode in an RPL message


/*
 The maximum numbers of RQ WINS on a network.
*/
#define RPL_MAX_OWNERS_INITIALLY                NMSDB_MAX_OWNERS_INITIALLY


/*
  RPL_MAX_GRP_MEMBERS --
  Maximum members allowed in a group
*/
#define RPL_MAX_GRP_MEMBERS                 25


//
// We don't send more than 5000 records at a time.  Note: This value is
// used to define MAX_BYTES_IN_MSG in comm.c
//
// By not having a very bug number we have a better chance for being serviced
// within our timeout period for a request.  This is because of queuing that
// results when there are a lot of replication requests
//
//
#define RPL_MAX_LIMIT_FOR_RPL           5000

/*
 This define is used by ReadPartnerInfo and by RplPull functions.  The size
 is made a multiple of  8.  I could have used sizeof(LARGE_INTEGER) instead of
 8 but I am not sure whether that will remain a multiple of 8 in the future.

 The size is made a multiple of 8 to avoid alignment exceptions on MIPS (
 check out ReadPartnerInfo in winscnf.c or GetReplicas in rplpull.c for
 more details)
*/

#define  RPL_CONFIG_REC_SIZE        (sizeof(RPL_CONFIG_REC_T) + \
                                   (8 - sizeof(RPL_CONFIG_REC_T)%8))
//
// check out GetDataRecs in nmsdb.c
//
#define  RPL_REC_ENTRY_SIZE        (sizeof(RPL_REC_ENTRY_T) + \
                                   (8 - sizeof(RPL_REC_ENTRY_T)%8))

//
// check out GetDataRecs in nmsdb.c
//
#define  RPL_REC_ENTRY2_SIZE        (sizeof(RPL_REC_ENTRY2_T) + \
                                   (8 - sizeof(RPL_REC_ENTRY2_T)%8))

//
// The following define is used to initialize the TimeInterval/UpdateCount
// field of a RPL_REC_ENTRY_T structure to indicate that it is invalid
//
#define RPL_INVALID_METRIC        -1


//
// defines to indicate whether the trigger needs to be propagated to all WINS
// in the PUSH chain
//
#define RPL_PUSH_PROP                TRUE        //must remain TRUE since in
                                        //NmsNmhNamRegInd, at one place
                                        //we use fAddDiff value in place of
                                        //this symbol. fAddDiff when TRUE
                                        //indicates that the address has
                                        //changed, thus initiating propagation
#define RPL_PUSH_NO_PROP        FALSE



/*
  macros
*/

//
// Macro called in an NBT thread after it increments the version number
// counter.  This macro is supposed to be called from within the
// NmsNmhNamRegCrtSec.
//
#define RPL_PUSH_NTF_M(fAddDiff, pCtx, pNoPushWins1, pNoPushWins2) {                \
                             if ((WinsCnf.PushInfo.NoPushRecsWValUpdCnt \
                                                              != 0) ||  \
                                        fAddDiff)                        \
                             {                                                \
                                ERplPushProc(fAddDiff, pCtx, pNoPushWins1,    \
                                                pNoPushWins2);          \
                             }                                                \
               }

/*
        FIND_ADD_BY_OWNER_ID_M - This macro is called by the PUSH thread
        when sending data records to its Pull Partner.  It calls this function
        to determine the Address of the WINS owning the database record

        The caller of this macro, if not executing in the PULL thread, must
        synchronize using NmsDbOwnAddTblCrtSec (Only PULL thread updates
        the NmsDbOwnAddTbl array during steady state).

        I am not putting the critical section entry and exit inside this
        macro for performance reasons (refer StoreGrpMems in nmsdb.c where
        this macro may be called many times -once for each member of a
        special group).  Also refer RplMsgfFrmAddVersMapRsp()  and
        WinsRecordAction (in winsintf.c)
*/

#define   RPL_FIND_ADD_BY_OWNER_ID_M(OwnerId, pWinsAdd, pWinsState_e, pStartVersNo)                                                                          \
                {                                                        \
                        PNMSDB_ADD_STATE_T pWinsRec;                     \
                        if (OwnerId < NmsDbTotNoOfSlots)                 \
                        {                                                \
                            pWinsRec       = pNmsDbOwnAddTbl+OwnerId;    \
                            (pWinsAdd)     = &(pWinsRec->WinsAdd);       \
                            (pWinsState_e) = &pWinsRec->WinsState_e;     \
                            (pStartVersNo) = &pWinsRec->StartVersNo;     \
                        }                                                \
                        else                                             \
                        {                                                \
                            (pWinsAdd)     = NULL;                       \
                            (pWinsState_e) = NULL;                       \
                            (pStartVersNo) = NULL;                       \
                        }                                                \
                }


//
//  Names of event variables signaled when Pull and/or Push configuration
//  changes
//
#define  RPL_PULL_CNF_EVT_NM                TEXT("RplPullCnfEvt")
#define  RPL_PUSH_CNF_EVT_NM                TEXT("RplPushCnfEvt")
/*
 externs
*/


/*
  Handle of heap used for allocating/deallocating work items for the RPL
  queues
*/

extern  HANDLE                RplWrkItmHeapHdl;
#if 0
extern  HANDLE                RplRecHeapHdl;
#endif

/*
  OwnerIdAddressTbl

  This table stores the Addresses corresponding to different WINS servers.

  In the local database, the local WINS's owner id is always 0.  The owner ids
  of other WINS servers are 1, 2, 3 ....  The owner ids form a sequential list,
  without any gap.  This is because, the first time the database is created
  at a WINS, it assigns sequential numbers to the other WINS.


  Note: The table is static for now.  We might change it to be a dynamic one
        later.

*/



/*
 PushPnrVersNoTbl

  This table stores the Max. version number pertaining to each WINS server
  owning entries in the database of Push Partners

  Note: The table is static for now.  We might change it to be a dynamic one
        later.
*/

#if 0
extern VERS_NO_T   pPushPnrVersNoTbl;
#endif

/*
 OwnerVersNo -- this array stores the maximum version number for each
         owner in the local database

        This is used by HandleAddVersMapReq() in RplPush.c

*/
extern VERS_NO_T   pRplOwnerVersNo;


extern HANDLE                RplSyncWTcpThdEvtHdl; //Sync up with the TCP thread

//
// critical section to guard the RplPullOwnerVersNo array
//
extern CRITICAL_SECTION  RplVersNoStoreCrtSec;

/*
 typedef  definitions
*/

/*
        The different types of records that can be read from the registry
*/
typedef enum _RPL_RR_TYPE_E {
        RPL_E_PULL = 0,   // pull record
        RPL_E_PUSH,          //push record
        RPL_E_QUERY          //query record
        } RPL_RR_TYPE_E, *PRPL_RR_TYPE_E;

typedef struct _RPL_VERS_NOS_T {
        VERS_NO_T                VersNo;
        VERS_NO_T                StartVersNo;
        } RPL_VERS_NOS_T, *PRPL_VERS_NOS_T;

/*
  RPL_CONFIG_REC_T -- Configuration record for the WINS replicator.  It
                specifies the Pull/Push/Query partner and associated
                parameters


  NOTE NOTE NOTE:  Keep the datatype of UpdateCount and TimeInterval the same
  (see LnkWSameMetricRecs)
*/
typedef  struct _RPL_CONFIG_REC_T {
    DWORD       MagicNo;    //Same as that in WinsCnf
        COMM_ADD_T        WinsAdd;        /*address of partner        */
        LPVOID                pWinsCnf;        //back pointer to the old WINS struct
        LONG                TimeInterval;   /*time interval in secs for pulling or
                                         * pushing        */
        BOOL                fSpTime;        //indicates whether pull/push
                                        //replication should be done at
                                        // a specific time
        LONG                SpTimeIntvl;        //Number of secs to specific time
        LONG                UpdateCount;        /*Count of updates after which
                                         *notification will be sent (applies
                                         *only to Push RR types*/
        DWORD                RetryCount;        //No of retries done
        DWORD                RetryAfterThisManyRpl; //Retry after this many rpl
                                               //time intervals have elapsed
                                               //from the time we stopped
                                               //replicating due to RetryCount
                                               //hitting the limit
        time_t                LastCommFailTime;   //time of last comm. failure
        time_t                LastRplTime;        //time of last replication
#if PRSCONN
        time_t                LastCommTime;   //time of last comm. 
#endif
        DWORD                PushNtfTries;       //No of tries for establishing
                                            //comm. in the past few minutes
        //
        // The two counters below have to 32 bit aligned otherwise
        // the Interlock instructions will fail on x86 MP machines
        //
        DWORD                NoOfRpls;           //no of times replication
                                           //happened with this partner
        DWORD                NoOfCommFails;           //no of times replication
                                           //failed due to comm failure
        DWORD                MemberPrec;        //precedence of members of special grp
                                        //relative to other WINS servers

        struct _RPL_CONFIG_REC_T        *pNext; //ptr to next rec. with same
                                                //time interval (in case of
                                                //of PULL record) or update
                                                //count (in case of PUSH record)
        VERS_NO_T        LastVersNo;     //Only valid for Push records.
                                        //Indicates what the value of the
                                        //local version number counter at the
                                        //time a push notification is sent
        DWORD           RplType;       //type of replication with this guy
        BOOL                fTemp;                //Indicates whether it is a temp
                                        //record that should be deallocated
                                        //after use.
        BOOL                fLinked;        //indicates whether the record is
                                        //is linked to a record before it in
                                        //the buffer of records of the same type                                        //as this record
        BOOL            fOnlyDynRecs; //indicates whether only dynamic
                                          //records should be pulled/pushed
        RPL_RR_TYPE_E    RRTyp_e;        /*Type of record PULL/PUSH/QUERY*/
#if MCAST > 0
    BOOL         fSelfFnd;    //indicates whether this record was self found
#endif
#if PRSCONN
        BOOL           fPrsConn;
        COMM_HDL_T     PrsDlgHdl;
#endif

        
        } RPL_CONFIG_REC_T, *PRPL_CONFIG_REC_T;




/*
 RPL_ADD_VERS_NO_T - stores the highest version No. pertaining to an owner
                 in the directory.

                 Used by GetVersNo and RplMsgUfrmAddVersMapRsp
*/
typedef struct _RPL_ADD_VERS_NO_T {
        COMM_ADD_T                OwnerWinsAdd;
        VERS_NO_T                 VersNo;
        VERS_NO_T                 StartVersNo;
        } RPL_ADD_VERS_NO_T, *PRPL_ADD_VERS_NO_T;

/*

 RPL_PUSHPNR_VERS_NO_T -- stores the Push Pnr Id, the id. of the owner whose
                         records  should be pulled, and the max version
                         number  of these records


        This structure is initializes at replication time.  The PULL thread
        looks at this structure and sends requests to its Push partners to
        pull records.

        This structure is used by functions in the rplpull.c and rplmsgf.c
        modules.

*/
typedef struct _RPL_PUSHPNR_VERS_NO_T {
        DWORD                PushPnrId;
        DWORD           OwnerId;
        VERS_NO_T        MaxVersNo;
        } RPL_PUSHPNR_VERS_NO_T, *PRPL_PUSHPNR_VERS_NO_T;


FUTURES("Use NmsDbRowInfo struture")
/*
  RPL_REC_ENTRY_T -- structure that holds a record in the range
                Min version no - Max version no for an owner WINS

                Used by RplPushHandleSndEntriesReq
  Size of this structure is 68 bytes
*/
typedef struct _RPL_REC_ENTRY_T {
        DWORD           NameLen;
        DWORD           NoOfAdds;
        union {
          PCOMM_ADD_T pNodeAdd;
          COMM_ADD_T  NodeAdd[2];
        };
        VERS_NO_T  VersNo;
        DWORD           TimeStamp;          //used only when doing scavenging
        DWORD           NewTimeStamp;          //used only when doing scavenging
        BOOL           fScv;        //used only when doing scavenging
        BOOL           fGrp;
        LPBYTE     pName;
        DWORD           Flag;
        } RPL_REC_ENTRY_T, *PRPL_REC_ENTRY_T;

// this struct is same as above plus has the ownerid.
// winsgetdatarecsbyname routine needs to know the ownerid of each
// record and so this new structure is created.
typedef struct _RPL_REC_ENTRY2_T {
        DWORD           NameLen;
        DWORD           NoOfAdds;
        union {
          PCOMM_ADD_T pNodeAdd;
          COMM_ADD_T  NodeAdd[2];
        };
        VERS_NO_T  VersNo;
        DWORD           TimeStamp;          //used only when doing scavenging
        DWORD           NewTimeStamp;          //used only when doing scavenging
        BOOL           fScv;        //used only when doing scavenging
        BOOL           fGrp;
        LPBYTE     pName;
        DWORD           Flag;
        DWORD       OwnerId;
        } RPL_REC_ENTRY2_T, *PRPL_REC_ENTRY2_T;

//
// Argument to GetReplicas, EstablishComm (both in rplpull.c), and
// WinsCnfGetNextCnfRec to  indicate to it how it should traverse
// the buffer of Configuration records
//
typedef enum _RPL_REC_TRAVERSAL_E {
                RPL_E_VIA_LINK = 0,
                RPL_E_IN_SEQ,
                RPL_E_NO_TRAVERSAL
                } RPL_REC_TRAVERSAL_E, *PRPL_REC_TRAVERSAL_E;



/*
 function declarations
*/

extern
STATUS
ERplInit(
        VOID
);

extern
STATUS
ERplInsertQue(
        WINS_CLIENT_E        Client_e,
        QUE_CMD_TYP_E   CmdTyp_e,
        PCOMM_HDL_T        pDlgHdl,
        MSG_T                pMsg,
        MSG_LEN_T        MsgLen,
        LPVOID                pClientCtx,
    DWORD       MagicNo
        );

extern
STATUS
RplFindOwnerId (
        IN  PCOMM_ADD_T                        pWinsAdd,
        IN  OUT LPBOOL                        pfAllocNew,
        OUT DWORD UNALIGNED         *pOwnerId,
        IN  DWORD                            InitpAction_e,
        IN  DWORD                            MemberPrec
        );

extern
VOID
ERplPushProc(
        BOOL                fAddDiff,
    LPVOID      pCtx,
        PCOMM_ADD_T     pNoPushWins1,
        PCOMM_ADD_T     pNoPushWins2
        );


extern
PRPL_CONFIG_REC_T
RplGetConfigRec(
    RPL_RR_TYPE_E   TypeOfRec_e,
    PCOMM_HDL_T     pDlgHdl,
    PCOMM_ADD_T     pAdd
    );

#if 0
extern
VOID
ERplPushCompl(
        PCOMM_ADD_T     pNoPushWins
        );
#endif

#endif //_RPL_