--- /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