Re: [os-libsynthesis] resent messages on server

2010-02-26 Thread Patrick Ohly
On Fri, 2010-02-26 at 06:51 +, Patrick Ohly wrote:
 The only implementation of canBufferRetryAnswer() that I find returns
 false, so we end up in the else branch and indeed, in some cases the
 state gets messed up.
 
 I'll keep looking into how I can enable this. Hints welcome.

I've got it working, but only in a hackish way. See
libsynthesis-resend.patch. It depends on the app knowing about
STEPCMD_RESENDDATA *and* buffering the last reply itself. I consider
this a hack a) because canBufferRetryAnswer() can't know whether the app
is capable of resending and b) the buffering should be inside the
engine, using the normal STEPCMD_SENDDATA.

I also tried STEPCMD_SENDDATA, but found that the content of the SML
message buffer was too messed up to get the old reply.

I'm also attaching the SyncEvolution patch necessary to support the hack
above. This is only for future reference, because I am not going to
commit it to our repo.

With these patches I get our tests to pass mostly, but the known issue
with not being able to resend the last reply in a session still breaks
it. This can only be fixed inside libsynthesis and/or SyncEvolution by
keeping sessions alive after the server considers them done, which
complicates the session handling considerably.

I found it easier to add caching of the last reply to our
syncevo-http-server.py script. It does not depend on the SyncML message
number (server cannot parse the message), instead it does a byte
comparison of the incoming message. Obviously that depends on the client
sending exactly the same data, but for SyncEvolution as client that
works. Lukas, do you know whether other clients (like the Nokia phones)
do the same?

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.

diff --git a/src/sysync/syncagent.cpp b/src/sysync/syncagent.cpp
index bc0f4e0..3cd3ccc 100755
--- a/src/sysync/syncagent.cpp
+++ b/src/sysync/syncagent.cpp
@@ -3053,6 +3053,14 @@ TSyError TSyncAgent::ServerProcessingStep(uInt16 aStepCmd, TEngineProgressInfo
 fServerEngineState = ses_generating;
 sta = LOCERR_OK;
   }
+  else if (rc==LOCERR_RETRYMSG) {
+// Resend existing reply. Note that the app must have buffered the
+// reply, because writing into the SML buffer wiped out the
+// old response.
+aStepCmd = STEPCMD_RESENDDATA;
+fServerEngineState = ses_dataready;
+sta = LOCERR_OK;
+  }
   else {
 // processing failed
 PDEBUGPRINTFX(DBG_ERROR,(=== smlProcessData failed, returned 0x%hX,(sInt16)rc));
diff --git a/src/sysync/syncappbase.h b/src/sysync/syncappbase.h
index caa1b6c..c2be374 100755
--- a/src/sysync/syncappbase.h
+++ b/src/sysync/syncappbase.h
@@ -501,7 +501,7 @@ public:
 SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the SyncHdr element
   ) = 0;
   // test if message buffering is available
-  virtual bool canBufferRetryAnswer(void) { return false; }; // must be set in server bases
+  virtual bool canBufferRetryAnswer(void) { return true; }; // must be set in server bases
   // non-virtual handlers, are always called with userData containing valid session pointer
   // - end of message
   Ret_t EndMessage(VoidPtr_t userData, Boolean_t aFinal);
diff --git a/src/syncevo/SyncContext.cpp b/src/syncevo/SyncContext.cpp
index c72bddc..492e975 100644
--- a/src/syncevo/SyncContext.cpp
+++ b/src/syncevo/SyncContext.cpp
@@ -3008,7 +3008,7 @@ SyncMLStatus SyncContext::doSync()
 sysync::STEPCMD_GOTDATA :
 sysync::STEPCMD_CLIENTSTART;
 SharedSession session = m_engine.OpenSession(m_sessionID);
-SharedBuffer sendBuffer;
+SharedBuffer sendBuffer, sendBufferCopy;
 SessionSentinel sessionSentinel(*this, session);
 
 if (m_serverMode) {
@@ -3236,7 +3236,14 @@ SyncMLStatus SyncContext::doSync()
 resendStart = time(NULL);
 /* We are resending previous message, just read from the
  * previous buffer */
-m_agent-send(sendBuffer.get(), sendBuffer.size());
+const char *data = sendBuffer.get();
+size_t size = sendBuffer.size();
+if (!data) {
+// server mode, use fallback copy
+data = sendBufferCopy.get();
+size = sendBufferCopy.size();
+}
+m_agent-send(data, size);
 stepCmd = sysync::STEPCMD_SENTDATA; // we have sent the data
 break;
 }
@@ -3279,6 +3286,14 @@ SyncMLStatus SyncContext::doSync()
 contentType.find(application/vnd.syncml+xml) != contentType.npos) {
 // put answer received earlier into SyncML engine's buffer
 m_retries = 0;
+// sendBuffer points to memory 

[os-libsynthesis] suspend/resume + datastore + tokens

2010-02-26 Thread Patrick Ohly
Hello!

When we started with SyncEvolution, we discussed the StartDataRead()
resumeToken parameter. At that time, we came to the conclusion that a
binfile based client doesn't have to distinguish between different
tokens. Always reporting the changes since the last sync is good enough,
the binfile layer takes care of merging the recent changes with those
that haven't been sent.

Now, on the server side I think tokens are relevant, right?
SyncEvolution as server doesn't support multiple tokens yet, and I was
hoping that one of the existing tests would fail because of that, but no
luck so far. I found two problems (see other emails), but none that I
could attribute to SyncEvolution ;-}

In which situation on the server side is the distinction between
lastToken and resumeToken relevant?

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.



___
os-libsynthesis mailing list
os-libsynthesis@synthesis.ch
http://lists.synthesis.ch/mailman/listinfo/os-libsynthesis