ucb/source/ucp/webdav-neon/NeonSession.cxx |   28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

New commits:
commit 84977c3c2541bc5baa72e94aa96391fa8e644272
Author:     Armin Le Grand (Allotropia) <armin.le.gr...@me.com>
AuthorDate: Fri Sep 10 17:58:40 2021 +0200
Commit:     Armin Le Grand (Allotropia) <armin.le.gr...@me.com>
CommitDate: Fri Sep 10 17:58:40 2021 +0200

    Reduce time until LOCK refresh 5% for more secure handling
    
    The LOCK refresh sometimes fails due to currently using
    exactly the timeout returned by the server which describes
    how long the lock will be held/guaranteed by the server.
    This leads to a sometimes too close and unnecessary racing
    condition, in consequence failing the lock refresh and
    creating an error.
    So I added to start that request 5% earlier if the timeout
    is more than 30s which removes the problem. Tested long run
    with over 24h where the original always stopped at some
    point.
    
    Change-Id: Ie941cd02e107846e4bb1003b0cd67e6e50cf9bbe

diff --git a/ucb/source/ucp/webdav-neon/NeonSession.cxx 
b/ucb/source/ucp/webdav-neon/NeonSession.cxx
index c1336c07a9c0..7de19fd30803 100644
--- a/ucb/source/ucp/webdav-neon/NeonSession.cxx
+++ b/ucb/source/ucp/webdav-neon/NeonSession.cxx
@@ -1569,6 +1569,19 @@ void NeonSession::LOCK( const OUString & inPath,
 
     if ( theRetVal == NE_OK )
     {
+        // independent from what input timeout was sent to the server, the
+        // accepted timeout is now returned in theLock->timeout. This is the
+        // base for preparing the LOCK refresh needed after that time. To not
+        // risk to fail due to asking too late, add a 5% security margin and
+        // just request the refresh a little bit earlier, to compensate slight
+        // timing losses/changes/errors in the complete data transfer chain.
+        // Cases where this happens just very tight in the time limit have been
+        // recorded.
+        if(theLock->timeout > 30)
+        {
+            theLock->timeout = 
static_cast<int>(static_cast<double>(theLock->timeout) * 0.95);
+        }
+
         m_aNeonLockStore.addLock( theLock,
                                   this,
                                   lastChanceToSendRefreshRequest(
@@ -1614,10 +1627,16 @@ bool NeonSession::LOCK( NeonLock * pLock,
     const int theRetVal = ne_lock_refresh(m_pHttpSession, pLock);
     if (theRetVal == NE_OK)
     {
+        // see above: Add 5% timeout safety to the new timeout returned from 
the Server
+        if(pLock->timeout > 30)
+        {
+            pLock->timeout = 
static_cast<int>(static_cast<double>(pLock->timeout) * 0.95);
+        }
+
         rlastChanceToSendRefreshRequest
             = lastChanceToSendRefreshRequest( startCall, pLock->timeout );
 
-        SAL_INFO( "ucb.ucp.webdav", "LOCK (refresh) - Lock successfully 
refreshed." );
+        SAL_INFO( "ucb.ucp.webdav", "LOCK (refresh) - Lock successfully 
refreshed (timeout:" << pLock->timeout << " sec.)" );
         return true;
     }
     else
@@ -1631,8 +1650,13 @@ bool NeonSession::LOCK( NeonLock * pLock,
         {
             // tdf#126279: see handling of NE_AUTH in HandleError
             m_bNeedNewSession = true;
-            m_aNeonLockStore.removeLockDeferred(pLock);
         }
+
+        // if NeonSession::LOCK initially worked, m_aNeonLockStore.addLock
+        // was executed. So, remove it here - independent from the type of
+        // error -> or short, in any error case
+        m_aNeonLockStore.removeLockDeferred(pLock);
+
         return false;
     }
 }

Reply via email to