beginning -- this is a snapshot -- of rewrite of how relay keeps

multiple thread out of a single game.  Add new class that locks
per-cid and start using it.  Very incomplete.
This commit is contained in:
Andy2 2011-06-22 06:51:26 -07:00
parent c87df3ce16
commit 3ebcc01e86
6 changed files with 432 additions and 152 deletions

View file

@ -30,6 +30,7 @@ SRC = \
states.cpp \
timermgr.cpp \
tpool.cpp \
cidlock.cpp \
xwrelay.cpp \
# STATIC ?= -static

148
xwords4/relay/cidlock.cpp Normal file
View file

@ -0,0 +1,148 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2005-2011 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <assert.h>
#include "cidlock.h"
#include "mlock.h"
CidLock* CidLock::s_instance = NULL;
CidLock::CidLock() : m_nextCID(0)
{
pthread_mutex_init( &m_infos_mutex, NULL );
pthread_cond_init( &m_infos_condvar, NULL );
}
CidLock::~CidLock()
{
pthread_mutex_destroy( &m_infos_mutex );
}
void
CidLock::print_claimed()
{
char buf[256] = {0};
int len = 0;
// Assume we have the mutex!!!!
map< CookieID, CidInfo*>::iterator iter = m_infos.begin();
while ( iter != m_infos.end() ) {
CidInfo* info = iter->second;
if ( 0 != info->GetOwner() ) {
len += snprintf( &buf[len], sizeof(buf)-len, "%d,",
info->GetCid() );
}
++iter;
}
logf( XW_LOGINFO, "%s: claimed: %s", __func__, buf );
}
CidInfo*
CidLock::Claim( CookieID cid )
{
logf( XW_LOGINFO, "%s(%d)", __func__, cid );
CidInfo* info = NULL;
for ( ; ; ) {
MutexLock ml( &m_infos_mutex );
if ( 0 == cid ) {
cid = ++m_nextCID;
logf( XW_LOGINFO, "%s: assigned cid: %d", __func__, cid );
}
map< CookieID, CidInfo*>::iterator iter = m_infos.find( cid );
if ( iter == m_infos.end() ) { // not there at all
info = new CidInfo( cid );
m_infos.insert( pair<CookieID, CidInfo*>( cid, info ) );
} else {
if ( 0 == iter->second->GetOwner() ) {
info = iter->second;
}
}
if ( NULL != info ) { // we're done
info->SetOwner( pthread_self() );
print_claimed();
break;
}
logf( XW_LOGINFO, "%s(%d): waiting....", __func__, cid );
pthread_cond_wait( &m_infos_condvar, &m_infos_mutex );
}
logf( XW_LOGINFO, "%s(%d): DONE", __func__, cid );
return info;
}
CidInfo*
CidLock::ClaimSocket( int sock )
{
CidInfo* info = NULL;
logf( XW_LOGINFO, "%s(%d)", __func__, sock );
MutexLock ml( &m_infos_mutex );
map< CookieID, CidInfo*>::iterator iter = m_infos.begin();
while ( iter != m_infos.end() ) {
if ( sock == iter->second->GetSocket() ) {
info = iter->second;
break;
}
++iter;
}
logf( XW_LOGINFO, "%s(%d): DONE", __func__, info? info->GetCid():0 );
return info;
}
void
CidLock::Associate( const CookieRef* cref, int socket )
{
MutexLock ml( &m_infos_mutex );
map< CookieID, CidInfo*>::iterator iter = m_infos.begin();
while ( iter != m_infos.end() ) {
if ( cref == iter->second->GetRef() ) {
iter->second->SetSocket( socket );
break;
}
++iter;
}
}
void
CidLock::DisAssociate( const CookieRef* cref, int socket )
{
Associate( cref, 0 );
}
void
CidLock::Relinquish( CidInfo* claim )
{
CookieID cid = claim->GetCid();
logf( XW_LOGINFO, "%s(%d)", __func__, cid );
MutexLock ml( &m_infos_mutex );
map< CookieID, CidInfo*>::iterator iter = m_infos.find( cid );
assert( iter != m_infos.end() );
iter->second->SetOwner( 0 );
print_claimed();
pthread_cond_signal( &m_infos_condvar );
logf( XW_LOGINFO, "%s(%d): DONE", __func__, cid );
}

