srsf/nssvasapi/nssvasdb/src/nssvascvasdb.cpp
branchRCL_3
changeset 19 e36f3802f733
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/nssvasapi/nssvasdb/src/nssvascvasdb.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,2810 @@
+/*
+* Copyright (c) 2004-2006 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:  Implementation of VAS database handling
+*
+*/
+
+
+#include "nssvascvasdb.h"
+#include <e32test.h>
+#include <e32std.h>
+#include <e32svr.h>
+#include "rubydebug.h"
+#include "nssvascoreconstant.h"
+#include "nssvascrrd.h"
+
+#include "nssvasbackupobserver.h"
+
+// CONSTANTS
+
+// Name of the DB lock mutex
+_LIT( KLockMutex, "VASDATABASE" );
+
+#ifdef _DEBUG
+// used in UDEB macros only
+_LIT( KVasDbPanic, "VasCNssVasDb.cpp");
+#endif // _UDEB
+
+// Maximum size of tag array
+static const TInt KMaxTagArraySize = 50;
+
+const TInt KContextListGranularity = 5;
+
+const TInt KSqlStatementmaxLength = 120;
+
+// MACROS
+
+// Complementary macro for TRAPD
+#define REACT( err, codeblock ) if ( err != KErrNone ) { codeblock; }
+
+// ============================ Methods ===============================
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::NewL
+// 2-level constructor
+// -----------------------------------------------------------------------------
+//
+CNssVasDb* CNssVasDb::NewL( CNssContextBuilder& contextBuilder,
+	                        CNssSpeechItemBuilder& speechItemBuilder )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::NewL" );
+
+    CNssVasDb* self = new(ELeave) CNssVasDb( contextBuilder,
+                                             speechItemBuilder );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::~CNssVasDb
+// Standard C++ destructor
+// -----------------------------------------------------------------------------
+//
+CNssVasDb::~CNssVasDb()
+    {
+    RUBY_DEBUG0( "CNssVasDb::~CNssVasDb" );
+
+    if ( iLocked )
+        {
+        RUBY_DEBUG0( "Signalling mutex in CNssVasDb::~CNssVasDb" );
+        iMutex.Signal();
+        }
+    else
+        {
+        RUBY_DEBUG0( "NOT signalling mutex in CNssVasDb::~CNssVasDb iLocked = EFalse" );
+        }
+
+    if ( iClientHasOpenedDatabase )
+        {
+        CloseDatabase();
+        }
+
+    iMutex.Close();
+    delete iBackupObserver;
+    iCriticalSection.Close();
+    RUBY_DEBUG0( "CNssVasDb::~CNssVasDb Mutex handle closed" );
+    }
+	
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CNssVasDb
+// Standard C++ contructor
+// -----------------------------------------------------------------------------
+//
+CNssVasDb::CNssVasDb( CNssContextBuilder& aContextBuilder,
+	                  CNssSpeechItemBuilder& aSpeechItemBuilder )
+: iClientHasOpenedDatabase( EFalse ),
+  iLocked( EFalse ),
+  iContextBuilder( aContextBuilder ),
+  iSpeechItemBuilder( aSpeechItemBuilder )
+    {
+    // empty
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::ConstructL
+// Symbian second constructor.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::ConstructL()
+    {
+    TInt err = iMutex.OpenGlobal( KLockMutex );
+    if ( err != KErrNone )
+        {
+        RUBY_DEBUG0( "CNssVasDb::ConstructL Creating new global mutex" );
+        iMutex.CreateGlobal( KLockMutex );
+        }
+    else
+        {
+        RUBY_DEBUG0( "CNssVasDb::ConstructL Using existing global mutex" );
+        }
+    iCriticalSection.CreateLocal();
+    iBackupObserver = CNssVasBackupObserver::NewL( *this );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::RollbackCleanupFunction
+// This function is used to form iRollbackCleanupItem. When this item is
+// popped from the cleanup stack, it makes a rollback on VAS DB.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::RollbackCleanupFunction( TAny* aArg )
+    {
+    RUBY_DEBUG0( "CNssVasDb::RollbackCleanupFunction" );
+
+    CNssVasDb* me = (CNssVasDb*)aArg;
+
+    me->RollbackTransaction();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CreateDatabaseL
+// Creates a new database.
+// from a resource file.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::CreateDatabaseL()
+    {
+    User::LeaveIfError( iDbSession.Connect() );
+    CleanupClosePushL( iDbSession );
+    iDbcreator.CreateVasDatabaseL( iDbSession );
+    CleanupStack::PopAndDestroy( &iDbSession );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::OpenDatabaseL
+// Opens the database. Reads the path and file name of the database
+// from a resource file.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::OpenDatabaseL()
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::OpenDatabaseL" );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        RFs fs;
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL ( fs ); // Stack: file session
+
+        // Open the database
+	    User::LeaveIfError( iDbSession.Connect() );
+	    
+        User::LeaveIfError( iDatabase.Open( iDbSession, 
+                            KVasDatabaseName, KVasDatabaseFormatString ) );
+        User::LeaveIfError( fs.CharToDrive( KVasDatabaseDrive, iDrive ) );
+
+        if ( iDatabase.IsDamaged() )
+            {
+            RUBY_DEBUG0( "CNssVasDb::OpenDatabaseL Recovering" );
+            User::LeaveIfError( iDatabase.Recover() );
+            }
+            
+        CleanupStack::PopAndDestroy( &fs ); 
+
+	    iClientHasOpenedDatabase = ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CloseDatabase
+// Closes the database.
+// -----------------------------------------------------------------------------
+//
+TInt CNssVasDb::CloseDatabase()
+    {
+    RUBY_DEBUG0( "CNssVasDb::CloseDatabase" ); 
+  
+    iDatabase.Close();
+    iDbSession.Close();
+    iClientHasOpenedDatabase = EFalse;
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetModelBankIdLexiconIdL
+// Returns the model bank ID and the lexicon ID.
+// -----------------------------------------------------------------------------
+//
+TBool CNssVasDb::GetModelBankIdLexiconIdL( TUint32& aModelBankId, TUint32& aLexiconId )
+    {
+    TBool ret = EFalse;
+    RDbView view;
+  
+    _LIT( KSQLGetModelBankLexicon, "select modelbankid,lexiconid from contexttable" );
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    CleanupClosePushL( view );
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( 
+                            KSQLGetModelBankLexicon, EDbCompareNormal ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+
+    // There is no ModelbankId or LexiconId 
+    if ( view.IsEmptyL() )
+        {
+        User::Leave( KErrNotFound );
+        }
+    // There is a ModelBankId and a LexiconId 
+    ret = ETrue;
+    view.FirstL();
+    view.GetL();
+
+    // Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get column ordinals
+    TDbColNo modelbankid_col = columns->ColNo( KModelBankIdCol );
+    TDbColNo lexiconid_col = columns->ColNo( KLexiconIdCol );
+    // Cleanup column set
+    delete columns;
+
+    aModelBankId = view.ColUint32( modelbankid_col );
+    aLexiconId   = view.ColUint32( lexiconid_col );
+ 
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    // Release lock
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    return ret;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::TagExistsL
+// Checks if a context is empty.
+// -----------------------------------------------------------------------------
+//
+TBool CNssVasDb::TagExistL( TInt aContextId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::TagExistL" );
+ 
+    TBool   ret( EFalse );
+    RDbView view;
+
+    CleanupClosePushL(view);
+
+    _LIT( KSQLGetTags, "select * from tagtable " );
+    _LIT( KSQLWhereContextId, "where contextid=" );
+
+    iSQLStatement = KSQLGetTags;
+    iSQLStatement.Append( KSQLWhereContextId );
+    iSQLStatement.AppendNumUC( aContextId );
+    
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+
+    if ( view.IsEmptyL() )
+        {
+        ret = EFalse;
+        }
+    else
+        {
+        ret = ETrue;
+        }
+
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::TagCountL
+// Returns the number of tags.
+// -----------------------------------------------------------------------------
+//
+TInt CNssVasDb::TagCountL( TInt aContextId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::TagCountL" );
+        
+    RDbView view;
+    TInt    numberOfTags = 0;
+
+    CleanupClosePushL( view );
+
+    _LIT( KSQLGetTags, "select * from tagtable " );
+    _LIT( KSQLWhereContextId, "where contextid=" );
+
+    iSQLStatement = KSQLGetTags;
+    iSQLStatement.Append( KSQLWhereContextId );
+    iSQLStatement.AppendNumUC( aContextId );
+    
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+
+    numberOfTags = view.CountL();
+   
+    view.Close();
+    CleanupStack::PopAndDestroy( &view );
+   
+    return numberOfTags;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CommitIfSuccess
+// Commits or rolls back accoring to success parameter.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::CommitIfSuccess( RDbDatabase /*aDatabase*/, TInt aSuccess, TBool aCompactIfCommit )
+    {
+    if ( aSuccess >= 0 )
+        {
+        CommitTransaction( aCompactIfCommit );
+        }
+    else
+        {
+        // Otherwise, roll back the transaction and release the lock.
+        RollbackTransaction();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::SaveContextL
+// Saves a newly created context. The Context ID is assigned and returned
+// using the reference parameter.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::SaveContextL( CNssContext& aContext, TInt& aContextId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::SaveContextL" );
+  
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    // Locks the database for the use of this process only
+    TInt error = StartTransaction();
+
+    if ( error != KErrNone )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: could not lock database." );
+        
+        User::Leave( KErrGeneral );
+        }
+
+    TRAP( error, SaveContextL( &aContext, aContextId ) );
+    REACT( error, RUBY_DEBUG0( "Context saving failed" ) );
+
+    if ( error == KErrNone )
+        {
+        TRAP ( error, DoUpdateContextClientDataL( aContext ) );
+        }
+    
+    CommitIfSuccess( iDatabase, error, ETrue );
+    
+    User::LeaveIfError( error );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateContextL
+// Updates the context to VAS DB.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateContextL( CNssContext& aContext )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::UpdateContextL" );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    TInt error = StartTransaction();
+
+    if ( error != KErrNone )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: could not lock database." );
+        
+        User::Leave( KErrGeneral );
+        }
+
+    TRAP( error, DoUpdateContextL( aContext ) );
+    REACT( error, RUBY_DEBUG0( "Context updating failed" ) );
+
+    CommitIfSuccess( iDatabase, error, ETrue );
+    
+    User::LeaveIfError( error );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateContextInsideTransactionL
+// Updates the context to VAS DB.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateContextInsideTransactionL( CNssContext& aContext )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::UpdateContextInsideTransactionL" );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    DoUpdateContextL( aContext );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateContextClientDataL
+// Updates the client data of the context.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateContextClientDataL( CNssContext& aContext )   
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::UpdateContextClientDataL" );
+	
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    TInt error = StartTransaction();
+
+    if ( error != KErrNone )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: could not lock database." );
+        
+        User::Leave( KErrGeneral );
+        }
+
+    TRAP( error, DoUpdateContextClientDataL( aContext ) );
+
+    CommitIfSuccess( iDatabase, error, ETrue );
+    
+    User::LeaveIfError( error );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetDefaultModelBankIdL
+// Usually, all contexts use the same Model Bank. This function
+// returns the first model bank ID it finds.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::GetDefaultModelBankIdL( TUint32& aId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::GetDefaultModelBankIdL" );
+      
+    _LIT( KSQLGetAll,"select modelbankid from contexttable");
+
+    iSQLStatement = KSQLGetAll;
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    StartTransaction();
+    CreatePushRollbackItemLC();
+
+    RDbView view;
+
+    CleanupClosePushL(view);
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+
+    if ( view.IsEmptyL() )
+        {
+	    User::Leave( KErrNotFound );
+        }
+
+    // Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get model bank id column ordinal
+	TDbColNo modelbankid_col= columns->ColNo( KModelBankIdCol );
+	delete columns;
+
+	view.FirstL();
+    view.GetL(); // Retrieve the current row - actually reads the row from the database.
+
+    aId = view.ColUint32( modelbankid_col );
+
+    CleanupStack::PopAndDestroy( &view );// close view
+
+    // Rollback cleanup
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::ResetModelBankL
+// Usually, all contexts use the same Model Bank. When the model bank is reseted,
+// (=speaker independent models are resotred and speaker adaptation is destroyed)
+// the model bank ID changes for all contexts.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::ResetModelBankL( TUint32 aNewId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::ResetModelBankL" );
+
+    _LIT( KSQLUpdateModelbank,"update contexttable set modelbankid=");
+
+    iSQLStatement = KSQLUpdateModelbank;
+    iSQLStatement.AppendNumUC( aNewId );
+
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    StartTransaction();
+    CreatePushRollbackItemLC();
+
+    User::LeaveIfError( iDatabase.Execute( iSQLStatement ) );
+
+    CleanupStack::Pop();  // Rollback cleanup item
+
+    User::LeaveIfError( CommitTransaction( ETrue ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetContextByNameL
+// Reads a context from VAS DB by name.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssContext>* CNssVasDb::GetContextByNameL(const TDesC& aName)
+    {
+	RUBY_DEBUG_BLOCK("CNssVasDb::GetContextByNameL");
+
+    _LIT( KSQLGetAll,"select * from contexttable ");
+    _LIT( KSQLWhereName,"where name='");
+    _LIT( KTick,"' ");
+
+    iSQLStatement = KSQLGetAll;
+    iSQLStatement.Append( KSQLWhereName );
+    iSQLStatement.Append( aName );
+    iSQLStatement.Append( KTick );
+
+    return GetContextL( iSQLStatement );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetGlobalContexts
+// Reads all global contexts from VAS DB.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssContext>* CNssVasDb::GetGlobalContexts()
+    {
+	RUBY_DEBUG0("CNssVasDb::GetGlobalContexts");
+	    
+    _LIT( KSQLGetAll,"select * from contexttable ");
+    _LIT( KSQLWhereGlobal,"where global=1");
+
+    iSQLStatement = KSQLGetAll;
+    iSQLStatement.Append( KSQLWhereGlobal );
+
+    CArrayPtrFlat<CNssContext>* ret( NULL );
+    TRAPD( error, ret = GetContextL( iSQLStatement ) );
+    if ( error != KErrNone )
+        {
+        return NULL;
+        }
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetAllContexts
+// Reads all contexts from VAS DB.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssContext>* CNssVasDb::GetAllContexts()
+    {   
+    RUBY_DEBUG0("CNssVasDb::GetAllContexts");
+    
+    _LIT( KSQLGetAll,"select * from contexttable ");
+
+    iSQLStatement = KSQLGetAll;
+
+    CArrayPtrFlat<CNssContext>* ret( NULL );
+    TRAPD( error, ret = GetContextL( iSQLStatement ) );
+    if ( error != KErrNone )
+        {
+        return NULL;
+        }
+    return ret;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetContextL
+// Executes the SQL query. After the query has selected a list of contexts,
+// these contexts are read from DB to memory.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssContext>* CNssVasDb::GetContextL(const TDesC& aSQLStatement)
+    {
+    RUBY_DEBUG_BLOCK("CNssVasDb::GetContextL");
+
+    __ASSERT_DEBUG( aSQLStatement.Left( 6 ).Compare( _L("select") ) == 0,
+                    User::Panic( KVasDbPanic, __LINE__ ) );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    TInt ret = StartTransaction();
+    RUBY_DEBUG1("Started transaction. Error code [%d]", ret);
+    
+    CreatePushRollbackItemLC();
+    CArrayPtrFlat<CNssContext>* contextList = GetContextInsideTransactionL( aSQLStatement );
+
+    // Rollback cleanup (just to avoid automatic locking)
+    CleanupStack::Pop();  // Rollback cleanup item 
+    CommitTransaction( EFalse );
+
+    return contextList;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetContextInsideTransaction
+// Reads a context by name. Assumes that a transaction has already been started.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssContext>* CNssVasDb::GetContextInsideTransactionL( const TDesC& aSQLStatement )
+    {
+    RUBY_DEBUG_BLOCK("CNssVasDb::GetContextInsideTransactionL");
+    RDbView view;
+
+    CleanupClosePushL(view);
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( aSQLStatement, EDbCompareNormal ) ) );
+    RUBY_DEBUG0("CNssVasDb::GetContextInsideTransactionL Prepared query");
+    User::LeaveIfError( view.EvaluateAll() );
+    RUBY_DEBUG0("CNssVasDb::GetContextInsideTransactionL Evaluated query");
+
+    if ( view.IsEmptyL() )
+        {
+        RUBY_DEBUG0("CNssVasDb::GetContextInsideTransactionL Empty view. Leaving with KErrNotFound");
+	    User::Leave( KErrNotFound );
+        }
+
+    CArrayPtrFlat<CNssContext>* contextList = 
+            new (ELeave) CArrayPtrFlat<CNssContext>( KContextListGranularity );
+    CleanupStack::PushL( contextList );
+    CleanupResetAndDestroyPushL( *contextList );
+    RUBY_DEBUG0("CNssVasDb::GetContextInsideTransactionL Before FillContextListArrayL");
+
+    FillContextListArrayL(view, *contextList);
+   
+    CleanupStack::Pop( contextList ); // ResetAndDestroy
+    CleanupStack::Pop( contextList );  // array itself
+    CleanupStack::PopAndDestroy( &view );// close view
+
+    return( contextList );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagReferenceList
+// Fetches tag references for all tags in a context.
+// -----------------------------------------------------------------------------
+//
+TNssTagReferenceListArray* CNssVasDb::GetTagReferenceListL( TInt aContextId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::GetTagReferenceListL" );
+    
+    RDbView view;
+    TNssTagReference tagRef;
+
+    TNssTagReferenceListArray* tagArray = 
+            new (ELeave) TNssTagReferenceListArray( KMaxTagArraySize );
+    CleanupStack::PushL( tagArray );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    // Start transaction - lock database
+    StartTransaction();
+    CreatePushRollbackItemLC();
+
+    // Make a query, which lists all tags in the context.
+    // Making a CNssTagReferece only requires tagid and name.
+    _LIT( KSQLGetTag, "select tagid,name from tagtable where contextid=" );
+    iSQLStatement = KSQLGetTag;
+    iSQLStatement.AppendNumUC( aContextId );
+
+    CleanupClosePushL(view);
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+
+    if ( view.IsEmptyL() )
+        {
+	    User::Leave( KErrNotFound );
+        }
+
+    // Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get column ordinals
+    TDbColNo name_col  = columns->ColNo( KNameCol );
+    TDbColNo tagid_col = columns->ColNo( KTagIdCol );
+
+    delete columns;
+
+    for( view.FirstL(); view.AtRow(); view.NextL() )
+        {
+        view.GetL();
+	    tagRef.iTagName = view.ColDes( name_col );
+	    tagRef.iTagId   = view.ColUint32( tagid_col );
+	    tagArray->AppendL( tagRef );
+        }
+
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    // Finish transaction - release lock
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    // Return result
+    CleanupStack::Pop( tagArray );
+
+    return( tagArray );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::SaveTagL
+// Saves a newly created tag. When a tag is saved, a Tag ID is assigned to it.
+// This Tag ID is returned in the reference parameter.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::SaveTagL( CNssTag& aTag, TInt& aNewId )
+    {
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    // Locks the database for the use of this process only	
+    
+    TInt error = StartTransaction();
+
+    if ( error != KErrNone )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: could not lock database." );
+        
+        User::Leave( KErrGeneral );
+        }
+
+    TInt contextId; // Discard context ID 
+    
+    CNssContext* context = static_cast<CNssContext*> ( aTag.Context() );
+    TRAP( error, SaveContextL( context, contextId ) );
+	
+    if ( error == KErrItemAlreadyExist || error == KErrNone )
+        {
+        TRAP( error, SaveTagL( &aTag, aNewId ) );
+        }
+    else 
+        {
+        RollbackTransaction(); 
+        User::Leave( error );
+        }
+    
+    // Check SavetagL result
+    if ( error != KErrNone )
+        {
+        RollbackTransaction(); 	
+        User::Leave( error );
+        }
+    else
+        {
+        CNssRRD* rrd = static_cast<CNssRRD*>( aTag.RRD() );
+        rrd->SetTagId( aNewId );
+
+        TRAPD( error, SaveRRDL( rrd ) );
+	    REACT( error, RUBY_DEBUG0( "RRD saving failed." ) );
+
+        CommitIfSuccess( iDatabase, error, ETrue );
+        }
+        
+    User::LeaveIfError( error );
+    }
+
+// ---------------------------------------------------------
+// CNssVasDb::SaveTagsL
+// Saves several tags in one commit.
+// ---------------------------------------------------------
+//
+void CNssVasDb::SaveTagsL( CArrayPtrFlat<CNssTag>* aTagArray, RArray<TInt>& aTagIdArray )
+    {
+	CleanupClosePushL( aTagIdArray );
+
+    TInt k( 0 );
+    TInt error( KErrNone );
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    // Locks the database for the use of this process only	
+    User::LeaveIfError( StartTransaction() );
+
+    CreatePushRollbackItemLC(); // Stack: rollback cleanup
+
+    RArray<TInt> contextIds;
+    CleanupClosePushL( contextIds ); // Stack: rollback cleanup, contextIds
+
+    for ( k = 0; k < aTagArray->Count(); k++ )
+        {
+        CNssTag* tag = (*aTagArray)[k];
+        CNssContext* context = static_cast<CNssContext*> ( tag->Context() );
+
+        if ( contextIds.Find( context->ContextId() ) == KErrNotFound )
+            {
+            TInt contextId;
+            TRAP( error, SaveContextL( context, contextId ) );
+
+            // We accept leaves with error KErrAlreadyExists
+            if ( error != KErrNone && error != KErrAlreadyExists )
+                {
+                break;
+                }
+
+            contextIds.Append( context->ContextId() );
+            }
+        }
+
+    // Close context id array
+    CleanupStack::PopAndDestroy( &contextIds ); // Stack: Rollback cleanup
+
+    // We accept leaves with error KErrAlreadyExists
+    if ( error != KErrNone && error != KErrAlreadyExists )
+        {
+        User::Leave( error );
+        }
+
+    TInt id;
+    for ( k = 0; k < aTagArray->Count(); k++ )
+        {
+        CNssTag* tag = (*aTagArray)[k];
+
+        if ( tag->TagId() == KNssVASDbDefaultValue )
+            {
+            SaveTagL( tag, id );
+
+            CNssRRD* rrd = static_cast<CNssRRD*>( tag->RRD() );
+            rrd->SetTagId( id );
+
+	        SaveRRDL( rrd );
+            User::LeaveIfError( aTagIdArray.Append( id ) );
+            }
+        else{
+            UpdateTagInTransactionL( *tag );
+            User::LeaveIfError( aTagIdArray.Append( tag->TagId() ) );
+            }
+        }
+
+    User::LeaveIfError( CommitTransaction( ETrue ) );
+
+    // Pop rollback cleanup
+    // (which would have made database rollback, if a leave had happened)
+    CleanupStack::Pop();  // Rollback cleanup item
+	CleanupStack::Pop();
+    }
+
+// ---------------------------------------------------------
+// CNssVasDb::DeleteTagsL
+// Deletes several tags in one commit.
+// ---------------------------------------------------------
+//
+void CNssVasDb::DeleteTagsL( const RArray<TUint32>& aTagIdArray )
+    {
+    TInt k( 0 );
+   
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+
+    // Locks the database for the use of this process only	
+    User::LeaveIfError( StartTransaction() );
+
+    CreatePushRollbackItemLC();
+
+    for ( k = 0; k < aTagIdArray.Count(); k++ )
+        {
+        DeleteTagInsideTransactionL( aTagIdArray[k] );
+        }
+
+    User::LeaveIfError( CommitTransaction( ETrue ) );
+
+    // Pop rollback cleanup
+    // (which would have made database rollback, if a leave had happened)
+    CleanupStack::Pop();  // Rollback cleanup item
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateTagL
+// Updates the data of an existing tag.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateTagL( CNssTag& aTag )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::UpdateTagL" );	
+
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+	
+    // Locks the database for the use of this process only
+    User::LeaveIfError( StartTransaction() );
+
+    TRAPD( error, UpdateTagInTransactionL( aTag ) );
+
+    CommitIfSuccess( iDatabase, error, ETrue );
+
+    User::LeaveIfError( error );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateTagRuleIDs
+// Changes the Rule IDs of some tags. The Rule ID changes, when
+// and already trained tags is retrained.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateTagRuleIDsL( const RArray<TNssSpeechItem>& aRetrainedTags )
+    {
+    TInt error( KErrNone );
+    if ( !iClientHasOpenedDatabase )
+        {
+        User::Leave( KErrDbNotSet );
+        }
+   
+    _LIT( KSQLUpdateTag,"update tagtable set ");
+    _LIT( KEqual,"=");
+    _LIT( KSQLWhereTagIdIs," where tagid = ");
+
+    TInt count = aRetrainedTags.Count();
+
+    if ( count > 0 )
+        {
+        return;
+        }
+
+    // Start transaction
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    // Make the changes to Rule IDs
+    for ( TInt k( 0 ); k < count; k++ )
+        {
+        // "update tagtable set "
+        iSQLStatement = KSQLUpdateTag;
+
+        // "ruleid=1234"
+        iSQLStatement.Append( KRuleIdCol );
+        iSQLStatement.Append( KEqual );
+        iSQLStatement.AppendNumUC( aRetrainedTags[k].iRuleId );
+
+        // " where tagid = 5678"
+        iSQLStatement.Append( KSQLWhereTagIdIs );
+        iSQLStatement.AppendNumUC( aRetrainedTags[k].iTagId );
+
+        error =  iDatabase.Execute( iSQLStatement );
+        if ( error < KErrNone )
+            {
+            ReleaseDiskSpace();
+            User::Leave( error );
+            }
+        }
+
+    // Commit transaction
+    error = CommitTransaction( ETrue );
+    if ( error )
+        {
+        ReleaseDiskSpace();
+        User::Leave( error );
+        }
+
+    // Pop rollback cleanup object
+    CleanupStack::Pop();  // Rollback cleanup item
+
+    ReleaseDiskSpace();    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::SaveContextL
+// Saves a newly created context. When a context is saved, a Context ID is
+// assigned to it. This id is returned using the reference parameter.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::SaveContextL( CNssContext* aContext, TInt& aContextId )
+    {
+    TBuf<KNssVasDbContextName> name;
+    RDbView view1;
+
+    _LIT( KSQLAdd, "select * from contexttable " );
+    _LIT( KSQLWhereName, "where name='" );
+    _LIT( KTick, "' " );
+
+    //Check to see if a context already exist with the new name
+    iSQLStatement = KSQLAdd;
+    iSQLStatement.Append( KSQLWhereName );
+    iSQLStatement.Append( aContext->ContextName() );
+    iSQLStatement.Append( KTick );
+	
+    CleanupClosePushL( view1 );
+   
+    User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );	
+    User::LeaveIfError( view1.EvaluateAll() );
+
+    if ( !view1.IsEmptyL() ) // context with that name already exist so return status
+        {  
+        // Get column set
+        CDbColSet* columns1 = view1.ColSetL();
+        TDbColNo contextid_col = columns1->ColNo( KContextIdCol );
+
+	    delete columns1;
+
+        view1.FirstL();
+        view1.GetL();
+	    //Get the  unique contextid key just generated
+	    aContextId = view1.ColUint32(contextid_col);
+	    aContext->SetContextId( aContextId );
+
+	    view1.Close();	  
+	    CleanupStack::PopAndDestroy( &view1 );
+        
+        User::Leave( KErrAlreadyExists );
+        }
+    else{
+        view1.Close();
+	    CleanupStack::PopAndDestroy( &view1 );
+	   
+	    RDbView view2;
+
+        CleanupClosePushL( view2 );
+
+	    User::LeaveIfError( view2.Prepare( iDatabase, TDbQuery(KSQLAdd,EDbCompareNormal)));	
+        User::LeaveIfError( view2.EvaluateAll() );
+  
+	    // Get column set
+        CDbColSet* columns = view2.ColSetL();
+        // Get column ordinals
+        TDbColNo name_col = columns->ColNo( KNameCol );
+        TDbColNo global_col = columns->ColNo( KGlobalCol );
+	    TDbColNo grammarid_col = columns->ColNo( KGrammarIdCol );
+	    TDbColNo lexiconid_col = columns->ColNo( KLexiconIdCol );
+	    TDbColNo modelbankid_col = columns->ColNo( KModelBankIdCol );
+	    TDbColNo contextid_col = columns->ColNo( KContextIdCol );
+
+	    delete columns;
+
+	    // Begin process of inserting a row...
+	    view2.InsertL();
+	    // set column values...
+	    view2.SetColL( name_col, aContext->ContextName() );
+	    view2.SetColL( global_col, aContext->IsGlobal() );
+	    view2.SetColL( lexiconid_col, aContext->LexiconId() );
+	    view2.SetColL( grammarid_col, aContext->GrammarId() );
+	    view2.SetColL( modelbankid_col, aContext->ModelBankId() );
+	
+	    // add the row to the table...
+	    view2.PutL();
+	             
+	    view2.GetL();
+        //Get the  unique contextid key just generated
+	    aContextId = view2.ColUint32( contextid_col );
+
+	    aContext->SetContextId( aContextId );
+
+	    name = view2.ColDes( name_col );
+	  
+	    view2.Close();
+	    CleanupStack::PopAndDestroy( &view2 );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::SaveTagL
+// Saves a newly created tag. When a tag is saved, a Tag ID is assigned to it.
+// This id is returned using the reference parameter.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::SaveTagL( CNssTag* aTag, TInt& aNewId )
+    {
+	RDbView view;
+ 
+    _LIT( KSQLGet,"select * from tagtable");
+	
+	CleanupClosePushL(view);
+
+	User::LeaveIfError( view.Prepare( iDatabase, TDbQuery(KSQLGet,EDbCompareNormal)));	
+	User::LeaveIfError( view.EvaluateAll());
+    
+	// Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get column ordinals
+    TDbColNo name_col           = columns->ColNo( KNameCol );
+	TDbColNo tagid_col          = columns->ColNo( KTagIdCol );
+	TDbColNo contextid_col      = columns->ColNo( KContextIdCol );
+	TDbColNo ruleid_col         = columns->ColNo( KRuleIdCol );
+
+	delete columns;
+	  
+	// Begin process of inserting a row...
+	view.InsertL();
+	// set column values...
+	
+	CNssContext* context = static_cast<CNssContext*> ( aTag->Context() );
+	CNssSpeechItem* speechItem = static_cast<CNssSpeechItem*> ( aTag->SpeechItem() );
+	
+	#ifdef __SIND_EXTENSIONS
+	    view.SetColL( name_col, aTag->SpeechItem()->RawText() ); 
+	#else
+	    view.SetColL( name_col, aTag->SpeechItem()->Text() ); 
+	#endif  // __SIND_EXTENSIONS
+	view.SetColL( contextid_col, context->ContextId() );
+	view.SetColL( ruleid_col, speechItem->RuleID() );
+	
+	// add the row to the table...
+	view.PutL();
+
+    aNewId = view.ColUint32( tagid_col );
+
+	// finished - so close the view
+	view.Close();
+	CleanupStack::PopAndDestroy( &view );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::SaveRRDL
+// Reads RRD from DB to memory. Utility function when reading tags.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::SaveRRDL( CNssRRD* aRRD )
+    {
+    TInt position;
+	RDbView view1,view2;
+   
+	_LIT( KSQLAddRRDText, "select * from rrdtexttable");
+	_LIT( KSQLAddRRDId,   "select * from rrdinttable");
+	
+    // Save the integer array, if we have one.
+    if ( aRRD->IntArray() )
+        {
+	    CleanupClosePushL(view1);
+	
+	    User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( KSQLAddRRDId, EDbCompareNormal ) ) );	
+	    User::LeaveIfError( view1.EvaluateAll());
+
+	    // Get column set	
+        CDbColSet* columns1 = view1.ColSetL();
+        // Get column ordinals
+        TDbColNo tagid_col           = columns1->ColNo( KTagIdCol );
+	    TDbColNo rrdint_col          = columns1->ColNo( KRRDIntCol );
+        TDbColNo rrdposition_col1    = columns1->ColNo( KRRDPositionCol );
+
+	    delete columns1;
+
+	    // Begin process of inserting a row...
+	    // set column values for id table...
+        for( position=0; position<aRRD->IntArray()->Count(); position++ )
+            {
+	        view1.InsertL();
+	        view1.SetColL( tagid_col,aRRD->TagId() );
+	        view1.SetColL(rrdint_col,aRRD->IntArray()->At( position ) );
+	        view1.SetColL(rrdposition_col1,position);
+	        // add the row to the table...
+	        view1.PutL();	   
+	        }	
+	
+	    // finished - so close the view
+	    view1.Close(); 	
+	    CleanupStack::PopAndDestroy( &view1 );
+        }
+
+    // Save the text array, if we have one
+    if ( aRRD->TextArray() )
+        {
+	    CleanupClosePushL( view2 );
+
+        User::LeaveIfError( view2.Prepare( iDatabase, 
+                            TDbQuery( KSQLAddRRDText, EDbCompareNormal ) ) );	
+	    User::LeaveIfError( view2.EvaluateAll() );
+    
+        // Get column set
+        CDbColSet* columns2 = view2.ColSetL();
+        // Get column ordinals
+        TDbColNo tagid_col2       = columns2->ColNo( KTagIdCol );
+	    TDbColNo rrdtext_col2     = columns2->ColNo( KRRDTextCol );
+        TDbColNo rrdposition_col2 = columns2->ColNo( KRRDPositionCol );
+
+	    delete columns2;
+
+	    //set colum values for text table
+	    for( position = 0; position < aRRD->TextArray()->Count(); position++ )
+            {
+	        view2.InsertL();
+	        view2.SetColL( tagid_col2, aRRD->TagId() );
+	        view2.SetColL( rrdtext_col2, aRRD->TextArray()->At( position ) );
+	        view2.SetColL( rrdposition_col2, position );
+	        view2.PutL();	   
+            }	
+	    // add the row to the table...
+	
+	    // finished - so close the view
+	    view2.Close();  
+	    CleanupStack::PopAndDestroy( &view2 );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::FillRRDL
+// Reads RRD from DB to memory. Utility function when reading tags.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::FillRRDL( TUint32 aTagId, CNssRRD& aRRD )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::FillRRDL" );
+    
+    TInt position;
+	RDbView view1,view2;
+
+	_LIT( KSQLAddRRDText, "select * from rrdtexttable ");
+	_LIT( KSQLAddRRDId,   "select * from rrdinttable ");
+	_LIT( KSQLWhereTagId,"where tagid=");
+
+	iSQLStatement = KSQLAddRRDId;
+	iSQLStatement.Append( KSQLWhereTagId );
+	iSQLStatement.AppendNumUC( aTagId );
+
+	CleanupClosePushL(view1);
+
+	User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view1.EvaluateAll());
+
+	// Get column set
+    CDbColSet* columns1 = view1.ColSetL();
+    // Get column ordinals
+    TDbColNo tagid_col           = columns1->ColNo( KTagIdCol );
+	TDbColNo rrdint_col          = columns1->ColNo( KRRDIntCol );
+    TDbColNo rrdposition_col1    = columns1->ColNo( KRRDPositionCol );
+	// Cleanup column1 set
+	delete columns1;
+
+	// Begin process of inserting a row...
+	TInt intarraysize = view1.CountL();
+    if ( intarraysize > 0 )
+        {
+        CArrayFixFlat<TInt>* intArray = new (ELeave) CArrayFixFlat<TInt>(intarraysize);
+        CleanupStack::PushL( intArray );
+        intArray->ResizeL( intarraysize );
+        
+        // set column values for id table...
+        for ( view1.FirstL(); view1.AtRow(); view1.NextL() )
+            {
+            view1.GetL();
+            aRRD.SetTagId( view1.ColUint32( tagid_col ) );
+            position = view1.ColUint32( rrdposition_col1 );
+            if ( position < 0 || position >= intarraysize )
+                {
+                RUBY_ERROR2("CNssVasDb::FillRRDL position out of bounds. 0 < %i < %i", 
+                    position, intarraysize );
+                User::Leave( KErrCorrupt );
+                }
+            intArray->At( position ) = view1.ColUint32( rrdint_col );
+            }
+
+        aRRD.SetIntArrayL( intArray );
+        CleanupStack::Pop( intArray );
+        intArray->Reset();
+        delete intArray;
+        }
+    
+	// finished - so close the view
+	view1.Close();
+	CleanupStack::PopAndDestroy( &view1 );
+ 
+	CleanupClosePushL(view2);
+
+	iSQLStatement = KSQLAddRRDText;
+	iSQLStatement.Append( KSQLWhereTagId );
+	iSQLStatement.AppendNumUC( aTagId );
+    User::LeaveIfError( view2.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view2.EvaluateAll() );
+    
+    // Get column set
+    CDbColSet* columns2 = view2.ColSetL();
+    // Get column ordinals
+    TDbColNo tagid_col2       = columns2->ColNo( KTagIdCol );
+	TDbColNo rrdtext_col2     = columns2->ColNo( KRRDTextCol );
+    TDbColNo rrdposition_col2 = columns2->ColNo( KRRDPositionCol );
+   
+	delete columns2;
+    
+	TInt textarraysize = view2.CountL();
+    if ( textarraysize > 0 )
+        {
+        CArrayFixFlat<NssRRDText>* textArray = 
+                    new (ELeave) CArrayFixFlat<NssRRDText>(textarraysize);
+        CleanupStack::PushL( textArray );
+        textArray->ResizeL( textarraysize );
+
+        //set colum values for text table
+        for ( view2.FirstL(); view2.AtRow(); view2.NextL() )
+            {
+            view2.GetL();
+            aRRD.SetTagId( view2.ColUint32( tagid_col2 ) );
+            position      = view2.ColUint32( rrdposition_col2 );
+            if ( position < 0 || position >= textarraysize )
+                {
+                RUBY_ERROR2("CNssVasDb::FillRRDL position out of bounds. 0 < %i < %i", 
+                    position, textarraysize );
+                User::Leave( KErrCorrupt );
+                }
+            textArray->At( position ) = view2.ColDes( rrdtext_col2 );
+            }	
+
+        aRRD.SetTextArrayL( textArray );
+        CleanupStack::Pop( textArray );
+        textArray->Reset();
+        delete textArray;
+        }
+
+	// finished - so close the view
+	view2.Close();
+        
+    CleanupStack::PopAndDestroy( &view2 );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagL
+// Gets a tag by grammar ID and rule ID.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL( TNssGrammarIdRuleId aGrammarIdRuleId )
+    {
+	CNssContext* context = iContextBuilder.CreateContextL();
+	CleanupStack::PushL( context );
+	RDbView view;
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+	CleanupClosePushL(view);
+
+	_LIT( KSQLGetContext, "select * from contexttable where grammarid=");
+	iSQLStatement.Copy(KSQLGetContext);
+	iSQLStatement.AppendNumUC(aGrammarIdRuleId.iGrammarId);
+
+    TDbQuery dbQuery(iSQLStatement, EDbCompareNormal);
+	User::LeaveIfError( view.Prepare( iDatabase, dbQuery ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+	view.FirstL(); 
+    FillContextL(view, *context);
+
+	_LIT( KSQLGetTag, "select * from tagtable where ruleid=");
+	_LIT( KSQLAnd," and contextid=");
+	iSQLStatement = KSQLGetTag;
+	iSQLStatement.AppendNumUC( aGrammarIdRuleId.iRuleId );
+    iSQLStatement.Append( KSQLAnd );
+	iSQLStatement.AppendNumUC( context->ContextId() );
+
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    CArrayPtrFlat<CNssTag>* res = GetTagListByQueryL( iSQLStatement );
+
+    // Pop rollback cleanup item
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+    
+    CleanupStack::PopAndDestroy( context );
+
+    return( res );
+    }
+    
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagsL
+// Gets a list of tags by grammar ID and rule ID.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagsL( TNssGrammarIdRuleIdListArray& aGrammarIdRuleIds )
+	{
+	CNssContext* context = iContextBuilder.CreateContextL();
+	CleanupStack::PushL( context );
+	RDbView view;
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    Mem::FillZ( context,     sizeof(*context)   );
+
+	CleanupClosePushL(view);
+	
+	_LIT( KSQLGetContext, "select * from contexttable where ");
+	_LIT( KGrammarIdParam, "grammarid=" );
+	_LIT( KOr, " OR ");
+	iSQLStatement.Copy(KSQLGetContext);
+	
+	for( TInt i = 0; i < aGrammarIdRuleIds.Count(); i++)
+		{
+		if( i !=0 )
+			{
+			iSQLStatement.Append(KOr);
+			}
+		iSQLStatement.Append(KGrammarIdParam);
+		iSQLStatement.AppendNumUC(aGrammarIdRuleIds[i].iGrammarId);
+		// same grammar ids usually appear, but that's ok and should not decrease performance
+		}
+		
+	TDbQuery dbQuery(iSQLStatement, EDbCompareNormal);
+	User::LeaveIfError( view.Prepare( iDatabase, dbQuery ));
+	User::LeaveIfError( view.EvaluateAll());
+	
+	_LIT( KSQLGetTags, "select * from tagtable where (");
+	_LIT( KRuleId, "ruleid=");
+	_LIT( KContextId,"contextid=");
+	_LIT( KBracketAnd, " AND (");
+	_LIT( KBracketOr, ") OR (");
+	_LIT( KFinalBracket, ")");
+	
+	// Get column set
+    CDbColSet* columns = view.ColSetL();
+	TDbColNo contextid_col= columns->ColNo( KContextIdCol );
+	TDbColNo grammarid_col= columns->ColNo( KGrammarIdCol );
+	delete columns;
+	TUint32 currContextId;
+	TUint32 currGrammarId;
+	TUint32 currRuleId;
+	
+	iSQLStatement = KSQLGetTags;
+	TBool firstPair = ETrue;
+	while( view.NextL())
+		{
+		view.GetL();
+		// before each iteration, but first, we add ") OR ("
+		if( firstPair )
+			{
+			firstPair = EFalse;
+			}
+		else 
+			{
+			iSQLStatement.Append(KBracketOr);
+			}
+		currContextId = view.ColUint32( contextid_col );
+		currGrammarId = view.ColUint32( grammarid_col );
+		iSQLStatement.Append( KContextId );
+		iSQLStatement.AppendNumUC( currContextId );
+		iSQLStatement.Append( KBracketAnd );
+		// we need to find corresponding rule id
+		TBool someGrammarFoundAlready = EFalse;
+		for( TInt i=0; i<aGrammarIdRuleIds.Count(); i++)
+			{
+			if( currGrammarId == aGrammarIdRuleIds[i].iGrammarId )
+				{
+				if( someGrammarFoundAlready )
+					{
+					iSQLStatement.Append( KOr );
+					}
+				else 
+					{
+					someGrammarFoundAlready = ETrue;
+					}
+				currRuleId = aGrammarIdRuleIds[i].iRuleId;
+				iSQLStatement.Append( KRuleId );
+				iSQLStatement.AppendNumUC( currRuleId );	
+				}
+			}  // for
+		iSQLStatement.Append(KFinalBracket);  // closing ruleid ORs
+		}  // while
+	// Close view
+    CleanupStack::PopAndDestroy( &view );
+    iSQLStatement.Append( KFinalBracket );
+    
+    CArrayPtrFlat<CNssTag>* res = GetTagListByQueryL( iSQLStatement );
+
+    // Pop rollback cleanup item
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    CleanupStack::PopAndDestroy( context );
+
+    return( res );
+	}
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagListByQuery
+// Executes the query and reads matches from DB to memory.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagListByQuery
+// Executes the query and reads matches from DB to memory.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagListByQueryL( const TDesC& aSqlQuery )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::GetTagListByQueryL" );
+
+    __ASSERT_DEBUG( aSqlQuery.Left(6).Compare( _L("select") ) == 0, User::Panic( KVasDbPanic, __LINE__ ) );
+
+	CNssContext* context = NULL;
+	CNssSpeechItem* speechItem = NULL;
+	CNssRRD* rrd = NULL;
+    TInt contextId = -1;
+
+    // 'context' variable is the context of the previous tag.
+    // When a new tag is read, 'context' is updated only if context changes.
+    // Set the ID invalid value in order to force the first tag to read a context.
+    //context.iContextId = (TUint32)-1;
+    //context->SetContextId( -1 );
+
+	RDbView view;
+	CleanupClosePushL( view );
+
+    CArrayPtrFlat<CNssTag>* tagList = new(ELeave)CArrayPtrFlat<CNssTag>( KMaxTagArraySize );
+    CleanupStack::PushL( tagList );
+    CleanupResetAndDestroyPushL( *tagList );
+
+	User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( aSqlQuery, EDbCompareNormal ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+	if ( !view.IsEmptyL() )
+	    {
+   	    for (view.FirstL(); view.AtRow(); view.NextL())
+	        {
+	        context = iContextBuilder.CreateContextL();
+	        CleanupStack::PushL( context );
+	        
+	        speechItem = iSpeechItemBuilder.CreateEmptySpeechItemL( *context );
+	        CleanupStack::PushL( speechItem );
+	        
+            FillSpeechItemL( view, *speechItem, contextId );
+
+            // Get context, if we haven't already done it.
+            if ( context->ContextId() != (TUint32)contextId )
+                {                
+                _LIT( KContextQuery, "select * from contexttable where contextid=" );
+
+                iSQLStatement.Copy( KContextQuery );
+                iSQLStatement.AppendNumUC( contextId );
+
+                CArrayPtrFlat<CNssContext>* contextList = 
+                            GetContextInsideTransactionL( iSQLStatement );
+                CleanupStack::PushL( contextList );
+
+                User::LeaveIfNull( contextList );
+
+                if ( contextList->Count() != 1 )
+                    {
+                    User::Leave( KErrCorrupt );
+                    }
+
+                CleanupStack::Pop( contextList );
+                CleanupStack::PopAndDestroy( speechItem );                
+                CleanupStack::PopAndDestroy( context );
+                
+                context = (*contextList)[0];                
+                delete contextList;
+                
+                CleanupStack::PushL( context );
+                
+	            speechItem = iSpeechItemBuilder.CreateEmptySpeechItemL( *context );
+	            CleanupStack::PushL( speechItem );
+	        	        
+                FillSpeechItemL( view, *speechItem, contextId );
+                }
+                
+            rrd = CNssRRD::NewL();
+            CleanupStack::PushL( rrd );
+            
+            FillRRDL( speechItem->TagId(), *rrd );
+            
+            // Append tag to the array 
+            FillTagListArrayL( *tagList, context, speechItem, rrd );
+            CleanupStack::PopAndDestroy( rrd );
+            CleanupStack::PopAndDestroy( speechItem );
+            CleanupStack::PopAndDestroy( context );
+            }
+        }
+	else
+	    {
+        User::Leave( KErrNotFound );
+	    }
+
+	CleanupStack::Pop( tagList );  // ResetAndDestroy
+    CleanupStack::Pop( tagList );  // array itself
+	// Finished with the view - so close it.
+    CleanupStack::PopAndDestroy( &view );
+
+    return tagList;
+    }
+    
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagL
+// Gets a tag by name.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL(const TDesC& aName)
+    {
+    _LIT( KTick,"' ");
+	_LIT( KSQLGetTag, "select * from tagtable where name='");
+	
+	iSQLStatement = KSQLGetTag;
+	iSQLStatement.Append( aName );
+    iSQLStatement.Append( KTick );
+
+    User::LeaveIfError( StartTransaction() );
+
+    CArrayPtrFlat<CNssTag>* arr = GetTagListByQueryL( iSQLStatement );
+
+    CommitTransaction( EFalse );
+
+    return arr;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagL
+// Gets all tags from a specified context.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL( const CNssContext& aContext)
+    {
+    RDbView view;
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    CleanupClosePushL( view );
+
+	// Validate the context
+    _LIT( KSQLGetContext, "select * from contexttable where contextid=");
+	iSQLStatement = KSQLGetContext;
+	iSQLStatement.AppendNumUC( aContext.ContextId() );
+
+	User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+    if ( view.IsEmptyL() )
+	    {
+        User::Leave( KErrNotFound );
+	    }
+
+	// Finished with the view - so close it.
+    CleanupStack::PopAndDestroy( &view );
+	
+	_LIT( KSQLGetTag, "select * from tagtable where contextid=" );
+	iSQLStatement.Copy( KSQLGetTag );
+	iSQLStatement.AppendNumUC( aContext.ContextId() );
+
+    CArrayPtrFlat<CNssTag>* result = GetTagListByQueryL( iSQLStatement );
+
+    // Transaction finished - free the transaction lock
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::GetTagListFromViewL
+// Reads the tags from DB to memory and appends them to the array.
+// Earlier, the caller has made an SQL query and placed the matches in RDbView.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::GetTagListFromViewL( RDbView& aView, CArrayPtrFlat<CNssTag>* aTagList, 
+                                     CNssContext* aContext )
+    {
+    TInt discardable( 0 );
+
+	for ( aView.FirstL(); aView.AtRow(); aView.NextL() )
+    	{
+    	CNssSpeechItem* speechItem = iSpeechItemBuilder.CreateEmptySpeechItemL( *aContext );
+    	CleanupStack::PushL( speechItem );
+    	
+	    FillSpeechItemL( aView, *speechItem, discardable );
+		CNssRRD* rrd = CNssRRD::NewL();
+		CleanupStack::PushL( rrd );
+		FillRRDL( speechItem->TagId(), *rrd );
+		    
+		FillTagListArrayL( *aTagList, aContext, speechItem, rrd );
+		
+		CleanupStack::PopAndDestroy( rrd );
+		CleanupStack::PopAndDestroy( speechItem );
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagL
+// Gets a list of tags by RRD data.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL( TInt aContextId, TInt aNum, TInt aPosition )
+    {
+  	RDbView     view;
+	TUint32     tagId;
+	CNssContext* context = iContextBuilder.CreateContextL();
+	CleanupStack::PushL( context );
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    CArrayPtrFlat<CNssTag>* tagArray = new(ELeave)CArrayPtrFlat<CNssTag>(1);
+    CleanupStack::PushL( tagArray );
+    CleanupResetAndDestroyPushL( *tagArray );
+
+    // Get the context based on ContextId
+  	CleanupClosePushL(view);
+
+	_LIT( KSQLGetContext, "select * from contexttable where contextid=" );
+	iSQLStatement.Copy( KSQLGetContext );
+	iSQLStatement.AppendNumUC( aContextId );
+
+	User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	view.FirstL();
+    view.GetL();
+	TRAPD( error, FillContextL( view, *context ) );
+	// Finished with the view - so close it.
+	view.Close();
+	CleanupStack::PopAndDestroy( &view );
+
+    // If filling of the context failed, return with Not Found
+	if ( error != KErrNone )
+	    {
+        User::Leave( KErrNotFound );
+        }
+
+    // Get the list of TagId from the RRD table based on Num and Position
+	RDbView view1;
+	CleanupClosePushL( view1 );
+
+	_LIT( KSQLGetRRDInt, "select * from rrdinttable where rrdposition=" );
+	_LIT( KSQLAndRRDInt, " and rrdint=" );
+	iSQLStatement = KSQLGetRRDInt;
+	iSQLStatement.AppendNumUC( aPosition );
+	iSQLStatement.Append( KSQLAndRRDInt );
+	iSQLStatement.AppendNumUC( aNum );
+
+	User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view1.EvaluateAll() );
+	
+	if ( view1.IsEmptyL() )
+	    {
+
+        User::Leave( KErrNotFound );
+	    }
+
+    // Get column set
+    CDbColSet* columns = view1.ColSetL();
+    // Get column ordinals
+    TDbColNo tagid_col= columns->ColNo( KTagIdCol );
+    // Cleanup column set
+    delete columns;
+
+    // Select the valid tagId from the list
+	for ( view1.FirstL(); view1.AtRow(); view1.NextL() )
+        {   
+        view1.GetL();
+        tagId = view1.ColUint32( tagid_col );
+
+        // Get the SpeechItem based on the tagId and ContextId
+        RDbView view2;
+		CleanupClosePushL( view2 );
+
+        _LIT( KSQLGetSpeechItem, "select * from tagtable where tagid=" );
+        _LIT( KSQLAndContextId," and contextid=" );
+        iSQLStatement = KSQLGetSpeechItem;
+        iSQLStatement.AppendNumUC( tagId );
+	    iSQLStatement.Append( KSQLAndContextId );
+        iSQLStatement.AppendNumUC( aContextId );
+
+        User::LeaveIfError( view2.Prepare( iDatabase, 
+                            TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+        User::LeaveIfError( view2.EvaluateAll() );
+    
+        if ( !view2.IsEmptyL() )
+	        {
+            GetTagListFromViewL( view2, tagArray, context );
+		    }
+        view2.Close();
+        CleanupStack::PopAndDestroy( &view2 );
+        }
+
+    // close the view 1
+	view1.Close();
+	CleanupStack::PopAndDestroy( &view1 );
+
+    CleanupStack::Pop( tagArray );  // ResetAndDestroy
+    CleanupStack::Pop( tagArray );  // array itself
+
+    // Rollback cleanup
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+    
+    CleanupStack::PopAndDestroy( context );
+
+    return tagArray;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagL
+// Gets a list of tags by RRD data.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL( TInt aContextId, 
+                                            const TDesC& aText, TInt aPosition )
+    {
+  	RDbView view;
+	TUint32 tagId;
+	CNssContext* context = iContextBuilder.CreateContextL();
+	CleanupStack::PushL( context );
+	
+    CArrayPtrFlat<CNssTag>* tagArray = new(ELeave)CArrayPtrFlat<CNssTag>(1);
+    CleanupStack::PushL( tagArray );
+    CleanupResetAndDestroyPushL( *tagArray );
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    // Get the context based on ContextId
+  	CleanupClosePushL( view );
+
+	_LIT( KSQLGetContext, "select * from contexttable where contextid=" );
+	iSQLStatement.Copy( KSQLGetContext );
+	iSQLStatement.AppendNumUC( aContextId );
+
+	User::LeaveIfError( view.Prepare(iDatabase, TDbQuery(iSQLStatement, EDbCompareNormal)));
+	User::LeaveIfError( view.EvaluateAll());
+	view.FirstL();
+    view.GetL();
+	TRAPD( error, FillContextL( view, *context ) );
+	// Finished with the view - so close it.
+	view.Close();
+	CleanupStack::PopAndDestroy( &view );
+
+    // If filling of the context failed, return with Not Found
+	if ( error != KErrNone )
+	    {
+        User::Leave( KErrNotFound );
+        }
+
+    // Get the list of TagId from the RRD table based on text and Position
+	RDbView view1;
+	CleanupClosePushL( view1 );
+
+	_LIT( KSQLGetRRDText, "select * from rrdtexttable where rrdposition=" );
+	_LIT( KSQLAndRRDText, " and rrdtext='" );
+	_LIT( KSQLTick, "'" );
+
+	iSQLStatement = KSQLGetRRDText;
+	iSQLStatement.AppendNumUC( aPosition );
+	iSQLStatement.Append( KSQLAndRRDText );
+	iSQLStatement.Append( aText );
+    iSQLStatement.Append( KSQLTick );
+
+	User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view1.EvaluateAll() );
+	
+	if ( view1.IsEmptyL() )
+	    {
+        User::Leave( KErrNotFound );
+	    }
+
+    // Get column set
+    CDbColSet* columns = view1.ColSetL();
+    // Get column ordinals
+    TDbColNo tagid_col= columns->ColNo( KTagIdCol );
+    // Cleanup column set
+    delete columns;
+
+    // Select the valid tagId from the list
+	for ( view1.FirstL(); view1.AtRow(); view1.NextL() )
+	    {
+        view1.GetL();
+        tagId = view1.ColUint32( tagid_col );
+
+        // Get the SpeechItem based on the tagId and ContextId
+        RDbView view2;
+		CleanupClosePushL( view2 );
+
+        _LIT( KSQLGetSpeechItem, "select * from tagtable where tagid=" );
+        _LIT( KSQLAndContextId, " and contextid=" );
+        iSQLStatement = KSQLGetSpeechItem;
+        iSQLStatement.AppendNumUC( tagId );
+	    iSQLStatement.Append( KSQLAndContextId );
+        iSQLStatement.AppendNumUC( aContextId );
+
+        User::LeaveIfError( view2.Prepare( iDatabase, 
+                            TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+        User::LeaveIfError( view2.EvaluateAll() );
+
+        if ( !view2.IsEmptyL() )
+	        {
+            GetTagListFromViewL( view2, tagArray, context );
+		    }
+        CleanupStack::PopAndDestroy( &view2 );
+        }
+    // close the view 1
+	CleanupStack::PopAndDestroy( &view1 );
+
+    // Roll back transaction
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    CleanupStack::Pop( tagArray );  // ResetAndDestroyPushL
+    CleanupStack::Pop( tagArray );  // array itself
+    CleanupStack::PopAndDestroy( context );
+
+    return tagArray;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagL
+// Get a tag by ID.
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CNssTag>* CNssVasDb::GetTagL( TUint32 aTagId )
+    {
+	RDbView view;
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    CleanupClosePushL( view );
+
+
+	_LIT( KSQLGetTag, "select * from tagtable where tagid=");
+
+	iSQLStatement = KSQLGetTag;
+	iSQLStatement.AppendNumUC( aTagId );
+
+    CArrayPtrFlat<CNssTag>* result = GetTagListByQueryL( iSQLStatement );
+
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    // Roll back transaction
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( EFalse );
+
+    return( result );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagL
+// Deletes a tag by name
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DeleteTagL( const TDesC& aName )
+    {
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    TUint32 tagId;
+    RDbView view;
+	
+    CleanupClosePushL(view);
+
+    _LIT( KTick,"' ");
+    _LIT( KSQLGetTag, "select * from tagtable where name='");
+	
+    iSQLStatement = KSQLGetTag;
+    iSQLStatement.Append( aName );
+    iSQLStatement.Append( KTick );
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery(iSQLStatement, EDbCompareNormal)));
+    User::LeaveIfError( view.EvaluateAll());
+
+    // Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get column ordinals
+    TDbColNo tagid_col= columns->ColNo( KTagIdCol );
+    // Cleanup column set
+    delete columns;
+
+    view.FirstL();
+    view.GetL();
+    tagId = view.ColUint32( tagid_col );
+
+    // Close view
+    CleanupStack::PopAndDestroy( &view );
+
+    // Pop rollback item and do commit
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( ETrue );
+
+    DeleteTagL( tagId );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagL
+// Deletes a tag by ID
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DeleteTagL( TUint32 aTagId )
+    {
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "CNssVasDb error: database not opened." );
+        
+        User::Leave( KErrNotReady );
+        }
+   
+    // Lock database
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+
+    DeleteTagInsideTransactionL( aTagId );
+
+    // Commit transaction - unlock databaes
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( ETrue );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteTagInsideTransactionL
+// Deletes the RRD information of a tag.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DeleteTagInsideTransactionL( TUint32 aTagId )
+    {
+    TInt error( KErrNone );
+
+    _LIT( KSQLDeleteTag, "delete from tagtable where tagid=");
+
+	ReserveDiskSpaceL( sizeof(CNssTag) );
+
+    iSQLStatement = KSQLDeleteTag;
+    iSQLStatement.AppendNumUC(aTagId);
+
+    error = iDatabase.Execute( iSQLStatement );
+    if ( error < KErrNone )
+        {
+        ReleaseDiskSpace();
+        User::Leave( error );
+        }
+
+    TRAP( error, DeleteRRDL( aTagId ) );
+    
+    ReleaseDiskSpace();
+    
+    User::LeaveIfError( error );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteRRDL
+// Deletes the RRD information of a tag.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DeleteRRDL(TUint32 aTagId)
+    {
+    TInt error( KErrNone );
+    
+    _LIT( KSQLAddRRDText, "delete from rrdtexttable ");
+    _LIT( KSQLAddRRDId,   "delete from rrdinttable ");
+    _LIT( KSQLWhereTagId,"where tagid=");
+
+    iSQLStatement = KSQLAddRRDId;
+    iSQLStatement.Append( KSQLWhereTagId );
+    iSQLStatement.AppendNumUC( aTagId );
+	
+    error = iDatabase.Execute( iSQLStatement );
+   
+    if ( error < KErrNone && error != KErrNotFound )
+        {
+        User::Leave( error );
+        }
+
+    iSQLStatement = KSQLAddRRDText;
+    iSQLStatement.Append( KSQLWhereTagId );
+    iSQLStatement.AppendNumUC( aTagId );
+
+    error = iDatabase.Execute( iSQLStatement );
+
+    if ( error < KErrNone && error != KErrNotFound )
+        {
+        User::Leave( error );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DeleteContextL
+// Deletes a context.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DeleteContextL( const TDesC& aName )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::DeleteContextL" );
+    
+    TInt error( KErrNone );
+    TUint32 contextId;
+    TUint32 tagId;
+    RDbView view1,view2;
+    
+    // Begin transaction
+    User::LeaveIfError( StartTransaction() );
+    CreatePushRollbackItemLC();
+    
+    CleanupClosePushL( view1 );
+    
+    // Search the context from DB
+    _LIT( KTick, "' " );
+    _LIT( KSQLGetContext, "select * from contexttable where name='" );
+    
+    iSQLStatement = KSQLGetContext;
+    iSQLStatement.Append( aName );
+    iSQLStatement.Append( KTick );
+    
+    User::LeaveIfError( view1.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view1.EvaluateAll() );
+    
+    // Get column set
+    CDbColSet* columns1 = view1.ColSetL();
+    // Get column ordinals
+    TDbColNo contextid_col= columns1->ColNo( KContextIdCol );
+    // Cleanup column set
+    delete columns1;
+    
+    view1.FirstL();
+    
+    // Doesn't exists, can't delete
+    if ( !view1.AtRow() )
+        {
+        User::Leave( KErrNotFound );
+        }
+    
+    view1.GetL();
+    contextId = view1.ColUint32( contextid_col );
+    
+    view1.DeleteL();
+    view1.Close();	
+    CleanupStack::PopAndDestroy( &view1 );
+    
+    // Delete all tags, which were in the context.
+    _LIT( KSQLGetTag, "select * from tagtable where contextid=" );
+    
+    iSQLStatement = KSQLGetTag;
+    iSQLStatement.AppendNumUC( contextId );
+    
+    CleanupClosePushL( view2 );
+    
+    User::LeaveIfError( view2.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );
+    User::LeaveIfError( view2.EvaluateAll() );
+    
+    ReserveDiskSpaceL( (sizeof(CNssTag) * view2.CountL()) + sizeof(CNssContext) );
+    
+    view2.FirstL();
+    
+    // If this context has any tags, remove the RRD entries from the RRD table.
+    if ( view2.AtRow() )
+        {
+        // Get column set
+        CDbColSet* columns2 = view2.ColSetL();
+        
+        // Get column ordinals
+        TDbColNo tagid_col = columns2->ColNo( KTagIdCol );
+        // Cleanup column2 set
+        delete columns2;
+        
+        for ( view2.FirstL(); view2.AtRow(); view2.NextL() )
+            {
+            view2.GetL();
+            tagId = view2.ColUint32( tagid_col );
+            RUBY_DEBUG0( "CNssVasDb::DeleteContextL deleting RRD" );
+            // Return value ignored since other tag ids should be iterated through
+            // even though one RRD deletion fails
+            TRAP( error, DeleteRRDL( tagId ) );
+            }
+        
+        view2.Close();
+        }
+    
+    // Remove tags from tag table
+    _LIT( KSQLDeleteTag, "delete from tagtable where contextid=");
+    iSQLStatement = KSQLDeleteTag;
+    iSQLStatement.AppendNumUC( contextId );
+    
+    error = iDatabase.Execute( iSQLStatement );
+    
+    CleanupStack::PopAndDestroy( &view2 );
+    
+    if ( error < KErrNone && error != KErrNotFound )
+        {
+        ReleaseDiskSpace();
+        // Roll back transaction
+        CleanupStack::PopAndDestroy(); // Rollback cleanup item
+        User::Leave( error );
+        }
+   
+    CleanupStack::Pop();  // Rollback cleanup item
+    CommitTransaction( ETrue );
+   
+    ReleaseDiskSpace();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateTagInTransactionL
+// Updates a tag. Assumes that a transaction has been started earlier.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateTagInTransactionL( CNssTag& aTag )
+    {
+    CNssContext* context = static_cast<CNssContext*> ( aTag.Context() );
+    UpdateContextInsideTransactionL( *context );
+    CNssSpeechItem* speechItem = static_cast<CNssSpeechItem*>
+        ( aTag.SpeechItem() );
+    UpdateSpeechItemL( *speechItem );
+    CNssRRD* rrd = static_cast<CNssRRD*> ( aTag.RRD() );
+    UpdateRRDL( *rrd );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DoUpdateContextL
+// Updates an existing context.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DoUpdateContextL( CNssContext& aContext )
+    {
+    _LIT( KSQLUpdateContext,"update contexttable set ");
+    _LIT( KEqual,"=");
+    _LIT( KCommon,",");
+    _LIT( KTick,"'");
+    _LIT( KSQLWhereContextId," where contextid = ");
+   
+    iSQLStatement = KSQLUpdateContext;
+     
+    iSQLStatement.Append( KNameCol );
+    iSQLStatement.Append( KEqual );
+    iSQLStatement.Append( KTick );
+    iSQLStatement.Append( aContext.ContextName() );
+    iSQLStatement.Append( KTick );
+   
+    iSQLStatement.Append( KCommon );
+    iSQLStatement.Append( KGlobalCol );
+    iSQLStatement.Append( KEqual );
+    iSQLStatement.AppendNumUC( aContext.IsGlobal() );
+
+    iSQLStatement.Append( KCommon );
+    iSQLStatement.Append( KGrammarIdCol );
+    iSQLStatement.Append( KEqual );
+    iSQLStatement.AppendNumUC( aContext.GrammarId() );
+
+    iSQLStatement.Append( KCommon );
+    iSQLStatement.Append( KLexiconIdCol );
+    iSQLStatement.Append( KEqual );
+    iSQLStatement.AppendNumUC( aContext.LexiconId() );
+
+    iSQLStatement.Append( KCommon );
+    iSQLStatement.Append( KModelBankIdCol );
+    iSQLStatement.Append( KEqual );
+    iSQLStatement.AppendNumUC( aContext.ModelBankId() );
+
+    iSQLStatement.Append( KSQLWhereContextId );
+    iSQLStatement.AppendNumUC( aContext.ContextId() );
+ 
+    User::LeaveIfError( iDatabase.Execute( iSQLStatement ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::DoUpdateUpdateContextClientDataL
+// Updates the client data of a context.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::DoUpdateContextClientDataL( CNssContext& aContext )
+    {
+	__UHEAP_MARK;
+
+	// Declare a literal string to hold the SQL statement
+	// SELECT KBinaryLexiconColumn , KBinaryLexiconColumn FROM  KLexiconName
+
+	_LIT( KSQLSelect1, "select clientdata from contexttable where name='" );
+
+	TBuf<KSqlStatementmaxLength> sqlStatement;
+	sqlStatement.Append( KSQLSelect1 );
+    sqlStatement.Append( aContext.ContextName() );
+    sqlStatement.Append( '\'' );
+
+	// create a view on the database
+	RDbView view;
+    CleanupClosePushL( view ); // Stack: view
+
+	User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( sqlStatement, EDbCompareNormal ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+	// Get the structure of rowset
+	CDbColSet* colSet = view.ColSetL();
+    CleanupStack::PushL( colSet ); // Stack: view, colset
+    TInt error( KErrNone );
+	
+	if( view.FirstL() )
+		{
+		view.UpdateL();
+
+    
+		// add binary buffer by Using the stream  
+
+		//RDbColWriteStream out;
+		TDbColNo col = colSet->ColNo( _L("clientdata") ); // Ordinal position of client data
+
+    	if ( col == KDbNullColNo )
+        	{
+        	User::Leave( KErrCorrupt );
+        	}
+
+    	view.SetColL( col, aContext.ClientData() ); 
+	
+		view.PutL();
+	
+		// close the view
+    	view.Close();
+		}
+	else 
+		{
+		error = KErrNotFound;
+		}
+    
+    CleanupStack::PopAndDestroy( colSet );
+    CleanupStack::PopAndDestroy( &view );
+
+	__UHEAP_MARKEND;
+
+    User::LeaveIfError( error );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateRRDL
+// Updates an existing RRD.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateRRDL( CNssRRD& aRRD )
+    {
+    TRAPD( error, DeleteRRDL( aRRD.TagId() ) );
+
+    if ( error != KErrNotFound)
+        {
+        error = KErrNone;
+        }
+
+    User::LeaveIfError( error );
+
+    SaveRRDL( &aRRD );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UpdateSpeechItemL
+// Updates an existing speech item.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UpdateSpeechItemL( CNssSpeechItem& aSpeechItem )
+    {
+    RDbView view;
+    CleanupClosePushL( view );
+ 
+    _LIT( KSQLGet, "select * from tagtable where tagid=" );
+    
+    iSQLStatement = KSQLGet;
+    iSQLStatement.AppendNumUC( aSpeechItem.TagId() );
+
+    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( iSQLStatement, EDbCompareNormal ) ) );	
+    User::LeaveIfError( view.EvaluateAll());
+    
+    // Get column set
+    CDbColSet* columns = view.ColSetL();
+    // Get column ordinals
+    TDbColNo name_col= columns->ColNo( KNameCol );
+
+    delete columns;
+	  
+    if ( view.FirstL() )
+        {
+        // Begin process of updating a row...
+        view.UpdateL();
+        // set column values...
+#ifdef __SIND_EXTENSIONS        
+        view.SetColL( name_col, aSpeechItem.RawText() ); 
+#else
+        view.SetColL( name_col, aSpeechItem.Text() ); 
+#endif
+
+        // add the row to the table...
+        view.PutL();
+		
+        // finished - so close the view
+        view.Close();
+		}
+    else 
+        {
+        User::Leave( KErrNotFound );
+        }	
+	
+    CleanupStack::PopAndDestroy( &view );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::FillSpeechItemL
+// Reads a TNssSpeechItem from DB to memory. Earlier, the caller has run an SQL
+// query and specifies the matching context in RDbView.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::FillSpeechItemL( RDbView& aView, CNssSpeechItem& aSpeechItem, TInt& aContextId )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::FillSpeechItemL" );
+
+	if ( aView.IsEmptyL() )
+	    {
+		User::Leave( KErrNotFound );
+	    }
+
+	// Get column set
+    CDbColSet* columns = aView.ColSetL();
+    // Get column ordinals
+ 	TDbColNo tagid_col    = columns->ColNo( KTagIdCol );
+ 	TDbColNo contextid_col= columns->ColNo( KContextIdCol );
+	TDbColNo ruleid_col   = columns->ColNo( KRuleIdCol );
+	TDbColNo name_col     = columns->ColNo( KNameCol );
+
+    // Cleanup column set
+    delete columns;
+
+	// Retrieve the current row
+	aView.GetL();
+	aSpeechItem.SetTagId( aView.ColUint32( tagid_col ) );
+	aSpeechItem.SetRuleID( aView.ColUint32( ruleid_col ) );
+	aSpeechItem.SetTextL( aView.ColDes( name_col ) );
+    aContextId = aView.ColUint32( contextid_col );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::FillContextL
+// Reads a context from DB to memory. Earlier, the caller has run an SQL query
+// and specifies the matching context in RDbView.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::FillContextL( RDbView& aView, CNssContext& aContext )
+    {
+    if ( aView.IsEmptyL() )
+	    {
+	    User::Leave( KErrNotFound );
+	    }
+
+	// Get column set
+    CDbColSet* columns = aView.ColSetL();
+    // Get column ordinals
+ 	TDbColNo contextid_col= columns->ColNo( KContextIdCol );
+	TDbColNo name_col = columns->ColNo( KNameCol );
+    TDbColNo global_col = columns->ColNo( KGlobalCol );
+	TDbColNo grammarid_col= columns->ColNo( KGrammarIdCol );
+	TDbColNo lexiconid_col= columns->ColNo( KLexiconIdCol );
+	TDbColNo modelbankid_col= columns->ColNo( KModelBankIdCol );
+    // Cleanup column set
+    delete columns;
+
+	// Retrieve the current row
+	aView.GetL();
+	aContext.SetContextId( aView.ColUint32( contextid_col ) );
+	aContext.SetGlobal( aView.ColUint32( global_col ) );
+	aContext.SetGrammarId( aView.ColUint32( grammarid_col ) );
+	aContext.SetLexiconId( aView.ColUint32( lexiconid_col ) );
+	aContext.SetModelBankId( aView.ColUint32( modelbankid_col ) );
+	aContext.SetNameL( aView.ColDes( name_col ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::FillTagListArrayL
+// Creates a TNssTag from context, speech item and RRD information.
+// Adds a tag to aTagList.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::FillTagListArrayL( CArrayPtrFlat<CNssTag>& aTagList, CNssContext* aContext, 
+                                   CNssSpeechItem* aSpeechItem, CNssRRD* aRRD )
+    {    
+    CNssContext* contextCopy = aContext->CopyL();
+    CNssSpeechItem* speechItenCopy = aSpeechItem->CopyL( contextCopy );
+    CNssRRD* rrdCopy = aRRD->CopyL();
+    CNssTag* tag = new (ELeave) CNssTag( contextCopy, rrdCopy, speechItenCopy );
+    tag->SetTagId( aSpeechItem->TagId() );
+	
+	aTagList.AppendL( tag );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::FillContextListArrayL
+// Utility function to read contexts from DB to memory. Earlier, the caller has
+// run an SQL query and the matches are listed in an RDbView.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::FillContextListArrayL( RDbView& aView, CArrayPtrFlat<CNssContext>& aContextList )
+    {
+    RUBY_DEBUG_BLOCK("CNssVasDb::FillContextListArrayL");
+	TInt pos( 0 );
+
+	// Clear the previous array.
+	aContextList.Reset();
+
+    // Get column set
+    CDbColSet* columns = aView.ColSetL();
+
+    // Get column ordinals
+    TDbColNo name_col       = columns->ColNo( KNameCol );
+    TDbColNo global_col     = columns->ColNo( KGlobalCol );
+	TDbColNo grammarid_col  = columns->ColNo( KGrammarIdCol );
+	TDbColNo lexiconid_col  = columns->ColNo( KLexiconIdCol );
+	TDbColNo modelbankid_col= columns->ColNo( KModelBankIdCol );
+	TDbColNo contextid_col  = columns->ColNo( KContextIdCol );
+
+    // New in 2.8
+    TDbColNo clientdata_col = columns->ColNo( KClientDataCol );
+
+	delete columns;
+
+	for (aView.FirstL(); aView.AtRow(); aView.NextL())
+	    {
+	    aView.GetL(); // Retrieve the current row - actually reads the row from the database.
+       
+        CNssContext* oneContext = iContextBuilder.CreateContextL();
+        CleanupStack::PushL( oneContext );
+       
+        oneContext->SetNameL( aView.ColDes( name_col ) );
+        oneContext->SetGlobal( aView.ColUint32( global_col ) );
+        oneContext->SetContextId( aView.ColUint32( contextid_col ) );
+        oneContext->SetLexiconId( aView.ColUint32( lexiconid_col ) );
+        oneContext->SetGrammarId( aView.ColUint32( grammarid_col ) );
+        oneContext->SetModelBankId( aView.ColUint32( modelbankid_col ) );
+        oneContext->SetClientData( aView.ColDes8( clientdata_col ) );
+       
+	    // Now add the context object to the list (array) of context.
+	    aContextList.InsertL( pos++, oneContext );
+	   
+	    // Copy has been created in aContextList, no need for pointer anymore
+	    CleanupStack::Pop( oneContext );
+	    }
+}
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::StartTransactionL
+// Starts a new transaction.
+// -----------------------------------------------------------------------------
+//
+TInt CNssVasDb::StartTransaction()
+    {
+    RUBY_DEBUG0( "CNssVasDb::StartTransaction" );
+    
+    if ( !iClientHasOpenedDatabase )
+        {
+        RUBY_DEBUG0( "No open DB. E.g. backup/restore in progress" );
+        return KErrNotReady;
+        }
+
+    __ASSERT_DEBUG( iLocked == iDatabase.InTransaction(), User::Panic( KVasDbPanic, __LINE__ ) );
+    
+    iCriticalSection.Wait();
+    if ( iLocked )
+        {
+        // If we already have the lock, no need to take it again
+        RUBY_DEBUG0( "CNssVasDb::StartTransaction DB is already locked by current process" );
+        return KErrNone;
+        }
+
+    // Wait for the mutex so that two processes don't try get the lock simultaneously
+    RUBY_DEBUG0( "Waiting for mutex in CNssVasDb::StartTransaction" );
+    iMutex.Wait();
+    
+    // check if backup is ongoing
+	    
+    TInt readLockErr = iDatabase.Begin();
+
+    // Mutex should make it sure that we have exclusive lock to Database
+    // Thus iDatabase.Begin() should succeed every time
+    __ASSERT_DEBUG( readLockErr == KErrNone, User::Panic( KVasDbPanic, __LINE__ ) );
+   
+    if ( readLockErr == KErrNone )
+        {
+        iLocked = ETrue;
+        }
+
+    RUBY_DEBUG0( "CNssVasDb::StartTransaction completed" );        
+        
+    return readLockErr;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CommitTransaction
+// Commits changes and releases the lock. If iShouldBeLocked flag is set,
+// opens a new tranaction in order to keep the database locked.
+// -----------------------------------------------------------------------------
+//
+TInt CNssVasDb::CommitTransaction( TBool aCompact )
+    {
+    RUBY_DEBUG0( "CNssVasDb::CommitTransaction" );
+
+    __ASSERT_DEBUG( iLocked == iDatabase.InTransaction(), User::Panic( KVasDbPanic, __LINE__ ) );
+    //__ASSERT_DEBUG( iLocked, User::Panic( _L("VasCNssVasDb.cpp"), __LINE__ ) );
+
+    TInt ret = KErrNone;
+
+    if ( iLocked )
+        {
+        ret = iDatabase.Commit();
+        
+        if ( iDatabase.IsDamaged() )
+            {
+            RUBY_DEBUG0( "CNssVasDb::CommitTransaction Recovering" );
+            ret = iDatabase.Recover();
+            }
+        
+        if ( aCompact )
+            {
+            RUBY_DEBUG0( "CNssVasDb::CommitTransaction compacting DB" );
+            iDatabase.Compact(); 
+            }
+        
+        iLocked = EFalse;
+        
+        RUBY_DEBUG0( "Signalling mutex in CNssVasDb::CommitTransaction" );
+        iMutex.Signal();
+        }
+    else
+        {
+        RUBY_DEBUG0( "ERROR: CNssVasDb::CommitTransaction does nothing, not locked" );
+        }
+        
+    iCriticalSection.Signal();
+    return( ret );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::RollbackTransaction
+// Discards changes and releases the lock.
+// -----------------------------------------------------------------------------
+//
+TInt CNssVasDb::RollbackTransaction()
+    {
+    __ASSERT_DEBUG( iLocked == iDatabase.InTransaction(), User::Panic( KVasDbPanic, __LINE__ ) );
+    __ASSERT_DEBUG( iLocked, User::Panic( KVasDbPanic, __LINE__ ) );
+
+    TInt ret = KErrNone;
+
+    iDatabase.Rollback();
+    
+    iLocked = EFalse;
+    
+    if ( iDatabase.IsDamaged() )
+        {
+        RUBY_DEBUG0( "CNssVasDb::RollbackTransaction Recovering" );
+        ret = iDatabase.Recover();
+        }
+
+
+    RUBY_DEBUG0( "Signalling mutex in CNssVasDb::RollbackTransaction" );
+    iMutex.Signal();
+    iCriticalSection.Signal();
+    
+    return( ret );
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::LockTransactionsL
+// Permit transactions and release database
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::LockTransactionsL()
+    {
+    // lock transactions
+    RUBY_DEBUG_BLOCK( "CNssVasDb::LockTransactionsL" );
+    
+    iCriticalSection.Wait(); // wait until a possible transaction ends
+            
+    // release a database
+    CloseDatabase();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::UnlockTransactionsL
+// Allow transactions and reserve database
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::UnlockTransactionsL()
+    {
+    // unlock transactions
+    RUBY_DEBUG_BLOCK( "CNssVasDb::UnlockTransactionsL" );
+    OpenDatabaseL(); // open database
+    
+    if ( iCriticalSection.IsBlocked() )
+        {        
+        iCriticalSection.Signal(); // allow to do transactions
+        }
+    }
+    	
+// -----------------------------------------------------------------------------
+// CNssVasDb::ReserveDiskSpaceL(
+// Reserves disk space. Leaves (KErrDiskFull), if not
+// enough space.
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::ReserveDiskSpaceL( TInt aRequestSize )
+    {
+    RUBY_DEBUG_BLOCK( "CNssVasDb::ReserveDiskSpaceL" );
+
+#ifdef _DEBUG
+    TInt error = iDbSession.ReserveDriveSpace( iDrive, aRequestSize );
+    if ( error )
+        {
+        RUBY_DEBUG1( "CNssVasDb::ReserveDiskSpaceL fails %d", error );
+        User::Leave( error );
+        }
+#else
+    User::LeaveIfError( iDbSession.ReserveDriveSpace( iDrive, aRequestSize ) );
+#endif // _DEBUG
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::ReleaseDiskSpace
+// Releases the disk space
+// -----------------------------------------------------------------------------
+//
+void CNssVasDb::ReleaseDiskSpace()
+    {
+    RUBY_DEBUG0( "CNssVasDb::ReleaseDiskSpace" );
+    iDbSession.FreeReservedSpace( iDrive );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssVasDb::CreateRollbackItemLC
+// Creates a cleanup item and pushes it to the cleanup stack. In case of a 
+// leave, PopAndDestroying this item will call RollbackCleanupFunction
+// -----------------------------------------------------------------------------
+void CNssVasDb::CreatePushRollbackItemLC() 
+    {
+    TCleanupItem item( RollbackCleanupFunction, this );
+    CleanupStack::PushL( item );
+    }
+
+// End of file