mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-27 07:58:49 +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.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
|
@ -62,6 +63,7 @@ public class BTService extends Service {
|
|||
, MESSAGE_NOGAME
|
||||
, MESSAGE_RESEND
|
||||
, MESSAGE_FAILOUT
|
||||
, MESSAGE_DROPPED
|
||||
};
|
||||
|
||||
public interface BTEventListener {
|
||||
|
@ -79,6 +81,7 @@ public class BTService extends Service {
|
|||
private static final int SEND = 3;
|
||||
private static final int RADIO = 4;
|
||||
private static final int CLEAR = 5;
|
||||
private static final int REMOVE = 6;
|
||||
|
||||
private static final String CMD_STR = "CMD";
|
||||
private static final String MSG_STR = "MSG";
|
||||
|
@ -110,6 +113,7 @@ public class BTService extends Service {
|
|||
MESG_ACCPT,
|
||||
MESG_DECL,
|
||||
MESG_GAMEGONE,
|
||||
REMOVE_FOR,
|
||||
};
|
||||
|
||||
private class BTQueueElem {
|
||||
|
@ -224,6 +228,13 @@ public class BTService extends Service {
|
|||
targetName, targetAddr, gameID );
|
||||
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 )
|
||||
{
|
||||
|
@ -307,6 +318,12 @@ public class BTService extends Service {
|
|||
stopSelf();
|
||||
}
|
||||
break;
|
||||
case REMOVE:
|
||||
gameID = intent.getIntExtra( GAMEID_STR, -1 );
|
||||
if ( -1 != gameID ) {
|
||||
m_sender.removeFor( gameID );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Assert.fail();
|
||||
}
|
||||
|
@ -578,11 +595,13 @@ public class BTService extends Service {
|
|||
private class BTSenderThread extends Thread {
|
||||
private LinkedBlockingQueue<BTQueueElem> m_queue;
|
||||
private HashMap<String,LinkedList<BTQueueElem> > m_resends;
|
||||
private HashSet<Integer> m_deadGames;
|
||||
|
||||
public BTSenderThread()
|
||||
{
|
||||
m_queue = new LinkedBlockingQueue<BTQueueElem>();
|
||||
m_resends = new HashMap<String,LinkedList<BTQueueElem> >();
|
||||
m_deadGames = new HashSet<Integer>();
|
||||
}
|
||||
|
||||
public void add( BTQueueElem elem )
|
||||
|
@ -590,6 +609,13 @@ public class BTService extends Service {
|
|||
m_queue.add( elem );
|
||||
}
|
||||
|
||||
public void removeFor( int gameID )
|
||||
{
|
||||
synchronized( m_deadGames ) {
|
||||
m_deadGames.add( gameID );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
@ -713,44 +739,58 @@ public class BTService extends Service {
|
|||
|
||||
private boolean sendMsg( BTQueueElem elem )
|
||||
{
|
||||
boolean success = false;
|
||||
BTEvent evt = BTEvent.MESSAGE_REFUSED;
|
||||
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 );
|
||||
boolean success;
|
||||
synchronized( m_deadGames ) {
|
||||
success = m_deadGames.contains( elem.m_gameID );
|
||||
}
|
||||
BTEvent evt;
|
||||
if ( success ) {
|
||||
evt = BTEvent.MESSAGE_DROPPED;
|
||||
DbgUtils.logf( "dropping message because game %X dead",
|
||||
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;
|
||||
outStream.writeShort( len );
|
||||
outStream.write( elem.m_msg, 0, elem.m_msg.length );
|
||||
short len = (short)elem.m_msg.length;
|
||||
outStream.writeShort( len );
|
||||
outStream.write( elem.m_msg, 0, elem.m_msg.length );
|
||||
|
||||
outStream.flush();
|
||||
Thread killer = killSocketIn( socket );
|
||||
outStream.flush();
|
||||
Thread killer = killSocketIn( socket );
|
||||
|
||||
DataInputStream inStream =
|
||||
new DataInputStream( socket.getInputStream() );
|
||||
BTCmd reply = BTCmd.values()[inStream.readByte()];
|
||||
killer.interrupt();
|
||||
success = true;
|
||||
DataInputStream inStream =
|
||||
new DataInputStream( socket.getInputStream() );
|
||||
BTCmd reply = BTCmd.values()[inStream.readByte()];
|
||||
killer.interrupt();
|
||||
success = true;
|
||||
|
||||
switch ( reply ) {
|
||||
case MESG_ACCPT:
|
||||
evt = BTEvent.MESSAGE_ACCEPTED;
|
||||
break;
|
||||
case MESG_GAMEGONE:
|
||||
evt = BTEvent.MESSAGE_NOGAME;
|
||||
break;
|
||||
switch ( reply ) {
|
||||
case MESG_ACCPT:
|
||||
evt = BTEvent.MESSAGE_ACCEPTED;
|
||||
break;
|
||||
case MESG_GAMEGONE:
|
||||
evt = BTEvent.MESSAGE_NOGAME;
|
||||
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 );
|
||||
|
|
|
@ -223,7 +223,7 @@ public class GameUtils {
|
|||
public static void resetGame( Context context, long rowidIn )
|
||||
{
|
||||
GameLock lock = new GameLock( rowidIn, true ).lock();
|
||||
tellRelayDied( context, lock, true );
|
||||
tellDied( context, lock, true );
|
||||
resetGame( context, lock, lock, false );
|
||||
lock.unlock();
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ public class GameUtils {
|
|||
// does this need to be synchronized?
|
||||
GameLock lock = new GameLock( rowid, true );
|
||||
if ( lock.tryLock() ) {
|
||||
tellRelayDied( context, lock, informNow );
|
||||
tellDied( context, lock, informNow );
|
||||
DBUtils.deleteGame( context, lock );
|
||||
lock.unlock();
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ public class GameUtils {
|
|||
CommonPrefs cp = CommonPrefs.get( context );
|
||||
|
||||
if ( forceNew ) {
|
||||
tellRelayDied( context, lock, true );
|
||||
tellDied( context, lock, true );
|
||||
} else {
|
||||
byte[] stream = savedGame( context, lock );
|
||||
// Will fail if there's nothing in the stream but a gi.
|
||||
|
@ -814,15 +814,24 @@ public class GameUtils {
|
|||
return rint;
|
||||
}
|
||||
|
||||
private static void tellRelayDied( Context context, GameLock lock,
|
||||
boolean informNow )
|
||||
private static void tellDied( Context context, GameLock lock,
|
||||
boolean informNow )
|
||||
{
|
||||
GameSummary summary = DBUtils.getSummary( context, lock );
|
||||
if ( null != summary.relayID ) {
|
||||
DBUtils.addDeceased( context, summary.relayID, summary.seed );
|
||||
if ( informNow ) {
|
||||
NetUtils.informOfDeaths( context );
|
||||
}
|
||||
tellRelayDied( context, summary, informNow );
|
||||
}
|
||||
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