--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tzservices/tzserver/Server/Source/tzuserdata.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,1022 @@
+// 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 "tzuserdata.h"
+#include <tz.h>
+#include <f32file.h>
+#include <e32property.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <tzusernames.h>
+#include <tzuserdefineddata.h>
+#endif
+#include "tzidinternal.h"
+
+_LIT(KUserDatabaseName, "c:\\private\\1020383e\\SQLite__tzuserdata.db");
+_LIT(KTzPrivatePath, "c:\\private\\1020383e\\");
+
+// Transaction constants
+_LIT(KBeginTransaction,"BEGIN TRANSACTION;");
+_LIT(KCommitTransaction,"COMMIT;");
+_LIT(KRollbackTransaction,"ROLLBACK;");
+
+// Tz Rules Table Parameters
+_LIT(KTzRulesTblTzIdParam, ":tzId");
+_LIT(KTzRulesTblRuleTypeParam, ":ruleType");
+_LIT(KTzRulesTblDSTStartTimeParam, ":dstStartTime");
+_LIT(KTzRulesTblDSTStartRefParam, ":dstStartRef");
+_LIT(KTzRulesTblDSTEndTimeParam, ":dstEndTime");
+_LIT(KTzRulesTblDSTEndRefParam, ":dstEndRef");
+_LIT(KTzRulesTblOldOffsetParam, ":oldOffset");
+_LIT(KTzRulesTblNewOffsetParam, ":newOffset");
+_LIT(KTzRulesTblMonthParam, ":month");
+_LIT(KTzRulesTblDayParam, ":day");
+_LIT(KTzRulesTblWeekParam, ":week");
+_LIT(KTzRulesTblTimeRefParam, ":timeRef");
+_LIT(KTzRulesTblMinsParam, ":mins");
+
+// Tz Rules Table Index
+_LIT(KTzRulesTblRuleTypeIndex, "ruleType");
+_LIT(KTzRulesTblDSTStartTimeIndex, "dstStartTime");
+_LIT(KTzRulesTblDSTStartRefIndex, "dstStartRef");
+_LIT(KTzRulesTblDSTEndTimeIndex, "dstEndTime");
+_LIT(KTzRulesTblDSTEndRefIndex, "dstEndRef");
+_LIT(KTzRulesTblOldOffsetIndex, "oldOffset");
+_LIT(KTzRulesTblNewOffsetIndex, "newOffset");
+_LIT(KTzRulesTblMonthIndex, "month");
+_LIT(KTzRulesTblDayIndex, "day");
+_LIT(KTzRulesTblWeekIndex, "week");
+_LIT(KTzRulesTblTimeRefIndex, "timeRef");
+_LIT(KTzRulesTblMinsIndex, "mins");
+
+// Tz Names Table Parameters
+_LIT(KTzNamesTblTzIdParam, ":tzId");
+_LIT(KTzNamesTblStdNameParam, ":stdName");
+_LIT(KTzNamesTblShortStdNameParam, ":shortStdName");
+_LIT(KTzNamesTblDSTNameParam, ":dstName");
+_LIT(KTzNamesTblShortDSTNameParam, ":shortDstName");
+_LIT(KTzNamesTblCityNameParam, ":cityName");
+_LIT(KTzNamesTblRegionNameParam, ":regionName");
+
+// Tz Names Table Index
+_LIT(KTzNamesTblTzIdIndex, "tzId");
+_LIT(KTzNamesTblStdNameIndex, "stdName");
+_LIT(KTzNamesTblShortStdNameIndex, "shortStdName");
+_LIT(KTzNamesTblDSTNameIndex, "dstName");
+_LIT(KTzNamesTblShortDSTNameIndex, "shortDstName");
+_LIT(KTzNamesTblCityNameIndex, "cityName");
+_LIT(KTzNamesTblRegionNameIndex, "regionName");
+
+// Identifier Table Index
+_LIT(KNextTzIdentifierIndex, "nextTzId");
+
+// InitialStdOffset Table Param
+_LIT(KTzInitialStdOffsetTblTzIdParam, ":tzId");
+_LIT(KTzInitialStdOffsetTblStdInitialOffsetParam, ":initialStdOffset");
+
+// InitialStdOffset Table Index
+_LIT(KTzInitialStdOffsetTblStdInitialOffsetIndex, "initialStdOffset");
+
+// Create statements
+_LIT8 (KTzRulesCreateStmnt, "CREATE TABLE rules (tzId INTEGER NOT NULL, ruleType \
+ INTEGER, dstStartTime INT64 NOT NULL, dstStartRef INTEGER, \
+ dstEndTime INT64 NOT NULL, dstEndRef INTEGER, oldOffset \
+ INTEGER NOT NULL, newOffset INTEGER NOT NULL, month INTEGER, \
+ day INTEGER, week INTEGER, timeRef INTEGER, mins INTEGER NOT NULL)");
+
+_LIT8 (KTzNamesCreateStmnt, "CREATE TABLE names ( tzId INTEGER NOT NULL PRIMARY \
+ KEY, stdName CHAR(255), shortStdName CHAR(10), dstName \
+ CHAR(255), shortDstName CHAR(10), cityName CHAR(255), \
+ regionName CHAR(255))");
+
+_LIT8 (KTzIdentifierCreateStmnt, "CREATE TABLE identifier ( nextTzId INTEGER NOT NULL )");
+
+_LIT8 (KTzInitialStdOffsetCreateStmnt, "CREATE TABLE initialStdOffset (tzId INTEGER NOT NULL, initialStdOffset INTEGER)");
+
+// Insert statements
+_LIT8(KInsertRulesStmnt, "INSERT INTO rules (tzId, ruleType, dstStartTime, dstStartRef, \
+ dstEndTime, dstEndRef, oldOffset, newOffset, month, day, \
+ week, timeRef, mins) VALUES (:tzId, :ruleType, :dstStartTime,\
+ :dstStartRef, :dstEndTime, :dstEndRef, :oldOffset, :newOffset,\
+ :month, :day, :week, :timeRef, :mins)");
+
+_LIT8(KInsertNamesStmnt, "INSERT INTO names(tzId, stdName, shortStdName, dstName, shortDstName,\
+ cityName, regionName) VALUES(:tzId, :stdName, :shortStdName, :dstName,\
+ :shortDstName, :cityName, :regionName)");
+
+_LIT(KInsertIdentifierStmnt, "INSERT INTO identifier (nextTzId) VALUES (%d)");
+
+_LIT8(KInsertInitialStdOffsetStmnt, "INSERT INTO initialStdOffset (tzId, initialStdOffset) \
+ VALUES (:tzId, :initialStdOffset)");
+
+//Select statements
+_LIT8(KSelectNextTzIdStmnt, "SELECT nextTzId FROM identifier");
+
+_LIT(KSelectRulesStmnt, "SELECT * FROM rules WHERE tzId = %d");
+
+_LIT(KSelectRulesCountStmnt, "SELECT COUNT(tzId) FROM rules WHERE tzId = %d");
+
+_LIT(KSelectNamesCountStmnt, "SELECT COUNT(tzId) FROM names WHERE tzId = %d");
+
+_LIT(KSelectTzIdCountFromNamesStmnt, "SELECT COUNT(tzId) FROM names WHERE tzId = %d");
+
+_LIT(KSelectNamesStmnt, "SELECT * FROM names WHERE tzId = %d");
+
+_LIT(KSelectTzIdFromNamesStmnt, "SELECT tzId FROM names");
+
+_LIT(KSelectInitialStdOffsetStmnt, "SELECT initialStdOffset FROM initialStdOffset WHERE tzId = %d");
+
+//Update statements
+_LIT (KUpdateIdentifierStmnt, "UPDATE identifier SET nextTzId = :nextTzId");
+
+//Delete statements
+_LIT(KDeleteRulesStmnt, "DELETE FROM rules WHERE tzId = %d");
+
+_LIT(KDeleteNamesStmnt, "DELETE FROM names WHERE tzId = %d");
+
+_LIT(KDeleteInitialStdOffset, "DELETE FROM initialStdOffset WHERE tzId = %d");
+
+const TInt KSqlStringLength = 100;
+const TUint KOutOfBoundsUserId = 0x5000;
+
+CTzUserDataDb* CTzUserDataDb::NewL()
+ {
+ CTzUserDataDb* self = new(ELeave) CTzUserDataDb();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CTzUserDataDb::CTzUserDataDb()
+ {
+ }
+
+CTzUserDataDb::~CTzUserDataDb()
+ {
+ // We don't own the pointers in this array
+ iChangeObservers.Close();
+ iDatabase.Close();
+ }
+
+void CTzUserDataDb::ConstructL()
+ {
+ OpenL();
+ }
+
+void CTzUserDataDb::Close()
+ {
+ iDatabase.Close();
+ }
+
+void CTzUserDataDb::OpenL()
+ {
+ RFs fs;
+ CleanupClosePushL(fs);
+
+ // Open the database
+ TInt ret = iDatabase.Open(KUserDatabaseName());
+ // If the database could not be opened because
+ // the file was not found in the path provided, create the directory
+ if(ret == KErrNotFound || ret == KErrPathNotFound)
+ {
+ User::LeaveIfError(fs.Connect());
+ ret = fs.MkDir(KTzPrivatePath);
+ // If there are no errors while creating path
+ // or the path already exists, create the database
+ if(ret == KErrNone || ret == KErrAlreadyExists)
+ {
+ CreateL();
+ }
+ }
+ else
+ {
+ User::LeaveIfError(ret);
+ }
+ CleanupStack::PopAndDestroy(&fs);
+ }
+
+void CTzUserDataDb::CreateL()
+ {
+ User::LeaveIfError(iDatabase.Create(KUserDatabaseName()));
+ iDatabase.Close();
+ CreateSchemaL();
+ }
+
+void CTzUserDataDb::CreateSchemaL()
+ {
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ User::LeaveIfError(iDatabase.Open(KUserDatabaseName()));
+ User::LeaveIfError(stmt.Prepare(iDatabase, KTzRulesCreateStmnt));
+ User::LeaveIfError(stmt.Exec());
+ stmt.Close();
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KTzNamesCreateStmnt));
+ User::LeaveIfError(stmt.Exec());
+ stmt.Close();
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KTzIdentifierCreateStmnt));
+ User::LeaveIfError(stmt.Exec());
+ stmt.Close();
+
+ TBuf<KSqlStringLength> sqlId;
+ sqlId.Format(KInsertIdentifierStmnt, KUserTzIdMin);
+ User::LeaveIfError(stmt.Prepare(iDatabase, sqlId));
+ User::LeaveIfError(stmt.Exec());
+ stmt.Close();
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KTzInitialStdOffsetCreateStmnt));
+ User::LeaveIfError(stmt.Exec());
+ stmt.Close();
+
+ CleanupStack::PopAndDestroy(&stmt);
+ }
+
+TInt CTzUserDataDb::CreateTzL(const CTzRules& aRules, const CTzUserNames& aNames)
+ {
+ if(iBackupInProgress || iRestoreInProgress)
+ {
+ User::Leave(KErrLocked);
+ }
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ BeginTransactionL();
+
+ TInt err = stmt.Prepare(iDatabase, KSelectNextTzIdStmnt);
+ User::LeaveIfError(err);
+ TInt colIndex = stmt.ColumnIndex(KNextTzIdentifierIndex);
+ User::LeaveIfError(colIndex);
+ while((err = stmt.Next()) == KSqlAtRow)
+ {
+ iNextCandidateTzId = stmt.ColumnInt64(colIndex);
+ }
+
+ stmt.Close();
+
+ // Check if the next available user ID is valid
+ if(iNextCandidateTzId == KOutOfBoundsUserId || IsIdInDbL(iNextCandidateTzId))
+ {
+ iNextCandidateTzId = FindUnusedTzIdL();
+ }
+
+ // If all the user IDs have been used, leave with KErrOverflow
+ if(iNextCandidateTzId == KOutOfBoundsUserId)
+ {
+ User::Leave(KErrOverflow);
+ }
+
+ TUint retId = iNextCandidateTzId;
+ TInt index;
+ TInt count = aRules.Count();
+ for(TInt i=0; i<count; i++)
+ {
+ TTzRule& rule = const_cast<CTzRules&>(aRules)[i];
+
+ // Insert a row in the rules
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertRulesStmnt()));
+
+ index = stmt.ParameterIndex(KTzRulesTblTzIdParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt64(index, iNextCandidateTzId));
+ index = stmt.ParameterIndex(KTzRulesTblRuleTypeParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iDayRule));
+ index = stmt.ParameterIndex(KTzRulesTblDSTStartTimeParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt64(index, rule.iFrom.iTime.Int64()));
+ index = stmt.ParameterIndex(KTzRulesTblDSTStartRefParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iFrom.iTimeReference));
+ index = stmt.ParameterIndex(KTzRulesTblDSTEndTimeParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt64(index, rule.iTo.iTime.Int64()));
+ index = stmt.ParameterIndex(KTzRulesTblDSTEndRefParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iTo.iTimeReference));
+ index = stmt.ParameterIndex(KTzRulesTblOldOffsetParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iOldLocalTimeOffset));
+ index = stmt.ParameterIndex(KTzRulesTblNewOffsetParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iNewLocalTimeOffset));
+ index = stmt.ParameterIndex(KTzRulesTblMonthParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iMonth));
+ index = stmt.ParameterIndex(KTzRulesTblDayParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iDayOfMonth));
+ index = stmt.ParameterIndex(KTzRulesTblWeekParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iDayOfWeek));
+ index = stmt.ParameterIndex(KTzRulesTblTimeRefParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iTimeReference));
+ index = stmt.ParameterIndex(KTzRulesTblMinsParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, rule.iTimeOfChange));
+
+ TInt ret = stmt.Exec();
+ stmt.Close();
+
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+
+ // Insert a row in the names
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertNamesStmnt()));
+ index = stmt.ParameterIndex(KTzNamesTblTzIdParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt64(index, iNextCandidateTzId));
+ index = stmt.ParameterIndex(KTzNamesTblStdNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.StandardName()));
+ index = stmt.ParameterIndex(KTzNamesTblShortStdNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.ShortStandardName()));
+ index = stmt.ParameterIndex(KTzNamesTblDSTNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.DaylightSaveName()));
+ index = stmt.ParameterIndex(KTzNamesTblShortDSTNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.ShortDaylightSaveName()));
+ index = stmt.ParameterIndex(KTzNamesTblCityNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.CityName()));
+ index = stmt.ParameterIndex(KTzNamesTblRegionNameParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindText(index, aNames.RegionName()));
+ TInt ret = stmt.Exec();
+ stmt.Close();
+
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertInitialStdOffsetStmnt));
+ index = stmt.ParameterIndex(KTzInitialStdOffsetTblTzIdParam);
+ User::LeaveIfError(index);
+ User::LeaveIfError(stmt.BindInt(index, iNextCandidateTzId));
+ index = stmt.ParameterIndex(KTzInitialStdOffsetTblStdInitialOffsetParam);
+ User::LeaveIfError(index);
+ TInt initialOffset = aRules.InitialStdTimeOffset();
+ User::LeaveIfError(stmt.BindInt(index, initialOffset));
+ ret = stmt.Exec();
+ stmt.Close();
+
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ // Update the next available user ID
+ if(iNextCandidateTzId >= KUserTzIdMax)
+ {
+ iNextCandidateTzId = FindUnusedTzIdL();
+ }
+ else
+ {
+ iNextCandidateTzId++;
+ }
+
+ //Insert a row with the new available value of tz id in TZ IdentifierTable
+ User::LeaveIfError(stmt.Prepare(iDatabase, KUpdateIdentifierStmnt));
+ User::LeaveIfError(stmt.BindInt64(0, iNextCandidateTzId));
+ ret = stmt.Exec();
+ stmt.Close();
+
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ CommitTransactionL();
+ NotifyTzRulesChange(retId, ETzUserDataCreated);
+ NotifyTzNamesChange(retId, ETzUserDataCreated);
+
+ CleanupStack::PopAndDestroy(&stmt);
+ return retId;
+ }
+
+void CTzUserDataDb::ReadTzRulesL(CTzRules& aRules, TUint aTzId)
+ {
+ if(iBackupInProgress || iRestoreInProgress)
+ {
+ User::Leave(KErrLocked);
+ }
+
+ TSqlScalarFullSelectQuery fullSelectQuery(iDatabase);
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ TTzRule tzRule;
+
+ TBuf<KSqlStringLength> sqlRules;
+ sqlRules.Format(KSelectRulesCountStmnt, aTzId);
+ TInt count = fullSelectQuery.SelectIntL(sqlRules);
+ if(count == 0)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ sqlRules.Format(KSelectRulesStmnt, aTzId);
+ TInt err = stmt.Prepare(iDatabase, sqlRules);
+ User::LeaveIfError(err);
+
+ TInt ruleTypeColIdx = stmt.ColumnIndex(KTzRulesTblRuleTypeIndex);
+ User::LeaveIfError(ruleTypeColIdx);
+ TInt startTimeColIdx = stmt.ColumnIndex(KTzRulesTblDSTStartTimeIndex);
+ User::LeaveIfError(startTimeColIdx);
+ TInt startRefColIdx = stmt.ColumnIndex(KTzRulesTblDSTStartRefIndex);
+ User::LeaveIfError(startRefColIdx);
+ TInt endTimeColIdx = stmt.ColumnIndex(KTzRulesTblDSTEndTimeIndex);
+ User::LeaveIfError(endTimeColIdx);
+ TInt endRefColIdx = stmt.ColumnIndex(KTzRulesTblDSTEndRefIndex);
+ User::LeaveIfError(endRefColIdx);
+ TInt oldOffsetColIdx = stmt.ColumnIndex(KTzRulesTblOldOffsetIndex);
+ User::LeaveIfError(oldOffsetColIdx);
+ TInt newOffsetColIdx = stmt.ColumnIndex(KTzRulesTblNewOffsetIndex);
+ User::LeaveIfError(newOffsetColIdx);
+ TInt monthColIdx = stmt.ColumnIndex(KTzRulesTblMonthIndex);
+ User::LeaveIfError(monthColIdx);
+ TInt dayColIdx = stmt.ColumnIndex(KTzRulesTblDayIndex);
+ User::LeaveIfError(dayColIdx);
+ TInt weekColIdx = stmt.ColumnIndex(KTzRulesTblWeekIndex);
+ User::LeaveIfError(weekColIdx);
+ TInt timeRefColIdx = stmt.ColumnIndex(KTzRulesTblTimeRefIndex);
+ User::LeaveIfError(timeRefColIdx);
+ TInt minsColIdx = stmt.ColumnIndex(KTzRulesTblMinsIndex);
+ User::LeaveIfError(minsColIdx);
+
+ while((err = stmt.Next()) == KSqlAtRow)
+ {
+ tzRule.iDayRule = static_cast<TTzRuleDay>(stmt.ColumnInt(ruleTypeColIdx));
+
+ tzRule.iFrom.iTime = stmt.ColumnInt64(startTimeColIdx);
+
+ tzRule.iFrom.iTimeReference = static_cast<TTzTimeReference>(stmt.ColumnInt(startRefColIdx));
+
+ tzRule.iTo.iTime = stmt.ColumnInt64(endTimeColIdx);
+
+ tzRule.iTo.iTimeReference = static_cast<TTzTimeReference>(stmt.ColumnInt(endRefColIdx));
+
+ tzRule.iOldLocalTimeOffset = stmt.ColumnInt(oldOffsetColIdx);
+
+ tzRule.iNewLocalTimeOffset = stmt.ColumnInt(newOffsetColIdx);
+
+ tzRule.iMonth = static_cast<TMonth>(stmt.ColumnInt(monthColIdx));
+
+ tzRule.iDayOfMonth = stmt.ColumnInt(dayColIdx);
+
+ tzRule.iDayOfWeek = stmt.ColumnInt(weekColIdx);
+
+ tzRule.iTimeReference = static_cast<TTzTimeReference>(stmt.ColumnInt(timeRefColIdx));
+
+ tzRule.iTimeOfChange = stmt.ColumnInt(minsColIdx);
+
+ aRules.AddRuleL(tzRule);
+ }
+ stmt.Close();
+
+ sqlRules.Format(KSelectInitialStdOffsetStmnt, aTzId);
+ err = stmt.Prepare(iDatabase, sqlRules);
+ User::LeaveIfError(err);
+ TInt stdInitialOffsetIdx = stmt.ColumnIndex(KTzInitialStdOffsetTblStdInitialOffsetIndex);
+ User::LeaveIfError(stdInitialOffsetIdx);
+
+ // Fetch the row.
+ User::LeaveIfError(stmt.Next());
+
+ TInt stdInitialOffset = stmt.ColumnInt(stdInitialOffsetIdx);
+ aRules.SetInitialStdTimeOffset(stdInitialOffset);
+
+ // This must be the only row.
+ __ASSERT_ALWAYS(stmt.Next() == KSqlAtEnd, RTz::Panic(RTz::EPanicBadSchema));
+
+ CleanupStack::PopAndDestroy(&stmt);
+ }
+
+CTzUserNames* CTzUserDataDb::ReadTzNamesL(TUint aTzId)
+ {
+ if(iBackupInProgress || iRestoreInProgress)
+ {
+ User::Leave(KErrLocked);
+ }
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ TBuf<KSqlStringLength> sqlNames;
+ TSqlScalarFullSelectQuery fullSelectQuery(iDatabase);
+ sqlNames.Format(KSelectNamesCountStmnt, aTzId);
+ TInt count = fullSelectQuery.SelectIntL(sqlNames);
+
+ if(count == 0)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ sqlNames.Format(KSelectNamesStmnt, aTzId);
+ TInt err = stmt.Prepare(iDatabase, sqlNames);
+ User::LeaveIfError(err);
+
+ TInt stdNameColIdx = stmt.ColumnIndex(KTzNamesTblStdNameIndex);
+ User::LeaveIfError(stdNameColIdx);
+
+ TInt shortStdNameColIdx = stmt.ColumnIndex(KTzNamesTblShortStdNameIndex);
+ User::LeaveIfError(shortStdNameColIdx);
+
+ TInt dstNameColIdx = stmt.ColumnIndex(KTzNamesTblDSTNameIndex);
+ User::LeaveIfError(dstNameColIdx);
+
+ TInt shortDstNameColIdx = stmt.ColumnIndex(KTzNamesTblShortDSTNameIndex);
+ User::LeaveIfError(shortDstNameColIdx);
+
+ TInt cityNameColIdx = stmt.ColumnIndex(KTzNamesTblCityNameIndex);
+ User::LeaveIfError(cityNameColIdx);
+
+ TInt regionNameColIdx = stmt.ColumnIndex(KTzNamesTblRegionNameIndex);
+ User::LeaveIfError(regionNameColIdx);
+
+ CTzUserNames* userNames = NULL;
+
+ // Fetch the row.
+ User::LeaveIfError(stmt.Next());
+
+ TPtrC standardName;
+ standardName.Set(stmt.ColumnTextL(stdNameColIdx));
+
+ TPtrC shortStandardName;
+ shortStandardName.Set(stmt.ColumnTextL(shortStdNameColIdx));
+
+ TPtrC daylightName;
+ daylightName.Set(stmt.ColumnTextL(dstNameColIdx));
+
+ TPtrC shortDaylightName;
+ shortDaylightName.Set(stmt.ColumnTextL(shortDstNameColIdx));
+
+ TPtrC cityName;
+ cityName.Set(stmt.ColumnTextL(cityNameColIdx));
+
+ TPtrC regionName;
+ regionName.Set(stmt.ColumnTextL(regionNameColIdx));
+
+ userNames = CTzUserNames::NewL(standardName, shortStandardName,
+ daylightName, shortDaylightName, cityName, regionName);
+
+ // This must be the only row.
+ __ASSERT_ALWAYS(stmt.Next() == KSqlAtEnd, RTz::Panic(RTz::EPanicBadSchema));
+
+ CleanupStack::PopAndDestroy(&stmt);
+
+ return userNames;
+ }
+
+void CTzUserDataDb::ReadTzIdsL(RArray<TUint32>& aTzIds)
+ {
+ if(iBackupInProgress || iRestoreInProgress )
+ {
+ User::Leave(KErrLocked);
+ }
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ TBuf<KSqlStringLength> sqlRule;
+ sqlRule.Format(KSelectTzIdFromNamesStmnt);
+ TInt err = stmt.Prepare(iDatabase, sqlRule);
+ User::LeaveIfError(err);
+
+ while((err = stmt.Next()) == KSqlAtRow)
+ {
+ TInt col = stmt.ColumnIndex(KTzNamesTblTzIdIndex);
+ User::LeaveIfError(col);
+ TUint id = stmt.ColumnInt64(col);
+ aTzIds.AppendL(id);
+ }
+
+ CleanupStack::PopAndDestroy(&stmt);
+ }
+
+void CTzUserDataDb::UpdateTzL(TUint aTzId, const CTzRules& aTzRules, const CTzUserNames& aTzNames)
+ {
+ if(iBackupInProgress || iRestoreInProgress)
+ {
+ User::Leave(KErrLocked);
+ }
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ BeginTransactionL();
+
+ TBuf<KSqlStringLength> sqlRules;
+ sqlRules.Format(KDeleteRulesStmnt, aTzId);
+ TInt ret = stmt.Prepare(iDatabase, sqlRules);
+ if(ret == KErrNone)
+ {
+ ret = stmt.Exec();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+ stmt.Close();
+
+ const TInt count = aTzRules.Count();
+ for(TInt i=0; i<count; i++)
+ {
+ TTzRule& rule = const_cast<CTzRules&>(aTzRules)[i];
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertRulesStmnt));
+
+ TInt paramIdx = stmt.ParameterIndex(KTzRulesTblTzIdParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblRuleTypeParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayRule));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblDSTStartTimeParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, rule.iFrom.iTime.Int64()));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblDSTStartRefParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iFrom.iTimeReference));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblDSTEndTimeParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, rule.iTo.iTime.Int64()));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblDSTEndRefParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTo.iTimeReference));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblOldOffsetParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iOldLocalTimeOffset));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblNewOffsetParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iNewLocalTimeOffset));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblMonthParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iMonth));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblDayParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayOfMonth));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblWeekParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iDayOfWeek));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblTimeRefParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTimeReference));
+
+ paramIdx = stmt.ParameterIndex(KTzRulesTblMinsParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt(paramIdx, rule.iTimeOfChange));
+
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+
+ TBuf<KSqlStringLength> sqlInitialOffset;
+ sqlInitialOffset.Format(KDeleteInitialStdOffset, aTzId);
+ ret = stmt.Prepare(iDatabase, sqlInitialOffset);
+ if(ret == KErrNone)
+ {
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertInitialStdOffsetStmnt));
+
+ TInt paramIdx = stmt.ParameterIndex(KTzInitialStdOffsetTblTzIdParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId));
+
+ TInt initialOffset = aTzRules.InitialStdTimeOffset();
+
+ paramIdx = stmt.ParameterIndex(KTzInitialStdOffsetTblStdInitialOffsetParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, initialOffset));
+
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ TBuf<KSqlStringLength> sqlNames;
+ sqlNames.Format(KDeleteNamesStmnt, aTzId);
+ ret = stmt.Prepare(iDatabase, sqlNames);
+ if(ret == KErrNone)
+ {
+ ret = stmt.Exec();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+ stmt.Close();
+
+ // Insert a row in the names
+ User::LeaveIfError(stmt.Prepare(iDatabase, KInsertNamesStmnt));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblTzIdParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindInt64(paramIdx, aTzId));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblStdNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.StandardName()));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblShortStdNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.ShortStandardName()));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblDSTNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.DaylightSaveName()));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblShortDSTNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.ShortDaylightSaveName()));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblCityNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.CityName()));
+
+ paramIdx = stmt.ParameterIndex(KTzNamesTblRegionNameParam);
+ User::LeaveIfError(paramIdx);
+ User::LeaveIfError(stmt.BindText(paramIdx, aTzNames.RegionName()));
+
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ CommitTransactionL();
+
+ NotifyTzRulesChange(aTzId, ETzUserDataUpdated);
+ NotifyTzNamesChange(aTzId, ETzUserDataUpdated);
+
+ CleanupStack::PopAndDestroy(&stmt);
+ }
+
+/**
+Delete the time zone rule and name from the database that matches aTzId
+*/
+void CTzUserDataDb::DeleteTzL(TUint aTzId)
+ {
+ if(iBackupInProgress || iRestoreInProgress)
+ {
+ User::Leave(KErrLocked);
+ }
+
+ RSqlStatement stmt;
+ CleanupClosePushL(stmt);
+
+ BeginTransactionL();
+
+ TInt ret;
+ TBuf<KSqlStringLength> sqlRules;
+ sqlRules.Format(KDeleteRulesStmnt, aTzId);
+ User::LeaveIfError(stmt.Prepare(iDatabase, sqlRules));
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ TBuf<KSqlStringLength> sqlInitialOffset;
+ sqlInitialOffset.Format(KDeleteInitialStdOffset, aTzId);
+ ret = stmt.Prepare(iDatabase, sqlInitialOffset);
+ if(ret == KErrNone)
+ {
+ ret = stmt.Exec();
+ stmt.Close();
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+ }
+
+ TBuf<KSqlStringLength> sqlNames;
+ sqlNames.Format(KDeleteNamesStmnt, aTzId);
+ User::LeaveIfError(stmt.Prepare(iDatabase, sqlNames));
+ ret = stmt.Exec();
+ stmt.Close();
+
+ if(ret < KErrNone)
+ {
+ User::Leave(ret);
+ }
+
+ CommitTransactionL();
+
+ NotifyTzRulesChange(aTzId, ETzUserDataDeleted);
+ NotifyTzNamesChange(aTzId, ETzUserDataDeleted);
+
+ CleanupStack::PopAndDestroy(&stmt);
+ }
+
+void CTzUserDataDb::CleanupDatabaseRollback(TAny *aDatabase)
+ {
+ ASSERT(aDatabase);
+ CTzUserDataDb* db = static_cast<CTzUserDataDb*>(aDatabase);
+ db->RollbackTransaction();
+ }
+
+/**
+Begin a new transation
+*/
+void CTzUserDataDb::BeginTransactionL()
+ {
+ User::LeaveIfError(iDatabase.Exec(KBeginTransaction));
+ CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback, this));
+ }
+
+/**
+Commit the changes made since the start of a transaction
+*/
+void CTzUserDataDb::CommitTransactionL()
+ {
+ User::LeaveIfError(iDatabase.Exec(KCommitTransaction));
+ CleanupStack::Pop(); //CleanupDatabaseRollback
+ }
+
+/**
+Rollback changes since the start of the transaction
+*/
+void CTzUserDataDb::RollbackTransaction()
+ {
+ iDatabase.Exec(KRollbackTransaction);
+ }
+
+// Notification operations.
+void CTzUserDataDb::NotifyTzRulesChange(TUint aTzId, TTzUserDataChangeOp aChangeOp)
+ {
+ TTzUserDataChange change;
+ change.iTzId = aTzId;
+ change.iOperation = aChangeOp;
+
+ TInt j = 0;
+ TInt jEnd = iChangeObservers.Count();
+ while (j < jEnd)
+ {
+ iChangeObservers[j]->NotifyUserTzRulesChange(change);
+ ++j;
+ }
+
+ //Publish ETzRulesChange property to the subscribed clients
+ NTzUpdate::TTzRulesChange rulesChange;
+ rulesChange.iUTCTimeOfRulesChange.UniversalTime();
+ TPckgBuf<NTzUpdate::TTzRulesChange> bufRules(rulesChange);
+ RProperty::Set(NTzUpdate::KPropertyCategory, NTzUpdate::ETzRulesChange, bufRules);
+ }
+
+void CTzUserDataDb::NotifyTzNamesChange(TUint aTzId, TTzUserDataChangeOp aChangeOp)
+ {
+ TTzUserDataChange change;
+ change.iTzId = aTzId;
+ change.iOperation = aChangeOp;
+
+ TInt j = 0;
+ TInt jEnd = iChangeObservers.Count();
+ while (j < jEnd)
+ {
+ iChangeObservers[j]->NotifyUserTzNamesChange(change);
+ ++j;
+ }
+
+ //Publish ETzNamesChange property to the subscribed clients
+ NTzUpdate::TTzNamesChange namesChange;
+ namesChange.iUTCTimeOfNamesChange.UniversalTime();
+ TPckgBuf<NTzUpdate::TTzNamesChange> bufNames(namesChange);
+ RProperty::Set(NTzUpdate::KPropertyCategory, NTzUpdate::ETzNamesChange, bufNames);
+ }
+
+ // Backup and restore operations
+void CTzUserDataDb::BackupBeginningL()
+ {
+ Close();
+ iBackupInProgress = ETrue;
+ }
+
+void CTzUserDataDb::BackupCompletedL()
+ {
+ OpenL();
+ iBackupInProgress = EFalse;
+ }
+
+void CTzUserDataDb::RestoreBeginningL()
+ {
+ Close();
+ iRestoreInProgress = ETrue;
+ }
+
+void CTzUserDataDb::RestoreCompletedL()
+ {
+ OpenL();
+ iRestoreInProgress = EFalse;
+ }
+
+void CTzUserDataDb::AddObserverL(MTzUserDataChangeObserver* aChangeObs)
+ {
+ User::LeaveIfError(iChangeObservers.Append(aChangeObs));
+ }
+
+void CTzUserDataDb::RemoveObserver(MTzUserDataChangeObserver* aChangeObs)
+ {
+ TInt j = 0;
+ TInt jEnd = iChangeObservers.Count();
+ while (j < jEnd)
+ {
+ if (iChangeObservers[j] == aChangeObs)
+ {
+ iChangeObservers.Remove(j);
+ break;
+ }
+ ++j;
+ }
+ }
+/**
+Checks if aTzId exists in the user timezone database
+*/
+TBool CTzUserDataDb::IsIdInDbL(TUint aTzId)
+ {
+ TBuf<KSqlStringLength> sqlNames;
+ TSqlScalarFullSelectQuery fullSelectQuery(iDatabase);
+ sqlNames.Format(KSelectTzIdCountFromNamesStmnt, aTzId);
+
+ TInt count = fullSelectQuery.SelectIntL(sqlNames);
+ if(count == 0)
+ {
+ return EFalse;
+ }
+ return ETrue;
+ }
+/**
+Find the next unused id in the database. If all ids have been used
+KOutOfBoundsUserId will be returned
+*/
+TUint32 CTzUserDataDb::FindUnusedTzIdL()
+ {
+ RArray<TUint32> ids;
+ CleanupClosePushL(ids);
+ ReadTzIdsL(ids);
+ const TInt count = ids.Count();
+ TUint foundId = KOutOfBoundsUserId;
+ if(count > 0)
+ {
+ ids.SortSigned();
+
+ for(TInt i=0; i<count-1; i++)
+ {
+ if(ids[i]+1 != ids[i+1])
+ {
+ foundId = ids[i]+1;
+ break;
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(&ids);
+ return foundId;
+ }