|
|
/*==========================================================================
* * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved. * * File: NameTable.h * Content: NameTable Object Header File *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 03/11/00 mjn Created * 04/09/00 mjn Track outstanding connections in NameTable * 05/03/00 mjn Implemented GetHostPlayerRef, GetLocalPlayerRef, GetAllPlayersGroupRef * 07/20/00 mjn Added ClearHostWithDPNID() * 07/30/00 mjn Added hrReason to CNameTable::EmptyTable() * 08/23/00 mjn Added CNameTableOp * 09/05/00 mjn Added m_dpnidMask * mjn Removed dwIndex from InsertEntry() * 09/17/00 mjn Split m_bilinkEntries into m_bilinkPlayers and m_bilinkGroups * mjn Changed AddPlayerToGroup and RemovePlayerFromGroup to use NameTableEntry params * 09/26/00 mjn Removed locking from SetVersion(),GetNewVersion() * mjn Changed DWORD GetNewVersion(void) to void GetNewVersion( PDWORD ) * 01/25/01 mjn Fixed 64-bit alignment problem when unpacking NameTable *@@END_MSINTERNAL * ***************************************************************************/
#ifndef __NAMETABLE_H__
#define __NAMETABLE_H__
#include "ReadWriteLock.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_CORE
//
// NameTable
//
// The NameTable consists of:
// - an array of CNameTableEntry pointers
// - short-cuts to the LocalPlayer, Host and AllPlayersGroup
// - a version number
//
// There is a list running through the free entries in the NameTable array.
// When a free entry is required, it is taken from the front of this list,
// and when an entry is released, it is added to the end of the list.
// If a particular entry is required, it must be properly removed from the
// list. This may be a little time-consuming, since the entire list may
// need to be traversed, but this will only happen on non-Host cases and
// is a small price to pay to keep the Host case timely.
//
//
// DPNIDs
//
// DPNIDs are unique identifiers for NameTable entries. They are constructed
// from the NameTable array index and the version number of the entry.
// The value 0x0 is invalid. As a result, we must prevent it from being
// generated. Since the DPNID is constructed from two parts, we can do
// this by ensuring that one of the two parts is never 0. The best
// solution is to ensure that the NameTable array index is never 0.
//
//
// Locking
//
// When locking multiple entries in the NameTable, locks should be taken
// in order based on DPNIDs. e.g. Locking two entries with DPNIDs 200 and
// 101, the lock for 101 should be taken before the lock for 200. Locks for
// groups should be taken before locks for players.
//
//**********************************************************************
// Constant definitions
//**********************************************************************
#define NAMETABLE_INDEX_MASK 0x000FFFFF
#define NAMETABLE_VERSION_MASK 0xFFF00000
#define NAMETABLE_VERSION_SHIFT 20
#define NAMETABLE_ARRAY_ENTRY_FLAG_VALID 0x0001
//**********************************************************************
// Macro definitions
//**********************************************************************
#define CONSTRUCT_DPNID(i,v) (((i & NAMETABLE_INDEX_MASK) | ((v << NAMETABLE_VERSION_SHIFT) & NAMETABLE_VERSION_MASK)) ^ m_dpnidMask)
#define DECODE_INDEX(d) ((d ^ m_dpnidMask) & NAMETABLE_INDEX_MASK)
#define VERIFY_VERSION(d,v) (((d ^ m_dpnidMask) & NAMETABLE_VERSION_MASK) == (v << NAMETABLE_VERSION_SHIFT))
//**********************************************************************
// Structure definitions
//**********************************************************************
class CPackedBuffer; class CConnection; class CNameTableEntry;
typedef struct _DIRECTNETOBJECT DIRECTNETOBJECT;
typedef struct _NAMETABLE_ARRAY_ENTRY { CNameTableEntry *pNameTableEntry; DWORD dwFlags; } NAMETABLE_ARRAY_ENTRY;
typedef struct _DN_NAMETABLE_INFO { DPNID dpnid; DWORD dwVersion; DWORD dwVersionNotUsed; DWORD dwEntryCount; DWORD dwMembershipCount; } DN_NAMETABLE_INFO;
//**********************************************************************
// Variable definitions
//**********************************************************************
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Class prototypes
//**********************************************************************
// class for NameTable
class CNameTable { public: CNameTable() // Constructor
{ m_Sig[0] = 'N'; m_Sig[1] = 'T'; m_Sig[2] = 'B'; m_Sig[3] = 'L'; };
#undef DPF_MODNAME
#define DPF_MODNAME "CNameTable::~CNameTable"
~CNameTable() { }; // Destructor
HRESULT CNameTable::Initialize(DIRECTNETOBJECT *const pdnObject);
void CNameTable::Deinitialize( void );
void ReadLock( void ) { m_RWLock.EnterReadLock(); };
void WriteLock( void ) { m_RWLock.EnterWriteLock(); };
void Unlock( void ) { m_RWLock.LeaveLock(); };
#ifdef DBG
void CNameTable::ValidateArray( void ); #endif // DBG
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
HRESULT CNameTable::SetNameTableSize( const DWORD dwNumEntries ); #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
HRESULT CNameTable::GrowNameTable( void ); #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
void CNameTable::ResetNameTable( void );
HRESULT CNameTable::UpdateTable(const DWORD dwIndex, CNameTableEntry *const pNameTableEntry);
HRESULT CNameTable::InsertEntry(CNameTableEntry *const pNameTableEntry);
void CNameTable::ReleaseEntry(const DWORD dwIndex);
#undef DPF_MODNAME
#define DPF_MODNAME "CNameTable::GetNewVersion"
void GetNewVersion( DWORD *const pdwVersion ) { DNASSERT( pdwVersion != NULL );
*pdwVersion = ++m_dwVersion;
DPFX(DPFPREP, 8,"Setting new version [%ld]",m_dwVersion); };
#undef DPF_MODNAME
#define DPF_MODNAME "CNameTable::SetVersion"
void SetVersion( const DWORD dwVersion ) { m_dwVersion = dwVersion;
DPFX(DPFPREP, 8,"Setting new version [%ld]",m_dwVersion); };
DWORD GetVersion( void ) const { return(m_dwVersion); };
void CNameTable::EmptyTable( const HRESULT hrReason );
HRESULT CNameTable::FindEntry(const DPNID dpnid, CNameTableEntry **const ppNameTableEntry);
HRESULT CNameTable::FindDeletedEntry(const DPNID dpnid, CNameTableEntry **const ppNTEntry);
HRESULT CNameTable::AddEntry(CNameTableEntry *const pNTEntry);
HRESULT CNameTable::DeletePlayer(const DPNID dpnid, DWORD *const pdwVersion);
HRESULT CNameTable::DeleteGroup(const DPNID dpnid, DWORD *const pdwVersion);
HRESULT CNameTable::AddPlayerToGroup(CNameTableEntry *const pGroup, CNameTableEntry *const pPlayer, DWORD *const pdwVersion);
HRESULT CNameTable::RemovePlayerFromGroup(CNameTableEntry *const pGroup, CNameTableEntry *const pPlayer, DWORD *const pdwVersion);
HRESULT CNameTable::RemoveAllPlayersFromGroup(CNameTableEntry *const pGroup);
HRESULT CNameTable::RemoveAllGroupsFromPlayer(CNameTableEntry *const pPlayer);
BOOL CNameTable::IsMember(const DPNID dpnidGroup, const DPNID dpnidPlayer);
HRESULT CNameTable::PackNameTable(CNameTableEntry *const pTarget, CPackedBuffer *const pPackedBuffer);
HRESULT CNameTable::UnpackNameTableInfo(UNALIGNED DN_NAMETABLE_INFO *const pdnNTInfo, BYTE *const pBufferStart, DPNID *const pdpnid);
CNameTableEntry *GetDefaultPlayer( void ) { return(m_pDefaultPlayer); };
void MakeLocalPlayer(CNameTableEntry *const pNameTableEntry);
void CNameTable::ClearLocalPlayer( void );
CNameTableEntry *GetLocalPlayer( void ) { return(m_pLocalPlayer); };
HRESULT CNameTable::GetLocalPlayerRef( CNameTableEntry **const ppNTEntry );
void MakeHostPlayer(CNameTableEntry *const pNameTableEntry);
void CNameTable::ClearHostPlayer( void );
BOOL CNameTable::ClearHostWithDPNID( const DPNID dpnid );
void CNameTable::UpdateHostPlayer( CNameTableEntry *const pNewHost );
CNameTableEntry *GetHostPlayer( void ) { return(m_pHostPlayer); };
HRESULT CNameTable::GetHostPlayerRef( CNameTableEntry **const ppNTEntry );
void MakeAllPlayersGroup(CNameTableEntry *const pNameTableEntry);
void CNameTable::ClearAllPlayersGroup( void );
CNameTableEntry *GetAllPlayersGroup( void ) { return(m_pAllPlayersGroup); };
HRESULT CNameTable::GetAllPlayersGroupRef( CNameTableEntry **const ppNTEntry );
HRESULT CNameTable::PopulateConnection(CConnection *const pConnection);
HRESULT CNameTable::PopulateGroup(CNameTableEntry *const pGroup);
HRESULT CNameTable::AutoCreateGroups(CNameTableEntry *const pPlayer);
HRESULT CNameTable::AutoDestructGroups(const DPNID dpnid);
void CNameTable::SetLatestVersion( const DWORD dwVersion ) { m_dwLatestVersion = dwVersion; };
DWORD CNameTable::GetLatestVersion( void ) const { return( m_dwLatestVersion ); };
void CNameTable::SetConnectVersion(const DWORD dwVersion) { m_dwConnectVersion = dwVersion; };
DWORD CNameTable::GetConnectVersion( void ) const { return(m_dwConnectVersion); };
#undef DPF_MODNAME
#define DPF_MODNAME "CNameTable::IncOutstandingConnections"
void IncOutstandingConnections( void ) { long lRefCount;
lRefCount = DNInterlockedIncrement(&m_lOutstandingConnections); DNASSERT(lRefCount > 0); };
void SetDPNIDMask( const DPNID dpnidMask ) { m_dpnidMask = dpnidMask; };
DPNID GetDPNIDMask( void ) const { return( m_dpnidMask ); };
void CNameTable::DecOutstandingConnections( void );
CBilink m_bilinkPlayers; CBilink m_bilinkGroups; CBilink m_bilinkDeleted; CBilink m_bilinkNameTableOps;
private: BYTE m_Sig[4]; DIRECTNETOBJECT *m_pdnObject;
DPNID m_dpnidMask;
CNameTableEntry *m_pDefaultPlayer; CNameTableEntry *m_pLocalPlayer; CNameTableEntry *m_pHostPlayer; CNameTableEntry *m_pAllPlayersGroup;
NAMETABLE_ARRAY_ENTRY *m_NameTableArray; DWORD m_dwNameTableSize; DWORD m_dwFirstFreeEntry; DWORD m_dwLastFreeEntry; DWORD m_dwNumFreeEntries;
DWORD m_dwVersion;
DWORD m_dwLatestVersion; // Only used by Host in PEER
DWORD m_dwConnectVersion; LONG m_lOutstandingConnections;
CReadWriteLock m_RWLock; };
#undef DPF_MODNAME
#endif // __NAMETABLE_H__
|