examples/Base/SemaphoreExample/src/CDatabase.cpp

00001 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
00002 // All rights reserved.
00003 // This component and the accompanying materials are made available
00004 // under the terms of "Eclipse Public License v1.0"
00005 // which accompanies this distribution, and is available
00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
00007 //
00008 // Initial Contributors:
00009 // Nokia Corporation - initial contribution.
00010 //
00011 // Contributors:
00012 //
00013 // Description:
00014 // This class contains methods to create a database of integers and periodically read /write integers
00015 // from/ to the database. The macro USE_SEMAPHORE is used at various places to show thread synchronization
00016 // using a semaphore. 
00017 
00018 #include "CDatabase.h"
00019 
00020 //Declare a delay of 1000000 microseconds i.e. 1 sec for the periodic functions. 
00021 const int KDelay = 1000000; 
00022 
00023 //The last number in the database.
00024 const int KLastNum = 50; 
00025 
00029 CDatabase* CDatabase::NewL()
00030     {
00031     CDatabase* self=new(ELeave)CDatabase();
00032     CleanupStack::PushL(self);
00033     self->ConstructL();
00034     CleanupStack::Pop(self);
00035     return self;
00036     }
00037 
00041 CDatabase::~CDatabase()
00042     {   
00043     iFsSession.Close();  //close the file server session. 
00044     delete iPeriodic;    //delete the periodic object.
00045     delete iConsole;     //delete the console. 
00046     #ifdef USE_SEMAPHORE
00047     iSemWrite.Close(); 
00048     #endif
00049     }
00050 
00054 void CDatabase::ConstructL()
00055     {
00056     iPeriodic = CPeriodic::NewL(CActive::EPriorityUserInput);
00057     
00058     _LIT(KDbCreateDb,"exampleDatabase.db");
00059       
00060     iFsSession.Connect();
00061     
00062     //The database exampleDatabase.db is created as a permanent file store 
00063     //in the app's private directory.
00064     User::LeaveIfError(iFsSession.CreatePrivatePath(RFs::GetSystemDrive()));
00065 
00066     User::LeaveIfError(iFsSession.PrivatePath(iDbname));
00067     iDbname.Append(KDbCreateDb); 
00068 
00069     #ifdef USE_SEMAPHORE
00070     //Open the global semaphore which was created in CSemaphoreExample. 
00071     _LIT(KSemaphoreWrite, "WriteSemaphore");
00072     User::LeaveIfError(iSemWrite.OpenGlobal(KSemaphoreWrite, EOwnerProcess)); 
00073     #endif
00074     }
00075 
00079 void CDatabase::CreateDatabaseL()
00080     {
00081     //Construct a file store object - the file to contain the
00082     //database replaces any existing file of the same name.
00083     CFileStore* store = CPermanentFileStore::ReplaceLC(iFsSession, iDbname, EFileRead|EFileWrite);
00084     //Complete file store creation.
00085     store->SetTypeL(store->Layout());
00086     
00087     //Create a database in the store.  
00088     TStreamId id= iDatabase.CreateL(store);
00089     
00090     //Keep database id as root of store.
00091     store->SetRootL(id);
00092     
00093     //Complete database creation by commiting the store.
00094     store->CommitL();
00095     
00096     
00097     //Create a table definition.
00098     CDbColSet* columns=CDbColSet::NewLC();
00099     
00100     //Add three columns each containing Int32 values. 
00101     _LIT(KCol1, "Number1");
00102     _LIT(KCol2, "Number2");
00103     _LIT(KCol3, "Number3");   
00104     columns->AddL(TDbCol(KCol1,EDbColInt32));
00105     columns->AddL(TDbCol(KCol2,EDbColInt32));
00106     columns->AddL(TDbCol(KCol3,EDbColInt32));
00107     
00108     
00109     //Create the table, table name is "Numbers" and add the columns to it.
00110     _LIT(KTable, "Numbers");
00111     User::LeaveIfError(iDatabase.CreateTable(KTable,*columns));
00112     
00113     CDbKey* key=CDbKey::NewLC();
00114     
00115     //Add the key columns.
00116     TDbKeyCol number1(KCol1);
00117     key->AddL(number1);
00118     TDbKeyCol number2(KCol2);
00119     key->AddL(number2);
00120     TDbKeyCol number3(KCol3);
00121     key->AddL(number3);
00122     User::LeaveIfError(iDatabase.CreateIndex(KTable,KTable,*key));
00123     
00124     iDatabase.Close();
00125     //Cleanup the column set.  
00126     CleanupStack::PopAndDestroy(key);
00127     CleanupStack::PopAndDestroy(columns);
00128     CleanupStack::PopAndDestroy(store);
00129     }
00130 
00135 void CDatabase::WritetoDatabaseL()
00136     {
00137     iPeriodic->Start(0, KDelay, TCallBack(PeriodicWriteL, this));
00138     CActiveScheduler::Start();
00139     }
00140 
00145 TInt CDatabase::PeriodicWriteL(TAny* aPtr)
00146     {
00147     CDatabase* ptr = static_cast<CDatabase*> (aPtr);
00148     //Invoke the RThread::Resume() function on the consumer thread repeatedly.
00149     ptr->PeriodicWriteFuncL();
00150     return KErrNone;
00151     }
00152 
00157 void CDatabase::PeriodicWriteFuncL()
00158     {
00159     //Declare an integer which is used to fill numbers in the database. 
00160     static int num = 0 ;  
00161     
00162      //Open the file store.
00163     _LIT(KSQLStatement,"select Number1, Number2, Number3 from Numbers order by Number1,Number2,Number3");
00164     CFileStore* store = CFileStore::OpenLC(iFsSession,iDbname,EFileRead|EFileWrite);
00165     
00166     
00167     //Open the database from the root stream.
00168     iDatabase.OpenL(store,store->Root());
00169     
00170     //Lock the database before use. 
00171     iDatabase.Begin();
00172     
00173     //Create a view on the database view to read/write numbers into it. 
00174     RDbView view;
00175     User::LeaveIfError(view.Prepare(iDatabase,TDbQuery(KSQLStatement,EDbCompareNormal)));
00176     User::LeaveIfError(view.EvaluateAll());
00177 
00178     
00179     //Insert a new row at the end of the database. 
00180     view.InsertL();
00181 
00182     //Fill three coloumns with numbers.
00183     view.SetColL(1, num++);
00184     view.SetColL(2, num++);
00185     view.SetColL(3, num++);
00186     view.PutL();
00187     
00188     //Close the view. 
00189     view.Close();
00190     
00191     //Unlock the database after writing. 
00192     iDatabase.Commit();
00193     
00194     // close the database.
00195     iDatabase.Close();
00196 
00197     //Do not commit store: database has taken control of commit.
00198     CleanupStack::PopAndDestroy(store);
00199     
00200     //Cancel the periodic function once 50 numbers have been written to the database.
00201     if(num > KLastNum )
00202         {
00203         iPeriodic->Cancel();
00204         CActiveScheduler::Stop();
00205         }
00206     
00207     #ifdef USE_SEMAPHORE
00208     /*Signal the semaphore and the PeriodicReadFunc() which was 
00209       waiting on the semaphore is scheduled to run. 
00210       */
00211     iSemWrite.Signal();
00212     #endif
00213     }
00214     
00220 void CDatabase::ReadfromDatabaseL()
00221     { 
00222     _LIT(KTextConsoleTitle, "ReaderThread");
00223     if(!iConsole)
00224         {
00225          iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)); 
00226          _LIT(KReading, "Reading the database.\n");
00227          iConsole->Printf(KReading);
00228         }   
00229     iPeriodic->Start(0, KDelay, TCallBack(PeriodicReadL,this));
00230     CActiveScheduler::Start();
00231     }
00232 
00237 TInt CDatabase::PeriodicReadL(TAny* aPtr)
00238     {
00239     CDatabase* ptr = static_cast<CDatabase*> (aPtr);
00240     ptr->PeriodicReadFuncL();
00241     return KErrNone;
00242     }
00243 
00248 void CDatabase::PeriodicReadFuncL()
00249     {
00250     #ifdef USE_SEMAPHORE
00251     //Semaphore waits till it gets a signal from the PeriodicWrite() function. 
00252     iSemWrite.Wait();
00253     #endif
00254     
00255     CFileStore* store = CFileStore::OpenLC(iFsSession,iDbname,EFileRead);  
00256     
00257     //Open the database from the root stream.
00258     iDatabase.OpenL(store,store->Root());
00259     
00260     //Lock the database.
00261     iDatabase.Begin();
00262     
00263     //Prepare an SQL query to read three numbers from the database. 
00264     _LIT(KSQLStatement,"select Number1,Number2,Number3  from Numbers order by Number1,Number2, Number3");
00265 
00266     //Create a view on the database.
00267     RDbView view; 
00268     User::LeaveIfError(view.Prepare(iDatabase,TDbQuery(KSQLStatement,EDbCompareNormal)));
00269     User::LeaveIfError(view.EvaluateAll());
00270     
00271     //Declare integers to iterate through the database rows. 
00272     static int count = 0; 
00273     TInt iter = 0; 
00274     
00275     /*Iterate through the database to read only the row which was most recently  
00276       written by the PeriodicWriteFunc.
00277       */
00278     view.FirstL();
00279     while( iter < count)
00280         {
00281         view.NextL();
00282         iter++; 
00283         }
00284     count ++ ; 
00285      
00286     //Read the integers from the view and display in console. 
00287     view.GetL();
00288     TInt number1 = view.ColInt(1);
00289     TInt number2 = view.ColInt(2);
00290     TInt number3 = view.ColInt(3);
00291     //Prepare a row formatter to print the numbers to the console. 
00292     _LIT(KRowFormatter, "\n reading  %d \t%d\t%d");
00293     
00294     iConsole->Printf(KRowFormatter,number1,number2, number3);
00295     
00296     //Cancel the periodic function after it has read the last number in the database.  
00297     if(number3 >= KLastNum)
00298         {
00299         iPeriodic->Cancel();
00300         CActiveScheduler::Stop();
00301         _LIT(KAllRead, "\nAll the numbers in the database have been read\n");
00302         iConsole->Printf(KAllRead);
00303         _LIT(KExit, "Press a key to exit\n");
00304         iConsole->Printf(KExit);
00305         iConsole->Getch();
00306         }     
00307     //Close the view. 
00308     view.Close();
00309     
00310     //Unlock the database. 
00311     iDatabase.Commit();
00312     
00313     iDatabase.Close();
00314     CleanupStack::PopAndDestroy(store);
00315     }

Generated by  doxygen 1.6.2