mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-28 09:58:30 +01:00
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:
parent
c87df3ce16
commit
3ebcc01e86
6 changed files with 432 additions and 152 deletions
|
@ -30,6 +30,7 @@ SRC = \
|
|||
states.cpp \
|
||||
timermgr.cpp \
|
||||
tpool.cpp \
|
||||
cidlock.cpp \
|
||||
xwrelay.cpp \
|
||||
|
||||
# STATIC ?= -static
|
||||
|
|
148
xwords4/relay/cidlock.cpp
Normal file
148
xwords4/relay/cidlock.cpp
Normal 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
86
xwords4/relay/cidlock.h
Normal 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
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue