diff -r 88ee4cf65e19 -r 1aa8c82cb4cb remotestoragefw/remotefileengine/src/rsfwcreatefilestatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotestoragefw/remotefileengine/src/rsfwcreatefilestatemachine.cpp Wed Sep 01 12:15:08 2010 +0100 @@ -0,0 +1,358 @@ +/* +* Copyright (c) 2005-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: State machine for creating files +* +*/ + + +#include "rsfwcreatefilestatemachine.h" +#include "rsfwfileentry.h" +#include "rsfwfiletable.h" +#include "rsfwinterface.h" +#include "rsfwfileengine.h" +#include "rsfwlockmanager.h" +#include "mdebug.h" +#include "rsfwdirentattr.h" +#include "rsfwvolumetable.h" + + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::CRsfwCreateFileStateMachine +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::CRsfwCreateFileStateMachine() + { + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::~CRsfwCreateFileStateMachine +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::~CRsfwCreateFileStateMachine() + { + delete iDirEntAttr; + delete iLockToken; + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::CompleteRequestL +// ---------------------------------------------------------------------------- +// +CRsfwRfeStateMachine::TState* +CRsfwCreateFileStateMachine::CompleteRequestL(TInt aError) + { + TRfeCreateOutArgs* outArgs = + static_cast(iOutArgs); + if (!aError) + { + // Set the return values for the create call + TFid* kidFidp = &(outArgs->iFid); + TDirEntAttr* oAttrp = &(outArgs->iAttr); + *kidFidp = iKidFep->Fid(); + iKidFep->GetAttributes(*oAttrp); + } + + if (iKidCreated && aError) + { + delete iKidFep; + iKidFep = NULL; + } + + // it may happen by chance that the new name is equal to iLastFailedLookup value + FileEngine()->ResetFailedLookup(); + + CompleteAndDestroyState()->SetErrorCode(aError); + return CompleteAndDestroyState(); + } + +// Check if exists + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCheckIfExistsState::TCheckIfExistsState +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine:: +TCheckIfExistsState::TCheckIfExistsState(CRsfwCreateFileStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL()")); + TRfeCreateInArgs* inArgs = + static_cast(iOperation->iInArgs); + TPtrC kidName(inArgs->iEntry.iName); + iExclp = inArgs->iExcl; + + // used to pass the file open mode + // could be something simpler, e.g. only one int + iOperation->iFlags = inArgs->iEntry.iAttr.iAtt; + + // Get the parent to which we are creating this + if (!iOperation->Node()) + { + User::Leave(KErrNotFound); + } + + + DEBUGSTRING16(("creating file '%S' in fid %d", + &kidName, + iOperation->Node()->Fid().iNodeId)); + + // Do we know about the kid yet? + iOperation->iKidFep = iOperation->Node()->FindKidByName(kidName); + if (!iOperation->iKidFep) + { + // This is either a completely new file, or a file that we + // have not yet created a file entry for. + + if (! iOperation->Volumes()->EnsureMetadataCanBeAddedL(iOperation->Node())) + { + User::Leave(KErrNoMemory); + } + iOperation->iKidFep = CRsfwFileEntry::NewL(kidName, iOperation->Node()); + iOperation->iKidCreated = ETrue; + iOperation->iKidFep->SetNewlyCreated(); + } + + if (iOperation->FileEngine()->Disconnected()) + { + if (iOperation->iKidFep->Type() != KNodeTypeUnknown) + { + // "file exists" + iOperation->HandleRemoteAccessResponse(0, KErrNone); + } + else + { + iOperation->HandleRemoteAccessResponse(0, KErrNotFound); + } + } + else + { + iOperation->FileEngine()->GetAttributesL(*iOperation->iKidFep, + iOperation->iDirEntAttr, + KNodeTypeFile, + iOperation); + } + } + + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL()")); + if (iExclp) + { + DEBUGSTRING(("kid exists!")); + return iOperation->CompleteRequestL(KErrAlreadyExists); + } + else + { // file with the same name exists, but exclusive is false + return new CRsfwCreateFileStateMachine::TCreateNodeState(iOperation); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL(TInt aCode) + { + DEBUGSTRING16(("CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL error=%d", aCode)); + return new CRsfwCreateFileStateMachine::TCreateNodeState(iOperation); + } + +// create node + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCreateNodeState::TCreateNodeState +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine:: +TCreateNodeState::TCreateNodeState(CRsfwCreateFileStateMachine* aParent) + : iOperation(aParent) + { + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCreateNodeState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwCreateFileStateMachine::TCreateNodeState::EnterL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TCreateNodeState::EnterL()")); + if (iOperation->iKidCreated) + { + iOperation->iKidFep->SetType(KNodeTypeFile); + } + + if (!iOperation->FileEngine()->WriteDisconnected()) + { + // Create the file + HBufC16* kidPath = + iOperation->FileEngine()->FullNameLC(*iOperation->iKidFep); + // iDirEntAttr exists, we know we are overwriting + // pass this info to the access module (needed e.g. by UPnP) + iOperation-> + FileEngine()-> + RemoteAccessL()->CreateFileL(*kidPath, + (iOperation->iDirEntAttr != NULL), + iOperation); + CleanupStack::PopAndDestroy(kidPath); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL()")); + return new CRsfwCreateFileStateMachine::TAcquireLockState(iOperation); + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL(TInt aCode) + { + DEBUGSTRING16(("CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL error=%d", aCode)); + DEBUGSTRING(("remote create failed!")); + return iOperation->CompleteRequestL(aCode); + } + +// Acquire lock + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TAcquireLockState::TAcquireLockState +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine:: +TAcquireLockState::TAcquireLockState(CRsfwCreateFileStateMachine* aParent) + { + iOperation = aParent; + iRequestedLock = EFalse; + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TAcquireLockState::EnterL +// ---------------------------------------------------------------------------- +// +void CRsfwCreateFileStateMachine::TAcquireLockState::EnterL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TAcquireLockState::EnterL()")); + if (!iOperation->FileEngine()->WriteDisconnected()) + { + // There are two state machines currently, + // which may take a lock for a file based on the mode, + // OpenByPath and this. + // Currently the mode check is different which is not a good + // thing, there is a clear risk of an error where they + // acquire a lock in different situations. + if (!iOperation->iKidFep->IsLocked() + && iOperation->iFlags != KEntryAttReadOnly) + { + iOperation->FileEngine()->LockManager()-> + ObtainLockL(iOperation->iKidFep, + EFileWrite, + iOperation->iLockToken, + iOperation); + iRequestedLock = ETrue; + } + else + { + iOperation->HandleRemoteAccessResponse(0, KErrNone); + } + } + else + { + iOperation->HandleRemoteAccessResponse(0, KErrNone); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL() + { + DEBUGSTRING(("CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL()")); + if (iRequestedLock) + { + iOperation->iKidFep-> + SetLockedL(iOperation->FileEngine()->LockManager(), + iOperation->iLockToken); + iOperation->iLockToken = NULL; + } + + // Note that the kid has to be attached to the file table + // to get a NodeId before the cache file is created. + if (iOperation->iKidCreated) + { + // Attach a new kid to its parent + iOperation->FileEngine()->iFileTable->AddL(iOperation->iKidFep); + iOperation->Node()->AddKid(*iOperation->iKidFep); + } + + // Create an empty container file locally + iOperation->FileEngine()->CreateContainerFileL(*iOperation->iKidFep); + + iOperation->iKidFep->SetSize(0); + iOperation->iKidFep->SetCachedSize(0); + iOperation->iKidFep->SetCached(ETrue); + iOperation->iKidFep->SetAttribValidationTime(); + + iOperation->FileEngine()->SetupAttributes(*iOperation->iKidFep); + + iOperation->Node()->SetLocallyDirty(); + + return iOperation->CompleteRequestL(KErrNone); + } + +// ---------------------------------------------------------------------------- +// CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL +// ---------------------------------------------------------------------------- +// +CRsfwCreateFileStateMachine::TState* +CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL(TInt aCode) + { + DEBUGSTRING16(("CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL error=%d", aCode)); + if (aCode == KErrNotSupported) + { + iRequestedLock = EFalse; + return this->CompleteL(); + } + else + { + return iOperation->CompleteRequestL(aCode); + } + } + + +