mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-29 08:34:37 +01:00
prevent continuing attempts to send messages from client after it's
deleted the game those messages are part of. I'm keeping a list of dead games and checking against that, and currently that list will grow for as long as the sender thread lives. Shouldn't be a problem but needs fixing. Better would be to remove all messages from queues, but that has synchronization issues.
This commit is contained in:
parent
456dcca7b8
commit
f1956ddcb4
2 changed files with 89 additions and 40 deletions
|
@ -35,6 +35,7 @@ import java.io.DataOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
@ -62,6 +63,7 @@ public class BTService extends Service {
|
||||||
, MESSAGE_NOGAME
|
, MESSAGE_NOGAME
|
||||||
, MESSAGE_RESEND
|
, MESSAGE_RESEND
|
||||||
, MESSAGE_FAILOUT
|
, MESSAGE_FAILOUT
|
||||||
|
, MESSAGE_DROPPED
|
||||||
};
|
};
|
||||||
|
|
||||||
public interface BTEventListener {
|
public interface BTEventListener {
|
||||||
|
@ -79,6 +81,7 @@ public class BTService extends Service {
|
||||||
private static final int SEND = 3;
|
private static final int SEND = 3;
|
||||||
private static final int RADIO = 4;
|
private static final int RADIO = 4;
|
||||||
private static final int CLEAR = 5;
|
private static final int CLEAR = 5;
|
||||||
|
private static final int REMOVE = 6;
|
||||||
|
|
||||||
private static final String CMD_STR = "CMD";
|
private static final String CMD_STR = "CMD";
|
||||||
private static final String MSG_STR = "MSG";
|
private static final String MSG_STR = "MSG";
|
||||||
|
@ -110,6 +113,7 @@ public class BTService extends Service {
|
||||||
MESG_ACCPT,
|
MESG_ACCPT,
|
||||||
MESG_DECL,
|
MESG_DECL,
|
||||||
MESG_GAMEGONE,
|
MESG_GAMEGONE,
|
||||||
|
REMOVE_FOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
private class BTQueueElem {
|
private class BTQueueElem {
|
||||||
|
@ -224,6 +228,13 @@ public class BTService extends Service {
|
||||||
targetName, targetAddr, gameID );
|
targetName, targetAddr, gameID );
|
||||||
return buf.length;
|
return buf.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void gameDied( Context context, int gameID )
|
||||||
|
{
|
||||||
|
Intent intent = getIntentTo( context, REMOVE );
|
||||||
|
intent.putExtra( GAMEID_STR, gameID );
|
||||||
|
context.startService( intent );
|
||||||
|
}
|
||||||
|
|
||||||
private static Intent getIntentTo( Context context, int cmd )
|
private static Intent getIntentTo( Context context, int cmd )
|
||||||
{
|
{
|
||||||
|
@ -307,6 +318,12 @@ public class BTService extends Service {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case REMOVE:
|
||||||
|
gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
||||||
|
if ( -1 != gameID ) {
|
||||||
|
m_sender.removeFor( gameID );
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
}
|
}
|
||||||
|
@ -578,11 +595,13 @@ public class BTService extends Service {
|
||||||
private class BTSenderThread extends Thread {
|
private class BTSenderThread extends Thread {
|
||||||
private LinkedBlockingQueue<BTQueueElem> m_queue;
|
private LinkedBlockingQueue<BTQueueElem> m_queue;
|
||||||
private HashMap<String,LinkedList<BTQueueElem> > m_resends;
|
private HashMap<String,LinkedList<BTQueueElem> > m_resends;
|
||||||
|
private HashSet<Integer> m_deadGames;
|
||||||
|
|
||||||
public BTSenderThread()
|
public BTSenderThread()
|
||||||
{
|
{
|
||||||
m_queue = new LinkedBlockingQueue<BTQueueElem>();
|
m_queue = new LinkedBlockingQueue<BTQueueElem>();
|
||||||
m_resends = new HashMap<String,LinkedList<BTQueueElem> >();
|
m_resends = new HashMap<String,LinkedList<BTQueueElem> >();
|
||||||
|
m_deadGames = new HashSet<Integer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add( BTQueueElem elem )
|
public void add( BTQueueElem elem )
|
||||||
|
@ -590,6 +609,13 @@ public class BTService extends Service {
|
||||||
m_queue.add( elem );
|
m_queue.add( elem );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeFor( int gameID )
|
||||||
|
{
|
||||||
|
synchronized( m_deadGames ) {
|
||||||
|
m_deadGames.add( gameID );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
|
@ -713,44 +739,58 @@ public class BTService extends Service {
|
||||||
|
|
||||||
private boolean sendMsg( BTQueueElem elem )
|
private boolean sendMsg( BTQueueElem elem )
|
||||||
{
|
{
|
||||||
boolean success = false;
|
boolean success;
|
||||||
BTEvent evt = BTEvent.MESSAGE_REFUSED;
|
synchronized( m_deadGames ) {
|
||||||
try {
|
success = m_deadGames.contains( elem.m_gameID );
|
||||||
BluetoothDevice dev = m_adapter.getRemoteDevice( elem.m_addr );
|
}
|
||||||
BluetoothSocket socket =
|
BTEvent evt;
|
||||||
dev.createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
if ( success ) {
|
||||||
if ( null != socket ) {
|
evt = BTEvent.MESSAGE_DROPPED;
|
||||||
DataOutputStream outStream = connect( socket, BTCmd.MESG_SEND );
|
DbgUtils.logf( "dropping message because game %X dead",
|
||||||
if ( null != outStream ) {
|
elem.m_gameID );
|
||||||
outStream.writeInt( elem.m_gameID );
|
} else {
|
||||||
|
evt = BTEvent.MESSAGE_REFUSED;
|
||||||
|
}
|
||||||
|
if ( !success ) {
|
||||||
|
try {
|
||||||
|
BluetoothDevice dev =
|
||||||
|
m_adapter.getRemoteDevice( elem.m_addr );
|
||||||
|
BluetoothSocket socket = dev.
|
||||||
|
createRfcommSocketToServiceRecord( XWApp.getAppUUID() );
|
||||||
|
if ( null != socket ) {
|
||||||
|
DataOutputStream outStream =
|
||||||
|
connect( socket, BTCmd.MESG_SEND );
|
||||||
|
if ( null != outStream ) {
|
||||||
|
outStream.writeInt( elem.m_gameID );
|
||||||
|
|
||||||
short len = (short)elem.m_msg.length;
|
short len = (short)elem.m_msg.length;
|
||||||
outStream.writeShort( len );
|
outStream.writeShort( len );
|
||||||
outStream.write( elem.m_msg, 0, elem.m_msg.length );
|
outStream.write( elem.m_msg, 0, elem.m_msg.length );
|
||||||
|
|
||||||
outStream.flush();
|
outStream.flush();
|
||||||
Thread killer = killSocketIn( socket );
|
Thread killer = killSocketIn( socket );
|
||||||
|
|
||||||
DataInputStream inStream =
|
DataInputStream inStream =
|
||||||
new DataInputStream( socket.getInputStream() );
|
new DataInputStream( socket.getInputStream() );
|
||||||
BTCmd reply = BTCmd.values()[inStream.readByte()];
|
BTCmd reply = BTCmd.values()[inStream.readByte()];
|
||||||
killer.interrupt();
|
killer.interrupt();
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
switch ( reply ) {
|
switch ( reply ) {
|
||||||
case MESG_ACCPT:
|
case MESG_ACCPT:
|
||||||
evt = BTEvent.MESSAGE_ACCEPTED;
|
evt = BTEvent.MESSAGE_ACCEPTED;
|
||||||
break;
|
break;
|
||||||
case MESG_GAMEGONE:
|
case MESG_GAMEGONE:
|
||||||
evt = BTEvent.MESSAGE_NOGAME;
|
evt = BTEvent.MESSAGE_NOGAME;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
socket.close();
|
||||||
}
|
}
|
||||||
socket.close();
|
} catch ( java.io.IOException ioe ) {
|
||||||
|
DbgUtils.logf( "sendMsg: ioe: %s", ioe.toString() );
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
} catch ( java.io.IOException ioe ) {
|
|
||||||
DbgUtils.logf( "sendMsg: ioe: %s", ioe.toString() );
|
|
||||||
success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResult( evt, elem.m_gameID, 0, elem.m_recipient );
|
sendResult( evt, elem.m_gameID, 0, elem.m_recipient );
|
||||||
|
|
|
@ -223,7 +223,7 @@ public class GameUtils {
|
||||||
public static void resetGame( Context context, long rowidIn )
|
public static void resetGame( Context context, long rowidIn )
|
||||||
{
|
{
|
||||||
GameLock lock = new GameLock( rowidIn, true ).lock();
|
GameLock lock = new GameLock( rowidIn, true ).lock();
|
||||||
tellRelayDied( context, lock, true );
|
tellDied( context, lock, true );
|
||||||
resetGame( context, lock, lock, false );
|
resetGame( context, lock, lock, false );
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ public class GameUtils {
|
||||||
// does this need to be synchronized?
|
// does this need to be synchronized?
|
||||||
GameLock lock = new GameLock( rowid, true );
|
GameLock lock = new GameLock( rowid, true );
|
||||||
if ( lock.tryLock() ) {
|
if ( lock.tryLock() ) {
|
||||||
tellRelayDied( context, lock, informNow );
|
tellDied( context, lock, informNow );
|
||||||
DBUtils.deleteGame( context, lock );
|
DBUtils.deleteGame( context, lock );
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -757,7 +757,7 @@ public class GameUtils {
|
||||||
CommonPrefs cp = CommonPrefs.get( context );
|
CommonPrefs cp = CommonPrefs.get( context );
|
||||||
|
|
||||||
if ( forceNew ) {
|
if ( forceNew ) {
|
||||||
tellRelayDied( context, lock, true );
|
tellDied( context, lock, true );
|
||||||
} else {
|
} else {
|
||||||
byte[] stream = savedGame( context, lock );
|
byte[] stream = savedGame( context, lock );
|
||||||
// Will fail if there's nothing in the stream but a gi.
|
// Will fail if there's nothing in the stream but a gi.
|
||||||
|
@ -814,15 +814,24 @@ public class GameUtils {
|
||||||
return rint;
|
return rint;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void tellRelayDied( Context context, GameLock lock,
|
private static void tellDied( Context context, GameLock lock,
|
||||||
boolean informNow )
|
boolean informNow )
|
||||||
{
|
{
|
||||||
GameSummary summary = DBUtils.getSummary( context, lock );
|
GameSummary summary = DBUtils.getSummary( context, lock );
|
||||||
if ( null != summary.relayID ) {
|
if ( null != summary.relayID ) {
|
||||||
DBUtils.addDeceased( context, summary.relayID, summary.seed );
|
tellRelayDied( context, summary, informNow );
|
||||||
if ( informNow ) {
|
}
|
||||||
NetUtils.informOfDeaths( context );
|
if ( 0 != summary.gameID ) {
|
||||||
}
|
BTService.gameDied( context, summary.gameID );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void tellRelayDied( Context context, GameSummary summary,
|
||||||
|
boolean informNow )
|
||||||
|
{
|
||||||
|
DBUtils.addDeceased( context, summary.relayID, summary.seed );
|
||||||
|
if ( informNow ) {
|
||||||
|
NetUtils.informOfDeaths( context );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue