sl@0: /* sl@0: * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Base class functionality for server-side asynchronous requests. sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include "scsserverconstants.h" sl@0: sl@0: EXPORT_C CAsyncRequest::CAsyncRequest(CScsSession* aSession, CScsSubsession* aSubsession, const RMessage2& aMessage) sl@0: /** sl@0: Record the session, subsession, and function associated with this request. sl@0: These are required to complete or to cancel the request later. sl@0: sl@0: Adds this object to the active scheduler. sl@0: sl@0: @param aSession Session used to launch this request. sl@0: @param aSubsession Subsession on which this request is queued. This sl@0: should be NULL if the request is relative to a session, sl@0: instead of a subsession sl@0: @param aMessage Handle to the kernel-side request object, which sl@0: will be completed later. sl@0: */ sl@0: : CActive(CActive::EPriorityStandard), sl@0: iSession(aSession), sl@0: iSubsession(aSubsession), sl@0: iMessagePtr2(aMessage) sl@0: { sl@0: // extract implementation function sl@0: ScsImpl::ExtractScsAndImplFunctions(aMessage, NULL, &iFunction); sl@0: sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: EXPORT_C void CAsyncRequest::TransferToScsFrameworkL() sl@0: /** sl@0: Adds this asynchronous request to the global collection. sl@0: This should be called after the subclass has performed its sl@0: own initialization, but before the active request has been sl@0: set up. sl@0: */ sl@0: { sl@0: iSession->iServer.AddAsyncRequestL(this); sl@0: } sl@0: sl@0: EXPORT_C void CAsyncRequest::RunL() sl@0: /** sl@0: Implement CActive by completing the server client's request status sl@0: with the AO error code, i.e. iStatus. This function also marks this sl@0: object for deletion. sl@0: sl@0: If a subclass overrides this implementation then it must call sl@0: CompleteAndMarkForDeletion itself to complete the client-side sl@0: request. sl@0: sl@0: @see CompleteAndMarkForDeletion sl@0: */ sl@0: { sl@0: TInt r = iStatus.Int(); sl@0: CompleteAndMarkForDeletion(r); sl@0: } sl@0: sl@0: EXPORT_C TInt CAsyncRequest::RunError(TInt aError) sl@0: /** sl@0: Override CActive by completing the request with the sl@0: supplied error code and marking this object for deletion. sl@0: The default implementation of RunL cannot leave, but the sl@0: subclass may override it with a more complex implementation. sl@0: sl@0: @param aError Error code with which aError left. sl@0: @return KErrNone, meaning do not propagate sl@0: the error to the active scheduler. sl@0: */ sl@0: { sl@0: CompleteAndMarkForDeletion(aError); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CAsyncRequest::CancelCompleteAndMarkForDeletion() sl@0: /** sl@0: Cancel this asynchronous request and complete the client sl@0: request with KErrCancel. On exit, this object has been sl@0: marked for deletion. sl@0: */ sl@0: { sl@0: CompleteAndMarkForDeletion(KErrCancel); sl@0: } sl@0: sl@0: EXPORT_C void CAsyncRequest::CompleteAndMarkForDeletion(TInt aError) sl@0: /** sl@0: Completes the client-side request associated with this sl@0: asynchronous request and marks this object for deletion. sl@0: sl@0: If the error was because the client passed a bad descriptor then sl@0: panick the client instead of completing the request for consistency sl@0: with synchronous requests. sl@0: sl@0: @param aError Error code with which the client request sl@0: will be completed. sl@0: */ sl@0: { sl@0: if (aError == KErrBadDescriptor) sl@0: PanicClient(iMessagePtr2, ScsImpl::EScsClBadDesc); sl@0: else sl@0: iMessagePtr2.Complete(aError); sl@0: MarkForDeletion(); sl@0: } sl@0: sl@0: void CAsyncRequest::MarkForDeletion() sl@0: /** sl@0: Mark this outstanding request for deletion, so it is sl@0: cleaned up when the cleanup AO runs. sl@0: */ sl@0: { sl@0: DoCleanup(); sl@0: // The deletion is processed at priority CActive::EPriorityHigh, sl@0: // so should happen ahead of any pending or new requests. sl@0: CAsyncCallBack* acb = iSession->iServer.iAsyncCleanup; sl@0: acb->CallBack(); // no effect if already queued sl@0: iSession = NULL; // mark for deletion sl@0: } sl@0: sl@0: EXPORT_C void CAsyncRequest::DoCleanup() sl@0: /** sl@0: This virtual function is called whenever the SCS needs to cancel an operation. sl@0: sl@0: If the asynchronous request implementation ALWAYS has an internal request active sl@0: for the duration of the client request, then this default implementation can be used, which sl@0: simply calls CActive::Cancel which will call the derived classe's DoCancel (if, and only if sl@0: the object IsActive). sl@0: sl@0: A more complex case is where the asynchronous requests may enter an internal queue where sl@0: the client request is (obviously still active), but the derived class has not outstanding request. sl@0: In this case the default implementation will cause a HANG, because Cancel will not call DoCancel if sl@0: the object is not active... sl@0: sl@0: In the generic case, the derived class should provide an overload for the Cleanup method. sl@0: This function should call Cancel to cancel any outstanding operation, then perform whatever other sl@0: cleanup is required to cleanup the request (closing handles, removing from queues etc). sl@0: The framework will then complete the client request. sl@0: sl@0: nb. The destructor of the CAsyncRequest may not run until sometime after the client request has been sl@0: completed. sl@0: */ sl@0: { sl@0: Cancel(); sl@0: } sl@0: