mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-28 09:58:30 +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 );
|
||||
}
|
||||
|
||||
// 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,
|
||||
boolean informNow )
|
||||
{
|
||||
|
|
|
@ -562,11 +562,34 @@ public class MQTTUtils extends Thread
|
|||
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,
|
||||
int gameID )
|
||||
{
|
||||
TopicsAndPackets tap = XwJNI.dvc_makeMQTTNoSuchGames( addressee, gameID );
|
||||
addToSendQueue( context, tap );
|
||||
|
||||
postNoSuchGame( context, gameID );
|
||||
}
|
||||
|
||||
public static int send( Context context, TopicsAndPackets tap )
|
||||
|
@ -775,6 +798,7 @@ public class MQTTUtils extends Thread
|
|||
new MQTTServiceHelper( context, from )
|
||||
.postEvent( MultiService.MultiEvent.MESSAGE_NOGAME, gameID,
|
||||
expl );
|
||||
postNoSuchGame( context, gameID );
|
||||
}
|
||||
|
||||
public static void fcmConfirmed( Context context, boolean working )
|
||||
|
|
|
@ -348,6 +348,8 @@ public class DUtilCtxt {
|
|||
|
||||
public void onGameGoneReceived( int gameID, CommsAddrRec from )
|
||||
{
|
||||
GameUtils.onGameGone( m_context, gameID );
|
||||
|
||||
Assert.assertTrueNR( from.contains( CommsAddrRec.CommsConnType.COMMS_CONN_MQTT ) );
|
||||
MQTTUtils.handleGameGone( m_context, from, gameID );
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ public class XwJNI {
|
|||
public static TopicsAndPackets dvc_makeMQTTNoSuchGames( String addressee, int 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 );
|
||||
}
|
||||
|
||||
|
@ -549,6 +549,7 @@ public class XwJNI {
|
|||
public static native CommsAddrRec comms_getHostAddr( GamePtr gamePtr );
|
||||
public static native CommsAddrRec[] comms_getAddrs( GamePtr gamePtr );
|
||||
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,
|
||||
CommsConnType filter,
|
||||
boolean andAck );
|
||||
|
|
|
@ -2664,6 +2664,20 @@ Java_org_eehouse_android_xw4_jni_XwJNI_comms_1dropHostAddr
|
|||
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
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_eehouse_android_xw4_jni_XwJNI_comms_1setAddrDisabled
|
||||
|
|
|
@ -238,6 +238,8 @@ struct CommsCtxt {
|
|||
};
|
||||
|
||||
#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
|
||||
typedef enum {
|
||||
|
@ -2082,7 +2084,9 @@ sendMsg( const CommsCtxt* comms, XWEnv xwe, MsgQueueElem* elem,
|
|||
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_ASSERT(0); /* firing */
|
||||
} else {
|
||||
|
@ -2235,7 +2239,9 @@ comms_resendAll( CommsCtxt* comms, XWEnv xwe, CommsConnType filter, XP_Bool forc
|
|||
XP_ASSERT( !!comms );
|
||||
|
||||
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",
|
||||
comms->nextResend - now );
|
||||
} else {
|
||||
|
@ -3256,6 +3262,23 @@ comms_isConnected( const CommsCtxt* const comms )
|
|||
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
|
||||
void
|
||||
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_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->queueLen );
|
||||
comms->queueLen, boolToStr(QUASHED(comms)) );
|
||||
stream_catString( stream, buf );
|
||||
|
||||
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_isConnected( const CommsCtxt* const comms );
|
||||
XP_Bool comms_setQuashed( CommsCtxt* comms, XP_Bool quashed );
|
||||
|
||||
#ifdef RELAY_VIA_HTTP
|
||||
void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid );
|
||||
|
|
Loading…
Reference in a new issue