diff -r 000000000000 -r 2e3d3ce01487 tzservices/tzserver/Server/Source/tzlocalizationdb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tzservices/tzserver/Server/Source/tzlocalizationdb.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,1357 @@ +// Copyright (c) 2008-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 "tzlocalizationdb.h" +#include "timezoneserver.h" +#include "mtimezonedataaccess.h" + +#include // For CRepository. +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include //new file added for CTzUserNames which is publishedPartner +#endif +#include +#include + +// Database location and access policy +_LIT(KTzLocalizationDbName,"c:TzLocalization.db"); +_LIT(KTzLocalizationDbSecurityPolicy,"secure[10206A8B]"); + +//Table and Column names for Cached Time Zone Table +//These text strings are never visible and do not need localizing +_LIT(KCZTableName, "FrequentlyUsedZones"); +_LIT(KCZTableTzIdCol, "TzId"); +_LIT(KCZTableStdCol, "StandardName"); +_LIT(KCZTableDSTCol, "DSTName"); +_LIT(KCZTableShortStdCol, "ShortStandardName"); +_LIT(KCZTableShortDSTCol, "ShortDSTName"); +_LIT(KCZTableCityCol, "City"); +_LIT(KCZTableCityGroupCol, "GroupId"); +_LIT(KCZTableResourceIdCol, "ResourceId"); +_LIT(KCZTableCityIndexCol, "CityIndex"); + +//Table and Column names for User Added Cities Table +//These text strings are never visible and do not need localizing +_LIT(KUCTableName, "UserCities"); +_LIT(KUCTableTzId, "TzId"); +_LIT(KUCTableCity, "City"); +_LIT(KUCTableGroup, "GroupId"); +_LIT(KUCTableResourceId, "ResourceId"); + +enum TTzZoneColumn + { + // Enum will used as a DB column index, so it must start at 1 + ETzZoneId = 1, + ETzZoneStdName, + ETzZoneDSTName, + ETzZoneShortStdName, + ETzZoneShortDSTName, + ETzZoneCity, + ETzZoneGroupId, + ETzZoneResourceId, + ETzZoneCityIndex + }; + +_LIT(KTzMutexName, "TZ_GlobalMutex"); + +void CTzLocalizationDb::CleanupTimeZonePointerArray(TAny* aArray) + { + RPointerArray* array = static_cast* >(aArray); + if (array) + { + array->ResetAndDestroy(); + array->Close(); + } + } + +void CTzLocalizationDb::CleanupCityPointerArray(TAny* aArray) + { + RPointerArray* array = static_cast* >(aArray); + if (array) + { + array->ResetAndDestroy(); + array->Close(); + } + } + +CTzLocalizationDb* CTzLocalizationDb::NewL(CTzServer& aServer) + { + CTzLocalizationDb* self = new(ELeave) CTzLocalizationDb(aServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CTzLocalizationDb::~CTzLocalizationDb() + { + iServer.UserTimeZoneDb().RemoveObserver(this); + CloseDb(); + iDbsSession.Close(); + } + +CTzLocalizationDb::CTzLocalizationDb(CTzServer& aServer) + : iServer(aServer) + { + } + +void CTzLocalizationDb::ConstructL() + { + User::LeaveIfError(iDbsSession.Connect()); + OpenDbL(); + iServer.UserTimeZoneDb().AddObserverL(this); + } + +void CTzLocalizationDb::OpenDbL() + { + if (iZoneMutex.OpenGlobal(KTzMutexName) != KErrNone) + { + User::LeaveIfError(iZoneMutex.CreateGlobal(KTzMutexName)) ; + } + //Attempt to open the database + TInt error = iLocalizedTimeZoneDb.Open(iDbsSession,KTzLocalizationDbName,KTzLocalizationDbSecurityPolicy); + if (error == KErrNotFound) + { + // Database file doesn't exist. Attempt to create a new one. + CreateBlankDatabaseL(); + } + else if ((error == KErrNone) && IsInvalidL()) + { + RecreateBlankDatabaseL(); + } + else if (error == KErrNone && iServer.TimeZoneManager().TzDbHasChanged()) + { + // We have to refresh the data in the frequently used zones table + // and the city table because it may contain the time zone id that + // is not existing in the Tz database. Or the the details of a tz rule + // has been changed. + RestoreDbL(); + } + else if (error != KErrNone) + { + User::Leave(error); + } + } + +void CTzLocalizationDb::CloseDb() + { + iLocalizedTimeZoneDb.Close(); + if (iZoneMutex.IsHeld()) // it is a leave, so release mutex + { + iZoneMutex.Signal(); + } + iZoneMutex.Close(); + } + +void CTzLocalizationDb::CreateBlankDatabaseL() + { + User::LeaveIfError(iLocalizedTimeZoneDb.Create(iDbsSession,KTzLocalizationDbName,KTzLocalizationDbSecurityPolicy)); + CreateBlankFrequentlyUsedZoneTableL(); + CreateBlankUserCityTableL(); + } + +/** +Creates the Cached Zone Table. +@return KErrNone if succesful, or one of the DBMS Leave codes +@internalTechnology +*/ +void CTzLocalizationDb::CreateBlankFrequentlyUsedZoneTableL() + { + // Create the columns for the cached zones table + RArray cachedTableCols; + CleanupClosePushL(cachedTableCols); + cachedTableCols.AppendL(TDbCol(KCZTableTzIdCol, EDbColUint16)); + cachedTableCols.AppendL(TDbCol(KCZTableStdCol, EDbColText)); + cachedTableCols.AppendL(TDbCol(KCZTableDSTCol, EDbColText)); + cachedTableCols.AppendL(TDbCol(KCZTableShortStdCol, EDbColText)); + cachedTableCols.AppendL(TDbCol(KCZTableShortDSTCol, EDbColText)); + cachedTableCols.AppendL(TDbCol(KCZTableCityCol, EDbColText)); + cachedTableCols.AppendL(TDbCol(KCZTableCityGroupCol, EDbColUint8)); + cachedTableCols.AppendL(TDbCol(KCZTableResourceIdCol, EDbColUint32)); + cachedTableCols.AppendL(TDbCol(KCZTableCityIndexCol, EDbColInt32)); + + // Create the columnset - add the columns + // Columns MUST be added in the same order they appear in TTzZoneColumn + CDbColSet* frequentlyUsedZoneColSet = CDbColSet::NewLC(); + TInt numCols = cachedTableCols.Count(); + for(TInt i = 0; i < numCols; ++i) + { + frequentlyUsedZoneColSet->AddL(cachedTableCols[i]); + } + + // Create the Cached Time Zone table + User::LeaveIfError(iLocalizedTimeZoneDb.CreateTable(KCZTableName,*frequentlyUsedZoneColSet)); + + //Open the newly created table + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + zoneView.Reset(); + //Populate with initial (blank) data. + + _LIT(KEmptyString," "); + + for (TInt x = 0; x < CTzLocalizedTimeZone::ECachedTimeZones; ++x) + { + iZoneMutex.Wait(); + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + // Insert empty row + zoneView.InsertL(); + // Fill the table with blank data + zoneView.SetColL(ETzZoneId, 0); + zoneView.SetColL(ETzZoneStdName, KEmptyString); + zoneView.SetColL(ETzZoneDSTName, KEmptyString); + zoneView.SetColL(ETzZoneShortStdName, KEmptyString); + zoneView.SetColL(ETzZoneShortDSTName, KEmptyString); + zoneView.SetColL(ETzZoneCity, KEmptyString); + zoneView.SetColL(ETzZoneGroupId, 0); + zoneView.SetColL(ETzZoneResourceId, 0); + zoneView.SetColL(ETzZoneCityIndex, 0); + zoneView.PutL(); // Complete insertion + CleanupStack::Pop() ; + iZoneMutex.Signal() ; + } + + CleanupStack::PopAndDestroy(&zoneView); + CleanupStack::PopAndDestroy(frequentlyUsedZoneColSet); + CleanupStack::PopAndDestroy(&cachedTableCols); //cachedTableCols + } + +/** +Creates the user added city database table. +@return KErrNone if succesful, or one of the DBMS Leave codes +@internalTechnology +*/ +void CTzLocalizationDb::CreateBlankUserCityTableL() + { + //Create the columns for the user aded cities table + RArray cityTableCols; + CleanupClosePushL(cityTableCols); + cityTableCols.AppendL(TDbCol(KUCTableTzId, EDbColUint16)); + cityTableCols.AppendL(TDbCol(KUCTableCity, EDbColText)); + cityTableCols.AppendL(TDbCol(KUCTableGroup, EDbColUint8)); + cityTableCols.AppendL(TDbCol(KUCTableResourceId, EDbColUint32)); + + // Create the columnset - add the columns + // Columns MUST be added in the same order they appear in TTzCityColumn + CDbColSet* userCityColSet = CDbColSet::NewLC(); + TInt numCols = cityTableCols.Count(); + for(TInt i = 0; i < numCols; ++i) + { + userCityColSet->AddL(cityTableCols[i]); + } + + // Create the User City table + User::LeaveIfError(iLocalizedTimeZoneDb.CreateTable(KUCTableName,*userCityColSet)); + + CleanupStack::PopAndDestroy(userCityColSet); + CleanupStack::PopAndDestroy(&cityTableCols); + } + +//Check if the database is corrupt or invalid. +TBool CTzLocalizationDb::IsInvalidL() + { + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + TBool isInvalid = EFalse; + if (!zoneView.FirstL()) + { + isInvalid = ETrue; + } + if (!isInvalid) + { + for (TInt i = 1; i < CTzLocalizedTimeZone::ECachedTimeZones; i++) + { + if (!zoneView.NextL()) + { + isInvalid = ETrue; + break; + } + } + } + CleanupStack::PopAndDestroy(&zoneView); + return isInvalid; + } + +void CTzLocalizationDb::RecreateBlankDatabaseL() + { + iLocalizedTimeZoneDb.Close(); + const TUid KTzLocalizationDbSecurityPolicyUid = {0x10206A8B}; + User::LeaveIfError(iDbsSession.DeleteDatabase(KTzLocalizationDbName(),KTzLocalizationDbSecurityPolicyUid)); + CreateBlankDatabaseL(); + } + +TBool CTzLocalizationDb::NeedsUpdatingL() + { + // Check the version of the database + // There are 9 columns as of Oct 2006 + TBool result = ETrue; + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + if (zoneView.ColCount() == ETzZoneCityIndex) + { + result = EFalse; + } + CleanupStack::PopAndDestroy(&zoneView); + return result; + } + +void CTzLocalizationDb::NotifyUserTzRulesChange(TTzUserDataChange /*aChange*/) + { + // Do nothing as we don't use any rules information + } + +void CTzLocalizationDb::NotifyUserTzNamesChange(TTzUserDataChange aChange) + { + if (iLocked) + { + return; + } + + if (aChange.iOperation == ETzUserDataCreated) + { + // Creation of new zones has no impact on existing zones + return; + } + + // Iterate through the tables and refresh contents if needed + TRAPD(err, NotifyUserTzNamesChangeL(aChange)); + if (err != KErrNone) + { + // If there has been an error we can't guarantee the contents of the + // database. Safest option is to lock it. The only way to unlock it + // is to reboot the server. + iLocked = ETrue; + } + } + +void CTzLocalizationDb::NotifyTZDataStatusChangeL(RTz::TTzChanges aChange) + { + if (iLocked) + { + return; + } + + if(aChange == RTz::ETZLocalizationDataChanged) + { + CTzSystemDataDb* systemDataDb = CTzSystemDataDb::NewLC(); + + RPointerArray frequentlyUsedZones; + CleanupStack::PushL(TCleanupItem(CleanupTimeZonePointerArray,&frequentlyUsedZones)); + + RPointerArray cachedCities; + CleanupStack::PushL(TCleanupItem(CleanupTimeZonePointerArray,&cachedCities)); + + for (TInt i = CTzLocalizedTimeZone::ECurrentZone; i < CTzLocalizedTimeZone::ECachedTimeZones; ++i) + { + CTzLocalizedTimeZone::TTzFrequentlyUsedZone freqUsedZone = (CTzLocalizedTimeZone::TTzFrequentlyUsedZone)i; + CTzLocalizedTimeZoneRecord* timeZoneRecord = ReadFrequentlyUsedZoneL(freqUsedZone); + CleanupStack::PushL(timeZoneRecord); + CTzLocalizedCityRecord* cityRecord = ReadCachedTimeZoneCityL(freqUsedZone); + CleanupStack::PushL(cityRecord); + + // If a change occurred, check if the timezone exists in the resource file and refresh it + // If not, delete it + if(!ExistsInSystemDbL(timeZoneRecord->Id(), *systemDataDb) && !CTzId::IsUserTzId(timeZoneRecord->Id())) + { + CleanupStack::PopAndDestroy(cityRecord); + cityRecord = NULL; + CleanupStack::PopAndDestroy(timeZoneRecord); + timeZoneRecord = NULL; + if(freqUsedZone != CTzLocalizedTimeZone::ECurrentZone) + { + // Put the default cached zone and its default city in the array instead + timeZoneRecord = systemDataDb->ReadFrequentlyUsedZoneL(freqUsedZone); + } + else + { + // get the current zone from the time zone server + TInt id = GetTimeZoneIdFromTzServerL(*systemDataDb); + timeZoneRecord = systemDataDb->ReadTimeZoneL(id); + } + CleanupStack::PushL(timeZoneRecord); + cityRecord = systemDataDb->ReadDefaultCityL(timeZoneRecord->Id()); + CleanupStack::PushL(cityRecord); + + cachedCities.AppendL(cityRecord); + // ownership is transferred into the array + CleanupStack::Pop(cityRecord); + frequentlyUsedZones.AppendL(timeZoneRecord); + // ownership is transferred into the array + CleanupStack::Pop(timeZoneRecord); + } + else + { + TUint tzid = timeZoneRecord->Id(); + CleanupStack::PopAndDestroy(cityRecord); + cityRecord = NULL; + CleanupStack::PopAndDestroy(timeZoneRecord); + timeZoneRecord = NULL; + UpdateTimeZoneAndCityRecordForSystemDataL(frequentlyUsedZones, cachedCities, tzid, *systemDataDb); + } + } + WriteAllFrequentlyUsedZonesL(frequentlyUsedZones, cachedCities); + + // Get the cities with the deleted time zone id + RDbView cityView; + CleanupClosePushL(cityView); + _LIT(KSQLQueryLit,"SELECT * FROM UserCities"); + // Iterate through all the cities and delete them when + // the corresponding tz id doesn't exist anymore + PrepareCityViewL(cityView, KSQLQueryLit); + // Loop through the rowset and delete the cities + for (cityView.FirstL(); cityView.AtRow(); cityView.NextL()) + { + cityView.GetL(); + if (!ExistsInSystemDbL(cityView.ColUint16(ETzCityId), *systemDataDb)) + { + cityView.DeleteL(); + } + } + CleanupStack::PopAndDestroy(&cityView); + CleanupStack::PopAndDestroy(&cachedCities); + CleanupStack::PopAndDestroy(&frequentlyUsedZones); + CleanupStack::PopAndDestroy(systemDataDb); + } + } + +void CTzLocalizationDb::UpdateTimeZoneAndCityRecordForSystemDataL(RPointerArray& aFrequentlyUsedZones, + RPointerArray& aCachedCities, TInt aTzId, CTzSystemDataDb& aSystemDataDb) + { + CTzLocalizedTimeZoneRecord* timeZone = aSystemDataDb.ReadTimeZoneL(aTzId); + CleanupStack::PushL(timeZone); + + CTzLocalizedCityRecord* city = aSystemDataDb.ReadDefaultCityL(aTzId); + CleanupStack::PushL(city); + + aCachedCities.AppendL(city); + // ownership is transferred into the array + CleanupStack::Pop(city); + aFrequentlyUsedZones.AppendL(timeZone); + // ownership is transferred into the array + CleanupStack::Pop(timeZone); + } + +TBool CTzLocalizationDb::ExistsInSystemDbL(TUint aTzId, CTzSystemDataDb& aSystemDataDb) + { + CTzLocalizedTimeZoneRecord* timeZoneRecord = NULL; + TRAPD(err, timeZoneRecord = aSystemDataDb.ReadTimeZoneL(aTzId)); + delete timeZoneRecord; + if(err == KErrNone) + { + return ETrue; + } + return EFalse; + } + +/** +Reads all the user defined cities stored in the +database. If the database is empty the +returned array will contain no elements. +@param aCities Array of cities to add the user defined to. +@internalTechnology +*/ +void CTzLocalizationDb::ReadCitiesL(RPointerArray& aCities) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + _LIT(KSQLQueryLit,"SELECT * FROM UserCities"); + DoReadCitiesL(aCities,KSQLQueryLit()); + } + +void CTzLocalizationDb::ReadCitiesL(RPointerArray& aCities, TInt aTimeZoneId) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + // Assign basic SQL query literal + _LIT(KSQLQueryLit,"SELECT * FROM UserCities WHERE TzId = "); + // Assign a buffer with enough room to hold the query including the time zone id + HBufC* sqlStr = HBufC::NewLC(KSQLQueryLit().Length() + EMaxTimeZoneIdStringLength); + // Set the buffer to the start of the query + *sqlStr = KSQLQueryLit; + // Append the time zone ID + sqlStr->Des().AppendNum(aTimeZoneId); + + DoReadCitiesL(aCities,*sqlStr); + CleanupStack::PopAndDestroy(sqlStr); + } + +void CTzLocalizationDb::ReadCitiesInGroupL(RPointerArray& aCities, TUint8 aGroupId) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + // Assign basic SQL query literal + _LIT(KSQLQueryLit,"SELECT * FROM UserCities WHERE GroupId = "); + HBufC* sqlStr = HBufC::NewLC(KSQLQueryLit().Length() + EMaxGroupIdStringLength); + // Set the buffer to the start of the query + *sqlStr = KSQLQueryLit; + // Append the time zone ID + sqlStr->Des().AppendNum(aGroupId); + + DoReadCitiesL(aCities,*sqlStr); + CleanupStack::PopAndDestroy(sqlStr); + } + +/** +Retrieves a cached zone from the database. +The calling function takes ownership of the returned zone +@param aFrequentlyUsedZone - The cached zone to return +@return a cached zone from the database +@internalTechnology +*/ +CTzLocalizedTimeZoneRecord* CTzLocalizationDb::ReadFrequentlyUsedZoneL(TInt aFrequentlyUsedZone) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + return DoReadFrequentlyUsedZoneL(aFrequentlyUsedZone); + } + +CTzLocalizedTimeZoneRecord* CTzLocalizationDb::DoReadFrequentlyUsedZoneL(TInt aFrequentlyUsedZone) + { + // You cannot pass ECachedTimeZones in as the argument, because it is only + // used to keep count of how many cached zones there are. + __ASSERT_ALWAYS(aFrequentlyUsedZone != CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument)); + + //Prepare a view of the zone table + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + + //Ensure the cursor is at the first row in the table. + zoneView.FirstL(); + + //Skip through the rows until we reach the row for the required zone + for (TInt x = 0; x < aFrequentlyUsedZone; ++x) + { + zoneView.NextL(); + } + + //Get the row + zoneView.GetL(); + + //Create the new localized time zone from the row data + CTzLocalizedTimeZoneRecord* localizedTimeZone = CTzLocalizedTimeZoneRecord::NewL(zoneView.ColUint16(ETzZoneId), + zoneView.ColDes(ETzZoneStdName), zoneView.ColDes(ETzZoneDSTName), zoneView.ColDes(ETzZoneShortStdName), + zoneView.ColDes(ETzZoneShortDSTName), zoneView.ColUint32(ETzZoneResourceId)); + + CleanupStack::PopAndDestroy(&zoneView); + return localizedTimeZone; + } + +/** +Retrieves the city used to select this time zone if set. If the time zone was not originally +set using a city then the default city for the time zone will be returned instead. +@param aFrequentlyUsedZone - The cached zone to find the city for +@return selected city for the cached zone +@internalTechnology +*/ +CTzLocalizedCityRecord* CTzLocalizationDb::ReadCachedTimeZoneCityL(TInt aFrequentlyUsedZone) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + + // You cannot pass ECachedTimeZones in as the argument, because it is only + // used to keep count of how many cached zones there are. + __ASSERT_ALWAYS(aFrequentlyUsedZone != CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument)); + + //Prepare a view of the zone table + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + + //Ensure the cursor is at the first row in the table. + zoneView.FirstL(); + + //Skip through the rows until we reach the row for the required zone + for (TInt x = 0; x < aFrequentlyUsedZone; ++x) + { + zoneView.NextL(); + } + + //Get the row + zoneView.GetL(); + + //Create the new localized time zone from the row data + TInt index = 0; + // An extra column was added but we still have to cope with the old format as we + // need to read the database contents when upgrading to the new format + if (zoneView.ColCount() == ETzZoneCityIndex) + { + index = zoneView.ColInt32(ETzZoneCityIndex); + } + CTzLocalizedCityRecord* city = CTzLocalizedCityRecord::NewL(zoneView.ColDes(ETzZoneCity), + zoneView.ColUint8(ETzZoneGroupId), index, zoneView.ColUint16(ETzZoneId), + zoneView.ColUint32(ETzZoneResourceId)); + + CleanupStack::PopAndDestroy(&zoneView); + return city; + } + +void CTzLocalizationDb::WriteCityL(const TDesC& aCityName, TUint16 aCityTzId, TUint8 aCityGroupId, TUint aCityTzResourceId) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + + // Build a SQL query to check if the city name already exists in the database + // with a matching timezoneID + RDbView cityView; + CleanupClosePushL(cityView); + HBufC* sqlStr = GetCityQueryLC(aCityName, aCityTzId); + PrepareCityViewL(cityView, *sqlStr); + CleanupStack::PopAndDestroy(sqlStr); + sqlStr = NULL; + + TInt cityCount = cityView.CountL(); + + if (cityCount == 0) + { + //City was not found. Add the new city to the database + //Retrieve the CdbColSet from the view + CDbColSet* cityColSet = cityView.ColSetL(); + CleanupStack::PushL(cityColSet); + + //Set the rowset cursor to the beginning of the rowset, + //insert an empty row to write the city to + cityView.Reset(); + cityView.InsertL(); + + //Set the city information for the new row + cityView.SetColL(ETzCityId,aCityTzId); + cityView.SetColL(ETzCityCity,aCityName); + cityView.SetColL(ETzCityGroup,aCityGroupId); + cityView.SetColL(ETzCityResourceId,aCityTzResourceId); + + CleanupStack::PopAndDestroy(cityColSet); + cityView.PutL(); // Complete insertion + } + else + { + //City already exists. + User::Leave(KErrAlreadyExists); + } + CleanupStack::PopAndDestroy(&cityView); + iZoneMutex.Wait(); + iLocalizedTimeZoneDb.Compact(); + iZoneMutex.Signal(); + } + +void CTzLocalizationDb::DeleteCityL(const TDesC& aCityName, TUint16 aCityTzId) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + + //Build a SQL query to check if the city name and time zone ID exist in the database + RDbView cityView; + CleanupClosePushL(cityView); + HBufC* sqlStr = GetCityQueryLC(aCityName, aCityTzId); + PrepareCityViewL(cityView, *sqlStr); + CleanupStack::PopAndDestroy(sqlStr); + sqlStr = NULL; + + TInt cityCount = cityView.CountL(); + + if (cityCount > 0) + { + //A city with this name exists in the database. Delete it. + if (cityView.FirstL()) + { + cityView.DeleteL(); + //Reset the cursor, as it now points to an invalid row + cityView.Reset(); + } + } + else + { + //City was not found + User::Leave(KErrNotFound); + } + CleanupStack::PopAndDestroy(&cityView); + iZoneMutex.Wait(); + iLocalizedTimeZoneDb.Compact(); + iZoneMutex.Signal(); + } + +/** +Stores the localized time zone in the database for easy retrieval. +The database keeps track of the two most recently used zones, these are updated every time +a new zone is set. The zone to be replaced becomes recently used zone 1, and recently used zone 1 becomes +recently used zone 2. The old recently used zone 2 is discarded. +@param Any city in the time zone to store +@param aFrequentlyUsedZone - specifies which time zone to overwrite in the database +@internalTechnology +*/ +void CTzLocalizationDb::WriteFrequentlyUsedZoneL(const CTzLocalizedTimeZoneRecord& aTimeZone, + const CTzLocalizedCityRecord& aCity, TInt aFrequentlyUsedZone) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + + // Only the Current, Home and Zone of Interest can be changed explicitly + // using this function. Recent Zones are automatically updated. + __ASSERT_ALWAYS(aFrequentlyUsedZone < CTzLocalizedTimeZone::ERecentZone1, User::Leave(KErrArgument)); + + iZoneMutex.Wait(); + + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + //Ensure the cursor is at the first row in the table. + zoneView.FirstL(); + TInt x; + //Skip through the rows until we reach the row for the zone to update + for (x = 0; x < aFrequentlyUsedZone; ++x) + { + zoneView.NextL(); + } + + //Get the row + zoneView.GetL(); + + //Bookmark the row + TDbBookmark rowToUpdate(zoneView.Bookmark()); + + //Insert a copy of the row - this is now the last row in the table, and will become + //recently used zone 1 after the original recently used zones are deleted + + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + zoneView.InsertCopyL(); + zoneView.PutL(); + CleanupStack::Pop(); + + //Position the cursor back at the row to update + zoneView.GotoL(rowToUpdate); + + //Update the row with the new data + DoWriteFrequentlyUsedZoneL(zoneView, aTimeZone, aCity); + + //Reset the cursor back to the first row in the table. + zoneView.FirstL(); + + //Skip through the rows until we reach the row for recent zone 1 + for (x = 0; x < CTzLocalizedTimeZone::ERecentZone1; ++x) + { + zoneView.NextL(); + } + + //Get the row + zoneView.GetL(); + + //Bookmark the row + TDbBookmark recentZone1(zoneView.Bookmark()); + + //Insert a copy of the row - this is now the last row in the table, and will become + //recently used zone 2 after the original recently used zones are deleted + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + zoneView.InsertCopyL(); + zoneView.PutL(); + CleanupStack::Pop(); + + //Reset the cursor to the orignal recent zone 1 position + zoneView.GotoL(recentZone1); + + //Delete the original recent zone 1 and recent zone 2. + //The new recent zone 1 and recent zone 2 are moved back into the correct + //position by the removal of the preceding rows + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + zoneView.DeleteL(); + CleanupStack::Pop(); + + zoneView.NextL(); + + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + zoneView.DeleteL(); + CleanupStack::Pop(); + + //Cursor is now invalid (pointing to an empty row) + //and shuold be reset to a known state before reusing + //Cleanup + CleanupStack::PopAndDestroy(&zoneView); + iLocalizedTimeZoneDb.Compact(); + iZoneMutex.Signal(); + } + +/** +Sets all the cached zones and their associated cities to be those that are +supplied. +@param aTimeZones Array of time zones to be written. +@param aCities Array of cities to be written. +@internalTechnology +*/ +void CTzLocalizationDb::WriteAllFrequentlyUsedZonesL(const RPointerArray& aTimeZones, + const RPointerArray& aCities) + { + if (iLocked) + { + User::Leave(KErrLocked); + } + DoWriteAllFrequentlyUsedZonesL(aTimeZones, aCities); + } + +void CTzLocalizationDb::DoWriteAllFrequentlyUsedZonesL(const RPointerArray& aTimeZones, + const RPointerArray& aCities) + { + // Ensure that the numbers of items in the arrays are the expected amount + __ASSERT_ALWAYS(aTimeZones.Count() == CTzLocalizedTimeZone::ECachedTimeZones && + aCities.Count() == CTzLocalizedTimeZone::ECachedTimeZones, User::Leave(KErrArgument)); + + iZoneMutex.Wait(); + + RDbView zoneView; + CleanupClosePushL(zoneView); + PrepareZoneViewL(zoneView); + //Ensure the cursor is at the first row in the table. + zoneView.FirstL(); + + //Skip through the rows until we reach the row for the zone to update + for (TInt i = 0; i < CTzLocalizedTimeZone::ECachedTimeZones; ++i) + { + DoWriteFrequentlyUsedZoneL(zoneView, *aTimeZones[i], *aCities[i]); + zoneView.NextL(); + } + + CleanupStack::PopAndDestroy(&zoneView); + + iLocalizedTimeZoneDb.Compact(); + iZoneMutex.Signal(); + } + +/** +Opens the a view on the city table and returns a reference to it. +The view should be released after use with a call to CloseCityView() +@param aSql A sql string to prepare the view with +@return reference to opened iCityTable +@internalTechnology +*/ +void CTzLocalizationDb::PrepareCityViewL(RDbView& aCityView, const TDesC& aSqlQuery) + { + User::LeaveIfError(aCityView.Prepare(iLocalizedTimeZoneDb, TDbQuery(aSqlQuery), aCityView.EUpdatable)); + User::LeaveIfError(aCityView.EvaluateAll()); + } + +/** +Opens a view to the zone table +@internalTechnology +*/ +void CTzLocalizationDb::PrepareZoneViewL(RDbView& aZoneView) + { + _LIT(KReadZoneView,"SELECT * FROM FrequentlyUsedZones"); + User::LeaveIfError(aZoneView.Prepare(iLocalizedTimeZoneDb, TDbQuery(KReadZoneView), aZoneView.EUpdatable)); + User::LeaveIfError(aZoneView.EvaluateAll()); + } + +/** +Returns the SQL string that will pick the specified city out of the user-added +cities database. Leaves the returned HBufC pointer on the Cleanup Stack. +The query is of the form: + "SELECT * FROM UserCities WHERE City = 'London' AND TZID = 2592" +@param aCity The city to make the query for. +@return The SQL Query that will select the aCity form the DB +@internalTechnology +*/ +HBufC* CTzLocalizationDb::GetCityQueryLC(const TDesC& aCityName, TInt aCityTimeZoneId) + { + // Assign the start and middle of the basic SQL query literal + _LIT(KSQLQueryLitStart,"SELECT * FROM UserCities WHERE City = '"); + _LIT(KSQLQueryLitMiddle,"' AND TZID = "); + + /* Assign a buffer with enough room to hold the query including the city + name and the time zone id */ + TInt maxBufferLength = KSQLQueryLitStart().Length() + KSQLQueryLitMiddle().Length() + + aCityName.Length() + EMaxTimeZoneIdStringLength; + HBufC* sqlStr = HBufC::NewLC(maxBufferLength); + + // Append the beginning of the query + sqlStr->Des().Append(KSQLQueryLitStart); + // Append the city name into the query + sqlStr->Des().Append(aCityName); + // Append the middle of the query + sqlStr->Des().Append(KSQLQueryLitMiddle); + // Append the time zone ID into the query + sqlStr->Des().AppendNum(aCityTimeZoneId); + + return sqlStr; + } + +HBufC* CTzLocalizationDb::GetCityQueryLC(TInt aCityTimeZoneId) + { + // Assign the start and middle of the basic SQL query literal + _LIT(KSQLQueryLitStart,"SELECT * FROM UserCities WHERE TZID = "); + + /* Assign a buffer with enough room to hold the query including the city + name and the time zone id */ + TInt maxBufferLength = KSQLQueryLitStart().Length() + EMaxTimeZoneIdStringLength; + HBufC* sqlStr = HBufC::NewLC(maxBufferLength); + + // Append the beginning of the query + sqlStr->Des().Append(KSQLQueryLitStart); + // Append the time zone ID into the query + sqlStr->Des().AppendNum(aCityTimeZoneId); + + return sqlStr; + } + +/** +Reads the user defined cities in the database +matched by the SQL query into the supplied array. If the +database is empty the returned array will contain no elements. +@param aCities array of cities to add the user defined to. +@param aSqlString - SQL search string determining the cities to retrieve +@internalTechnology +*/ +void CTzLocalizationDb::DoReadCitiesL(RPointerArray& aCities, const TDesC& aSqlString) + { + RDbView cityView; + CleanupClosePushL(cityView); + PrepareCityViewL(cityView, aSqlString); + + //Loop through the rowset + for (cityView.FirstL(); cityView.AtRow(); cityView.NextL()) + { + // Fetch a cached copy of current row + cityView.GetL(); + + //Create the new city from the row data + CTzLocalizedCityRecord* newCity = CTzLocalizedCityRecord::NewLC(cityView.ColDes(ETzCityCity), + cityView.ColUint8(ETzCityGroup), aCities.Count(), cityView.ColUint16(ETzCityId), + cityView.ColUint32(ETzCityResourceId)); + + //Append the new city to the city array - aCities takes ownership of newCity + aCities.AppendL(newCity); + CleanupStack::Pop(newCity); + } + CleanupStack::PopAndDestroy(&cityView); + } + +/** +Does the actual writing of a zone and city into the database. iZoneView must +have already been prepared and moved to the correct offset into the row set +before this function is called. e.g. at least the following should have been +done: + PrepareZoneViewL(); + iZoneView.FirstL(); +Otherwise the cursor position may be invalid and a DBMS panic will occur. +@param aTimeZone The time zone to write. +@param aCity The city to write. +@param aFrequentlyUsedZone The enum of the cached zone to write to. +@internalTechnology +*/ +void CTzLocalizationDb::DoWriteFrequentlyUsedZoneL(RDbView& aZoneView, const CTzLocalizedTimeZoneRecord& aTimeZone, + const CTzLocalizedCityRecord& aCity) + { + CleanupStack::PushL(TCleanupItem(ReleaseMutex,&iZoneMutex)); + aZoneView.UpdateL(); + aZoneView.SetColL(ETzZoneId, (TInt)aTimeZone.Id()); + aZoneView.SetColL(ETzZoneStdName, aTimeZone.StandardName()); + aZoneView.SetColL(ETzZoneDSTName, aTimeZone.DaylightName()); + aZoneView.SetColL(ETzZoneShortStdName, aTimeZone.ShortStandardName()); + aZoneView.SetColL(ETzZoneShortDSTName, aTimeZone.ShortDaylightName()); + aZoneView.SetColL(ETzZoneCity, aCity.Name()); + aZoneView.SetColL(ETzZoneGroupId, aCity.GroupId()); + aZoneView.SetColL(ETzZoneResourceId, aTimeZone.ResourceId()); + if (aZoneView.ColCount() == ETzZoneCityIndex) + { + aZoneView.SetColL(ETzZoneCityIndex, aCity.Index()); + } + aZoneView.PutL(); + CleanupStack::Pop(); + } + +TInt CTzLocalizationDb::GetTimeZoneIdFromTzServerL(CTzSystemDataDb& aSystemDataDb) + { + // Get current time zone using the current CTzId from the time zone server + TUint timeZoneIdInt = iServer.TimeZoneManager().GetTimeZoneIdL().TimeZoneNumericID(); + + // Is the time zone ID the unknown/invalid ID? + // This is temporary measure that is required until PREQ 234' TzServer + // changes are introduced + const TUint32 KUnknownTZId = 0x0ffffff0; + if((TUint32)timeZoneIdInt == KUnknownTZId) + { + // Return the ID of the DEFAULT home zone instead + CTzLocalizedTimeZoneRecord* homeZone = aSystemDataDb.ReadFrequentlyUsedZoneL(CTzLocalizedTimeZone::EHomeZone); + CleanupStack::PushL(homeZone); + timeZoneIdInt = homeZone->Id(); + CleanupStack::PopAndDestroy(homeZone); + } + + return timeZoneIdInt; + } + +void CTzLocalizationDb::NotifyUserTzNamesChangeL(TTzUserDataChange aChange) + { + // If an existing user-defined time zone is updated it means we may have + // to refresh the data in the frequently used zones table but the city table + // only contains the time zone id so there is nothing to update in there. + + // If an existing user-defined time zone is deleted it means we may have + // to refresh the data in the frequently used zones table and the city table + // because it may contain the time zone id that has been deleted. + CTzSystemDataDb* systemDataDb = CTzSystemDataDb::NewLC(); + TBool frequentlyUsedZonesNeedUpdating = EFalse; + RPointerArray frequentlyUsedZones; + CleanupStack::PushL(TCleanupItem(CleanupTimeZonePointerArray,&frequentlyUsedZones)); + RPointerArray cachedCities; + CleanupStack::PushL(TCleanupItem(CleanupCityPointerArray,&cachedCities)); + for (TInt i = CTzLocalizedTimeZone::ECurrentZone; i < CTzLocalizedTimeZone::ECachedTimeZones; ++i) + { + CTzLocalizedTimeZone::TTzFrequentlyUsedZone freqUsedZone = (CTzLocalizedTimeZone::TTzFrequentlyUsedZone)i; + CTzLocalizedTimeZoneRecord* timeZoneRecord = ReadFrequentlyUsedZoneL(freqUsedZone); + CleanupStack::PushL(timeZoneRecord); + CTzLocalizedCityRecord* cityRecord = ReadCachedTimeZoneCityL(freqUsedZone); + CleanupStack::PushL(cityRecord); + + if (timeZoneRecord->Id() == aChange.iTzId || cityRecord->TzId() == aChange.iTzId) + { + if (aChange.iOperation == ETzUserDataUpdated) + { + CleanupStack::PopAndDestroy(cityRecord); + cityRecord = NULL; + CleanupStack::PopAndDestroy(timeZoneRecord); + timeZoneRecord = NULL; + UpdateTimeZoneAndCityRecordL(frequentlyUsedZones, cachedCities, aChange.iTzId); + } + else if (aChange.iOperation == ETzUserDataDeleted) + { + CleanupStack::PopAndDestroy(cityRecord); + cityRecord = NULL; + CleanupStack::PopAndDestroy(timeZoneRecord); + timeZoneRecord = NULL; + + if(freqUsedZone != CTzLocalizedTimeZone::ECurrentZone) + { + // Put the default cached zone and its default city in the array instead + timeZoneRecord = systemDataDb->ReadFrequentlyUsedZoneL(freqUsedZone); + } + else + { + // get the current zone from the time zone server + TInt id = GetTimeZoneIdFromTzServerL(*systemDataDb); + timeZoneRecord = systemDataDb->ReadTimeZoneL(id); + } + CleanupStack::PushL(timeZoneRecord); + cityRecord = systemDataDb->ReadDefaultCityL(timeZoneRecord->Id()); + CleanupStack::PushL(cityRecord); + + cachedCities.AppendL(cityRecord); + // ownership is transferred into the array + CleanupStack::Pop(cityRecord); + frequentlyUsedZones.AppendL(timeZoneRecord); + // ownership is transferred into the array + CleanupStack::Pop(timeZoneRecord); + } + frequentlyUsedZonesNeedUpdating = ETrue; + } + else + { + cachedCities.AppendL(cityRecord); + // ownership is transferred into the array + CleanupStack::Pop(cityRecord); + frequentlyUsedZones.AppendL(timeZoneRecord); + // ownership is transferred into the array + CleanupStack::Pop(timeZoneRecord); + } + } + + if (frequentlyUsedZonesNeedUpdating) + { + WriteAllFrequentlyUsedZonesL(frequentlyUsedZones, cachedCities); + } + + if (aChange.iOperation == ETzUserDataDeleted) + { + DeleteCitiesL(aChange); + iZoneMutex.Wait(); + iLocalizedTimeZoneDb.Compact(); + iZoneMutex.Signal(); + } + CleanupStack::PopAndDestroy(&cachedCities); + CleanupStack::PopAndDestroy(&frequentlyUsedZones); + CleanupStack::PopAndDestroy(systemDataDb); + } + +void CTzLocalizationDb::UpdateTimeZoneAndCityRecordL(RPointerArray& aFrequentlyUsedZones, RPointerArray& aCachedCities, TInt aTzId) + { + CTzUserNames* names = iServer.UserTimeZoneDb().ReadTzNamesL(aTzId); + CleanupStack::PushL(names); + + CTzLocalizedTimeZoneRecord* timeZoneRecord = CTzLocalizedTimeZoneRecord::NewL(aTzId, names->StandardName(), + names->DaylightSaveName(), names->ShortStandardName(), names->ShortDaylightSaveName(), 0); + CleanupStack::PushL(timeZoneRecord); + + CTzLocalizedCityRecord* cityRecord = CTzLocalizedCityRecord::NewL(names->CityName(), 0, 0, aTzId, 0); + CleanupStack::PushL(cityRecord); + + aCachedCities.AppendL(cityRecord); + // ownership is transferred into the array + CleanupStack::Pop(cityRecord); + aFrequentlyUsedZones.AppendL(timeZoneRecord); + // ownership is transferred into the array + CleanupStack::Pop(timeZoneRecord); + CleanupStack::PopAndDestroy(names); + } + +void CTzLocalizationDb::DeleteCitiesL(TTzUserDataChange aChange) + { + // Get the cities with the deleted time zone id + RDbView cityView; + CleanupClosePushL(cityView); + if(aChange.iOperation == ETzUserDataDeleted) + { + HBufC* sqlStr = GetCityQueryLC(aChange.iTzId); + PrepareCityViewL(cityView, *sqlStr); + CleanupStack::PopAndDestroy(sqlStr); + sqlStr = NULL; + } + else if(aChange.iOperation == ETzUserDataRestored) + { + _LIT(KSQLQueryLit,"SELECT * FROM UserCities"); + // Iterate through all the cities and delete them when + // the corresponding tz id doesn't exist anymore + PrepareCityViewL(cityView, KSQLQueryLit); + } + // Loop through the rowset and delete the cities + for (cityView.FirstL(); cityView.AtRow(); cityView.NextL()) + { + if(aChange.iOperation == ETzUserDataDeleted) + { + cityView.DeleteL(); + } + else if(aChange.iOperation == ETzUserDataRestored) + { + cityView.GetL(); + if (!iServer.TimeZoneManager().TzDataProvider().IsIdInDbL(cityView.ColUint16(ETzCityId))) + { + cityView.DeleteL(); + } + } + } + CleanupStack::PopAndDestroy(&cityView); + } + +/** +Releases the mutex if leave occurs between wait and signal. +@internalTechnology +*/ +void CTzLocalizationDb::ReleaseMutex(TAny* iTarget) + { + RMutex* mutex = static_cast(iTarget); + mutex->Signal(); + } + +// Backup and restore operations +void CTzLocalizationDb::BackupBeginningL() + { + CloseDb(); + iLocked = ETrue; + } + +void CTzLocalizationDb::BackupCompletedL() + { + OpenDbL(); + iLocked = EFalse; + } + +void CTzLocalizationDb::RestoreBeginningL() + { + CloseDb(); + iLocked = ETrue; + } + +void CTzLocalizationDb::RestoreDbL() + { + // When the Tz server is connected or a restore completes, we have to + // refresh the data in the frequently used zones table and the city table + // because it may contain the time zone id that has been deleted. Or if the + // time zone id is still there but the details of the rule has been changed. + + CTzSystemDataDb* systemDataDb = CTzSystemDataDb::NewLC(); + + TBool frequentlyUsedZonesNeedUpdating = EFalse; + + RPointerArray frequentlyUsedZones; + CleanupStack::PushL(TCleanupItem(CleanupTimeZonePointerArray,&frequentlyUsedZones)); + + RPointerArray cachedCities; + CleanupStack::PushL(TCleanupItem(CleanupCityPointerArray,&cachedCities)); + + for (TInt i = CTzLocalizedTimeZone::ECurrentZone; i < CTzLocalizedTimeZone::ECachedTimeZones; ++i) + {//Loop through each record in frequently used table + CTzLocalizedTimeZone::TTzFrequentlyUsedZone freqUsedZone = (CTzLocalizedTimeZone::TTzFrequentlyUsedZone)i; + CTzLocalizedTimeZoneRecord* timeZoneRecord = DoReadFrequentlyUsedZoneL(freqUsedZone); + TUint tzid = timeZoneRecord->Id(); + delete timeZoneRecord; + TBool tzIdExistInDb = iServer.TimeZoneManager().TzDataProvider().IsIdInDbL(tzid); + + if(!tzIdExistInDb) + { + if(freqUsedZone == CTzLocalizedTimeZone::ECurrentZone) + { + tzid = GetTimeZoneIdFromTzServerL(*systemDataDb); + } + else + { + tzid = GetFrequentlyUsedDefaultZoneIdL(freqUsedZone, *systemDataDb); + } + } + + if (CTzId::IsUserTzId(tzid)) + { + UpdateTimeZoneAndCityRecordL(frequentlyUsedZones, cachedCities, tzid); + } + else + { + UpdateTimeZoneAndCityRecordForSystemDataL(frequentlyUsedZones, cachedCities, tzid, *systemDataDb); + } + + frequentlyUsedZonesNeedUpdating = ETrue; + } + + if (frequentlyUsedZonesNeedUpdating) + { + //Update the frequently used zone table + DoWriteAllFrequentlyUsedZonesL(frequentlyUsedZones, cachedCities); + } + + TTzUserDataChange change; + change.iOperation = ETzUserDataRestored; + change.iTzId = KInvalidTzId; + //Delete the city infomation if the associated time zone no longer exist. + DeleteCitiesL(change); + + CleanupStack::PopAndDestroy(&cachedCities); + CleanupStack::PopAndDestroy(&frequentlyUsedZones); + CleanupStack::PopAndDestroy(systemDataDb); + } + +/** +Get the localized default time zone Id for the given frequently used time zone. +The default time zone for each of the possible frequently used time zones may be +specified in the TZ Server repository or in the TZ Localization resource file. +Check the possible sources in this order. + +@param aFreqUsedZone The frequently used time zone for which the localized +default time zone is required. +@param aSystemDataDb For TZ Localization database access. + +@return The localized default time zone Id for the given frequently used time zone. +*/ +TInt CTzLocalizationDb::GetFrequentlyUsedDefaultZoneIdL( + CTzLocalizedTimeZone::TTzFrequentlyUsedZone aFreqUsedZone, + CTzSystemDataDb& aSystemDataDb) + { + // Assume that we will not find the key in the repository or that we do find + // the key but it has no value. If either of these scenarios is true then + // we will use the time zone identifier recorded in the resource file for + // the default time zone. + + TUint32 defaultTimeZoneKey = GetFrequentlyUsedDefaultZoneCenRepKeyL(aFreqUsedZone); + CRepository* tzRepository = CRepository::NewL(NTzUpdate::KPropertyCategory); + CleanupStack::PushL(tzRepository); + TInt defaultTimeZoneId = 0; + TInt err = tzRepository->Get(defaultTimeZoneKey, defaultTimeZoneId); + CleanupStack::PopAndDestroy(tzRepository); + + if(err != KErrNotFound) + { + User::LeaveIfError(err); + } + + if(defaultTimeZoneId == 0) + { + defaultTimeZoneId = aSystemDataDb.ReadFrequentlyUsedZoneIdL(aFreqUsedZone); + } + + return defaultTimeZoneId; + } + +/** +Get the TZ Server's CenRep repository key for the given frequently used zone. + +@param aFreqUsedZone The frequently used time zone for which the TZ Server's +CenRep repository key is required. + +@return The TZ Server's CenRep repository key for the given frequently used +zone. +*/ +TUint32 CTzLocalizationDb::GetFrequentlyUsedDefaultZoneCenRepKeyL(CTzLocalizedTimeZone::TTzFrequentlyUsedZone aFreqUsedZone) + { + // These key values are copied from those defined in tzconfigagent.h. We + // want to keep the key values private - this is one way to do it. + const TUint32 KDefaultHomeTimeZoneKey = 0x3UL; + const TUint32 KDefaultInterestTimeZoneKey = 0x4UL; + const TUint32 KDefaultRecent1TimeZoneKey = 0x5UL; + const TUint32 KDefaultRecent2TimeZoneKey = 0x6UL; + + TUint32 key = 0; + + switch(aFreqUsedZone) + { + case CTzLocalizedTimeZone::EHomeZone: + { + key = KDefaultHomeTimeZoneKey; + } + break; + + case CTzLocalizedTimeZone::EInterestZone: + { + key = KDefaultInterestTimeZoneKey; + } + break; + + case CTzLocalizedTimeZone::ERecentZone1: + { + key = KDefaultRecent1TimeZoneKey; + } + break; + + case CTzLocalizedTimeZone::ERecentZone2: + { + key = KDefaultRecent2TimeZoneKey; + } + break; + + default: + { + User::Leave(KErrArgument); + } + } + + return key; + } + +void CTzLocalizationDb::RestoreCompletedL() + { + OpenDbL(); + iLocked = EFalse; + RestoreDbL(); + } +