remotestoragefw/remotefileengine/src/rsfwlockmanager.cpp
changeset 0 3ad9d5175a89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/remotestoragefw/remotefileengine/src/rsfwlockmanager.cpp	Thu Dec 17 09:07:59 2009 +0200
@@ -0,0 +1,318 @@
+/*
+* Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Lock manager for locked remote files
+*
+*/
+
+
+#include "rsfwfileentry.h"
+#include "rsfwrfestatemachine.h"
+#include "rsfwlockmanager.h"
+#include "rsfwfileentry.h"
+#include "rsfwconfig.h"
+#include "mdebug.h"
+
+// ----------------------------------------------------------------------------
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::NewL
+// ----------------------------------------------------------------------------
+//
+CRsfwLockManager* CRsfwLockManager::NewL(CRsfwRemoteAccess* aRemoteAccess)
+    {
+    CRsfwLockManager* self = CRsfwLockManager::NewLC(aRemoteAccess);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::NewLC
+// ----------------------------------------------------------------------------
+//
+CRsfwLockManager* CRsfwLockManager::NewLC(CRsfwRemoteAccess* aRemoteAccess)
+    {
+    DEBUGSTRING(("CRsfwLockManager::NewLC"));
+    CRsfwLockManager* self = new (ELeave) CRsfwLockManager();
+    CleanupStack::PushL(self);
+    self->ConstructL(aRemoteAccess);
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::ConstructL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::ConstructL(CRsfwRemoteAccess* aRemoteAccess)
+    {
+    iRemoteAccess = aRemoteAccess;
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::~CRsfwLockManager
+// ----------------------------------------------------------------------------
+//
+CRsfwLockManager::~CRsfwLockManager()
+    {
+    iLockRefreshContexts.Close();
+
+    // set unlock flag for all the entries locked
+    while (iLockedEntries.Count() > 0)
+        {
+        CRsfwFileEntry* entry = iLockedEntries[0];
+        iLockedEntries.Remove(0);
+        // note that RemoveLocked will call CRsfwLockManager::RemoveLockedEntry
+        entry->RemoveLocked();
+        }
+    iLockedEntries.Close();    
+    }
+
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::HandleRemoteAccessResponse
+// For handling the response from RefreshLockL().
+// If the lock refresh is successful we restart the timer
+// as the server may have changed the timeout.
+// If the refresh request returns an error we remove the lock
+// We assume that server does not hold the lock anymore,
+// so we cannot re-acquire it simply by trying to refresh it again.
+// Instead, we should do a fresh lock operation
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::HandleRemoteAccessResponse(TUint aId,
+                                              TInt aStatus)
+    {
+    DEBUGSTRING(("CRsfwLockManager::HandleRemoteAccessResponse id: %d, status: %d", aId, aStatus));
+    TPendingLockRefreshContext lockRefresh;
+    lockRefresh.iId = aId;
+    TInt index = iLockRefreshContexts.Find(lockRefresh);
+    if (index != KErrNotFound) 
+        {
+        lockRefresh = iLockRefreshContexts[index];
+        if (aStatus == KErrNone) 
+            {
+            // Note that this can leave only when creating the timer
+            // so it shouldn't really leave anymore at this point.
+            // Also resetting the timer and calling Start() do not even
+            // return an error, so there is no need to examine err or ret value
+            TRAP_IGNORE(lockRefresh.iFileEntry->SetLockedL(this, NULL));
+            }
+        else 
+            {
+            lockRefresh.iFileEntry->RemoveLocked();
+            }
+        iLockRefreshContexts.Remove(index);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::ObtainLockL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::ObtainLockL(CRsfwFileEntry *aFileEntry,
+                               TUint aLockFlags,
+                               TDesC8*& aLockToken,
+                               CRsfwRfeStateMachine* aOperation)
+    {
+    DEBUGSTRING(("CRsfwLockManager::ObtainLockL"));
+    if (aFileEntry->iLockTimeout == 0)
+        {
+        // No locking wanted,
+        // we use notsupported as a return code in this case too....
+        DEBUGSTRING(("lock timeout in CFileEntry is 0, no locking"));
+        aOperation->HandleRemoteAccessResponse(0, KErrNotSupported); 
+        }
+    else 
+        {
+        HBufC* fullName = aFileEntry->FullNameLC();
+         if (!iRemoteAccess) 
+            {
+            DEBUGSTRING(("iRemoteAccess NULL"));
+            User::Leave(KErrNotReady);
+            }
+        else 
+            {
+            DEBUGSTRING(("calling iRemoteAccess::ObtainLockL()"));
+            iRemoteAccess->ObtainLockL(*fullName,
+                                   aLockFlags,
+                                   aFileEntry->iLockTimeout,
+                                   aLockToken,
+                                   aOperation);
+            }
+
+        CleanupStack::PopAndDestroy(fullName); // fullname  
+        }
+    
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::ReleaseLockL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::ReleaseLockL(CRsfwFileEntry* aFileEntry,
+                                CRsfwRfeStateMachine* aOperation)
+    {
+    DEBUGSTRING(("CRsfwLockManager::ReleaseLockL"));
+    if (aFileEntry->iLockTimeout == 0)
+        {
+        // No locking
+        User::Leave(KErrNotFound);
+        }
+    
+
+    if (!iRemoteAccess) 
+        {
+        User::Leave(KErrNotReady);
+        }
+    else 
+        {
+        HBufC* fullName = aFileEntry->FullNameLC();
+#ifdef _DEBUG
+        TInt err;
+        err = iRemoteAccess->ReleaseLockL(*fullName, aOperation);
+        TPtrC p = fullName->Des();
+        DEBUGSTRING16(("ReleaseLockL(): returned %d for file '%S'", err, &p));     
+
+
+
+#else        
+        iRemoteAccess->ReleaseLockL(*fullName, aOperation);
+#endif
+        CleanupStack::PopAndDestroy(fullName); // fullname
+        }
+    
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::RefreshLockL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::RefreshLockL(CRsfwFileEntry* aFileEntry)
+    {
+   DEBUGSTRING(("CRsfwLockManager::RefreshLockL"));
+    TInt id = 0;
+    if (aFileEntry->iLockTimeout > 0) // timeout = 0 indicates no locking
+        {
+        aFileEntry->iLockTimer->Cancel(); // cancel the old timer
+        HBufC* fullName = aFileEntry->FullNameLC();
+        TRAPD(err, id = iRemoteAccess->RefreshLockL(*fullName,
+                                                    aFileEntry->iLockTimeout,
+                                                    this)); 
+        if (err == KErrNone) 
+            {
+            TPendingLockRefreshContext lockRefresh;
+            lockRefresh.iId = id;
+            lockRefresh.iFileEntry = aFileEntry;
+            iLockRefreshContexts.AppendL(lockRefresh);
+            } 
+        else 
+            {
+            // This error would come from the lower layers of the communication
+            // stack, not from the server.
+            // We use the timer mechanism to try again
+            // but set the timeout to smaller.
+            // Note that we don't touch aFileEntry->iLockTimer, 
+            // which will be used to set the timeout requested from the server
+            TInt lockTimeout =
+                Min((aFileEntry->iLockTimeout / KLockRefreshAdjustment) / 2,
+                    KMinLockRefreshAttempt);
+            TCallBack callBack(CRsfwFileEntry::LockTimerExpiredL, this);
+            aFileEntry->iLockTimer->Start(1000000 * lockTimeout,
+                                          1000000 * lockTimeout,
+                                          callBack);
+            }
+        CleanupStack::PopAndDestroy(fullName); // fullname
+        }
+    }
+  
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::LockedCount
+// ----------------------------------------------------------------------------
+//  
+TInt CRsfwLockManager::LockedCount()
+    {
+    return iLockedEntries.Count();
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::AddLockedEntryL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::AddLockedEntryL(CRsfwFileEntry* aEntry)
+    {
+    // prevent from adding the same item twice
+    if (iLockedEntries.Find(aEntry) != KErrNotFound)
+        {
+        return;
+        }
+    
+    iLockedEntries.AppendL(aEntry);
+    DEBUGSTRING(("Update locked count %d -> %d",
+                 iLockedEntries.Count() - 1,
+                 iLockedEntries.Count()));
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::RemoveLockedEntry
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::RemoveLockedEntry(CRsfwFileEntry* aEntry)
+    {
+    TInt index = iLockedEntries.Find(aEntry);
+    if (index != KErrNotFound)
+        {
+        iLockedEntries.Remove(index);        
+        DEBUGSTRING(("Update locked count %d -> %d",
+                 iLockedEntries.Count() + 1,
+                 iLockedEntries.Count()));
+
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CRsfwLockManager::PopulateExternalLockTokenCacheL
+// ----------------------------------------------------------------------------
+//
+void CRsfwLockManager::PopulateExternalLockTokenCacheL(CRsfwFileEntry* aRoot)
+    {
+    if (aRoot)
+        {
+        const TDesC8* lockToken = aRoot->LockToken();
+        if (lockToken)
+            {
+            HBufC* path = aRoot->FullNameLC();
+            TPtr pathPtr = path->Des();
+            if (aRoot->Type() == KNodeTypeDir)
+                {
+                // the MaxLength() of path is KMaxPath, so we can append
+            if (pathPtr.Length() && (pathPtr[pathPtr.Length() - 1] != '/'))
+                {
+                pathPtr.Append('/');
+                }
+                }
+            iRemoteAccess->SetLockToken(pathPtr, *lockToken);
+            CleanupStack::PopAndDestroy(path);
+            }
+        
+        RPointerArray<CRsfwFileEntry>* kids = aRoot->Kids();
+        TInt i;
+        for (i = 0; i < kids->Count(); i++)
+            {
+            PopulateExternalLockTokenCacheL((*kids)[i]);
+            }
+        }
+    }
+
+//  End of File