srsf/sisrscontrollerplugin/src/sidatabase.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
equal deleted inserted replaced
18:cad71a31b7fc 19:e36f3802f733
       
     1 /*
       
     2 * Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class implements the SI Controller Plugin database.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "sidatabase.h"
       
    21 #include "rubydebug.h"
       
    22 #include "nssbackupobserver.h"
       
    23 
       
    24 
       
    25 // CONSTANTS
       
    26 // Estimate size in bytes for an empty database
       
    27 // const TInt KSizeEstimateDb = 650;
       
    28 
       
    29 // Plugin database format string for secure DBMS
       
    30 _LIT( KPluginDatabaseFormatString, "SECURE[10201AFF]" );
       
    31 
       
    32 // Name of the DB lock mutex
       
    33 _LIT( KLockMutex, "SIDATABASE" );
       
    34 
       
    35 // ============================ MEMBER FUNCTIONS ===============================
       
    36 
       
    37 // -----------------------------------------------------------------------------
       
    38 // CSIDatabase::CSIDatabase
       
    39 // C++ default constructor can NOT contain any code, that
       
    40 // might leave.
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 CSIDatabase::CSIDatabase( TFileName aDatabaseFileName )
       
    44                         : iOpenTransaction( EFalse ),
       
    45                           iDatabaseFileName( aDatabaseFileName ),
       
    46                           iDatabaseOpen( EFalse )
       
    47     {
       
    48     // Nothing
       
    49     }
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CSIDatabase::ConstructL
       
    53 // Symbian 2nd phase constructor can leave.
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 void CSIDatabase::ConstructL()
       
    57     {
       
    58     RUBY_DEBUG_BLOCKL( "CSIDatabase::ConstructL" );
       
    59     // Checks to see if the Database already exists.  If not, it creates one.
       
    60     User::LeaveIfError( iDbSession.Connect() );
       
    61     CreateDatabaseL();
       
    62     OpenDatabaseL();
       
    63     
       
    64     TInt err = iMutex.OpenGlobal( KLockMutex );
       
    65     if ( err != KErrNone )
       
    66         {
       
    67         RUBY_DEBUG0( "CSIDatabase::ConstructL Creating new global mutex" );
       
    68         iMutex.CreateGlobal( KLockMutex );
       
    69         }
       
    70     else
       
    71         {
       
    72         RUBY_DEBUG0( "CSIDatabase::ConstructL Using existing global mutex" );
       
    73         }
       
    74         
       
    75     iCriticalSection.CreateLocal();
       
    76     iBackupObserver = CNssBackupObserver::NewL( *this );
       
    77     
       
    78     }
       
    79 
       
    80 // -----------------------------------------------------------------------------
       
    81 // CSIDatabase::NewL
       
    82 // Two-phased constructor.
       
    83 // -----------------------------------------------------------------------------
       
    84 //
       
    85 CSIDatabase* CSIDatabase::NewL( TFileName aSDDatabaseFileName )
       
    86     {
       
    87     RUBY_DEBUG_BLOCKL( "CSIDatabase::NewL" );
       
    88     
       
    89     CSIDatabase* self = new( ELeave ) CSIDatabase( aSDDatabaseFileName );
       
    90     CleanupStack::PushL( self );
       
    91     self->ConstructL();
       
    92     CleanupStack::Pop();
       
    93     
       
    94     return self;
       
    95     }
       
    96 
       
    97 // -----------------------------------------------------------------------------
       
    98 // CSIDatabase::Rollback
       
    99 // Rollback all changes to the database. 
       
   100 // -----------------------------------------------------------------------------
       
   101 //
       
   102 void CSIDatabase::Rollback()
       
   103     {
       
   104     RUBY_DEBUG0( "CSIDatabase::Rollback" );
       
   105     if ( iOpenTransaction )
       
   106         {
       
   107         iDb.Rollback();
       
   108         // Try to recover the database, if it is damaged
       
   109         if( iDb.IsDamaged() )
       
   110             {
       
   111             iDb.Recover();
       
   112             }
       
   113         iMutex.Signal();
       
   114         iCriticalSection.Signal();
       
   115         iOpenTransaction = EFalse;
       
   116         }
       
   117     
       
   118     }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CSIDatabase::~CSIDatabase
       
   122 // Destructor 
       
   123 // -----------------------------------------------------------------------------
       
   124 //
       
   125 CSIDatabase::~CSIDatabase()
       
   126     {
       
   127     // Rollback if there are any changes not commited
       
   128     if ( iOpenTransaction )
       
   129         {
       
   130         iDb.Rollback();
       
   131         // Try to recover the database, if it is damaged
       
   132         if( iDb.IsDamaged() )
       
   133             {
       
   134             iDb.Recover();
       
   135             }
       
   136         // Signal mutex if somebody happens to be waiting in BeginTransactionL()
       
   137         iMutex.Signal();
       
   138         }
       
   139         
       
   140     delete iBackupObserver;
       
   141     iCriticalSection.Close();
       
   142 
       
   143     iDb.Close();
       
   144     iDbSession.Close();
       
   145     iDatabaseOpen = EFalse;
       
   146     }
       
   147 
       
   148 // -----------------------------------------------------------------------------
       
   149 // CSIDatabase::BeginTransactionL
       
   150 // Begins a database transaction if not already. Waits until exclusive write lock
       
   151 // has been gained.
       
   152 // -----------------------------------------------------------------------------
       
   153 //
       
   154 void CSIDatabase::BeginTransactionL()
       
   155     {
       
   156    
       
   157 
       
   158     if ( iOpenTransaction )
       
   159         {
       
   160         // If we already have the lock, no need to take it again
       
   161         RUBY_DEBUG0( "CSIDatabase::BeginTransactionL DB is already locked by current process" );
       
   162         return;
       
   163         }
       
   164     
       
   165     // Take mutex to ensure that only one process tries to gain the lock
       
   166     iMutex.Wait();
       
   167     iCriticalSection.Wait();
       
   168     
       
   169     // Taking the global mutex makes it sure that this should succeed every time
       
   170     TInt readLockErr = iDb.Begin();
       
   171 
       
   172     if ( readLockErr == KErrNone )
       
   173         {
       
   174         iOpenTransaction = ETrue;
       
   175         }
       
   176     }
       
   177 
       
   178 // -----------------------------------------------------------------------------
       
   179 // CSIDatabase::CommitChangesL
       
   180 // Commits all changes to the database.
       
   181 // -----------------------------------------------------------------------------
       
   182 //
       
   183 void CSIDatabase::CommitChangesL( TBool aCompact )
       
   184     {
       
   185     if ( iOpenTransaction )
       
   186         {
       
   187         TInt err = iDb.Commit();
       
   188         
       
   189         RUBY_DEBUG1( "CSIDatabase::CommitChangesL iDb.Commit() [%d]", err );
       
   190         
       
   191         if ( err != KErrNone )
       
   192             {
       
   193             iDb.Rollback();
       
   194             // Try to recover the database, if it is damaged
       
   195             if( iDb.IsDamaged() )
       
   196                 {
       
   197                 iDb.Recover();
       
   198                 }
       
   199                 
       
   200             iMutex.Signal();
       
   201             iCriticalSection.Signal();  
       
   202             iOpenTransaction = EFalse;
       
   203             User::Leave( err );
       
   204             }
       
   205         
       
   206         if ( aCompact )
       
   207             {
       
   208             RUBY_DEBUG0( "CSIDatabase::CommitChangesL compacting DB" );
       
   209             TInt error = iDb.Compact();
       
   210             if ( error != KErrNone )
       
   211                 {
       
   212                 RUBY_DEBUG1( "CSIDatabase::CommitChangesL compact error: [%d]", error );
       
   213                 }
       
   214             }
       
   215         
       
   216         // Signal waiting BeginTransactionL()
       
   217         iMutex.Signal();
       
   218         iCriticalSection.Signal();  
       
   219         iOpenTransaction = EFalse;
       
   220         
       
   221         User::LeaveIfError( err );
       
   222         }
       
   223         
       
   224           
       
   225     }
       
   226 
       
   227 // -----------------------------------------------------------------------------
       
   228 // CSIDatabase::DoIDTablesExistL
       
   229 // Checks to see if ID tables exist.
       
   230 // -----------------------------------------------------------------------------
       
   231 //
       
   232 TBool CSIDatabase::DoIDTablesExistL()
       
   233     {
       
   234     // Get db table names list
       
   235     CDbTableNames* table_names = iDb.TableNamesL();
       
   236     TInt count = table_names->Count();
       
   237     delete table_names;
       
   238     // 1 is for the lock table!
       
   239     return ( count > 1 );
       
   240     }
       
   241 
       
   242 // -----------------------------------------------------------------------------
       
   243 // CSIDatabase::DoesLockTableExistL
       
   244 // Checks to see if lock table exists
       
   245 // -----------------------------------------------------------------------------
       
   246 //
       
   247 TBool CSIDatabase::DoesLockTableExistL()
       
   248     {
       
   249     // Get db table names list
       
   250     CDbTableNames* table_names = iDb.TableNamesL();
       
   251     TInt count = table_names->Count();
       
   252 
       
   253     for ( TInt counter = 0 ; counter < count ; counter++ )
       
   254         {
       
   255         if ( (*table_names)[counter] == _L( "writelocktable" ) )
       
   256             {
       
   257             delete table_names;
       
   258             return ETrue;
       
   259             }
       
   260         }
       
   261 
       
   262     delete table_names;
       
   263     return EFalse;
       
   264     }
       
   265 
       
   266 // -----------------------------------------------------------------------------
       
   267 // CSIDatabase::DoesModelBankTableExistL
       
   268 // Checks to see if model bank table exists
       
   269 // -----------------------------------------------------------------------------
       
   270 //
       
   271 TBool CSIDatabase::DoesModelBankTableExistL()
       
   272     {
       
   273     // Get db table names list
       
   274     CDbTableNames* table_names = iDb.TableNamesL();
       
   275     TInt count = table_names->Count();
       
   276 
       
   277     for ( TInt counter = 0 ; counter < count ; counter++ )
       
   278         {
       
   279         if ( (*table_names)[counter] == _L( "siModelBankIdTable" ) )
       
   280             {
       
   281             delete table_names;
       
   282             return ETrue;
       
   283             }
       
   284         }
       
   285 
       
   286     delete table_names;
       
   287     return EFalse;
       
   288     }
       
   289 
       
   290 // -----------------------------------------------------------------------------
       
   291 // CSIDatabase::DoesLexiconTableExistL
       
   292 // Checks if lexicon table exists
       
   293 // -----------------------------------------------------------------------------
       
   294 //
       
   295 TBool CSIDatabase::DoesLexiconTableExistL()
       
   296     {
       
   297     // Get db table names list
       
   298     CDbTableNames* table_names = iDb.TableNamesL();
       
   299     TInt count = table_names->Count();
       
   300 
       
   301     for ( TInt counter = 0 ; counter < count ; counter++ )
       
   302         {
       
   303         if ( (*table_names)[counter] == _L( "siLexiconIdTable" ) )
       
   304             {
       
   305             delete table_names;
       
   306             return ETrue;
       
   307             }
       
   308         }
       
   309 
       
   310     delete table_names;
       
   311     return EFalse;
       
   312     }
       
   313 
       
   314 // -----------------------------------------------------------------------------
       
   315 // CSIDatabase::DoesGrammarTableExistL
       
   316 // Checks if grammar table exists
       
   317 // -----------------------------------------------------------------------------
       
   318 //
       
   319 TBool CSIDatabase::DoesGrammarTableExistL()
       
   320     {
       
   321     // Get db table names list
       
   322     CDbTableNames* table_names = iDb.TableNamesL();
       
   323     TInt count = table_names->Count();
       
   324 
       
   325     for ( TInt counter = 0 ; counter < count ; counter++ )
       
   326         {
       
   327         if ( (*table_names)[counter] == _L( "siGrammarIdTable" ) )
       
   328             {
       
   329             delete table_names;
       
   330             return ETrue;
       
   331             }
       
   332         }
       
   333 
       
   334     delete table_names;
       
   335     return EFalse;
       
   336     }
       
   337 
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CSIDatabase::SIDatabase
       
   341 // Returns a reference to the database.
       
   342 // -----------------------------------------------------------------------------
       
   343 //
       
   344 RDbNamedDatabase& CSIDatabase::SIDatabase()
       
   345     {
       
   346     return iDb;
       
   347     }
       
   348 
       
   349 // -----------------------------------------------------------------------------
       
   350 // CSIDatabase::CreateDatabaseL
       
   351 // Creates a database file if one does not exist yet.
       
   352 // -----------------------------------------------------------------------------
       
   353 //
       
   354 void CSIDatabase::CreateDatabaseL()
       
   355     {
       
   356     RUBY_DEBUG_BLOCKL( "CSIDatabase::CreateDatabaseL" );
       
   357     
       
   358     // Get the drive of the database file
       
   359     iDatabaseDrive = EDriveC;
       
   360     if ( iDatabaseFileName.Locate( 'c' ) == 0 || iDatabaseFileName.Locate( 'C' ) == 0 )
       
   361         {
       
   362         iDatabaseDrive = EDriveC;
       
   363         }
       
   364     else if ( iDatabaseFileName.Locate( 'd' ) == 0 || iDatabaseFileName.Locate( 'D' ) == 0 )
       
   365         {
       
   366         iDatabaseDrive = EDriveD;
       
   367         }
       
   368     else if ( iDatabaseFileName.Locate( 'z' ) == 0 || iDatabaseFileName.Locate( 'Z' ) == 0 )
       
   369         {
       
   370         iDatabaseDrive = EDriveZ;
       
   371         }
       
   372     
       
   373     else if ( iDatabaseFileName.Locate( 'e' ) == 0 || iDatabaseFileName.Locate( 'E' ) == 0 )
       
   374         {
       
   375         iDatabaseDrive = EDriveE;
       
   376         }
       
   377     else
       
   378         {
       
   379         User::Leave( KErrPathNotFound );
       
   380         }
       
   381     
       
   382     RDbNamedDatabase database;
       
   383     TInt ret = database.Create( iDbSession, iDatabaseFileName, KPluginDatabaseFormatString );
       
   384     if ( ret == KErrAlreadyExists )
       
   385         {
       
   386         // Ignore KErrAlreadyExists, we will use the existing one if it is there
       
   387         ret = KErrNone;
       
   388         }
       
   389     database.Close();
       
   390     User::LeaveIfError( ret );
       
   391     }
       
   392 
       
   393 // -----------------------------------------------------------------------------
       
   394 // CSIDatabase::OpenDatabaseL
       
   395 // Opens the database.
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 void CSIDatabase::OpenDatabaseL()
       
   399     {
       
   400     if ( !iDatabaseOpen )
       
   401         {
       
   402         
       
   403         User::LeaveIfError( iDb.Open( iDbSession, iDatabaseFileName, KPluginDatabaseFormatString ) );
       
   404         
       
   405         // Try to recover the database, if it is damaged
       
   406         if( iDb.IsDamaged() )
       
   407             {
       
   408             RUBY_DEBUG0( "CSIDatabase::OpenDatabaseL - Db is damaged. Attempt to recover." );
       
   409             
       
   410             User::LeaveIfError( iDb.Recover() );
       
   411             }
       
   412         
       
   413         iDatabaseOpen = ETrue;
       
   414         }
       
   415     }
       
   416     
       
   417 // -----------------------------------------------------------------------------
       
   418 // CSIDatabase::CloseDatabase
       
   419 // Closes the database.
       
   420 // -----------------------------------------------------------------------------
       
   421 //
       
   422 TInt CSIDatabase::CloseDatabase()
       
   423     {
       
   424     RUBY_DEBUG0( "CSIDatabase::CloseDatabase" ); 
       
   425   
       
   426     iDb.Close();
       
   427     iDatabaseOpen = EFalse;
       
   428 
       
   429     return KErrNone;
       
   430     }
       
   431 
       
   432 // -----------------------------------------------------------------------------
       
   433 // CSIDatabase::DbSession
       
   434 // Return reference to DB session.
       
   435 // -----------------------------------------------------------------------------
       
   436 //
       
   437 RDbs& CSIDatabase::DbSession()
       
   438     {
       
   439     return iDbSession;
       
   440     }
       
   441 
       
   442 // -----------------------------------------------------------------------------
       
   443 // CSIDatabase::DbDrive
       
   444 // Returns a drive for DB file.
       
   445 // -----------------------------------------------------------------------------
       
   446 //
       
   447 TInt CSIDatabase::DbDrive()
       
   448     {
       
   449     return iDatabaseDrive;
       
   450     }
       
   451 
       
   452 // -----------------------------------------------------------------------------
       
   453 // CSIDatabase::CreateLockTableL
       
   454 // Creates a dummy table to gain write-lock at the beginning of each transaction.
       
   455 // -----------------------------------------------------------------------------
       
   456 //
       
   457 void CSIDatabase::CreateLockTableL()
       
   458     {
       
   459     // Create writelocktable
       
   460     // This table is accessed every time when transaction starts to gain
       
   461     // exclusive locking of the DB
       
   462     _LIT( KWriteLockTable, "writelocktable" );
       
   463     
       
   464     _LIT( KCol1, "temporary" );
       
   465     
       
   466     OpenDatabaseL();
       
   467     
       
   468     // Create the rrd tables definition (columnset).
       
   469     CDbColSet* columns = CDbColSet::NewLC();
       
   470     
       
   471     // The tag id 
       
   472     TDbCol dbCol1( KCol1, EDbColUint32 );
       
   473     columns->AddL( dbCol1 );
       
   474     
       
   475     User::LeaveIfError( iDb.CreateTable( KWriteLockTable, *columns ) );
       
   476     
       
   477     // Cleanup columns
       
   478     CleanupStack::PopAndDestroy( columns ); 
       
   479     }
       
   480     
       
   481 // -----------------------------------------------------------------------------
       
   482 // CSIDatabase::LockTransactionsL
       
   483 // Permit transactions and release database
       
   484 // -----------------------------------------------------------------------------
       
   485 //
       
   486 void CSIDatabase::LockTransactionsL()
       
   487     {
       
   488     // lock transactions
       
   489     RUBY_DEBUG_BLOCK( "CSIDatabase::LockTransactionsL" );
       
   490     
       
   491     iCriticalSection.Wait(); // wait until a possible transaction ends
       
   492             
       
   493     // release a database
       
   494     CloseDatabase();
       
   495     }
       
   496 
       
   497 // -----------------------------------------------------------------------------
       
   498 // CSIDatabase::UnlockTransactionsL
       
   499 // Allow transactions and reserve database
       
   500 // -----------------------------------------------------------------------------
       
   501 //
       
   502 void CSIDatabase::UnlockTransactionsL()
       
   503     {
       
   504     // unlock transactions
       
   505     RUBY_DEBUG_BLOCK( "CSIDatabase::UnlockTransactionsL" );
       
   506     OpenDatabaseL(); // open database
       
   507     
       
   508     if ( iCriticalSection.IsBlocked() )
       
   509         {        
       
   510         iCriticalSection.Signal(); // allow to do transactions
       
   511         }
       
   512     }
       
   513 
       
   514 //  End of File