86
xwords4/relay/cidlock.h Normal file
View file

@ -0,0 +1,86 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2005-2011 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _CIDLOCK_H_
#define _CIDLOCK_H_
#include <map>
#include "xwrelay.h"
#include "cref.h"
using namespace std;
class CidInfo {
public:
CidInfo( CookieID cid )
:m_cid(cid),
m_cref(NULL),
m_owner(NULL),
m_socket(0) {}
CookieID GetCid( void ) { return m_cid; }
CookieRef* GetRef( void ) { return m_cref; }
pthread_t GetOwner( void ) { return m_owner; }
int GetSocket( void ) { return m_socket; }
void SetRef( CookieRef* cref ) { m_cref = cref; }
void SetOwner( pthread_t owner ) { m_owner = owner; }
void SetSocket( int socket ) { m_socket = socket; }
private:
CookieID m_cid;
CookieRef* m_cref;
pthread_t m_owner;
int m_socket;
};
class CidLock {
public:
static CidLock* GetInstance() {
if ( NULL == s_instance ) {
s_instance = new CidLock();
}
return s_instance;
}
CidInfo* Claim( void ) { return Claim(0); }
CidInfo* Claim( CookieID cid );
CidInfo* ClaimSocket( int sock );
void Relinquish( CidInfo* claim );
void Associate( const CookieRef* cref, int socket );
void DisAssociate( const CookieRef* cref, int socket );
private:
CidLock();
~CidLock();
void print_claimed();
static CidLock* s_instance;
map< CookieID, CidInfo*> m_infos;
pthread_mutex_t m_infos_mutex;
pthread_cond_t m_infos_condvar;
int m_nextCID;
}; /* CidLock */
#endif

View file

@ -1283,7 +1283,7 @@ CookieRef::s_checkAllConnected( void* closure )
{
/* Need to ensure */
CookieRef* self = (CookieRef*)closure;
SafeCref scr(self);
SafeCref scr(self->GetCookieID(), false );
scr.CheckAllConnected();
}
@ -1294,7 +1294,7 @@ CookieRef::s_checkAck( void* closure )
CookieRef* self = at->m_this;
if ( NULL != self ) {
at->m_this = NULL;
SafeCref scr(self);
SafeCref scr(self->GetCookieID(), false );
scr.CheckNotAcked( at->m_hid );
}
}

View file

