pimappservices/calendar/server/src/agstzruleindex.cpp
changeset 0 f979ecb2b13e
child 30 d68a4b5d5885
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 2008-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 <vtzrules.h>
       
    17 #include <tz.h>
       
    18 #include "agmentry.h"
       
    19 #include "agmtlsproxy.h"
       
    20 #include "agmtzrules.h"
       
    21 #include "agstzruleindex.h"
       
    22 #include "agmpanic.h"
       
    23 #include "agmrptdef.h"
       
    24 #include "agsfilemanager.h"
       
    25 
       
    26 const TUid KUidAgnSystemTzIndex = {0x10285b96};
       
    27 const TUid KUidAgnImportedTzIndex = {0x10285b97};
       
    28 const TUid KUidAgnTimeStamp = {0x102863fb};
       
    29 
       
    30 const TInt KMinYear = 0;
       
    31 const TInt KMaxYear = 9999;
       
    32 
       
    33 /* ------------------- CAgnTzRuleIndexItem -------------------*/
       
    34 CAgnTzRuleIndexItem::CAgnTzRuleIndexItem(TStreamId aStreamId, CTzRules* aRule) :
       
    35 	iRefCount(1), iTzRules(aRule)
       
    36 	{
       
    37 	iStreamId = aStreamId;
       
    38 	}
       
    39 
       
    40 CAgnTzRuleIndexItem::CAgnTzRuleIndexItem() :
       
    41 	iRefCount(1), iTzRules(NULL)
       
    42 	{
       
    43 	}
       
    44 
       
    45 CAgnTzRuleIndexItem* CAgnTzRuleIndexItem::NewL(RReadStream& aStream)
       
    46 	{
       
    47 	CAgnTzRuleIndexItem* self = new (ELeave) CAgnTzRuleIndexItem();
       
    48 	CleanupStack::PushL(self);
       
    49 	self->InternalizeL(aStream);
       
    50 	CleanupStack::Pop(self);
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 CAgnTzRuleIndexItem* CAgnTzRuleIndexItem::NewL(TStreamId aStreamId, CTzRules* aTzRule)
       
    55 	{
       
    56 	CAgnTzRuleIndexItem* self = new (ELeave) CAgnTzRuleIndexItem(aStreamId, aTzRule);
       
    57 	return self;
       
    58 	}
       
    59 
       
    60 CAgnTzRuleIndexItem::~CAgnTzRuleIndexItem()
       
    61 	{
       
    62 	delete iTzRules;
       
    63 	}
       
    64 
       
    65 void CAgnTzRuleIndexItem::IncrementRef()
       
    66 	{
       
    67 	++iRefCount;
       
    68 	}
       
    69 
       
    70 TInt CAgnTzRuleIndexItem::DecrementRef()
       
    71 	{
       
    72 	__ASSERT_DEBUG(iRefCount>0, User::Invariant());
       
    73 	return --iRefCount;
       
    74 	}
       
    75 
       
    76 void CAgnTzRuleIndexItem::ExternalizeL(RWriteStream& aStream) const
       
    77 	{
       
    78 	aStream.WriteInt16L(iRefCount);
       
    79 	aStream << iStreamId;
       
    80 	}
       
    81 
       
    82 void CAgnTzRuleIndexItem::InternalizeL(RReadStream& aStream)
       
    83 	{
       
    84 	iRefCount = aStream.ReadInt16L();
       
    85 	aStream >> iStreamId;
       
    86 	}
       
    87 
       
    88 void CAgnTzRuleIndexItem::SetRule(CTzRules* aTzRules)
       
    89 	{
       
    90 	if (iTzRules)
       
    91 		{
       
    92 		delete iTzRules;
       
    93 		}
       
    94 	iTzRules = aTzRules;
       
    95 	}
       
    96 
       
    97 CTzRules* CAgnTzRuleIndexItem::TzRule() const
       
    98 	{
       
    99 	return iTzRules;
       
   100 	}
       
   101 
       
   102 const TStreamId& CAgnTzRuleIndexItem::StreamId() const
       
   103 	{
       
   104 	return iStreamId;
       
   105 	}
       
   106 
       
   107 TBool CAgnTzRuleIndexItem::IsSystemTzRule() const
       
   108 	{
       
   109 	return EFalse;
       
   110 	}
       
   111 
       
   112 /* ------------------- CAgnSystemTzRuleIndexItem -------------------*/
       
   113 void CAgnSystemTzRuleIndexItem::ConstructL(const TDesC8& aTzId)
       
   114 	{
       
   115 	iTzId = aTzId.AllocL();
       
   116 	}
       
   117 
       
   118 CAgnSystemTzRuleIndexItem* CAgnSystemTzRuleIndexItem::NewL(TStreamId aStreamId,	const TDesC8& aTzId, CTzRules* aRule)
       
   119 	{
       
   120 	CAgnSystemTzRuleIndexItem* self = new (ELeave) CAgnSystemTzRuleIndexItem(aStreamId, aRule);
       
   121 	CleanupStack::PushL(self);
       
   122 	self->ConstructL(aTzId);
       
   123 	CleanupStack::Pop(self);
       
   124 	return self;
       
   125 	}
       
   126 
       
   127 CAgnSystemTzRuleIndexItem::CAgnSystemTzRuleIndexItem() :
       
   128 	CAgnTzRuleIndexItem(), iTzId(NULL)
       
   129 	{
       
   130 	}
       
   131 
       
   132 CAgnSystemTzRuleIndexItem::CAgnSystemTzRuleIndexItem(TStreamId aStreamId,
       
   133 		CTzRules* aRules) :
       
   134 	CAgnTzRuleIndexItem(aStreamId, aRules), iTzId(NULL)
       
   135 	{
       
   136 	}
       
   137 
       
   138 CAgnSystemTzRuleIndexItem::~CAgnSystemTzRuleIndexItem()
       
   139 	{
       
   140 	delete iTzId;
       
   141 	}
       
   142 
       
   143 CAgnSystemTzRuleIndexItem* CAgnSystemTzRuleIndexItem::NewL(RReadStream& aStream)
       
   144 	{
       
   145 	CAgnSystemTzRuleIndexItem* self = new (ELeave) CAgnSystemTzRuleIndexItem();
       
   146 	CleanupStack::PushL(self);
       
   147 	self->InternalizeL(aStream);
       
   148 	CleanupStack::Pop(self);
       
   149 	return self;
       
   150 	}
       
   151 
       
   152 const TDesC8& CAgnSystemTzRuleIndexItem::TzId() const
       
   153 	{
       
   154 	return *iTzId;
       
   155 	}
       
   156 
       
   157 void CAgnSystemTzRuleIndexItem::ExternalizeL(RWriteStream& aStream) const
       
   158 	{
       
   159 	CAgnTzRuleIndexItem::ExternalizeL(aStream);
       
   160 	aStream << *iTzId;
       
   161 	}
       
   162 
       
   163 void CAgnSystemTzRuleIndexItem::InternalizeL(RReadStream& aStream)
       
   164 	{
       
   165 	CAgnTzRuleIndexItem::InternalizeL(aStream);
       
   166 	iTzId = HBufC8::NewL(aStream, KMaxTInt);
       
   167 	}
       
   168 
       
   169 TBool CAgnSystemTzRuleIndexItem::IsSystemTzRule() const
       
   170 	{
       
   171 	return ETrue;
       
   172 	}
       
   173 
       
   174 /* ------------------- CAgnTzRuleIndex -------------------*/
       
   175 CAgnTzRuleIndex::CAgnTzRuleIndex(CStreamDictionary& aDictionary, CFileStore& aStore) :
       
   176 	iDictionary(&aDictionary),
       
   177 	iStore(&aStore),
       
   178 	iPosCurSystemTzRule(KErrNotFound),
       
   179 	iPosFetchedLastTime(0),
       
   180 	iTzDbChangeTimeStamp(Time::NullTTime()),
       
   181 	iTzRulesLastModifiedTime(Time::NullTTime())
       
   182 	{
       
   183 	}
       
   184 
       
   185 CAgnTzRuleIndex* CAgnTzRuleIndex::NewL(CStreamDictionary& aDictionary, CFileStore& aStore)
       
   186 	{
       
   187 	CAgnTzRuleIndex* self = new(ELeave) CAgnTzRuleIndex(aDictionary, aStore);
       
   188 	CleanupStack::PushL(self);
       
   189 	self->ConstructL();
       
   190 	CleanupStack::Pop();
       
   191 	return (self);
       
   192 	}
       
   193 
       
   194 void CAgnTzRuleIndex::ConstructL()
       
   195 	{
       
   196 	iTimeZoneAccessor = CAgnTlsProxy::CreateL(CAgnTlsProxy::TAgnTlsTzRulesType_Server);
       
   197 
       
   198 	iSystemRuleStreamId = ReadItemsFromStoreL(KUidAgnSystemTzIndex);
       
   199 	iUserDefinedRuleStreamId = ReadItemsFromStoreL(KUidAgnImportedTzIndex);
       
   200 
       
   201 	RTz& tzServer = iTimeZoneAccessor->TzServer();
       
   202 	CTzId* tzid = tzServer.GetTimeZoneIdL();
       
   203 	CleanupStack::PushL(tzid);
       
   204 	HandleCurrentTimeZoneChangeL(*tzid);
       
   205 	CleanupStack::PopAndDestroy(tzid);
       
   206 	}
       
   207 
       
   208 /* Read the time stamp of time zone database has been modified last time.
       
   209 
       
   210 - If the file is newly created, the time stamp will be set to current time
       
   211 - If the file is re-opened, read the time stamp from the file.
       
   212 - If the file is re-opened, but there isn't a time stamp, the time stamp will be set to current time
       
   213  */
       
   214 void CAgnTzRuleIndex::ReadTimeStampL()
       
   215 	{
       
   216 	TStreamId streamId = iDictionary->At(KUidAgnTimeStamp);
       
   217 
       
   218 	if (streamId == KNullStreamId)
       
   219 		{//There is not a time stamp in the file either it is newly created or an existing one.
       
   220 		TTime currentTime;
       
   221 		currentTime.UniversalTime();
       
   222 		iTzDbChangeTimeStamp = currentTime;
       
   223 
       
   224 		if (RefreshTzRulesL())
       
   225 			{
       
   226 			iTzRulesLastModifiedTime = currentTime;
       
   227 			}
       
   228 		PersistToStoreL(KUidAgnTimeStamp);
       
   229 		}
       
   230 	else
       
   231 		{//iTzChangTimeStamp is read from file
       
   232 		ReadFromStoreL(KUidAgnTimeStamp, EFalse);
       
   233 		}
       
   234 	}
       
   235 
       
   236 /** Check if the time zone server has been modified since last time the
       
   237  * Calendar server shut down. If so, the time zones of entries cached in the Calendar
       
   238  * will be updated. Calendar clients will be also notified with the change if
       
   239  * any of time zones associated with Calendar entries have been modified.
       
   240  *
       
   241  * This function is called when a Calendar file is opened.
       
   242  *
       
   243  */
       
   244 void CAgnTzRuleIndex::CheckTzDbModificationL(CAgnServFile& aAgnServFile)
       
   245 	{
       
   246 	iAgnFile = &aAgnServFile;
       
   247 	ReadTimeStampL();
       
   248 	//This will result in HandleTzRulesChangeL to be called immediatly if a tz change has been published.
       
   249 	iTimeZoneAccessor->AddSystemTimeObserverL(this);
       
   250 	}
       
   251 /*
       
   252  Called when the file is closed. It will write the current time to the Calendar file.
       
   253  */
       
   254 void CAgnTzRuleIndex::WriteTimeStampL()
       
   255 	{
       
   256 	TStreamId streamId = iDictionary->At(KUidAgnTimeStamp);
       
   257 	RStoreWriteStream writeStream;
       
   258 	writeStream.ReplaceLC(*iStore, streamId);
       
   259 	ExternalizeTimesL(writeStream);
       
   260 	writeStream.CommitL();
       
   261 	CleanupStack::PopAndDestroy(&writeStream);
       
   262 	iStore->CommitL();
       
   263 
       
   264 	}
       
   265 void CAgnTzRuleIndex::ExternalizeTimesL(RStoreWriteStream& aWriteStream) const
       
   266 	{
       
   267 	aWriteStream << I64LOW(iTzDbChangeTimeStamp.Int64());
       
   268 	aWriteStream << I64HIGH(iTzDbChangeTimeStamp.Int64());
       
   269 	aWriteStream << I64LOW(iTzRulesLastModifiedTime.Int64());
       
   270 	aWriteStream << I64HIGH(iTzRulesLastModifiedTime.Int64());
       
   271 	}
       
   272 
       
   273 void CAgnTzRuleIndex::InternalizeTimesL(RReadStream& aReadStream)
       
   274 	{
       
   275 	TUint32 low = aReadStream.ReadUint32L();
       
   276 	TUint32 high = aReadStream.ReadUint32L();
       
   277 	iTzDbChangeTimeStamp = TTime(MAKE_TINT64(high, low));
       
   278 
       
   279 	low = aReadStream.ReadUint32L();
       
   280 	high = aReadStream.ReadUint32L();
       
   281 	iTzRulesLastModifiedTime = TTime(MAKE_TINT64(high, low));
       
   282 	}
       
   283 
       
   284 /* Externalise an array of tz rules or a time stamp to first time Calendar file.
       
   285 
       
   286  @param aUid refer to uid of object to write to the file.
       
   287  @return Stream Id refer to the object being written to the file
       
   288  */
       
   289 TStreamId CAgnTzRuleIndex::PersistToStoreL(const TUid& aUid)
       
   290 	{
       
   291 	RStoreWriteStream writeStream;
       
   292 	TStreamId streamId = writeStream.CreateLC(*iStore);
       
   293 	if (aUid == KUidAgnSystemTzIndex)
       
   294 		{
       
   295 		ExternalizeRulesL(writeStream, iSystemTzRules);
       
   296 		}
       
   297 	else
       
   298 		if (aUid == KUidAgnImportedTzIndex)
       
   299 			{
       
   300 			ExternalizeRulesL(writeStream, iUserDefinedTzRules);
       
   301 			}
       
   302 		else
       
   303 			{
       
   304 			__ASSERT_ALWAYS(aUid == KUidAgnTimeStamp,User::Invariant());
       
   305 			ExternalizeTimesL(writeStream);
       
   306 			}
       
   307 
       
   308 	writeStream.CommitL();
       
   309 	CleanupStack::PopAndDestroy(&writeStream);
       
   310 
       
   311 	iDictionary->AssignL(aUid, streamId);
       
   312 
       
   313 	// Re-write the dictionary stream
       
   314 	RStoreWriteStream stream;
       
   315 	TStreamId rootStreamId = iStore->Root();
       
   316 	stream.ReplaceLC(*iStore, rootStreamId);
       
   317 	stream<< *iDictionary;
       
   318 	stream.CommitL();
       
   319 	CleanupStack::PopAndDestroy(); // dictionary stream
       
   320 	iStore->CommitL();
       
   321 	return streamId;
       
   322 	}
       
   323 
       
   324 void CAgnTzRuleIndex::ReadFromStoreL(const TUid& aUid, TBool aRollback)
       
   325 	{
       
   326 	TStreamId streamId = iDictionary->At(aUid);
       
   327 	__ASSERT_ALWAYS(streamId != KNullStreamId, User::Leave(KErrNotFound));
       
   328 	RStoreReadStream readStream;
       
   329 	readStream.OpenLC(*iStore, streamId);
       
   330 	if (aUid == KUidAgnSystemTzIndex)
       
   331 		{
       
   332 		InternalizeRulesL(readStream, ETrue, aRollback);
       
   333 		}
       
   334 	else
       
   335 		if (aUid == KUidAgnImportedTzIndex)
       
   336 			{
       
   337 			InternalizeRulesL(readStream, EFalse, aRollback);
       
   338 			}
       
   339 		else
       
   340 			{
       
   341 			__ASSERT_ALWAYS(aUid==KUidAgnTimeStamp,User::Invariant());
       
   342 			InternalizeTimesL(readStream);
       
   343 			}
       
   344 
       
   345 	CleanupStack::PopAndDestroy(&readStream);
       
   346 	}
       
   347 
       
   348 TStreamId CAgnTzRuleIndex::ReadItemsFromStoreL(const TUid& aUid, TBool aRollback)
       
   349 	{
       
   350 	TStreamId streamId = iDictionary->At(aUid);
       
   351 
       
   352 	if (streamId == KNullStreamId)
       
   353 		{
       
   354 		streamId = PersistToStoreL(aUid);
       
   355 		}
       
   356 	else
       
   357 		{
       
   358 		ReadFromStoreL(aUid, aRollback);
       
   359 		}
       
   360 
       
   361 	return streamId;
       
   362 	}
       
   363 
       
   364 void CAgnTzRuleIndex::InternalizeRulesL(RReadStream& aStream,
       
   365 		TBool aIsSystemRule, TBool aRollback)
       
   366 	{
       
   367 	TInt count = aStream.ReadInt16L();
       
   368 	CAgnTzRuleIndexItem* item= NULL;
       
   369 	for (TInt ii=0; ii<count; ++ii)
       
   370 		{
       
   371 		if (aIsSystemRule)
       
   372 			{
       
   373 			item = CAgnSystemTzRuleIndexItem::NewL(aStream);
       
   374 			}
       
   375 		else
       
   376 			{
       
   377 			item = CAgnTzRuleIndexItem::NewL(aStream);
       
   378 			}
       
   379 
       
   380 		CleanupStack::PushL(item);
       
   381 		RStoreReadStream readStream;
       
   382 
       
   383 		readStream.OpenLC(*iStore, item->StreamId());
       
   384 		CTzRules* tzRules = CTzRules::NewL(readStream);
       
   385 		item->SetRule(tzRules);
       
   386 		CleanupStack::PopAndDestroy(&readStream);
       
   387 
       
   388 		if (aIsSystemRule)
       
   389 			{
       
   390 			if (aRollback)
       
   391 				{
       
   392 				CleanupStack::Pop(item);
       
   393 				RollbackItemL(iSystemTzRules, item);
       
   394 				}
       
   395 			else
       
   396 				{
       
   397 				iSystemTzRules.AppendL(item);
       
   398 				CleanupStack::Pop(item);
       
   399 				}
       
   400 			}
       
   401 		else
       
   402 			{
       
   403 			if (aRollback)
       
   404 				{
       
   405 				CleanupStack::Pop(item);
       
   406 				RollbackItemL(iUserDefinedTzRules, item);
       
   407 				}
       
   408 			else
       
   409 				{
       
   410 				iUserDefinedTzRules.AppendL(item);
       
   411 				CleanupStack::Pop(item);
       
   412 				}
       
   413 			}
       
   414 		}
       
   415 	}
       
   416 
       
   417 void CAgnTzRuleIndex::ExternalizeRulesL(RWriteStream& aStream, const RPointerArray<CAgnTzRuleIndexItem>& aArray) const
       
   418 	{
       
   419 	TInt count = aArray.Count();
       
   420 	aStream.WriteInt16L(count);
       
   421 
       
   422 	for (TInt ii=0; ii<count; ++ii)
       
   423 		{
       
   424 		aArray[ii]->ExternalizeL(aStream);
       
   425 		}
       
   426 	}
       
   427 
       
   428 CAgnTzRuleIndex::~CAgnTzRuleIndex()
       
   429 	{
       
   430 	iSystemTzRules.ResetAndDestroy();
       
   431 	iUserDefinedTzRules.ResetAndDestroy();
       
   432 	iTimeZoneAccessor->RemoveSystemTimeObserver(this);
       
   433 	CAgnTlsProxy::Release(iTimeZoneAccessor);
       
   434 	}
       
   435 
       
   436 /**
       
   437  It is called when:
       
   438 
       
   439  Creating a light entry during index building.
       
   440  Fetch an entry
       
   441 
       
   442  @param reference to the entry fetching tz rules
       
   443  */
       
   444 void CAgnTzRuleIndex::FetchTzRuleL(CAgnSimpleEntry& aEntry)
       
   445 	{
       
   446 	CAgnTzRules* tzZone = GetTzRulesFromEntry(aEntry);
       
   447 	if (tzZone == NULL)
       
   448 		{
       
   449 		return;
       
   450 		}
       
   451 
       
   452 	TInt pos = KErrNotFound;
       
   453 	if (tzZone->SystemTzRule())
       
   454 		{
       
   455 		pos = FindTzRuleByStreamIdL(tzZone->TzZoneStreamId(), iSystemTzRules,
       
   456 				ETrue);
       
   457 		if (pos>=0)
       
   458 			{
       
   459 			tzZone->SetTzRules(iSystemTzRules[pos]->TzRule());
       
   460 			tzZone->SetUseCurrentSystemTzRules((pos == iPosCurSystemTzRule));
       
   461 			}
       
   462 		}
       
   463 	else
       
   464 		{
       
   465 		__ASSERT_DEBUG(!tzZone->UseCurrentSystemTzRules(), User::Invariant());
       
   466 		pos = FindTzRuleByStreamIdL(tzZone->TzZoneStreamId(),
       
   467 				iUserDefinedTzRules, ETrue);
       
   468 		if (pos>=0)
       
   469 			{
       
   470 			tzZone->SetTzRules(iUserDefinedTzRules[pos]->TzRule());
       
   471 			}
       
   472 		}
       
   473 
       
   474 	if (pos == KErrNotFound)
       
   475 		{
       
   476 		AddCurrentSystemTzRuleL(*tzZone);
       
   477 		}
       
   478 	}
       
   479 
       
   480 /**
       
   481  Remove a tz rule from one of tz rule arraies
       
   482 
       
   483  It should be called when an entry is removed or an entry is updated
       
   484 
       
   485  @param reference to the entry to be deleted
       
   486  */
       
   487 void CAgnTzRuleIndex::RemoveTzRuleL(CAgnSimpleEntry& aEntry)
       
   488 	{
       
   489 	CAgnTzRules* tzZone = GetTzRulesFromEntry(aEntry);
       
   490 	if (tzZone == NULL || !tzZone->HasValidTzZoneStreamId())
       
   491 		{
       
   492 		return;
       
   493 		}
       
   494 
       
   495 	TInt pos = KErrNotFound;
       
   496 	if (tzZone->SystemTzRule())
       
   497 		{
       
   498 		pos = FindTzRuleByStreamIdL(tzZone->TzZoneStreamId(), iSystemTzRules,
       
   499 				EFalse);
       
   500 		if (pos >=0)
       
   501 			{
       
   502 			DeleteARuleL(pos, iSystemTzRules, iSystemRuleStreamId);
       
   503 			}
       
   504 		}
       
   505 	else
       
   506 		{
       
   507 		pos = FindTzRuleByStreamIdL(tzZone->TzZoneStreamId(),
       
   508 				iUserDefinedTzRules, EFalse);
       
   509 		if (pos >=0)
       
   510 			{
       
   511 			DeleteARuleL(pos, iUserDefinedTzRules, iUserDefinedRuleStreamId);
       
   512 			}
       
   513 		}
       
   514 
       
   515 	__ASSERT_DEBUG(pos != KErrNotFound, Panic(EAgmErrTzRuleIsNotFound));
       
   516 
       
   517 	User::LeaveIfError(pos);
       
   518 	}
       
   519 
       
   520 /**
       
   521  Add a tz rule to the array if it is not existing in the array otherwise
       
   522  increase the refference count for that rule.
       
   523 
       
   524  It is called when:
       
   525 
       
   526  An entry is added with a user defined tz rule
       
   527  An old format file (9.4 prior) is converted to a new format
       
   528 
       
   529  @param reference to the entry to be added.
       
   530  */
       
   531 void CAgnTzRuleIndex::AddTzRuleL(CAgnEntry& aEntry)
       
   532 	{
       
   533 	CAgnTzRules* tzZone = GetTzRulesFromEntry(aEntry);
       
   534 	if (tzZone == NULL)
       
   535 		{
       
   536 		return;
       
   537 		}
       
   538 
       
   539 	if (tzZone->TzRules() == NULL || tzZone->UseCurrentSystemTzRules())
       
   540 		{
       
   541 		AddCurrentSystemTzRuleL(*tzZone);
       
   542 		return;
       
   543 		}
       
   544 
       
   545 	TBool isSysRule = EFalse;
       
   546 	TInt pos = FindRule(*tzZone->TzRules(), isSysRule);
       
   547 	if (pos >= 0)
       
   548 		{
       
   549 		if (isSysRule)
       
   550 			{
       
   551 			iSystemTzRules[pos]->IncrementRef();
       
   552 			}
       
   553 		else
       
   554 			{
       
   555 			iUserDefinedTzRules[pos]->IncrementRef();
       
   556 			}
       
   557 
       
   558 		}
       
   559 	else
       
   560 		{
       
   561 		CTzRules* tzRule = tzZone->TzRules()->CloneL();
       
   562 		CleanupStack::PushL(tzRule);
       
   563 		TStreamId streamId = PersistTzRuleL(*tzRule);//It will not be commited until model commit the entry into the file
       
   564 		CAgnTzRuleIndexItem* item = CAgnTzRuleIndexItem::NewL(streamId, tzRule);
       
   565 		CleanupStack::Pop(tzRule);
       
   566 
       
   567 		CleanupStack::PushL(item);
       
   568 		iUserDefinedTzRules.AppendL(item);
       
   569 		pos = iUserDefinedTzRules.Count()-1;
       
   570 		CleanupStack::Pop(item);
       
   571 		}
       
   572 
       
   573 	if (isSysRule)
       
   574 		{
       
   575 		UpdateItemsInStoreL(iSystemTzRules, iSystemRuleStreamId);
       
   576 		tzZone->SetTzRules(iSystemTzRules[pos]->TzRule());
       
   577 		tzZone->SetSystemTzRule(ETrue);
       
   578 		tzZone->SetTzZoneStreamId(iSystemTzRules[pos]->StreamId());
       
   579 		}
       
   580 	else
       
   581 		{
       
   582 		UpdateItemsInStoreL(iUserDefinedTzRules, iUserDefinedRuleStreamId);
       
   583 		tzZone->SetTzRules(iUserDefinedTzRules[pos]->TzRule());
       
   584 		tzZone->SetSystemTzRule(EFalse);
       
   585 		tzZone->SetTzZoneStreamId(iUserDefinedTzRules[pos]->StreamId());
       
   586 		}
       
   587 	}
       
   588 
       
   589 /**
       
   590  Called when entry's tz rule changed
       
   591 
       
   592  @param aOldEntry reference to the original entry to be updated.
       
   593  @param aNewEntry reference to the entry containing updated content.
       
   594  */
       
   595 void CAgnTzRuleIndex::UpdateTzRuleL(CAgnEntry& aOldEntry, CAgnEntry& aNewEntry)
       
   596 	{
       
   597 	CAgnTzRules* newTzZone = GetTzRulesFromEntry(aNewEntry);
       
   598 	if (newTzZone != NULL && newTzZone->HasValidTzZoneStreamId())
       
   599 		{
       
   600 		TInt pos = KErrNotFound;
       
   601 		if (newTzZone->SystemTzRule())
       
   602 			{
       
   603 			pos = FindTzRuleByStreamIdL(newTzZone->TzZoneStreamId(), iSystemTzRules, EFalse);
       
   604 			iSystemTzRules[pos]->IncrementRef();
       
   605 			newTzZone->SetTzRules(iSystemTzRules[pos]->TzRule());
       
   606 			UpdateItemsInStoreL(iSystemTzRules, iSystemRuleStreamId);
       
   607 			}
       
   608 		else
       
   609 			{
       
   610 			pos = FindTzRuleByStreamIdL(newTzZone->TzZoneStreamId(), iUserDefinedTzRules, EFalse);
       
   611 			iUserDefinedTzRules[pos]->IncrementRef();
       
   612 			newTzZone->SetTzRules(iUserDefinedTzRules[pos]->TzRule());
       
   613 			UpdateItemsInStoreL(iUserDefinedTzRules, iUserDefinedRuleStreamId);
       
   614 			}
       
   615 
       
   616 		__ASSERT_DEBUG(pos !=KErrNotFound, Panic(EAgmErrTzRuleIsNotFound));
       
   617 		}
       
   618 	else
       
   619 		{
       
   620 		AddTzRuleL(aNewEntry);
       
   621 		}
       
   622 
       
   623 	RemoveTzRuleL(aOldEntry);
       
   624 	}
       
   625 
       
   626 void CAgnTzRuleIndex::UpdateItemsInStoreL(
       
   627 		RPointerArray<CAgnTzRuleIndexItem>& aArray, TStreamId aStreamId)
       
   628 	{
       
   629 	RStoreWriteStream writeStream;
       
   630 	writeStream.ReplaceLC(*iStore, aStreamId);
       
   631 	ExternalizeRulesL(writeStream, aArray);
       
   632 	writeStream.CommitL();
       
   633 	CleanupStack::PopAndDestroy(&writeStream);
       
   634 	}
       
   635 
       
   636 TInt CAgnTzRuleIndex::FindTzRuleByStreamIdL(TStreamId aStreamId, RPointerArray<CAgnTzRuleIndexItem>& aArray, TBool aTryPosLastTime)
       
   637 	{
       
   638 	TInt count = aArray.Count();
       
   639 	if (aTryPosLastTime && iPosFetchedLastTime >= 0 && count
       
   640 			> iPosFetchedLastTime)
       
   641 		{
       
   642 		if (aStreamId == aArray[iPosFetchedLastTime]->StreamId())
       
   643 			{
       
   644 			return iPosFetchedLastTime;
       
   645 			}
       
   646 		}
       
   647 
       
   648 	TInt pos = KErrNotFound;
       
   649 	TInt ii = 0;
       
   650 	while (pos == KErrNotFound && ii < count)
       
   651 		{
       
   652 		if (aStreamId == aArray[ii]->StreamId())
       
   653 			{
       
   654 			pos = ii;
       
   655 			}
       
   656 		++ii;
       
   657 		}
       
   658 
       
   659 	if (aTryPosLastTime)
       
   660 		{
       
   661 		iPosFetchedLastTime = pos;
       
   662 		}
       
   663 
       
   664 	return pos;
       
   665 	}
       
   666 
       
   667 TInt CAgnTzRuleIndex::FindRule(RPointerArray<CAgnTzRuleIndexItem>& aRuleArray, const CTzRules& aRule)
       
   668 	{
       
   669 	TInt pos = KErrNotFound;
       
   670 	TInt count = aRuleArray.Count();
       
   671 	TInt ii = 0;
       
   672 	while (pos < 0 && ii<count)
       
   673 		{
       
   674 		if (aRule.IsEqualTo(*(aRuleArray[ii]->TzRule())))
       
   675 			{
       
   676 			pos = ii;
       
   677 			}
       
   678 		++ii;
       
   679 		}
       
   680 
       
   681 	return pos;
       
   682 	}
       
   683 
       
   684 TInt CAgnTzRuleIndex::FindRule(const CTzRules& aTzRule, TBool& aIsSystemRule)
       
   685 	{
       
   686 	TInt pos = KErrNotFound;
       
   687 	pos = FindRule(iSystemTzRules, aTzRule);
       
   688 	if (pos>=0)
       
   689 		{
       
   690 		aIsSystemRule = ETrue;
       
   691 		}
       
   692 	else
       
   693 		{
       
   694 		pos = FindRule(iUserDefinedTzRules, aTzRule);
       
   695 		if (pos>=0)
       
   696 			{
       
   697 			aIsSystemRule = EFalse;
       
   698 			}
       
   699 		}
       
   700 	return pos;
       
   701 	}
       
   702 
       
   703 /**
       
   704  Add the current system tz rule to the array if it is not there otherwise
       
   705  increase the refference count for the rule.
       
   706 
       
   707 
       
   708  It is called when:
       
   709 
       
   710  An entry is added with the current tz rule
       
   711  @param reference to a CAgnTzRules object which is added to the index
       
   712  */
       
   713 void CAgnTzRuleIndex::AddCurrentSystemTzRuleL(CAgnTzRules& aTzZone)
       
   714 	{
       
   715 	if (iPosCurSystemTzRule >= 0)
       
   716 		{
       
   717 		iSystemTzRules[iPosCurSystemTzRule]->IncrementRef();
       
   718 		}
       
   719 	else
       
   720 		{
       
   721 		RTz& tzServer = iTimeZoneAccessor->TzServer();
       
   722 		CTzId* tzId = tzServer.GetTimeZoneIdL();
       
   723 		CleanupStack::PushL(tzId);
       
   724 		CTzRules* rule = tzServer.GetTimeZoneRulesL(*tzId, KMinYear, KMaxYear, ETzUtcTimeReference);
       
   725 		CleanupStack::PushL(rule);
       
   726 		TStreamId streamId = PersistTzRuleL(*rule);//It will not be commited until model commit the entry into the file
       
   727 		CAgnSystemTzRuleIndexItem* item = CAgnSystemTzRuleIndexItem::NewL(streamId, tzId->TimeZoneNameID(), rule);
       
   728 		CleanupStack::Pop(rule);
       
   729 		CleanupStack::PushL(item);
       
   730 		iSystemTzRules.AppendL(item);
       
   731 		iPosCurSystemTzRule = iSystemTzRules.Count()-1;
       
   732 		CleanupStack::Pop(item);
       
   733 
       
   734 		CleanupStack::PopAndDestroy(tzId);
       
   735 		}
       
   736 
       
   737 	UpdateItemsInStoreL(iSystemTzRules, iSystemRuleStreamId);
       
   738 	aTzZone.SetTzZoneStreamId(iSystemTzRules[iPosCurSystemTzRule]->StreamId());
       
   739 	aTzZone.SetTzRules(iSystemTzRules[iPosCurSystemTzRule]->TzRule());
       
   740 	aTzZone.SetSystemTzRule(ETrue);
       
   741 	aTzZone.SetUseCurrentSystemTzRules(ETrue);
       
   742 	}
       
   743 
       
   744 void CAgnTzRuleIndex::DeleteARuleL(TInt aPos, RPointerArray<CAgnTzRuleIndexItem>& aArray, TStreamId aStreamId)
       
   745 	{
       
   746 	TInt ref = aArray[aPos]->DecrementRef();
       
   747 	if (ref ==0)
       
   748 		{
       
   749 		iStore->DeleteL(aArray[aPos]->StreamId());
       
   750 		delete aArray[aPos];
       
   751 		aArray.Remove(aPos);
       
   752 
       
   753 		if (aPos == iPosCurSystemTzRule)
       
   754 			{
       
   755 			iPosCurSystemTzRule = KErrNotFound;
       
   756 			}
       
   757 		else if (aPos < iPosCurSystemTzRule)
       
   758 			{
       
   759 			--iPosCurSystemTzRule;
       
   760 			}
       
   761 		}
       
   762 
       
   763 	UpdateItemsInStoreL(aArray, aStreamId);
       
   764 	}
       
   765 
       
   766 TStreamId CAgnTzRuleIndex::PersistTzRuleL(const CTzRules& aTzRule)
       
   767 	{
       
   768 	TStreamId streamId = iStore->ExtendL();
       
   769 	RStoreWriteStream writeStream;
       
   770 	writeStream.ReplaceLC(*iStore, streamId);
       
   771 	aTzRule.ExternalizeL(writeStream);
       
   772 	writeStream.CommitL();//Don't commit to store until the CAgnEntryModel does it
       
   773 	CleanupStack::PopAndDestroy(&writeStream);
       
   774 	return streamId;
       
   775 	}
       
   776 
       
   777 void CAgnTzRuleIndex::HandleCurrentTimeZoneChangeL(const CTzId& aSystemTzId)
       
   778 	{
       
   779 	if (iPosCurSystemTzRule != KErrNotFound && 0 == static_cast<CAgnSystemTzRuleIndexItem*>(iSystemTzRules[iPosCurSystemTzRule])->TzId().Compare(aSystemTzId.TimeZoneNameID()))
       
   780 		{
       
   781 		//the rule doesn't change.
       
   782 		return;
       
   783 		}
       
   784 
       
   785 	CTzRules* rule = iTimeZoneAccessor->GetCurrentSystemTzRulesL();
       
   786 	CleanupStack::PushL(rule);
       
   787 	iPosCurSystemTzRule = FindRule(iSystemTzRules, *rule);
       
   788 	CleanupStack::PopAndDestroy(rule);
       
   789 	}
       
   790 
       
   791 void CAgnTzRuleIndex::HandleTzRulesChangeL(const TTime& aTime)
       
   792 	{
       
   793 	if(!iAgnFile->IsLocked())
       
   794 	    {
       
   795         if (iTzDbChangeTimeStamp < aTime)
       
   796             {
       
   797             iTzDbChangeTimeStamp = aTime;
       
   798             if (RefreshTzRulesL())
       
   799                 {
       
   800                 iTzRulesLastModifiedTime = aTime;
       
   801                 }
       
   802             WriteTimeStampL();
       
   803             }
       
   804 	    }
       
   805 	else // set the flag so that it can be done later when agendar server is unlocked.
       
   806 	    {
       
   807 	    iAgnFile->SetRefreshTzRules(ETrue);
       
   808 	    }
       
   809 	}
       
   810 
       
   811 /* Refresh cached system tz rules and broadcast the change if any of rules has been updated
       
   812  */
       
   813 TBool CAgnTzRuleIndex::RefreshTzRulesL()
       
   814 	{
       
   815 	TBool rulesChanged = EFalse;
       
   816 	const TInt KCount = iSystemTzRules.Count();
       
   817 	for (TInt ii = 0; ii<KCount; ++ii)
       
   818 		{
       
   819 		CTzId* id = CTzId::NewL(static_cast<CAgnSystemTzRuleIndexItem*>(iSystemTzRules[ii])->TzId());
       
   820 		CTzRules* rules= NULL;
       
   821 		TRAPD(err, rules = iTimeZoneAccessor->TzServer().GetTimeZoneRulesL(*id, KMinYear, KMaxYear , ETzUtcTimeReference));
       
   822 		delete id;
       
   823 		if(err == KErrNone)
       
   824 		    {
       
   825             CleanupStack::PushL(rules);
       
   826             if (rules && !iSystemTzRules[ii]->TzRule()->IsEqualTo(*rules))
       
   827                 {//If a tz rule cached is different from the one in tz server for the same TZ ID, it needs to be updated with the new one.
       
   828                 CAgnTzRuleIndexItem* item = iSystemTzRules[ii];
       
   829                 item->TzRule()->CopyL(*rules);
       
   830                 RStoreWriteStream writeStream;
       
   831                 writeStream.ReplaceLC(*iStore, item->StreamId());
       
   832                 item->TzRule()->ExternalizeL(writeStream);
       
   833                 writeStream.CommitL();
       
   834                 CleanupStack::PopAndDestroy(&writeStream);
       
   835                 iStore->CommitL();
       
   836                 rulesChanged = ETrue;
       
   837                 }
       
   838             CleanupStack::PopAndDestroy(rules);
       
   839             }
       
   840 		}
       
   841 	if (rulesChanged)
       
   842 		{
       
   843 		iAgnFile->TzRulesHaveChangedL();
       
   844 		}
       
   845 	return rulesChanged;
       
   846 	}
       
   847 
       
   848 void CAgnTzRuleIndex::RollBackL()
       
   849 	{
       
   850 	ReadItemsFromStoreL(KUidAgnSystemTzIndex, ETrue);
       
   851 	ReadItemsFromStoreL(KUidAgnImportedTzIndex, ETrue);
       
   852 	}
       
   853 
       
   854 void CAgnTzRuleIndex::ReloadStore(CStreamDictionary& aDictionary, CFileStore& aStore)
       
   855 	{
       
   856 	iDictionary = &aDictionary;
       
   857 	iStore = &aStore;
       
   858 	}
       
   859 
       
   860 CTzRules* CAgnTzRuleIndex::FindTzRuleByStreamIdL(TStreamId aStreamId, TBool aIsSystemRule)
       
   861 	{
       
   862 	CTzRules* tzRules= NULL;
       
   863 	if (aIsSystemRule)
       
   864 		{
       
   865 		TInt pos = FindTzRuleByStreamIdL(aStreamId, iSystemTzRules, EFalse);
       
   866 		if (pos != KErrNotFound)
       
   867 			{
       
   868 			tzRules = iSystemTzRules[pos]->TzRule()->CloneL();
       
   869 			}
       
   870 		}
       
   871 	else
       
   872 		{
       
   873 		TInt pos = FindTzRuleByStreamIdL(aStreamId, iUserDefinedTzRules, EFalse);
       
   874 		if (pos != KErrNotFound)
       
   875 			{
       
   876 			tzRules = iUserDefinedTzRules[pos]->TzRule()->CloneL();
       
   877 			}
       
   878 		}
       
   879 
       
   880 	if (tzRules == NULL)
       
   881 		{
       
   882 		tzRules = iTimeZoneAccessor->GetCurrentSystemTzRulesL();
       
   883 		}
       
   884 
       
   885 	return tzRules;
       
   886 	}
       
   887 
       
   888 CAgnTzRules* CAgnTzRuleIndex::GetTzRulesFromEntry(CAgnSimpleEntry& aEntry)
       
   889 	{
       
   890 	CAgnTzRules* tzZone= NULL;
       
   891 	if (aEntry.TimeMode() != MAgnCalendarTimeMode::EFloating)
       
   892 		{
       
   893 		CAgnRptDef* rptDef = aEntry.RptDef();
       
   894 		if (rptDef != NULL)
       
   895 			{
       
   896 			tzZone = rptDef->AgnTzRules();
       
   897 			}
       
   898 		}
       
   899 
       
   900 	return tzZone;
       
   901 	}
       
   902 
       
   903 void CAgnTzRuleIndex::RollbackItemL(RPointerArray<CAgnTzRuleIndexItem>& aRuleArray,	CAgnTzRuleIndexItem* aItem)
       
   904 	{
       
   905 	CleanupStack::PushL(aItem);
       
   906 	TInt pos = FindTzRuleByStreamIdL(aItem->StreamId(), aRuleArray, EFalse);
       
   907 	if (pos == KErrNotFound)
       
   908 		{
       
   909 		aRuleArray.AppendL(aItem);
       
   910 		CleanupStack::Pop(aItem);
       
   911 		}
       
   912 	else
       
   913 		{
       
   914 		CAgnTzRuleIndexItem* item = aRuleArray[pos];
       
   915 		item->SetReferenceCount(aItem->ReferenceCount());
       
   916 		CleanupStack::PopAndDestroy(aItem);
       
   917 		}
       
   918 	}
       
   919 
       
   920 /** Get the last modified time for tz rules
       
   921  * It is called when the client getting the last modified date for an entry since the
       
   922  * last modified time of an entry is not updated when tz database is updated.
       
   923 */
       
   924 TTime CAgnTzRuleIndex::TzRulesLastModifiedDateL()
       
   925 	{
       
   926 	return iTzRulesLastModifiedTime;
       
   927 	}