when a move comes in whose hash doesn't match the top of the move

stack, go down the stack looking for a match. If it's found, pop down
to that point then apply the move. This fixes stalls in the test
engine when undo is enabled, and so I assume that undos and turns are
somehow coming in out-of-order. Should be rare that this happens.
This commit is contained in:
Eric House 2015-12-31 06:04:55 -08:00
parent dd242c3ff5
commit 02d5d26c60
3 changed files with 63 additions and 4 deletions

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2000-2011 by Eric House (xwords@eehouse.org). All rights
* Copyright 2000-2015 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -342,6 +342,56 @@ model_hashMatches( const ModelCtxt* model, const XP_U32 hash )
return matches;
}
XP_Bool
model_revertToHash( ModelCtxt* model, const XP_U32 hash, PoolContext* pool )
{
XP_U16 nPopped = 0;
StackCtxt* stack = model->vol.stack;
const XP_U16 nEntries = stack_getNEntries( stack );
StackEntry entries[nEntries];
#ifdef DEBUG
XP_U32 hashes[nEntries];
#endif
XP_S16 foundAt = -1;
for ( XP_U16 ii = 0; ii < nEntries; ++ii ) {
XP_U32 thisHash =
#ifdef DEBUG
hashes[ii] =
#endif
stack_getHash( stack );
if ( hash == thisHash ) {
foundAt = ii;
break;
}
if ( ! stack_popEntry( stack, &entries[ii] ) ) {
break;
}
++nPopped;
}
for ( XP_S16 ii = nPopped - 1; ii >= 0; --ii ) {
stack_redo( stack, &entries[ii] );
/* Assert not needed for long */
XP_ASSERT( hashes[ii] = stack_getHash( stack ) );
}
XP_Bool found = -1 != foundAt;
if ( found ) {
XP_LOGF( "%s: undoing %d turns to match hash %X", __func__,
foundAt, hash );
#ifdef DEBUG
XP_Bool success =
#endif
model_undoLatestMoves( model, pool, foundAt, NULL, NULL );
XP_ASSERT( success );
/* Assert not needed for long */
XP_ASSERT( hash == stack_getHash( model->vol.stack ) );
}
return found;
}
#ifdef STREAM_VERS_BIGBOARD
void
model_setSquareBonuses( ModelCtxt* model, XWBonusType* bonuses, XP_U16 nBonuses )

View file

@ -124,6 +124,9 @@ void model_setSize( ModelCtxt* model, XP_U16 boardSize );
void model_destroy( ModelCtxt* model );
XP_U32 model_getHash( const ModelCtxt* model, XP_U16 version );
XP_Bool model_hashMatches( const ModelCtxt* model, XP_U32 hash );
XP_Bool model_revertToHash( ModelCtxt* model, const XP_U32 hash,
PoolContext* pool );
void model_setNPlayers( ModelCtxt* model, XP_U16 numPlayers );
XP_U16 model_getNPlayers( const ModelCtxt* model );

View file

@ -2086,11 +2086,17 @@ readMoveInfo( ServerCtxt* server, XWStreamCtxt* stream,
#ifdef STREAM_VERS_BIGBOARD
if ( STREAM_VERS_BIGBOARD <= stream_getVersion( stream ) ) {
XP_U32 hashReceived = stream_getU32( stream );
success = model_hashMatches( server->vol.model, hashReceived );
success = model_hashMatches( server->vol.model, hashReceived )
|| model_revertToHash( server->vol.model, hashReceived,
server->pool );
// XP_ASSERT( success ); /* I need to understand when this can fail */
if ( !success ) {
XP_LOGF( "%s: hash mismatch",__func__);
#ifdef DEBUG_HASHING
if ( success ) {
XP_LOGF( "%s: hash match: %X",__func__, hashReceived );
} else {
XP_LOGF( "%s: hash mismatch: %X not found",__func__, hashReceived );
}
#endif
}
#endif
if ( success ) {