diff -r 000000000000 -r 667063e416a2 locationtriggering/ltcontainer/src/lbtdbtriggersmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locationtriggering/ltcontainer/src/lbtdbtriggersmanager.cpp Tue Feb 02 01:06:48 2010 +0200 @@ -0,0 +1,3070 @@ +/* +* Copyright (c) 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: This file defines the class that handles the storage +* of triggers in database. +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lbtdbtriggersmanager.h" +#include "lbtdboperationao.h" +#include "lbtcontainerextendedtriggerinfo.h" +#include "lbtcontainertriggerfilter.h" +#include "lbtcontainerfilterbase.h" +#include "lbtcontainerareafilter.h" +#include "lbtcontainerattrfilter.h" +#include "lbtcontainercompfilter.h" +#include "lbttriggerstoreobserver.h" +#include "lbtcontainerutilities.h" +#include "lbtserverconsts.h" +#include "lbtlogger.h" + + +_LIT(KLbtDbName,"lbt.db"); // Name of the Database file for storing triggers. +_LIT(KTriggersTable,"Triggers"); // Name of the Table for Triggers +_LIT(KCircularTriggersTable, "CircularTriggers"); +_LIT(KCellTriggersTable, "CellTriggers"); +_LIT(KHybridTriggersTable, "HybridTriggers"); +_LIT(KTriggersIndexId,"TriggerIdIndex"); // Index based on Trigger Id column +_LIT(KCircTriggersIndexId,"CircularTriggerIdIndex"); +_LIT(KCellTriggersIndexId,"CellularTriggerIdIndex"); +_LIT(KHybridTriggersIndexId,"HybridTriggerIdIndex"); + +// Names for the fields in the table +_LIT(KLbtDbFieldId, "id"); +_LIT(KLbtDbFieldName, "name"); +_LIT(KLbtDbFieldType, "type"); +_LIT(KLbtDbFieldDirection, "direction"); +_LIT(KLbtDbFieldOwnerSid, "owner"); +_LIT(KLbtDbFieldManagerUiSid, "managerui"); +_LIT(KLbtDbFieldRearmTime, "rearmtime"); +_LIT(KLbtDbFieldStartupSid, "stprocess"); +_LIT(KLbtDbFieldStartupPath, "stprocesspath"); +_LIT(KLbtDbFieldStartupCommandLine, "stprocesscmdline"); +_LIT(KLbtDbFieldState, "state"); +_LIT(KLbtDbFieldIsTriggerFired, "IsFired"); +_LIT(KLbtDbFieldDistanceToLastLocation,"distance"); +_LIT(KLbtDbFieldValidity, "validity"); +_LIT(KLbtDbFieldIsTriggerFireOnCreation, "IsTriggerFireOnCreation"); +_LIT(KLbtDbTriggerAreaType, "triggerareatype"); + +// Name for the fields in circular trigger table +_LIT(KLbtCircTrigDbFieldId, "idcirculartrigger"); +_LIT(KLbtDbFieldCenterLat, "latitude"); +_LIT(KLbtDbFieldCenterLong, "longitude"); +_LIT(KLbtDbFieldRadius, "radius"); +_LIT(KLbtDbFieldHysteresis, "hysteresis"); +_LIT(KLbtDbFieldAreaLeft, "westlong"); +_LIT(KLbtDbFieldAreaRight, "eastlong"); +_LIT(KLbtDbFieldAreaTop, "northlat"); +_LIT(KLbtDbFieldAreaBottom, "southlat"); +_LIT(KLbtDbFieldTriggerFiredLat, "FiredLat"); +_LIT(KLbtDbFieldTriggerFiredLong, "FiredLong"); +_LIT(KLbtDbFieldTriggerFiredAlt, "FiredAlt"); +_LIT(KLbtDbFieldTriggerFiredHorizAcc, "FiredHorizAcc"); +_LIT(KLbtDbFieldTriggerFiredVertAcc, "FiredVertAcc"); +_LIT(KLbtDbFieldCellIdStream,"cellidstream"); // 9.2TB Column additions start + +// Name for the fields in cellular trigger table +_LIT(KLbtCellTrigDbFieldId, "idcelltrigger"); +_LIT(KLbtCellTrigDbCountryCode, "countrycode"); +_LIT(KLbtCellTrigDbNetworkId, "networkid"); +_LIT(KLbtCellTrigDbNetworkType, "networktype"); +_LIT(KLbtCellTrigDbLAC, "locationcode"); +_LIT(KLbtCellTrigDbCellId, "cellid"); + +// Name for fields in Hybrid trigger table +_LIT(KLbtHybridTrigDbFieldId, "idhybridtrigger"); +_LIT(KLbtHybridDataStream, "hybriddatastream"); // Added for 9.2 TB. Older fields not valid from 9.2 TB + +// Constants for SQL Queries +_LIT(KWhere, " WHERE "); +_LIT(KLike, " = "); +_LIT(KLessThanEqualTo, " <= "); +_LIT(KGreaterThanEqualTo, " >= "); +_LIT(KAnd, " AND "); + +// Enums for the coulumn ids in the common table +enum TCommonDbColNum + { + ELbtDbFieldId = 1, + ELbtDbFieldName, + ELbtDbFieldType, + ELbtDbFieldDirection, + ELbtDbFieldOwnerSid, + ELbtDbFieldManagerUiSid, + ELbtDbFieldRearmTime, + ELbtDbFieldStartupSid, + ELbtDbFieldStartupPath, + ELbtDbFieldStartupCommandLine, + ELbtDbFieldState, + ELbtDbFieldIsTriggerFired, + ELbtDbFieldDistanceToLastLocation, + ELbtDbFieldValidity, + ELbtDbFieldIsTriggerFireOnCreation, + ELbtDbTriggerAreaType, + }; + +// Enums for the column ids in the cicular trigger's db +enum TCircleTriggerDbColNum + { + ECircleDbFieldId = 1, + ECircleDbFieldCenterLat, + ECircleDbFieldCenterLong, + ECircleDbFieldRadius, + ECircleDbFieldHysteresis, + ECircleDbFieldAreaLeft, + ECircleDbFieldAreaRight, + ECircleDbFieldAreaTop, + ECircleDbFieldAreaBottom, + ECircleDbFieldTriggerFiredLat, + ECircleDbFieldTriggerFiredLong, + ECircleDbFieldTriggerFiredAlt, + ECircleDbFieldTriggerFiredHorizAcc, + ECircleDbFieldTriggerFiredVertAcc, + }; + +// Enums for the column ids in the cellular trigger db +enum TCellTriggerDbColNum + { + ECellDbFieldId = 1, + ECellDbCountryCode, + ECellDbNetworkId, + ECellDbNetworkType, + ECellDbLocationAreaCode, + ECellDbTriggerCellId, + }; + +// Enums added for 9.2 TB +enum THybridTriggersDbColNum + { + EHybridDbFieldId = 1, + EHybridDataStream + }; + +// SQL Query related constants +const TInt KMaxSqlQueryLength = 256; + +// If less than the below % of the db is used for legitimate data then compaction is needed +const TInt KDatabaseMinUsagePercentage = 60; +const TInt KDatabaseMaxWastageBytes = (50 * 1024); // More than 50 KB cannot be wasted +const TInt KStepCount(2); // Number of steps to be executed in one step for async operation + +// Assumption that the worst case time needed for compaction is the amount in seconds defined +// by KSecondsNeededForCompaction +const TTimeIntervalSeconds KSecondsNeededForCompaction(15); + +_LIT(KSelect, "SELECT "); +_LIT(KFrom, " FROM "); +_LIT(KSelectAllFields, "* "); +_LIT(KDelete,"DELETE "); + +#ifdef _DEBUG + _LIT(KLbtCntDbPanic,"LBT: Db "); + TInt KLbtCntDbSqlQueryError = -1; +#endif + +// ======== MEMBER FUNCTIONS ======== + + +// --------------------------------------------------------------------------- +// The Symbian 2 phase constructor +// --------------------------------------------------------------------------- +// +CLbtDbTriggersManager* CLbtDbTriggersManager::NewL( ) + { + CLbtDbTriggersManager* self = new(ELeave)CLbtDbTriggersManager( ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CLbtDbTriggersManager::~CLbtDbTriggersManager() + { + FUNC_ENTER("CLbtDbTriggersManager::~CLbtDbTriggersManager"); + // Close all open Handles + delete iDbOperation; + delete iSqlQuery; + + iIdArray.Close(); + + if(iIsDbOpened) + { + // Compact the data base before going down + iDb.Compact(); + } + iDb.Close(); + iFs.Close(); + } + + +// --------------------------------------------------------------------------- +// Specify the types of triggers supported by the Db Trigger Store +// --------------------------------------------------------------------------- +// +TTriggerTypeMask CLbtDbTriggersManager::SupportedTriggerTypes() + { + return ( CLbtTriggerEntry::ETypeStartup ); + } + + +// --------------------------------------------------------------------------- +// Specify the types of triggers supported by the Db Trigger Store +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::CreateTriggerL( CLbtContainerTriggerEntry &aEntry, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::CreateTriggerL-I"); + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + TRequestStatus* status = &aStatus; + User::RequestComplete(status, KErrServerBusy); + return; + } + + // Save client data for create trigger + iCurrentOperation = EDbOpCreateTrigger; + iEntry = &aEntry; + iClientReqStatus = &aStatus; + + TInt size = 500;//ToDo: implement this GetSize( aEntry ); + if ( SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, size ) ) + { + // Try Db Compaction in case we don't have enough disk space + iDbOperation->CompactDb(); + iOperationState = EOpCompaction; + } + else + { + iOperationState = EOpStateQuery; + TInt error = AsyncPrepareViewOfCommonTable(); + + if( error != KErrNone ) + { + CompleteClientRequest( error ); + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::ResetCurrentStates +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::ResetCurrentStates() + { + iOperationState = EOpStateNone; + iCurrentOperation = EDbOpNone; + iEntry = NULL; + iClientReqStatus = NULL; + iFilter = NULL; + delete iFilterBase; + iFilterBase = NULL; + iView.Close(); + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleTriggerCreationEventL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleTriggerCreationEventL( ) + { + FUNC_ENTER("CLbtDbTriggersManager::HandleTriggerCreationEventL"); + + switch(iOperationState) + { + case EOpStateQuery: + { + // Query is done. Now update the view + TRAPD( err, CreateTriggerInViewL() ); + if( err == KErrNone ) + { + CLbtTriggerEntry* trigger = iEntry->TriggerEntry(); + if((trigger->State() == CLbtTriggerEntry::EStateEnabled) && + (iEntry->DynInfo()->iValidity == TLbtTriggerDynamicInfo::EValid)) + { + iCountOfEnabledAndValidTrigger++; + } + } + CompleteClientRequest(err); + CompactDbIfRequiredL(); + break; + } + case EOpCompaction: + { + TInt size = 500;//ToDo: implement this GetSize( aEntry ); + if ( !SysUtil::FFSSpaceBelowCriticalLevelL(&iFs, size) ) + { + iOperationState = EOpStateQuery; + TInt error = AsyncPrepareViewOfCommonTable(); + if( error != KErrNone ) + { + CompleteClientRequest( KErrDiskFull ); + } + } + else + { + CompleteClientRequest( KErrDiskFull ); + } + break; + } + default: + { + CompleteClientRequest( KErrGeneral ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleTriggerUpdationEventL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleTriggerUpdationEventL() + { + + // Sanity checks to be done here + __ASSERT_DEBUG(iView.CountL() < 2, User::Panic(KLbtCntDbPanic, KLbtCntDbSqlQueryError) ); + + switch(iOperationState) + { + case EOpStateQuery: + { + iView.FirstL(); + // check if view is empty, return KErrNotFound + if( iView.IsEmptyL() || !iView.AtRow() ) + { + CompleteClientRequest( KErrNotFound ); + break; + } + // Start iterating through all the triggers in view + iOperationState = EOpStateIterating; + iView.FirstL(); + } + // Omitting break is intentional + case EOpStateIterating: + { + TPtr sql = iSqlQuery->Des(); + + iView.GetL(); + CLbtContainerTriggerEntry* triggerEntry = RetrieveTriggerEntryFromDbL( iView ); + TBool securityCheck = LbtContainerUtilities::RunSecurityPolicy( triggerEntry, iClientSecurityPolicy ); + + if( securityCheck ) + { + // if security check has passed then the trigger will be updated + AppendTriggerInfo( triggerEntry ); + } + else + { + CompleteClientRequest( KErrAccessDenied ); + return; + } + + delete triggerEntry; + iView.FirstL(); + iView.UpdateL(); + + // Check the trigger type and update the appropriate view + CLbtGeoAreaBase::TGeoAreaType triggerAreaType = static_cast(iView.ColInt8(ELbtDbTriggerAreaType)); + CLbtStartupTrigger* trigger = static_cast(iEntry->TriggerEntry()); + + // Check if the condition itself has to be replaced + if( iAttrMask & CLbtTriggerEntry::EAttributeCondition ) + { + CLbtTriggerConditionArea* cond=static_cast (trigger->GetCondition()); + CLbtGeoAreaBase* areaBase = cond->TriggerArea(); + + // The area condition has changed + if( triggerAreaType != areaBase->Type() ) + { + // Check if the trigger area type itself has been updated + RemoveTriggerConditionFromDb( iEntry->TriggerEntry()->Id(), triggerAreaType ); + switch(areaBase->Type()) + { + case CLbtGeoAreaBase::ECircle: + { + AddGeoCircleIntoDbL(trigger); + break; + } + case CLbtGeoAreaBase::ECellular: + { + AddGeoCellIntoDbL(trigger); + break; + } + case CLbtGeoAreaBase::EHybrid: + { + AddGeoHybridIntoDbL(trigger); + break; + } + default: + { + CompleteClientRequest( KErrArgument ); + break; + } + } + + // Write the area type + iView.SetColL(ELbtDbTriggerAreaType,static_cast(areaBase->Type())); + + // Negate the Attribute condition so that it is not updated again + iAttrMask = iAttrMask & (~(CLbtTriggerEntry::EAttributeCondition)); + + // Update trigger area type + triggerAreaType = areaBase->Type(); + } + + CLbtTriggerConditionArea::TDirection currentTriggerDirection = + static_cast(iView.ColInt8(ELbtDbFieldDirection)); + + if( currentTriggerDirection != cond->Direction() ) + { + iView.SetColL( ELbtDbFieldDirection, static_cast((cond->Direction())) ); + } + } + + CLbtTriggerEntry::TLbtTriggerState currentState = + static_cast(iView.ColInt8(ELbtDbFieldState)); + + if( (iEntry->TriggerEntry()->State() == CLbtTriggerEntry::EStateEnabled) && + (currentState == CLbtTriggerEntry::EStateDisabled) ) + { + iCountOfEnabledAndValidTrigger++; + } + else if( (iEntry->TriggerEntry()->State() == CLbtTriggerEntry::EStateDisabled) && + (currentState == CLbtTriggerEntry::EStateEnabled) ) + { + iCountOfEnabledAndValidTrigger--; + } + + CLbtExtendedTriggerInfo* extdInfo = iEntry->ExtendedTriggerInfo(); + TLbtTriggerDynamicInfo* trigDynInfo = iEntry->DynInfo(); + + //Check the masks and update the specified attributes + if(trigger != NULL) + { + if( iAttrMask & CLbtTriggerEntry::EAttributeId ) + { + iView.SetColL( ELbtDbFieldId, static_cast(trigger->Id()) ); + } + + if( iAttrMask & CLbtTriggerEntry::EAttributeName ) + { + iView.SetColL( ELbtDbFieldName, trigger->Name() ); + } + + if( iAttrMask & CLbtTriggerEntry::EAttributeState ) + { + iView.SetColL( ELbtDbFieldState, trigger->State() ); + } + + if( iAttrMask & CLbtTriggerEntry::EAttributeRearmTime ) + { + iView.SetColL( ELbtDbFieldRearmTime, trigger->TimeToRearm() ); + } + + if( iAttrMask & CLbtTriggerEntry::EAttributeStartUpCommandLine ) + { + iView.SetColL( ELbtDbFieldStartupCommandLine, trigger->CommandLine() ); + } + + if( iAttrMask & CLbtTriggerEntry::EAttributeCondition ) + { + CLbtTriggerConditionArea* cond=static_cast (trigger->GetCondition()); + + switch( triggerAreaType ) + { + case CLbtGeoAreaBase::ECircle: + { + //Since the trigger type is circular get the appropriate tuple from the circular trigger table + RDbView circView; + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KCircularTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCircTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum(iEntry->TriggerEntry()->Id()); + + TInt error = iDbOperation->ExecuteSyncQuery( circView, sql ); + if(error != KErrNone) + { + circView.Close(); + User::Leave(error); + } + + CleanupClosePushL(circView); + circView.FirstL(); + if ( circView.IsEmptyL() || !circView.AtRow() ) + { + CleanupStack::PopAndDestroy(1); //circView + CompleteClientRequest( KErrNotFound ); + return; + } + + circView.UpdateL(); + + // The area is of type circle + CLbtGeoCircle* area= static_cast (cond->TriggerArea()); + + circView.SetColL( ECircleDbFieldCenterLat, area->Center().Latitude() ); + circView.SetColL( ECircleDbFieldCenterLong, area->Center().Longitude() ); + circView.SetColL( ECircleDbFieldRadius, area->Radius() ); + + if(extdInfo!=NULL) + { + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeHysteresisRadius ) + { + circView.SetColL( ECircleDbFieldHysteresis, extdInfo->HysteresisRadius() ); + } + + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeRectTriggerArea ) + { + circView.SetColL( ECircleDbFieldAreaLeft, extdInfo->TriggerReactangleArea().iTrigAreaWestLong ); + circView.SetColL( ECircleDbFieldAreaRight, extdInfo->TriggerReactangleArea().iTrigAreaEastLong ); + circView.SetColL( ECircleDbFieldAreaTop, extdInfo->TriggerReactangleArea().iTrigAreaNorthLat ); + circView.SetColL( ECircleDbFieldAreaBottom, extdInfo->TriggerReactangleArea().iTrigAreaSouthLat ); + } + + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeFireInfo ) + { + TLbtTriggerFireInfo fireInfo = extdInfo->GetFiredInfo(); + TPosition pos; + fireInfo.iFiredPositionInfo.GetPosition(pos); + + circView.SetColL(ECircleDbFieldTriggerFiredLat, pos.Latitude()); + circView.SetColL(ECircleDbFieldTriggerFiredLong, pos.Longitude()); + circView.SetColL(ECircleDbFieldTriggerFiredAlt, pos.Altitude()); + circView.SetColL(ECircleDbFieldTriggerFiredHorizAcc, pos.HorizontalAccuracy()); + circView.SetColL(ECircleDbFieldTriggerFiredVertAcc, pos.VerticalAccuracy()); + } + } + circView.PutL(); + CleanupStack::PopAndDestroy(1); // circView + break; + } + case CLbtGeoAreaBase::ECellular: + { + //Since the trigger type is cell get the appropriate tuple from the cell trigger table + RDbView cellView; + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KCellTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCellTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum( iEntry->TriggerEntry()->Id() ); + + TInt error = iDbOperation->ExecuteSyncQuery( cellView, sql ); + if( error != KErrNone ) + { + cellView.Close(); + User::Leave(error); + } + + CleanupClosePushL( cellView ); + cellView.FirstL(); + if ( cellView.IsEmptyL() || !cellView.AtRow() ) + { + CleanupStack::PopAndDestroy(); //cellView + CompleteClientRequest( KErrNotFound ); + return; + } + + cellView.UpdateL(); + + // The area is of type cell + CLbtGeoCell* cell = static_cast (cond->TriggerArea()); + + // Update the cell parameters + + // Update NCC + TLex lex( cell->NetworkCountryCode() ); + TUint netCountryCode; + lex.Val( netCountryCode ); + cellView.SetColL( ECellDbCountryCode, netCountryCode ); + + // Update NIC + lex.Assign( cell->NetworkIdentityCode() ); + TUint networkIdentityCode; + lex.Val( networkIdentityCode ); + cellView.SetColL( ECellDbNetworkId, networkIdentityCode ); + + // Update Network Type + RMobilePhone::TMobilePhoneNetworkMode nwmode = cell->NetworkType(); + if(nwmode == RMobilePhone::ENetworkModeGsm) + { + cellView.SetColL( ECellDbNetworkType, RMobilePhone::ENetworkModeGsm ); + } + else if(nwmode == RMobilePhone::ENetworkModeWcdma) + { + cellView.SetColL( ECellDbNetworkType, RMobilePhone::ENetworkModeWcdma ); + } + + // Update LAC and Cell Id + cellView.SetColL( ECellDbLocationAreaCode, cell->LocationAreaCode()); + cellView.SetColL( ECellDbTriggerCellId, cell->CellId()); + cellView.PutL(); + CleanupStack::PopAndDestroy(1); //cellView + break; + } + case CLbtGeoAreaBase::EHybrid: + { + RDbView hybridView; + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KHybridTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtHybridTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum( iEntry->TriggerEntry()->Id() ); + + TInt err = iDbOperation->ExecuteSyncQuery(hybridView, sql); + if( err != KErrNone ) + { + hybridView.Close(); + User::Leave(err); + } + CleanupClosePushL(hybridView); + + hybridView.FirstL(); + if ( hybridView.IsEmptyL() || !hybridView.AtRow() ) + { + CleanupStack::PopAndDestroy(); //hybridView + CompleteClientRequest( KErrNotFound ); + return; + } + + hybridView.UpdateL(); + + // cast to hybrid area + CLbtGeoHybrid* hybrid = static_cast(cond->TriggerArea()); + + // Externalize the hybrid areas into the DB + hybridView.SetColNullL( EHybridDataStream ); + RDbColWriteStream writeStream; + writeStream.OpenLC(hybridView, EHybridDataStream); + const RPointerArray& hybridAreas = hybrid->HybridArea(); + // Write the count into the the stream + writeStream.WriteInt32L( hybridAreas.Count() ); + for( TInt i=0; iType() ); + + // Externalize the area data + hybridAreas[i]->ExternalizeL(writeStream); + } + writeStream.CommitL(); + writeStream.Close(); + hybridView.PutL(); + CleanupStack::PopAndDestroy( 2 ); // hybridView, writeStream + break; + } + default: + { + CompleteClientRequest( KErrArgument ); + break; + } + } + } + } + + if(extdInfo!=NULL) + { + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeIsFired ) + { + iView.SetColL(ELbtDbFieldIsTriggerFired, extdInfo->IsTriggerFired()); + } + + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeOwnerSid ) + { + iView.SetColL( ELbtDbFieldOwnerSid, extdInfo->OwnerSid().iId ); + } + + if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation ) + { + iView.SetColL( ELbtDbFieldIsTriggerFireOnCreation, extdInfo->IsTriggerFireOnCreation() ); + } + } + + if(trigDynInfo != NULL) + { + if( iDataMask & CLbtContainerTriggerEntry::EContainerDynInfoAttributeValidity ) + { + iView.SetColL( ELbtDbFieldValidity, static_cast(trigDynInfo->iValidity) ); + } + } + + // Flush the updates into the view/db + iView.PutL(); + CompleteClientRequest( KErrNone ); + CompactDbIfRequiredL(); + break; + } + default: + { + CompleteClientRequest( KErrGeneral ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleTriggerStateUpdationEventL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleTriggerStateUpdationEventL() + { + FUNC_ENTER("CLbtDbTriggersManager::HandleTriggerStateUpdationEventL"); + + switch(iOperationState) + { + case EOpStateQuery: + { + // check if view is empty, return KErrNotFound + if( iView.IsEmptyL() ) + { + CompleteClientRequest( KErrNotFound ); + break; + } + // Start iterating through all the triggers in view + iOperationState = EOpStateIterating; + iView.FirstL(); + } + // Omitting break is intentional + case EOpStateIterating: + { + TUid ownerSid; + TUid managerUi; + TSecureId startupSid; + TInt isTriggerPresent = 0; + TInt count = 0; + while( iView.AtRow() && count < KStepCount ) + { + ++count; + iView.GetL(); + // Check if the trigger satisfies the security policy + ownerSid.iUid = iView.ColUint32(ELbtDbFieldOwnerSid); + managerUi.iUid = iView.ColUint32(ELbtDbFieldManagerUiSid); + startupSid.iId = iView.ColUint32(ELbtDbFieldStartupSid); + + if( LbtContainerUtilities::RunSecurityPolicy( ownerSid, + managerUi, + startupSid, + iClientSecurityPolicy ) ) + { + CLbtContainerTriggerEntry* entry = RetrieveTriggerEntryFromDbL( iView ); + CleanupStack::PushL(entry); + + TInt isFilterPresent = 0; + TBool isEntryRequested = EFalse; + + iFilterBase->ProcessFilter(entry, isFilterPresent, isEntryRequested); + + if(isFilterPresent > 0 && isEntryRequested) + { + AppendTriggerInfo(entry); + isTriggerPresent++; + + iView.UpdateL(); + iView.SetColL( ELbtDbFieldState, iState ); + + if( iFireOnUpdate == ELbtTrue ) + { + iView.SetColL( ELbtDbFieldIsTriggerFireOnCreation, ETrue ); + } + else if( iFireOnUpdate == ELbtFalse ) + { + iView.SetColL( ELbtDbFieldIsTriggerFireOnCreation, EFalse ); + } + iView.PutL(); + + CLbtTriggerEntry* trigEntry = entry->TriggerEntry(); + + if( trigEntry->State() == CLbtTriggerEntry::EStateDisabled && + iState == CLbtTriggerEntry::EStateEnabled ) + { + iCountOfEnabledAndValidTrigger++; + } + else if( trigEntry->State() == CLbtTriggerEntry::EStateEnabled && + iState == CLbtTriggerEntry::EStateDisabled) + { + iCountOfEnabledAndValidTrigger--; + } + } + CleanupStack::PopAndDestroy(entry); + } + iView.NextL(); + } + + if( count >= KStepCount ) + { + // Self complete to process next request + SelfComplete(); + } + else + { + CompleteClientRequest( KErrNone ); + CompactDbIfRequiredL(); + } + } + break; + default: + { + CompleteClientRequest( KErrGeneral ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleTriggersDeletionEventL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleTriggersDeletionEventL() + { + switch( iOperationState ) + { + case EOpStateQuery: + { + // check if view is empty, return KErrNotFound + if( iView.IsEmptyL() ) + { + CompleteClientRequest( KErrNotFound ); + break; + } + + // Start iterating through all the triggers in view + iOperationState = EOpStateIterating; + iView.FirstL(); + } + // Omitting break is intentional + case EOpStateIterating: + { + TInt count = 0; + while( count != KStepCount ) + { + ++count; + if( iView.AtRow() ) + { + iView.GetL(); + TUid ownerSid; + TUid managerUi; + TSecureId startupSid; + + ownerSid.iUid = iView.ColUint32( ELbtDbFieldOwnerSid ); + managerUi.iUid = iView.ColUint32( ELbtDbFieldManagerUiSid ); + startupSid.iId = iView.ColUint32( ELbtDbFieldStartupSid ); + + if( LbtContainerUtilities::RunSecurityPolicy( ownerSid, + managerUi, + startupSid, + iClientSecurityPolicy ) ) + { + CLbtContainerTriggerEntry* entry = RetrieveTriggerEntryFromDbL( iView ); + CleanupStack::PushL( entry ); + TInt isFilterPresent = 0; + TBool isEntryRequested = EFalse; + + iFilterBase->ProcessFilter(entry, isFilterPresent, isEntryRequested); + if( isFilterPresent > 0 && isEntryRequested ) + { + AppendTriggerInfo(entry); + CLbtTriggerEntry* trigEntry = entry->TriggerEntry(); + + if( trigEntry->State() == CLbtTriggerEntry::EStateEnabled && + entry->DynInfo()->iValidity == TLbtTriggerDynamicInfo::EValid ) + { + iCountOfEnabledAndValidTrigger--; + } + + // TODO: Check if this will crash + DeleteTriggerL( entry->TriggerEntry()->Id() ); + } + CleanupStack::PopAndDestroy( entry ); + } + iView.NextL(); + } + } + + if( !iView.AtRow() ) + { + CompleteClientRequest( KErrNone ); + CompactDbIfRequiredL(); + } + else + { + SelfComplete(); + } + break; + } + default: + { + CompleteClientRequest( KErrGeneral ); + break; + } + } + } + +//------------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleGetTriggersEventL +//------------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleGetTriggersEventL( ) + { + /** + * Once control reaches here it means that the Db Query + * "Select * From table Triggers" has been executed and + * the view contains all the rows. + */ + + TInt count = 0; + while( iView.AtRow() && count < KStepCount ) + { + ++count; + iView.GetL(); + TLbtTriggerId trigId = iView.ColInt64( ELbtDbFieldId ); + TInt index = iTriggerIds->Find(trigId); + + if( index != KErrNotFound ) + { + CLbtContainerTriggerEntry* entry = RetrieveTriggerEntryFromDbL( iView ); + iTriggerIds->Remove( index ); + + if( LbtContainerUtilities::RunSecurityPolicy( entry, iClientSecurityPolicy ) ) + { + iTriggers->Append(entry); + } + else + { + delete entry; + } + } + + iView.NextL(); + } + + if( count >= KStepCount ) + { + // Self complete to process next request + SelfComplete(); + } + else // Operation is over + { + if(iTriggers->Count() == 0) + { + CompleteClientRequest( KErrNotFound ); + } + else + { + CompleteClientRequest( KErrNone ); + } + } + } +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::CompleteClientRequest +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::CompleteClientRequest(TInt aError) + { + FUNC_ENTER("CLbtDbTriggersManager::CompleteClientRequest"); + if( iClientReqStatus ) + User::RequestComplete(iClientReqStatus,aError); + ResetCurrentStates(); + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::AsyncPrepareViewOfCommonTable +// --------------------------------------------------------------------------- +// +TInt CLbtDbTriggersManager::AsyncPrepareViewOfCommonTable() + { + FUNC_ENTER("CLbtDbTriggersManager::PrepareViewsL"); + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + + // First close the view just as a safe check + iView.Close(); + + TInt error = iView.Prepare( iDb, TDbQuery( sql, EDbCompareFolded) ); + if( error != KErrNone ) + { + iView.Close(); + } + else + { + iView.Evaluate(iStatus); + SetActive(); + } + return error; + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::RetrieveTriggerEntryFromDbL +// Retreives a trigger entry from the first row in the views +// --------------------------------------------------------------------------- +// +CLbtContainerTriggerEntry* CLbtDbTriggersManager::RetrieveTriggerEntryFromDbL( RDbView& aMainView ) + { + /** + * This function is coded under the assumption that aMainView has been initialized + * and other views have been un-initialized. + */ + FUNC_ENTER("CLbtDbTriggersManager::RetrieveTriggerEntryFromDbL"); + CLbtContainerTriggerEntry* entry = CLbtContainerTriggerEntry::NewL(); + CleanupStack::PushL(entry); + + CLbtStartupTrigger* clientEntry = CLbtStartupTrigger::NewL(); + CleanupStack::PushL(clientEntry); + + CLbtExtendedTriggerInfo* clientExtInfo = CLbtExtendedTriggerInfo::NewL(); + CleanupStack::PushL(clientExtInfo); + + CLbtTriggerConditionArea* cond = CLbtTriggerConditionArea::NewL(); + CleanupStack::PushL(cond); + + TLbtTriggerId trigId = aMainView.ColInt64(ELbtDbFieldId); + clientEntry->SetId(trigId); + clientEntry->SetNameL(aMainView.ColDes16(ELbtDbFieldName)); + CLbtTriggerEntry::TLbtTriggerState state = + static_cast (aMainView.ColInt8(ELbtDbFieldState)); + clientEntry->SetState(state); + TSecureId sid; + sid.iId = aMainView.ColUint32(ELbtDbFieldStartupSid); + + TUid managerUi; + managerUi.iUid=aMainView.ColUint32(ELbtDbFieldManagerUiSid); + clientEntry->SetManagerUi(managerUi); + + clientEntry->SetTimeToRearm( aMainView.ColInt32(ELbtDbFieldRearmTime) ); + + clientEntry->SetProcessId(aMainView.ColDes16(ELbtDbFieldStartupPath),sid); + + clientEntry->SetCommandLineL( aMainView.ColDes16(ELbtDbFieldStartupCommandLine) ); + + TInt fireOnCreation; + fireOnCreation=aMainView.ColInt(ELbtDbFieldIsTriggerFireOnCreation); + clientExtInfo->SetTriggerFireOnCreation(fireOnCreation); + cond->SetDirection(static_cast(aMainView.ColInt8(ELbtDbFieldDirection))); + + TUid ownerSid; + ownerSid.iUid=aMainView.ColUint32(ELbtDbFieldOwnerSid); + clientExtInfo->SetOwnerSid(ownerSid); + clientExtInfo->SetTriggerFiredState(aMainView.ColInt(ELbtDbFieldIsTriggerFired)) ; + + TLbtTriggerFireInfo fireInfo; + fireInfo.iAreaType = static_cast(aMainView.ColInt8(ELbtDbTriggerAreaType)); + fireInfo.iTriggerId = aMainView.ColInt64(ELbtDbFieldId); + clientExtInfo->SetFiredInfo(fireInfo); + + switch( aMainView.ColInt8(ELbtDbTriggerAreaType) ) + { + case CLbtGeoAreaBase::ECircle: + { + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KCircularTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCircTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum(trigId); + + RDbView circView; + TInt error = iDbOperation->ExecuteSyncQuery( circView, sql ); + if(error != KErrNone) + { + circView.Close(); + User::Leave(error); + } + + CleanupClosePushL( circView ); + circView.FirstL(); + circView.GetL(); + TCoordinate center; + center.SetCoordinate(circView.ColReal64(ECircleDbFieldCenterLat),circView.ColReal64(ECircleDbFieldCenterLong)); + CLbtGeoCircle* circle=CLbtGeoCircle::NewL(center,circView.ColReal64(ECircleDbFieldRadius)); + cond->SetTriggerArea(circle); + clientExtInfo->SetHysteresisRadius(circView.ColReal64(ECircleDbFieldHysteresis)); + + CLbtExtendedTriggerInfo::TLbtTriggerRectArea rect; + rect.iTrigAreaSouthLat=circView.ColReal64(ECircleDbFieldAreaBottom); + rect.iTrigAreaNorthLat=circView.ColReal64(ECircleDbFieldAreaTop); + rect.iTrigAreaEastLong=circView.ColReal64(ECircleDbFieldAreaRight); + rect.iTrigAreaWestLong=circView.ColReal64(ECircleDbFieldAreaLeft); + clientExtInfo->SetTriggerRectangleArea(rect); + + TPosition pos; + pos.SetCoordinate( circView.ColReal64(ECircleDbFieldTriggerFiredLat), + circView.ColReal64(ECircleDbFieldTriggerFiredLong), + circView.ColReal32(ECircleDbFieldTriggerFiredAlt) ); + + TReal32 horAcc = circView.ColReal32(ECircleDbFieldTriggerFiredHorizAcc); + TReal32 verAcc = circView.ColReal32(ECircleDbFieldTriggerFiredVertAcc); + + if ( horAcc != -1) + { + pos.SetHorizontalAccuracy(horAcc); + } + if(verAcc != -1) + { + pos.SetVerticalAccuracy(verAcc); + } + fireInfo.iFiredPositionInfo.SetPosition(pos); + CleanupStack::PopAndDestroy(1); // circView + break; + } + case CLbtGeoAreaBase::ECellular: + { + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KCellTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCellTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum( trigId ); + + RDbView cellView; + TInt error = iDbOperation->ExecuteSyncQuery( cellView, sql ); + if(error != KErrNone) + { + cellView.Close(); + User::Leave(error); + } + + CleanupClosePushL( cellView ); + cellView.FirstL(); + cellView.GetL(); + + TUint32 countryCode = cellView.ColUint32(ECellDbCountryCode); + TUint32 networkID = cellView.ColUint32(ECellDbNetworkId); + RMobilePhone::TMobilePhoneNetworkMode netType = static_cast(cellView.ColInt8(ECellDbNetworkType)); + TUint32 locAreaCode = cellView.ColUint32(ECellDbLocationAreaCode); + TUint32 cellid = cellView.ColUint32(ECellDbTriggerCellId); + + RMobilePhone::TMobilePhoneNetworkIdentity networkCode; + networkCode.AppendNum( networkID ); + + RMobilePhone::TMobilePhoneNetworkCountryCode setCountryCode; + setCountryCode.AppendNum( countryCode ); + + CLbtGeoCell* cell= CLbtGeoCell::NewL( netType, + setCountryCode, + networkCode, + locAreaCode,cellid ); + cond->SetTriggerArea(cell); + CleanupStack::PopAndDestroy(1); // cellView + break; + } + case CLbtGeoAreaBase::EHybrid: + { + TPtr sql = iSqlQuery->Des(); + RDbView view; + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KHybridTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtHybridTrigDbFieldId ); + sql.Append( KLike ); + sql.AppendNum( trigId ); + + TInt error = iDbOperation->ExecuteSyncQuery( view, sql ); + if(error != KErrNone) + { + view.Close(); + User::Leave(error); + } + CleanupClosePushL(view); + + view.FirstL(); + view.GetL(); + + RPointerArray areaArray; + CleanupClosePushL( areaArray ); + + RDbColReadStream readStream; + readStream.OpenLC(view, EHybridDataStream); + + // Get count of number of area base objects + TInt count = readStream.ReadInt32L(); + for( TInt i=0;iInternalizeL(readStream); + areaArray.Append(areaBase); + CleanupStack::Pop(1); //areaBase + } + + CLbtGeoHybrid* hybrid = CLbtGeoHybrid::NewLC(areaArray); + // Set the wlan area to the trigger + cond->SetTriggerArea( hybrid ); // cond takes ownership of hybrid + CleanupStack::Pop(4); // hybrid, readStream, areaArray and view + readStream.Close(); + view.Close(); + areaArray.Close(); // Ownership of pointers taken by CLbtGeoHybrid + break; + } + } + + clientEntry->SetCondition(cond); + TLbtTriggerDynamicInfo* info = new (ELeave) TLbtTriggerDynamicInfo; + info->iValidity=static_cast (aMainView.ColInt8(ELbtDbFieldValidity)); + info->iDistanceToLatestLocation= aMainView.ColReal32(ELbtDbFieldDistanceToLastLocation) ; + TPosition firedPosition; + fireInfo.iFiredPositionInfo.GetPosition( firedPosition ); + info->iFiredLocality = firedPosition; + + entry->SetTriggerEntry(clientEntry); + entry->SetExtendedTriggerInfo(clientExtInfo); + entry->SetDynInfo(info); + CleanupStack::Pop(4); // entry, clientEntry, clientExtInfo and cond + return entry; + } + +// -------------------------------------------------------------------------- +// CLbtDbTriggersManager::GetTriggersL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::GetTriggersL( RArray& aTriggerIds, + RPointerArray& aTriggers, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus &aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::GetTriggersL"); + aStatus = KRequestPending; + iClientReqStatus = &aStatus; + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + ERROR("COMPACTION ONGOING.THIS SHOULD NOT HAPPEN", KErrServerBusy); + CompleteClientRequest( KErrServerBusy ); + return; + } + + iClientSecurityPolicy = aSecurityPolicy; + iTriggers = &aTriggers; + iTriggerIds = &aTriggerIds; + iCurrentOperation = EDbOpGetTriggers; + // Prepare view for triggers + PrepareViewForTriggersL( aTriggerIds, iView ); + + // rest of list triggers operation is in the method HandleGetTriggersEventL. + iView.FirstL(); + SelfComplete(); + } + +// --------------------------------------------------------------------------- +// List the triggers in database based on filter +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::ListTriggersL( CLbtContainerListOptions* aFilter, + RPointerArray < CLbtContainerTriggerEntry >& aTriggers, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus &aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::ListTriggersL"); + /** + * Here is the alogirthm to do list triggers. The List Triggers + * has filter based on the various attributes of the trigger like, + * State, Validity, ManagerUi, area, Trigger Id etc. + * In order to list triggers based on these various constraints + * we would have to construct a nested query. But since Symbian DBMS does + * not support nested queries, the idea is to implement this as follows. + * + * 1. For i = 1 to number of filter attributes in aFilter + * 2. Construct a SQL query based on the attribute[i] value list. + * 3. Execute this SQL query on the previously obtained view + * 4. Obtain a view that contains only rows that have value matching + * the value list for attribute[i] in aFilter. + * 5. Continue the loop till i < number of filter attributes in aFilter. + * + * So the idea here is to repeatedly execute the query on the filtered + * list of triggers. Each time the query is executed on the already + * updated db view. + * + * As of now this is not the Implementation. TODO: Fix this algo later. + */ + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + aStatus = KRequestPending; + iClientReqStatus = &aStatus; + + if(iDbOperation->IsCompactionOngoing()) + { + CompleteClientRequest( KErrServerBusy ); + return; + } + + // Check if this filter is application for the type of triggers supported by DB + CLbtListTriggerOptions* options = aFilter->ListOptions(); + if(options) + { + if( !IsFilterForDBTriggersL(options->Filter()) ) + { + CompleteClientRequest( KErrNotFound ); + return; + } + } + + if( aFilter == NULL ) + { + CompleteClientRequest( KErrArgument ); + return; + } + + // Store the parameters first for later references + iFilter = aFilter; + iTriggers = &aTriggers; + iClientSecurityPolicy = aSecurityPolicy; + iCurrentOperation = EDbOpListTriggers; + + // Prepare view for listing + PrepareViewForListingL( iView ); + + // rest of list triggers operation is in the method HandleListTriggersEventL. + iView.FirstL(); + iFilterBase = LbtContainerUtilities::GetContainerFilterFromListOptionsLC(iFilter); + CleanupStack::Pop(1); // iFilterBase + + SelfComplete(); + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::UpdateTriggerL +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::UpdateTriggerL( CLbtContainerTriggerEntry& aEntry, + TLbtTriggerDataMask aDataMask, + TLbtTriggerAttributeFieldsMask aAttrMask, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::UpdateTriggerL"); + aStatus = KRequestPending; + iClientReqStatus = &aStatus; + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + CompleteClientRequest( KErrServerBusy ); + return; + } + + // Save user provided data + iClientSecurityPolicy = aSecurityPolicy; + iClientReqStatus = &aStatus; + iEntry = &aEntry; + iDataMask = aDataMask; + iAttrMask = aAttrMask; + + // Save the current operation and its state + iCurrentOperation = EDbOpUpdateTriggers; + iOperationState = EOpStateQuery; + iIdArray.Reset(); + + // Get the tuple from common db for which the primary key is the trigger id + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtDbFieldId ); + sql.Append( KLike ); + sql.AppendNum(aEntry.TriggerEntry()->Id()); + + // First close the view just as a safe check + iView.Close(); + + TInt error = iView.Prepare( iDb, TDbQuery( sql, EDbCompareFolded) ); + if( error != KErrNone ) + { + iView.Close(); + CompleteClientRequest( error ); + } + else + { + iView.Evaluate(iStatus); + SetActive(); + } + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::RemoveTriggerConditionFromDb +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::RemoveTriggerConditionFromDb( TLbtTriggerId aTriggerId, + CLbtGeoAreaBase::TGeoAreaType aAreaType ) + { + RDbView view; + TPtr sql = iSqlQuery->Des(); + + sql.Zero(); + sql.Append( KDelete ); + sql.Append( KFrom ); + + switch( aAreaType ) + { + case CLbtGeoAreaBase::ECircle: + { + sql.Append( KCircularTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCircTrigDbFieldId ); + break; + } + case CLbtGeoAreaBase::ECellular: + { + sql.Append( KCellTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtCellTrigDbFieldId ); + break; + } + case CLbtGeoAreaBase::EHybrid: + { + sql.Append( KHybridTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtHybridTrigDbFieldId ); + break; + } + } + + sql.Append( KLike ); + sql.AppendNum( aTriggerId ); + + // Execute the query to delete the entry + iDbOperation->ExecuteSyncQuery( view, sql ); + view.Close(); + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::AddGeoCellIntoDbL +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::AddGeoCellIntoDbL( CLbtTriggerEntry* aTriggerEntry ) + { + // Prepare view for cellular trigger table + // Create the trigger + CLbtTriggerConditionArea* cond=static_cast (aTriggerEntry->GetCondition()); + if( cond->TriggerArea()->Type() != CLbtGeoAreaBase::ECellular ) + { + User::Leave( KErrArgument ); + } + + CLbtGeoCell* cell = static_cast(cond->TriggerArea()); + RDbView view; + TPtr cellSql = iSqlQuery->Des(); + cellSql.Zero(); + cellSql.Append( KSelect ); + cellSql.Append( KSelectAllFields ); + cellSql.Append( KFrom ); + cellSql.Append( KCellTriggersTable ); + + TInt err = iDbOperation->ExecuteSyncQuery(view, cellSql); + if( err != KErrNone ) + { + view.Close(); + User::Leave(err); + return; + } + CleanupClosePushL(view); + + view.InsertL(); + view.SetColL( ECellDbFieldId, static_cast(aTriggerEntry->Id()) ); + + // insert MNC + TLex lex( cell->NetworkCountryCode() ); + TUint netCountryCode; + lex.Val( netCountryCode ); + view.SetColL( ECellDbCountryCode, netCountryCode ); + + lex.Assign( cell->NetworkIdentityCode() ); + TUint networkIdentityCode; + lex.Val( networkIdentityCode ); + view.SetColL( ECellDbNetworkId, networkIdentityCode ); + + RMobilePhone::TMobilePhoneNetworkMode nwmode = cell->NetworkType(); + if(nwmode == RMobilePhone::ENetworkModeGsm) + { + view.SetColL( ECellDbNetworkType, RMobilePhone::ENetworkModeGsm); + } + else if(nwmode == RMobilePhone::ENetworkModeWcdma) + { + view.SetColL( ECellDbNetworkType, RMobilePhone::ENetworkModeWcdma); + } + + view.SetColL( ECellDbLocationAreaCode, cell->LocationAreaCode()); + view.SetColL( ECellDbTriggerCellId, cell->CellId()); + view.PutL(); + CleanupStack::PopAndDestroy(1); // view + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::AddGeoCircleIntoDbL +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::AddGeoCircleIntoDbL( CLbtTriggerEntry* aTriggerEntry ) + { + CLbtTriggerConditionArea* cond = static_cast(aTriggerEntry->GetCondition()); + CLbtGeoAreaBase * areaBase = cond->TriggerArea(); + if( areaBase->Type() != CLbtGeoAreaBase::ECircle ) + { + User::Leave( KErrArgument ); + } + + // Prepare view from circlar triggers table + RDbView view; + TPtr circSql = iSqlQuery->Des(); + circSql.Zero(); + circSql.Append( KSelect ); + circSql.Append( KSelectAllFields ); + circSql.Append( KFrom ); + circSql.Append( KCircularTriggersTable ); + + TInt err = iDbOperation->ExecuteSyncQuery(view, circSql); + if( err != KErrNone ) + { + view.Close(); + User::Leave(err); + return; + } + CleanupClosePushL(view); + + CLbtGeoCircle* area = static_cast(cond->TriggerArea()); + + view.InsertL(); + view.SetColL( ECircleDbFieldId, static_cast(aTriggerEntry->Id()) ); + view.SetColL( ECircleDbFieldCenterLat, area->Center().Latitude() ); + view.SetColL( ECircleDbFieldCenterLong, area->Center().Longitude() ); + view.SetColL( ECircleDbFieldRadius, area->Radius() ); + + TReal defaultValue = -1; + TReal32 alt = -1; + view.SetColL(ECircleDbFieldTriggerFiredLat,defaultValue); + view.SetColL(ECircleDbFieldTriggerFiredLong,defaultValue); + view.SetColL(ECircleDbFieldTriggerFiredAlt,alt); + view.SetColL(ECircleDbFieldTriggerFiredHorizAcc,alt); + view.SetColL(ECircleDbFieldTriggerFiredVertAcc,alt); + view.PutL(); // Complete insertion + CleanupStack::PopAndDestroy(1); // view + } + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::AddGeoHybridIntoDbL +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::AddGeoHybridIntoDbL( CLbtTriggerEntry* aTriggerEntry ) + { + CLbtTriggerConditionArea* cond = static_cast(aTriggerEntry->GetCondition()); + CLbtGeoAreaBase * areaBase = cond->TriggerArea(); + + if( areaBase->Type() != CLbtGeoAreaBase::EHybrid ) + { + User::Leave(KErrArgument); + } + + RDbView view; + TPtr hybridSql = iSqlQuery->Des(); + hybridSql.Zero(); + hybridSql.Append( KSelect ); + hybridSql.Append( KSelectAllFields ); + hybridSql.Append( KFrom ); + hybridSql.Append( KHybridTriggersTable ); + + TInt err = iDbOperation->ExecuteSyncQuery(view, hybridSql); + if( err != KErrNone ) + { + view.Close(); + User::Leave(err); + } + CleanupClosePushL(view); + view.InsertL(); + + // cast to hybrid area + CLbtGeoHybrid* hybrid = static_cast(cond->TriggerArea()); + + // Set Primary key, trigger id. + view.SetColL( EHybridDbFieldId ,static_cast(aTriggerEntry->Id()) ); + + // Externalize the hybrid areas into the DB + view.SetColNullL( EHybridDataStream ); + RDbColWriteStream writeStream; + writeStream.OpenLC(view, EHybridDataStream); + const RPointerArray& hybridAreas = hybrid->HybridArea(); + // Write the count into the the stream + writeStream.WriteInt32L( hybridAreas.Count() ); + for( TInt i=0; iType() ); + + // Externalize the area data + hybridAreas[i]->ExternalizeL(writeStream); + } + writeStream.CommitL(); + writeStream.Close(); + view.PutL(); + CleanupStack::PopAndDestroy( 2 ); // view, writeStream + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::UpdateTriggersState +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::UpdateTriggersStateL( CLbtTriggerEntry::TLbtTriggerState aState, + CLbtContainerUpdateFilter* aFilter, + TLbtFireOnUpdate aFireOnUpdate, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::UpdateTriggersState"); + aStatus = KRequestPending; + iClientReqStatus = &aStatus; + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if( iDbOperation->IsCompactionOngoing() ) + { + CompleteClientRequest( KErrServerBusy ); + return; + } + + if(aFilter==NULL) + { + CompleteClientRequest( KErrArgument ); + return; + } + + // Save user provided data + iClientSecurityPolicy = aSecurityPolicy; + iState = aState; + iFireOnUpdate = aFireOnUpdate; + iFilterBase = LbtContainerUtilities::GetContainerFilterFromUpdateFilterLC( aFilter ); + CleanupStack::Pop(1); // iFilterBase + + // Save the current operation and its state + iCurrentOperation = EDbOpUpdateTriggersState; + iOperationState = EOpStateQuery; + iIdArray.Reset(); + + TInt error = AsyncPrepareViewOfCommonTable(); + + if( error != KErrNone ) + { + CompleteClientRequest( error ); + } + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::UpdateTriggersValidity +// -------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::UpdateTriggersValidityL( TLbtTriggerDynamicInfo::TLbtTriggerValidity aValidity, + RArray & aTriggerIds, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::UpdateTriggersValidity"); + TRequestStatus* status = &aStatus; + aStatus = KRequestPending; + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + User::RequestComplete(status, KErrServerBusy); + return; + } + + if(aTriggerIds.Count() == 0) + { + User::RequestComplete(status, KErrArgument); + return; + } + + iIdArray.Reset(); + RDbView view; + PrepareViewForTriggersL( aTriggerIds, view ); + + CleanupClosePushL( view ); + view.FirstL(); + while(view.AtRow()) + { + view.GetL(); + TLbtTriggerId triggerId = view.ColInt64(ELbtDbFieldId); + TInt index = aTriggerIds.Find(triggerId); + + if( KErrNotFound != index ) + { + // This trigger is found in this db. So remove the trigger from the list + aTriggerIds.Remove(index); + + // Check if the trigger satisfies the security policy + TUid ownerSid; + TUid managerUi; + TSecureId startupSid; + + ownerSid.iUid = view.ColUint32(ELbtDbFieldOwnerSid); + managerUi.iUid = view.ColUint32(ELbtDbFieldManagerUiSid); + startupSid.iId = view.ColUint32(ELbtDbFieldStartupSid); + + if( LbtContainerUtilities::RunSecurityPolicy( ownerSid, + managerUi, + startupSid, + aSecurityPolicy ) ) + { + TLbtTriggerDynamicInfo::TLbtTriggerValidity currentValidity= + static_cast(view.ColInt8(ELbtDbFieldValidity)); + + if( currentValidity != aValidity ) + { + view.UpdateL(); + view.SetColL( ELbtDbFieldValidity, static_cast(aValidity) ); + view.PutL(); + + TLbtTriggerModifiedInfo info; + info.iTriggerId = triggerId; + info.iAreaType = static_cast(view.ColInt8(ELbtDbTriggerAreaType));; + iIdArray.Append(info); + + if( currentValidity == TLbtTriggerDynamicInfo::EInvalid && + aValidity == TLbtTriggerDynamicInfo::EValid) + { + iCountOfEnabledAndValidTrigger++; + } + else if(currentValidity == TLbtTriggerDynamicInfo::EValid && + aValidity == TLbtTriggerDynamicInfo::EInvalid) + { + iCountOfEnabledAndValidTrigger--; + } + } + } + } + view.NextL(); + } + CleanupStack::PopAndDestroy(); // view + User::RequestComplete( status, KErrNone ); + } + + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::UpdateTriggerFiredStateL +// -------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::UpdateTriggerFiredStateL( RArray& aTriggerIds, + TBool aFireBool, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::UpdateTriggerFiredStateL"); + TRequestStatus* status = &aStatus; + aStatus = KRequestPending; + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + User::RequestComplete(status, KErrServerBusy); + return; + } + + if(aTriggerIds.Count() == 0) + { + User::RequestComplete(status, KErrArgument); + return; + } + + RDbView view; + PrepareViewForTriggersL( aTriggerIds, view ); + + TBool found = EFalse; + CleanupClosePushL( view ); + view.FirstL(); + while(view.AtRow()) + { + view.GetL(); + TLbtTriggerId triggerId = view.ColInt64(ELbtDbFieldId); + + if( KErrNotFound != aTriggerIds.Find(triggerId) ) + { + TBool currentFiredFlag = view.ColInt(ELbtDbFieldIsTriggerFired); + found = ETrue; + if(currentFiredFlag != aFireBool) + { + view.UpdateL(); + view.SetColL( ELbtDbFieldIsTriggerFired, aFireBool ); + view.PutL(); + } + } + view.NextL(); + } + CleanupStack::PopAndDestroy(); //view + + TInt error = KErrNone; + if(!found) + { + error = KErrNotFound; + } + User::RequestComplete(status, error); + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::DeleteTriggersL +// -------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::DeleteTriggersL( CLbtContainerUpdateFilter* aFilter, + TLbtSecurityPolicy& aSecurityPolicy, + TRequestStatus& aStatus ) + { + FUNC_ENTER("CLbtDbTriggersManager::DeleteTriggersL"); + + // Save user provided data + iClientSecurityPolicy = aSecurityPolicy; + iClientReqStatus = &aStatus; + + // This is just a safe check. While compaction is ongoing the + // request is queued in container AO + if(iDbOperation->IsCompactionOngoing()) + { + CompleteClientRequest( KErrServerBusy ); + return; + } + + if(aFilter == NULL) + { + CompleteClientRequest( KErrArgument ); + return; + } + + if( !IsFilterForDBTriggersL(aFilter->TrigInfoFilter()) ) + { + CompleteClientRequest( KErrNotFound ); + return; + } + + TInt error = AsyncPrepareViewOfCommonTable(); + if( error != KErrNone ) + { + CompleteClientRequest( error ); + return; + } + + + iFilterBase = LbtContainerUtilities::GetContainerFilterFromUpdateFilterLC( aFilter ); + CleanupStack::Pop(1); // iFilterBase + + // Save the current operation and its state + iCurrentOperation = EDbOpDeleteTriggers; + iOperationState = EOpStateQuery; + iIdArray.Reset(); + } + +// -------------------------------------------------------------------------- +// CLbtDbTriggersManager::SelfComplete +// -------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::SelfComplete() + { + TRequestStatus* status = &iStatus; + iStatus = KRequestPending; + SetActive(); + User::RequestComplete(status, KErrNone); + } + + +// -------------------------------------------------------------------------- +// CLbtDbTriggersManager::DeleteTriggerL +// -------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::DeleteTriggerL( TLbtTriggerId aTriggerId ) + { + FUNC_ENTER("CLbtDbTriggersManager::DeleteTriggerL"); + + CLbtGeoAreaBase::TGeoAreaType areaType = + static_cast( iView.ColInt8(ELbtDbTriggerAreaType) ); + + switch( areaType ) + { + case CLbtGeoAreaBase::ECircle: + { + TPtr circSql = iSqlQuery->Des(); + RDbView circView; + circSql.Zero(); + circSql.Append( KSelect ); + circSql.Append( KSelectAllFields ); + circSql.Append( KFrom ); + circSql.Append( KCircularTriggersTable ); + circSql.Append( KWhere ); + circSql.Append( KLbtCircTrigDbFieldId ); + circSql.Append( KLike ); + circSql.AppendNum(aTriggerId); + + TInt error = iDbOperation->ExecuteSyncQuery( circView, circSql ); + if(error != KErrNone) + { + circView.Close(); + User::Leave(error); + } + CleanupClosePushL(circView); + circView.FirstL(); + circView.GetL(); + circView.DeleteL(); + circView.Close(); + CleanupStack::PopAndDestroy(1); // circView + break; + } + case CLbtGeoAreaBase::ECellular: + { + TPtr cellSql = iSqlQuery->Des(); + cellSql.Zero(); + cellSql.Append( KSelect ); + cellSql.Append( KSelectAllFields ); + cellSql.Append( KFrom ); + cellSql.Append( KCellTriggersTable ); + cellSql.Append( KWhere ); + cellSql.Append( KLbtCellTrigDbFieldId ); + cellSql.Append( KLike ); + cellSql.AppendNum(aTriggerId); + + RDbView cellView; + TInt error = iDbOperation->ExecuteSyncQuery( cellView, cellSql ); + if(error != KErrNone) + { + cellView.Close(); + User::Leave(error); + } + CleanupClosePushL(cellView); + cellView.FirstL(); + cellView.GetL(); + cellView.DeleteL(); + cellView.Close(); + CleanupStack::PopAndDestroy(1); // cellView + break; + } + case CLbtGeoAreaBase::EHybrid: + { + TPtr cellSql = iSqlQuery->Des(); + cellSql.Zero(); + cellSql.Append( KSelect ); + cellSql.Append( KSelectAllFields ); + cellSql.Append( KFrom ); + cellSql.Append( KHybridTriggersTable ); + cellSql.Append( KWhere ); + cellSql.Append( KLbtHybridTrigDbFieldId ); + cellSql.Append( KLike ); + cellSql.AppendNum(aTriggerId); + + RDbView hybridView; + TInt error = iDbOperation->ExecuteSyncQuery( hybridView, cellSql ); + if(error != KErrNone) + { + hybridView.Close(); + User::Leave(error); + } + CleanupClosePushL(hybridView); + hybridView.FirstL(); + hybridView.GetL(); + hybridView.DeleteL(); + hybridView.Close(); + CleanupStack::PopAndDestroy(1); // hybridView + break; + } + } + + if(iIdArray.Count() == 0) + { + MLbtTriggerStore::TLbtTriggerModifiedInfo info; + info.iTriggerId = aTriggerId; + info.iAreaType = areaType; + iIdArray.Append(info); + } + + iView.DeleteL(); + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::RunL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::RunL() + { + if( iStatus.Int() != KErrNone ) + { + CompleteClientRequest( iStatus.Int() ); + return; + } + + switch( iCurrentOperation ) + { + case EDbOpCreateTrigger: + { + HandleTriggerCreationEventL(); + break; + } + case EDbOpDeleteTriggers: + { + HandleTriggersDeletionEventL(); + break; + } + case EDbOpListTriggers: + { + HandleListTriggersEventL(); + break; + } + case EDbOpGetTriggers: + { + HandleGetTriggersEventL(); + break; + } + case EDbOpUpdateTriggersState: + { + HandleTriggerStateUpdationEventL(); + break; + } + case EDbOpUpdateTriggers: + { + HandleTriggerUpdationEventL(); + break; + } + default: + { + //CompleteClientRequest( KErrGeneral ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::RunError +// --------------------------------------------------------------------------- +// +TInt CLbtDbTriggersManager::RunError( TInt aError ) + { + CompleteClientRequest( aError ); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::DoCancel +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::DoCancel() + { + switch( iOperationState ) + { + case EOpCompaction: + { + // Cancel compaction if ongoing + iDbOperation->Cancel(); + break; + } + case EOpStateQuery: + { + iView.Cancel(); + break; + } + case EOpStateIterating: + default: + { + break; + } + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::PrepareViewForTriggersL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::PrepareViewForTriggersL( const RArray& aTriggerIds, RDbView& aView ) + { + FUNC_ENTER("CLbtDbTriggersManager::PrepareViewForTriggersL"); + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + + if( !aTriggerIds.Count() ) + { + User::Leave( KErrArgument ); + return; + } + + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtDbFieldId ); + + if( aTriggerIds.Count() == 1 ) + { + sql.Append( KLike ); + sql.AppendNum( aTriggerIds[0] ); + } + else + { + // Find the max and min of trigger ids so that we get only thos triggers + // that fall into that bracket + TInt min = 0xFFFFFFFF; + TInt max = KLbtNullTriggerId; + + for(TInt i=0;i max) + { + max = aTriggerIds[i]; + } + } + + sql.Append( KLessThanEqualTo ); + sql.AppendNum( max ); + sql.Append( KAnd ); + sql.Append( KLbtDbFieldId ); + sql.Append( KGreaterThanEqualTo ); + sql.AppendNum( min ); + } + + TInt err = iDbOperation->ExecuteSyncQuery(aView, sql); + if( err != KErrNone ) + { + aView.Close(); + User::Leave(err); + return; + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::AsyncPrepareViewForTriggersL +// --------------------------------------------------------------------------- +// +TInt CLbtDbTriggersManager::AsyncPrepareViewForTriggers( const RArray& aTriggerIds, RDbView& /*aView*/ ) + { + FUNC_ENTER("CLbtDbTriggersManager::PrepareViewForTriggersL"); + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + + if( !aTriggerIds.Count() ) + { + return KErrArgument; + } + + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtDbFieldId ); + + if( aTriggerIds.Count() == 1 ) + { + sql.Append( KLike ); + sql.AppendNum( aTriggerIds[0] ); + } + else + { + // Find the max and min of trigger ids so that we get only thos triggers + // that fall into that bracket + TInt min = 0xFFFFFFFF; + TInt max = KLbtNullTriggerId; + + for(TInt i=0;i max) + { + max = aTriggerIds[i]; + } + } + + sql.Append( KLessThanEqualTo ); + sql.AppendNum( max ); + sql.Append( KAnd ); + sql.Append( KLbtDbFieldId ); + sql.Append( KGreaterThanEqualTo ); + sql.AppendNum( min ); + } + iView.Close(); + + TInt err = iView.Prepare( iDb, TDbQuery(sql, EDbCompareFolded),KDbUnlimitedWindow ); + // This should evaluate the query fully + if ( err == KErrNone ) + { + iView.Evaluate(iStatus); + SetActive(); + return KErrNone; + } + else + { + iView.Close(); + return err; + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::IsFilterForDBTriggersL +// --------------------------------------------------------------------------- +// +TBool CLbtDbTriggersManager::IsFilterForDBTriggersL( CLbtTriggerFilterBase* aFilter ) + { + if( aFilter == NULL ) + { + return ETrue; + } + + if( aFilter->Type() == CLbtTriggerFilterBase::EFilterByAttribute ) + { + CLbtTriggerFilterByAttribute* attributeFilter = + static_cast(aFilter); + + RArray triggerTypeArray; + attributeFilter->GetTypeArrayL( triggerTypeArray ); + + if( triggerTypeArray.Count() ) + { + // If the trigger type does not have startup triggers then return EFalse + if( !attributeFilter->IsTriggerTypeInFilter(CLbtTriggerEntry::ETypeStartup) ) + { + return EFalse; + } + } + triggerTypeArray.Close(); + } + return ETrue; + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::PrepareViewForListingL +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::PrepareViewForListingL( RDbView& aView ) + { + FUNC_ENTER("CLbtDbTriggersManager::PrepareViewsL"); + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + // As of now,create trigger operation on db side is implemented synchronously.So using Synchronous version. + + TInt err = iDbOperation->ExecuteSyncQuery( aView, sql ); + if( err != KErrNone ) + { + aView.Close(); + User::Leave(err); + return; + } + } + +// --------------------------------------------------------------------------- +// Callback method that gets called when SQL Evaluation is completed. +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::DbSqlOperationCompletedL( TInt error ) + { + FUNC_ENTER("CLbtDbTriggersManager::DbSqlOperationCompleted"); + switch( iCurrentOperation ) + { + case EDbOpCreateTrigger: + { + if ( KErrNone == error ) + { + TRAP(error, CreateTriggerInViewL()); + } + User::RequestComplete(iClientReqStatus, error); + iClientReqStatus = NULL; + + if(KErrNone == error) + { + CompactDbIfRequiredL(); + } + + iCurrentOperation = EDbOpNone; + } + break; + + default: + break; + } + } + +// --------------------------------------------------------------------------- +// CLbtDbTriggersManager::AppendTriggerInfo +// +// Appends the trigger info into the triggers modified array which is used for +// notifying observers +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::AppendTriggerInfo(CLbtContainerTriggerEntry* aEntry) + { + FUNC_ENTER("CLbtDbTriggersManager::AppendTriggerInfo"); + const CLbtTriggerConditionArea* conditionBase = + static_cast(aEntry->TriggerEntry()->GetCondition()); + CLbtGeoAreaBase* areaBase = conditionBase->TriggerArea(); + + TLbtTriggerModifiedInfo info; + info.iTriggerId = aEntry->TriggerEntry()->Id(); + info.iAreaType = areaBase->Type(); + info.iManagerUi = aEntry->TriggerEntry()->ManagerUi(); + + TSecureId sid = aEntry->ExtendedTriggerInfo()->OwnerSid(); + TUid ownerUid; + ownerUid.iUid = (TInt)(sid.iId); + info.iOwner = ownerUid; + + CLbtTriggerEntry* triggerEntry = aEntry->TriggerEntry(); + if( triggerEntry->Type() == CLbtTriggerEntry::ETypeStartup) + { + CLbtStartupTrigger* startupTrigger = static_cast(triggerEntry); + TSecureId secureId; + TBuf16 fileName; + startupTrigger->GetProcessId(fileName, secureId); + TUid startupUid; + startupUid.iUid = (TInt)(sid.iId); + info.iStartupProcess = startupUid; + } + else + { + info.iStartupProcess = KNullUid; + } + + iIdArray.Append(info); + } + + +// ----------------------------------------------------------------------------- +// CLbtDbTriggersManager::TriggersModified +// ----------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::TriggersModified(RArray& aArray) + { + for( TInt i = 0;iDynInfo(); + + CLbtStartupTrigger* clientEntry = static_cast( aEntry->TriggerEntry() ); + + if( !(aDynInfoMask & TLbtTriggerDynamicInfo::EValidityStatus) ) + { + info->iValidity = TLbtTriggerDynamicInfo::EInvalid; + } + + if( !(aDynInfoMask & TLbtTriggerDynamicInfo::EDistanceToLatestLocation) ) + { + info->iDistanceToLatestLocation = 0; + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeId ) ) + { + clientEntry->SetId(0); + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeName) ) + { + TRAP_IGNORE(clientEntry->SetNameL(KNullDesC)); + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeState) ) + { + clientEntry->SetState(CLbtTriggerEntry::EStateEnabled); + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeRequestor) ) + { + // TBD + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeManagerUi) ) + { + TUid managerUi = TUid::Null(); + clientEntry->SetManagerUi(managerUi); + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeCondition) ) + { + CLbtTriggerConditionBase* condBase = clientEntry->GetCondition(); + clientEntry->SetCondition(NULL); + } + + if( !(aAttrMask & CLbtTriggerEntry::EAttributeStartUpProcessId) ) + { + TSecureId sid(0); + clientEntry->SetProcessId( KNullDesC, sid ); + } + + if( !(aDataMask & CLbtContainerTriggerEntry::EContainerAttributeRectTriggerArea) ) + { + + } + } + +//------------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CompactDbIfRequiredL +//------------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::CompactDbIfRequiredL() + { + FUNC_ENTER("CLbtDbTriggersManager::CompactDbIfRequiredL"); + // First update the stats to get the accurate db size information + User::LeaveIfError(iDb.UpdateStats()); + RDbDatabase::TSize size = iDb.Size(); + TReal wastedBytes = size.iSize * static_cast(100 - size.iUsage)/100; + + // Check if the amount of legitimate data present in less than the minimum usage percentage + if( size.iUsage < KDatabaseMinUsagePercentage && + wastedBytes > KDatabaseMaxWastageBytes ) + { + TTime currentTime; + + // Get the current time + currentTime.UniversalTime(); + + // Find the seconds we have to compact + TTimeIntervalSeconds seconds; + + TInt error = currentTime.SecondsFrom(iTimeTillCompaction, seconds); + + // If error is not equal to KErrNone that means that iTimeTillCompaction has not been set appropriately + if(seconds > KSecondsNeededForCompaction || error != KErrNone) + { + // Compaction is needed + iDbOperation->CompactDb(); + } + } + } + +//------------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::HandleListTriggersEventL +//------------------------------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::HandleListTriggersEventL( ) + { + FUNC_ENTER("CLbtDbTriggersManager::HandleListTriggersEventL"); + /** + * Once control reaches here it means that the Db Query + * "Select * From table Triggers" has been executed and + * the view contains all the rows. + */ + + CLbtListTriggerOptions* listOptions = iFilter->ListOptions(); + TLbtTriggerAttributeFieldsMask attrMask; + TLbtTriggerDynamicInfoFieldsMask dynInfoMask; + listOptions->GetRetrievedFields(attrMask,dynInfoMask); + TLbtTriggerDataMask dataMask = iFilter->DataMask(); + + TUid ownerSid; + TUid managerUi; + TSecureId startupSid; + TInt count = 0; + while( iView.AtRow() && count < KStepCount ) + { + ++count; + iView.GetL(); + ownerSid.iUid = iView.ColUint32(ELbtDbFieldOwnerSid); + managerUi.iUid = iView.ColUint32(ELbtDbFieldManagerUiSid); + startupSid.iId = iView.ColUint32(ELbtDbFieldStartupSid); + + if( LbtContainerUtilities::RunSecurityPolicy( ownerSid, + managerUi, + startupSid, + iClientSecurityPolicy ) ) + { + CLbtContainerTriggerEntry* entry = RetrieveTriggerEntryFromDbL( iView ); + TInt isFilterPresent = 0; + TBool isEntryRequested = EFalse; + iFilterBase->ProcessFilter(entry, isFilterPresent, isEntryRequested); + + if(isFilterPresent > 0 && isEntryRequested) + { + ProcessListTriggers(entry,attrMask,dynInfoMask,dataMask); + iTriggers->Append(entry); + } + else + { + delete entry; + } + } + + iView.NextL(); + } + + if( count >= KStepCount ) + { + // Self complete to process next request + SelfComplete(); + } + else // Operation is over + { + if(iTriggers->Count() == 0) + { + CompleteClientRequest( KErrNotFound ); + } + else + { + CompleteClientRequest( KErrNone ); + } + } + } + + +// --------------------------------------------------------------------------- +// Callback method that is called when an Incremental operation is executed +// on the database (like database compaction, recovery) +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::DbIncrementalOperationCompleted( TInt /*aError*/ ) + { + FUNC_ENTER("CLbtDbTriggersManager::DbIncrementalOperationCompleted"); + switch( iCurrentOperation ) + { + case EDbOpCreateTrigger: + { + // Even if there is an error, it just means that Db Compaction + // failed. So lets try Create trigger once more even in case of + // failure. There is a remote possibility that some other process + // might have done some cleanup and created enough space for this + // trigger. So ignoring the error from compaction action here + // deliberately. + TInt error = KErrNone; + TRAP( error, HandleTriggerCreationEventL() ); + if( error != KErrNone ) + { + CompleteClientRequest( error ); + } + } + break; + default: + { + // Notfy the client that we are ready to serve requests again + iObserver->NotifyTriggerStoreReadyToServe(); + break; + } + } + } + +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- +// +CLbtDbTriggersManager::CLbtDbTriggersManager( ) + : CActive(CActive::EPriorityStandard), + iDbOperation( NULL ), + iSqlQuery( NULL ), + iCurrentOperation( EDbOpNone ), + iOperationState( EOpStateNone ), + iFilterBase( NULL ) + { + CActiveScheduler::Add(this); + iIdArray.Reset(); + iCountOfEnabledAndValidTrigger=0; + } + + +// --------------------------------------------------------------------------- +// The 2nd phase Symbian Constructor +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::ConstructL() + { + FUNC_ENTER("CLbtDbTriggersManager::ConstructL"); + + // db has not been opened yet + iIsDbOpened = EFalse; + + // Can't do much if the file server open fails. Hence just leave + // with that error code. + User::LeaveIfError(iFs.Connect()); + + // Obtain the Db file path + TFileName dbFile; + iFs.SessionPath(dbFile); + + // Create the Database Directory ie the private directory of the process + iFs.MkDirAll(dbFile); + + // Generate the Db file + dbFile.Append(KLbtDbName); + + // Initialize the Database + TInt error = iDb.Open(iFs, dbFile); + + if ( error == KErrNotFound ) + { + // The Db does not exist. Create the Db file + User::LeaveIfError(iDb.Create(iFs, dbFile)); + CreateTablesInDbL(); + } + else + { + User::LeaveIfError( error ); + } + + // Successfully opened db + iIsDbOpened = ETrue; + + // Create the Db Operation Active Object + iDbOperation = CLbtDbOperationAO::NewL(iDb, this); + + // Allocate the SQL Query String + iSqlQuery = HBufC::NewL(KMaxSqlQueryLength); + + iObserver = NULL; + + // List the set of all enabled and valid triggers + RDbView view; + TPtr sql = iSqlQuery->Des(); + sql.Zero(); + sql.Append( KSelect ); + sql.Append( KSelectAllFields ); + sql.Append( KFrom ); + sql.Append( KTriggersTable ); + sql.Append( KWhere ); + sql.Append( KLbtDbFieldValidity ); + sql.Append( KLike ); + sql.AppendNum( TLbtTriggerDynamicInfo::EValid ); + sql.Append( KAnd ); + sql.Append( KLbtDbFieldState ); + sql.Append( KLike ); + sql.AppendNum( CLbtTriggerEntry::EStateEnabled ); + + CleanupClosePushL( view ); + User::LeaveIfError( iDbOperation->ExecuteSyncQuery( view, sql ) ); + iCountOfEnabledAndValidTrigger = view.CountL(); + CleanupStack::PopAndDestroy(1); // view + } + + +// --------------------------------------------------------------------------- +// Create the Table in the Database as part of initialization of Container +// --------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::CreateTablesInDbL( ) + { + FUNC_ENTER("CLbtDbTriggersManager::CreateTablesInDbL"); + CreateCommonTriggerAttributesTableL(); + CreateCoordinateTriggersTableL(); + CreateCellTriggersTableL(); + CreateHybridTriggersTableL(); + } + + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CreateCommonTriggerAttributesTableL +// -------------------------------------------------------------------------------------------- +void CLbtDbTriggersManager::CreateCommonTriggerAttributesTableL() + { + CDbColSet* triggerColSet = CDbColSet::NewLC(); + + // Id + triggerColSet->AddL(TDbCol(KLbtDbFieldId, EDbColInt64)); + + // Name + triggerColSet->AddL(TDbCol(KLbtDbFieldName, EDbColText16, KLbtMaxNameLength - 1)); + + // Trigger Type + triggerColSet->AddL(TDbCol(KLbtDbFieldType, EDbColInt8)); + + // direction of Trigger (Entry type or Exit type) + triggerColSet->AddL(TDbCol(KLbtDbFieldDirection, EDbColInt8)); + + + // SID of the Trigger Creator + triggerColSet->AddL(TDbCol(KLbtDbFieldOwnerSid, EDbColUint32)); + + // SID of the Manager UI for this trigger + triggerColSet->AddL(TDbCol(KLbtDbFieldManagerUiSid, EDbColUint32)); + + // Time to rearm a trigger + triggerColSet->AddL(TDbCol(KLbtDbFieldRearmTime, EDbColInt32)); + + // SID of the trigger handling process + triggerColSet->AddL(TDbCol(KLbtDbFieldStartupSid, EDbColUint32)); + + // Absolute path of the trigger handling process + triggerColSet->AddL(TDbCol(KLbtDbFieldStartupPath, EDbColText16)); + + // Commandline parameters for the trigger handling process + triggerColSet->AddL(TDbCol(KLbtDbFieldStartupCommandLine, EDbColText16)); + + // State of the trigger + triggerColSet->AddL(TDbCol(KLbtDbFieldState, EDbColInt8)); + + // Bool for trigger fire event + triggerColSet->AddL(TDbCol(KLbtDbFieldIsTriggerFired, EDbColBit)); + + // The distance of this trigger from the last acquired location in strategy + triggerColSet->AddL(TDbCol(KLbtDbFieldDistanceToLastLocation, EDbColReal32)); + + // Validity of the trigger + triggerColSet->AddL(TDbCol(KLbtDbFieldValidity, EDbColInt8)); + + // Trigger Fire on creation flag. + triggerColSet->AddL(TDbCol(KLbtDbFieldIsTriggerFireOnCreation, EDbColBit)); + + // Trigger Area type ( Cell/Circular) + triggerColSet->AddL(TDbCol(KLbtDbTriggerAreaType, EDbColInt8)); + + User::LeaveIfError( iDb.CreateTable( KTriggersTable, *triggerColSet ) ); + + // Create index key set based on Trigger Id + CDbKey* index = CDbKey::NewLC(); + index->AddL(TDbKeyCol(KLbtDbFieldId)); + index->AddL(TDbKeyCol(KLbtDbFieldOwnerSid)); + + User::LeaveIfError(iDb.CreateIndex(KTriggersIndexId, KTriggersTable, *index)); + CleanupStack::PopAndDestroy( 2 ); // index & triggerColSet + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CreateCoordinateTriggersTableL +// -------------------------------------------------------------------------------------------- +void CLbtDbTriggersManager::CreateCoordinateTriggersTableL() + { + CDbColSet* circTriggerColSet = CDbColSet::NewLC(); + + // Id + circTriggerColSet->AddL(TDbCol(KLbtCircTrigDbFieldId, EDbColInt64)); + // Trigger Condition center latitude + circTriggerColSet->AddL(TDbCol(KLbtDbFieldCenterLat, EDbColReal64)); + + // Trigger Condition center longitude + circTriggerColSet->AddL(TDbCol(KLbtDbFieldCenterLong, EDbColReal64)); + + // Trigger Condition radius + circTriggerColSet->AddL(TDbCol(KLbtDbFieldRadius, EDbColReal64)); + + // Trigger Condition Hysteresis radius + circTriggerColSet->AddL(TDbCol(KLbtDbFieldHysteresis, EDbColReal64)); + + // The Square approximation of the trigger condition area. Used by + // supervision for better supervision alogrithm. + circTriggerColSet->AddL(TDbCol(KLbtDbFieldAreaLeft, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldAreaRight, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldAreaTop, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldAreaBottom, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldTriggerFiredLat, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldTriggerFiredLong, EDbColReal64)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldTriggerFiredAlt, EDbColReal32)); + circTriggerColSet->AddL(TDbCol(KLbtDbFieldTriggerFiredHorizAcc, EDbColReal32)); + + circTriggerColSet->AddL(TDbCol(KLbtDbFieldTriggerFiredVertAcc, EDbColReal32)); + + // Cell id stream for cell ids of the area. Hybrid info + circTriggerColSet->AddL(TDbCol(KLbtDbFieldCellIdStream, EDbColLongText8)); + User::LeaveIfError( iDb.CreateTable( KCircularTriggersTable, *circTriggerColSet ) ); + + // Create index key set based on Trigger Id + CDbKey* circindex = CDbKey::NewLC(); + circindex->AddL( TDbKeyCol(KLbtCircTrigDbFieldId) ); + + User::LeaveIfError( iDb.CreateIndex(KCircTriggersIndexId, KCircularTriggersTable, *circindex) ); + CleanupStack::PopAndDestroy( 2 ); // circindex & circTriggerColSet + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CreateCellTriggersTableL +// -------------------------------------------------------------------------------------------- +void CLbtDbTriggersManager::CreateCellTriggersTableL( ) + { + CDbColSet* cellTriggerColSet = CDbColSet::NewLC(); + + // Cell Based Triggering : Create new col set for cell triggers and add fields + + // Id + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbFieldId, EDbColInt64)); + + // MCC + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbCountryCode, EDbColUint32)); + + // MNC + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbNetworkId, EDbColUint32)); + + // Network Type (GSM/WCDMA) + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbNetworkType, EDbColInt8)); + + // LAC + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbLAC, EDbColUint32)); + + // Cell ID + cellTriggerColSet->AddL(TDbCol(KLbtCellTrigDbCellId, EDbColUint32)); + + User::LeaveIfError( iDb.CreateTable( KCellTriggersTable, *cellTriggerColSet ) ); + CleanupStack::PopAndDestroy( cellTriggerColSet ); + + // Create index key set based on Trigger Id + CDbKey* cellindex = CDbKey::NewLC(); + cellindex->AddL(TDbKeyCol(KLbtCellTrigDbFieldId)); + + User::LeaveIfError(iDb.CreateIndex(KCellTriggersIndexId, KCellTriggersTable, *cellindex)); + CleanupStack::PopAndDestroy(cellindex); + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CreateHybridTriggersTableL +// -------------------------------------------------------------------------------------------- +void CLbtDbTriggersManager::CreateHybridTriggersTableL() + { + // Hybrid Triggers table : Create new column set + CDbColSet* hybridTriggerColSet = CDbColSet::NewLC(); + + // Id + hybridTriggerColSet->AddL( TDbCol(KLbtHybridTrigDbFieldId, EDbColUint32) ); + + // Hybrid area base stream + hybridTriggerColSet->AddL( TDbCol(KLbtHybridDataStream, EDbColLongText8) ); + + User::LeaveIfError( iDb.CreateTable( KHybridTriggersTable, *hybridTriggerColSet ) ); + CleanupStack::PopAndDestroy( hybridTriggerColSet ); + + // Create index key set based on Trigger Id + CDbKey* cellindex = CDbKey::NewLC(); + cellindex->AddL( TDbKeyCol(KLbtHybridTrigDbFieldId) ); + + User::LeaveIfError( iDb.CreateIndex(KHybridTriggersIndexId, KHybridTriggersTable, *cellindex) ); + CleanupStack::PopAndDestroy(cellindex); + } + +// -------------------------------------------------------------------------------------------- +// CLbtDbTriggersManager::CreateTriggerInViewL +// -------------------------------------------------------------------------------------------- +void CLbtDbTriggersManager::CreateTriggerInViewL() + { + FUNC_ENTER("CLbtDbTriggersManager::CreateTriggerInViewL"); + + CLbtStartupTrigger* trigger = static_cast(iEntry->TriggerEntry()); + TLbtTriggerDynamicInfo* dynInfo = iEntry->DynInfo(); + CLbtExtendedTriggerInfo* extdInfo = iEntry->ExtendedTriggerInfo(); + CLbtTriggerConditionArea* cond = static_cast(trigger->GetCondition()); + CLbtGeoAreaBase * areaBase = cond->TriggerArea(); + CLbtGeoCircle* area = static_cast(cond->TriggerArea()); + + // Insert a Row in the View + iView.InsertL(); // Insert a row. Column order matches sql select statement + + /* Cell Based Triggering : add fields in the various views based on the field values*/ + iView.SetColL( ELbtDbFieldId, static_cast(trigger->Id()) ); + iView.SetColL( ELbtDbFieldName, trigger->Name() ); + iView.SetColL( ELbtDbFieldType, static_cast(trigger->Type()) ); + iView.SetColL( ELbtDbFieldDirection, static_cast((cond->Direction())) ); + iView.SetColL( ELbtDbFieldOwnerSid, extdInfo->OwnerSid().iId ); + iView.SetColL( ELbtDbFieldManagerUiSid, static_cast(trigger->ManagerUi().iUid) ); + iView.SetColL( ELbtDbFieldRearmTime, trigger->TimeToRearm() ); + + HBufC* startupProcFile = HBufC::NewLC( KMaxFileName ); + TPtr startupFile = startupProcFile->Des(); + TSecureId startupProcSid; + trigger->GetProcessId( startupFile, startupProcSid ); + iView.SetColL( ELbtDbFieldStartupSid, startupProcSid ); + iView.SetColL( ELbtDbFieldStartupPath, *startupProcFile ); + CleanupStack::PopAndDestroy( startupProcFile ); + + iView.SetColL( ELbtDbFieldStartupCommandLine, trigger->CommandLine() ); + iView.SetColL( ELbtDbFieldState, trigger->State() ); + iView.SetColL(ELbtDbFieldIsTriggerFired, extdInfo->IsTriggerFired()); + iView.SetColL(ELbtDbFieldDistanceToLastLocation, static_cast(0.0) ); + iView.SetColL( ELbtDbFieldValidity, static_cast(dynInfo->iValidity) ); + iView.SetColL( ELbtDbFieldIsTriggerFireOnCreation, extdInfo->IsTriggerFireOnCreation() ); + + /* add local enum */ + iView.SetColL(ELbtDbTriggerAreaType,static_cast(areaBase->Type() )); + + iView.PutL(); // Complete insertion + iView.Close(); + + switch(areaBase->Type()) + { + case CLbtGeoAreaBase::ECircle: + { + AddGeoCircleIntoDbL(trigger); + break; + } + case CLbtGeoAreaBase::ECellular: + { + AddGeoCellIntoDbL(trigger); + break; + } + case CLbtGeoAreaBase::EHybrid: + { + AddGeoHybridIntoDbL(trigger); + break; + } + default: + { + break; + } + } + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::GetCountOfEnabledAndValidTriggers +//--------------------------------------------------------------------------- +// +TInt CLbtDbTriggersManager::GetCountOfEnabledAndValidTriggers() + { + return iCountOfEnabledAndValidTrigger; + } + + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::SetTimeTillCompaction +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::SetTimeTillCompaction(TTime aTime) + { + iTimeTillCompaction = aTime; + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::IsStoreBusy +//--------------------------------------------------------------------------- +// +TBool CLbtDbTriggersManager::IsStoreBusy() + { + return iDbOperation->IsCompactionOngoing(); + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::SetStoreChangeObserver +//--------------------------------------------------------------------------- +// +void CLbtDbTriggersManager::SetStoreChangeObserver(MLbtTriggerStoreObserver* aObserver) + { + iObserver = aObserver; + } + +//--------------------------------------------------------------------------- +// CLbtDbTriggersManager::CancelCurrentOperation +//--------------------------------------------------------------------------- +// +TInt CLbtDbTriggersManager::CancelCurrentOperation() + { + TInt error = KErrCancel; + switch( iCurrentOperation ) + { + case EDbOpDeleteTriggers: + { + if( !iView.AtEnd() && !iView.AtBeginning() ) + { + error = KLbtErrPartial; + } + break; + } + case EDbOpUpdateTriggersState: + { + if( !iView.AtEnd() && !iView.AtBeginning() ) + { + error = KLbtErrPartial; + } + break; + } + } + CompleteClientRequest( KErrCancel ); + Cancel(); + return error; + } + +// end of file + +