|
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 } |