diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/server/src/agsinstanceiterator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendar/server/src/agsinstanceiterator.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,452 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "agsinstanceiterator.h" +#include "agsinstancesorter.h" +#include "agmfilter.h" +#include "agmsortcriteria.h" +#include "agsentrymodel.h" +#include "agssortinstance.h" +#include "agmdate.h" +#include "agmpanic.h" +#include "agmsimpleentry.h" +#include "agsfilemanager.h" + +const TInt KMaxCachedNumber = 1000; //The maxium number of instance IDs cahed in the server side iterator +const TInt KInitialInstanceCount = -1; +const TInt KInstanceArrayGranularity = 16; + +// CAgsInstanceIterator // + +CAgsInstanceIterator::CAgsInstanceIterator(TInt aIteratorId, CAgnServFileMgr& aFileManager) + :iIteratorId(aIteratorId), + iInstanceCount(KInitialInstanceCount), + iCachedOffset(0), + iFileManager(aFileManager) + { + } + +CAgsInstanceIterator::~CAgsInstanceIterator() + { + iCachedInstances.Close(); + delete iFindParams; + delete iSorter; + iModels.Close();//Doesn't own the elements of the array. + } + +CAgsInstanceIterator* CAgsInstanceIterator::NewLC(TInt aIteratorId, TFindInstanceParams* aFindParams, CAgnSortCriteria* aSortCriteria, + const RArray& aDefaultTypeOrder, RArray& aFileIds, CAgnServFileMgr& aFileManager) + { + CAgsInstanceIterator* self = new (ELeave) CAgsInstanceIterator(aIteratorId, aFileManager); + CleanupStack::PushL(self); + self->ConstructL(aSortCriteria, aDefaultTypeOrder, aFindParams, aFileIds); + return self; + } + +void CAgsInstanceIterator::ConstructL(CAgnSortCriteria* aSortCriteria, const RArray& aDefaultTypeOrder, TFindInstanceParams* aFindParams, RArray& aFileIds) + { + iFindParams = NULL; + iSorter = NULL; + const TInt count = aFileIds.Count(); + for(TInt ii=0;iiModel()); + } + iSorter = CAgsInstanceSorter::NewL(aSortCriteria, aDefaultTypeOrder); + iFindParams = aFindParams; + } + +void CAgsInstanceIterator::AddInstanceL(TAgnSortInstance& aSortInstance, RArray& aInstances) + { + TAgnInstance instance; + instance.iId = aSortInstance.InstanceIdL(); + instance.iCollectionId = aSortInstance.SimpleEntry().CollectionId(); + aInstances.AppendL(instance); + } + +/** + * Get the instances started after specified index +@param aInstances reference to instance array that will store matched instances +@param aIndex The start index of instance to look for +*/ +void CAgsInstanceIterator::NextInstancesL(RArray& aInstances, TInt aIndex) + { + if(IsCached(aIndex, EFalse)) + { + //The required instances are in cache, so suck out the instances + const TInt KNumber(iFindParams->iNumInstances); + while(0 < iCachedInstances.Count() && aInstances.Count() < KNumber) + { + if(iCachedOffset >= aIndex) + { + aInstances.AppendL(iCachedInstances[0]); + } + iCachedInstances.Remove(0); + ++iCachedOffset; + } + } + else + { + //Either the cache is empty or out of range to aIndex so reloading all instance is needed + + //reset cache + iCachedInstances.Reset(); + iCachedOffset = 0; + + //Fetching and sorting instances + CArrayFixSeg* instances = FindSortedInstanceLC(); + + const TInt KInstanceCount(instances->Count()); + if(iInstanceCount != KInstanceCount) + { + iInstanceCount = KInstanceCount; + } + + if(aIndex < KInstanceCount) + { + //get rid of the instances that are before aIndex + instances->Delete(0, aIndex); + + //appending the instances + const TInt KMaxCount = (instances->Count() > iFindParams->iNumInstances) ? iFindParams->iNumInstances : instances->Count(); + for(TInt index = 0; index < KMaxCount; index++) + { + AddInstanceL((*instances)[index], aInstances); + } + + if(KMaxCount == iFindParams->iNumInstances) + { + //cache the rest instances which are fetched and indexed after aIndex + instances->Delete(0, KMaxCount); + const TInt KCachedCount = (instances->Count() > KMaxCachedNumber) ? KMaxCachedNumber : instances->Count(); + + for(TInt index = 0; index < KCachedCount; index++) + { + AddInstanceL((*instances)[index], iCachedInstances); + } + + iCachedOffset = aIndex + KMaxCount; + } + } + + CleanupStack::PopAndDestroy(instances); + } + } + +/** + * Get the instances indexed before aIndex +@param aInstances reference to instance array that will store matched instances +@param aIndex The end index of instances to look for +*/ +void CAgsInstanceIterator::PreviousInstancesL(RArray& aInstances, TInt aIndex) + { + if(IsCached(aIndex, ETrue)) + { + //The required instances are in cache, so suck out the instances + const TInt KNumber(iFindParams->iNumInstances); + TInt startIndex = (aIndex > KNumber) ? (aIndex - KNumber) : 0; + startIndex -= iCachedOffset; + + while(iCachedInstances.Count() > startIndex) + { + if(aInstances.Count() < KNumber) + { + aInstances.AppendL(iCachedInstances[startIndex]); + } + iCachedInstances.Remove(startIndex); + } + } + else + { + //Either the cache is empty or out of range to aIndex so reloading all instance is needed + + //reset cache + iCachedInstances.Reset(); + iCachedOffset = 0; + + //reloading instances + CArrayFixSeg* instances = FindSortedInstanceLC(); + + const TInt KInstanceCount(instances->Count()); + if(iInstanceCount != KInstanceCount) + { + iInstanceCount = KInstanceCount; + } + + //Adding the instances indexed before aIndex to aInstances + TInt startIndex = (aIndex > iFindParams->iNumInstances) ? aIndex - iFindParams->iNumInstances : 0; + TInt endIndex = (aIndex < instances->Count()) ? aIndex : instances->Count() - 1; + + __ASSERT_DEBUG(endIndex >= startIndex, Panic(EAgmErrOutsideArrayRange)); + + for(TInt index = startIndex; index <= endIndex; index++) + { + AddInstanceL((*instances)[index], aInstances); + } + + //Cache in the rest instances + iCachedOffset = (startIndex > KMaxCachedNumber) ? startIndex - KMaxCachedNumber : 0; + + for(TInt index = iCachedOffset; index < startIndex; index++) + { + AddInstanceL((*instances)[index], iCachedInstances); + } + + CleanupStack::PopAndDestroy(instances); + } + } + +/** + * Get the instances started after specified index +@return The number of overall instances which shall be contained in the iterator +*/ +TInt CAgsInstanceIterator::CountL() + { + if(iInstanceCount == KInitialInstanceCount) + { + CArrayFixSeg* instances = NULL; + if(iCachedInstances.Count() == 0 && iCachedOffset == 0) + { + instances = FindSortedInstanceLC(); + //cache is empty so just cached in the first part of instances + const TInt KCachedCount = (iInstanceCount > KMaxCachedNumber) ? KMaxCachedNumber : iInstanceCount; + + for(TInt index = 0; index < KCachedCount; index++) + { + AddInstanceL((*instances)[index], iCachedInstances); + } + } + else + { + const TInt count = iModels.Count(); + instances = new (ELeave) CArrayFixSeg(KInstanceArrayGranularity); + CleanupStack::PushL(instances); + for(TInt ii =0; iiFindInstancesL(*instances, *iFindParams); + } + } + iInstanceCount = instances->Count(); + CleanupStack::PopAndDestroy(instances); + } + + return iInstanceCount; + } + +CArrayFixSeg* CAgsInstanceIterator::FindSortedInstanceLC() + { + const TInt count = iModels.Count(); + CArrayFixSeg* instances = new (ELeave) CArrayFixSeg(KInstanceArrayGranularity); + CleanupStack::PushL(instances); + + for(TInt ii =0; iiAgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + iModels[ii]->FindInstancesL(*instances, *iFindParams); + } + iSorter->SortL(*instances); + return instances; + } + + +TInt CAgsInstanceIterator::LocateIndexL(TAgnInstance& aInstanceId) + { + __ASSERT_DEBUG(!aInstanceId.iId.IsNullId(), Panic(EAgmErrInstanceIteratorLocatedIndexFault)); + + //We are assuming the function is called just after the iterator is created + __ASSERT_DEBUG(iInstanceCount == KInitialInstanceCount && + iCachedInstances.Count() == 0 && + iCachedOffset == 0, Panic(EAgmErrInstanceIteratorLocatedIndexFault)); + + //Find all instances in the iterator and sort them + CArrayFixSeg* instances = FindSortedInstanceLC(); + iInstanceCount = instances->Count(); + + //Find the index of the given instance id. + CAgnEntryModel* model = iFileManager.GetFileL(aInstanceId.iCollectionId)->Model(); + + const CAgnSimpleEntry* searchFromEntry = model->GetSimpleEntryFromIndexes(aInstanceId.iId); + const_cast(searchFromEntry)->SetCollectionId(aInstanceId.iCollectionId); + + TAgnSortInstance searchFromInstance(*searchFromEntry); + + searchFromInstance.SetL(aInstanceId.iId.Date().LocalL(), iFindParams->iUndatedTodoTimeLocal); + + //the search from instance must match the filter settings + __ASSERT_ALWAYS(searchFromInstance.CheckStartAndEndDateOverlap(*iFindParams), User::Leave(KErrNotFound)); + + TInt foundIndex = iSorter->FindL(*instances, searchFromInstance); + + //cache the instances on server side + TInt endIndex; + if(iInstanceCount > KMaxCachedNumber) + { + //The instances are more than the size of cache so just store those after the given instance + iCachedOffset = foundIndex; + endIndex = (iInstanceCount - foundIndex) > KMaxCachedNumber ? (foundIndex + KMaxCachedNumber) : iInstanceCount; + } + else + { + //cache all instances + iCachedOffset = 0; + endIndex = iInstanceCount; + } + + for(TInt index = iCachedOffset; index < endIndex; index++) + { + AddInstanceL((*instances)[index], iCachedInstances); + } + + CleanupStack::PopAndDestroy(instances); + + return foundIndex; + } + + +/** + * Check if the instance at aIndex is cached and the cached instances are + * enough for fetch(more than iFindParams->iNumInstances) +*/ +TBool CAgsInstanceIterator::IsCached(TInt aIndex, TBool aPrevious) const + { + const TInt KNumber(iFindParams->iNumInstances); + TInt startIndex(aIndex); + if(aPrevious) + { + startIndex = (aIndex > KNumber) ? (aIndex - KNumber) : 0; + } + + return ((iCachedOffset <= startIndex) && (iCachedInstances.Count() >= KNumber)); + } + +// CAgsInstanceIteratorMgr // + +CAgsInstanceIteratorMgr* CAgsInstanceIteratorMgr::NewL() + { + CAgsInstanceIteratorMgr* self = new (ELeave) CAgsInstanceIteratorMgr(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CAgsInstanceIteratorMgr::CAgsInstanceIteratorMgr() + :iNextAvailableId(0) + { + } + +void CAgsInstanceIteratorMgr::ConstructL() + { + //buid up the default sort order for sorting entry type + iDefaultTypeOrder.AppendL(CCalEntry::ETodo); + iDefaultTypeOrder.AppendL(CCalEntry::EAnniv); + iDefaultTypeOrder.AppendL(CCalEntry::EEvent); + iDefaultTypeOrder.AppendL(CCalEntry::EAppt); + iDefaultTypeOrder.AppendL(CCalEntry::EReminder); + } + +CAgsInstanceIteratorMgr::~CAgsInstanceIteratorMgr() + { + //release all iterators + TInt KCount(iIteratorList.Count()); + for(TInt count = 0; count < KCount; count++) + { + delete iIteratorList[count]; + } + iIteratorList.Close(); + iDefaultTypeOrder.Close(); + } + +/** + * Create an iterator +@param aFindParams Finding instance settings/search criteria +@param aSortCriteria Sort criteria for the iterator +@return Iterator id assigned to the new iterator +*/ +TInt CAgsInstanceIteratorMgr::CreateIteratorL(TFindInstanceParams* aFindParams, CAgnSortCriteria* aSortCriteria, RArray& aFileIds, CAgnServFileMgr& aFileManager) + { + CAgsInstanceIterator* iterator = CAgsInstanceIterator::NewLC(iNextAvailableId, aFindParams, aSortCriteria, iDefaultTypeOrder, aFileIds, aFileManager); + iIteratorList.AppendL(iterator); + CleanupStack::Pop(iterator); + return iNextAvailableId++; + } + +TInt CAgsInstanceIteratorMgr::FindIteratorById(TInt aIteratorId) const + { + TInt ret(KErrNotFound); + const TInt KCount(iIteratorList.Count()); + for(TInt index = 0; index < KCount; index++) + { + if(iIteratorList[index]->IteratorId() == aIteratorId) + { + ret = index; + break; + } + } + return ret; + } + + +/** + * Remove and destroy and remove an iterator +@param Iterator id of the iterator to be destroyed +*/ +void CAgsInstanceIteratorMgr::DestroyIteratorL(TInt aIteratorId) + { + TInt index = FindIteratorById(aIteratorId); + User::LeaveIfError(index); + + CAgsInstanceIterator* iterator = iIteratorList[index]; + iIteratorList.Remove(index); + delete iterator; + } + +void CAgsInstanceIteratorMgr::NextInstancesL(TInt aIteratorId, RArray& aInstances, TInt aStartIndex) + { + TInt index = FindIteratorById(aIteratorId); + User::LeaveIfError(index); + + iIteratorList[index]->NextInstancesL(aInstances, aStartIndex); + } + +void CAgsInstanceIteratorMgr::PreviousInstancesL(TInt aIteratorId, RArray& aInstances, TInt aLastIndex) + { + TInt index = FindIteratorById(aIteratorId); + User::LeaveIfError(index); + + iIteratorList[index]->PreviousInstancesL(aInstances, aLastIndex); + } + +TInt CAgsInstanceIteratorMgr::CountL(TInt aIteratorId) + { + TInt index = FindIteratorById(aIteratorId); + User::LeaveIfError(index); + + return iIteratorList[index]->CountL(); + } + +TInt CAgsInstanceIteratorMgr::LocateIndexL(TInt aIteratorId, TAgnInstance& aInstanceId) + { + TInt index = FindIteratorById(aIteratorId); + User::LeaveIfError(index); + + return iIteratorList[index]->LocateIndexL(aInstanceId); + } + +