xwords/xwords4/relay/dbmgr.h
Eric House 4fa1b3faf4 Don't join a game that's been idle for more than two weeks
The two weeks is configurable. But the idea is somebody creates a game
with a random name but it's never joined. Eventually the name is used
again and the first to connect joins the existing game that will never
progress. I could just prune from the DB, but this is less work ongoing.
2020-01-10 20:13:06 -08:00

207 lines
8.4 KiB
C

/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2010 - 2012 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 _DBMGR_H_
#define _DBMGR_H_
#include <string>
#include <set>
#include <libpq-fe.h>
#include "strwpf.h"
#include "xwrelay.h"
#include "xwrelay_priv.h"
#include "devid.h"
#include "strwpf.h"
#include "querybld.h"
using namespace std;
class DBMgr {
public:
/* DevIDs on various platforms are stored in devices table. This is the
key, and used in msgs and games tables as a shorter way to refer to
them. */
static const DevIDRelay DEVID_NONE = 0;
class MsgInfo {
public:
MsgInfo( int id, AddrInfo::ClientToken tok, bool hc ) {
m_msgID = id; m_token = tok; m_hasConnname = hc;
}
bool hasConnname() const { return m_hasConnname; }
AddrInfo::ClientToken token() const { return m_token; }
int msgID() const { return m_msgID; }
vector<uint8_t> msg;
private:
bool m_hasConnname;
AddrInfo::ClientToken m_token;
int m_msgID;
};
static DBMgr* Get();
~DBMgr();
void WaitDBConn( void );
void ClearCIDs( void );
void AddNew( const char* cookie, const char* connName, CookieID cid,
int langCode, int nPlayersT, bool isPublic );
bool FindPlayer( DevIDRelay relayID, AddrInfo::ClientToken,
string& connName, HostID* hid, unsigned short* seed );
bool FindRelayIDFor( const char* connName, HostID hid, unsigned short seed,
const DevID* host, DevIDRelay* devID );
CookieID FindGame( const char* connName, HostID hid, char* cookieBuf, int bufLen,
int* langP, int* nPlayersTP, int* nPlayersHP,
bool* isDead );
CookieID FindGame( const AddrInfo::ClientToken clientToken, HostID hid,
char* connNameBuf, int connNameBufLen,
char* cookieBuf, int cookieBufLen,
int* langP, int* nPlayersTP, int* nPlayersHP );
bool FindGameFor( const char* connName, char* cookieBuf, int bufLen,
unsigned short seed, HostID hid,
int nPlayersH, int nPlayersS,
int* langP, bool* isDead, CookieID* cidp );
bool SeenSeed( const char* cookie, unsigned short seed,
int langCode, int nPlayersT, bool wantsPublic,
char* connNameBuf, int bufLen, int* nPlayersHP,
CookieID* cid );
CookieID FindRecentOpen( const char* cookie, int lang, int nPlayersT,
int nPlayersH, bool wantsPublic,
char* connNameBuf, int bufLen, int* nPlayersHP );
bool AllDevsAckd( const char* const connName );
DevIDRelay RegisterDevice( const DevID* host );
DevIDRelay RegisterDevice( const DevID* host, int clientVersion,
const char* const desc, const char* const model,
const char* const osVers,
unsigned short variantCode );
void ReregisterDevice( DevIDRelay relayID, const DevID* host,
const char* const desc, int clientVersion,
const char* const model, const char* const osVers,
unsigned short variantCode );
bool UpdateDevice( DevIDRelay relayID, const char* const desc,
int clientVersion, const char* const model,
const char* const osVers, unsigned short variantCode,
bool check );
HostID AddToGame( const char* const connName, HostID curID, int clientVersion,
int nToAdd, unsigned short seed, const AddrInfo* addr,
DevIDRelay devID, bool unAckd );
void NoteAckd( const char* const connName, HostID id );
HostID HIDForSeed( const char* const connName, unsigned short seed );
bool RmDeviceByHid( const char* const connName, HostID id );
void RmDeviceBySeed( const char* const connName, unsigned short seed );
bool HaveDevice( const char* const connName, HostID id, int seed );
bool AddCID( const char* const connName, CookieID cid );
void ClearCID( const char* connName );
void RecordSent( const char* const connName, HostID hid, int nBytes );
void RecordSent( const int* msgID, int nMsgIDs );
void RecordAddress( const char* const connName, HostID hid,
const AddrInfo* addr );
void GetPlayerCounts( const char* const connName, int* nTotal,
int* nHere );
void KillGame( const char* const connName, int hid );
/* Return list of roomName/playersStillWanted/age for open public games
matching this language and total game size. Will probably want to cache
lists locally and only update them every few seconds to avoid to many
queries.*/
void PublicRooms( int lang, int nPlayers, int* nNames, string& names );
/* Get stored address info, if available and valid */
bool TokenFor( const char* const connName, int hid, DevIDRelay* devid,
AddrInfo::ClientToken* token );
/* message storage -- different DB */
int CountStoredMessages( const char* const connName );
int CountStoredMessages( DevIDRelay relayID );
int StoreMessage( DevIDRelay destRelayID, const uint8_t* const buf,
int len );
int StoreMessage( const char* const connName, int destHid,
const uint8_t* const buf, int len );
void GetStoredMessages( DevIDRelay relayID, vector<MsgInfo>& msgs );
void GetStoredMessages( const char* const connName, HostID hid,
vector<DBMgr::MsgInfo>& msgs );
void RemoveStoredMessages( const int* msgID, int nMsgIDs );
void RemoveStoredMessage( const int msgID );
void RemoveStoredMessages( vector<int>& ids );
DevIDRelay getDevID( string& relayID );
private:
DBMgr();
bool execSql( const string& query );
bool execSql( const char* const query ); /* no-results query */
bool execParams( QueryBuilder& qb );
void readArray( const char* const connName, const char* column, int arr[] );
DevIDRelay getDevID( const char* connName, int hid );
DevIDRelay getDevID( const DevID* devID );
int getCountWhere( const char* table, string& test );
void RemoveStoredMessages( string& msgIDs );
void decodeMessage( PGresult* result, bool useB64, int rowIndx, int b64indx,
int byteaIndex, vector<uint8_t>& buf );
void storedMessagesImpl( string query, vector<DBMgr::MsgInfo>& msgs,
bool nullConnnameOK );
int CountStoredMessages( const char* const connName, int hid );
bool UpdateDevice( DevIDRelay relayID );
void formatUpdate( QueryBuilder& qb, bool append, const char* const desc,
int clientVersion, const char* const model,
const char* const osVers, unsigned short variantCode,
DevIDRelay relayID );
PGconn* getThreadConn( void );
void clearThreadConn();
bool hasNoMessages( const char* const connName, HostID hid );
void setHasNoMessages( const char* const connName, HostID hid );
void clearHasNoMessages( const char* const connName, HostID hid );
void formatKey( StrWPF& key, const char* const connName, HostID hid );
bool hasNoMessages( DevIDRelay devid );
void setHasNoMessages( DevIDRelay devid );
void clearHasNoMessages( DevIDRelay devid );
void conn_key_alloc();
pthread_key_t m_conn_key;
bool m_useB64;
char m_interval[64];
pthread_mutex_t m_haveNoMessagesMutex;
set<DevIDRelay> m_haveNoMessagesDevID;
set<StrWPF> m_haveNoMessagesConnname;
}; /* DBMgr */
#endif