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 00014 #include <d32dbms.h> //Used for RDbDatabase class. 00015 #include "SmpExample.h" 00016 _LIT(KDatabase1, "C:\\DBforSMP1.db"); 00017 _LIT(KDatabase2, "C:\\DBforSMP2.db"); 00018 00022 CSmpExample::~CSmpExample() 00023 { 00024 iReadThread.Close(); //Reader thread closed. 00025 iWriteThread1.Close(); //Writer thread closed. 00026 iWriteThread2.Close(); //Writer thread closed. 00027 delete iConsole; 00028 } 00029 00033 CSmpExample* CSmpExample::NewL() 00034 { 00035 CSmpExample* self = new(ELeave)CSmpExample(); 00036 CleanupStack::PushL(self); 00037 self->ConstructL(); 00038 CleanupStack::Pop(self); 00039 return self; 00040 } 00041 00045 void CSmpExample::ConstructL() 00046 { 00047 CreateDatabaseL(KDatabase1); 00048 CreateDatabaseL(KDatabase2); 00049 00050 _LIT(KTextConsoleTitle, "SmpExample"); 00051 iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen)); 00052 00053 //Creates a reader thread to read the databases. 00054 _LIT(KReader, "ReaderThread"); 00055 User::LeaveIfError(iReadThread.Create(KReader, ReadThreadFuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); 00056 00057 //Creates a writer thread to write to the DBforSMP1.db database. 00058 _LIT(KWriter1, "WriterThread1"); 00059 User::LeaveIfError(iWriteThread1.Create(KWriter1, WriteThread1FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); 00060 00061 //Creates a writer thread to write to the DBforSMP2.db database. 00062 _LIT(KWriter2, "WriterThread2"); 00063 User::LeaveIfError(iWriteThread2.Create(KWriter2, WriteThread2FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); 00064 00065 00066 //Sets priority to the threads. 00067 iWriteThread1.SetPriority(EPriorityMuchLess); 00068 iWriteThread2.SetPriority(EPriorityMore); 00069 iReadThread.SetPriority(EPriorityNormal); 00070 } 00071 00075 void CSmpExample::StartThreads() 00076 { 00077 TRequestStatus writerThread1Status; 00078 TRequestStatus readerThreadStatus; 00079 TRequestStatus writerThread2Status; 00080 00081 _LIT(KTextPressKey, "\nPress any key to start writing to and reading from the database\n"); 00082 iConsole->Printf(KTextPressKey); 00083 iConsole->Getch(); 00084 00085 //Requests a notification for the ReaderThread to terminate. 00086 iReadThread.Logon(readerThreadStatus); 00087 iReadThread.Resume(); 00088 00089 //Requests a notification for the WriterThread1 to terminate. 00090 iWriteThread1.Logon(writerThread1Status); 00091 iWriteThread1.Resume(); 00092 00093 //Requests a notification for the WriterThread2 to terminate. 00094 iWriteThread2.Logon(writerThread2Status); 00095 iWriteThread2.Resume(); 00096 00097 //Control returns to the main thread when the all the threads terminate. 00098 User::WaitForRequest(writerThread1Status); 00099 User::WaitForRequest(readerThreadStatus); 00100 User::WaitForRequest(writerThread2Status); 00101 } 00102 00106 void CSmpExample::PrintMessage() 00107 { 00108 _LIT(KTextWelcome, "Welcome to the SmpExample.\n"); 00109 _LIT(KTextPurposel1, "There are three threads running in the example: WriterThread1 has the lowest priority,\n"); 00110 _LIT(KTextPurposel2, "ReaderThread has normal priority and WriterThread2 has maximum priority.\n"); 00111 _LIT(KTextPurposel3, "The two WriterThreads open two different databases and write some integers to them.\n"); 00112 _LIT(KTextPurposel4, "ReaderThread reads the two databases and prints the output to the console.\n"); 00113 00114 _LIT(KTextPurposel5, "In a unicore environment, WriterThread1 will be scheduled to run last and would not have\n"); 00115 _LIT(KTextPurposel6, "written to the database when ReaderThread starts reading the databases.\n"); 00116 _LIT(KTextPurposel7, "But in an SMP environment, both the WriterThreads write to their respective databases simultaneously.\n"); 00117 00118 iConsole->Printf(KTextWelcome); 00119 iConsole->Printf(KTextPurposel1); 00120 iConsole->Printf(KTextPurposel2); 00121 iConsole->Printf(KTextPurposel3); 00122 iConsole->Printf(KTextPurposel4); 00123 iConsole->Printf(KTextPurposel5); 00124 iConsole->Printf(KTextPurposel6); 00125 iConsole->Printf(KTextPurposel7); 00126 } 00127 00131 void CSmpExample::ReadDatabaseL(const TDesC& aDbName, CConsoleBase& console) 00132 { 00133 //Creates a file server session object before any file system manipulation. 00134 RFs fsSession; 00135 CleanupClosePushL(fsSession); 00136 fsSession.Connect(); 00137 00138 //Creates Rdbs object 00139 RDbs dbs; 00140 CleanupClosePushL(dbs); 00141 dbs.Connect(); 00142 00143 //Opens the named database using the RDbs object 00144 RDbNamedDatabase database; 00145 CleanupClosePushL(database); 00146 User::LeaveIfError(database.Open(dbs, aDbName)); 00147 00148 //Locks the database. 00149 database.Begin(); 00150 //Prepare an SQL query to read one row of numbers from the database. 00151 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3"); 00152 00153 //Creates a view on the database to read it. 00154 RDbView view; 00155 CleanupClosePushL(view); 00156 00157 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal))); 00158 User::LeaveIfError(view.EvaluateAll()); 00159 00160 _LIT(KTextReading, "Reading the database\t %S.\n"); 00161 console.Printf(KTextReading, &aDbName); 00162 00163 //Boolean variable to check whether the database is empty. 00164 TBool isDbEmpty= EFalse; 00165 //Iterates through the database till the last row is read. 00166 for (view.FirstL(); view.AtRow(); view.NextL()) 00167 { 00168 view.GetL(); 00169 TInt number1 = view.ColInt(1); 00170 TInt number2 = view.ColInt(2); 00171 TInt number3 = view.ColInt(3); 00172 //Prepare a row formatter to print numbers in the console. 00173 _LIT(KRowFormatter, "Reading %d \t%d\t%d\n"); 00174 //Reads the integers from the view and display them in the console. 00175 console.Printf(KRowFormatter, number1, number2, number3); 00176 isDbEmpty= ETrue; 00177 } 00178 00179 if(isDbEmpty== EFalse) 00180 { 00181 _LIT(KTextDbEmpty, "Database is empty.\n\n"); 00182 console.Printf(KTextDbEmpty); 00183 } 00184 else 00185 { 00186 _LIT(KTextAllRead, "All the numbers in the database have been read.\n\n"); 00187 console.Printf(KTextAllRead); 00188 } 00189 00190 CleanupStack::PopAndDestroy(&view); 00191 CleanupStack::PopAndDestroy(&database); 00192 CleanupStack::PopAndDestroy(&dbs); 00193 CleanupStack::PopAndDestroy(&fsSession); 00194 } 00195 00199 void CSmpExample::ReadBothDatabasesL() 00200 { 00201 _LIT(KTextConsoleTitle, "ReaderThread"); 00202 CConsoleBase* console= Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen)); 00203 CleanupStack::PushL(console); 00204 00205 //Reads DBforSMP1.db and prints the output to the console. 00206 ReadDatabaseL(KDatabase1, *console); 00207 //Reads DBforSMP2.db and prints the output to the console. 00208 ReadDatabaseL(KDatabase2, *console); 00209 00210 _LIT(KExit, "Press any key to exit\n"); 00211 console->Printf(KExit); 00212 console->Getch(); 00213 CleanupStack::PopAndDestroy(console); 00214 } 00215 00220 TInt CSmpExample::ReadThreadFuncL(TAny* /*aPtr*/) 00221 { 00222 __UHEAP_MARK; 00223 //Creates cleanup stack. 00224 CTrapCleanup* cleanup = CTrapCleanup::New(); 00225 if(!cleanup) 00226 { 00227 return KErrNoMemory; 00228 } 00229 00230 TRAPD(error, ReadBothDatabasesL()); 00231 if(error != KErrNone) 00232 { 00233 _LIT(KUserPanic, "DB Read Failed"); 00234 User::Panic(KUserPanic, error); 00235 } 00236 delete cleanup; 00237 __UHEAP_MARKEND; 00238 return KErrNone; 00239 } 00240 00245 void CSmpExample::WriteDbFuncL(const TDesC& aDbName, TInt aNum) 00246 { 00247 //Creates a file server session object before any file system manipulation. 00248 RFs fsSession; 00249 CleanupClosePushL(fsSession); 00250 fsSession.Connect(); 00251 00252 00253 //Creates Rdbs object 00254 RDbs dbs; 00255 CleanupClosePushL(dbs); 00256 dbs.Connect(); 00257 00258 //Opens the database using the RDbs object 00259 RDbNamedDatabase database; 00260 CleanupClosePushL(database); 00261 User::LeaveIfError(database.Open(dbs, aDbName)); 00262 00263 //Locks the database. 00264 database.Begin(); 00265 00266 //Creates a view on the database. 00267 RDbView view; 00268 CleanupClosePushL(view); 00269 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3"); 00270 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal))); 00271 User::LeaveIfError(view.EvaluateAll()); 00272 00273 for(int i=0; i<5; i++) 00274 { 00275 //Inserts a new row at the end of the database. 00276 view.InsertL(); 00277 //Fills three columns with numbers. 00278 view.SetColL(1, aNum++); 00279 view.SetColL(2, aNum++); 00280 view.SetColL(3, aNum++); 00281 view.PutL(); 00282 } 00283 00284 CleanupStack::PopAndDestroy(&view); 00285 //Commits the database and unlocks it. 00286 database.Commit(); 00287 CleanupStack::PopAndDestroy(&database); 00288 CleanupStack::PopAndDestroy(&dbs); 00289 CleanupStack::PopAndDestroy(&fsSession); 00290 } 00291 00292 00297 TInt CSmpExample::WriteThread2FuncL(TAny* /*aPtr*/) 00298 { 00299 __UHEAP_MARK; 00300 //Creates cleanup stack. 00301 CTrapCleanup* cleanup = CTrapCleanup::New(); 00302 if(!cleanup) 00303 { 00304 return KErrNoMemory; 00305 } 00306 00307 //First number to be written to the database. 00308 const int KFirstNumforDb2 = 500; 00309 TRAPD(err, WriteDbFuncL(KDatabase2, KFirstNumforDb2)); 00310 if(err != KErrNone) 00311 { 00312 _LIT(KUserPanic, "DB Write Failed"); 00313 User::Panic(KUserPanic, err); 00314 } 00315 delete cleanup; 00316 __UHEAP_MARKEND; 00317 return KErrNone; 00318 } 00319 00324 TInt CSmpExample::WriteThread1FuncL(TAny* /*aPtr*/) 00325 { 00326 __UHEAP_MARK; 00327 //Creates cleanup stack. 00328 CTrapCleanup* cleanup = CTrapCleanup::New(); 00329 if(!cleanup) 00330 { 00331 return KErrNoMemory; 00332 } 00333 00334 //First number to be written to the database. 00335 const int KFirstNumforDb1 = 0; 00336 TRAPD(err, WriteDbFuncL(KDatabase1, KFirstNumforDb1)); 00337 if(err != KErrNone) 00338 { 00339 _LIT(KUserPanic, "DB Write Failed"); 00340 User::Panic(KUserPanic, err); 00341 } 00342 delete cleanup; 00343 __UHEAP_MARKEND; 00344 return KErrNone; 00345 } 00346 00351 void CSmpExample::CreateDatabaseL(const TDesC& aDbName) 00352 { 00353 //Creates a file server session object before any file system manipulation. 00354 RFs fsSession; 00355 CleanupClosePushL(fsSession); 00356 fsSession.Connect(); 00357 00358 //Creates Rdbs object 00359 RDbs dbs; 00360 CleanupClosePushL(dbs); 00361 dbs.Connect(); 00362 00363 //Creates a new database with the name specified in the parameter aDbName, 00364 //if database with same name is present, it will be replaced. 00365 RDbNamedDatabase database; 00366 CleanupClosePushL(database); 00367 User::LeaveIfError(database.Replace(fsSession, aDbName)); 00368 database.Close(); 00369 00370 //Opens the database using the RDbs object 00371 User::LeaveIfError(database.Open(dbs, aDbName)); 00372 //Creates a table definition. 00373 CDbColSet* columns=CDbColSet::NewLC(); 00374 00375 //Adds three columns each containing Int32 values. 00376 _LIT(KCol1, "Number1"); 00377 _LIT(KCol2, "Number2"); 00378 _LIT(KCol3, "Number3"); 00379 columns->AddL(TDbCol(KCol1, EDbColInt32)); 00380 columns->AddL(TDbCol(KCol2, EDbColInt32)); 00381 columns->AddL(TDbCol(KCol3, EDbColInt32)); 00382 00383 00384 //Creates the table, table name is "Numbers" and add the columns to it. 00385 _LIT(KTable, "Numbers"); 00386 User::LeaveIfError(database.CreateTable(KTable, *columns)); 00387 00388 CDbKey* key=CDbKey::NewLC(); 00389 00390 //Add the key columns. 00391 TDbKeyCol number1(KCol1); 00392 key->AddL(number1); 00393 TDbKeyCol number2(KCol2); 00394 key->AddL(number2); 00395 TDbKeyCol number3(KCol3); 00396 key->AddL(number3); 00397 User::LeaveIfError(database.CreateIndex(KTable, KTable, *key)); 00398 00399 //Cleans up the column set. 00400 CleanupStack::PopAndDestroy(key); 00401 CleanupStack::PopAndDestroy(columns); 00402 CleanupStack::PopAndDestroy(&database); 00403 CleanupStack::PopAndDestroy(&dbs); 00404 CleanupStack::PopAndDestroy(&fsSession); 00405 } 00406 00411 static void MainL() 00412 { 00413 CSmpExample* smpExample = CSmpExample::NewL(); 00414 CleanupStack::PushL(smpExample); 00415 smpExample->PrintMessage(); 00416 smpExample->StartThreads(); 00417 CleanupStack::PopAndDestroy(smpExample); 00418 } 00419 00423 extern TInt E32Main() 00424 { 00425 //Creates cleanup stack. 00426 __UHEAP_MARK; 00427 CTrapCleanup* cleanup = CTrapCleanup::New(); 00428 if(!cleanup) 00429 { 00430 return KErrNoMemory; 00431 } 00432 //Run application code inside a TRAP harness. 00433 TRAPD(mainError, MainL()); 00434 if(mainError != KErrNone) 00435 { 00436 _LIT(KUserPanic, "Main Failed"); 00437 User::Panic(KUserPanic, mainError); 00438 } 00439 delete cleanup; 00440 __UHEAP_MARKEND; 00441 return KErrNone; 00442 } 00443
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.