examples/Base/SemaphoreExample/src/CDatabase.cpp

00001 /*
00002 Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008 � list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010 � this list of conditions and the following disclaimer in the documentation
00011 � and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013 � may be used to endorse or promote products derived from this software
00014 � without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:�
00028 This class contains methods to create a database of integers and periodically read /write integers
00029 from/ to the database. The macro USE_SEMAPHORE is used at various places to show thread synchronization
00030 using a semaphore.  
00031 */
00032 
00033 
00034 #include "CDatabase.h"
00035 
00036 //Declare a delay of 1000000 microseconds i.e. 1 sec for the periodic functions. 
00037 const int KDelay = 1000000; 
00038 
00039 //The last number in the database.
00040 const int KLastNum = 50; 
00041 
00045 CDatabase* CDatabase::NewL()
00046     {
00047     CDatabase* self=new(ELeave)CDatabase();
00048     CleanupStack::PushL(self);
00049     self->ConstructL();
00050     CleanupStack::Pop(self);
00051     return self;
00052     }
00053 
00057 CDatabase::~CDatabase()
00058     {   
00059     iFsSession.Close();  //close the file server session. 
00060     delete iPeriodic;    //delete the periodic object.
00061     delete iConsole;     //delete the console. 
00062     #ifdef USE_SEMAPHORE
00063     iSemWrite.Close(); 
00064     #endif
00065     }
00066 
00070 void CDatabase::ConstructL()
00071     {
00072     iPeriodic = CPeriodic::NewL(CActive::EPriorityUserInput);
00073     
00074     _LIT(KDbCreateDb,"exampleDatabase.db");
00075       
00076     iFsSession.Connect();
00077     
00078     //The database exampleDatabase.db is created as a permanent file store 
00079     //in the app's private directory.
00080     User::LeaveIfError(iFsSession.CreatePrivatePath(RFs::GetSystemDrive()));
00081 
00082     User::LeaveIfError(iFsSession.PrivatePath(iDbname));
00083     iDbname.Append(KDbCreateDb); 
00084 
00085     #ifdef USE_SEMAPHORE
00086     //Open the global semaphore which was created in CSemaphoreExample. 
00087     _LIT(KSemaphoreWrite, "WriteSemaphore");
00088     User::LeaveIfError(iSemWrite.OpenGlobal(KSemaphoreWrite, EOwnerProcess)); 
00089     #endif
00090     }
00091 
00095 void CDatabase::CreateDatabaseL()
00096     {
00097     //Construct a file store object - the file to contain the
00098     //database replaces any existing file of the same name.
00099     CFileStore* store = CPermanentFileStore::ReplaceLC(iFsSession, iDbname, EFileRead|EFileWrite);
00100     //Complete file store creation.
00101     store->SetTypeL(store->Layout());
00102     
00103     //Create a database in the store.  
00104     TStreamId id= iDatabase.CreateL(store);
00105     
00106     //Keep database id as root of store.
00107     store->SetRootL(id);
00108     
00109     //Complete database creation by commiting the store.
00110     store->CommitL();
00111     
00112     
00113     //Create a table definition.
00114     CDbColSet* columns=CDbColSet::NewLC();
00115     
00116     //Add three columns each containing Int32 values. 
00117     _LIT(KCol1, "Number1");
00118     _LIT(KCol2, "Number2");
00119     _LIT(KCol3, "Number3");   
00120     columns->AddL(TDbCol(KCol1,EDbColInt32));
00121     columns->AddL(TDbCol(KCol2,EDbColInt32));
00122     columns->AddL(TDbCol(KCol3,EDbColInt32));
00123     
00124     
00125     //Create the table, table name is "Numbers" and add the columns to it.
00126     _LIT(KTable, "Numbers");
00127     User::LeaveIfError(iDatabase.CreateTable(KTable,*columns));
00128     
00129     CDbKey* key=CDbKey::NewLC();
00130     
00131     //Add the key columns.
00132     TDbKeyCol number1(KCol1);
00133     key->AddL(number1);
00134     TDbKeyCol number2(KCol2);
00135     key->AddL(number2);
00136     TDbKeyCol number3(KCol3);
00137     key->AddL(number3);
00138     User::LeaveIfError(iDatabase.CreateIndex(KTable,KTable,*key));
00139     
00140     iDatabase.Close();
00141     //Cleanup the column set.  
00142     CleanupStack::PopAndDestroy(key);
00143     CleanupStack::PopAndDestroy(columns);
00144     CleanupStack::PopAndDestroy(store);
00145     }
00146 
00151 void CDatabase::WritetoDatabaseL()
00152     {
00153     iPeriodic->Start(0, KDelay, TCallBack(PeriodicWriteL, this));
00154     CActiveScheduler::Start();
00155     }
00156 
00161 TInt CDatabase::PeriodicWriteL(TAny* aPtr)
00162     {
00163     CDatabase* ptr = static_cast<CDatabase*> (aPtr);
00164     //Invoke the RThread::Resume() function on the consumer thread repeatedly.
00165     ptr->PeriodicWriteFuncL();
00166     return KErrNone;
00167     }
00168 
00173 void CDatabase::PeriodicWriteFuncL()
00174     {
00175     //Declare an integer which is used to fill numbers in the database. 
00176     static int num = 0 ;  
00177     
00178      //Open the file store.
00179     _LIT(KSQLStatement,"select Number1, Number2, Number3 from Numbers order by Number1,Number2,Number3");
00180     CFileStore* store = CFileStore::OpenLC(iFsSession,iDbname,EFileRead|EFileWrite);
00181     
00182     
00183     //Open the database from the root stream.
00184     iDatabase.OpenL(store,store->Root());
00185     
00186     //Lock the database before use. 
00187     iDatabase.Begin();
00188     
00189     //Create a view on the database view to read/write numbers into it. 
00190     RDbView view;
00191     User::LeaveIfError(view.Prepare(iDatabase,TDbQuery(KSQLStatement,EDbCompareNormal)));
00192     User::LeaveIfError(view.EvaluateAll());
00193 
00194     
00195     //Insert a new row at the end of the database. 
00196     view.InsertL();
00197 
00198     //Fill three coloumns with numbers.
00199     view.SetColL(1, num++);
00200     view.SetColL(2, num++);
00201     view.SetColL(3, num++);
00202     view.PutL();
00203     
00204     //Close the view. 
00205     view.Close();
00206     
00207     //Unlock the database after writing. 
00208     iDatabase.Commit();
00209     
00210     // close the database.
00211     iDatabase.Close();
00212 
00213     //Do not commit store: database has taken control of commit.
00214     CleanupStack::PopAndDestroy(store);
00215     
00216     //Cancel the periodic function once 50 numbers have been written to the database.
00217     if(num > KLastNum )
00218         {
00219         iPeriodic->Cancel();
00220         CActiveScheduler::Stop();
00221         }
00222     
00223     #ifdef USE_SEMAPHORE
00224     /*Signal the semaphore and the PeriodicReadFunc() which was 
00225       waiting on the semaphore is scheduled to run. 
00226       */
00227     iSemWrite.Signal();
00228     #endif
00229     }
00230     
00236 void CDatabase::ReadfromDatabaseL()
00237     { 
00238     _LIT(KTextConsoleTitle, "ReaderThread");
00239     if(!iConsole)
00240         {
00241          iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)); 
00242          _LIT(KReading, "Reading the database.\n");
00243          iConsole->Printf(KReading);
00244         }   
00245     iPeriodic->Start(0, KDelay, TCallBack(PeriodicReadL,this));
00246     CActiveScheduler::Start();
00247     }
00248 
00253 TInt CDatabase::PeriodicReadL(TAny* aPtr)
00254     {
00255     CDatabase* ptr = static_cast<CDatabase*> (aPtr);
00256     ptr->PeriodicReadFuncL();
00257     return KErrNone;
00258     }
00259 
00264 void CDatabase::PeriodicReadFuncL()
00265     {
00266     #ifdef USE_SEMAPHORE
00267     //Semaphore waits till it gets a signal from the PeriodicWrite() function. 
00268     iSemWrite.Wait();
00269     #endif
00270     
00271     CFileStore* store = CFileStore::OpenLC(iFsSession,iDbname,EFileRead);  
00272     
00273     //Open the database from the root stream.
00274     iDatabase.OpenL(store,store->Root());
00275     
00276     //Lock the database.
00277     iDatabase.Begin();
00278     
00279     //Prepare an SQL query to read three numbers from the database. 
00280     _LIT(KSQLStatement,"select Number1,Number2,Number3  from Numbers order by Number1,Number2, Number3");
00281 
00282     //Create a view on the database.
00283     RDbView view; 
00284     User::LeaveIfError(view.Prepare(iDatabase,TDbQuery(KSQLStatement,EDbCompareNormal)));
00285     User::LeaveIfError(view.EvaluateAll());
00286     
00287     //Declare integers to iterate through the database rows. 
00288     static int count = 0; 
00289     TInt iter = 0; 
00290     
00291     /*Iterate through the database to read only the row which was most recently  
00292       written by the PeriodicWriteFunc.
00293       */
00294     view.FirstL();
00295     while( iter < count)
00296         {
00297         view.NextL();
00298         iter++; 
00299         }
00300     count ++ ; 
00301      
00302     //Read the integers from the view and display in console. 
00303     view.GetL();
00304     TInt number1 = view.ColInt(1);
00305     TInt number2 = view.ColInt(2);
00306     TInt number3 = view.ColInt(3);
00307     //Prepare a row formatter to print the numbers to the console. 
00308     _LIT(KRowFormatter, "\n reading  %d \t%d\t%d");
00309     
00310     iConsole->Printf(KRowFormatter,number1,number2, number3);
00311     
00312     //Cancel the periodic function after it has read the last number in the database.  
00313     if(number3 >= KLastNum)
00314         {
00315         iPeriodic->Cancel();
00316         CActiveScheduler::Stop();
00317         _LIT(KAllRead, "\nAll the numbers in the database have been read\n");
00318         iConsole->Printf(KAllRead);
00319         _LIT(KExit, "Press a key to exit\n");
00320         iConsole->Printf(KExit);
00321         iConsole->Getch();
00322         }     
00323     //Close the view. 
00324     view.Close();
00325     
00326     //Unlock the database. 
00327     iDatabase.Commit();
00328     
00329     iDatabase.Close();
00330     CleanupStack::PopAndDestroy(store);
00331     }

Generated by  doxygen 1.6.2