diff -r 88ee4cf65e19 -r 1aa8c82cb4cb remotestoragefw/remotefileengine/src/rsfwlockmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotestoragefw/remotefileengine/src/rsfwlockmanager.cpp Wed Sep 01 12:15:08 2010 +0100 @@ -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* kids = aRoot->Kids(); + TInt i; + for (i = 0; i < kids->Count(); i++) + { + PopulateExternalLockTokenCacheL((*kids)[i]); + } + } + } + +// End of File