activityfw/activitydatabase/hsactivitydbserver/src/afstorage.cpp
changeset 103 b99b84bcd2d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/activityfw/activitydatabase/hsactivitydbserver/src/afstorage.cpp	Wed Jun 23 18:33:40 2010 +0300
@@ -0,0 +1,505 @@
+/*
+* Copyright (c) 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 "afstorage.h"
+#include "afqueries.h"
+#include "afentry.h"
+#include <bautils.h>
+#include <s32mem.h>
+
+_LIT(KDbName, "activity.db");
+_LIT(KDbDrive, "c:");
+const TInt KMaxPathLength = 256;
+
+// -----------------------------------------------------------------------------
+LOCAL_C void CleanupResetAndDestroy(TAny*  item)
+{
+    RPointerArray<CAfEntry> *array = static_cast< RPointerArray<CAfEntry>* >(item);
+    array->ResetAndDestroy();
+    array->Close();
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Constructor for performing 1st stage construction
+ * @param session - initialized session to file system
+ */
+CAfStorage::CAfStorage(RFs& session)
+:
+mFsSession(session)
+{
+    // No implementation required
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Destructor.
+ */
+CAfStorage::~CAfStorage()
+{
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Two-phased constructor.
+ * @param session - initialized session to file system
+ */
+CAfStorage* CAfStorage::NewL(RFs& session)
+{
+    CAfStorage* self = new (ELeave) CAfStorage(session);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(); // self;
+    return self;
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * EPOC default constructor for performing 2nd stage construction
+ */
+void CAfStorage::ConstructL()
+{
+    RBuf path;
+    CleanupClosePushL( path );
+    path.CreateL(KMaxPathLength);
+    User::LeaveIfError(mFsSession.PrivatePath(path ));
+    path.Append(KDbName);
+    path.Insert(0, KDbDrive);
+    BaflUtils::EnsurePathExistsL(mFsSession, path);
+    BaflUtils::FileExists(mFsSession, path) ? OpenDbL(path) : CreateDbL(path);
+    CleanupStack::PopAndDestroy(&path);
+
+    DeleteNonPersistentActivitiesL();
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Create database and its structure
+ * @param databaseFile - database file path
+ */
+void CAfStorage::CreateDbL(const TDesC& databaseFile)
+{
+    mFileStore = CPermanentFileStore::ReplaceL(mFsSession,
+                                               databaseFile,
+                                               EFileRead|EFileWrite);
+    mFileStore->SetTypeL(mFileStore->Layout());// Set file store type
+    TStreamId id = mActDb.CreateL(mFileStore);// Create stream object
+    mFileStore->SetRootL(id);// Keep database id as root of store
+    mFileStore->CommitL();// Complete creation by commiting
+    CreateTableL();
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Open database
+ * @param databaseFile - database file path
+ */
+void CAfStorage::OpenDbL(const TDesC& databaseFile)
+{
+    mFileStore = CPermanentFileStore::OpenL(mFsSession,
+                                            databaseFile,
+                                            EFileRead|EFileWrite);
+    mFileStore->SetTypeL(mFileStore->Layout()); /* Set file store type*/
+    mActDb.OpenL(mFileStore,mFileStore->Root());
+    CDbTableNames* tables = mActDb.TableNamesL();
+    CleanupStack::PushL(tables);
+    if (0 == tables->Count()) {
+        CreateTableL();
+    }
+    CleanupStack::PopAndDestroy(tables);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Create database structure
+ */
+void CAfStorage::CreateTableL()
+{
+    // Add the columns to column set
+    CDbColSet* actColSet = CDbColSet::NewLC();
+
+    TDbCol appName(KApplicationColumnName, EDbColInt64);
+    appName.iAttributes = TDbCol::ENotNull;
+    actColSet->AddL(appName);
+
+    TDbCol actName(KActivityColumnName, EDbColText16);// Using default length
+    actName.iAttributes = TDbCol::ENotNull;
+    actColSet->AddL(actName);
+
+    TDbCol actFlags(KFlagsColumnName, EDbColInt32);
+    actFlags.iAttributes = TDbCol::ENotNull;
+    actColSet->AddL(actFlags);
+
+    actColSet->AddL(TDbCol(KDataColumnName, EDbColLongBinary));// Stream Data
+
+    // Create the table
+    User::LeaveIfError(mActDb.CreateTable(KActivityTableName,
+                                         *actColSet));
+
+    CleanupStack::PopAndDestroy(actColSet);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Delete non-persistent activities
+ */
+void CAfStorage::DeleteNonPersistentActivitiesL()
+{
+    HBufC *query(BuildQueryLC(KDeleteNonPersistentActivities(), CAfEntry::Persistent, KNullDesC));
+    User::LeaveIfError(mActDb.Execute(*query));
+    CleanupStack::PopAndDestroy(query);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Register new activity
+ * @param appId - application id
+ * @param actId - activity id
+ * @param flags - activity flags
+ * @param imgSrc - activity thumbnail source
+ * @param privateData - activity private data
+ * @param publicData - activity public data
+ */
+void CAfStorage::AddActivityL(CAfEntry& entry)
+{
+    //verify if row already exists
+    TInt errNo(KErrNone);
+    RDbView view;
+    CleanupClosePushL(view);
+    TRAP( errNo, GetActivityForUpdateL(view, entry.ApplicationId(), entry.ActivityId()));
+    if (KErrNone == errNo) {
+        User::Leave(KErrAlreadyExists);
+    }
+    CleanupStack::PopAndDestroy(&view);
+
+    //write table
+    RDbTable table;
+    CleanupClosePushL(table);
+    User::LeaveIfError(table.Open(mActDb, KActivityTableName, table.EUpdatable));
+    CDbColSet *row = table.ColSetL();
+    CleanupStack::PushL(row);
+
+    table.InsertL();
+    TRAP(errNo,
+    table.SetColL(row->ColNo(KApplicationColumnName), TInt64(entry.ApplicationId()));
+    table.SetColL(row->ColNo(KActivityColumnName), entry.ActivityId());
+    table.SetColL(row->ColNo(KFlagsColumnName), entry.Flags());
+    ExternalizeDataL(table, entry, row->ColNo(KDataColumnName));
+    table.PutL();)
+    if (KErrNone != errNo) {
+        table.Cancel();
+        User::Leave(errNo);
+    }
+    CleanupStack::PopAndDestroy(row);
+    CleanupStack::PopAndDestroy(&table);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Update activity
+ * @param entry - activity data
+ */
+void CAfStorage::UpdateActivityL(CAfEntry& entry)
+{
+    RDbView view;
+    CleanupClosePushL(view);
+    GetActivityForUpdateL(view, entry.ApplicationId(), entry.ActivityId());
+    view.UpdateL();
+    TRAPD(errNo,
+    CDbColSet* colSet = view.ColSetL();
+    CleanupStack::PushL(colSet);
+
+    view.SetColL(colSet->ColNo(KFlagsColumnName), entry.Flags());
+    ExternalizeDataL(view, entry, colSet->ColNo(KDataColumnName));
+
+    view.PutL();
+    if (KErrNone != errNo) {
+        view.Cancel();
+        User::Leave(errNo);
+    }
+    CleanupStack::PopAndDestroy(colSet);)
+
+    if (KErrNone != errNo) {
+        view.Cancel();
+        User::Leave(errNo);
+    }
+    CleanupStack::PopAndDestroy(&view);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Delete activity
+ * @param appId - application id
+ * @param actId - activity id
+ */
+void CAfStorage::DeleteActivityL(CAfEntry& entry)
+{
+    HBufC *query(DeleteRowLC(entry.ApplicationId(), entry.ActivityId()));
+    User::LeaveIfError(mActDb.Execute(*query));
+    CleanupStack::PopAndDestroy(query);
+}
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CAfStorage::DeleteActivitiesL(CAfEntry& entry)
+{
+    HBufC *query(DeleteRowsLC(entry.ApplicationId()));
+    User::LeaveIfError(mActDb.Execute(*query));
+    CleanupStack::PopAndDestroy(query);
+}
+
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+//
+void CAfStorage::ActivitiesL(RPointerArray<CAfEntry>& dst)
+{
+    ActivitiesL(dst, KSelectRows(), CAfEntry::Public);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Serialize application activity into the buffer
+ * @param dst - destination buffer
+ * @param appId - application id
+ */
+void CAfStorage::ActivitiesL(RPointerArray<CAfEntry>& dst,TInt appId)
+{
+    HBufC *query(SelectRowsLC(appId));
+    ActivitiesL(dst, *query, CAfEntry::Private);
+    CleanupStack::PopAndDestroy(query);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Serialize application activity into the buffer
+ * @param dst - destination entry
+ * @param src - condition pattern
+ */
+void CAfStorage::ActivityL(CAfEntry *&dst, CAfEntry& src)
+{
+    HBufC *query = SelectRowLC(src.ApplicationId(), src.ActivityId());
+    RPointerArray<CAfEntry> array;
+    CleanupStack::PushL(TCleanupItem(CleanupResetAndDestroy,&array));
+    ActivitiesL(array, *query, CAfEntry::Private, 1);
+    if (0 >= array.Count()) {
+        User::Leave(KErrNotFound);
+    }
+    dst = array[0];
+    array.Remove(0);
+    CleanupStack::PopAndDestroy(&array);
+    CleanupStack::PopAndDestroy(query);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Provide initialized file system session
+ * @return file system session
+ */
+RFs& CAfStorage::Fs()
+{
+    return mFsSession;
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Format query to select activity row
+ * @param appId - application id
+ * @param actId - activity id
+ * @return formated sql query
+ */
+HBufC* CAfStorage::SelectRowLC(TInt appId, const TDesC& actId) const
+{
+    return BuildQueryLC(KSelectRow(),appId, actId);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Format query to select activities for application
+ * @param appId - application id
+ * @return formated sql query
+ */
+HBufC* CAfStorage::SelectRowsLC(TInt appId) const
+{
+    return BuildQueryLC(KSelectAppRows(), appId, KNullDesC);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Format query to delete activity
+ * @param appId - application id
+ * @param actId - activity id
+ * @return formated sql query
+ */
+HBufC* CAfStorage::DeleteRowLC(TInt appId, const TDesC& actId) const
+{
+    return BuildQueryLC(KDeleteRow(),appId, actId);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Format query to delete activities for application
+ * @param appId - application id
+ * @return formated sql query
+ */
+HBufC* CAfStorage::DeleteRowsLC(TInt appId) const
+{
+    return BuildQueryLC(KDeleteRows(),appId, KNullDesC);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Format sql query
+ * @format - sql format string
+ * @param appId - application id
+ * @param actId - activity id
+ * @return formated sql query
+ */
+HBufC* CAfStorage::BuildQueryLC(const TDesC& format,
+                                      TInt appId,
+                                      const TDesC& actId) const
+{
+    TBuf<16> appName;
+    appName.AppendNum(appId);
+    RBuf actName;
+    CleanupClosePushL(actName);
+    actName.CreateL(actId.Length());
+    actName.Copy(actId);
+    HBufC* query = HBufC::NewL(format.Length() +
+                               appName.Length() +
+                               actName.Length() );
+    query->Des().AppendFormat(format, &appName, &actName);
+    CleanupStack::PopAndDestroy(&actName);
+    CleanupStack::PushL(query);
+    return query;
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Execute sql query and result serialize into buffer
+ * @param dst - destination result buffer
+ * @param query - sql activity query
+ */
+void CAfStorage::ActivitiesL(RPointerArray<CAfEntry>& dst, const TDesC& query, CAfEntry::AccessRights rights, TInt limit)
+{
+    RDbView view;// Create a view on the database
+    CleanupClosePushL(view);
+    User::LeaveIfError(view.Prepare(mActDb, TDbQuery(query), view.EReadOnly));
+    User::LeaveIfError(view.EvaluateAll());
+    ActivitiesL(dst, view, rights, limit);
+    CleanupStack::PopAndDestroy(&view);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Return view deserialisd into entries array
+ * @param dst - destination result
+ * @param query - view
+ * @param rights - acess rights
+ */
+void CAfStorage::ActivitiesL(RPointerArray<CAfEntry>& dst, RDbView& src, CAfEntry::AccessRights rights, TInt limit)
+{
+    CDbColSet* row = src.ColSetL();
+    CleanupStack::PushL(row);
+
+    const TInt flagsOffset(row->ColNo(KFlagsColumnName)),
+               applicationOffset(row->ColNo(KApplicationColumnName)),
+               activityOffset(row->ColNo(KActivityColumnName)),
+               dataOffset(row->ColNo(KDataColumnName));
+
+    RBuf activityName;
+    CleanupClosePushL(activityName);
+
+    for (src.FirstL(); src.AtRow(); src.NextL()) {
+        if(0 < limit && dst.Count() >= limit) {
+            break;
+        }
+        src.GetL();
+        ReadDataL(activityName, src, activityOffset);
+
+        CAfEntry *entry = CAfEntry::NewLC(src.ColInt32(flagsOffset),
+                                          src.ColInt64(applicationOffset),
+                                          activityName,
+                                          KNullDesC,
+                                          KNullDesC8,
+                                          KNullDesC8);
+        if (CAfEntry::Public == rights && (entry->Flags() & CAfEntry::Invisible)) {
+            CleanupStack::PopAndDestroy(entry);
+            continue;
+        }
+        InternalizeDataL(*entry, src, dataOffset);
+        
+        if (CAfEntry::Public == rights || 0 >= limit) {
+            entry->SetDataL(KNullDesC8(), CAfEntry::Private);
+        }
+        dst.AppendL(entry);
+        CleanupStack::Pop(entry);
+    }
+
+    CleanupStack::PopAndDestroy(&activityName);
+    CleanupStack::PopAndDestroy(row);
+}
+
+// -----------------------------------------------------------------------------
+/**
+ * Get activity for update
+ * @param query - destination query result
+ * @param appId - application id
+ * @param actId - activity id
+ */
+void CAfStorage::GetActivityForUpdateL(RDbView& view, TInt appId, const TDesC& actId)
+{
+    HBufC* query(SelectRowLC(appId, actId));
+    User::LeaveIfError(view.Prepare(mActDb, TDbQuery(*query), view.EUpdatable));
+    CleanupStack::PopAndDestroy(query);
+    User::LeaveIfError(view.EvaluateAll());
+    if (!view.FirstL()) {
+        User::Leave(KErrNotFound);
+    }
+}
+
+// -----------------------------------------------------------------------------
+void CAfStorage::ReadDataL(RBuf& dst, RDbRowSet& src, TInt offset) const
+{
+    const TInt length(src.ColLength(offset));
+    CAfEntry::ReallocL(dst, length);
+    RDbColReadStream srcStream;
+    srcStream.OpenLC(src,offset);
+    srcStream.ReadL(dst, src.ColLength(offset));
+    CleanupStack::PopAndDestroy(&srcStream);
+}
+
+// -----------------------------------------------------------------------------
+void CAfStorage::ExternalizeDataL(RDbRowSet& dst,const CAfEntry &src, TInt offset) const
+{
+    RDbColWriteStream dbStream;
+    CleanupClosePushL(dbStream);
+    dbStream.OpenL(dst, offset);
+    src.ExternalizeDataOnlyL(dbStream);
+    CleanupStack::PopAndDestroy(&dbStream);
+}
+
+// -----------------------------------------------------------------------------
+void CAfStorage::InternalizeDataL(CAfEntry & dst, RDbRowSet& src, TInt offset) const
+{
+    RDbColReadStream dbStream;
+    CleanupClosePushL(dbStream);
+    dbStream.OpenL(src, offset);
+    dst.InternalizeDataOnlyL(dbStream);
+    CleanupStack::PopAndDestroy(&dbStream);
+}