pimappservices/calendar/server/src/agsinstanceiterator.cpp
changeset 0 f979ecb2b13e
child 18 c198609911f9
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "agsinstanceiterator.h"
       
    17 #include "agsinstancesorter.h"
       
    18 #include "agmfilter.h"
       
    19 #include "agmsortcriteria.h"
       
    20 #include "agsentrymodel.h"
       
    21 #include "agssortinstance.h"
       
    22 #include "agmdate.h"
       
    23 #include "agmpanic.h"
       
    24 #include "agmsimpleentry.h"
       
    25 #include "agsfilemanager.h"
       
    26 
       
    27 const TInt KMaxCachedNumber = 1000; //The maxium number of instance IDs cahed in the server side iterator
       
    28 const TInt KInitialInstanceCount = -1;
       
    29 const TInt KInstanceArrayGranularity = 16;
       
    30 
       
    31 // CAgsInstanceIterator //
       
    32 
       
    33 CAgsInstanceIterator::CAgsInstanceIterator(TInt aIteratorId,  CAgnServFileMgr&	aFileManager)
       
    34 	:iIteratorId(aIteratorId),
       
    35 	iInstanceCount(KInitialInstanceCount),
       
    36 	iCachedOffset(0),
       
    37 	iFileManager(aFileManager)
       
    38 	{
       
    39 	}
       
    40 
       
    41 CAgsInstanceIterator::~CAgsInstanceIterator()
       
    42 	{
       
    43 	iCachedInstances.Close();
       
    44 	delete iFindParams;
       
    45 	delete iSorter;
       
    46 	iModels.Close();//Doesn't own the elements of the array.
       
    47 	}
       
    48 
       
    49 CAgsInstanceIterator* CAgsInstanceIterator::NewLC(TInt aIteratorId, TFindInstanceParams* aFindParams, CAgnSortCriteria* aSortCriteria, 
       
    50 								const RArray<CCalEntry::TType>& aDefaultTypeOrder, RArray<TInt64>& aFileIds, CAgnServFileMgr&	aFileManager)
       
    51 	{
       
    52 	CAgsInstanceIterator* self = new (ELeave) CAgsInstanceIterator(aIteratorId, aFileManager);
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL(aSortCriteria, aDefaultTypeOrder, aFindParams, aFileIds);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 void CAgsInstanceIterator::ConstructL(CAgnSortCriteria* aSortCriteria, const RArray<CCalEntry::TType>& aDefaultTypeOrder, TFindInstanceParams* aFindParams, RArray<TInt64>& aFileIds)
       
    59 	{
       
    60 	iFindParams = NULL;
       
    61 	iSorter = NULL;
       
    62 	const TInt count = aFileIds.Count();
       
    63 	for(TInt ii=0;ii<count;++ii)
       
    64 		{
       
    65 		CAgnServFile* file = iFileManager.GetFileL(aFileIds[ii]);
       
    66 		iModels.AppendL(file->Model());
       
    67 		}
       
    68 	iSorter = CAgsInstanceSorter::NewL(aSortCriteria, aDefaultTypeOrder);
       
    69 	iFindParams = aFindParams;
       
    70 	}
       
    71 
       
    72 void CAgsInstanceIterator::AddInstanceL(TAgnSortInstance& aSortInstance, RArray<TAgnInstance>& aInstances)
       
    73 	{
       
    74 	TAgnInstance instance;
       
    75 	instance.iId = aSortInstance.InstanceIdL();
       
    76 	instance.iCollectionId = aSortInstance.SimpleEntry().CollectionId();
       
    77 	aInstances.AppendL(instance);
       
    78 	}
       
    79 
       
    80 /**
       
    81  * Get the instances started after specified index
       
    82 @param aInstances reference to instance array that will store matched instances
       
    83 @param aIndex The start index of instance to look for
       
    84 */
       
    85 void CAgsInstanceIterator::NextInstancesL(RArray<TAgnInstance>& aInstances, TInt aIndex)
       
    86 	{
       
    87 	if(IsCached(aIndex, EFalse))
       
    88 		{
       
    89 		//The required instances are in cache, so suck out the instances
       
    90 		const TInt KNumber(iFindParams->iNumInstances);
       
    91 		while(0 < iCachedInstances.Count() && aInstances.Count() < KNumber)
       
    92 			{
       
    93 			if(iCachedOffset >= aIndex)
       
    94 				{
       
    95 				aInstances.AppendL(iCachedInstances[0]);
       
    96 				}
       
    97 			iCachedInstances.Remove(0);
       
    98 			++iCachedOffset;
       
    99 			}
       
   100 		}
       
   101 	else
       
   102 		{
       
   103 		//Either the cache is empty or out of range to aIndex so reloading all instance is needed
       
   104 		
       
   105 		//reset cache
       
   106 		iCachedInstances.Reset();
       
   107 		iCachedOffset = 0; 
       
   108 		
       
   109 		//Fetching and sorting instances
       
   110 		CArrayFixSeg<TAgnSortInstance>* instances = FindSortedInstanceLC();
       
   111 		
       
   112 		const TInt KInstanceCount(instances->Count());
       
   113 		if(iInstanceCount != KInstanceCount)
       
   114 			{
       
   115 			iInstanceCount = KInstanceCount;
       
   116 			}
       
   117 		
       
   118 		if(aIndex < KInstanceCount)
       
   119 			{
       
   120 			//get rid of the instances that are before aIndex
       
   121 			instances->Delete(0, aIndex);
       
   122 			
       
   123 			//appending the instances
       
   124 			const TInt KMaxCount = (instances->Count() > iFindParams->iNumInstances) ? iFindParams->iNumInstances : instances->Count();
       
   125 			for(TInt index = 0; index < KMaxCount; index++)
       
   126 				{
       
   127 				AddInstanceL((*instances)[index], aInstances);
       
   128 				}
       
   129 			
       
   130 			if(KMaxCount == iFindParams->iNumInstances)
       
   131 				{
       
   132 				//cache the rest instances which are fetched and indexed after aIndex 
       
   133 				instances->Delete(0, KMaxCount);
       
   134 				const TInt KCachedCount = (instances->Count() > KMaxCachedNumber) ? KMaxCachedNumber : instances->Count();  
       
   135 				
       
   136 				for(TInt index = 0; index < KCachedCount; index++)
       
   137 					{
       
   138 					AddInstanceL((*instances)[index], iCachedInstances);
       
   139 					}
       
   140 				
       
   141 				iCachedOffset = aIndex + KMaxCount;
       
   142 				}
       
   143 			}
       
   144 		
       
   145 		CleanupStack::PopAndDestroy(instances);
       
   146 		}
       
   147 	}
       
   148 
       
   149 /**
       
   150  * Get the instances indexed before aIndex
       
   151 @param aInstances reference to instance array that will store matched instances
       
   152 @param aIndex The end index of instances to look for
       
   153 */
       
   154 void CAgsInstanceIterator::PreviousInstancesL(RArray<TAgnInstance>& aInstances, TInt aIndex)
       
   155 	{
       
   156 	if(IsCached(aIndex, ETrue))
       
   157 		{
       
   158 		//The required instances are in cache, so suck out the instances
       
   159 		const TInt KNumber(iFindParams->iNumInstances);
       
   160 		TInt startIndex = (aIndex > KNumber) ? (aIndex - KNumber) : 0;   
       
   161 		startIndex -= iCachedOffset;   
       
   162 		
       
   163 		while(iCachedInstances.Count() > startIndex)
       
   164 			{
       
   165 			if(aInstances.Count() < KNumber)
       
   166 				{
       
   167 				aInstances.AppendL(iCachedInstances[startIndex]);
       
   168 				}
       
   169 			iCachedInstances.Remove(startIndex);
       
   170 			}
       
   171 		}
       
   172 	else
       
   173 		{
       
   174 		//Either the cache is empty or out of range to aIndex so reloading all instance is needed
       
   175 		
       
   176 		//reset cache
       
   177 		iCachedInstances.Reset();
       
   178 		iCachedOffset = 0;
       
   179 		
       
   180 		//reloading instances
       
   181 		CArrayFixSeg<TAgnSortInstance>* instances = FindSortedInstanceLC();
       
   182 
       
   183 		const TInt KInstanceCount(instances->Count());
       
   184 		if(iInstanceCount != KInstanceCount)
       
   185 			{
       
   186 			iInstanceCount = KInstanceCount;
       
   187 			}
       
   188 		
       
   189 		//Adding the instances indexed before aIndex to aInstances
       
   190 		TInt startIndex = (aIndex > iFindParams->iNumInstances) ? aIndex - iFindParams->iNumInstances : 0;   	
       
   191 		TInt endIndex = (aIndex < instances->Count()) ? aIndex : instances->Count() - 1;  
       
   192 		
       
   193 		__ASSERT_DEBUG(endIndex >= startIndex, Panic(EAgmErrOutsideArrayRange));
       
   194 		
       
   195 		for(TInt index = startIndex; index <= endIndex; index++)
       
   196 			{
       
   197 			AddInstanceL((*instances)[index], aInstances);
       
   198 			}
       
   199 		
       
   200 		//Cache in the rest instances 
       
   201 		iCachedOffset = (startIndex > KMaxCachedNumber) ? startIndex - KMaxCachedNumber : 0;
       
   202 		
       
   203 		for(TInt index = iCachedOffset; index < startIndex; index++)
       
   204 			{
       
   205 			AddInstanceL((*instances)[index], iCachedInstances);
       
   206 			}
       
   207 		
       
   208 		CleanupStack::PopAndDestroy(instances);
       
   209 		}
       
   210 	}
       
   211 
       
   212 /**
       
   213  * Get the instances started after specified index
       
   214 @return The number of overall instances which shall be contained in the iterator  
       
   215 */
       
   216 TInt CAgsInstanceIterator::CountL()
       
   217 	{
       
   218 	if(iInstanceCount == KInitialInstanceCount)
       
   219 		{
       
   220 		CArrayFixSeg<TAgnSortInstance>* instances = NULL;
       
   221 		if(iCachedInstances.Count() == 0 && iCachedOffset == 0)
       
   222 			{
       
   223 			instances = FindSortedInstanceLC();
       
   224 			//cache is empty so just cached in the first part of instances
       
   225 			const TInt KCachedCount = (iInstanceCount > KMaxCachedNumber) ? KMaxCachedNumber : iInstanceCount;  
       
   226 			
       
   227 			for(TInt index = 0; index < KCachedCount; index++)
       
   228 				{
       
   229 				AddInstanceL((*instances)[index], iCachedInstances);
       
   230 				}
       
   231 			}
       
   232 		else
       
   233 			{
       
   234 			const TInt count = iModels.Count();
       
   235 			instances = new (ELeave) CArrayFixSeg<TAgnSortInstance>(KInstanceArrayGranularity);
       
   236 			CleanupStack::PushL(instances);
       
   237 			for(TInt ii =0; ii<count; ++ii )
       
   238 				{
       
   239 				iModels[ii]->FindInstancesL(*instances, *iFindParams);
       
   240 				}
       
   241 			}
       
   242 		iInstanceCount = instances->Count();
       
   243 		CleanupStack::PopAndDestroy(instances);
       
   244 		}
       
   245 	
       
   246 	return iInstanceCount; 
       
   247 	}
       
   248 
       
   249 CArrayFixSeg<TAgnSortInstance>* CAgsInstanceIterator::FindSortedInstanceLC()
       
   250 	{
       
   251 	const TInt count = iModels.Count();
       
   252 	CArrayFixSeg<TAgnSortInstance>* instances = new (ELeave) CArrayFixSeg<TAgnSortInstance>(KInstanceArrayGranularity);
       
   253 	CleanupStack::PushL(instances);
       
   254 
       
   255 	for(TInt ii =0; ii<count; ++ii )
       
   256 		{
       
   257 		if(iModels[ii]->AgnServFile().IsLocked())
       
   258 			{
       
   259 			User::Leave(KErrLocked);
       
   260 			}
       
   261 		iModels[ii]->FindInstancesL(*instances, *iFindParams);
       
   262 		}
       
   263 	iSorter->SortL(*instances);
       
   264 	return instances;
       
   265 	}
       
   266 
       
   267 
       
   268 TInt CAgsInstanceIterator::LocateIndexL(TAgnInstance& aInstanceId)
       
   269 	{
       
   270 	__ASSERT_DEBUG(!aInstanceId.iId.IsNullId(), Panic(EAgmErrInstanceIteratorLocatedIndexFault));
       
   271 	
       
   272 	//We are assuming the function is called just after the iterator is created
       
   273 	__ASSERT_DEBUG(iInstanceCount == KInitialInstanceCount && 
       
   274 			       iCachedInstances.Count() == 0 && 
       
   275 			       iCachedOffset == 0, Panic(EAgmErrInstanceIteratorLocatedIndexFault));
       
   276 	
       
   277 	//Find all instances in the iterator and sort them
       
   278 	CArrayFixSeg<TAgnSortInstance>* instances = FindSortedInstanceLC();
       
   279 	iInstanceCount = instances->Count();
       
   280 	
       
   281 	//Find the index of the given instance id.
       
   282 	CAgnEntryModel* model = iFileManager.GetFileL(aInstanceId.iCollectionId)->Model();
       
   283 
       
   284 	const CAgnSimpleEntry* searchFromEntry = model->GetSimpleEntryFromIndexes(aInstanceId.iId);
       
   285 	const_cast<CAgnSimpleEntry*>(searchFromEntry)->SetCollectionId(aInstanceId.iCollectionId);
       
   286 	
       
   287 	TAgnSortInstance searchFromInstance(*searchFromEntry);
       
   288 	
       
   289 	searchFromInstance.SetL(aInstanceId.iId.Date().LocalL(), iFindParams->iUndatedTodoTimeLocal);
       
   290 	
       
   291 	//the search from instance must match the filter settings
       
   292 	__ASSERT_ALWAYS(searchFromInstance.CheckStartAndEndDateOverlap(*iFindParams), User::Leave(KErrNotFound));
       
   293 
       
   294 	TInt foundIndex = iSorter->FindL(*instances, searchFromInstance);
       
   295 	
       
   296 	//cache the instances on server side
       
   297 	TInt endIndex;
       
   298 	if(iInstanceCount > KMaxCachedNumber)
       
   299 		{
       
   300 		//The instances are more than the size of cache so just store those after the given instance
       
   301 		iCachedOffset = foundIndex;
       
   302 		endIndex = (iInstanceCount - foundIndex) > KMaxCachedNumber ? (foundIndex + KMaxCachedNumber) : iInstanceCount; 
       
   303 		}
       
   304 	else
       
   305 		{
       
   306 		//cache all instances
       
   307 		iCachedOffset = 0;
       
   308 		endIndex = iInstanceCount; 
       
   309 		}
       
   310 	
       
   311 	for(TInt index = iCachedOffset; index < endIndex; index++)
       
   312 		{
       
   313 		AddInstanceL((*instances)[index], iCachedInstances);
       
   314 		}
       
   315 
       
   316 	CleanupStack::PopAndDestroy(instances);
       
   317 	
       
   318 	return foundIndex;
       
   319 	}
       
   320 
       
   321 
       
   322 /**
       
   323  * Check if the instance at aIndex is cached and the cached instances are
       
   324  * enough for fetch(more than iFindParams->iNumInstances)
       
   325 */
       
   326 TBool CAgsInstanceIterator::IsCached(TInt aIndex, TBool aPrevious) const
       
   327 	{
       
   328 	const TInt KNumber(iFindParams->iNumInstances);
       
   329 	TInt startIndex(aIndex);
       
   330 	if(aPrevious)
       
   331 		{
       
   332 		startIndex = (aIndex > KNumber) ? (aIndex - KNumber) : 0;   
       
   333 		}
       
   334 	
       
   335 	return ((iCachedOffset <= startIndex) && (iCachedInstances.Count() >= KNumber));
       
   336 	}	
       
   337 
       
   338 // CAgsInstanceIteratorMgr //
       
   339 
       
   340 CAgsInstanceIteratorMgr* CAgsInstanceIteratorMgr::NewL()
       
   341 	{
       
   342 	CAgsInstanceIteratorMgr* self = new (ELeave) CAgsInstanceIteratorMgr();
       
   343 	CleanupStack::PushL(self);
       
   344 	self->ConstructL();
       
   345 	CleanupStack::Pop(self);
       
   346 	return self;
       
   347 	}
       
   348 
       
   349 CAgsInstanceIteratorMgr::CAgsInstanceIteratorMgr()
       
   350 	:iNextAvailableId(0) 
       
   351 	{
       
   352 	}
       
   353 
       
   354 void CAgsInstanceIteratorMgr::ConstructL()
       
   355 	{
       
   356 	//buid up the default sort order for sorting entry type
       
   357 	iDefaultTypeOrder.AppendL(CCalEntry::ETodo);
       
   358 	iDefaultTypeOrder.AppendL(CCalEntry::EAnniv);
       
   359 	iDefaultTypeOrder.AppendL(CCalEntry::EEvent);
       
   360 	iDefaultTypeOrder.AppendL(CCalEntry::EAppt);
       
   361 	iDefaultTypeOrder.AppendL(CCalEntry::EReminder);
       
   362 	}
       
   363 
       
   364 CAgsInstanceIteratorMgr::~CAgsInstanceIteratorMgr()
       
   365 	{
       
   366 	//release all iterators
       
   367 	TInt KCount(iIteratorList.Count());
       
   368 	for(TInt count = 0; count < KCount; count++)
       
   369 		{
       
   370 		delete iIteratorList[count]; 
       
   371 		}	
       
   372 	iIteratorList.Close();
       
   373 	iDefaultTypeOrder.Close();
       
   374 	}
       
   375 
       
   376 /**
       
   377  * Create an iterator
       
   378 @param aFindParams Finding instance settings/search criteria
       
   379 @param aSortCriteria Sort criteria for the iterator
       
   380 @return Iterator id assigned to the new iterator
       
   381 */
       
   382 TInt CAgsInstanceIteratorMgr::CreateIteratorL(TFindInstanceParams* aFindParams, CAgnSortCriteria* aSortCriteria, RArray<TInt64>& aFileIds, CAgnServFileMgr& aFileManager)
       
   383 	{
       
   384 	CAgsInstanceIterator* iterator = CAgsInstanceIterator::NewLC(iNextAvailableId, aFindParams, aSortCriteria, iDefaultTypeOrder, aFileIds, aFileManager);
       
   385 	iIteratorList.AppendL(iterator);
       
   386 	CleanupStack::Pop(iterator);
       
   387 	return iNextAvailableId++; 
       
   388 	}
       
   389 
       
   390 TInt CAgsInstanceIteratorMgr::FindIteratorById(TInt aIteratorId) const
       
   391 	{
       
   392 	TInt ret(KErrNotFound);
       
   393 	const TInt KCount(iIteratorList.Count());
       
   394 	for(TInt index = 0; index < KCount; index++)
       
   395 		{
       
   396 		if(iIteratorList[index]->IteratorId() == aIteratorId)
       
   397 			{
       
   398 			ret = index;
       
   399 			break;
       
   400 			}
       
   401 		}
       
   402 	return ret;
       
   403 	}
       
   404 
       
   405 
       
   406 /**
       
   407  * Remove and destroy and remove an iterator
       
   408 @param Iterator id of the iterator to be destroyed
       
   409 */
       
   410 void CAgsInstanceIteratorMgr::DestroyIteratorL(TInt aIteratorId)
       
   411 	{
       
   412 	TInt index = FindIteratorById(aIteratorId);
       
   413 	User::LeaveIfError(index);
       
   414 	
       
   415 	CAgsInstanceIterator* iterator = iIteratorList[index];
       
   416 	iIteratorList.Remove(index);
       
   417 	delete iterator;
       
   418 	}
       
   419 
       
   420 void CAgsInstanceIteratorMgr::NextInstancesL(TInt aIteratorId, RArray<TAgnInstance>& aInstances, TInt aStartIndex)
       
   421 	{
       
   422 	TInt index = FindIteratorById(aIteratorId);
       
   423 	User::LeaveIfError(index);
       
   424 	
       
   425 	iIteratorList[index]->NextInstancesL(aInstances, aStartIndex);
       
   426 	}
       
   427 	
       
   428 void CAgsInstanceIteratorMgr::PreviousInstancesL(TInt aIteratorId, RArray<TAgnInstance>& aInstances, TInt aLastIndex)
       
   429 	{
       
   430 	TInt index = FindIteratorById(aIteratorId);
       
   431 	User::LeaveIfError(index);
       
   432 	
       
   433 	iIteratorList[index]->PreviousInstancesL(aInstances, aLastIndex);
       
   434 	}
       
   435 
       
   436 TInt CAgsInstanceIteratorMgr::CountL(TInt aIteratorId)
       
   437 	{
       
   438 	TInt index = FindIteratorById(aIteratorId);
       
   439 	User::LeaveIfError(index);
       
   440 	
       
   441 	return iIteratorList[index]->CountL();
       
   442 	}
       
   443 
       
   444 TInt CAgsInstanceIteratorMgr::LocateIndexL(TInt aIteratorId, TAgnInstance& aInstanceId)
       
   445 	{
       
   446 	TInt index = FindIteratorById(aIteratorId);
       
   447 	User::LeaveIfError(index);
       
   448 	
       
   449 	return iIteratorList[index]->LocateIndexL(aInstanceId);
       
   450 	}
       
   451 
       
   452