--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fotaapplication/fotaserver/src/FotaDB.cpp Tue Jul 06 15:14:24 2010 +0300
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2005 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: Fota package state preservation
+ *
+ */
+
+#include <centralrepository.h>
+#include "FotaDB.h"
+#include "FotaSrvDebug.h"
+#include "fotaserverPrivateCRKeys.h"
+
+#define __LEAVE_IF_ERROR(x) if(KErrNone!=x) {FLOG(_L("LEAVE in %s: %d"), __FILE__, __LINE__); User::Leave(x); }
+
+// ====================== MEMBER FUNCTIONS ===================================
+
+// ---------------------------------------------------------------------------
+// CFotaDB::CFotaDB()
+// ---------------------------------------------------------------------------
+CFotaDB::CFotaDB() :
+ iIsOpen(EFalse)
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::~CFotaDB()
+// ---------------------------------------------------------------------------
+CFotaDB::~CFotaDB()
+ {
+ //Delete columns set
+ if (iColSet)
+ {
+ delete iColSet;
+ iColSet = NULL;
+ }
+ //Close table
+ iTable.Close();
+
+ //Close database
+ iStateDB.Close();
+
+ //Close file server session
+ if (iFSSession.Handle())
+ iFSSession.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::NewL()
+// ---------------------------------------------------------------------------
+CFotaDB* CFotaDB::NewL()
+ {
+ CFotaDB* self = new (ELeave) CFotaDB();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::ConstructL()
+// ---------------------------------------------------------------------------
+void CFotaDB::ConstructL()
+ {
+ TInt err;
+ TBuf<KMaxPath> tmp;
+ User::LeaveIfError(iFSSession.Connect());
+ err = iFSSession.CreatePrivatePath(EDriveC);
+ if (err != KErrNone && err != KErrAlreadyExists)
+ User::Leave(err);
+ User::LeaveIfError(iFSSession.SetSessionToPrivate(EDriveC));
+ User::LeaveIfError(iFSSession.SessionPath(tmp));
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::CreateDatabaseL()
+// Creates db in private dir of fotaserver
+// ---------------------------------------------------------------------------
+void CFotaDB::CreateDatabaseL()
+ {
+ FLOG(_L("CFotaDB::CreateDatabaseL() >>"));
+ TInt err;
+ User::LeaveIfError(iStateDB.Create(iFSSession, KDatabaseName));
+ User::LeaveIfError(iStateDB.Begin());
+ User::LeaveIfError(iStateDB.Execute(KCreateTable));
+ err = iStateDB.Commit();
+ if (err)
+ {
+ FLOG(_L(" cdb err %d"), err);
+ iStateDB.Rollback();
+ User::Leave(err);
+ }
+ User::LeaveIfError(iStateDB.Compact());
+ FLOG(_L("CFotaDB::CreateDatabaseL() <<"));
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::AddPackageStateL
+// Adds state to db
+// ---------------------------------------------------------------------------
+void CFotaDB::AddPackageStateL(const TPackageState& aState,
+ const TDesC8& aPkgURL)
+ {
+ FLOG(_L(" CFotaDB::AddPackageStateL >>"));
+ TInt err;
+ RDbView view;
+ CleanupClosePushL(view);
+ TPackageState pkgstate(aState);
+ pkgstate.iResult = -1; // result should be -1 if no Execs have been done
+ err = view.Prepare(iStateDB, TDbQuery(KSelectAll), RDbView::EInsertOnly);
+ __LEAVE_IF_ERROR(err);
+ FLOG(_L(" CFotaDB::AddPackageStateL inserting. pkgid:%d result:%d state:%d"),
+ pkgstate.iPkgId, pkgstate.iResult, pkgstate.iState);
+ view.InsertL();
+ StateToRowL(pkgstate, aPkgURL, view);
+ view.PutL();
+ CleanupStack::PopAndDestroy(); //view
+ FLOG(_L(" CFotaDB::AddPackageStateL <<"));
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::GetAllL
+// Get all states
+// ---------------------------------------------------------------------------
+void CFotaDB::GetAllL(RArray<TInt>& aStates)
+ {
+ RDbView view;
+ CleanupClosePushL(view);
+
+ TInt err = view.Prepare(iStateDB, TDbQuery(KSelectAll));
+ __LEAVE_IF_ERROR(err);
+ view.EvaluateAll();
+
+ view.FirstL();
+ FLOG(_L("[fota DB] --- rows ------------------------------------------------------------------- v"));
+ while (view.AtRow())
+ {
+ view.GetL();
+ HBufC8* url;
+ TPackageState s = RowToStateL(url, view);
+ aStates.Append(s.iPkgId);
+ CleanupStack::PushL(url);
+ FLOG(_L("[fotaDB] pkgid: %d profid:%d state:%d result:%d \
+ url: %d chars sessiontype:%d IapId:%d Pkgsize:%d UpdateLtr:%d"),
+ s.iPkgId, s.iProfileId, s.iState, s.iResult,
+ url->Des().Length(), s.iSessionType, s.iIapId, s.iPkgSize,
+ s.iUpdateLtr);
+ CleanupStack::PopAndDestroy(); // url
+ view.NextL();
+ }
+ FLOG(_L("[fota DB] --- rows ------------------------------------------------------------------- ^"));
+ view.Close();
+ CleanupStack::PopAndDestroy(); //view
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::OpenDBL()
+// Opens database
+// ---------------------------------------------------------------------------
+void CFotaDB::OpenDBL()
+ {
+ FLOG(_L("CFotaDB::OpenDBL()"));
+ if (!iIsOpen) //Prevents accidental opening of database twice
+ {
+ TInt err;
+ err = iStateDB.Open(iFSSession, KDatabaseName);
+
+ if (err == KErrNotFound)
+ {
+ CreateDatabaseL();
+ }
+ else if (err != KErrNone)
+ {
+ FLOG(_L("[fota DB openDB]\t db open error: %d"), err);
+ FLOG(_L("deleting fota DB and creating it again..."));
+ err = iFSSession.Delete(KDatabaseName);
+ CreateDatabaseL();
+ User::LeaveIfError(err);
+ }
+ User::LeaveIfError(iTable.Open(iStateDB, KTblState));
+ iColSet = iTable.ColSetL();
+
+ iIsOpen = ETrue;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::CloseAndCommitDB
+// Closes and commits DB
+// ---------------------------------------------------------------------------
+void CFotaDB::CloseAndCommitDB()
+ {
+ if (iColSet)
+ {
+ delete iColSet;
+ iColSet = NULL;
+ }
+ iTable.Close();
+ iStateDB.Close();
+ iIsOpen = EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::IsOpen()
+// Chekcs if db is open
+// ---------------------------------------------------------------------------
+TBool CFotaDB::IsOpen()
+ {
+ return iIsOpen;
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::GetStateL
+// Gets pkg state from db
+// ---------------------------------------------------------------------------
+TPackageState CFotaDB::GetStateL(const TInt aPkgId, TDes8& aPkgURL)
+ {
+ RDbView view;
+ TPackageState s;
+ CleanupClosePushL(view);
+
+ s.iState = RFotaEngineSession::EIdle; // default state is idle
+
+ HBufC* select = HBufC::NewLC(KSelect_where_packageid().Length() + 10);
+ select->Des().Format(KSelect_where_packageid, aPkgId);
+
+ TInt err = view.Prepare(iStateDB, TDbQuery(*select));
+ __LEAVE_IF_ERROR(err);
+ view.EvaluateAll();
+ view.FirstL();
+
+ while (view.AtRow())
+ {
+ view.GetL();
+ HBufC8* url;
+ s = RowToStateL(url, view);
+ CleanupStack::PushL(url);
+ aPkgURL.Copy(url->Des());
+ CleanupStack::PopAndDestroy(); // url
+ view.NextL();
+ }
+ CleanupStack::PopAndDestroy(); //select
+ CleanupStack::PopAndDestroy(); //view
+ return s;
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::SetStateL
+// Writes package state to DB.
+// ---------------------------------------------------------------------------
+void CFotaDB::SetStateL(TPackageState& aState, const TDesC8& aPkgURL,
+ TUint aChangedFields)
+ {
+ FLOG(_L(" CFotaDB::SetStateL >> id %d result %d state %d sessiontype %d iapid %d pkgsize %d updateltr %d"), aState.iPkgId, aState.iResult, aState.iState);
+ __ASSERT_ALWAYS( aChangedFields!=0, User::Leave(KErrArgument) );
+ TBuf8<KMaxFileName> temp;
+ TPackageState found = GetStateL(aState.iPkgId, temp);
+ if (found.iPkgId == KErrNotFound)
+ {
+ AddPackageStateL(aState, aPkgURL);
+ }
+ else
+ {
+ // sml try count must be reset, if state is set
+ if (aChangedFields & EFDBState)
+ {
+ aChangedFields = aChangedFields | EFDBSmlTryCount;
+ SetRetryCount(aState);
+ }
+
+ // Construct a SQL string for update.
+ // Example: UPDATE State SET Result=40,State=4 WHERE pkgID=5
+ //
+ TInt sqlsize = 0;
+ _LIT8( KSqlbegin, "UPDATE State SET " );
+ TBuf<21> sqlEnd;
+ HBufC8* sql(NULL);
+ // determine characters needed
+ sqlsize = DetermineCharNeeded(aChangedFields, aState, aPkgURL);
+ sqlEnd.AppendFormat(_L(" WHERE pkgID=%d"), aState.iPkgId);
+
+ sql = HBufC8::NewLC(((TDesC8) KSqlbegin).Length() + sqlsize
+ + sqlEnd.Length());
+
+ sql->Des().Append(KSqlbegin);
+
+ if (aChangedFields & EFDBResult)
+ {
+ // check FUMO compability
+ __ASSERT_ALWAYS( aState.iResult>=KErrNotFound
+ && aState.iResult<=602, User::Leave(KErrArgument) );
+ sql->Des().AppendFormat(_L8("Result=%d,"), aState.iResult);
+ }
+ if (aChangedFields & EFDBState)
+ {
+ // check FUMO compability
+ __ASSERT_ALWAYS( aState.iState>=0 && aState.iState<=100
+ , User::Leave(KErrArgument) );
+ sql->Des().AppendFormat(_L8("State=%d,"), aState.iState);
+ }
+ if (aChangedFields & EFDBProfileId)
+ {
+ sql->Des().AppendFormat(_L8("profileid=%d,"), aState.iProfileId);
+ }
+ if (aChangedFields & EFDBPkgUrl)
+ {
+ sql->Des().AppendFormat(_L8("pkgurl='%S',"), &aPkgURL);
+ }
+ if (aChangedFields & EFDBPkgName)
+ {
+ sql->Des().AppendFormat(_L8("pkgname='%S',"), &(aState.iPkgName));
+ }
+ if (aChangedFields & EFDBVersion)
+ {
+ sql->Des().AppendFormat(_L8("Version='%S',"),
+ &(aState.iPkgVersion));
+ }
+ if (aChangedFields & EFDBSmlTryCount)
+ {
+ __ASSERT_ALWAYS( aState.iSmlTryCount>=0
+ , User::Leave(KErrArgument) );
+ sql->Des().AppendFormat(_L8("SmlTryCount=%d,"),
+ aState.iSmlTryCount);
+
+ }
+ if (aChangedFields & EFDBSessionType)
+ {
+ sql->Des().AppendFormat(_L8("SessionType=%d,"),
+ aState.iSessionType);
+ }
+ if (aChangedFields & EFDBIapId)
+ {
+ // validate IAP ID
+ __ASSERT_ALWAYS( aState.iIapId>=-1 ,User::Leave(KErrArgument) );
+ sql->Des().AppendFormat(_L8("IapId=%d,"), aState.iIapId);
+ }
+ if (aChangedFields & EFDBPkgSize)
+ {
+ sql->Des().AppendFormat(_L8("PkgSize=%d,"), aState.iPkgSize);
+ }
+ if (aChangedFields & EFDBUpdateLtr)
+ {
+ // validate bit
+ sql->Des().AppendFormat(_L8("UpdateLtr=%d,"), aState.iUpdateLtr);
+ }
+ // remove trailing ,
+ if (aChangedFields)
+ {
+ sql->Des().SetLength(sql->Des().Length() - 1);
+ }
+ sql->Des().Append(sqlEnd);
+ HBufC* sql2 = HBufC::NewLC(sql->Length()); // to cleanupstack
+ sql2->Des().Copy(sql->Des());
+ FLOG(_L(" sql:%S"), sql2);
+
+ User::LeaveIfError(iStateDB.Begin());
+ User::LeaveIfError(iStateDB.Execute(*sql2));
+ User::LeaveIfError(iStateDB.Commit());
+ User::LeaveIfError(iStateDB.Compact());
+
+ CleanupStack::PopAndDestroy(sql2); //sql2
+ CleanupStack::PopAndDestroy(sql); //sql
+ }
+ FLOG(_L(" CFotaDB::SetStateL <<"));
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::DetermineCharNeeded
+// Returns the char needed fro the query
+// ---------------------------------------------------------------------------
+
+TInt CFotaDB::DetermineCharNeeded(TInt aChangedFields, TPackageState& aState,
+ const TDesC8& aPkgURL)
+
+ {
+
+ TInt sqlsize = 0;
+ if (aChangedFields & EFDBResult)
+ sqlsize += 4 + 7 + 4;
+ if (aChangedFields & EFDBState)
+ sqlsize += 4 + 5 + 4;
+ if (aChangedFields & EFDBProfileId)
+ sqlsize += 4 + 9 + 4;
+ if (aChangedFields & EFDBPkgUrl)
+ sqlsize += aPkgURL.Length() + 6 + 4;
+ if (aChangedFields & EFDBPkgName)
+ sqlsize += aState.iPkgName.Length() + 7 + 4;
+ if (aChangedFields & EFDBVersion)
+ sqlsize += aState.iPkgVersion.Length() + 7 + 4;
+ if (aChangedFields & EFDBSmlTryCount)
+ sqlsize += 4 + 11 + 4;
+
+ if (aChangedFields & EFDBSessionType)
+ sqlsize += 4 + 11 + 4;
+ if (aChangedFields & EFDBIapId)
+ sqlsize += 4 + 5 + 4;
+ if (aChangedFields & EFDBPkgSize)
+ sqlsize += 4 + 7 + 10;
+ if (aChangedFields & EFDBUpdateLtr)
+ sqlsize += 4 + 11 + 4;
+
+ return sqlsize;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::SetRetryCount
+// Sets the retry count
+// ---------------------------------------------------------------------------
+void CFotaDB::SetRetryCount(TPackageState& aState)
+ {
+ CRepository* centrep(NULL);
+ TInt err = KErrNone;
+ TInt retry = 0;
+
+ TRAP(err, centrep = CRepository::NewL( KCRUidFotaServer ) );
+ if (centrep)
+ {
+ err = centrep->Get(KGenericAlertRetries, retry);
+ delete centrep;
+ centrep = NULL;
+ }
+ if (err == KErrNone)
+ {
+ if (retry < 0)
+ {
+ aState.iSmlTryCount = KDefaultSmlTryCount;
+ }
+ else if (retry == 0)
+ {
+ aState.iSmlTryCount = 2;
+ }
+ else if (retry > KMaximumSmlTryCount)
+ {
+ aState.iSmlTryCount = KMaximumSmlTryCount + 1;
+ }
+ else
+ {
+ aState.iSmlTryCount = retry + 1;
+ }
+ }
+ else
+ {
+ aState.iSmlTryCount = KDefaultSmlTryCount;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::RowToStateL
+// Extracts db row contents to package state object and aPkgUrl
+// Returns url in aPkgURL parameter
+// ---------------------------------------------------------------------------
+TPackageState CFotaDB::RowToStateL(HBufC8*& aPkgUrl, const RDbView& aView)
+ {
+ TPackageState s;
+ TInt pkgid = aView.ColInt(iColSet->ColNo(KColPkgId));
+ TInt state = aView.ColInt(iColSet->ColNo(KColState));
+ TInt result = aView.ColInt(iColSet->ColNo(KColResult));
+ TSmlProfileId profileid(aView.ColInt(iColSet->ColNo(KColProfileId)));
+ TPtrC pkgname = aView.ColDes(iColSet->ColNo(KColPkgName));
+ TPtrC version = aView.ColDes(iColSet->ColNo(KColVersion));
+ TInt smltrycount = aView.ColInt(iColSet->ColNo(KColSmlTryCount));
+ TInt sessiontype = aView.ColInt(iColSet->ColNo(KColSessionType));
+ TInt iapid = aView.ColInt(iColSet->ColNo(KColIapId));
+ TUint pkgsize = aView.ColUint(iColSet->ColNo(KColPkgSize));
+ TBool updateltr = aView.ColUint8(iColSet->ColNo(KColUpdateLtr));
+
+ s.iPkgId = pkgid;
+ s.iPkgName.Copy(pkgname);
+ s.iPkgVersion.Copy(version);
+ s.iProfileId = profileid;
+ s.iResult = result;
+ s.iState = RFotaEngineSession::TState(state);
+ s.iSmlTryCount = smltrycount;
+ s.iSessionType = sessiontype;
+ s.iIapId = iapid;
+ s.iPkgSize = pkgsize;
+ s.iUpdateLtr = updateltr;
+
+ RDbColReadStream rstream;
+ TInt len = aView.ColLength(iColSet->ColNo(KColPkgUrl));
+ rstream.OpenLC(aView, iColSet->ColNo(KColPkgUrl));
+ HBufC* pkgurl = HBufC::NewLC(len);
+ TPtr ptr = pkgurl->Des();
+ rstream.ReadL(ptr, len);
+
+ HBufC8* tmp = HBufC8::NewL(pkgurl->Des().Length());
+ tmp->Des().Copy(pkgurl->Des());
+ aPkgUrl = tmp;
+
+ CleanupStack::PopAndDestroy(pkgurl);
+ CleanupStack::PopAndDestroy(&rstream);
+ return s;
+ }
+
+// ---------------------------------------------------------------------------
+// CFotaDB::StateToRowL
+// Converts state object to database row (into view object)
+// ---------------------------------------------------------------------------
+void CFotaDB::StateToRowL(const TPackageState& aPkg, const TDesC8& aPkgURL,
+ RDbView& aView)
+ {
+ HBufC* pkgname = HBufC::NewLC(aPkg.iPkgName.Length());
+ HBufC* version = HBufC::NewLC(aPkg.iPkgVersion.Length());
+
+ pkgname->Des().Copy(aPkg.iPkgName);
+ version->Des().Copy(aPkg.iPkgVersion);
+
+ aView.SetColL(iColSet->ColNo(KColPkgId), aPkg.iPkgId);
+ aView.SetColL(iColSet->ColNo(KColResult), aPkg.iResult);
+ aView.SetColL(iColSet->ColNo(KColState), aPkg.iState);
+ aView.SetColL(iColSet->ColNo(KColProfileId), aPkg.iProfileId);
+ aView.SetColL(iColSet->ColNo(KColPkgName), *pkgname);
+ aView.SetColL(iColSet->ColNo(KColVersion), *version);
+ aView.SetColL(iColSet->ColNo(KColSmlTryCount), aPkg.iSmlTryCount);
+ aView.SetColL(iColSet->ColNo(KColSessionType), aPkg.iSessionType);
+ aView.SetColL(iColSet->ColNo(KColIapId), aPkg.iIapId);
+ aView.SetColL(iColSet->ColNo(KColPkgSize), aPkg.iPkgSize);
+ aView.SetColL(iColSet->ColNo(KColUpdateLtr), aPkg.iUpdateLtr);
+
+ RDbColWriteStream wstream;
+ CleanupClosePushL(wstream);
+ wstream.OpenL(aView, iColSet->ColNo(KColPkgUrl));
+ // Cannot write 8 bit descriptors to databae
+ HBufC* buf = HBufC::NewLC(aPkgURL.Length());
+ buf->Des().Copy(aPkgURL);
+ wstream.WriteL(buf->Des());
+
+ FLOG(_L("CFotaDB::StateToRowL id:%d result:%d state:%d profileid:%d \
+ name:%d chars version: %d chars url: %d chars sessiontype:%d iapid:%d pkgsize:%d updateltr = %d"),
+ aPkg.iPkgId, aPkg.iResult, aPkg.iState, aPkg.iProfileId,
+ pkgname->Des().Length(), version->Des().Length(),
+ buf->Des().Length(), aPkg.iSessionType, aPkg.iIapId,
+ aPkg.iPkgSize, aPkg.iUpdateLtr);
+
+ CleanupStack::PopAndDestroy(buf);
+ CleanupStack::PopAndDestroy(&wstream);
+ CleanupStack::PopAndDestroy(version);
+ CleanupStack::PopAndDestroy(pkgname);
+ }