mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-29 10:26:36 +01:00
reduce sending of dead-game mqtt messages
Two cases dealt with here. First, if my opponent deletes the game when I have an un-ack'd message, I'll keep sending it forever. Fix is to flip a bit in comms in response to a game_gone event so no more sending will happen. (Better than emptying the queue, as it leaves open the possibility of resurrecting the game with code changes later.) Second, if there's a retained message from a dead game I'll keep receiving it until it's replaced, and if the game's dead it never will be. Fix is to add a new api endpoint noSuchGame() to the relay2 server and to call it on receiving a message for which I have no game to deliver it to. The endpoint "unretains" the message so I won't get it again unless it's resent.
This commit is contained in:
parent
0528e5b5fd
commit
259357a818
7 changed files with 102 additions and 5 deletions
|
@ -1404,6 +1404,38 @@ public class GameUtils {
|
||||||
body, rowid );
|
body, rowid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PENDING This -- finding or opening game, doing something, then saving
|
||||||
|
// and closing if it was opened -- gets done a lot. Try refactoring.
|
||||||
|
public static void onGameGone( Context context, int gameID )
|
||||||
|
{
|
||||||
|
long[] rowids = DBUtils.getRowIDsFor( context, gameID );
|
||||||
|
if ( null == rowids || 0 == rowids.length ) {
|
||||||
|
Log.d( TAG, "onGameGone(): no rows for game %X", gameID );
|
||||||
|
} else {
|
||||||
|
for ( long rowid: rowids ) {
|
||||||
|
try ( JNIThread thread = JNIThread.getRetained( rowid ) ) {
|
||||||
|
if ( null != thread ) {
|
||||||
|
XwJNI.comms_setQuashed( thread.getGamePtr() );
|
||||||
|
// JNIThread saves automatically on release
|
||||||
|
} else {
|
||||||
|
try ( GameLock lock = GameLock.lock( rowid, 300 ) ) {
|
||||||
|
if ( null != lock ) {
|
||||||
|
CurGameInfo gi = new CurGameInfo( context );
|
||||||
|
try ( GamePtr gamePtr = loadMakeGame( context, gi, lock ) ) {
|
||||||
|
if ( null != gamePtr ) {
|
||||||
|
if ( XwJNI.comms_setQuashed( gamePtr ) ) {
|
||||||
|
saveGame( context, gamePtr, gi, lock, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void tellDied( Context context, GameLock lock,
|
private static void tellDied( Context context, GameLock lock,
|
||||||
boolean informNow )
|
boolean informNow )
|
||||||
{
|
{
|
||||||
|
|
|
@ -562,11 +562,34 @@ public class MQTTUtils extends Thread
|
||||||
clearInstance( this );
|
clearInstance( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void postNoSuchGame( final Context context, final int gameID )
|
||||||
|
{
|
||||||
|
// Run in thread in case we're called on main thread
|
||||||
|
new Thread( new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
JSONObject params = new JSONObject();
|
||||||
|
try {
|
||||||
|
String devid = XwJNI.dvc_getMQTTDevID();
|
||||||
|
params.put( "devid", devid );
|
||||||
|
params.put( "gameid", gameID );
|
||||||
|
HttpsURLConnection conn
|
||||||
|
= NetUtils.makeHttpsMQTTConn( context, "noSuchGame" );
|
||||||
|
/*(void*)*/NetUtils.runConn( conn, params, true );
|
||||||
|
} catch ( JSONException jex ) {
|
||||||
|
Log.e( TAG, "notifyNotHere() ex: %s", jex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ).start();
|
||||||
|
}
|
||||||
|
|
||||||
private static void notifyNotHere( Context context, String addressee,
|
private static void notifyNotHere( Context context, String addressee,
|
||||||
int gameID )
|
int gameID )
|
||||||
{
|
{
|
||||||
TopicsAndPackets tap = XwJNI.dvc_makeMQTTNoSuchGames( addressee, gameID );
|
TopicsAndPackets tap = XwJNI.dvc_makeMQTTNoSuchGames( addressee, gameID );
|
||||||
addToSendQueue( context, tap );
|
addToSendQueue( context, tap );
|
||||||
|
|
||||||
|
postNoSuchGame( context, gameID );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int send( Context context, TopicsAndPackets tap )
|
public static int send( Context context, TopicsAndPackets tap )
|
||||||
|
@ -775,6 +798,7 @@ public class MQTTUtils extends Thread
|
||||||
new MQTTServiceHelper( context, from )
|
new MQTTServiceHelper( context, from )
|
||||||
.postEvent( MultiService.MultiEvent.MESSAGE_NOGAME, gameID,
|
.postEvent( MultiService.MultiEvent.MESSAGE_NOGAME, gameID,
|
||||||
expl );
|
expl );
|
||||||
|
postNoSuchGame( context, gameID );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fcmConfirmed( Context context, boolean working )
|
public static void fcmConfirmed( Context context, boolean working )
|
||||||
|
|
|
@ -348,6 +348,8 @@ public class DUtilCtxt {
|
||||||
|
|
||||||
public void onGameGoneReceived( int gameID, CommsAddrRec from )
|
public void onGameGoneReceived( int gameID, CommsAddrRec from )
|
||||||
{
|
{
|
||||||
|
GameUtils.onGameGone( m_context, gameID );
|
||||||
|
|
||||||
Assert.assertTrueNR( from.contains( CommsAddrRec.CommsConnType.COMMS_CONN_MQTT ) );
|
Assert.assertTrueNR( from.contains( CommsAddrRec.CommsConnType.COMMS_CONN_MQTT ) );
|
||||||
MQTTUtils.handleGameGone( m_context, from, gameID );
|
MQTTUtils.handleGameGone( m_context, from, gameID );
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class XwJNI {
|
||||||
public static TopicsAndPackets dvc_makeMQTTNoSuchGames( String addressee, int gameID )
|
public static TopicsAndPackets dvc_makeMQTTNoSuchGames( String addressee, int gameID )
|
||||||
{
|
{
|
||||||
Log.d( TAG, "dvc_makeMQTTNoSuchGames(to: %s, gameID: %X)", addressee, gameID );
|
Log.d( TAG, "dvc_makeMQTTNoSuchGames(to: %s, gameID: %X)", addressee, gameID );
|
||||||
DbgUtils.printStack( TAG );
|
// DbgUtils.printStack( TAG );
|
||||||
return dvc_makeMQTTNoSuchGames( getJNI().m_ptrGlobals, addressee, gameID );
|
return dvc_makeMQTTNoSuchGames( getJNI().m_ptrGlobals, addressee, gameID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,6 +549,7 @@ public class XwJNI {
|
||||||
public static native CommsAddrRec comms_getHostAddr( GamePtr gamePtr );
|
public static native CommsAddrRec comms_getHostAddr( GamePtr gamePtr );
|
||||||
public static native CommsAddrRec[] comms_getAddrs( GamePtr gamePtr );
|
public static native CommsAddrRec[] comms_getAddrs( GamePtr gamePtr );
|
||||||
public static native void comms_dropHostAddr( GamePtr gamePtr, CommsConnType typ );
|
public static native void comms_dropHostAddr( GamePtr gamePtr, CommsConnType typ );
|
||||||
|
public static native boolean comms_setQuashed( GamePtr gamePtr );
|
||||||
public static native int comms_resendAll( GamePtr gamePtr, boolean force,
|
public static native int comms_resendAll( GamePtr gamePtr, boolean force,
|
||||||
CommsConnType filter,
|
CommsConnType filter,
|
||||||
boolean andAck );
|
boolean andAck );
|
||||||
|
|
|
@ -2664,6 +2664,20 @@ Java_org_eehouse_android_xw4_jni_XwJNI_comms_1dropHostAddr
|
||||||
LOG_RETURN_VOID();
|
LOG_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1setQuashed
|
||||||
|
( JNIEnv* env, jclass C, GamePtrType gamePtr )
|
||||||
|
{
|
||||||
|
jboolean result = false;
|
||||||
|
XWJNI_START(gamePtr);
|
||||||
|
XP_ASSERT( !!state->game.comms );
|
||||||
|
if ( NULL != state->game.comms ) {
|
||||||
|
result = comms_setQuashed( state->game.comms, XP_TRUE );
|
||||||
|
}
|
||||||
|
XWJNI_END();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1setAddrDisabled
|
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1setAddrDisabled
|
||||||
|
|
|
@ -238,6 +238,8 @@ struct CommsCtxt {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FLAG_HARVEST_DONE 1
|
#define FLAG_HARVEST_DONE 1
|
||||||
|
#define FLAG_QUASHED 2
|
||||||
|
#define QUASHED(COMMS) (0 != ((COMMS)->flags & FLAG_QUASHED))
|
||||||
|
|
||||||
#if defined XWFEATURE_IP_DIRECT || defined XWFEATURE_DIRECTIP
|
#if defined XWFEATURE_IP_DIRECT || defined XWFEATURE_DIRECTIP
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -2082,7 +2084,9 @@ sendMsg( const CommsCtxt* comms, XWEnv xwe, MsgQueueElem* elem,
|
||||||
addrP = &comms->recs->addr;
|
addrP = &comms->recs->addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( NULL == addrP ) {
|
if ( QUASHED(comms) ) {
|
||||||
|
// XP_LOGFF( "not sending; comms is quashed" );
|
||||||
|
} else if ( NULL == addrP ) {
|
||||||
XP_LOGFF( TAGFMT() "no addr for channel %x; dropping!'", TAGPRMS, channelNo );
|
XP_LOGFF( TAGFMT() "no addr for channel %x; dropping!'", TAGPRMS, channelNo );
|
||||||
// XP_ASSERT(0); /* firing */
|
// XP_ASSERT(0); /* firing */
|
||||||
} else {
|
} else {
|
||||||
|
@ -2235,7 +2239,9 @@ comms_resendAll( CommsCtxt* comms, XWEnv xwe, CommsConnType filter, XP_Bool forc
|
||||||
XP_ASSERT( !!comms );
|
XP_ASSERT( !!comms );
|
||||||
|
|
||||||
XP_U32 now = dutil_getCurSeconds( comms->dutil, xwe );
|
XP_U32 now = dutil_getCurSeconds( comms->dutil, xwe );
|
||||||
if ( !force && (now < comms->nextResend) ) {
|
if ( QUASHED(comms) ) {
|
||||||
|
// XP_LOGFF( "not sending; comms is quashed" );
|
||||||
|
} else if ( !force && (now < comms->nextResend) ) {
|
||||||
XP_LOGFF( "aborting: %d seconds left in backoff",
|
XP_LOGFF( "aborting: %d seconds left in backoff",
|
||||||
comms->nextResend - now );
|
comms->nextResend - now );
|
||||||
} else {
|
} else {
|
||||||
|
@ -3256,6 +3262,23 @@ comms_isConnected( const CommsCtxt* const comms )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XP_Bool
|
||||||
|
comms_setQuashed( CommsCtxt* comms, XP_Bool quashed )
|
||||||
|
{
|
||||||
|
XP_U8 flags = comms->flags;
|
||||||
|
if ( quashed ) {
|
||||||
|
flags |= FLAG_QUASHED;
|
||||||
|
} else {
|
||||||
|
flags &= ~FLAG_QUASHED;
|
||||||
|
}
|
||||||
|
XP_Bool changed = flags != comms->flags;
|
||||||
|
if ( changed ) {
|
||||||
|
comms->flags = flags;
|
||||||
|
XP_LOGFF( "(quashed=%s): changing state", boolToStr(quashed) );
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XWFEATURE_KNOWNPLAYERS
|
#ifdef XWFEATURE_KNOWNPLAYERS
|
||||||
void
|
void
|
||||||
comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created )
|
comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created )
|
||||||
|
@ -3459,9 +3482,9 @@ comms_getStats( const CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
XP_UCHAR buf[100];
|
XP_UCHAR buf[100];
|
||||||
|
|
||||||
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
||||||
(XP_UCHAR*)"role: %s; msg queue len: %d\n",
|
(XP_UCHAR*)"role: %s; msg queue len: %d; quashed: %s;\n",
|
||||||
comms->isServer ? "host" : "guest",
|
comms->isServer ? "host" : "guest",
|
||||||
comms->queueLen );
|
comms->queueLen, boolToStr(QUASHED(comms)) );
|
||||||
stream_catString( stream, buf );
|
stream_catString( stream, buf );
|
||||||
|
|
||||||
forEachElem( (CommsCtxt*)comms, statsProc, stream );
|
forEachElem( (CommsCtxt*)comms, statsProc, stream );
|
||||||
|
|
|
@ -244,6 +244,7 @@ XP_Bool comms_checkComplete( const CommsAddrRec* const addr );
|
||||||
|
|
||||||
XP_Bool comms_canChat( const CommsCtxt* comms );
|
XP_Bool comms_canChat( const CommsCtxt* comms );
|
||||||
XP_Bool comms_isConnected( const CommsCtxt* const comms );
|
XP_Bool comms_isConnected( const CommsCtxt* const comms );
|
||||||
|
XP_Bool comms_setQuashed( CommsCtxt* comms, XP_Bool quashed );
|
||||||
|
|
||||||
#ifdef RELAY_VIA_HTTP
|
#ifdef RELAY_VIA_HTTP
|
||||||
void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid );
|
void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid );
|
||||||
|
|
Loading…
Reference in a new issue