diff -r 000000000000 -r c53acadfccc6 metadataengine/server/src/mdsserversession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/metadataengine/server/src/mdsserversession.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,1627 @@ +/* +* Copyright (c) 2009 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: This is Metadata engine server session file +* +*/ + + +// INCLUDE FILES +#include "mdsserversession.h" + +#include "mdcresult.h" +#include "mdslogger.h" +#include "mdcserializationbuffer.h" +#include "mdsserver.h" +#include "mdsmanipulationengine.h" +#include "mdsmaintenanceengine.h" +#include "mdsfindengine.h" +#include "mdsobjectlocklist.h" +#include "mdsnotifier.h" +#include "mdsschema.h" +#include "mdcresult.h" +#include "mdcitem.h" + +#include "mdsutils.h" + +__USES_LOGGER + + +// ========================= MEMBER FUNCTIONS ================================== + + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +CMdSServerSession* CMdSServerSession::NewL( CMdSServer& aServer ) + { + CMdSServerSession* self = CMdSServerSession::NewLC( aServer ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// NewLC +// --------------------------------------------------------------------------- +// +CMdSServerSession* CMdSServerSession::NewLC( CMdSServer& aServer ) + { + CMdSServerSession* self = new ( ELeave ) CMdSServerSession( aServer ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// ConstructL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ConstructL() + { + iServer.IncrementSessions(); + } + +// --------------------------------------------------------------------------- +// Default constructor +// --------------------------------------------------------------------------- +// +CMdSServerSession::CMdSServerSession( CMdSServer& aServer ) + : iServer( aServer ) + { + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CMdSServerSession::~CMdSServerSession() + { + iFindEngines.ResetAndDestroy(); + iFindEngines.Close(); + + iServer.LockList().UnlockBySession( *this ); + iServer.Notifier().RemoveEntriesBySession( *this ); + iServer.DecrementSessions(); + + // purge any pending notifications + iNotificationCache.ResetAndDestroy(); + iNotificationCache.Close(); + } + +// --------------------------------------------------------------------------- +// Service the server message +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ServiceL( const RMessage2& aMessage ) + { + __LOG2( ELogServer, "ServiceL message: %d uid: %.8x", + aMessage.Function(), + aMessage.Identity()); + + if( iServer.BackupOrRestoreRunning() ) + { + aMessage.Complete( KErrServerBusy ); + return; + } + + TRAPD( err, ServiceFunctionL( aMessage ) ); + if( err != KErrNone ) + { + aMessage.Complete( err ); + } + } + +// --------------------------------------------------------------------------- +// ServiceFunctionL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ServiceFunctionL( const RMessage2& aMessage ) + { + TInt complete(KErrNone); + + switch ( aMessage.Function() ) + { + // Add items + case EAdd: + { + AddL( aMessage ); + break; + } + + // Add relation def + case EAddRelationDef: + { + AddRelationDefL(aMessage); + iServer.Notifier().NotifySchemaAddedL(); + break; + } + + // Add event def + case EAddEventDef: + { + AddEventDefL(aMessage); + iServer.Notifier().NotifySchemaAddedL(); + break; + } + + // Remove items + case ERemove: + { + RemoveL( aMessage ); + break; + } + + // Find items + case EFind: + { + TRAPD( err, FindL( aMessage ) ); + if ( err != KErrNone ) + { + if ( err != KErrNotReady ) + { + FindCancel( aMessage, err ); + return; + } + complete = err; + } + break; + } + + case EAsyncFind: + { + TRAPD( err, FindAsyncL( aMessage ) ); + if ( err != KErrNone) + { + if(err != KErrNotReady) + { + FindCancel( aMessage, err ); + return; + } + complete = err; + } + else + { + // if no error don't complete message + return; + } + break; + } + + case EContinueAsyncFind: + { + TRAPD( err, FindContinueAsyncL( aMessage ) ); + if ( err != KErrNone ) + { + FindCancel( aMessage, err ); + } + + // if no error don't complete message + return; + } + + case ECancelFind: + { + FindCancel( aMessage, KErrNone ); + return; + } + + case ECheckObject: + { + CheckObjectL( aMessage ); + break; + } + + case EGetData: + { + GetDataL( aMessage ); + break; + } + + case ECancelObject: + { + CancelObjectL( aMessage ); + break; + } + + case EUpdate: + { + UpdateL( aMessage ); + break; + } + + case ERegister: + { + RegisterL( aMessage ); + break; + } + + case EListen: + { + ListenL( aMessage ); + + // if no error don't complete message + return; + } + + case EUnregister: + { + UnregisterL( aMessage ); + break; + } + + case EShutdown: + { + ShutdownL( aMessage ); + break; + } + + case EImportMetadata: + case EAsyncImportMetadata: + { + ImportMetadataL( aMessage ); + break; + } + + case EExportMetadata: + case EAsyncExportMetadata: + { + ExportMetadataL( aMessage ); + break; + } + + case EImportSchema: + { + TRAPD( err, ImportSchemaL( aMessage ) ); + if(err != KErrNone && err != KErrAccessDenied) + { + // Map all other errors to KErrCorrupt + err = KErrCorrupt; + } + + if(!err) + { + iServer.Notifier().NotifySchemaAddedL(); + } + + complete = err; + break; + } + + case EAddMemoryCard: + { + AddMemoryCardL( aMessage ); + break; + } + + case EGetMemoryCard: + { + GetMemoryCardL( aMessage ); + break; + } + + case ECheckMemoryCard: + { + CheckMemoryCardL( aMessage ); + break; + } + + case ESetMedia: + { + SetMediaL( aMessage ); + break; + } + + case EGetMedia: + { + GetMediaL( aMessage ); + break; + } + + case EGetPresentMedias: + { + GetPresentMediasL( aMessage ); + break; + } + + case ESetFileToPresent: + { + complete = KErrNotSupported; + break; + } + + case ESetFilesToPresent: + { + SetFilesToPresentL(aMessage); + break; + } + + case ESetFilesToNotPresent: + { + SetFilesToNotPresentL(aMessage); + break; + } + + case ERemoveFilesNotPresent: + { + RemoveFilesNotPresentL(aMessage); + break; + } + + case EGetSchemaVersion: + { + GetSchemaVersionL(aMessage); + break; + } + + case ESetObjectToPresentByGuid: + { + SetObjectToPresentByGuidL(aMessage); + break; + } + + case EResetDB: + { + #ifdef _DEBUG + iServer.ResetDBL(); + #else + User::Leave( KErrNotSupported ); + #endif + break; + } + + case ESetHarvestingPrioritizationChunk: + { + iServer.SetHarvestingPrioritizationChunkL( aMessage, 0 ); + break; + } + + case EAddHarvestingPrioritizationObserver: + { + User::LeaveIfError( iServer.AddHarvestingPrioritizationObserver( aMessage ) ); + // if no error don't complete message + return; + } + + case ECancelHarvestingPrioritizationObserver: + { + User::LeaveIfError( iServer.CancelHarvestingPrioritizationObserver() ); + break; + } + + case EChangePath: + { + ChangePathL( aMessage ); + break; + } + + case EChangeMediaId: + { + ChangeMediaIdL( aMessage ); + break; + } + + case ESetPending: + { + SetPendingL( aMessage ); + } + break; + + case EResetPending: + { + ResetPendingL( aMessage ); + } + break; + + case EGetPendingCount: + { + complete = GetPendingCountL( aMessage ); + } + break; + + case EGetPending: + { + complete = GetPendingL( aMessage ); + } + break; + + default: + iServer.PanicClient( aMessage, EBadRequest ); + } + + aMessage.Complete(complete); + } + +// --------------------------------------------------------------------------- +// QueriesCompleteL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::QueriesCompleteL() + { + // check if all queries are complete + for( TInt i = iFindEngines.Count() - 1; i >= 0; i--) + { + CMdSFindEngine* fe = iFindEngines[i]; + + if( !fe->IsComplete() ) + { + User::Leave( KErrNotReady ); + } + } + } + +// --------------------------------------------------------------------------- +// AddL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::AddL( const RMessage2& aMsg ) + { + if ( iServer.DiskFull() ) + { + User::Leave( KErrDiskFull ); + } + + TInt resultLength = aMsg.GetDesLengthL( 1 ); + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( aMsg, 0 ); + CMdCSerializationBuffer* resultBuf = CMdCSerializationBuffer::NewLC( resultLength ); + + iServer.Manipulate().AddL( *buffer, *resultBuf, this ); + + aMsg.WriteL(1, resultBuf->Buffer() ); + CleanupStack::PopAndDestroy( resultBuf ); + CleanupStack::PopAndDestroy( buffer ); + } + +// --------------------------------------------------------------------------- +// AddRelationDefL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::AddRelationDefL(const RMessage2 &aMsg) + { + TDefId namespaceId = aMsg.Int0(); + + TInt nameLength = aMsg.GetDesLength( EAddDefArgDefName ); + if ( nameLength < 0 ) + { + User::Leave( KErrBadDescriptor ); + } + HBufC* namebuf = HBufC::NewLC( nameLength ); + TPtr bufdes = namebuf->Des(); + aMsg.ReadL( EAddDefArgDefName, bufdes ); + + iServer.Manipulate().AddRelationDefL( namespaceId, *namebuf ); + + iServer.Schema().SerializeToSharedMemoryL(); + + CleanupStack::PopAndDestroy( namebuf ); + } + +void CMdSServerSession::AddEventDefL(const RMessage2 &aMsg) + { + TDefId namespaceId = aMsg.Int0(); + + TInt nameLength = aMsg.GetDesLength( EAddDefArgDefName ); + if ( nameLength < 0 ) + { + User::Leave( KErrBadDescriptor ); + } + HBufC* namebuf = HBufC::NewLC( nameLength ); + TPtr bufdes = namebuf->Des(); + aMsg.ReadL( EAddDefArgDefName, bufdes ); + + iServer.Manipulate().AddEventDefL( namespaceId, *namebuf ); + + iServer.Schema().SerializeToSharedMemoryL(); + + CleanupStack::PopAndDestroy( namebuf ); + } + +// RemoveL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::RemoveL( const RMessage2& aMsg ) + { + TInt successfulLength = aMsg.GetDesLengthL( 1 ); + + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( aMsg, 0 ); + CMdCSerializationBuffer* successfullBuffer = CMdCSerializationBuffer::NewLC( successfulLength ); + + iServer.Manipulate().RemoveL( *buffer, *successfullBuffer ); + aMsg.WriteL( 1, successfullBuffer->Buffer() ); + CleanupStack::PopAndDestroy( 2, buffer ); // successfullBuffer, buffer + } + +// --------------------------------------------------------------------------- +// FindL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::FindL( const RMessage2& aMsg ) + { + __LOGLB( ELogServer, "-> Find Sync" ); + + // check that all queries are complete + QueriesCompleteL(); + + TInt serializedCriteriaLength = aMsg.GetDesLength( EFindArgConditions ); + CMdCSerializationBuffer* serializedCriteriaBuffer = CMdCSerializationBuffer::NewLC( serializedCriteriaLength ); + TPtr8 serializedCriteriaBufferPtr(serializedCriteriaBuffer->Buffer()); + aMsg.ReadL( EFindArgConditions, serializedCriteriaBufferPtr ); + + const TUint32 queryId = (TUint32)aMsg.Int0(); + + CMdSFindEngine* find = CMdSFindEngine::NewLC( queryId, *this, + iServer.LockList(), iServer.Schema() ); + find->SetFindCriteria( serializedCriteriaBuffer ); + find->CreateResultSet( aMsg ); + find->SetFindParams( (TUint32)aMsg.Int3() ); + + CleanupStack::Pop( find ); + CleanupStack::Pop( serializedCriteriaBuffer ); + CleanupStack::PushL( find ); + + // check clients user level (whether access to confidential data or not) + TUserLevel userLevel = EUserLevelNone; + userLevel = ( aMsg.HasCapability( ECapabilityReadDeviceData ) ? + EUserLevelDeviceAccess : EUserLevelNormal ); + + find->FindL( userLevel ); + + CleanupStack::Pop( find ); + + iFindEngines.Append( find ); + } + +// --------------------------------------------------------------------------- +// FindAsyncL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::FindAsyncL( const RMessage2& aMsg ) + { + __LOGLB( ELogServer, "-> Find Async" ); + + // check that all queries are complete + QueriesCompleteL(); + + TInt serializedCriteriaLength = aMsg.GetDesLength( EFindArgConditions ); + CMdCSerializationBuffer* serializedCriteriaBuffer = CMdCSerializationBuffer::NewLC( serializedCriteriaLength ); + TPtr8 serializedCriteriaBufferPtr(serializedCriteriaBuffer->Buffer()); + aMsg.ReadL( EFindArgConditions, serializedCriteriaBufferPtr ); + + const TUint32 queryId = (TUint32)aMsg.Int0(); + + CMdSFindEngine* find = CMdSFindEngine::NewLC( queryId, *this, + iServer.LockList(), iServer.Schema() ); + find->SetFindCriteria( serializedCriteriaBuffer ); + find->CreateResultSet( aMsg ); + find->SetFindParams( (TUint32)aMsg.Int3() ); + + CleanupStack::Pop( find ); + CleanupStack::Pop( serializedCriteriaBuffer ); + CleanupStack::PushL( find ); + + // check clients user level (whether access to confidential data or not) + TUserLevel userLevel = EUserLevelNone; + userLevel = ( aMsg.HasCapability( ECapabilityReadDeviceData ) ? + EUserLevelDeviceAccess : EUserLevelNormal ); + + find->FindAsyncL( userLevel ); + + CleanupStack::Pop( find ); + + iFindEngines.Append( find ); + } + +// --------------------------------------------------------------------------- +// FindContinueAsyncL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::FindContinueAsyncL( const RMessage2& aMsg ) + { + __LOGLB( ELogServer, "-> Find Continue" ); + + CMdSFindEngine* findEngine = NULL; + + const TUint32 queryId = (TUint32)aMsg.Int0(); + + const TInt count = iFindEngines.Count(); + + TInt feIndex = 0; + + for( TInt i = 0; i < count; i++ ) + { + if( queryId == iFindEngines[i]->QueryId() ) + { + findEngine = iFindEngines[i]; + + feIndex = i; + break; + } + } + + // no correct find engine found + if( !findEngine ) + { + User::Leave( KErrNotFound ); + } + // find engine is already complete + else if( findEngine->IsComplete() ) + { + delete findEngine; + + iFindEngines.Remove( feIndex ); + + User::Leave( KErrCompletion ); + } + + findEngine->CreateResultSet( aMsg ); + + findEngine->ContinueAsync(); + } + +// --------------------------------------------------------------------------- +// FindCancel +// --------------------------------------------------------------------------- +// +void CMdSServerSession::FindCancel( const RMessage2& aMsg, TInt aError ) + { + __LOGLB( ELogServer, "-> Find Cancel" ); + + const TUint32 queryId = (TUint32)aMsg.Int0(); + + const TInt count = iFindEngines.Count(); + + for( TInt i = 0; i < count; i++ ) + { + CMdSFindEngine* findEngine = iFindEngines[i]; + + if( queryId == findEngine->QueryId() ) + { + findEngine->Cancel( aError ); + + delete findEngine; + + iFindEngines.Remove( i ); + + aMsg.Complete( aError ); + return; + } + } + + // complete message even if correct find engine wasn't found + aMsg.Complete( KErrNotFound ); + } + +// --------------------------------------------------------------------------- +// CheckObjectL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::CheckObjectL( const RMessage2& aMsg ) + { + TPckgBuf namespaceDefIdPckg; + TInt nsDefIdLength = aMsg.GetDesLengthL( ECheckObjectArgNamespaceDefId ); + if( nsDefIdLength != sizeof( TDefId ) ) + { + User::Leave( KErrArgument ); + } + aMsg.Read( ECheckObjectArgNamespaceDefId, namespaceDefIdPckg ); + const TDefId namespaceDefId = namespaceDefIdPckg(); + + const TInt resultBufferLength = aMsg.GetDesLengthL( ECheckObjectArgObject ); + if( resultBufferLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + CMdCSerializationBuffer* buffer = NULL; + + const TInt type = aMsg.Int0(); + switch( type ) + { + case ECheckObjectByUri: + { + TInt uriLength = aMsg.GetDesLengthL( ECheckObjectArgTypeValue ); + if( uriLength <= 0 ) + { + User::Leave( KErrArgument ); + } + RBuf uri; + uri.Create( uriLength ); + CleanupClosePushL( uri ); + aMsg.ReadL( ECheckObjectArgTypeValue, uri ); + buffer = iServer.Manipulate().CheckObjectL( resultBufferLength, uri, namespaceDefId ); + CleanupStack::PopAndDestroy( &uri ); + CleanupStack::PushL( buffer ); + } + break; + + case ECheckObjectById: + { + TPckgBuf idPckg; + TInt idLength = aMsg.GetDesLengthL( ECheckObjectArgTypeValue ); + if( idLength != sizeof( TItemId ) ) + { + User::Leave( KErrArgument ); + } + aMsg.Read( ECheckObjectArgTypeValue, idPckg ); + const TItemId id = idPckg(); + buffer = iServer.Manipulate().CheckObjectL( resultBufferLength, id, namespaceDefId ); + CleanupStack::PushL( buffer ); + } + break; + + case ECheckObjectByIds: + { + TInt idLength = aMsg.GetDesLengthL( ECheckObjectArgTypeValue ); + if( idLength < CMdCSerializationBuffer::KRequiredSizeForTUint32 ) + { + User::Leave( KErrArgument ); + } + + CMdCSerializationBuffer* ids = CMdCSerializationBuffer::NewLC( idLength ); + TPtr8 idsPtr( ids->Buffer() ); + aMsg.ReadL( ECheckObjectArgTypeValue, idsPtr ); + + buffer = iServer.Manipulate().CheckObjectL( resultBufferLength, *ids, namespaceDefId ); + + CleanupStack::PopAndDestroy( ids ); + + CleanupStack::PushL( buffer ); + } + break; + + default: + { + User::Leave( KErrNotSupported ); + } + } + + aMsg.WriteL( ECheckObjectArgObject, buffer->Buffer() ); + CleanupStack::PopAndDestroy( buffer ); + } + +// --------------------------------------------------------------------------- +// GetDataL writes to the client the data from the required operation +// --------------------------------------------------------------------------- +// +void CMdSServerSession::GetDataL( const RMessage2& aMsg ) + { + TMdEServRqst serverRequest = (TMdEServRqst)aMsg.Int2(); + + switch( serverRequest ) + { + case ELoadSchema: + { + __LOGLB( ELogServer, "-> Get data (Schema)" ); + TPckgBuf handleBuf( iServer.Schema().SharedMemoryHandleL() ); + aMsg.WriteL( 1, handleBuf ); + } + break; + case EFind: + case EAsyncFindSetReady: + case EAsyncFindComplete: + { + __LOGLB( ELogServer, "-> Get data (Find)" ); + + const TUint32 queryId = (TUint32)aMsg.Int0(); + + CMdSFindEngine* findEngine = NULL; + + const TInt count = iFindEngines.Count(); + + TInt findEngineIndex; + for( findEngineIndex = 0; findEngineIndex < count; findEngineIndex++ ) + { + if( queryId == iFindEngines[findEngineIndex]->QueryId() ) + { + findEngine = iFindEngines[findEngineIndex]; + break; + } + } + + if( !findEngine ) + { + User::Leave( KErrNotFound ); + } + + TMdCQueryLockType extraData = (TMdCQueryLockType)aMsg.Int3(); + if (extraData == ELock && aMsg.HasCapability( ECapabilityWriteDeviceData ) ) + { + findEngine->LockFindResultObjectsL( iServer.LockList() ); + } + + // write result to client's result buffer + aMsg.WriteL( 1, findEngine->ResultsL().Buffer() ); + + if ( serverRequest != EAsyncFindSetReady ) + { + delete findEngine; + + iFindEngines.Remove( findEngineIndex ); + } + } + break; + case EListen: + { + __LOGLB( ELogServer, "-> Get data (Listen)" ); + CMdSNotifier::TEntry& entry = iServer.Notifier().FindEntryL( aMsg.Int3() ); + CMdCSerializationBuffer* buffer = entry.GetDataBuffer(); + CleanupStack::PushL( buffer ); + aMsg.WriteL( 1, buffer->Buffer() ); + CleanupStack::PopAndDestroy( buffer ); + } + break; + default: + User::Leave( KErrNotSupported ); + } + } + +// --------------------------------------------------------------------------- +// CancelObjectL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::CancelObjectL( const RMessage2& aMsg ) + { + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( aMsg, 0 ); + + const TMdCItemIds& itemIds = TMdCItemIds::GetFromBufferL( *buffer ); + if ( itemIds.iObjectIds.iPtr.iCount != 1 ) + { + User::Leave( KErrArgument ); + } + TItemId idValue; + buffer->PositionL( itemIds.iObjectIds.iPtr.iOffset ); + buffer->ReceiveL( idValue ); + + CMdsSchema& schema = iServer.Schema(); + const CMdsNamespaceDef* namespaceDef = schema.GetNamespaceByIdL( itemIds.iNamespaceDefId ); + + if (iServer.LockList().IsLocked( *namespaceDef, idValue ) ) + { + iServer.LockList().UnlockById( *namespaceDef, idValue ); + } + else + { + idValue = KNoId; + } + + buffer->PositionL( itemIds.iObjectIds.iPtr.iOffset ); + buffer->InsertL( idValue ); + + aMsg.WriteL( 0, buffer->Buffer() ); + CleanupStack::PopAndDestroy( buffer ); // buffer + } + +// --------------------------------------------------------------------------- +// UpdateL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::UpdateL( const RMessage2& aMsg ) + { + TInt successfulLength = aMsg.GetDesLengthL( 1 ); + + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( aMsg, 0 ); + CMdCSerializationBuffer* successfullBuffer = CMdCSerializationBuffer::NewLC( successfulLength ); + + iServer.Manipulate().UpdateL( *buffer, *successfullBuffer ); + aMsg.WriteL( 1, successfullBuffer->Buffer() ); + CleanupStack::PopAndDestroy( 2, buffer ); // successfullBuffer, buffer + } + +// --------------------------------------------------------------------------- +// RegisterL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::RegisterL( const RMessage2& aMsg ) + { + __LOG3( ELogServer, "-> Register %u for NS: %u Type: %d", + (TUint32)aMsg.Int0(), (TDefId)aMsg.Int3(), aMsg.Int1() ); + + TInt length = aMsg.GetDesLength( 2 ); + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( length ); + TPtr8 bufferPtr( buffer->Buffer() ); + aMsg.ReadL( 2, bufferPtr ); + + iServer.Notifier().CreateEntryL( aMsg.Int0(), + (TConditionType)aMsg.Int1(), buffer, (TDefId)aMsg.Int3(), *this, + aMsg.HasCapability(ECapabilityReadDeviceData) ); + + CleanupStack::Pop( buffer ); + } + +// --------------------------------------------------------------------------- +// ListenL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ListenL( const RMessage2& aMsg ) + { + const TInt notifierId = aMsg.Int0(); + __LOG1( ELogServer, "-> Listen %d", notifierId ); + + CMdSNotifier::TEntry& entry = iServer.Notifier().FindEntryL( notifierId ); + entry.SetupForCallback( aMsg, 1 ); + + const TInt count = iNotificationCache.Count(); + for( TInt i = 0; i < count; ++i ) + { + const TInt notificationCacheId = iNotificationCache[i]->iId; + const TInt entryId = entry.Id(); + + if( notificationCacheId == entryId ) + { + // The cache holds a new notification for this notifier, trigger it + CNotificationCacheItem* item = iNotificationCache[i]; + iNotificationCache.Remove(i); + + CleanupStack::PushL( item ); + + entry.TriggerCachedL( item->iCode, item->iData ); + + // take ownership of iData from item and delete it + item->iData = NULL; + CleanupStack::PopAndDestroy( item ); + + return; + } + } + } + +// --------------------------------------------------------------------------- +// UnregisterL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::UnregisterL( const RMessage2& aMsg ) + { + __LOG1( ELogServer, "-> Unregister %d", aMsg.Int0() ); + TInt id = aMsg.Int0(); + iServer.Notifier().RemoveEntryL(id); + TInt count = iNotificationCache.Count(); + for(TInt i(count - 1); i >= 0; --i) + { + if(iNotificationCache[i]->iId == id) + { + delete iNotificationCache[i]->iData; + iNotificationCache[i]->iData = NULL; + iNotificationCache.Remove(i); + } + } + } + +// --------------------------------------------------------------------------- +// CacheNotificationL caches a notifier event +// --------------------------------------------------------------------------- +// + +CMdCSerializationBuffer* CMdSServerSession::CombineBuffersL(CMdCSerializationBuffer& aLeftBuffer, + CMdCSerializationBuffer& aRightBuffer ) + { + // IDs are always stored in object IDs, + // even if those are actually relation or event IDs + + aLeftBuffer.PositionL( KNoOffset ); + aRightBuffer.PositionL( KNoOffset ); + + const TMdCItemIds& leftItemIds = TMdCItemIds::GetFromBufferL( aLeftBuffer ); + const TMdCItemIds& rightItemIds = TMdCItemIds::GetFromBufferL( aRightBuffer ); + + // check that namespaces match + if ( leftItemIds.iNamespaceDefId != rightItemIds.iNamespaceDefId ) + { + return NULL; + } + + // create new buffer, which will contain combined results + const TInt leftBufferSize = aLeftBuffer.Size(); + const TInt rightBufferSize = aRightBuffer.Size(); + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( + leftBufferSize + rightBufferSize ); + + TMdCItemIds combinedItemIds; + + // use left buffer's data as base line + Mem::Copy( &combinedItemIds, &leftItemIds, sizeof( TMdCItemIds ) ); + + // and add right buffer's relation count + combinedItemIds.iObjectIds.iPtr.iCount += rightItemIds.iObjectIds.iPtr.iCount; + + combinedItemIds.SerializeL( *buffer ); + + // move left and right buffer to begin of relations + aLeftBuffer.PositionL( leftItemIds.iObjectIds.iPtr.iOffset ); + aRightBuffer.PositionL( rightItemIds.iObjectIds.iPtr.iOffset ); + + // copy IDs from left and right buffers to combined buffer + for (TInt i = 0; i < leftItemIds.iObjectIds.iPtr.iCount; ++i) + { + TItemId id; + aLeftBuffer.ReceiveL( id ); + buffer->InsertL( id ); + } + + for (TInt i = 0; i < rightItemIds.iObjectIds.iPtr.iCount; ++i) + { + TItemId id; + aRightBuffer.ReceiveL( id ); + buffer->InsertL( id ); + } + + CleanupStack::Pop( buffer ); + return buffer; + } + +CMdCSerializationBuffer* CMdSServerSession::CombineItemBuffersL( CMdCSerializationBuffer& aLeftBuffer, + CMdCSerializationBuffer& aRightBuffer ) + { + // Current implementation supports only combining relations + // (used in remove relation item observer case) + + aLeftBuffer.PositionL( KNoOffset ); + aRightBuffer.PositionL( KNoOffset ); + + const TMdCItems& leftItems = TMdCItems::GetFromBufferL( aLeftBuffer ); + const TMdCItems& rightItems = TMdCItems::GetFromBufferL( aRightBuffer ); + + // check that namespaces match + if ( leftItems.iNamespaceDefId != rightItems.iNamespaceDefId ) + { + return NULL; + } + + // create new buffer, which will contain combined results + const TInt leftBufferSize = aLeftBuffer.Size(); + const TInt rightBufferSize = aRightBuffer.Size(); + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( + leftBufferSize + rightBufferSize ); + + TMdCItems combinedItems; + + // use left buffer's data as base line + Mem::Copy( &combinedItems, &leftItems, sizeof( TMdCItems ) ); + + // and add right buffer's relation count + combinedItems.iRelations.iPtr.iCount += rightItems.iRelations.iPtr.iCount; + + combinedItems.SerializeL( *buffer ); + + // move left and right buffer to begin of relations + aLeftBuffer.PositionL( leftItems.iRelations.iPtr.iOffset ); + aRightBuffer.PositionL( rightItems.iRelations.iPtr.iOffset ); + + // copy relations from left and right buffers to combined buffer + for ( TUint32 i = 0; i < leftItems.iRelations.iPtr.iCount; ++i ) + { + TMdCRelation& leftRelation = CONST_CAST( TMdCRelation&, + TMdCRelation::GetFromBufferL( aLeftBuffer ) ); + + leftRelation.SerializeL( *buffer ); + } + + for ( TUint32 i = 0; i < rightItems.iRelations.iPtr.iCount; ++i ) + { + TMdCRelation& rightRelation = CONST_CAST( TMdCRelation&, + TMdCRelation::GetFromBufferL( aRightBuffer ) ); + + rightRelation.SerializeL( *buffer ); + } + + CleanupStack::Pop( buffer ); + return buffer; + } + + +// --------------------------------------------------------------------------- +// CacheNotificationL caches a notifier event +// --------------------------------------------------------------------------- +// +void CMdSServerSession::CacheNotificationL(TInt aId, TUint32 aCompleteCode, CMdCSerializationBuffer* aData) + { + CleanupStack::PushL( aData ); + + const TInt notificationCount = iNotificationCache.Count(); + + const TInt KMaxCachedItems = 256; + + if(notificationCount > KMaxCachedItems) + { + User::Leave( KErrOverflow ); + } + + if( aData ) + { + // search for matching notification and combine new results to it + for (TInt i = 0; i < notificationCount; ++i) + { + CNotificationCacheItem& notificationItem = *iNotificationCache[i]; + if ( notificationItem.iId == aId && notificationItem.iCode == aCompleteCode ) + { + CMdCSerializationBuffer* data = NULL; + // combine buffers + if ( notificationItem.iCode != ERelationItemNotifyRemove ) + { + data = CombineBuffersL( *notificationItem.iData, *aData ); + } + else + { + data = CombineItemBuffersL( *notificationItem.iData, *aData ); + } + // delete unecessary ones and change iData to new data + if (data) + { + CleanupStack::PopAndDestroy( aData ); + + delete notificationItem.iData; + notificationItem.iData = data; + return; + } + } + } + } + + // change ownership of aData to item + CNotificationCacheItem* item = + new (ELeave) CNotificationCacheItem( aId, aCompleteCode, aData ); + CleanupStack::Pop( aData ); + CleanupStack::PushL( item ); + + iNotificationCache.AppendL( item ); + + CleanupStack::Pop( item ); + } + +CMdSServer& CMdSServerSession::GetServer() const + { + return iServer; + } + +// --------------------------------------------------------------------------- +// ShutdownL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ShutdownL( const RMessage2& /*aMsg*/ ) + { + __LOGLB( ELogServer, "-> Shutdown session" ); + + const TInt count = iFindEngines.Count(); + + for( TInt i = 0; i < count; i++ ) + { + CMdSFindEngine* fe = iFindEngines[i]; + + fe->Cancel( KErrNone ); + } + iFindEngines.ResetAndDestroy(); + iFindEngines.Close(); + } + +// --------------------------------------------------------------------------- +// SizeToRemoteL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::SizeToRemoteL( const RMessage2& aMsg, + TInt aMessageSlot, TInt aSize) + { + __LOGLB( ELogServer, "-> Size to remote" ); + TPckgBuf sizeBuf( aSize ); + aMsg.WriteL( aMessageSlot, sizeBuf ); + } + +// --------------------------------------------------------------------------- +// ImportSchemaL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ImportSchemaL( const RMessage2& aMsg ) + { + __LOGLB( ELogServer, "-> Import schema" ); + + const TInt fileNameLength = aMsg.GetDesLength( 0 ); + if ( fileNameLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + RBuf fileName; + fileName.Create( fileNameLength ); + CleanupClosePushL( fileName ); + aMsg.ReadL( 0, fileName ); + + TVendorId id = aMsg.VendorId(); + iServer.Maintenance().ImportSchemaL( iServer.Schema(), fileName, id.iId ); + CleanupStack::PopAndDestroy( &fileName ); + } + +// --------------------------------------------------------------------------- +// ImportMetadataL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ImportMetadataL( const RMessage2& aMsg ) + { + __LOGLB( ELogServer, "-> Import (async?) metadata" ); + + const TInt fileNameLength = aMsg.GetDesLength( 0 ); + if ( fileNameLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + RBuf fileName; + fileName.Create( fileNameLength ); + CleanupClosePushL( fileName ); + aMsg.ReadL( 0, fileName ); + + // if result is negative then result is error code + // else result is item import fail count + TInt result = iServer.Maintenance().ImportMetadataL( + iServer.Manipulate(), iServer.Schema(), fileName ); + + CleanupStack::PopAndDestroy( &fileName ); + + TPckgBuf failBuf( result ); + aMsg.WriteL( 1, failBuf ); + } + +// --------------------------------------------------------------------------- +// ExportMetadataL +// --------------------------------------------------------------------------- +// +void CMdSServerSession::ExportMetadataL( const RMessage2& aMsg ) + { + const TInt fileNameLength = aMsg.GetDesLength( 0 ); + if ( fileNameLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + RBuf fileName; + fileName.Create( fileNameLength ); + CleanupClosePushL( fileName ); + aMsg.ReadL( 0, fileName ); + + CMdCSerializationBuffer* items = CMdCSerializationBuffer::NewLC( aMsg, 1 ); + + iServer.Maintenance().ExportMetadataL( iServer.Schema(), fileName, *items ); + + CleanupStack::PopAndDestroy( 2, &fileName ); // items, fileName + } + +void CMdSServerSession::AddMemoryCardL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.ReadL( 0, mediaIdPckg ); + + iServer.Manipulate().AddMemoryCardL( mediaId ); + } + +void CMdSServerSession::GetMemoryCardL(const RMessage2& aMessage) + { + TUint32 mediaId; + + iServer.Manipulate().GetMemoryCardL( mediaId ); + + TPckg mediaIdPckg( mediaId ); + aMessage.WriteL( 0, mediaIdPckg ); + } + +void CMdSServerSession::CheckMemoryCardL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.ReadL( 0, mediaIdPckg ); + + TBool result = iServer.Manipulate().CheckMemoryCardL( mediaId ); + + TPckg resultPckg( result ); + aMessage.WriteL( 1, resultPckg ); + } + +void CMdSServerSession::SetMediaL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.ReadL( 0, mediaIdPckg ); + TChar drive; + TPckg drivePckg( drive ); + aMessage.ReadL( 1, drivePckg ); + TBool presentState; + TPckg presentStatePckg( presentState ); + aMessage.ReadL( 2, presentStatePckg ); + + iServer.Manipulate().SetMediaL( mediaId, drive, presentState ); + } + +void CMdSServerSession::GetMediaL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.ReadL( 0, mediaIdPckg ); + + TChar drive; + TBool presentState; + + const TBool exists = iServer.Manipulate().GetMediaL( mediaId, drive, + presentState ); + + if( exists ) + { + TPckg drivePckg( drive ); + aMessage.WriteL( 1, drivePckg ); + TPckg presentStatePckg( presentState ); + aMessage.WriteL( 2, presentStatePckg ); + } + + TPckg existsPckg( exists ); + aMessage.WriteL( 3, existsPckg ); + } + +void CMdSServerSession::GetPresentMediasL(const RMessage2& aMessage) + { + // buffer size for media info for every possible drive + const TInt32 KMediaInfoSize = sizeof( TMdEMediaInfo ) * KMaxDrives; + + RBuf8 mediaInfoBuffer; + mediaInfoBuffer.Create( KMediaInfoSize ); + CleanupClosePushL( mediaInfoBuffer ); + + const TInt32 mediaCount = iServer.Manipulate().GetPresentMediasL( + mediaInfoBuffer ); + + TPckgC mediaCountPckg( mediaCount ); + aMessage.WriteL( 0, mediaCountPckg ); + + if( mediaCount > 0) + { + const TInt32 mediaInfosLength = aMessage.GetDesMaxLength( 1 ); + if ( mediaInfosLength < KMediaInfoSize ) + { + User::Leave( KErrBadDescriptor ); + } + + aMessage.WriteL( 1, mediaInfoBuffer ); + } + + CleanupStack::PopAndDestroy(); //mediaInfoBuffer + } + +void CMdSServerSession::SetFilesToPresentL(const RMessage2& aMessage) + { + TMdSMediaIdAndCount mediaIdAndCount; + TPckg mediaIdAndCountPckg( mediaIdAndCount ); + aMessage.Read( 0, mediaIdAndCountPckg ); + + CMdCSerializationBuffer* uris = CMdCSerializationBuffer::NewLC( aMessage, 1 ); + CMdCSerializationBuffer* fileInfos = CMdCSerializationBuffer::NewLC( aMessage, 2 ); + + TInt resultsSize = aMessage.GetDesMaxLengthL( 3 ); + if( resultsSize < ( mediaIdAndCount.iCount * CMdCSerializationBuffer::KRequiredSizeForTUint8 ) ) + { + User::Leave( KErrBadDescriptor ); + } + CMdCSerializationBuffer* results = CMdCSerializationBuffer::NewLC( resultsSize ); + + iServer.Manipulate().SetFilesToPresentL( + mediaIdAndCount.iMediaId, mediaIdAndCount.iCount, *uris, *fileInfos, + *results ); + + aMessage.WriteL( 3, results->Buffer() ); + + CleanupStack::PopAndDestroy( results ); + CleanupStack::PopAndDestroy( fileInfos ); + CleanupStack::PopAndDestroy( uris ); + } + + +void CMdSServerSession::SetFilesToNotPresentL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.Read( 0, mediaIdPckg ); + + TBool startUp; + TPckg startUpPckg( startUp ); + aMessage.Read( 1, startUpPckg ); + + // only accept correct media IDs, other are silently ignored + if( mediaId != 0 ) + { + iServer.Manipulate().SetFilesToNotPresentL( mediaId, startUp ); + } + } + +void CMdSServerSession::RemoveFilesNotPresentL(const RMessage2& aMessage) + { + TUint32 mediaId; + TPckg mediaIdPckg( mediaId ); + aMessage.Read( 0, mediaIdPckg ); + + TBool startUp; + TPckg startUpPckg( startUp ); + aMessage.Read( 1, startUpPckg ); + + iServer.Manipulate().RemoveFilesNotPresentL( mediaId, startUp ); + } + +void CMdSServerSession::GetSchemaVersionL(const RMessage2& aMessage) + { + TInt majorVersion, minorVersion; + + iServer.Manipulate().GetSchemaVersionL( majorVersion, minorVersion ); + + TPckg pckgMajorVersion( majorVersion ); + TPckg pckgMinorVersion( minorVersion ); + aMessage.WriteL( 0, pckgMajorVersion ); + aMessage.WriteL( 1, pckgMinorVersion ); + } + +void CMdSServerSession::SetObjectToPresentByGuidL(const RMessage2& aMessage) + { + TInt64 guidHigh; + TPckg guidHighPckg( guidHigh ); + aMessage.ReadL( ESetObjectToPresentByGuidArgGuidHigh, guidHighPckg ); + + TInt64 guidLow; + TPckg guidLowPckg( guidLow ); + aMessage.ReadL( ESetObjectToPresentByGuidArgGuidLow, guidLowPckg ); + + iServer.Manipulate().SetObjectToPresentByGuidL( guidHigh, guidLow ); + } + +void CMdSServerSession::ChangePathL(const RMessage2& aMessage) + { + const TInt oldPathLength = aMessage.GetDesLength( 0 ); + if ( oldPathLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + const TInt newPathLength = aMessage.GetDesLength( 1 ); + if ( newPathLength <= 0 ) + { + User::Leave( KErrBadDescriptor ); + } + + RBuf oldPath; + oldPath.Create( oldPathLength ); + CleanupClosePushL( oldPath ); + aMessage.ReadL( 0, oldPath ); + + RBuf newPath; + newPath.Create( newPathLength ); + CleanupClosePushL( newPath ); + aMessage.ReadL( 1, newPath ); + + iServer.Manipulate().ChangePathL( oldPath, newPath ); + + CleanupStack::PopAndDestroy(&newPath); + CleanupStack::PopAndDestroy(&oldPath); + } + +void CMdSServerSession::ChangeMediaIdL( const RMessage2& /*aMessage*/ ) + { + iServer.Manipulate().ChangeMediaIdL(); + } + +void CMdSServerSession::SetPendingL(const RMessage2& aMessage) + { + const TInt serializedObjectIdsLength = aMessage.GetDesLength( 0 ); + + if ( serializedObjectIdsLength < 0 || serializedObjectIdsLength % sizeof( TItemId ) ) + { + User::Leave( KErrBadDescriptor ); + } + + if( serializedObjectIdsLength > 0 ) + { + RArray objectIds; + CleanupClosePushL( objectIds ); + + HBufC8* serializedObjectIds = HBufC8::NewLC( serializedObjectIdsLength ); + + TPtr8 ptr = serializedObjectIds->Des(); + aMessage.ReadL( 0, ptr ); + + DeserializeArrayL( *serializedObjectIds, objectIds ); + + iServer.Manipulate().SetPendingL( objectIds ); + + CleanupStack::PopAndDestroy( serializedObjectIds ); + + CleanupStack::PopAndDestroy( &objectIds ); + } + } + +void CMdSServerSession::ResetPendingL(const RMessage2& aMessage) + { + const TInt serializedObjectIdsLength = aMessage.GetDesLength( 0 ); + + if ( serializedObjectIdsLength < 0 || serializedObjectIdsLength % sizeof( TItemId ) ) + { + User::Leave( KErrBadDescriptor ); + } + + if( serializedObjectIdsLength > 0 ) + { + RArray objectIds; + CleanupClosePushL( objectIds ); + + HBufC8* serializedObjectIds = HBufC8::NewLC( serializedObjectIdsLength ); + + TPtr8 ptr = serializedObjectIds->Des(); + aMessage.ReadL( 0, ptr ); + + DeserializeArrayL( *serializedObjectIds, objectIds ); + + iServer.Manipulate().ResetPendingL( objectIds ); + + CleanupStack::PopAndDestroy( serializedObjectIds ); + + CleanupStack::PopAndDestroy( &objectIds ); + } + } + +TInt CMdSServerSession::GetPendingCountL(const RMessage2& aMessage) + { + TDefId objectDefId; + TPckg objectDefIdPckg( objectDefId ); + aMessage.ReadL( 0, objectDefIdPckg ); + + TInt result = iServer.Manipulate().GetPendingCountL( objectDefId ); + + TPckg objectIdCountPckg( result ); + aMessage.WriteL( 1, objectIdCountPckg ); + + return KErrNone; + } + +TInt CMdSServerSession::GetPendingL(const RMessage2& aMessage) + { + TDefId objectDefId; + TPckg objectDefIdPckg( objectDefId ); + aMessage.ReadL( 0, objectDefIdPckg ); + + const TInt serializedObjectIdsLength = aMessage.GetDesLength( 2 ); + + if ( serializedObjectIdsLength < sizeof(TItemId) || + serializedObjectIdsLength % sizeof(TItemId) ) + { + User::Leave( KErrBadDescriptor ); + } + + RArray objectIds; + CleanupClosePushL( objectIds ); + + TInt bufferSize = serializedObjectIdsLength / sizeof(TItemId); + + TInt result = iServer.Manipulate().GetPendingL( objectDefId, bufferSize, objectIds ); + + const TInt objectIdCount = objectIds.Count(); + + TPckg resultPckg( result ); + aMessage.WriteL( 3, resultPckg ); + + TPckg objectIdCountPckg( objectIdCount ); + aMessage.WriteL( 1, objectIdCountPckg ); + + if( objectIdCount > 0 ) + { + HBufC8* serializedObjectIds = SerializeArrayL( objectIds ); + CleanupStack::PushL( serializedObjectIds ); + + aMessage.WriteL( 2, serializedObjectIds->Des() ); + + CleanupStack::PopAndDestroy( serializedObjectIds ); + } + + CleanupStack::PopAndDestroy( &objectIds ); + + return KErrNone; + } +