Eric,

I appreciate your detailed analysis.  I spent some time stepping through the 
code and found that in COSynchronizerClient, it was doing the opposite of what 
it seem it should when it receives a message with the same UUID as the last one 
it sent.  After removing the negation, the infinite loop is interrupted.

- (void) handleResponseMessage: 
(COSynchronizerResponseToClientForSentRevisionsMessage *)aMessage
{
//      if (![aMessage.lastRevisionUUIDSentByClient isEqual: [self 
lastRevisionUUIDInTransitToServer]])
  if ([aMessage.lastRevisionUUIDSentByClient isEqual: [self 
lastRevisionUUIDInTransitToServer]])
        {
                return;
        }

It seems possible that the infinite loop may only occur in a single-application 
scenario such as this one, and why it does not happen in the sample app, a 
single context in a thread will either sort itself out or keep spinning, but 
will not get caught up in a sort of race condition where client/server are 
trying to sort themselves out in the same  thread.

I am also concerned with the following code at the end of 
COSynchronizerServer::sendPushToClient

        if (currentlyHandlingLastSentRevision != nil
                && [currentlyRespondingToClient isEqualToString: clientID])
        {
                ETAssert(currentlyRespondingToClient != nil);
                
                COSynchronizerResponseToClientForSentRevisionsMessage * message 
= [[COSynchronizerResponseToClientForSentRevisionsMessage alloc] init];
                message.revisions = revs;
                message.lastRevisionUUIDSentByClient = 
currentlyHandlingLastSentRevision;
                
                [self.delegate sendResponseMessage: message toClient: clientID];
                
                currentlyHandlingLastSentRevision = nil;
                currentlyRespondingToClient = nil;
        }
        else
        {
                COSynchronizerPushedRevisionsToClientMessage *message = 
[[COSynchronizerPushedRevisionsToClientMessage alloc] init];
                message.revisions = revs;
                [self.delegate sendPushedRevisions: message toClients: 
@[clientID]];
        }

In my trace, the message that is created here is one with a single revision 
(the one previously sent by the client), and the lastRevisionUUIDSentByClient 
as being the same as the revision in the message.  It seems like if this state 
were to occur, it should not be sent to the client in the first place where it 
is then handled in the code fixed handleResponseMessage.

I wonder if I am the first to attempt a synchronizer client/server within the 
same thread.  I will clean up and put this code up on GitHub for you to 
examine, and perhaps contribute to the CoreObject samples at some point.

Thanks for your help.
_______________________________________________
Etoile-discuss mailing list
[email protected]
https://mail.gna.org/listinfo/etoile-discuss

Répondre à