@ -55,17 +55,16 @@ CRefMgr::Get()
} /* Get */
CRefMgr::CRefMgr()
: m_nextCID(0)
, m_nRoomsFilled(0)
: m_nRoomsFilled(0)
, m_startTime(time(NULL))
{
/* should be using pthread_once() here */
pthread_mutex_init( &m_SocketStuffMutex, NULL );
pthread_mutex_init( &m_nextCIDMutex, NULL );
pthread_mutex_init( &m_roomsFilledMutex, NULL );
pthread_mutex_init( &m_freeList_mutex, NULL );
pthread_rwlock_init( &m_cookieMapRWLock, NULL );
m_db = DBMgr::Get();
m_cidlock = CidLock::GetInstance();
}
CRefMgr::~CRefMgr()
@ -101,21 +100,21 @@ CRefMgr::CloseAll()
}
cref = iter->second;
{
SafeCref scr( cref ); /* cref */
SafeCref scr( cref->GetCookieID(), false ); /* cref */
scr.Shutdown();
}
}
}
} /* CloseAll */
CookieID
CRefMgr::nextCID( const char* connName )
{
/* Later may want to guarantee that wrap-around doesn't cause an overlap.
But that's really only a theoretical possibility. */
MutexLock ml(&m_nextCIDMutex);
return ++m_nextCID;
} /* nextCID */
/* CookieID */
/* CRefMgr::nextCID( const char* connName ) */
/* { */
/* /\* Later may want to guarantee that wrap-around doesn't cause an overlap. */
/* But that's really only a theoretical possibility. *\/ */
/* MutexLock ml(&m_nextCIDMutex); */
/* return ++m_nextCID; */
/* } /\* nextCID *\/ */
void
CRefMgr::IncrementFullCount( void )
@ -179,7 +178,7 @@ CRefMgr::GetStats( CrefMgrInfo& mgrInfo )
info.m_startTime = cref->GetStarttime();
info.m_langCode = cref->GetLangCode();
SafeCref sc(cref);
SafeCref sc(cref->GetCookieID(), false );
sc.GetHostsConnected( &info.m_hostsIds, &info.m_hostSeeds,
&info.m_hostIps );
@ -229,13 +228,13 @@ CRefMgr::getFromFreeList( void )
}
/* connect case */
CookieRef*
CidInfo*
CRefMgr::getMakeCookieRef( const char* cookie, HostID hid, int socket,
int nPlayersH, int nPlayersT, int langCode,
int seed, bool wantsPublic,
bool makePublic, bool* seenSeed )
{
CookieRef* cref;
CidInfo* cinfo;
CookieID cid;
char connNameBuf[MAX_CONNNAME_LEN+1] = {0};
int alreadyHere = 0;
@ -258,11 +257,13 @@ CRefMgr::getMakeCookieRef( const char* cookie, HostID hid, int socket,
}
if ( cid > 0 ) {
cref = getCookieRef_impl( cid );
cinfo = getCookieRef_impl( cid );
} else {
cid = nextCID( NULL );
cref = AddNew( cookie, connNameBuf, cid, langCode,
nPlayersT, alreadyHere );
cinfo = m_cidlock->Claim();
cid = cinfo->GetCid();
CookieRef* cref = AddNew( cookie, connNameBuf, cid, langCode,
nPlayersT, alreadyHere );
cinfo->SetRef( cref );
if ( !connNameBuf[0] ) { /* didn't exist in DB */
m_db->AddNew( cookie, cref->ConnName(), cid, langCode, nPlayersT,
wantsPublic || makePublic );
@ -271,17 +272,18 @@ CRefMgr::getMakeCookieRef( const char* cookie, HostID hid, int socket,
}
}
return cref;
return cinfo;
} /* getMakeCookieRef */
/* reconnect case */
CookieRef*
CidInfo*
CRefMgr::getMakeCookieRef( const char* connName, const char* cookie,
HostID hid, int socket, int nPlayersH,
int nPlayersS, int seed, int langCode,
bool isPublic, bool* isDead )
{
CookieRef* cref = NULL;
CidInfo* cinfo;
/* fetch these from DB */
char curCookie[MAX_INVITE_LEN+1];
@ -293,11 +295,13 @@ CRefMgr::getMakeCookieRef( const char* connName, const char* cookie,
&curLangCode, &nPlayersT, &nAlreadyHere,
isDead );
if ( 0 != cid ) { /* already open */
cref = getCookieRef_impl( cid );
cinfo = getCookieRef_impl( cid );
} else {
CookieID cid;
/* The entry may not even be in the DB, e.g. if it got deleted.
Deal with that possibility by taking the caller's word for it. */
CookieID cid = nextCID( NULL );
cinfo = m_cidlock->Claim();
cid = cinfo->GetCid();
if ( nPlayersT == 0 ) { /* wasn't in the DB */
m_db->AddNew( cookie, connName, cid, langCode, nPlayersS, isPublic );
@ -309,15 +313,17 @@ CRefMgr::getMakeCookieRef( const char* connName, const char* cookie,
cref = AddNew( cookie, connName, cid, curLangCode, nPlayersT,
nAlreadyHere );
cinfo->SetRef( cref );
m_db->AddCID( connName, cid );
}
return cref;
return cinfo;
} /* getMakeCookieRef */
CookieRef*
CidInfo*
CRefMgr::getMakeCookieRef( const char* const connName, bool* isDead )
{
CookieRef* cref = NULL;
CidInfo* cinfo;
char curCookie[MAX_INVITE_LEN+1];
int curLangCode;
int nPlayersT = 0;
@ -327,23 +333,25 @@ CRefMgr::getMakeCookieRef( const char* const connName, bool* isDead )
&curLangCode, &nPlayersT, &nAlreadyHere,
isDead );
if ( 0 != cid ) { /* already open */
cref = getCookieRef_impl( cid );
cinfo = getCookieRef_impl( cid );
} else {
if ( nPlayersT == 0 ) { /* wasn't in the DB */
/* do nothing; insufficient info to fake it */
} else {
CookieID cid = nextCID( NULL );
cref = AddNew( curCookie, connName, cid, curLangCode, nPlayersT,
nAlreadyHere );
m_db->AddCID( connName, cid );
cinfo = m_cidlock->Claim();
cref = AddNew( curCookie, connName, cinfo->GetCid(), curLangCode,
nPlayersT, nAlreadyHere );
cinfo->SetRef( cref );
m_db->AddCID( connName, cinfo->GetCid() );
}
}
return cref;
return cinfo;
}
bool
CRefMgr::Associate( int socket, CookieRef* cref )
{
m_cidlock->Associate( cref, socket );
MutexLock ml( &m_SocketStuffMutex );
return Associate_locked( socket, cref );
}
@ -372,6 +380,7 @@ CRefMgr::Associate_locked( int socket, CookieRef* cref )
void
CRefMgr::Disassociate_locked( int socket, CookieRef* cref )
{
m_cidlock->DisAssociate( cref, socket );
SocketMap::iterator iter = m_SocketStuff.find( socket );
if ( iter == m_SocketStuff.end() ) {
logf( XW_LOGERROR, "can't find SocketStuff for socket %d", socket );
@ -457,24 +466,26 @@ CRefMgr::MakeSocketsIterator()
return iter;
}
CookieRef*
CidInfo*
CRefMgr::getCookieRef( CookieID cookieID )
{
return getCookieRef_impl( cookieID );
} /* getCookieRef */
CookieRef*
CidInfo*
CRefMgr::getCookieRef( int socket )
{
CookieRef* cref = NULL;
MutexLock ml( &m_SocketStuffMutex );
SocketMap::iterator iter = m_SocketStuff.find( socket );
if ( iter != m_SocketStuff.end() ) {
SocketStuff* stuff = iter->second;
cref = stuff->m_cref;
}
CidInfo* cinfo = m_cidlock->ClaimSocket( socket );
/* if ( NULL == cinfo ) { */
/* MutexLock ml( &m_SocketStuffMutex ); */
/* SocketMap::iterator iter = m_SocketStuff.find( socket ); */
/* if ( iter != m_SocketStuff.end() ) { */
/* SocketStuff* stuff = iter->second; */
/* cinfo = m_cidlock->Claim( stuff->m_cref->GetCookieID() ); */
/* } */
/* } */
return cref;
return cinfo;
} /* getCookieRef */
#ifdef RELAY_HEARTBEAT
@ -566,8 +577,9 @@ CRefMgr::Recycle_locked( CookieRef* cref )
void
CRefMgr::Recycle( CookieID id )
{
CookieRef* cref = getCookieRef( id );
if ( cref != NULL ) {
CidInfo* cinfo = getCookieRef( id );
if ( cinfo != NULL ) {
CookieRef* cref = cinfo->GetRef();
cref->Lock();
Recycle_locked( cref );
}
@ -580,22 +592,24 @@ CRefMgr::Recycle( const char* connName )
Recycle( id );
} /* Delete */
CookieRef*
CRefMgr::getCookieRef_impl( CookieID cookieID )
CidInfo*
CRefMgr::getCookieRef_impl( CookieID cid )
{
CookieRef* ref = NULL;
RWReadLock rwl( &m_cookieMapRWLock );
CidInfo* info = m_cidlock->Claim( cid );
/* CookieRef* ref = NULL; */
/* RWReadLock rwl( &m_cookieMapRWLock ); */
CookieMap::iterator iter = m_cookieMap.find( cookieID );
while ( iter != m_cookieMap.end() ) {
CookieRef* second = iter->second;
if ( second->GetCookieID() == cookieID ) {
ref = second;
break;
}
++iter;
}
return ref;
/* CookieMap::iterator iter = m_cookieMap.find( cid ); */
/* while ( iter != m_cookieMap.end() ) { */
/* CookieRef* second = iter->second; */
/* if ( second->GetCookieID() == cid ) { */
/* ref = second; */
/* break; */
/* } */
/* ++iter; */
/* } */
/* info->SetRef( ref ); */
return info;
}
#ifdef RELAY_HEARTBEAT
@ -661,20 +675,21 @@ CookieMapIterator::Next()
SafeCref::SafeCref( const char* cookie, int socket, int nPlayersH, int nPlayersS,
unsigned short gameSeed, int langCode, bool wantsPublic,
bool makePublic )
: m_cref( NULL )
: m_cinfo( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
, m_seenSeed( false )
{
CookieRef* cref;
CidInfo* cinfo;
cref = m_mgr->getMakeCookieRef( cookie, 0, socket,
nPlayersH, nPlayersS, langCode,
gameSeed, wantsPublic, makePublic,
&m_seenSeed );
if ( cref != NULL ) {
cinfo = m_mgr->getMakeCookieRef( cookie, 0, socket,
nPlayersH, nPlayersS, langCode,
gameSeed, wantsPublic, makePublic,
&m_seenSeed );
if ( cinfo != NULL ) {
CookieRef* cref = cinfo->GetRef();
m_locked = cref->Lock();
m_cref = cref;
m_cinfo = cinfo;
m_isValid = true;
}
}
@ -684,20 +699,20 @@ SafeCref::SafeCref( const char* connName, const char* cookie, HostID hid,
int socket, int nPlayersH, int nPlayersS,
unsigned short gameSeed, int langCode,
bool wantsPublic, bool makePublic )
: m_cref( NULL )
: m_cinfo( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
{
CookieRef* cref;
CidInfo* cinfo;
assert( hid <= 4 ); /* no more than 4 hosts */
bool isDead = false;
cref = m_mgr->getMakeCookieRef( connName, cookie, hid, socket, nPlayersH,
nPlayersS, gameSeed, langCode,
wantsPublic || makePublic, &isDead );
if ( cref != NULL ) {
m_locked = cref->Lock();
m_cref = cref;
cinfo = m_mgr->getMakeCookieRef( connName, cookie, hid, socket, nPlayersH,
nPlayersS, gameSeed, langCode,
wantsPublic || makePublic, &isDead );
if ( cinfo != NULL ) {
m_locked = cinfo->GetRef()->Lock();
m_cinfo = cinfo;
m_isValid = true;
m_dead = isDead;
}
@ -705,63 +720,70 @@ SafeCref::SafeCref( const char* connName, const char* cookie, HostID hid,
/* ConnName case -- must exist */
SafeCref::SafeCref( const char* const connName )
: m_cref( NULL )
: m_cinfo( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
{
bool isDead = false;
CookieRef* cref = m_mgr->getMakeCookieRef( connName, &isDead );
if ( cref != NULL ) {
m_locked = cref->Lock();
m_cref = cref;
CidInfo* cinfo = m_mgr->getMakeCookieRef( connName, &isDead );
if ( cinfo != NULL ) {
m_locked = cinfo->GetRef()->Lock();
m_cinfo = cinfo;
m_isValid = true;
m_dead = isDead;
}
}
SafeCref::SafeCref( CookieID connID, bool failOk )
: m_cref( NULL )
: m_cinfo( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
{
CookieRef* cref = m_mgr->getCookieRef( connID );
if ( cref != NULL ) { /* known cookie? */
CidInfo* cinfo = m_mgr->getCookieRef( connID );
if ( cinfo != NULL ) { /* known cookie? */
CookieRef* cref = cinfo->GetRef();
m_locked = cref->Lock();
m_isValid = m_locked && connID == cref->GetCookieID();
m_cref = cref;
m_cinfo = cinfo;
}
}
SafeCref::SafeCref( int socket )
: m_cref( NULL )
: m_cinfo( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
{
CookieRef* cref = m_mgr->getCookieRef( socket );
if ( cref != NULL ) { /* known socket? */
CidInfo* cinfo = m_mgr->getCookieRef( socket );
if ( cinfo != NULL ) { /* known socket? */
CookieRef* cref = cinfo->GetRef();
m_locked = cref->Lock();
m_isValid = m_locked && cref->HasSocket_locked( socket );
m_cref = cref;
m_cinfo = cinfo;
}
}
SafeCref::SafeCref( CookieRef* cref )
: m_cref( NULL )
, m_mgr( CRefMgr::Get() )
, m_isValid( false )
{
m_locked = cref->Lock();
m_isValid = m_locked;
m_cref = cref;
}
/* SafeCref::SafeCref( CookieRef* cref ) */
/* : m_cinfo( NULL ) */
/* , m_mgr( CRefMgr::Get() ) */
/* , m_isValid( false ) */
/* { */
/* assert(0); /\* path to this? *\/ */
/* m_locked = cref->Lock(); */
/* m_isValid = m_locked; */
/* // m_cref = cref; */
/* } */
SafeCref::~SafeCref()
{
if ( m_cref != NULL && m_locked ) {
if ( m_cref->ShouldDie() ) {
m_mgr->Recycle_locked( m_cref );
} else {
m_cref->Unlock();
if ( m_cinfo != NULL ) {
if ( m_locked ) {
CookieRef* cref = m_cinfo->GetRef();
if ( cref->ShouldDie() ) {
m_mgr->Recycle_locked( cref );
} else {
cref->Unlock();
}
}
m_mgr->m_cidlock->Relinquish( m_cinfo );
}
}

View file

@ -27,6 +27,7 @@
#include "cref.h"
#include "dbmgr.h"
#include "mlock.h"
#include "cidlock.h"
typedef map<CookieID,CookieRef*> CookieMap;
class CookieMapIterator;
@ -135,24 +136,24 @@ class CRefMgr {
CookieRef* getFromFreeList( void );
/* connect case */
CookieRef* getMakeCookieRef( const char* cookie,
HostID hid, int socket, int nPlayersH,
int nPlayersS, int langCode, int seed,
bool wantsPublic, bool makePublic,
bool* seenSeed );
CidInfo* getMakeCookieRef( const char* cookie,
HostID hid, int socket, int nPlayersH,
int nPlayersS, int langCode, int seed,
bool wantsPublic, bool makePublic,
bool* seenSeed );
/* reconnect case; just the stuff we don't have in db */
CookieRef* getMakeCookieRef( const char* connName, const char* cookie,
HostID hid, int socket, int nPlayersH,
int nPlayersS, int seed, int langCode,
bool isPublic, bool* isDead );
CidInfo* getMakeCookieRef( const char* connName, const char* cookie,
HostID hid, int socket, int nPlayersH,
int nPlayersS, int seed, int langCode,
bool isPublic, bool* isDead );
CookieRef* getMakeCookieRef( const char* const connName, bool* isDead );
CidInfo* getMakeCookieRef( const char* const connName, bool* isDead );
CookieRef* getCookieRef( CookieID cookieID );
CookieRef* getCookieRef( int socket );
CidInfo* getCookieRef( CookieID cookieID );
CidInfo* getCookieRef( int socket );
bool checkCookieRef_locked( CookieRef* cref );
CookieRef* getCookieRef_impl( CookieID cookieID );
CidInfo* getCookieRef_impl( CookieID cookieID );
CookieRef* AddNew( const char* cookie, const char* connName, CookieID id,
int langCode, int nPlayers, int nAlreadyHere );
CookieRef* FindOpenGameFor( const char* cookie, const char* connName,
@ -166,8 +167,8 @@ class CRefMgr {
static void heartbeatProc( void* closure );
void checkHeartbeats( time_t now );
pthread_mutex_t m_nextCIDMutex;
CookieID m_nextCID;
/* pthread_mutex_t m_nextCIDMutex; */
/* CookieID m_nextCID; */
pthread_mutex_t m_roomsFilledMutex;
int m_nRoomsFilled;
@ -182,6 +183,7 @@ class CRefMgr {
string m_ports;
DBMgr* m_db;
CidLock* m_cidlock;
friend class CookieMapIterator;
}; /* CRefMgr */
@ -205,13 +207,14 @@ class SafeCref {
SafeCref( const char* const connName );
SafeCref( CookieID cid, bool failOk = false );
SafeCref( int socket );
SafeCref( CookieRef* cref );
/* SafeCref( CookieRef* cref ); */
~SafeCref();
bool Forward( HostID src, HostID dest, unsigned char* buf, int buflen ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_Forward( src, dest, buf, buflen );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_Forward( src, dest, buf, buflen );
return true;
} else {
return false;
@ -219,9 +222,10 @@ class SafeCref {
}
bool Connect( int socket, int nPlayersH, int nPlayersS, int seed ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
return m_cref->_Connect( socket, nPlayersH, nPlayersS, seed,
m_seenSeed );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
return cref->_Connect( socket, nPlayersH, nPlayersS, seed,
m_seenSeed );
} else {
return false;
}
@ -229,9 +233,10 @@ class SafeCref {
bool Reconnect( int socket, HostID srcID, int nPlayersH, int nPlayersS,
int seed ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_Reconnect( socket, srcID, nPlayersH, nPlayersS,
seed, m_dead );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_Reconnect( socket, srcID, nPlayersH, nPlayersS,
seed, m_dead );
return true;
} else {
return false;
@ -239,23 +244,26 @@ class SafeCref {
}
void Disconnect(int socket, HostID hostID ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_Disconnect( socket, hostID );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_Disconnect( socket, hostID );
}
}
void DeviceGone( HostID hid, int seed )
{
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_DeviceGone( hid, seed );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_DeviceGone( hid, seed );
}
}
bool HandleAck(HostID hostID ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_HandleAck( hostID );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_HandleAck( hostID );
return true;
} else {
return false;
@ -263,22 +271,25 @@ class SafeCref {
}
void Shutdown() {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_Shutdown();
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_Shutdown();
}
}
void Remove( int socket ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_Remove( socket );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_Remove( socket );
}
}
#ifdef RELAY_HEARTBEAT
bool HandleHeartbeat( HostID id, int socket ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_HandleHeartbeat( id, socket );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_HandleHeartbeat( id, socket );
return true;
} else {
return false;
@ -286,37 +297,43 @@ class SafeCref {
}
void CheckHeartbeats( time_t now ) {
if ( IsValid() ) {
assert( 0 != m_cref->GetCookieID() );
m_cref->_CheckHeartbeats( now );
CookieRef* cref = m_cinfo->GetRef();
assert( 0 != cref->GetCookieID() );
cref->_CheckHeartbeats( now );
}
}
#endif
void PrintCookieInfo( string& out ) {
if ( IsValid() ) {
m_cref->_PrintCookieInfo( out );
CookieRef* cref = m_cinfo->GetRef();
cref->_PrintCookieInfo( out );
}
}
void CheckAllConnected() {
if ( IsValid() ) {
m_cref->_CheckAllConnected();
CookieRef* cref = m_cinfo->GetRef();
cref->_CheckAllConnected();
}
}
void CheckNotAcked( HostID hid ) {
if ( IsValid() ) {
m_cref->_CheckNotAcked( hid );
CookieRef* cref = m_cinfo->GetRef();
cref->_CheckNotAcked( hid );
}
}
const char* Cookie() {
if ( IsValid() ) {
return m_cref->Cookie();
CookieRef* cref = m_cinfo->GetRef();
return cref->Cookie();
} else {
return ""; /* so don't crash.... */
}
}
const char* ConnName() {
if ( IsValid() ) {
return m_cref->ConnName();
CookieRef* cref = m_cinfo->GetRef();
return cref->ConnName();
} else {
return ""; /* so don't crash.... */
}
@ -324,7 +341,8 @@ class SafeCref {
CookieID GetCookieID() {
if ( IsValid() ) {
return m_cref->GetCookieID();
CookieRef* cref = m_cinfo->GetRef();
return cref->GetCookieID();
} else {
return 0; /* so don't crash.... */
}
@ -332,14 +350,16 @@ class SafeCref {
int GetPlayersTotal() {
if ( IsValid() ) {
return m_cref->GetPlayersSought();
CookieRef* cref = m_cinfo->GetRef();
return cref->GetPlayersSought();
} else {
return -1; /* so don't crash.... */
}
}
int GetPlayersHere() {
if ( IsValid() ) {
return m_cref->GetPlayersHere();
CookieRef* cref = m_cinfo->GetRef();
return cref->GetPlayersHere();
} else {
return -1; /* so don't crash.... */
}
@ -347,7 +367,8 @@ class SafeCref {
const char* StateString() {
if ( IsValid() ) {
return stateString( m_cref->CurState() );
CookieRef* cref = m_cinfo->GetRef();
return stateString( cref->CurState() );
} else {
return "";
}
@ -355,13 +376,15 @@ class SafeCref {
void GetHostsConnected( string* hosts, string* seeds, string* addrs ) {
if ( IsValid() ) {
m_cref->_FormatHostInfo( hosts, seeds, addrs );
CookieRef* cref = m_cinfo->GetRef();
cref->_FormatHostInfo( hosts, seeds, addrs );
}
}
time_t GetStartTime(void) {
if ( IsValid() ) {
return m_cref->GetStarttime();
CookieRef* cref = m_cinfo->GetRef();
return cref->GetStarttime();
} else {
return 0;
}
@ -371,7 +394,7 @@ class SafeCref {
bool SeenSeed() { return m_seenSeed; }
private:
CookieRef* m_cref;
CidInfo* m_cinfo;
CRefMgr* m_mgr;
bool m_isValid;
bool m_locked;