diff -r c16e04725da3 -r 5c4486441ae6 keepalive/flextimer/client/src/rflextimer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keepalive/flextimer/client/src/rflextimer.cpp Mon May 24 20:51:35 2010 +0300 @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2010 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: Implementation of RFlexTimer class + * + */ + +/* + * %version: 1 % + */ +#include "rflextimer.h" +#include "flextimercommon.h" +#include "OstTraceDefinitions.h" +#ifdef OST_TRACE_COMPILER_IN_USE +#include "rflextimerTraces.h" +#endif + + +_LIT( KFlexTimerSemaphoreName, "FlexTimerSemaphore" ); + +// Semaphore count value initialization to 1. The 1st to call Wait() will +// pass the semaphore. Other processes attempting entry will wait until the +// 1st one has called Signal() on the semaphore. +const TInt KPassFirstWaitEntry = 1; + +// ======== MEMBER FUNCTIONS ======== +// --------------------------------------------------------------------------- +// Constructs the object. +// --------------------------------------------------------------------------- +// +EXPORT_C RFlexTimer::RFlexTimer() + { + OstTrace1( TRACE_NORMAL, RFLEXTIMER_RFLEXTIMER, + "RFlexTimer::RFlexTimer;this=%x", this ); + + } + +// --------------------------------------------------------------------------- +// Destructs the object. +// --------------------------------------------------------------------------- +// +EXPORT_C RFlexTimer::~RFlexTimer() + { + OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_RFLEXTIMER, + "RFlexTimer::~RFlexTimer;this=%x", ( TUint )this ); + + Close(); + } + +// --------------------------------------------------------------------------- +// Connects to the server and create a session. +// --------------------------------------------------------------------------- +// +EXPORT_C TInt RFlexTimer::Connect() + { + OstTrace1( TRACE_NORMAL, RFLEXTIMER_CONNECT, + "RFlexTimer::Connect;this=%x", ( TUint )this ); + + // Not opened handle-number + const TInt kHandleNotOpened( 0 ); + + // Starts the server, if it does not already exist in the system. + TInt ret = StartServer(); + + if ( ret == KErrNone ) + { // No session, create it + + // Handle() is zero when initialized RHandleBase. Close() also zeroes + // the handle. If CreateSession() fails, Handle() is still zero. + // If session is created ok, the Handle() contains the (non zero) + // handle-number. + // + // Handle() can be used for checking is the handle opened or not. + // + if ( Handle() == kHandleNotOpened ) + { + // Creates the session for this client. + ret = CreateSession( KFlexTimerServerName, + Version(), + KFlexTimerServerMessageSlots ); + } + else + { // Session already exists - panic. + + OstTrace1( + TRACE_NORMAL, + DUP1_RFLEXTIMER_CONNECT, + "RFlexTimer::Connect already connected - PANIC;this=%x", + ( TUint )this ); + + User::Panic( KRFlexTimerPanicCat, EFlexTimerAlreadyConnected ); + } + } + return ret; + } + +// --------------------------------------------------------------------------- +// Cancels any outstanding request to the server. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::Cancel() + { + OstTrace1( TRACE_NORMAL, RFLEXTIMER_CANCEL, + "RFlexTimer::Cancel;this=%x", ( TUint )this ); + + SendReceive( EFlexTimerServCancelRequest ); + } + +// --------------------------------------------------------------------------- +// Fire timer at latest on the given interval. 32-bit interval. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus, + TTimeIntervalMicroSeconds32 aInterval ) + { + OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER32, + "RFlexTimer::After32;this=%x;aStatus=%x;aInterval=%d", + ( TUint )this, ( TUint )&( aStatus ), aInterval.Int() ); + + const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0); + __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL32, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerAfterIntervalLessThanZero)); + + TIpcArgs args( aInterval.Int(), 0 ); + //asynchronous request for timer creation and timeout request. + SendReceive( EFlexTimerServAfterRequest, args, aStatus ); + } + +// --------------------------------------------------------------------------- +// Fire timer at latest on the given interval. 64-bit interval. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::After( TRequestStatus& aStatus, + TTimeIntervalMicroSeconds aInterval ) + { + OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTER64, + "RFlexTimer::After64;this=%x;aStatus=%x;aInterval=%lld", + ( TUint )this, ( TUint )&( aStatus ), aInterval.Int64() ); + + const TTimeIntervalMicroSeconds ZERO_INTERVAL(0); + __ASSERT_ALWAYS(aInterval >= ZERO_INTERVAL, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerAfterIntervalLessThanZero)); + + TIpcArgs args( I64LOW(aInterval.Int64()), I64HIGH(aInterval.Int64()) ); + //asynchronous request for timer creation and timeout request. + SendReceive( EFlexTimerServAfterRequest, args, aStatus ); + } + +// --------------------------------------------------------------------------- +// Fire timer at latest after the given number of ticks. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::AfterTicks( TRequestStatus& aStatus, TInt aTicks ) + { + OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AFTERTICKS, + "RFlexTimer::AfterTicks;this=%x;aStatus=%d;aTicks=%d", + ( TUint )this, ( TUint )&( aStatus ), aTicks ); + + __ASSERT_ALWAYS(aTicks >= 0, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerAfterTicksIntervalLessThanZero)); + + TIpcArgs args( aTicks ); + //asynchronous request for timer creation and timeout request. + SendReceive( EFlexTimerServAfterTicksRequest, args, aStatus ); + } + +// --------------------------------------------------------------------------- +// Fire timer between at latest by the given time value. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::At( TRequestStatus& aStatus, const TTime& aTime ) + { + OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_AT, + "RFlexTimer::At;this=%x;aStatus=%d;aTime=%lld", + ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() ); + + TTime nowTime; + nowTime.HomeTime(); + + __ASSERT_ALWAYS(aTime >= nowTime, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerAtIntervalLessThanZero)); + + TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) ); + //asynchronous request for timer creation and timeout request. + SendReceive( EFlexTimerServAtRequest, args, aStatus ); + } + +// --------------------------------------------------------------------------- +// Fire timer between at latest by the given time value. +// --------------------------------------------------------------------------- +// +EXPORT_C void RFlexTimer::AtUTC( TRequestStatus& aStatus, const TTime& aTime ) + { + OstTraceExt3( TRACE_NORMAL, RFLEXTIMER_ATUTC, + "RFlexTimer::AtUTC;this=%x;aStatus=%d;aTime=%lld", + ( TUint )this, ( TUint )&( aStatus ), aTime.Int64() ); + + TTime nowTime; + nowTime.UniversalTime(); + + __ASSERT_ALWAYS(aTime >= nowTime, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerAtUTCIntervalLessThanZero)); + + TIpcArgs args( I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()) ); + //asynchronous request for timer creation and timeout request. + SendReceive( EFlexTimerServAtUTCRequest, args, aStatus ); + } + +// --------------------------------------------------------------------------- +// Sets the window size in which alignment is possible for the timer. +// This is a synchronous command. 32-bit function version. +// --------------------------------------------------------------------------- +// +EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds32 aWindowSize ) + { + OstTraceExt2( TRACE_NORMAL, RFLEXTIMER_CONFIGURE, + "RFlexTimer::Configure32;this=%x;aWindowSize=%d", + ( TUint )this, aWindowSize.Int() ); + + const TTimeIntervalMicroSeconds32 ZERO_INTERVAL32(0); + __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL32, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerWindowLessThanZero)); + + TInt64 transfer = MAKE_TINT64( 0, aWindowSize.Int() ); + + // Regardless of the user function, the window size is always transmitted + // as a 64-bit integer. + TIpcArgs args( EConfigureRequestWindowSize, + I64LOW(transfer), I64HIGH(transfer) ); + + return SendReceive( EFlexTimerServConfigureRequest, args ); + } + +// --------------------------------------------------------------------------- +// Sets the window size in which alignment is possible for the timer. +// This is a synchronous command. 64-bit function version. +// --------------------------------------------------------------------------- +// +EXPORT_C TInt RFlexTimer::Configure( TTimeIntervalMicroSeconds aWindowSize ) + { + OstTraceExt2( TRACE_NORMAL, DUP1_RFLEXTIMER_CONFIGURE, + "RFlexTimer::Configure64;this=%x;aWindowSize=%lld", + ( TUint )this, aWindowSize.Int64() ); + + const TTimeIntervalMicroSeconds ZERO_INTERVAL64(0); + __ASSERT_ALWAYS(aWindowSize >= ZERO_INTERVAL64, + User::Panic(KRFlexTimerPanicCat, + EFlexTimerWindowLessThanZero)); + + // Regardless of the user function, the window size is always transmitted + // as a 64-bit integer. + TIpcArgs args( EConfigureRequestWindowSize, + I64LOW(aWindowSize.Int64()), + I64HIGH(aWindowSize.Int64()) ); + + return SendReceive( EFlexTimerServConfigureRequest, args ); + } + +// --------------------------------------------------------------------------- +// Gets the version number. +// --------------------------------------------------------------------------- +// +TVersion RFlexTimer::Version() const + { + return ( TVersion( KFlexTimerServMajorVersionNumber, + KFlexTimerServMinorVersionNumber, + KFlexTimerServBuildVersionNumber ) ); + } + +// --------------------------------------------------------------------------- +// Connects to the server. If server does not exist, it is created. +// --------------------------------------------------------------------------- +// +TInt RFlexTimer::StartServer() + { + OstTrace1( TRACE_NORMAL, RFLEXTIMER_STARTSERVER, + "RFlexTimer::StartServer;this=%x", ( TUint )this ); + + TFindServer findServer( KFlexTimerServerName ); + TFullName serverName; + + // See if the server is already started. + TInt ret = findServer.Next( serverName ); + + if ( ret != KErrNone ) + { + //Server was not found so create one. + RProcess serverProcess; + TBuf<1> serverParameters; + + // Semaphore to guard the opening of the server process. + RSemaphore semaphore; + + // Prevent two clients from creating the serverProcess at the same + // time. + if ( ( ret = semaphore.CreateGlobal( + KFlexTimerSemaphoreName, KPassFirstWaitEntry ) ) != KErrNone ) + { + ret = semaphore.OpenGlobal( KFlexTimerSemaphoreName ); + } + + if ( ret == KErrNone ) + { + semaphore.Wait(); + + // See again if the server is already started. This doublechecking + // is necessary, since two or processes may have resolved the + // first findserver before any server was created. + + // TFindServer sets its content only when instantiated. + // Just using findServer.Next() does not work in here. + TFindServer findServerAgain( KFlexTimerServerName ); + if ( findServerAgain.Next( serverName ) != KErrNone ) + { + // Load the executable for the server. + ret = serverProcess.Create( KFlexTimerServerExe, + serverParameters, + EOwnerThread ); + + if ( ret == KErrNone ) + { + // Server has been created successfully. It is initially + // in suspended state. Now resume the server process. + serverProcess.Resume(); + + // Wait until the server process has been started. + TRequestStatus status; + serverProcess.Rendezvous( status ); + User::WaitForRequest( status ); + + // Check if server has panicked during initialization. + ret = serverProcess.ExitType(); + if ( ret == EExitPanic ) + { + OstTrace1( TRACE_NORMAL, DUP1_RFLEXTIMER_STARTSERVER, + "RFlexTimer::StartServer;this=%x; " + "ERROR: Server paniced", + ( TUint )this ); + + ret = KErrServerTerminated; + } + else + { + ret = status.Int(); + } + + // The server process stands on its own. This handle can + // be closed. + serverProcess.Close(); + } + else + { + OstTrace1( TRACE_NORMAL, DUP2_RFLEXTIMER_STARTSERVER, + "RFlexTimer::StartServer;this=%x; " + "ERROR: Server creation failed", + ( TUint )this ); + } + } + + semaphore.Signal(); + semaphore.Close(); + } + } + + return ret; + } +